diff --git a/README.md b/README.md index b9b3f52..fe0daf1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,52 @@ # 公共安全技术研究中心--智慧电梯 +包含智慧电梯相关例程 +### 项目描述: +智慧电梯摄像头模组开发作为建设电梯安全服务及监管综合平台中的感知层部分,需要实现对电梯内画面的采 +集,利用深度模型对帧数据进行异常行为检测,并实现对检测结果与其他传感器数据进行校验整合,按照标准 +编码要求,将前端设备信息上传到平台。实现信息互联、数据互通、系统协同。 +### 运行流程 +* 开机后将ip设置为192.168.8.100 +* 进行联网时间矫正例程 +* 开启http服务,用于接收设备ID分配信息,若设备从未被分配ID,则等待ID分配后才继续执行下列步骤 +* 开启摄像头模型检测例程,检测到超载、火焰、吸烟、烟雾、跌倒、电瓶车等行为,上报服务器 +* 开启串口透传例程,接收传感器数据,透传给服务器 +* 开启ymodem-ota例程,用于利用ymodem协议通过串口给传感器板子进行固件升级 +* 开启update-engine例程,用于给摄像头模组进行ota升级 -## 系统 \ No newline at end of file +## build_http +此工程文件夹是用于构建http服务的 功能: 1、接收APP分配下来的设备ID,保存与DEVICE_ID文件中 端口:10000 2、接收APP下发的用于透传给传感器的气压计校准命令,并将传感器应答返回给APP 端口:11000 + + +## chuankou2 +此工程文件夹是用于构建串口透传服务的 功能: 读取串口信息,转发给服务器 编译: ./build.sh + +## rknn_yolo_demo +用于运行yolov5模型检测,检测载、火焰、吸烟、烟雾、跌倒、电瓶车等行为,上传报警信息 + +## time_sync +联网时间矫正例程 + +## update_engine/recovery/update_engine +基于rknn官方的update_engine修改而来,用于ota升级摄像头模组 + +## ymodem-master +用于利用ymodem协议通过串口给传感器板子进行固件升级 + +## 开机脚本 +相关开机自启脚本、ip设置文件等请刷了update.img固件后去对应位置参考 + +### 脚本位置 +开机IP设置相关脚本 +``` +/etc/init.d/S99z-network +/etc/init.d/S99z-ipreboot +/etc/network/interface +``` +例程开机自启脚本 +``` +/demo/bin/receive.sh +``` + + +## 其他信息 +由于传感器板子串口数量受限,透传例程、http气压计传输命令、ymodem-ota例程共用一个串口,所以设计进程间互斥锁保证功能正常。 \ No newline at end of file diff --git a/build_http/CMakeLists.txt b/build_http/CMakeLists.txt new file mode 100644 index 0000000..ec15bb5 --- /dev/null +++ b/build_http/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.8) +message(STATUS "cmake version ${CMAKE_VERSION}") + +set(TOOLCHAIN_DIR /opt/atk-dlrv1126-toolchain) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-g++) +set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-gcc) +set(SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot/usr/include) +set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot) + +set(CMAKE_CXX_STANDARD 11) +add_definitions(-g -O0 -ggdb -gdwarf -funwind-tables -rdynamic) +add_definitions(-Wno-write-strings -Wno-return-type) + + + + +link_directories(include lib) +link_directories(include ./librtsp) + +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIR}) +message("CURL_LIBRARIES: ${CURL_LIBRARIES}") +message("CURL_INCLUDE_DIR: ${CURL_INCLUDE_DIR}") +find_package(OpenCV REQUIRED) + +include_directories(${SYSROOT}) +# include_directories(${SYSROOT}/rga) +# include_directories(${SYSROOT}/easymedia) +# include_directories(${SYSROOT}/rkaiq/uAPI) +# include_directories(${SYSROOT}/rkaiq/xcore) +# include_directories(${SYSROOT}/rkaiq/algos) +# include_directories(${SYSROOT}/rkaiq/common) +# include_directories(${SYSROOT}/rkaiq/iq_parser) +# include_directories(${SYSROOT}/rknn) +include_directories(.) +include_directories(./include) +# include_directories(./include/3rdparty) +# include_directories(./include/3rdparty/drm/include/libdrm) +# include_directories(./include/3rdparty/rga/include) +# include_directories(./librtsp) + + + +add_definitions(-DRKAIQ) + + + +add_executable(http_test main.cpp mongoose.c) +target_link_libraries(http_test -lrt -lpthread) \ No newline at end of file diff --git a/build_http/build/CMakeCache.txt b/build_http/build/CMakeCache.txt new file mode 100644 index 0000000..bdd1392 --- /dev/null +++ b/build_http/build/CMakeCache.txt @@ -0,0 +1,454 @@ +# This is the CMakeCache file. +# For build in directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build +# It was generated by CMake: /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/pkgRedirects + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//The directory containing a CMake configuration file for CURL. +CURL_DIR:PATH=CURL_DIR-NOTFOUND + +//Path to a file. +CURL_INCLUDE_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +//Path to a library. +CURL_LIBRARY_DEBUG:FILEPATH=CURL_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +CURL_LIBRARY_RELEASE:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so + +//The directory containing a CMake configuration file for OpenCV. +OpenCV_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV + +//Arguments to supply to pkg-config +PKG_CONFIG_ARGN:STRING= + +//pkg-config executable +PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build + +//Value Computed by CMake +Project_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http + +//Path to a library. +pkgcfg_lib_PC_CURL_curl:FILEPATH=/usr/lib/x86_64-linux-gnu/libcurl.so + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=26 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=0 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_DIR +CURL_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_INCLUDE_DIR +CURL_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_DEBUG +CURL_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_RELEASE +CURL_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//Details about finding CURL +FIND_PACKAGE_MESSAGE_DETAILS_CURL:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so][/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include][c ][v7.75.0()] +//Details about finding OpenCV +FIND_PACKAGE_MESSAGE_DETAILS_OpenCV:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr][v3.4.12()] +PC_CURL_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_CFLAGS_I:INTERNAL= +PC_CURL_CFLAGS_OTHER:INTERNAL= +PC_CURL_FOUND:INTERNAL=1 +PC_CURL_INCLUDEDIR:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lcurl +PC_CURL_LDFLAGS_OTHER:INTERNAL= +PC_CURL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBRARIES:INTERNAL=curl +PC_CURL_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBS:INTERNAL= +PC_CURL_LIBS_L:INTERNAL= +PC_CURL_LIBS_OTHER:INTERNAL= +PC_CURL_LIBS_PATHS:INTERNAL= +PC_CURL_MODULE_NAME:INTERNAL=libcurl +PC_CURL_PREFIX:INTERNAL=/usr +PC_CURL_STATIC_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_CFLAGS_I:INTERNAL= +PC_CURL_STATIC_CFLAGS_OTHER:INTERNAL= +PC_CURL_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-L/usr/lib/x86_64-linux-gnu/mit-krb5;-lcurl;-lnghttp2;-lidn2;-lrtmp;-lssh;-lpsl;-lssl;-lcrypto;-lssl;-lcrypto;-Wl,-Bsymbolic-functions;-Wl,-z,relro;-lgssapi_krb5;-lkrb5;-lk5crypto;-lcom_err;-llber;-lldap;-llber;-lbrotlidec;-lz +PC_CURL_STATIC_LDFLAGS_OTHER:INTERNAL=-Wl,-Bsymbolic-functions;-Wl,-z,relro +PC_CURL_STATIC_LIBDIR:INTERNAL= +PC_CURL_STATIC_LIBRARIES:INTERNAL=curl;nghttp2;idn2;rtmp;ssh;psl;ssl;crypto;ssl;crypto;gssapi_krb5;krb5;k5crypto;com_err;lber;ldap;lber;brotlidec;z +PC_CURL_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu;/usr/lib/x86_64-linux-gnu/mit-krb5 +PC_CURL_STATIC_LIBS:INTERNAL= +PC_CURL_STATIC_LIBS_L:INTERNAL= +PC_CURL_STATIC_LIBS_OTHER:INTERNAL= +PC_CURL_STATIC_LIBS_PATHS:INTERNAL= +PC_CURL_VERSION:INTERNAL=7.68.0 +PC_CURL_libcurl_INCLUDEDIR:INTERNAL= +PC_CURL_libcurl_LIBDIR:INTERNAL= +PC_CURL_libcurl_PREFIX:INTERNAL= +PC_CURL_libcurl_VERSION:INTERNAL= +//ADVANCED property for variable: PKG_CONFIG_ARGN +PKG_CONFIG_ARGN-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE +PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1 +//linker supports push/pop state +_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED:INTERNAL=TRUE +__pkg_config_arguments_PC_CURL:INTERNAL=QUIET;libcurl +__pkg_config_checked_PC_CURL:INTERNAL=1 +//ADVANCED property for variable: pkgcfg_lib_PC_CURL_curl +pkgcfg_lib_PC_CURL_curl-ADVANCED:INTERNAL=1 +prefix_result:INTERNAL=SSL;IPv6;UnixSockets;libz;brotli;AsynchDNS;IDN;GSS-API;PSL;SPNEGO;Kerberos;NTLM;NTLM_WB;TLS-SRP;HTTP2;HTTPS-proxy + diff --git a/build_http/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake b/build_http/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake new file mode 100644 index 0000000..db12033 --- /dev/null +++ b/build_http/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "9.4.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/build_http/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake b/build_http/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..9950db3 --- /dev/null +++ b/build_http/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "9.4.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/build_http/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin b/build_http/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000..d10d50b Binary files /dev/null and b/build_http/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin differ diff --git a/build_http/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin b/build_http/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin new file mode 100644 index 0000000..61bb758 Binary files /dev/null and b/build_http/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/build_http/build/CMakeFiles/3.26.0/CMakeSystem.cmake b/build_http/build/CMakeFiles/3.26.0/CMakeSystem.cmake new file mode 100644 index 0000000..5241841 --- /dev/null +++ b/build_http/build/CMakeFiles/3.26.0/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-5.15.0-83-generic") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "5.15.0-83-generic") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-5.15.0-83-generic") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "5.15.0-83-generic") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/build_http/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c b/build_http/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..88155ff --- /dev/null +++ b/build_http/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,866 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/build_http/build/CMakeFiles/3.26.0/CompilerIdC/a.out b/build_http/build/CMakeFiles/3.26.0/CompilerIdC/a.out new file mode 100644 index 0000000..6dc55f1 Binary files /dev/null and b/build_http/build/CMakeFiles/3.26.0/CompilerIdC/a.out differ diff --git a/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp b/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..746b167 --- /dev/null +++ b/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,855 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out b/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out new file mode 100644 index 0000000..3198cb5 Binary files /dev/null and b/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out differ diff --git a/build_http/build/CMakeFiles/CMakeConfigureLog.yaml b/build_http/build/CMakeFiles/CMakeConfigureLog.yaml new file mode 100644 index 0000000..d09b5d0 --- /dev/null +++ b/build_http/build/CMakeFiles/CMakeConfigureLog.yaml @@ -0,0 +1,529 @@ + +--- +events: + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineSystem.cmake:204 (message)" + - "CMakeLists.txt" + message: | + The system is: Linux - 5.15.0-83-generic - x86_64 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCCompiler.cmake:123 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt" + message: | + Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. + Compiler: /usr/bin/cc + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + + The C compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/3.26.0/CompilerIdC/a.out + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt" + message: | + Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. + Compiler: /usr/bin/c++ + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + + The CXX compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + checks: + - "Detecting C compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm" + cmakeVariables: + CMAKE_C_FLAGS: "" + buildResult: + variable: "CMAKE_C_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_bc4c3/fast && /usr/bin/make -f CMakeFiles/cmTC_bc4c3.dir/build.make CMakeFiles/cmTC_bc4c3.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm' + Building C object CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o + /usr/bin/cc -v -o CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c + Using built-in specs. + COLLECT_GCC=/usr/bin/cc + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccENw1Z9.s + GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/lib/gcc/x86_64-linux-gnu/9/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 01da938ff5dc2163489aa33cb3b747a7 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o /tmp/ccENw1Z9.s + GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34 + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + Linking C executable cmTC_bc4c3 + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_bc4c3.dir/link.txt --verbose=1 + /usr/bin/cc -v -rdynamic CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -o cmTC_bc4c3 + Using built-in specs. + COLLECT_GCC=/usr/bin/cc + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_bc4c3' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cciUYzsD.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_bc4c3 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_bc4c3' '-mtune=generic' '-march=x86-64' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed C implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-linux-gnu/9/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed C implicit link information: + link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_bc4c3/fast && /usr/bin/make -f CMakeFiles/cmTC_bc4c3.dir/build.make CMakeFiles/cmTC_bc4c3.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-jU39Cm'] + ignore line: [Building C object CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccENw1Z9.s] + ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 01da938ff5dc2163489aa33cb3b747a7] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o /tmp/ccENw1Z9.s] + ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking C executable cmTC_bc4c3] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_bc4c3.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -o cmTC_bc4c3 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_bc4c3' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cciUYzsD.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_bc4c3 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/cciUYzsD.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_bc4c3] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] + arg [CMakeFiles/cmTC_bc4c3.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + checks: + - "Detecting CXX compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj" + cmakeVariables: + CMAKE_CXX_FLAGS: "" + buildResult: + variable: "CMAKE_CXX_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_383ce/fast && /usr/bin/make -f CMakeFiles/cmTC_383ce.dir/build.make CMakeFiles/cmTC_383ce.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj' + Building CXX object CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o + /usr/bin/c++ -v -o CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/cceHFsyj.s + GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9" + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/include/c++/9 + /usr/include/x86_64-linux-gnu/c++/9 + /usr/include/c++/9/backward + /usr/lib/gcc/x86_64-linux-gnu/9/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 3d1eba838554fa2348dba760e4770469 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o /tmp/cceHFsyj.s + GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34 + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + Linking CXX executable cmTC_383ce + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_383ce.dir/link.txt --verbose=1 + /usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_383ce + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_383ce' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccm0vVoN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_383ce /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_383ce' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed CXX implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/include/c++/9] + add: [/usr/include/x86_64-linux-gnu/c++/9] + add: [/usr/include/c++/9/backward] + add: [/usr/lib/gcc/x86_64-linux-gnu/9/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/include/c++/9] ==> [/usr/include/c++/9] + collapse include dir [/usr/include/x86_64-linux-gnu/c++/9] ==> [/usr/include/x86_64-linux-gnu/c++/9] + collapse include dir [/usr/include/c++/9/backward] ==> [/usr/include/c++/9/backward] + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed CXX implicit link information: + link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_383ce/fast && /usr/bin/make -f CMakeFiles/cmTC_383ce.dir/build.make CMakeFiles/cmTC_383ce.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/CMakeScratch/TryCompile-yhSfFj'] + ignore line: [Building CXX object CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/cceHFsyj.s] + ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/include/c++/9] + ignore line: [ /usr/include/x86_64-linux-gnu/c++/9] + ignore line: [ /usr/include/c++/9/backward] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 3d1eba838554fa2348dba760e4770469] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o /tmp/cceHFsyj.s] + ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking CXX executable cmTC_383ce] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_383ce.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_383ce ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_383ce' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccm0vVoN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_383ce /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccm0vVoN.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_383ce] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] + arg [CMakeFiles/cmTC_383ce.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + +... diff --git a/build_http/build/CMakeFiles/CMakeDirectoryInformation.cmake b/build_http/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..5d63074 --- /dev/null +++ b/build_http/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build_http/build/CMakeFiles/Makefile.cmake b/build_http/build/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..8b11e0f --- /dev/null +++ b/build_http/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,56 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCommonLanguageInclude.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeGenericSystem.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeInitializeConfigs.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeLanguageInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeSystemSpecificInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeSystemSpecificInitialize.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU-C.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU-CXX.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindCURL.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageHandleStandardArgs.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageMessage.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPkgConfig.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU-C.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU-CXX.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/UnixPaths.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/SelectLibraryConfigurations.cmake" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/CMakeLists.txt" + "CMakeFiles/3.26.0/CMakeCCompiler.cmake" + "CMakeFiles/3.26.0/CMakeCXXCompiler.cmake" + "CMakeFiles/3.26.0/CMakeSystem.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVConfig-version.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVConfig.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVModules-release.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVModules.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/http_test.dir/DependInfo.cmake" + ) diff --git a/build_http/build/CMakeFiles/Makefile2 b/build_http/build/CMakeFiles/Makefile2 new file mode 100644 index 0000000..4c0b802 --- /dev/null +++ b/build_http/build/CMakeFiles/Makefile2 @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/http_test.dir/all +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/http_test.dir/clean +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/http_test.dir + +# All Build rule for target. +CMakeFiles/http_test.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles --progress-num=1,2,3 "Built target http_test" +.PHONY : CMakeFiles/http_test.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/http_test.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles 3 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/http_test.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles 0 +.PHONY : CMakeFiles/http_test.dir/rule + +# Convenience name for target. +http_test: CMakeFiles/http_test.dir/rule +.PHONY : http_test + +# clean rule for target. +CMakeFiles/http_test.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/clean +.PHONY : CMakeFiles/http_test.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build_http/build/CMakeFiles/TargetDirectories.txt b/build_http/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..5f43520 --- /dev/null +++ b/build_http/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/http_test.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/edit_cache.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/rebuild_cache.dir diff --git a/build_http/build/CMakeFiles/cmake.check_cache b/build_http/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/build_http/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/build_http/build/CMakeFiles/http_test.dir/DependInfo.cmake b/build_http/build/CMakeFiles/http_test.dir/DependInfo.cmake new file mode 100644 index 0000000..1311826 --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/DependInfo.cmake @@ -0,0 +1,20 @@ + +# Consider dependencies only in project. +set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) + +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + ) + +# The set of dependency files which are needed: +set(CMAKE_DEPENDS_DEPENDENCY_FILES + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c" "CMakeFiles/http_test.dir/mongoose.c.o" "gcc" "CMakeFiles/http_test.dir/mongoose.c.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp" "CMakeFiles/http_test.dir/main.cpp.o" "gcc" "CMakeFiles/http_test.dir/main.cpp.o.d" + ) + +# Targets to which this target links which contain Fortran sources. +set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/build_http/build/CMakeFiles/http_test.dir/build.make b/build_http/build/CMakeFiles/http_test.dir/build.make new file mode 100644 index 0000000..ef9cb1d --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/build.make @@ -0,0 +1,126 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build + +# Include any dependencies generated for this target. +include CMakeFiles/http_test.dir/depend.make +# Include any dependencies generated by the compiler for this target. +include CMakeFiles/http_test.dir/compiler_depend.make + +# Include the progress variables for this target. +include CMakeFiles/http_test.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/http_test.dir/flags.make + +CMakeFiles/http_test.dir/main.cpp.o: CMakeFiles/http_test.dir/flags.make +CMakeFiles/http_test.dir/main.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp +CMakeFiles/http_test.dir/main.cpp.o: CMakeFiles/http_test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/http_test.dir/main.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/http_test.dir/main.cpp.o -MF CMakeFiles/http_test.dir/main.cpp.o.d -o CMakeFiles/http_test.dir/main.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp + +CMakeFiles/http_test.dir/main.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/http_test.dir/main.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp > CMakeFiles/http_test.dir/main.cpp.i + +CMakeFiles/http_test.dir/main.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/http_test.dir/main.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp -o CMakeFiles/http_test.dir/main.cpp.s + +CMakeFiles/http_test.dir/mongoose.c.o: CMakeFiles/http_test.dir/flags.make +CMakeFiles/http_test.dir/mongoose.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c +CMakeFiles/http_test.dir/mongoose.c.o: CMakeFiles/http_test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/http_test.dir/mongoose.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/http_test.dir/mongoose.c.o -MF CMakeFiles/http_test.dir/mongoose.c.o.d -o CMakeFiles/http_test.dir/mongoose.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c + +CMakeFiles/http_test.dir/mongoose.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/http_test.dir/mongoose.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c > CMakeFiles/http_test.dir/mongoose.c.i + +CMakeFiles/http_test.dir/mongoose.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/http_test.dir/mongoose.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c -o CMakeFiles/http_test.dir/mongoose.c.s + +# Object files for target http_test +http_test_OBJECTS = \ +"CMakeFiles/http_test.dir/main.cpp.o" \ +"CMakeFiles/http_test.dir/mongoose.c.o" + +# External object files for target http_test +http_test_EXTERNAL_OBJECTS = + +http_test: CMakeFiles/http_test.dir/main.cpp.o +http_test: CMakeFiles/http_test.dir/mongoose.c.o +http_test: CMakeFiles/http_test.dir/build.make +http_test: CMakeFiles/http_test.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Linking CXX executable http_test" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/http_test.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/http_test.dir/build: http_test +.PHONY : CMakeFiles/http_test.dir/build + +CMakeFiles/http_test.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/http_test.dir/cmake_clean.cmake +.PHONY : CMakeFiles/http_test.dir/clean + +CMakeFiles/http_test.dir/depend: + cd /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles/http_test.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/http_test.dir/depend + diff --git a/build_http/build/CMakeFiles/http_test.dir/cmake_clean.cmake b/build_http/build/CMakeFiles/http_test.dir/cmake_clean.cmake new file mode 100644 index 0000000..fd0aabe --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/cmake_clean.cmake @@ -0,0 +1,13 @@ +file(REMOVE_RECURSE + "CMakeFiles/http_test.dir/main.cpp.o" + "CMakeFiles/http_test.dir/main.cpp.o.d" + "CMakeFiles/http_test.dir/mongoose.c.o" + "CMakeFiles/http_test.dir/mongoose.c.o.d" + "http_test" + "http_test.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C CXX) + include(CMakeFiles/http_test.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/build_http/build/CMakeFiles/http_test.dir/compiler_depend.internal b/build_http/build/CMakeFiles/http_test.dir/compiler_depend.internal new file mode 100644 index 0000000..7aa8d7b --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/compiler_depend.internal @@ -0,0 +1,432 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/http_test.dir/main.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include/mongoose.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/math.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rpc/netdb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h + +CMakeFiles/http_test.dir/mongoose.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include/mongoose.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + diff --git a/build_http/build/CMakeFiles/http_test.dir/compiler_depend.make b/build_http/build/CMakeFiles/http_test.dir/compiler_depend.make new file mode 100644 index 0000000..06b3faa --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/compiler_depend.make @@ -0,0 +1,1004 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/http_test.dir/main.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include/mongoose.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/math.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rpc/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h + +CMakeFiles/http_test.dir/mongoose.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include/mongoose.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include/mongoose.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/math.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rpc/netdb.h: diff --git a/build_http/build/CMakeFiles/http_test.dir/compiler_depend.ts b/build_http/build/CMakeFiles/http_test.dir/compiler_depend.ts new file mode 100644 index 0000000..cc002b1 --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for http_test. diff --git a/build_http/build/CMakeFiles/http_test.dir/depend.make b/build_http/build/CMakeFiles/http_test.dir/depend.make new file mode 100644 index 0000000..0978bb2 --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/depend.make @@ -0,0 +1,2 @@ +# Empty dependencies file for http_test. +# This may be replaced when dependencies are built. diff --git a/build_http/build/CMakeFiles/http_test.dir/flags.make b/build_http/build/CMakeFiles/http_test.dir/flags.make new file mode 100644 index 0000000..be06409 --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/flags.make @@ -0,0 +1,17 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# compile C with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +# compile CXX with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +C_DEFINES = -DRKAIQ + +C_INCLUDES = -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/. -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/./include + +C_FLAGS = -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + +CXX_DEFINES = -DRKAIQ + +CXX_INCLUDES = -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/. -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/./include + +CXX_FLAGS = -std=gnu++11 -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + diff --git a/build_http/build/CMakeFiles/http_test.dir/link.txt b/build_http/build/CMakeFiles/http_test.dir/link.txt new file mode 100644 index 0000000..910697b --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/link.txt @@ -0,0 +1 @@ +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot CMakeFiles/http_test.dir/main.cpp.o CMakeFiles/http_test.dir/mongoose.c.o -o http_test -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/lib -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/./librtsp -Wl,-rpath,/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/include:/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/lib:/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/./librtsp -lrt -lpthread diff --git a/build_http/build/CMakeFiles/http_test.dir/main.cpp.o b/build_http/build/CMakeFiles/http_test.dir/main.cpp.o new file mode 100644 index 0000000..846af8d Binary files /dev/null and b/build_http/build/CMakeFiles/http_test.dir/main.cpp.o differ diff --git a/build_http/build/CMakeFiles/http_test.dir/main.cpp.o.d b/build_http/build/CMakeFiles/http_test.dir/main.cpp.o.d new file mode 100644 index 0000000..d211227 --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/main.cpp.o.d @@ -0,0 +1,287 @@ +CMakeFiles/http_test.dir/main.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/main.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/./include/mongoose.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/math.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rpc/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h diff --git a/build_http/build/CMakeFiles/http_test.dir/mongoose.c.o b/build_http/build/CMakeFiles/http_test.dir/mongoose.c.o new file mode 100644 index 0000000..fb1f912 Binary files /dev/null and b/build_http/build/CMakeFiles/http_test.dir/mongoose.c.o differ diff --git a/build_http/build/CMakeFiles/http_test.dir/mongoose.c.o.d b/build_http/build/CMakeFiles/http_test.dir/mongoose.c.o.d new file mode 100644 index 0000000..17804df --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/mongoose.c.o.d @@ -0,0 +1,140 @@ +CMakeFiles/http_test.dir/mongoose.c.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/mongoose.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/./include/mongoose.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/arpa/inet.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netinet/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/in.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/netdb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h diff --git a/build_http/build/CMakeFiles/http_test.dir/progress.make b/build_http/build/CMakeFiles/http_test.dir/progress.make new file mode 100644 index 0000000..6a9dc74 --- /dev/null +++ b/build_http/build/CMakeFiles/http_test.dir/progress.make @@ -0,0 +1,4 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 + diff --git a/build_http/build/CMakeFiles/progress.marks b/build_http/build/CMakeFiles/progress.marks new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/build_http/build/CMakeFiles/progress.marks @@ -0,0 +1 @@ +3 diff --git a/build_http/build/Makefile b/build_http/build/Makefile new file mode 100644 index 0000000..d0104d4 --- /dev/null +++ b/build_http/build/Makefile @@ -0,0 +1,208 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named http_test + +# Build rule for target. +http_test: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 http_test +.PHONY : http_test + +# fast build rule for target. +http_test/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/build +.PHONY : http_test/fast + +main.o: main.cpp.o +.PHONY : main.o + +# target to build an object file +main.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/main.cpp.o +.PHONY : main.cpp.o + +main.i: main.cpp.i +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/main.cpp.s +.PHONY : main.cpp.s + +mongoose.o: mongoose.c.o +.PHONY : mongoose.o + +# target to build an object file +mongoose.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/mongoose.c.o +.PHONY : mongoose.c.o + +mongoose.i: mongoose.c.i +.PHONY : mongoose.i + +# target to preprocess a source file +mongoose.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/mongoose.c.i +.PHONY : mongoose.c.i + +mongoose.s: mongoose.c.s +.PHONY : mongoose.s + +# target to generate assembly for a file +mongoose.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/http_test.dir/build.make CMakeFiles/http_test.dir/mongoose.c.s +.PHONY : mongoose.c.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... http_test" + @echo "... main.o" + @echo "... main.i" + @echo "... main.s" + @echo "... mongoose.o" + @echo "... mongoose.i" + @echo "... mongoose.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build_http/build/cmake_install.cmake b/build_http/build/cmake_install.cmake new file mode 100644 index 0000000..d4aae45 --- /dev/null +++ b/build_http/build/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/build_http/build/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/build_http/build/http_test b/build_http/build/http_test new file mode 100644 index 0000000..c9c1eb2 Binary files /dev/null and b/build_http/build/http_test differ diff --git a/build_http/include/mongoose.h b/build_http/include/mongoose.h new file mode 100644 index 0000000..65ac0c7 --- /dev/null +++ b/build_http/include/mongoose.h @@ -0,0 +1,5830 @@ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/common.h" +#endif +/* + * Copyright (c) 2004-2013 Sergey Lyubka + * Copyright (c) 2013-2015 Cesanta Software Limited + * All rights reserved + * + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +#ifndef CS_MONGOOSE_SRC_COMMON_H_ +#define CS_MONGOOSE_SRC_COMMON_H_ + +#define MG_VERSION "6.7" + +/* Local tweaks, applied before any of Mongoose's own headers. */ +#ifdef MG_LOCALS +#include +#endif + +#endif /* CS_MONGOOSE_SRC_COMMON_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platform.h" +#endif +#ifndef CS_COMMON_PLATFORM_H_ +#define CS_COMMON_PLATFORM_H_ + +/* + * For the "custom" platform, includes and dependencies can be + * provided through mg_locals.h. + */ +#define CS_P_CUSTOM 0 +#define CS_P_UNIX 1 +#define CS_P_WINDOWS 2 +#define CS_P_ESP32 15 +#define CS_P_ESP8266 3 +#define CS_P_CC3200 4 +#define CS_P_MSP432 5 +#define CS_P_CC3100 6 +#define CS_P_TM4C129 14 +#define CS_P_MBED 7 +#define CS_P_WINCE 8 +#define CS_P_NXP_LPC 13 +#define CS_P_NXP_KINETIS 9 +#define CS_P_NRF51 12 +#define CS_P_NRF52 10 +#define CS_P_PIC32 11 +#define CS_P_STM32 16 +/* Next id: 17 */ + +/* If not specified explicitly, we guess platform by defines. */ +#ifndef CS_PLATFORM + +#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__) +#define CS_PLATFORM CS_P_MSP432 +#elif defined(cc3200) +#define CS_PLATFORM CS_P_CC3200 +#elif defined(__unix__) || defined(__APPLE__) +#define CS_PLATFORM CS_P_UNIX +#elif defined(WINCE) +#define CS_PLATFORM CS_P_WINCE +#elif defined(_WIN32) +#define CS_PLATFORM CS_P_WINDOWS +#elif defined(__MBED__) +#define CS_PLATFORM CS_P_MBED +#elif defined(__USE_LPCOPEN) +#define CS_PLATFORM CS_P_NXP_LPC +#elif defined(FRDM_K64F) || defined(FREEDOM) +#define CS_PLATFORM CS_P_NXP_KINETIS +#elif defined(PIC32) +#define CS_PLATFORM CS_P_PIC32 +#elif defined(ESP_PLATFORM) +#define CS_PLATFORM CS_P_ESP32 +#elif defined(ICACHE_FLASH) +#define CS_PLATFORM CS_P_ESP8266 +#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \ + defined(TARGET_IS_TM4C129_RA2) +#define CS_PLATFORM CS_P_TM4C129 +#elif defined(STM32) +#define CS_PLATFORM CS_P_STM32 +#endif + +#ifndef CS_PLATFORM +#error "CS_PLATFORM is not specified and we couldn't guess it." +#endif + +#endif /* !defined(CS_PLATFORM) */ + +#define MG_NET_IF_SOCKET 1 +#define MG_NET_IF_SIMPLELINK 2 +#define MG_NET_IF_LWIP_LOW_LEVEL 3 +#define MG_NET_IF_PIC32 4 + +#define MG_SSL_IF_OPENSSL 1 +#define MG_SSL_IF_MBEDTLS 2 +#define MG_SSL_IF_SIMPLELINK 3 + +/* Amalgamated: #include "common/platforms/platform_unix.h" */ +/* Amalgamated: #include "common/platforms/platform_windows.h" */ +/* Amalgamated: #include "common/platforms/platform_esp32.h" */ +/* Amalgamated: #include "common/platforms/platform_esp8266.h" */ +/* Amalgamated: #include "common/platforms/platform_cc3200.h" */ +/* Amalgamated: #include "common/platforms/platform_cc3100.h" */ +/* Amalgamated: #include "common/platforms/platform_mbed.h" */ +/* Amalgamated: #include "common/platforms/platform_nrf51.h" */ +/* Amalgamated: #include "common/platforms/platform_nrf52.h" */ +/* Amalgamated: #include "common/platforms/platform_wince.h" */ +/* Amalgamated: #include "common/platforms/platform_nxp_lpc.h" */ +/* Amalgamated: #include "common/platforms/platform_nxp_kinetis.h" */ +/* Amalgamated: #include "common/platforms/platform_pic32.h" */ +/* Amalgamated: #include "common/platforms/platform_stm32.h" */ + +/* Common stuff */ + +#if !defined(WEAK) +#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32) +#define WEAK __attribute__((weak)) +#else +#define WEAK +#endif +#endif + +#ifdef __GNUC__ +#define NORETURN __attribute__((noreturn)) +#define NOINLINE __attribute__((noinline)) +#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#define NOINSTR __attribute__((no_instrument_function)) +#define DO_NOT_WARN_UNUSED __attribute__((unused)) +#else +#define NORETURN +#define NOINLINE +#define WARN_UNUSED_RESULT +#define NOINSTR +#define DO_NOT_WARN_UNUSED +#endif /* __GNUC__ */ + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) +#endif + +#endif /* CS_COMMON_PLATFORM_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_windows.h" +#endif +#ifndef CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ +#if CS_PLATFORM == CS_P_WINDOWS + +/* + * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) + * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) + * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) + * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) + * MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) + * MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) + * MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003) + * MSVC++ 7.0 _MSC_VER == 1300 + * MSVC++ 6.0 _MSC_VER == 1200 + * MSVC++ 5.0 _MSC_VER == 1100 + */ +#ifdef _MSC_VER +#pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */ +#pragma warning(disable : 4204) /* missing c99 support */ +#endif + +#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS +#define _WINSOCK_DEPRECATED_NO_WARNINGS 1 +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */ +#endif + +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#define strdup _strdup +#endif + +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#ifndef __func__ +#define STRX(x) #x +#define STR(x) STRX(x) +#define __func__ __FILE__ ":" STR(__LINE__) +#endif +#define snprintf _snprintf +#define fileno _fileno +#define vsnprintf _vsnprintf +#define sleep(x) Sleep((x) *1000) +#define to64(x) _atoi64(x) +#if !defined(__MINGW32__) && !defined(__MINGW64__) +#define popen(x, y) _popen((x), (y)) +#define pclose(x) _pclose(x) +#endif +#define rmdir _rmdir +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#define fseeko(x, y, z) _fseeki64((x), (y), (z)) +#else +#define fseeko(x, y, z) fseek((x), (y), (z)) +#endif +#if defined(_MSC_VER) && _MSC_VER <= 1200 +typedef unsigned long uintptr_t; +typedef long intptr_t; +#endif +typedef int socklen_t; +#if _MSC_VER >= 1700 +#include +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#endif +typedef SOCKET sock_t; +typedef uint32_t in_addr_t; +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif +#ifndef UINT32_MAX +#define UINT32_MAX 4294967295 +#endif +#ifndef pid_t +#define pid_t HANDLE +#endif +#define INT64_FMT "I64d" +#define INT64_X_FMT "I64x" +#define SIZE_T_FMT "Iu" +typedef struct _stati64 cs_stat_t; +#ifndef S_ISDIR +#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR) +#endif +#ifndef S_ISREG +#define S_ISREG(x) (((x) &_S_IFMT) == _S_IFREG) +#endif +#define DIRSEP '\\' + +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(x, y) (x) = (y) +#endif +#endif + +#ifndef MG_MAX_HTTP_REQUEST_SIZE +#define MG_MAX_HTTP_REQUEST_SIZE 8192 +#endif + +#ifndef MG_MAX_HTTP_SEND_MBUF +#define MG_MAX_HTTP_SEND_MBUF 4096 +#endif + +#ifndef MG_MAX_HTTP_HEADERS +#define MG_MAX_HTTP_HEADERS 40 +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#ifndef MG_ENABLE_BROADCAST +#define MG_ENABLE_BROADCAST 1 +#endif + +#ifndef MG_ENABLE_DIRECTORY_LISTING +#define MG_ENABLE_DIRECTORY_LISTING 1 +#endif + +#ifndef MG_ENABLE_FILESYSTEM +#define MG_ENABLE_FILESYSTEM 1 +#endif + +#ifndef MG_ENABLE_HTTP_CGI +#define MG_ENABLE_HTTP_CGI MG_ENABLE_FILESYSTEM +#endif + +#ifndef MG_NET_IF +#define MG_NET_IF MG_NET_IF_SOCKET +#endif + +#endif /* CS_PLATFORM == CS_P_WINDOWS */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_unix.h" +#endif +#ifndef CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ +#if CS_PLATFORM == CS_P_UNIX + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif + +/* wants this for C++ */ +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +/* C++ wants that for INT64_MAX */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +/* Enable fseeko() and ftello() functions */ +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif + +/* Enable 64-bit file offsets */ +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#ifndef BYTE_ORDER +#define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN +#define BIG_ENDIAN __DARWIN_BIG_ENDIAN +#define PDP_ENDIAN __DARWIN_PDP_ENDIAN +#define BYTE_ORDER __DARWIN_BYTE_ORDER +#endif +#endif + +/* + * osx correctly avoids defining strtoll when compiling in strict ansi mode. + * c++ 11 standard defines strtoll as well. + * We require strtoll, and if your embedded pre-c99 compiler lacks one, please + * implement a shim. + */ +#if !(defined(__cplusplus) && __cplusplus >= 201103L) && \ + !(defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L) +long long strtoll(const char *, char **, int); +#endif + +typedef int sock_t; +#define INVALID_SOCKET (-1) +#define SIZE_T_FMT "zu" +typedef struct stat cs_stat_t; +#define DIRSEP '/' +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 + +#ifndef __cdecl +#define __cdecl +#endif + +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(x, y) (x) = (y) +#endif +#endif + +#define closesocket(x) close(x) + +#ifndef MG_MAX_HTTP_REQUEST_SIZE +#define MG_MAX_HTTP_REQUEST_SIZE 8192 +#endif + +#ifndef MG_MAX_HTTP_SEND_MBUF +#define MG_MAX_HTTP_SEND_MBUF 4096 +#endif + +#ifndef MG_MAX_HTTP_HEADERS +#define MG_MAX_HTTP_HEADERS 40 +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#ifndef MG_ENABLE_BROADCAST +#define MG_ENABLE_BROADCAST 1 +#endif + +#ifndef MG_ENABLE_DIRECTORY_LISTING +#define MG_ENABLE_DIRECTORY_LISTING 1 +#endif + +#ifndef MG_ENABLE_FILESYSTEM +#define MG_ENABLE_FILESYSTEM 1 +#endif + +#ifndef MG_ENABLE_HTTP_CGI +#define MG_ENABLE_HTTP_CGI MG_ENABLE_FILESYSTEM +#endif + +#ifndef MG_NET_IF +#define MG_NET_IF MG_NET_IF_SOCKET +#endif + +#endif /* CS_PLATFORM == CS_P_UNIX */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_esp32.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_ +#if CS_PLATFORM == CS_P_ESP32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define DIRSEP '/' +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define __cdecl +#define _FILE_OFFSET_BITS 32 + +#define MG_LWIP 1 + +#ifndef MG_NET_IF +#define MG_NET_IF MG_NET_IF_SOCKET +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#endif /* CS_PLATFORM == CS_P_ESP32 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_esp8266.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_ +#if CS_PLATFORM == CS_P_ESP8266 + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define DIRSEP '/' +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define __cdecl +#define _FILE_OFFSET_BITS 32 + +#ifndef RTOS_SDK +#define fileno(x) -1 +#endif + +#define MG_LWIP 1 + +/* struct timeval is defined in sys/time.h. */ +#define LWIP_TIMEVAL_PRIVATE 0 + +#ifndef MG_NET_IF +#include +#if LWIP_SOCKET /* RTOS SDK has LWIP sockets */ +# define MG_NET_IF MG_NET_IF_SOCKET +#else +# define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL +#endif +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#endif /* CS_PLATFORM == CS_P_ESP8266 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_cc3100.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ +#if CS_PLATFORM == CS_P_CC3100 + +#include +#include +#include +#include +#include +#include +#include + +#define MG_NET_IF MG_NET_IF_SIMPLELINK +#define MG_SSL_IF MG_SSL_IF_SIMPLELINK + +/* + * CC3100 SDK and STM32 SDK include headers w/out path, just like + * #include "simplelink.h". As result, we have to add all required directories + * into Makefile IPATH and do the same thing (include w/out path) + */ + +#include +#include +#undef timeval + +typedef int sock_t; +#define INVALID_SOCKET (-1) + +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define SIZE_T_FMT "u" + +#define SOMAXCONN 8 + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); +char *inet_ntoa(struct in_addr in); +int inet_pton(int af, const char *src, void *dst); + +#endif /* CS_PLATFORM == CS_P_CC3100 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_cc3200.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ +#if CS_PLATFORM == CS_P_CC3200 + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __TI_COMPILER_VERSION__ +#include +#include +#endif + +#define MG_NET_IF MG_NET_IF_SIMPLELINK +#define MG_SSL_IF MG_SSL_IF_SIMPLELINK + +/* Only SPIFFS supports directories, SLFS does not. */ +#if defined(CC3200_FS_SPIFFS) && !defined(MG_ENABLE_DIRECTORY_LISTING) +#define MG_ENABLE_DIRECTORY_LISTING 1 +#endif + +/* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */ + +typedef int sock_t; +#define INVALID_SOCKET (-1) +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define DIRSEP '/' +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define __cdecl + +#define fileno(x) -1 + +/* Some functions we implement for Mongoose. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __TI_COMPILER_VERSION__ +struct SlTimeval_t; +#define timeval SlTimeval_t +int gettimeofday(struct timeval *t, void *tz); + +int asprintf(char **strp, const char *fmt, ...); + +#endif + +/* TI's libc does not have stat & friends, add them. */ +#ifdef __TI_COMPILER_VERSION__ + +#include + +typedef unsigned int mode_t; +typedef size_t _off_t; +typedef long ssize_t; + +struct stat { + int st_ino; + mode_t st_mode; + int st_nlink; + time_t st_mtime; + off_t st_size; +}; + +int _stat(const char *pathname, struct stat *st); +#define stat(a, b) _stat(a, b) + +#define __S_IFMT 0170000 + +#define __S_IFDIR 0040000 +#define __S_IFCHR 0020000 +#define __S_IFREG 0100000 + +#define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask)) + +#define S_IFDIR __S_IFDIR +#define S_IFCHR __S_IFCHR +#define S_IFREG __S_IFREG +#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) +#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG) + +/* As of 5.2.7, TI compiler does not support va_copy() yet. */ +#define va_copy(apc, ap) ((apc) = (ap)) + +#endif /* __TI_COMPILER_VERSION__ */ + +#ifdef CC3200_FS_SPIFFS +#include + +typedef struct { + spiffs_DIR dh; + struct spiffs_dirent de; +} DIR; + +#define d_name name +#define dirent spiffs_dirent + +DIR *opendir(const char *dir_name); +int closedir(DIR *dir); +struct dirent *readdir(DIR *dir); +#endif /* CC3200_FS_SPIFFS */ + +#ifdef CC3200_FS_SLFS +#define MG_FS_SLFS +#endif + +#if (defined(CC3200_FS_SPIFFS) || defined(CC3200_FS_SLFS)) && \ + !defined(MG_ENABLE_FILESYSTEM) +#define MG_ENABLE_FILESYSTEM 1 +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CS_PLATFORM == CS_P_CC3200 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_msp432.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_ +#if CS_PLATFORM == CS_P_MSP432 + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __TI_COMPILER_VERSION__ +#include +#include +#endif + +#define MG_NET_IF MG_NET_IF_SIMPLELINK +#define MG_SSL_IF MG_SSL_IF_SIMPLELINK + +/* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */ + +typedef int sock_t; +#define INVALID_SOCKET (-1) +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define DIRSEP '/' +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define __cdecl + +#define fileno(x) -1 + +/* Some functions we implement for Mongoose. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __TI_COMPILER_VERSION__ +struct SlTimeval_t; +#define timeval SlTimeval_t +int gettimeofday(struct timeval *t, void *tz); +#endif + +/* TI's libc does not have stat & friends, add them. */ +#ifdef __TI_COMPILER_VERSION__ + +#include + +typedef unsigned int mode_t; +typedef size_t _off_t; +typedef long ssize_t; + +struct stat { + int st_ino; + mode_t st_mode; + int st_nlink; + time_t st_mtime; + off_t st_size; +}; + +int _stat(const char *pathname, struct stat *st); +#define stat(a, b) _stat(a, b) + +#define __S_IFMT 0170000 + +#define __S_IFDIR 0040000 +#define __S_IFCHR 0020000 +#define __S_IFREG 0100000 + +#define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask)) + +#define S_IFDIR __S_IFDIR +#define S_IFCHR __S_IFCHR +#define S_IFREG __S_IFREG +#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) +#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG) + +/* As of 5.2.7, TI compiler does not support va_copy() yet. */ +#define va_copy(apc, ap) ((apc) = (ap)) + +#endif /* __TI_COMPILER_VERSION__ */ + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#if (defined(CC3200_FS_SPIFFS) || defined(CC3200_FS_SLFS)) && !defined(MG_ENABLE_FILESYSTEM) +#define MG_ENABLE_FILESYSTEM 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CS_PLATFORM == CS_P_MSP432 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_tm4c129.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_ +#if CS_PLATFORM == CS_P_TM4C129 + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __TI_COMPILER_VERSION__ +#include +#include +#endif + +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define DIRSEP '/' +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define __cdecl + +#ifndef MG_NET_IF +# include +# if LWIP_SOCKET +# define MG_NET_IF MG_NET_IF_SOCKET +# else +# define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL +# endif +# define MG_LWIP 1 +#elif MG_NET_IF == MG_NET_IF_SIMPLELINK +# include "common/platforms/simplelink/cs_simplelink.h" +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#ifdef __TI_COMPILER_VERSION__ +/* As of 5.2.8, TI compiler does not support va_copy() yet. */ +#define va_copy(apc, ap) ((apc) = (ap)) +#endif /* __TI_COMPILER_VERSION__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* CS_PLATFORM == CS_P_TM4C129 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_mbed.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ +#if CS_PLATFORM == CS_P_MBED + +/* + * mbed.h contains C++ code (e.g. templates), thus, it should be processed + * only if included directly to startup file (ex: main.cpp) + */ +#ifdef __cplusplus +/* Amalgamated: #include "mbed.h" */ +#endif /* __cplusplus */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct stat cs_stat_t; +#define DIRSEP '/' + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +/* + * mbed can be compiled with the ARM compiler which + * just doesn't come with a gettimeofday shim + * because it's a BSD API and ARM targets embedded + * non-unix platforms. + */ +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +#define _TIMEVAL_DEFINED +#define gettimeofday _gettimeofday + +/* copied from GCC on ARM; for some reason useconds are signed */ +typedef long suseconds_t; /* microseconds (signed) */ +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* and microseconds */ +}; + +#endif + +#if MG_NET_IF == MG_NET_IF_SIMPLELINK + +#define MG_SIMPLELINK_NO_OSI 1 + +#include + +typedef int sock_t; +#define INVALID_SOCKET (-1) + +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define INT64_X_FMT PRIx64 +#define SIZE_T_FMT "u" + +#define SOMAXCONN 8 + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); +char *inet_ntoa(struct in_addr in); +int inet_pton(int af, const char *src, void *dst); +int inet_aton(const char *cp, struct in_addr *inp); +in_addr_t inet_addr(const char *cp); + +#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */ + +#endif /* CS_PLATFORM == CS_P_MBED */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_nrf51.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ +#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_ +#if CS_PLATFORM == CS_P_NRF51 + +#include +#include +#include +#include +#include +#include + +#define to64(x) strtoll(x, NULL, 10) + +#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL +#define MG_LWIP 1 +#define MG_ENABLE_IPV6 1 + +/* + * For ARM C Compiler, make lwip to export `struct timeval`; for other + * compilers, suppress it. + */ +#if !defined(__ARMCC_VERSION) +# define LWIP_TIMEVAL_PRIVATE 0 +#else +struct timeval; +int gettimeofday(struct timeval *tp, void *tzp); +#endif + +#define INT64_FMT PRId64 +#define SIZE_T_FMT "u" + +/* + * ARM C Compiler doesn't have strdup, so we provide it + */ +#define CS_ENABLE_STRDUP defined(__ARMCC_VERSION) + +#endif /* CS_PLATFORM == CS_P_NRF51 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_nrf52.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ +#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_ +#if CS_PLATFORM == CS_P_NRF52 + +#include +#include +#include +#include +#include +#include +#include + +#define to64(x) strtoll(x, NULL, 10) + +#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL +#define MG_LWIP 1 +#define MG_ENABLE_IPV6 1 + +#if !defined(ENOSPC) +# define ENOSPC 28 /* No space left on device */ +#endif + +/* + * For ARM C Compiler, make lwip to export `struct timeval`; for other + * compilers, suppress it. + */ +#if !defined(__ARMCC_VERSION) +# define LWIP_TIMEVAL_PRIVATE 0 +#endif + +#define INT64_FMT PRId64 +#define SIZE_T_FMT "u" + +/* + * ARM C Compiler doesn't have strdup, so we provide it + */ +#define CS_ENABLE_STRDUP defined(__ARMCC_VERSION) + +#endif /* CS_PLATFORM == CS_P_NRF52 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/cs_simplelink.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ +#define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ + +/* If simplelink.h is already included, all bets are off. */ +#if defined(MG_NET_IF) && MG_NET_IF == MG_NET_IF_SIMPLELINK && \ + !defined(__SIMPLELINK_H__) + +#include + +#ifndef __TI_COMPILER_VERSION__ +#undef __CONCAT +#undef FD_CLR +#undef FD_ISSET +#undef FD_SET +#undef FD_SETSIZE +#undef FD_ZERO +#undef fd_set +#endif + +/* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves + * and undef it. */ +#define PROVISIONING_API_H_ +#include +#undef PROVISIONING_API_H_ +#undef SL_INC_STD_BSD_API_NAMING + +#include +#include + +/* Now define only the subset of the BSD API that we use. + * Notably, close(), read() and write() are not defined. */ +#define AF_INET SL_AF_INET + +#define socklen_t SlSocklen_t +#define sockaddr SlSockAddr_t +#define sockaddr_in SlSockAddrIn_t +#define in_addr SlInAddr_t + +#define SOCK_STREAM SL_SOCK_STREAM +#define SOCK_DGRAM SL_SOCK_DGRAM + +#define htonl sl_Htonl +#define ntohl sl_Ntohl +#define htons sl_Htons +#define ntohs sl_Ntohs + +#ifndef EACCES +#define EACCES SL_EACCES +#endif +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT SL_EAFNOSUPPORT +#endif +#ifndef EAGAIN +#define EAGAIN SL_EAGAIN +#endif +#ifndef EBADF +#define EBADF SL_EBADF +#endif +#ifndef EINVAL +#define EINVAL SL_EINVAL +#endif +#ifndef ENOMEM +#define ENOMEM SL_ENOMEM +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK SL_EWOULDBLOCK +#endif + +#define SOMAXCONN 8 + +#ifdef __cplusplus +extern "C" { +#endif + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); +char *inet_ntoa(struct in_addr in); +int inet_pton(int af, const char *src, void *dst); + +struct mg_mgr; +struct mg_connection; + +typedef void (*mg_init_cb)(struct mg_mgr *mgr); +bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init); + +void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg); + +int sl_fs_init(void); + +void sl_restart_cb(struct mg_mgr *mgr); + +int sl_set_ssl_opts(struct mg_connection *nc); + +#ifdef __cplusplus +} +#endif + +#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(__SIMPLELINK_H__) */ + +#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_wince.h" +#endif +#ifndef CS_COMMON_PLATFORMS_PLATFORM_WINCE_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_WINCE_H_ + +#if CS_PLATFORM == CS_P_WINCE + +/* + * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) + * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) + * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) + * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) + * MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) + * MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) + * MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003) + * MSVC++ 7.0 _MSC_VER == 1300 + * MSVC++ 6.0 _MSC_VER == 1200 + * MSVC++ 5.0 _MSC_VER == 1100 + */ +#pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */ +#pragma warning(disable : 4204) /* missing c99 support */ + +#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS +#define _WINSOCK_DEPRECATED_NO_WARNINGS 1 +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "ws2.lib") /* Linking with WinCE winsock library */ + +#include +#include +#include + +#define strdup _strdup + +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif + +#ifndef __func__ +#define STRX(x) #x +#define STR(x) STRX(x) +#define __func__ __FILE__ ":" STR(__LINE__) +#endif + +#define snprintf _snprintf +#define fileno _fileno +#define vsnprintf _vsnprintf +#define sleep(x) Sleep((x) *1000) +#define to64(x) _atoi64(x) +#define rmdir _rmdir + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#define fseeko(x, y, z) _fseeki64((x), (y), (z)) +#else +#define fseeko(x, y, z) fseek((x), (y), (z)) +#endif + +typedef int socklen_t; + +#if _MSC_VER >= 1700 +#include +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#endif + +typedef SOCKET sock_t; +typedef uint32_t in_addr_t; + +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX 4294967295 +#endif + +#ifndef pid_t +#define pid_t HANDLE +#endif + +#define INT64_FMT "I64d" +#define INT64_X_FMT "I64x" +/* TODO(alashkin): check if this is correct */ +#define SIZE_T_FMT "u" + +#define DIRSEP '\\' + +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(x, y) (x) = (y) +#endif +#endif + +#ifndef MG_MAX_HTTP_REQUEST_SIZE +#define MG_MAX_HTTP_REQUEST_SIZE 8192 +#endif + +#ifndef MG_MAX_HTTP_SEND_MBUF +#define MG_MAX_HTTP_SEND_MBUF 4096 +#endif + +#ifndef MG_MAX_HTTP_HEADERS +#define MG_MAX_HTTP_HEADERS 40 +#endif + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#define abort() DebugBreak(); + +#ifndef BUFSIZ +#define BUFSIZ 4096 +#endif +/* + * Explicitly disabling MG_ENABLE_THREADS for WinCE + * because they are enabled for _WIN32 by default + */ +#ifndef MG_ENABLE_THREADS +#define MG_ENABLE_THREADS 0 +#endif + +#ifndef MG_ENABLE_FILESYSTEM +#define MG_ENABLE_FILESYSTEM 1 +#endif + +#ifndef MG_NET_IF +#define MG_NET_IF MG_NET_IF_SOCKET +#endif + +typedef struct _stati64 { + uint32_t st_mtime; + uint32_t st_size; + uint32_t st_mode; +} cs_stat_t; + +/* + * WinCE 6.0 has a lot of useful definitions in ATL (not windows.h) headers + * use #ifdefs to avoid conflicts + */ + +#ifndef ENOENT +#define ENOENT ERROR_PATH_NOT_FOUND +#endif + +#ifndef EACCES +#define EACCES ERROR_ACCESS_DENIED +#endif + +#ifndef ENOMEM +#define ENOMEM ERROR_NOT_ENOUGH_MEMORY +#endif + +#ifndef _UINTPTR_T_DEFINED +typedef unsigned int* uintptr_t; +#endif + +#define _S_IFREG 2 +#define _S_IFDIR 4 + +#ifndef S_ISDIR +#define S_ISDIR(x) (((x) & _S_IFDIR) != 0) +#endif + +#ifndef S_ISREG +#define S_ISREG(x) (((x) & _S_IFREG) != 0) +#endif + +int open(const char *filename, int oflag, int pmode); +int _wstati64(const wchar_t *path, cs_stat_t *st); +const char *strerror(); + +#endif /* CS_PLATFORM == CS_P_WINCE */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_WINCE_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_nxp_lpc.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_ + +#if CS_PLATFORM == CS_P_NXP_LPC + +#include +#include +#include + +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define INT64_FMT "lld" +#define INT64_X_FMT "llx" +#define __cdecl + +#define MG_LWIP 1 + +#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL + +/* + * LPCXpress comes with 3 C library implementations: Newlib, NewlibNano and Redlib. + * See https://community.nxp.com/message/630860 for more details. + * + * Redlib is the default and lacks certain things, so we provide them. + */ +#ifdef __REDLIB_INTERFACE_VERSION__ + +/* Let LWIP define timeval for us. */ +#define LWIP_TIMEVAL_PRIVATE 1 + +#define va_copy(d, s) __builtin_va_copy(d, s) + +#define CS_ENABLE_TO64 1 +#define to64(x) cs_to64(x) + +#define CS_ENABLE_STRDUP 1 + +#else + +#include +#define LWIP_TIMEVAL_PRIVATE 0 +#define to64(x) strtoll(x, NULL, 10) + +#endif + +#endif /* CS_PLATFORM == CS_P_NXP_LPC */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_nxp_kinetis.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_ + +#if CS_PLATFORM == CS_P_NXP_KINETIS + +#include +#include +#include +#include + +#define SIZE_T_FMT "u" +typedef struct stat cs_stat_t; +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT "lld" +#define INT64_X_FMT "llx" +#define __cdecl + +#define MG_LWIP 1 + +#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL + +/* struct timeval is defined in sys/time.h. */ +#define LWIP_TIMEVAL_PRIVATE 0 + +#endif /* CS_PLATFORM == CS_P_NXP_KINETIS */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_pic32.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_ + +#if CS_PLATFORM == CS_P_PIC32 + +#define MG_NET_IF MG_NET_IF_PIC32 + +#include +#include +#include +#include + +#include +#include + +#include + +typedef TCP_SOCKET sock_t; +#define to64(x) strtoll(x, NULL, 10) + +#define SIZE_T_FMT "lu" +#define INT64_FMT "lld" + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +char* inet_ntoa(struct in_addr in); + +#endif /* CS_PLATFORM == CS_P_PIC32 */ + +#endif /* CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/platform_stm32.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PLATFORM_STM32_H_ +#define CS_COMMON_PLATFORMS_PLATFORM_STM32_H_ +#if CS_PLATFORM == CS_P_STM32 + +#include +#include +#include +#include +#include +#include +#include + +#define to64(x) strtoll(x, NULL, 10) +#define INT64_FMT PRId64 +#define SIZE_T_FMT "u" + +#ifndef CS_ENABLE_STDIO +#define CS_ENABLE_STDIO 1 +#endif + +#endif /* CS_PLATFORM == CS_P_STM32 */ +#endif /* CS_COMMON_PLATFORMS_PLATFORM_STM32_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/lwip/mg_lwip.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ +#define CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ + +#ifndef MG_LWIP +#define MG_LWIP 0 +#endif + +#if MG_LWIP + +/* + * When compiling for nRF5x chips with arm-none-eabi-gcc, it has BYTE_ORDER + * already defined, so in order to avoid warnings in lwip, we have to undefine + * it. + * + * TODO: Check if in the future versions of nRF5 SDK that changes. + * Current version of nRF51 SDK: 0.8.0 + * nRF5 SDK: 0.9.0 + */ +#if CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52 +#undef BYTE_ORDER +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef LWIP_PROVIDE_ERRNO +#include +#endif + +#if LWIP_SOCKET +#include +#else +/* We really need the definitions from sockets.h. */ +#undef LWIP_SOCKET +#define LWIP_SOCKET 1 +#include +#undef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif + +#define INVALID_SOCKET (-1) +#define SOMAXCONN 10 +typedef int sock_t; + +#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL +struct mg_mgr; +struct mg_connection; +uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr); +void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle, + int interval, int count); +#endif + +#endif /* MG_LWIP */ + +#endif /* CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/cs_time.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_CS_TIME_H_ +#define CS_COMMON_CS_TIME_H_ + +/* Amalgamated: #include "common/platform.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Sub-second granularity time(). */ +double cs_time(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_CS_TIME_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/mg_str.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_MG_STR_H_ +#define CS_COMMON_MG_STR_H_ + +#include + +/* Amalgamated: #include "common/platform.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Describes chunk of memory */ +struct mg_str { + const char *p; /* Memory chunk pointer */ + size_t len; /* Memory chunk length */ +}; + +/* + * Helper functions for creating mg_str struct from plain C string. + * `NULL` is allowed and becomes `{NULL, 0}`. + */ +struct mg_str mg_mk_str(const char *s); +struct mg_str mg_mk_str_n(const char *s, size_t len); + +/* Macro for initializing mg_str. */ +#define MG_MK_STR(str_literal) \ + { str_literal, sizeof(str_literal) - 1 } + +/* + * Cross-platform version of `strcmp()` where where first string is + * specified by `struct mg_str`. + */ +int mg_vcmp(const struct mg_str *str2, const char *str1); + +/* + * Cross-platform version of `strncasecmp()` where first string is + * specified by `struct mg_str`. + */ +int mg_vcasecmp(const struct mg_str *str2, const char *str1); + +struct mg_str mg_strdup(const struct mg_str s); +int mg_strcmp(const struct mg_str str1, const struct mg_str str2); +int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_MG_STR_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/mbuf.h" +#endif +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + */ + +/* + * === Memory Buffers + * + * Mbufs are mutable/growing memory buffers, like C++ strings. + * Mbuf can append data to the end of a buffer or insert data into arbitrary + * position in the middle of a buffer. The buffer grows automatically when + * needed. + */ + +#ifndef CS_COMMON_MBUF_H_ +#define CS_COMMON_MBUF_H_ + +#include +/* Amalgamated: #include "common/platform.h" */ + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef MBUF_SIZE_MULTIPLIER +#define MBUF_SIZE_MULTIPLIER 1.5 +#endif + +/* Memory buffer descriptor */ +struct mbuf { + char *buf; /* Buffer pointer */ + size_t len; /* Data length. Data is located between offset 0 and len. */ + size_t size; /* Buffer size allocated by realloc(1). Must be >= len */ +}; + +/* + * Initialises an Mbuf. + * `initial_capacity` specifies the initial capacity of the mbuf. + */ +void mbuf_init(struct mbuf *, size_t initial_capacity); + +/* Frees the space allocated for the mbuffer and resets the mbuf structure. */ +void mbuf_free(struct mbuf *); + +/* + * Appends data to the Mbuf. + * + * Returns the number of bytes appended or 0 if out of memory. + */ +size_t mbuf_append(struct mbuf *, const void *data, size_t data_size); + +/* + * Inserts data at a specified offset in the Mbuf. + * + * Existing data will be shifted forwards and the buffer will + * be grown if necessary. + * Returns the number of bytes inserted. + */ +size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t); + +/* Removes `data_size` bytes from the beginning of the buffer. */ +void mbuf_remove(struct mbuf *, size_t data_size); + +/* + * Resizes an Mbuf. + * + * If `new_size` is smaller than buffer's `len`, the + * resize is not performed. + */ +void mbuf_resize(struct mbuf *, size_t new_size); + +/* Shrinks an Mbuf by resizing its `size` to `len`. */ +void mbuf_trim(struct mbuf *); + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_MBUF_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/sha1.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_SHA1_H_ +#define CS_COMMON_SHA1_H_ + +#ifndef DISABLE_SHA1 +#define DISABLE_SHA1 0 +#endif + +#if !DISABLE_SHA1 + +/* Amalgamated: #include "common/platform.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} cs_sha1_ctx; + +void cs_sha1_init(cs_sha1_ctx *); +void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len); +void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *); +void cs_hmac_sha1(const unsigned char *key, size_t key_len, + const unsigned char *text, size_t text_len, + unsigned char out[20]); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DISABLE_SHA1 */ + +#endif /* CS_COMMON_SHA1_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/md5.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_MD5_H_ +#define CS_COMMON_MD5_H_ + +/* Amalgamated: #include "common/platform.h" */ + +#ifndef DISABLE_MD5 +#define DISABLE_MD5 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + unsigned char in[64]; +} MD5_CTX; + +void MD5_Init(MD5_CTX *c); +void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len); +void MD5_Final(unsigned char *md, MD5_CTX *c); + +/* + * Return stringified MD5 hash for NULL terminated list of pointer/length pairs. + * A length should be specified as size_t variable. + * Example: + * + * char buf[33]; + * cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL); + */ +char *cs_md5(char buf[33], ...); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_MD5_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/base64.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_BASE64_H_ +#define CS_COMMON_BASE64_H_ + +#ifndef DISABLE_BASE64 +#define DISABLE_BASE64 0 +#endif + +#if !DISABLE_BASE64 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*cs_base64_putc_t)(char, void *); + +struct cs_base64_ctx { + /* cannot call it putc because it's a macro on some environments */ + cs_base64_putc_t b64_putc; + unsigned char chunk[3]; + int chunk_size; + void *user_data; +}; + +void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc, + void *user_data); +void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len); +void cs_base64_finish(struct cs_base64_ctx *ctx); + +void cs_base64_encode(const unsigned char *src, int src_len, char *dst); +void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len); +int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len); + +#ifdef __cplusplus +} +#endif + +#endif /* DISABLE_BASE64 */ + +#endif /* CS_COMMON_BASE64_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/str_util.h" +#endif +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_STR_UTIL_H_ +#define CS_COMMON_STR_UTIL_H_ + +#include +#include + +/* Amalgamated: #include "common/platform.h" */ + +#ifndef CS_ENABLE_STRDUP +#define CS_ENABLE_STRDUP 0 +#endif + +#ifndef CS_ENABLE_TO64 +#define CS_ENABLE_TO64 0 +#endif + +/* + * Expands to a string representation of its argument: e.g. + * `CS_STRINGIFY_LIT(5) expands to "5"` + */ +#define CS_STRINGIFY_LIT(x) #x + +/* + * Expands to a string representation of its argument, which is allowed + * to be a macro: e.g. + * + * #define FOO 123 + * CS_STRINGIFY_MACRO(FOO) + * + * expands to 123. + */ +#define CS_STRINGIFY_MACRO(x) CS_STRINGIFY_LIT(x) + +#ifdef __cplusplus +extern "C" { +#endif + +size_t c_strnlen(const char *s, size_t maxlen); +int c_snprintf(char *buf, size_t buf_size, const char *format, ...); +int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap); +/* + * Find the first occurrence of find in s, where the search is limited to the + * first slen characters of s. + */ +const char *c_strnstr(const char *s, const char *find, size_t slen); + +/* + * Stringify binary data. Output buffer size must be 2 * size_of_input + 1 + * because each byte of input takes 2 bytes in string representation + * plus 1 byte for the terminating \0 character. + */ +void cs_to_hex(char *to, const unsigned char *p, size_t len); + +/* + * Convert stringified binary data back to binary. + * Does the reverse of `cs_to_hex()`. + */ +void cs_from_hex(char *to, const char *p, size_t len); + +#if CS_ENABLE_STRDUP +char *strdup(const char *src); +#endif + +#if CS_ENABLE_TO64 +#include +/* + * Simple string -> int64 conversion routine. + */ +int64_t cs_to64(const char *s); +#endif + +/* + * Cross-platform version of `strncasecmp()`. + */ +int mg_ncasecmp(const char *s1, const char *s2, size_t len); + +/* + * Cross-platform version of `strcasecmp()`. + */ +int mg_casecmp(const char *s1, const char *s2); + +/* + * Prints message to the buffer. If the buffer is large enough to hold the + * message, it returns buffer. If buffer is to small, it allocates a large + * enough buffer on heap and returns allocated buffer. + * This is a supposed use case: + * + * char buf[5], *p = buf; + * mg_avprintf(&p, sizeof(buf), "%s", "hi there"); + * use_p_somehow(p); + * if (p != buf) { + * free(p); + * } + * + * The purpose of this is to avoid malloc-ing if generated strings are small. + */ +int mg_asprintf(char **buf, size_t size, const char *fmt, ...); + +/* Same as mg_asprintf, but takes varargs list. */ +int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap); + +#ifdef __cplusplus +} +#endif + +#endif /* CS_COMMON_STR_UTIL_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/queue.h" +#endif +/* clang-format off */ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define QMD_SAVELINK(name, link) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/features.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_FEATURES_H_ +#define CS_MONGOOSE_SRC_FEATURES_H_ + +#ifndef MG_DISABLE_HTTP_DIGEST_AUTH +#define MG_DISABLE_HTTP_DIGEST_AUTH 0 +#endif + +#ifndef MG_DISABLE_HTTP_KEEP_ALIVE +#define MG_DISABLE_HTTP_KEEP_ALIVE 0 +#endif + +#ifndef MG_DISABLE_PFS +#define MG_DISABLE_PFS 0 +#endif + +#ifndef MG_DISABLE_WS_RANDOM_MASK +#define MG_DISABLE_WS_RANDOM_MASK 0 +#endif + +#ifndef MG_ENABLE_ASYNC_RESOLVER +#define MG_ENABLE_ASYNC_RESOLVER 1 +#endif + +#ifndef MG_ENABLE_BROADCAST +#define MG_ENABLE_BROADCAST 0 +#endif + +#ifndef MG_ENABLE_COAP +#define MG_ENABLE_COAP 0 +#endif + +#ifndef MG_ENABLE_DEBUG +#define MG_ENABLE_DEBUG 0 +#endif + +#ifndef MG_ENABLE_DIRECTORY_LISTING +#define MG_ENABLE_DIRECTORY_LISTING 0 +#endif + +#ifndef MG_ENABLE_DNS +#define MG_ENABLE_DNS 1 +#endif + +#ifndef MG_ENABLE_DNS_SERVER +#define MG_ENABLE_DNS_SERVER 0 +#endif + +#ifndef MG_ENABLE_FAKE_DAVLOCK +#define MG_ENABLE_FAKE_DAVLOCK 0 +#endif + +#ifndef MG_ENABLE_FILESYSTEM +#define MG_ENABLE_FILESYSTEM 0 +#endif + +#ifndef MG_ENABLE_GETADDRINFO +#define MG_ENABLE_GETADDRINFO 0 +#endif + +#ifndef MG_ENABLE_HEXDUMP +#define MG_ENABLE_HEXDUMP CS_ENABLE_STDIO +#endif + +#ifndef MG_ENABLE_HTTP +#define MG_ENABLE_HTTP 1 +#endif + +#ifndef MG_ENABLE_HTTP_CGI +#define MG_ENABLE_HTTP_CGI 0 +#endif + +#ifndef MG_ENABLE_HTTP_SSI +#define MG_ENABLE_HTTP_SSI MG_ENABLE_FILESYSTEM +#endif + +#ifndef MG_ENABLE_HTTP_SSI_EXEC +#define MG_ENABLE_HTTP_SSI_EXEC 0 +#endif + +#ifndef MG_ENABLE_HTTP_STREAMING_MULTIPART +#define MG_ENABLE_HTTP_STREAMING_MULTIPART 0 +#endif + +#ifndef MG_ENABLE_HTTP_WEBDAV +#define MG_ENABLE_HTTP_WEBDAV 0 +#endif + +#ifndef MG_ENABLE_HTTP_WEBSOCKET +#define MG_ENABLE_HTTP_WEBSOCKET MG_ENABLE_HTTP +#endif + +#ifndef MG_ENABLE_IPV6 +#define MG_ENABLE_IPV6 0 +#endif + +#ifndef MG_ENABLE_JAVASCRIPT +#define MG_ENABLE_JAVASCRIPT 0 +#endif + +#ifndef MG_ENABLE_MQTT +#define MG_ENABLE_MQTT 1 +#endif + +#ifndef MG_ENABLE_MQTT_BROKER +#define MG_ENABLE_MQTT_BROKER 0 +#endif + +#ifndef MG_ENABLE_SSL +#define MG_ENABLE_SSL 0 +#endif + +#ifndef MG_ENABLE_SYNC_RESOLVER +#define MG_ENABLE_SYNC_RESOLVER 0 +#endif + +#ifndef MG_ENABLE_STDIO +#define MG_ENABLE_STDIO CS_ENABLE_STDIO +#endif + +#ifndef MG_NET_IF +#define MG_NET_IF MG_NET_IF_SOCKET +#endif + +#ifndef MG_SSL_IF +#define MG_SSL_IF MG_SSL_IF_OPENSSL +#endif + +#ifndef MG_ENABLE_THREADS /* ifdef-ok */ +#ifdef _WIN32 +#define MG_ENABLE_THREADS 1 +#else +#define MG_ENABLE_THREADS 0 +#endif +#endif + +#if MG_ENABLE_DEBUG && !defined(CS_ENABLE_DEBUG) +#define CS_ENABLE_DEBUG 1 +#endif + +/* MQTT broker requires MQTT */ +#if MG_ENABLE_MQTT_BROKER && !MG_ENABLE_MQTT +#undef MG_ENABLE_MQTT +#define MG_ENABLE_MQTT 1 +#endif + +#ifndef MG_ENABLE_HTTP_URL_REWRITES +#define MG_ENABLE_HTTP_URL_REWRITES \ + (CS_PLATFORM == CS_P_WINDOWS || CS_PLATFORM == CS_P_UNIX) +#endif + +#ifndef MG_ENABLE_TUN +#define MG_ENABLE_TUN MG_ENABLE_HTTP_WEBSOCKET +#endif + +#ifndef MG_ENABLE_SNTP +#define MG_ENABLE_SNTP 0 +#endif + +#ifndef MG_ENABLE_EXTRA_ERRORS_DESC +#define MG_ENABLE_EXTRA_ERRORS_DESC 0 +#endif + +#endif /* CS_MONGOOSE_SRC_FEATURES_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net_if.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_NET_IF_H_ +#define CS_MONGOOSE_SRC_NET_IF_H_ + +/* Amalgamated: #include "common/platform.h" */ + +/* + * Internal async networking core interface. + * Consists of calls made by the core, which should not block, + * and callbacks back into the core ("..._cb"). + * Callbacks may (will) cause methods to be invoked from within, + * but methods are not allowed to invoke callbacks inline. + * + * Implementation must ensure that only one callback is invoked at any time. + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MG_MAIN_IFACE 0 + +struct mg_mgr; +struct mg_connection; +union socket_address; + +struct mg_iface_vtable; + +struct mg_iface { + struct mg_mgr *mgr; + void *data; /* Implementation-specific data */ + struct mg_iface_vtable *vtable; +}; + +struct mg_iface_vtable { + void (*init)(struct mg_iface *iface); + void (*free)(struct mg_iface *iface); + void (*add_conn)(struct mg_connection *nc); + void (*remove_conn)(struct mg_connection *nc); + time_t (*poll)(struct mg_iface *iface, int timeout_ms); + + /* Set up a listening TCP socket on a given address. rv = 0 -> ok. */ + int (*listen_tcp)(struct mg_connection *nc, union socket_address *sa); + /* Request that a "listening" UDP socket be created. */ + int (*listen_udp)(struct mg_connection *nc, union socket_address *sa); + + /* Request that a TCP connection is made to the specified address. */ + void (*connect_tcp)(struct mg_connection *nc, const union socket_address *sa); + /* Open a UDP socket. Doesn't actually connect anything. */ + void (*connect_udp)(struct mg_connection *nc); + + /* Send functions for TCP and UDP. Sent data is copied before return. */ + void (*tcp_send)(struct mg_connection *nc, const void *buf, size_t len); + void (*udp_send)(struct mg_connection *nc, const void *buf, size_t len); + + void (*recved)(struct mg_connection *nc, size_t len); + + /* Perform interface-related connection initialization. Return 1 on ok. */ + int (*create_conn)(struct mg_connection *nc); + /* Perform interface-related cleanup on connection before destruction. */ + void (*destroy_conn)(struct mg_connection *nc); + + /* Associate a socket to a connection. */ + void (*sock_set)(struct mg_connection *nc, sock_t sock); + + /* Put connection's address into *sa, local (remote = 0) or remote. */ + void (*get_conn_addr)(struct mg_connection *nc, int remote, + union socket_address *sa); +}; + +extern struct mg_iface_vtable *mg_ifaces[]; +extern int mg_num_ifaces; + +/* Creates a new interface instance. */ +struct mg_iface *mg_if_create_iface(struct mg_iface_vtable *vtable, + struct mg_mgr *mgr); + +/* + * Find an interface with a given implementation. The search is started from + * interface `from`, exclusive. Returns NULL if none is found. + */ +struct mg_iface *mg_find_iface(struct mg_mgr *mgr, + struct mg_iface_vtable *vtable, + struct mg_iface *from); +/* + * Deliver a new TCP connection. Returns NULL in case on error (unable to + * create connection, in which case interface state should be discarded. + * This is phase 1 of the two-phase process - MG_EV_ACCEPT will be delivered + * when mg_if_accept_tcp_cb is invoked. + */ +struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc); +void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa, + size_t sa_len); + +/* Callback invoked by connect methods. err = 0 -> ok, != 0 -> error. */ +void mg_if_connect_cb(struct mg_connection *nc, int err); +/* Callback that reports that data has been put on the wire. */ +void mg_if_sent_cb(struct mg_connection *nc, int num_sent); +/* + * Receive callback. + * if `own` is true, buf must be heap-allocated and ownership is transferred + * to the core. + * Core will acknowledge consumption by calling iface::recved. + */ +void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len, int own); +/* + * Receive callback. + * buf must be heap-allocated and ownership is transferred to the core. + * Core will acknowledge consumption by calling iface::recved. + */ +void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, + union socket_address *sa, size_t sa_len); + +/* void mg_if_close_conn(struct mg_connection *nc); */ + +/* Deliver a POLL event to the connection. */ +void mg_if_poll(struct mg_connection *nc, time_t now); + +/* Deliver a TIMER event to the connection. */ +void mg_if_timer(struct mg_connection *c, double now); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_MONGOOSE_SRC_NET_IF_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/ssl_if.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_SSL_IF_H_ +#define CS_MONGOOSE_SRC_SSL_IF_H_ + +#if MG_ENABLE_SSL + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct mg_ssl_if_ctx; +struct mg_connection; + +void mg_ssl_if_init(); + +enum mg_ssl_if_result { + MG_SSL_OK = 0, + MG_SSL_WANT_READ = -1, + MG_SSL_WANT_WRITE = -2, + MG_SSL_ERROR = -3, +}; + +struct mg_ssl_if_conn_params { + const char *cert; + const char *key; + const char *ca_cert; + const char *server_name; + const char *cipher_suites; +}; + +enum mg_ssl_if_result mg_ssl_if_conn_init( + struct mg_connection *nc, const struct mg_ssl_if_conn_params *params, + const char **err_msg); +enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc, + struct mg_connection *lc); +void mg_ssl_if_conn_free(struct mg_connection *nc); + +enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc); +int mg_ssl_if_read(struct mg_connection *nc, void *buf, size_t buf_size); +int mg_ssl_if_write(struct mg_connection *nc, const void *data, size_t len); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_SSL */ + +#endif /* CS_MONGOOSE_SRC_SSL_IF_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +/* + * === Core API: TCP/UDP/SSL + * + * NOTE: Mongoose manager is single threaded. It does not protect + * its data structures by mutexes, therefore all functions that are dealing + * with a particular event manager should be called from the same thread, + * with exception of the `mg_broadcast()` function. It is fine to have different + * event managers handled by different threads. + */ + +#ifndef CS_MONGOOSE_SRC_NET_H_ +#define CS_MONGOOSE_SRC_NET_H_ + +#if MG_ENABLE_JAVASCRIPT +#define EXCLUDE_COMMON +#include +#endif + +/* Amalgamated: #include "mongoose/src/common.h" */ +/* Amalgamated: #include "mongoose/src/net_if.h" */ +/* Amalgamated: #include "common/mbuf.h" */ + +#ifndef MG_VPRINTF_BUFFER_SIZE +#define MG_VPRINTF_BUFFER_SIZE 100 +#endif + +#ifdef MG_USE_READ_WRITE +#define MG_RECV_FUNC(s, b, l, f) read(s, b, l) +#define MG_SEND_FUNC(s, b, l, f) write(s, b, l) +#else +#define MG_RECV_FUNC(s, b, l, f) recv(s, b, l, f) +#define MG_SEND_FUNC(s, b, l, f) send(s, b, l, f) +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +union socket_address { + struct sockaddr sa; + struct sockaddr_in sin; +#if MG_ENABLE_IPV6 + struct sockaddr_in6 sin6; +#else + struct sockaddr sin6; +#endif +}; + +struct mg_connection; + +/* + * Callback function (event handler) prototype. Must be defined by the user. + * Mongoose calls the event handler, passing the events defined below. + */ +typedef void (*mg_event_handler_t)(struct mg_connection *nc, int ev, + void *ev_data); + +/* Events. Meaning of event parameter (evp) is given in the comment. */ +#define MG_EV_POLL 0 /* Sent to each connection on each mg_mgr_poll() call */ +#define MG_EV_ACCEPT 1 /* New connection accepted. union socket_address * */ +#define MG_EV_CONNECT 2 /* connect() succeeded or failed. int * */ +#define MG_EV_RECV 3 /* Data has benn received. int *num_bytes */ +#define MG_EV_SEND 4 /* Data has been written to a socket. int *num_bytes */ +#define MG_EV_CLOSE 5 /* Connection is closed. NULL */ +#define MG_EV_TIMER 6 /* now >= conn->ev_timer_time. double * */ + +/* + * Mongoose event manager. + */ +struct mg_mgr { + struct mg_connection *active_connections; +#if MG_ENABLE_HEXDUMP + const char *hexdump_file; /* Debug hexdump file path */ +#endif +#if MG_ENABLE_BROADCAST + sock_t ctl[2]; /* Socketpair for mg_broadcast() */ +#endif + void *user_data; /* User data */ + int num_ifaces; + struct mg_iface **ifaces; /* network interfaces */ +#if MG_ENABLE_JAVASCRIPT + struct v7 *v7; +#endif +}; + +/* + * Mongoose connection. + */ +struct mg_connection { + struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */ + struct mg_connection *listener; /* Set only for accept()-ed connections */ + struct mg_mgr *mgr; /* Pointer to containing manager */ + + sock_t sock; /* Socket to the remote peer */ + int err; + union socket_address sa; /* Remote peer address */ + size_t recv_mbuf_limit; /* Max size of recv buffer */ + struct mbuf recv_mbuf; /* Received data */ + struct mbuf send_mbuf; /* Data scheduled for sending */ + time_t last_io_time; /* Timestamp of the last socket IO */ + double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ +#if MG_ENABLE_SSL + void *ssl_if_data; /* SSL library data. */ +#endif + mg_event_handler_t proto_handler; /* Protocol-specific event handler */ + void *proto_data; /* Protocol-specific data */ + void (*proto_data_destructor)(void *proto_data); + mg_event_handler_t handler; /* Event handler function */ + void *user_data; /* User-specific data */ + union { + void *v; + /* + * the C standard is fussy about fitting function pointers into + * void pointers, since some archs might have fat pointers for functions. + */ + mg_event_handler_t f; + } priv_1; /* Used by mg_enable_multithreading() */ + void *priv_2; /* Used by mg_enable_multithreading() */ + void *mgr_data; /* Implementation-specific event manager's data. */ + struct mg_iface *iface; + unsigned long flags; +/* Flags set by Mongoose */ +#define MG_F_LISTENING (1 << 0) /* This connection is listening */ +#define MG_F_UDP (1 << 1) /* This connection is UDP */ +#define MG_F_RESOLVING (1 << 2) /* Waiting for async resolver */ +#define MG_F_CONNECTING (1 << 3) /* connect() call in progress */ +#define MG_F_SSL (1 << 4) /* SSL is enabled on the connection */ +#define MG_F_SSL_HANDSHAKE_DONE (1 << 5) /* SSL hanshake has completed */ +#define MG_F_WANT_READ (1 << 6) /* SSL specific */ +#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */ +#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */ + +/* Flags that are settable by user */ +#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */ +#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */ +#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */ +#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */ +#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */ +#define MG_F_TUN_DO_NOT_RECONNECT (1 << 15) /* Don't reconnect tunnel */ + +#define MG_F_USER_1 (1 << 20) /* Flags left for application */ +#define MG_F_USER_2 (1 << 21) +#define MG_F_USER_3 (1 << 22) +#define MG_F_USER_4 (1 << 23) +#define MG_F_USER_5 (1 << 24) +#define MG_F_USER_6 (1 << 25) +}; + +/* + * Initialise Mongoose manager. Side effect: ignores SIGPIPE signal. + * `mgr->user_data` field will be initialised with a `user_data` parameter. + * That is an arbitrary pointer, where the user code can associate some data + * with the particular Mongoose manager. For example, a C++ wrapper class + * could be written in which case `user_data` can hold a pointer to the + * class instance. + */ +void mg_mgr_init(struct mg_mgr *mgr, void *user_data); + +/* + * Optional parameters to `mg_mgr_init_opt()`. + * + * If `main_iface` is not NULL, it will be used as the main interface in the + * default interface set. The pointer will be free'd by `mg_mgr_free`. + * Otherwise, the main interface will be autodetected based on the current + * platform. + * + * If `num_ifaces` is 0 and `ifaces` is NULL, the default interface set will be + * used. + * This is an advanced option, as it requires you to construct a full interface + * set, including special networking interfaces required by some optional + * features such as TCP tunneling. Memory backing `ifaces` and each of the + * `num_ifaces` pointers it contains will be reclaimed by `mg_mgr_free`. + */ +struct mg_mgr_init_opts { + struct mg_iface_vtable *main_iface; + int num_ifaces; + struct mg_iface_vtable **ifaces; +}; + +/* + * Like `mg_mgr_init` but with more options. + * + * Notably, this allows you to create a manger and choose + * dynamically which networking interface implementation to use. + */ +void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, + struct mg_mgr_init_opts opts); + +/* + * De-initialises Mongoose manager. + * + * Closes and deallocates all active connections. + */ +void mg_mgr_free(struct mg_mgr *); + +/* + * This function performs the actual IO and must be called in a loop + * (an event loop). It returns the current timestamp. + * `milli` is the maximum number of milliseconds to sleep. + * `mg_mgr_poll()` checks all connections for IO readiness. If at least one + * of the connections is IO-ready, `mg_mgr_poll()` triggers the respective + * event handlers and returns. + */ +time_t mg_mgr_poll(struct mg_mgr *, int milli); + +#if MG_ENABLE_BROADCAST +/* + * Passes a message of a given length to all connections. + * + * Must be called from a thread that does NOT call `mg_mgr_poll()`. + * Note that `mg_broadcast()` is the only function + * that can be, and must be, called from a different (non-IO) thread. + * + * `func` callback function will be called by the IO thread for each + * connection. When called, the event will be `MG_EV_POLL`, and a message will + * be passed as the `ev_data` pointer. Maximum message size is capped + * by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes. + */ +void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t); +#endif + +/* + * Iterates over all active connections. + * + * Returns the next connection from the list + * of active connections or `NULL` if there are no more connections. Below + * is the iteration idiom: + * + * ```c + * for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) { + * // Do something with connection `c` + * } + * ``` + */ +struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *); + +/* + * Optional parameters to `mg_add_sock_opt()`. + * + * `flags` is an initial `struct mg_connection::flags` bitmask to set, + * see `MG_F_*` flags definitions. + */ +struct mg_add_sock_opts { + void *user_data; /* Initial value for connection's user_data */ + unsigned int flags; /* Initial connection flags */ + const char **error_string; /* Placeholder for the error string */ + struct mg_iface *iface; /* Interface instance */ +}; + +/* + * Creates a connection, associates it with the given socket and event handler + * and adds it to the manager. + * + * For more options see the `mg_add_sock_opt` variant. + */ +struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t); + +/* + * Creates a connection, associates it with the given socket and event handler + * and adds to the manager. + * + * See the `mg_add_sock_opts` structure for a description of the options. + */ +struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t, + mg_event_handler_t, + struct mg_add_sock_opts); + +/* + * Optional parameters to `mg_bind_opt()`. + * + * `flags` is an initial `struct mg_connection::flags` bitmask to set, + * see `MG_F_*` flags definitions. + */ +struct mg_bind_opts { + void *user_data; /* Initial value for connection's user_data */ + unsigned int flags; /* Extra connection flags */ + const char **error_string; /* Placeholder for the error string */ + struct mg_iface *iface; /* Interface instance */ +#if MG_ENABLE_SSL + /* + * SSL settings. + * + * Server certificate to present to clients or client certificate to + * present to tunnel dispatcher (for tunneled connections). + */ + const char *ssl_cert; + /* Private key corresponding to the certificate. If ssl_cert is set but + * ssl_key is not, ssl_cert is used. */ + const char *ssl_key; + /* CA bundle used to verify client certificates or tunnel dispatchers. */ + const char *ssl_ca_cert; + /* Colon-delimited list of acceptable cipher suites. + * Names depend on the library used, for example: + * + * ECDH-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256 (OpenSSL) + * TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 + * (mbedTLS) + * + * For OpenSSL the list can be obtained by running "openssl ciphers". + * For mbedTLS, names can be found in library/ssl_ciphersuites.c + * If NULL, a reasonable default is used. + */ + const char *ssl_cipher_suites; +#endif +}; + +/* + * Creates a listening connection. + * + * See `mg_bind_opt` for full documentation. + */ +struct mg_connection *mg_bind(struct mg_mgr *, const char *, + mg_event_handler_t); +/* + * Creates a listening connection. + * + * The `address` parameter specifies which address to bind to. It's format is + * the same as for the `mg_connect()` call, where `HOST` part is optional. + * `address` can be just a port number, e.g. `:8000`. To bind to a specific + * interface, an IP address can be specified, e.g. `1.2.3.4:8000`. By default, + * a TCP connection is created. To create UDP connection, prepend `udp://` + * prefix, e.g. `udp://:8000`. To summarize, `address` paramer has following + * format: `[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or + * `udp`. + * + * See the `mg_bind_opts` structure for a description of the optional + * parameters. + * + * Returns a new listening connection or `NULL` on error. + * NOTE: The connection remains owned by the manager, do not free(). + */ +struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, + mg_event_handler_t handler, + struct mg_bind_opts opts); + +/* Optional parameters to `mg_connect_opt()` */ +struct mg_connect_opts { + void *user_data; /* Initial value for connection's user_data */ + unsigned int flags; /* Extra connection flags */ + const char **error_string; /* Placeholder for the error string */ + struct mg_iface *iface; /* Interface instance */ +#if MG_ENABLE_SSL + /* + * SSL settings. + * Client certificate to present to the server. + */ + const char *ssl_cert; + /* + * Private key corresponding to the certificate. + * If ssl_cert is set but ssl_key is not, ssl_cert is used. + */ + const char *ssl_key; + /* + * Verify server certificate using this CA bundle. If set to "*", then SSL + * is enabled but no cert verification is performed. + */ + const char *ssl_ca_cert; + /* Colon-delimited list of acceptable cipher suites. + * Names depend on the library used, for example: + * + * ECDH-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256 (OpenSSL) + * TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 + * (mbedTLS) + * + * For OpenSSL the list can be obtained by running "openssl ciphers". + * For mbedTLS, names can be found in library/ssl_ciphersuites.c + * If NULL, a reasonable default is used. + */ + const char *ssl_cipher_suites; + /* + * Server name verification. If ssl_ca_cert is set and the certificate has + * passed verification, its subject will be verified against this string. + * By default (if ssl_server_name is NULL) hostname part of the address will + * be used. Wildcard matching is supported. A special value of "*" disables + * name verification. + */ + const char *ssl_server_name; +#endif +}; + +/* + * Connects to a remote host. + * + * See `mg_connect_opt()` for full documentation. + */ +struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address, + mg_event_handler_t handler); + +/* + * Connects to a remote host. + * + * The `address` format is `[PROTO://]HOST:PORT`. `PROTO` could be `tcp` or + * `udp`. `HOST` could be an IP address, + * IPv6 address (if Mongoose is compiled with `-DMG_ENABLE_IPV6`) or a host + * name. If `HOST` is a name, Mongoose will resolve it asynchronously. Examples + * of valid addresses: `google.com:80`, `udp://1.2.3.4:53`, `10.0.0.1:443`, + * `[::1]:80` + * + * See the `mg_connect_opts` structure for a description of the optional + * parameters. + * + * Returns a new outbound connection or `NULL` on error. + * + * NOTE: The connection remains owned by the manager, do not free(). + * + * NOTE: To enable IPv6 addresses `-DMG_ENABLE_IPV6` should be specified + * in the compilation flags. + * + * NOTE: The new connection will receive `MG_EV_CONNECT` as its first event + * which will report the connect success status. + * If the asynchronous resolution fails or the `connect()` syscall fails for + * whatever reason (e.g. with `ECONNREFUSED` or `ENETUNREACH`), then + * `MG_EV_CONNECT` event will report failure. Code example below: + * + * ```c + * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + * int connect_status; + * + * switch (ev) { + * case MG_EV_CONNECT: + * connect_status = * (int *) ev_data; + * if (connect_status == 0) { + * // Success + * } else { + * // Error + * printf("connect() error: %s\n", strerror(connect_status)); + * } + * break; + * ... + * } + * } + * + * ... + * mg_connect(mgr, "my_site.com:80", ev_handler); + * ``` + */ +struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, + mg_event_handler_t handler, + struct mg_connect_opts opts); + +#if MG_ENABLE_SSL && MG_NET_IF != MG_NET_IF_SIMPLELINK +/* + * Note: This function is deprecated. Please, use SSL options in + * mg_connect_opt. + * + * Enables SSL for a given connection. + * `cert` is a server certificate file name for a listening connection + * or a client certificate file name for an outgoing connection. + * The certificate files must be in PEM format. The server certificate file + * must contain a certificate, concatenated with a private key, optionally + * concatenated with DH parameters. + * `ca_cert` is a CA certificate or NULL if peer verification is not + * required. + * Return: NULL on success or error message on error. + */ +const char *mg_set_ssl(struct mg_connection *nc, const char *cert, + const char *ca_cert); +#endif + +/* + * Sends data to the connection. + * + * Note that sending functions do not actually push data to the socket. + * They just append data to the output buffer. MG_EV_SEND will be delivered when + * the data has actually been pushed out. + */ +void mg_send(struct mg_connection *, const void *buf, int len); + +/* Enables format string warnings for mg_printf */ +#if defined(__GNUC__) +__attribute__((format(printf, 2, 3))) +#endif +/* don't separate from mg_printf declaration */ + +/* + * Sends `printf`-style formatted data to the connection. + * + * See `mg_send` for more details on send semantics. + */ +int mg_printf(struct mg_connection *, const char *fmt, ...); + +/* Same as `mg_printf()`, but takes `va_list ap` as an argument. */ +int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap); + +/* + * Creates a socket pair. + * `sock_type` can be either `SOCK_STREAM` or `SOCK_DGRAM`. + * Returns 0 on failure and 1 on success. + */ +int mg_socketpair(sock_t[2], int sock_type); + +#if MG_ENABLE_SYNC_RESOLVER +/* + * Convert domain name into IP address. + * + * This is a utility function. If compilation flags have + * `-DMG_ENABLE_GETADDRINFO`, then `getaddrinfo()` call is used for name + * resolution. Otherwise, `gethostbyname()` is used. + * + * CAUTION: this function can block. + * Return 1 on success, 0 on failure. + */ +int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len); +#endif + +/* + * Verify given IP address against the ACL. + * + * `remote_ip` - an IPv4 address to check, in host byte order + * `acl` - a comma separated list of IP subnets: `x.x.x.x/x` or `x.x.x.x`. + * Each subnet is + * prepended by either a - or a + sign. A plus sign means allow, where a + * minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`, + * it means that only that single IP address is denied. + * Subnet masks may vary from 0 to 32, inclusive. The default setting + * is to allow all access. On each request the full list is traversed, + * and the last match wins. Example: + * + * `-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet + * + * To learn more about subnet masks, see this + * link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork]. + * + * Returns -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. + */ +int mg_check_ip_acl(const char *acl, uint32_t remote_ip); + +/* + * Optional parameters for mg_enable_multithreading_opt() + */ +struct mg_multithreading_opts { + int poll_timeout; /* Polling interval */ +}; + +/* + * Enables multi-threaded handling for the given listening connection `nc`. + * For each accepted connection, Mongoose will create a separate thread + * and run an event handler in that thread. Thus, if an event handler is doing + * a blocking call or some long computation, it will not slow down + * other connections. + */ +void mg_enable_multithreading(struct mg_connection *nc); +void mg_enable_multithreading_opt(struct mg_connection *nc, + struct mg_multithreading_opts opts); + +#if MG_ENABLE_JAVASCRIPT +/* + * Enables server-side JavaScript scripting. + * Requires a `-DMG_ENABLE_JAVASCRIPT` compilation flag and V7 engine sources. + * V7 instance must not be destroyed during manager's lifetime. + * Returns a V7 error. + */ +enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7, + const char *init_js_file_name); +#endif + +/* + * Schedules an MG_EV_TIMER event to be delivered at `timestamp` time. + * `timestamp` is UNIX time (the number of seconds since Epoch). It is + * `double` instead of `time_t` to allow for sub-second precision. + * Returns the old timer value. + * + * Example: set the connect timeout to 1.5 seconds: + * + * ``` + * c = mg_connect(&mgr, "cesanta.com", ev_handler); + * mg_set_timer(c, mg_time() + 1.5); + * ... + * + * void ev_handler(struct mg_connection *c, int ev, void *ev_data) { + * switch (ev) { + * case MG_EV_CONNECT: + * mg_set_timer(c, 0); // Clear connect timer + * break; + * case MG_EV_TIMER: + * log("Connect timeout"); + * c->flags |= MG_F_CLOSE_IMMEDIATELY; + * break; + * ``` + */ +double mg_set_timer(struct mg_connection *c, double timestamp); + +/* + * A sub-second precision version of time(). + */ +double mg_time(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_MONGOOSE_SRC_NET_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/uri.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * === URI + */ + +#ifndef CS_MONGOOSE_SRC_URI_H_ +#define CS_MONGOOSE_SRC_URI_H_ + +/* Amalgamated: #include "mongoose/src/net.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Parses an URI and fills string chunks with locations of the respective + * uri components within the input uri string. NULL pointers will be + * ignored. + * + * General syntax: + * + * [scheme://[user_info@]]host[:port][/path][?query][#fragment] + * + * Example: + * + * foo.com:80 + * tcp://foo.com:1234 + * http://foo.com:80/bar?baz=1 + * https://user:pw@foo.com:443/blah + * + * `path` will include the leading slash. `query` won't include the leading `?`. + * `host` can contain embedded colons if surrounded by square brackets in order + * to support IPv6 literal addresses. + * + * + * Returns 0 on success, -1 on error. + */ +int mg_parse_uri(struct mg_str uri, struct mg_str *scheme, + struct mg_str *user_info, struct mg_str *host, + unsigned int *port, struct mg_str *path, struct mg_str *query, + struct mg_str *fragment); + +int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* CS_MONGOOSE_SRC_URI_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/util.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * === Utility API + */ + +#ifndef CS_MONGOOSE_SRC_UTIL_H_ +#define CS_MONGOOSE_SRC_UTIL_H_ + +#include + +/* Amalgamated: #include "mongoose/src/common.h" */ +/* Amalgamated: #include "mongoose/src/net_if.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MAX_PATH_SIZE +#define MAX_PATH_SIZE 500 +#endif + +/* + * Fetches substring from input string `s`, `end` into `v`. + * Skips initial delimiter characters. Records first non-delimiter character + * at the beginning of substring `v`. Then scans the rest of the string + * until a delimiter character or end-of-string is found. + * `delimiters` is a 0-terminated string containing delimiter characters. + * Either one of `delimiters` or `end_string` terminates the search. + * Returns an `s` pointer, advanced forward where parsing has stopped. + */ +const char *mg_skip(const char *s, const char *end_string, + const char *delimiters, struct mg_str *v); + +/* + * Decodes base64-encoded string `s`, `len` into the destination `dst`. + * The destination has to have enough space to hold the decoded buffer. + * Decoding stops either when all strings have been decoded or invalid an + * character appeared. + * Destination is '\0'-terminated. + * Returns the number of decoded characters. On success, that should be equal + * to `len`. On error (invalid character) the return value is smaller then + * `len`. + */ +int mg_base64_decode(const unsigned char *s, int len, char *dst); + +/* + * Base64-encode chunk of memory `src`, `src_len` into the destination `dst`. + * Destination has to have enough space to hold encoded buffer. + * Destination is '\0'-terminated. + */ +void mg_base64_encode(const unsigned char *src, int src_len, char *dst); + +#if MG_ENABLE_FILESYSTEM +/* + * Performs a 64-bit `stat()` call against a given file. + * + * `path` should be UTF8 encoded. + * + * Return value is the same as for `stat()` syscall. + */ +int mg_stat(const char *path, cs_stat_t *st); + +/* + * Opens the given file and returns a file stream. + * + * `path` and `mode` should be UTF8 encoded. + * + * Return value is the same as for the `fopen()` call. + */ +FILE *mg_fopen(const char *path, const char *mode); + +/* + * Opens the given file and returns a file stream. + * + * `path` should be UTF8 encoded. + * + * Return value is the same as for the `open()` syscall. + */ +int mg_open(const char *path, int flag, int mode); +#endif /* MG_ENABLE_FILESYSTEM */ + +#if MG_ENABLE_THREADS +/* + * Starts a new detached thread. + * Arguments and semantics are the same as pthead's `pthread_create()`. + * `thread_func` is a thread function, `thread_func_param` is a parameter + * that is passed to the thread function. + */ +void *mg_start_thread(void *(*thread_func)(void *), void *thread_func_param); +#endif + +void mg_set_close_on_exec(sock_t); + +#define MG_SOCK_STRINGIFY_IP 1 +#define MG_SOCK_STRINGIFY_PORT 2 +#define MG_SOCK_STRINGIFY_REMOTE 4 +/* + * Converts a connection's local or remote address into string. + * + * The `flags` parameter is a bit mask that controls the behaviour, + * see `MG_SOCK_STRINGIFY_*` definitions. + * + * - MG_SOCK_STRINGIFY_IP - print IP address + * - MG_SOCK_STRINGIFY_PORT - print port number + * - MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address + * + * If both port number and IP address are printed, they are separated by `:`. + * If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported. + */ +void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len, + int flags); +#if MG_NET_IF == MG_NET_IF_SOCKET +/* Legacy interface. */ +void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags); +#endif + +/* + * Convert the socket's address into string. + * + * `flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT. + */ +void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len, + int flags); + +#if MG_ENABLE_HEXDUMP +/* + * Generates a human-readable hexdump of memory chunk. + * + * Takes a memory buffer `buf` of length `len` and creates a hex dump of that + * buffer in `dst`. The generated output is a-la hexdump(1). + * Returns the length of generated string, excluding terminating `\0`. If + * returned length is bigger than `dst_len`, the overflow bytes are discarded. + */ +int mg_hexdump(const void *buf, int len, char *dst, int dst_len); + +/* + * Generates human-readable hexdump of the data sent or received by the + * connection. `path` is a file name where hexdump should be written. + * `num_bytes` is a number of bytes sent/received. `ev` is one of the `MG_*` + * events sent to an event handler. This function is supposed to be called from + * the event handler. + */ +void mg_hexdump_connection(struct mg_connection *nc, const char *path, + const void *buf, int num_bytes, int ev); +#endif + +/* + * Returns true if target platform is big endian. + */ +int mg_is_big_endian(void); + +/* + * A helper function for traversing a comma separated list of values. + * It returns a list pointer shifted to the next value or NULL if the end + * of the list found. + * The value is stored in a val vector. If the value has a form "x=y", then + * eq_val vector is initialised to point to the "y" part, and val vector length + * is adjusted to point only to "x". + * If the list is just a comma separated list of entries, like "aa,bb,cc" then + * `eq_val` will contain zero-length string. + * + * The purpose of this function is to parse comma separated string without + * any copying/memory allocation. + */ +const char *mg_next_comma_list_entry(const char *list, struct mg_str *val, + struct mg_str *eq_val); + +/* + * Matches 0-terminated string (mg_match_prefix) or string with given length + * mg_match_prefix_n against a glob pattern. + * + * Match is case-insensitive. Returns number of bytes matched, or -1 if no + * match. + */ +int mg_match_prefix(const char *pattern, int pattern_len, const char *str); +int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str); + +/* + * Use with cs_base64_init/update/finish in order to write out base64 in chunks. + */ +void mg_mbuf_append_base64_putc(char ch, void *user_data); + +/* + * Encode `len` bytes starting at `data` as base64 and append them to an mbuf. + */ +void mg_mbuf_append_base64(struct mbuf *mbuf, const void *data, size_t len); + +/* + * Generate a Basic Auth header and appends it to buf. + * If pass is NULL, then user is expected to contain the credentials pair + * already encoded as `user:pass`. + */ +void mg_basic_auth_header(const char *user, const char *pass, struct mbuf *buf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* CS_MONGOOSE_SRC_UTIL_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * === Common API reference + */ + +#ifndef CS_MONGOOSE_SRC_HTTP_H_ +#define CS_MONGOOSE_SRC_HTTP_H_ + +#if MG_ENABLE_HTTP + +/* Amalgamated: #include "mongoose/src/net.h" */ +/* Amalgamated: #include "common/mg_str.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MG_MAX_HTTP_HEADERS +#define MG_MAX_HTTP_HEADERS 20 +#endif + +#ifndef MG_MAX_HTTP_REQUEST_SIZE +#define MG_MAX_HTTP_REQUEST_SIZE 1024 +#endif + +#ifndef MG_MAX_PATH +#ifdef PATH_MAX +#define MG_MAX_PATH PATH_MAX +#else +#define MG_MAX_PATH 256 +#endif +#endif + +#ifndef MG_MAX_HTTP_SEND_MBUF +#define MG_MAX_HTTP_SEND_MBUF 1024 +#endif + +#ifndef MG_CGI_ENVIRONMENT_SIZE +#define MG_CGI_ENVIRONMENT_SIZE 8192 +#endif + +/* HTTP message */ +struct http_message { + struct mg_str message; /* Whole message: request line + headers + body */ + + /* HTTP Request line (or HTTP response line) */ + struct mg_str method; /* "GET" */ + struct mg_str uri; /* "/my_file.html" */ + struct mg_str proto; /* "HTTP/1.1" -- for both request and response */ + + /* For responses, code and response status message are set */ + int resp_code; + struct mg_str resp_status_msg; + + /* + * Query-string part of the URI. For example, for HTTP request + * GET /foo/bar?param1=val1¶m2=val2 + * | uri | query_string | + * + * Note that question mark character doesn't belong neither to the uri, + * nor to the query_string + */ + struct mg_str query_string; + + /* Headers */ + struct mg_str header_names[MG_MAX_HTTP_HEADERS]; + struct mg_str header_values[MG_MAX_HTTP_HEADERS]; + + /* Message body */ + struct mg_str body; /* Zero-length for requests with no body */ +}; + +#if MG_ENABLE_HTTP_WEBSOCKET +/* WebSocket message */ +struct websocket_message { + unsigned char *data; + size_t size; + unsigned char flags; +}; +#endif + +/* HTTP multipart part */ +struct mg_http_multipart_part { + const char *file_name; + const char *var_name; + struct mg_str data; + int status; /* <0 on error */ + void *user_data; +}; + +/* SSI call context */ +struct mg_ssi_call_ctx { + struct http_message *req; /* The request being processed. */ + struct mg_str file; /* Filesystem path of the file being processed. */ + struct mg_str arg; /* The argument passed to the tag: . */ +}; + +/* HTTP and websocket events. void *ev_data is described in a comment. */ +#define MG_EV_HTTP_REQUEST 100 /* struct http_message * */ +#define MG_EV_HTTP_REPLY 101 /* struct http_message * */ +#define MG_EV_HTTP_CHUNK 102 /* struct http_message * */ +#define MG_EV_SSI_CALL 105 /* char * */ +#define MG_EV_SSI_CALL_CTX 106 /* struct mg_ssi_call_ctx * */ + +#if MG_ENABLE_HTTP_WEBSOCKET +#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* struct http_message * */ +#define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112 /* NULL */ +#define MG_EV_WEBSOCKET_FRAME 113 /* struct websocket_message * */ +#define MG_EV_WEBSOCKET_CONTROL_FRAME 114 /* struct websocket_message * */ +#endif + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART +#define MG_EV_HTTP_MULTIPART_REQUEST 121 /* struct http_message */ +#define MG_EV_HTTP_PART_BEGIN 122 /* struct mg_http_multipart_part */ +#define MG_EV_HTTP_PART_DATA 123 /* struct mg_http_multipart_part */ +#define MG_EV_HTTP_PART_END 124 /* struct mg_http_multipart_part */ +/* struct mg_http_multipart_part */ +#define MG_EV_HTTP_MULTIPART_REQUEST_END 125 +#endif + +/* + * Attaches a built-in HTTP event handler to the given connection. + * The user-defined event handler will receive following extra events: + * + * - MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request + * is passed as + * `struct http_message` through the handler's `void *ev_data` pointer. + * - MG_EV_HTTP_REPLY: The HTTP reply has arrived. The parsed HTTP reply is + * passed as `struct http_message` through the handler's `void *ev_data` + * pointer. + * - MG_EV_HTTP_CHUNK: The HTTP chunked-encoding chunk has arrived. + * The parsed HTTP reply is passed as `struct http_message` through the + * handler's `void *ev_data` pointer. `http_message::body` would contain + * incomplete, reassembled HTTP body. + * It will grow with every new chunk that arrives, and it can + * potentially consume a lot of memory. An event handler may process + * the body as chunks are coming, and signal Mongoose to delete processed + * body by setting `MG_F_DELETE_CHUNK` in `mg_connection::flags`. When + * the last zero chunk is received, + * Mongoose sends `MG_EV_HTTP_REPLY` event with + * full reassembled body (if handler did not signal to delete chunks) or + * with empty body (if handler did signal to delete chunks). + * - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket + * handshake request. `ev_data` contains parsed HTTP request. + * - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket + * handshake. `ev_data` is `NULL`. + * - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is + * `struct websocket_message *` + * + * When compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART, Mongoose parses + * multipart requests and splits them into separate events: + * - MG_EV_HTTP_MULTIPART_REQUEST: Start of the request. + * This event is sent before body is parsed. After this, the user + * should expect a sequence of PART_BEGIN/DATA/END requests. + * This is also the last time when headers and other request fields are + * accessible. + * - MG_EV_HTTP_PART_BEGIN: Start of a part of a multipart message. + * Argument: mg_http_multipart_part with var_name and file_name set + * (if present). No data is passed in this message. + * - MG_EV_HTTP_PART_DATA: new portion of data from the multipart message. + * Argument: mg_http_multipart_part. var_name and file_name are preserved, + * data is available in mg_http_multipart_part.data. + * - MG_EV_HTTP_PART_END: End of the current part. var_name, file_name are + * the same, no data in the message. If status is 0, then the part is + * properly terminated with a boundary, status < 0 means that connection + * was terminated. + * - MG_EV_HTTP_MULTIPART_REQUEST_END: End of the multipart request. + * Argument: mg_http_multipart_part, var_name and file_name are NULL, + * status = 0 means request was properly closed, < 0 means connection + * was terminated (note: in this case both PART_END and REQUEST_END are + * delivered). + */ +void mg_set_protocol_http_websocket(struct mg_connection *nc); + +#if MG_ENABLE_HTTP_WEBSOCKET +/* + * Send websocket handshake to the server. + * + * `nc` must be a valid connection, connected to a server. `uri` is an URI + * to fetch, extra_headers` is extra HTTP headers to send or `NULL`. + * + * This function is intended to be used by websocket client. + * + * Note that the Host header is mandatory in HTTP/1.1 and must be + * included in `extra_headers`. `mg_send_websocket_handshake2` offers + * a better API for that. + * + * Deprecated in favour of `mg_send_websocket_handshake2` + */ +void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri, + const char *extra_headers); + +/* + * Send websocket handshake to the server. + * + * `nc` must be a valid connection, connected to a server. `uri` is an URI + * to fetch, `host` goes into the `Host` header, `protocol` goes into the + * `Sec-WebSocket-Proto` header (NULL to omit), extra_headers` is extra HTTP + * headers to send or `NULL`. + * + * This function is intended to be used by websocket client. + */ +void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path, + const char *host, const char *protocol, + const char *extra_headers); + +/* Like mg_send_websocket_handshake2 but also passes basic auth header */ +void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path, + const char *host, const char *protocol, + const char *extra_headers, const char *user, + const char *pass); +/* + * Helper function that creates an outbound WebSocket connection. + * + * `url` is a URL to connect to. It must be properly URL-encoded, e.g. have + * no spaces, etc. By default, `mg_connect_ws()` sends Connection and + * Host headers. `extra_headers` is an extra HTTP header to send, e.g. + * `"User-Agent: my-app\r\n"`. + * If `protocol` is not NULL, then a `Sec-WebSocket-Protocol` header is sent. + * + * Examples: + * + * ```c + * nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL, + * NULL); + * nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL, + * NULL); + * nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com", + * "clubby.cesanta.com", NULL); + * ``` + */ +struct mg_connection *mg_connect_ws(struct mg_mgr *mgr, + mg_event_handler_t event_handler, + const char *url, const char *protocol, + const char *extra_headers); + +/* + * Helper function that creates an outbound WebSocket connection + * + * Mostly identical to `mg_connect_ws`, but allows to provide extra parameters + * (for example, SSL parameters) + */ +struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr, + mg_event_handler_t ev_handler, + struct mg_connect_opts opts, + const char *url, const char *protocol, + const char *extra_headers); + +/* + * Send WebSocket frame to the remote end. + * + * `op_and_flags` specifies the frame's type. It's one of: + * + * - WEBSOCKET_OP_CONTINUE + * - WEBSOCKET_OP_TEXT + * - WEBSOCKET_OP_BINARY + * - WEBSOCKET_OP_CLOSE + * - WEBSOCKET_OP_PING + * - WEBSOCKET_OP_PONG + * + * Orred with one of the flags: + * + * - WEBSOCKET_DONT_FIN: Don't set the FIN flag on the frame to be sent. + * + * `data` and `data_len` contain frame data. + */ +void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags, + const void *data, size_t data_len); + +/* + * Sends multiple websocket frames. + * + * Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers. + */ +void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags, + const struct mg_str *strings, int num_strings); + +/* + * Sends WebSocket frame to the remote end. + * + * Like `mg_send_websocket_frame()`, but allows to create formatted messages + * with `printf()`-like semantics. + */ +void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags, + const char *fmt, ...); + +/* Websocket opcodes, from http://tools.ietf.org/html/rfc6455 */ +#define WEBSOCKET_OP_CONTINUE 0 +#define WEBSOCKET_OP_TEXT 1 +#define WEBSOCKET_OP_BINARY 2 +#define WEBSOCKET_OP_CLOSE 8 +#define WEBSOCKET_OP_PING 9 +#define WEBSOCKET_OP_PONG 10 + +/* + * If set causes the FIN flag to not be set on outbound + * frames. This enables sending multiple fragments of a single + * logical message. + * + * The WebSocket protocol mandates that if the FIN flag of a data + * frame is not set, the next frame must be a WEBSOCKET_OP_CONTINUE. + * The last frame must have the FIN bit set. + * + * Note that mongoose will automatically defragment incoming messages, + * so this flag is used only on outbound messages. + */ +#define WEBSOCKET_DONT_FIN 0x100 + +#endif /* MG_ENABLE_HTTP_WEBSOCKET */ + +/* + * Decodes a URL-encoded string. + * + * Source string is specified by (`src`, `src_len`), and destination is + * (`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then + * `+` character is decoded as a blank space character. This function + * guarantees to NUL-terminate the destination. If destination is too small, + * then the source string is partially decoded and `-1` is returned. Otherwise, + * a length of the decoded string is returned, not counting final NUL. + */ +int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, + int is_form_url_encoded); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_HTTP */ + +#endif /* CS_MONGOOSE_SRC_HTTP_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http_server.h" +#endif +/* + * === Server API reference + */ + +#ifndef CS_MONGOOSE_SRC_HTTP_SERVER_H_ +#define CS_MONGOOSE_SRC_HTTP_SERVER_H_ + +#if MG_ENABLE_HTTP + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Parses a HTTP message. + * + * `is_req` should be set to 1 if parsing a request, 0 if reply. + * + * Returns the number of bytes parsed. If HTTP message is + * incomplete `0` is returned. On parse error, a negative number is returned. + */ +int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req); + +/* + * Searches and returns the header `name` in parsed HTTP message `hm`. + * If header is not found, NULL is returned. Example: + * + * struct mg_str *host_hdr = mg_get_http_header(hm, "Host"); + */ +struct mg_str *mg_get_http_header(struct http_message *hm, const char *name); + +/* + * Parses the HTTP header `hdr`. Finds variable `var_name` and stores its value + * in the buffer `buf`, `buf_size`. Returns 0 if variable not found, non-zero + * otherwise. + * + * This function is supposed to parse cookies, authentication headers, etc. + * Example (error handling omitted): + * + * char user[20]; + * struct mg_str *hdr = mg_get_http_header(hm, "Authorization"); + * mg_http_parse_header(hdr, "username", user, sizeof(user)); + * + * Returns the length of the variable's value. If buffer is not large enough, + * or variable not found, 0 is returned. + */ +int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf, + size_t buf_size); + +/* + * Gets and parses the Authorization: Basic header + * Returns -1 if no Authorization header is found, or if + * mg_parse_http_basic_auth + * fails parsing the resulting header. + */ +int mg_get_http_basic_auth(struct http_message *hm, char *user, size_t user_len, + char *pass, size_t pass_len); + +/* + * Parses the Authorization: Basic header + * Returns -1 iif the authorization type is not "Basic" or any other error such + * as incorrectly encoded base64 user password pair. + */ +int mg_parse_http_basic_auth(struct mg_str *hdr, char *user, size_t user_len, + char *pass, size_t pass_len); + +/* + * Parses the buffer `buf`, `buf_len` that contains multipart form data chunks. + * Stores the chunk name in a `var_name`, `var_name_len` buffer. + * If a chunk is an uploaded file, then `file_name`, `file_name_len` is + * filled with an uploaded file name. `chunk`, `chunk_len` + * points to the chunk data. + * + * Return: number of bytes to skip to the next chunk or 0 if there are + * no more chunks. + * + * Usage example: + * + * ```c + * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + * switch(ev) { + * case MG_EV_HTTP_REQUEST: { + * struct http_message *hm = (struct http_message *) ev_data; + * char var_name[100], file_name[100]; + * const char *chunk; + * size_t chunk_len, n1, n2; + * + * n1 = n2 = 0; + * while ((n2 = mg_parse_multipart(hm->body.p + n1, + * hm->body.len - n1, + * var_name, sizeof(var_name), + * file_name, sizeof(file_name), + * &chunk, &chunk_len)) > 0) { + * printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n", + * var_name, file_name, (int) chunk_len, + * (int) chunk_len, chunk); + * n1 += n2; + * } + * } + * break; + * ``` + */ +size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, + size_t var_name_len, char *file_name, + size_t file_name_len, const char **chunk, + size_t *chunk_len); + +/* + * Fetches a HTTP form variable. + * + * Fetches a variable `name` from a `buf` into a buffer specified by `dst`, + * `dst_len`. The destination is always zero-terminated. Returns the length of + * a fetched variable. If not found, 0 is returned. `buf` must be valid + * url-encoded buffer. If destination is too small, `-1` is returned. + */ +int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst, + size_t dst_len); + +#if MG_ENABLE_FILESYSTEM +/* + * This structure defines how `mg_serve_http()` works. + * Best practice is to set only required settings, and leave the rest as NULL. + */ +struct mg_serve_http_opts { + /* Path to web root directory */ + const char *document_root; + + /* List of index files. Default is "" */ + const char *index_files; + + /* + * Leave as NULL to disable authentication. + * To enable directory protection with authentication, set this to ".htpasswd" + * Then, creating ".htpasswd" file in any directory automatically protects + * it with digest authentication. + * Use `mongoose` web server binary, or `htdigest` Apache utility to + * create/manipulate passwords file. + * Make sure `auth_domain` is set to a valid domain name. + */ + const char *per_directory_auth_file; + + /* Authorization domain (domain name of this web server) */ + const char *auth_domain; + + /* + * Leave as NULL to disable authentication. + * Normally, only selected directories in the document root are protected. + * If absolutely every access to the web server needs to be authenticated, + * regardless of the URI, set this option to the path to the passwords file. + * Format of that file is the same as ".htpasswd" file. Make sure that file + * is located outside document root to prevent people fetching it. + */ + const char *global_auth_file; + + /* Set to "no" to disable directory listing. Enabled by default. */ + const char *enable_directory_listing; + + /* + * SSI files pattern. If not set, "**.shtml$|**.shtm$" is used. + * + * All files that match ssi_pattern are treated as SSI. + * + * Server Side Includes (SSI) is a simple interpreted server-side scripting + * language which is most commonly used to include the contents of a file + * into a web page. It can be useful when it is desirable to include a common + * piece of code throughout a website, for example, headers and footers. + * + * In order for a webpage to recognize an SSI-enabled HTML file, the + * filename should end with a special extension, by default the extension + * should be either .shtml or .shtm + * + * Unknown SSI directives are silently ignored by Mongoose. Currently, + * the following SSI directives are supported: + * <!--#include FILE_TO_INCLUDE --> + * <!--#exec "COMMAND_TO_EXECUTE" --> + * <!--#call COMMAND --> + * + * Note that <!--#include ...> directive supports three path + *specifications: + * + * <!--#include virtual="path" --> Path is relative to web server root + * <!--#include abspath="path" --> Path is absolute or relative to the + * web server working dir + * <!--#include file="path" -->, Path is relative to current document + * <!--#include "path" --> + * + * The include directive may be used to include the contents of a file or + * the result of running a CGI script. + * + * The exec directive is used to execute + * a command on a server, and show command's output. Example: + * + * <!--#exec "ls -l" --> + * + * The call directive is a way to invoke a C handler from the HTML page. + * On each occurence of <!--#call COMMAND OPTIONAL_PARAMS> directive, + * Mongoose calls a registered event handler with MG_EV_SSI_CALL event, + * and event parameter will point to the COMMAND OPTIONAL_PARAMS string. + * An event handler can output any text, for example by calling + * `mg_printf()`. This is a flexible way of generating a web page on + * server side by calling a C event handler. Example: + * + * <!--#call foo --> ... <!--#call bar --> + * + * In the event handler: + * case MG_EV_SSI_CALL: { + * const char *param = (const char *) ev_data; + * if (strcmp(param, "foo") == 0) { + * mg_printf(c, "hello from foo"); + * } else if (strcmp(param, "bar") == 0) { + * mg_printf(c, "hello from bar"); + * } + * break; + * } + */ + const char *ssi_pattern; + + /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */ + const char *ip_acl; + +#if MG_ENABLE_HTTP_URL_REWRITES + /* URL rewrites. + * + * Comma-separated list of `uri_pattern=url_file_or_directory_path` rewrites. + * When HTTP request is received, Mongoose constructs a file name from the + * requested URI by combining `document_root` and the URI. However, if the + * rewrite option is used and `uri_pattern` matches requested URI, then + * `document_root` is ignored. Instead, `url_file_or_directory_path` is used, + * which should be a full path name or a path relative to the web server's + * current working directory. It can also be an URI (http:// or https://) + * in which case mongoose will behave as a reverse proxy for that destination. + * + * Note that `uri_pattern`, as all Mongoose patterns, is a prefix pattern. + * + * If uri_pattern starts with `@` symbol, then Mongoose compares it with the + * HOST header of the request. If they are equal, Mongoose sets document root + * to `file_or_directory_path`, implementing virtual hosts support. + * Example: `@foo.com=/document/root/for/foo.com` + * + * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with + * the listening port. If they match, then Mongoose issues a 301 redirect. + * For example, to redirect all HTTP requests to the + * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is + * automatically appended to the redirect location. + */ + const char *url_rewrites; +#endif + + /* DAV document root. If NULL, DAV requests are going to fail. */ + const char *dav_document_root; + + /* + * DAV passwords file. If NULL, DAV requests are going to fail. + * If passwords file is set to "-", then DAV auth is disabled. + */ + const char *dav_auth_file; + + /* Glob pattern for the files to hide. */ + const char *hidden_file_pattern; + + /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */ + const char *cgi_file_pattern; + + /* If not NULL, ignore CGI script hashbang and use this interpreter */ + const char *cgi_interpreter; + + /* + * Comma-separated list of Content-Type overrides for path suffixes, e.g. + * ".txt=text/plain; charset=utf-8,.c=text/plain" + */ + const char *custom_mime_types; + + /* + * Extra HTTP headers to add to each server response. + * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *". + */ + const char *extra_headers; +}; + +/* + * Serves given HTTP request according to the `options`. + * + * Example code snippet: + * + * ```c + * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + * struct http_message *hm = (struct http_message *) ev_data; + * struct mg_serve_http_opts opts = { .document_root = "/var/www" }; // C99 + * + * switch (ev) { + * case MG_EV_HTTP_REQUEST: + * mg_serve_http(nc, hm, opts); + * break; + * default: + * break; + * } + * } + * ``` + */ +void mg_serve_http(struct mg_connection *nc, struct http_message *hm, + struct mg_serve_http_opts opts); + +/* + * Serves a specific file with a given MIME type and optional extra headers. + * + * Example code snippet: + * + * ```c + * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + * switch (ev) { + * case MG_EV_HTTP_REQUEST: { + * struct http_message *hm = (struct http_message *) ev_data; + * mg_http_serve_file(nc, hm, "file.txt", + * mg_mk_str("text/plain"), mg_mk_str("")); + * break; + * } + * ... + * } + * } + * ``` + */ +void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm, + const char *path, const struct mg_str mime_type, + const struct mg_str extra_headers); + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART + +/* Callback prototype for `mg_file_upload_handler()`. */ +typedef struct mg_str (*mg_fu_fname_fn)(struct mg_connection *nc, + struct mg_str fname); + +/* + * File upload handler. + * This handler can be used to implement file uploads with minimum code. + * This handler will process MG_EV_HTTP_PART_* events and store file data into + * a local file. + * `local_name_fn` will be invoked with whatever name was provided by the client + * and will expect the name of the local file to open. A return value of NULL + * will abort file upload (client will get a "403 Forbidden" response). If + * non-null, the returned string must be heap-allocated and will be freed by + * the caller. + * Exception: it is ok to return the same string verbatim. + * + * Example: + * + * ```c + * struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) { + * // Just return the same filename. Do not actually do this except in test! + * // fname is user-controlled and needs to be sanitized. + * return fname; + * } + * void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + * switch (ev) { + * ... + * case MG_EV_HTTP_PART_BEGIN: + * case MG_EV_HTTP_PART_DATA: + * case MG_EV_HTTP_PART_END: + * mg_file_upload_handler(nc, ev, ev_data, upload_fname); + * break; + * } + * } + * ``` + */ +void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data, + mg_fu_fname_fn local_name_fn); +#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */ +#endif /* MG_ENABLE_FILESYSTEM */ + +/* + * Registers a callback for a specified http endpoint + * Note: if callback is registered it is called instead of the + * callback provided in mg_bind + * + * Example code snippet: + * + * ```c + * static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) { + * (void) ev; (void) ev_data; + * mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]"); + * nc->flags |= MG_F_SEND_AND_CLOSE; + * } + * + * static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) { + * (void) ev; (void) ev_data; + * mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]"); + * nc->flags |= MG_F_SEND_AND_CLOSE; + * } + * + * void init() { + * nc = mg_bind(&mgr, local_addr, cb1); + * mg_register_http_endpoint(nc, "/hello1", handle_hello1); + * mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2); + * } + * ``` + */ +void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, + mg_event_handler_t handler); + +/* + * Authenticates a HTTP request against an opened password file. + * Returns 1 if authenticated, 0 otherwise. + */ +int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain, + FILE *fp); + +/* + * Sends buffer `buf` of size `len` to the client using chunked HTTP encoding. + * This function sends the buffer size as hex number + newline first, then + * the buffer itself, then the newline. For example, + * `mg_send_http_chunk(nc, "foo", 3)` whill append the `3\r\nfoo\r\n` string + * to the `nc->send_mbuf` output IO buffer. + * + * NOTE: The HTTP header "Transfer-Encoding: chunked" should be sent prior to + * using this function. + * + * NOTE: do not forget to send an empty chunk at the end of the response, + * to tell the client that everything was sent. Example: + * + * ``` + * mg_printf_http_chunk(nc, "%s", "my response!"); + * mg_send_http_chunk(nc, "", 0); // Tell the client we're finished + * ``` + */ +void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len); + +/* + * Sends a printf-formatted HTTP chunk. + * Functionality is similar to `mg_send_http_chunk()`. + */ +void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...); + +/* + * Sends the response status line. + * If `extra_headers` is not NULL, then `extra_headers` are also sent + * after the reponse line. `extra_headers` must NOT end end with new line. + * Example: + * + * mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *"); + * + * Will result in: + * + * HTTP/1.1 200 OK\r\n + * Access-Control-Allow-Origin: *\r\n + */ +void mg_send_response_line(struct mg_connection *nc, int status_code, + const char *extra_headers); + +/* + * Sends an error response. If reason is NULL, the message will be inferred + * from the error code (if supported). + */ +void mg_http_send_error(struct mg_connection *nc, int code, const char *reason); + +/* + * Sends a redirect response. + * `status_code` should be either 301 or 302 and `location` point to the + * new location. + * If `extra_headers` is not empty, then `extra_headers` are also sent + * after the reponse line. `extra_headers` must NOT end end with new line. + * + * Example: + * + * mg_http_send_redirect(nc, 302, mg_mk_str("/login"), mg_mk_str(NULL)); + */ +void mg_http_send_redirect(struct mg_connection *nc, int status_code, + const struct mg_str location, + const struct mg_str extra_headers); + +/* + * Sends the response line and headers. + * This function sends the response line with the `status_code`, and + * automatically + * sends one header: either "Content-Length" or "Transfer-Encoding". + * If `content_length` is negative, then "Transfer-Encoding: chunked" header + * is sent, otherwise, "Content-Length" header is sent. + * + * NOTE: If `Transfer-Encoding` is `chunked`, then message body must be sent + * using `mg_send_http_chunk()` or `mg_printf_http_chunk()` functions. + * Otherwise, `mg_send()` or `mg_printf()` must be used. + * Extra headers could be set through `extra_headers`. Note `extra_headers` + * must NOT be terminated by a new line. + */ +void mg_send_head(struct mg_connection *n, int status_code, + int64_t content_length, const char *extra_headers); + +/* + * Sends a printf-formatted HTTP chunk, escaping HTML tags. + */ +void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...); + +#if MG_ENABLE_HTTP_URL_REWRITES +/* + * Proxies a given request to a given upstream http server. The path prefix + * in `mount` will be stripped of the path requested to the upstream server, + * e.g. if mount is /api and upstream is http://localhost:8001/foo + * then an incoming request to /api/bar will cause a request to + * http://localhost:8001/foo/bar + * + * EXPERIMENTAL API. Please use http_serve_http + url_rewrites if a static + * mapping is good enough. + */ +void mg_http_reverse_proxy(struct mg_connection *nc, + const struct http_message *hm, struct mg_str mount, + struct mg_str upstream); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_HTTP */ + +#endif /* CS_MONGOOSE_SRC_HTTP_SERVER_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http_client.h" +#endif +/* + * === Client API reference + */ + +#ifndef CS_MONGOOSE_SRC_HTTP_CLIENT_H_ +#define CS_MONGOOSE_SRC_HTTP_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Helper function that creates an outbound HTTP connection. + * + * `url` is the URL to fetch. It must be properly URL-encoded, e.g. have + * no spaces, etc. By default, `mg_connect_http()` sends the Connection and + * Host headers. `extra_headers` is an extra HTTP header to send, e.g. + * `"User-Agent: my-app\r\n"`. + * If `post_data` is NULL, then a GET request is created. Otherwise, a POST + * request is created with the specified POST data. Note that if the data being + * posted is a form submission, the `Content-Type` header should be set + * accordingly (see example below). + * + * Examples: + * + * ```c + * nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL, + * NULL); + * nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL); + * nc3 = mg_connect_http( + * mgr, ev_handler_1, "my_server:8000/form_submit/", + * "Content-Type: application/x-www-form-urlencoded\r\n", + * "var_1=value_1&var_2=value_2"); + * ``` + */ +struct mg_connection *mg_connect_http(struct mg_mgr *mgr, + mg_event_handler_t event_handler, + const char *url, + const char *extra_headers, + const char *post_data); + +/* + * Helper function that creates an outbound HTTP connection. + * + * Mostly identical to mg_connect_http, but allows you to provide extra + *parameters + * (for example, SSL parameters) + */ +struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr, + mg_event_handler_t ev_handler, + struct mg_connect_opts opts, + const char *url, + const char *extra_headers, + const char *post_data); + +/* Creates digest authentication header for a client request. */ +int mg_http_create_digest_auth_header(char *buf, size_t buf_len, + const char *method, const char *uri, + const char *auth_domain, const char *user, + const char *passwd); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* CS_MONGOOSE_SRC_HTTP_CLIENT_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/mqtt.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +/* + * === MQTT API reference + */ + +#ifndef CS_MONGOOSE_SRC_MQTT_H_ +#define CS_MONGOOSE_SRC_MQTT_H_ + +/* Amalgamated: #include "mongoose/src/net.h" */ + +struct mg_mqtt_message { + int cmd; + int qos; + struct mg_str topic; + struct mg_str payload; + + uint8_t connack_ret_code; /* connack */ + uint16_t message_id; /* puback */ + + /* connect */ + uint8_t protocol_version; + uint8_t connect_flags; + uint16_t keep_alive_timer; + struct mg_str protocol_name; + struct mg_str client_id; + struct mg_str will_topic; + struct mg_str will_message; + struct mg_str user_name; + struct mg_str password; +}; + +struct mg_mqtt_topic_expression { + const char *topic; + uint8_t qos; +}; + +struct mg_send_mqtt_handshake_opts { + unsigned char flags; /* connection flags */ + uint16_t keep_alive; + const char *will_topic; + const char *will_message; + const char *user_name; + const char *password; +}; + +/* mg_mqtt_proto_data should be in header to allow external access to it */ +struct mg_mqtt_proto_data { + uint16_t keep_alive; +}; + +/* Message types */ +#define MG_MQTT_CMD_CONNECT 1 +#define MG_MQTT_CMD_CONNACK 2 +#define MG_MQTT_CMD_PUBLISH 3 +#define MG_MQTT_CMD_PUBACK 4 +#define MG_MQTT_CMD_PUBREC 5 +#define MG_MQTT_CMD_PUBREL 6 +#define MG_MQTT_CMD_PUBCOMP 7 +#define MG_MQTT_CMD_SUBSCRIBE 8 +#define MG_MQTT_CMD_SUBACK 9 +#define MG_MQTT_CMD_UNSUBSCRIBE 10 +#define MG_MQTT_CMD_UNSUBACK 11 +#define MG_MQTT_CMD_PINGREQ 12 +#define MG_MQTT_CMD_PINGRESP 13 +#define MG_MQTT_CMD_DISCONNECT 14 + +/* MQTT event types */ +#define MG_MQTT_EVENT_BASE 200 +#define MG_EV_MQTT_CONNECT (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_CONNECT) +#define MG_EV_MQTT_CONNACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_CONNACK) +#define MG_EV_MQTT_PUBLISH (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBLISH) +#define MG_EV_MQTT_PUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBACK) +#define MG_EV_MQTT_PUBREC (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBREC) +#define MG_EV_MQTT_PUBREL (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBREL) +#define MG_EV_MQTT_PUBCOMP (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBCOMP) +#define MG_EV_MQTT_SUBSCRIBE (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_SUBSCRIBE) +#define MG_EV_MQTT_SUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_SUBACK) +#define MG_EV_MQTT_UNSUBSCRIBE (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_UNSUBSCRIBE) +#define MG_EV_MQTT_UNSUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_UNSUBACK) +#define MG_EV_MQTT_PINGREQ (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PINGREQ) +#define MG_EV_MQTT_PINGRESP (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PINGRESP) +#define MG_EV_MQTT_DISCONNECT (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_DISCONNECT) + +/* Message flags */ +#define MG_MQTT_RETAIN 0x1 +#define MG_MQTT_DUP 0x4 +#define MG_MQTT_QOS(qos) ((qos) << 1) +#define MG_MQTT_GET_QOS(flags) (((flags) &0x6) >> 1) +#define MG_MQTT_SET_QOS(flags, qos) (flags) = ((flags) & ~0x6) | ((qos) << 1) + +/* Connection flags */ +#define MG_MQTT_CLEAN_SESSION 0x02 +#define MG_MQTT_HAS_WILL 0x04 +#define MG_MQTT_WILL_RETAIN 0x20 +#define MG_MQTT_HAS_PASSWORD 0x40 +#define MG_MQTT_HAS_USER_NAME 0x80 +#define MG_MQTT_GET_WILL_QOS(flags) (((flags) &0x18) >> 3) +#define MG_MQTT_SET_WILL_QOS(flags, qos) \ + (flags) = ((flags) & ~0x18) | ((qos) << 3) + +/* CONNACK return codes */ +#define MG_EV_MQTT_CONNACK_ACCEPTED 0 +#define MG_EV_MQTT_CONNACK_UNACCEPTABLE_VERSION 1 +#define MG_EV_MQTT_CONNACK_IDENTIFIER_REJECTED 2 +#define MG_EV_MQTT_CONNACK_SERVER_UNAVAILABLE 3 +#define MG_EV_MQTT_CONNACK_BAD_AUTH 4 +#define MG_EV_MQTT_CONNACK_NOT_AUTHORIZED 5 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Attaches a built-in MQTT event handler to the given connection. + * + * The user-defined event handler will receive following extra events: + * + * - MG_EV_MQTT_CONNACK + * - MG_EV_MQTT_PUBLISH + * - MG_EV_MQTT_PUBACK + * - MG_EV_MQTT_PUBREC + * - MG_EV_MQTT_PUBREL + * - MG_EV_MQTT_PUBCOMP + * - MG_EV_MQTT_SUBACK + */ +void mg_set_protocol_mqtt(struct mg_connection *nc); + +/* Sends an MQTT handshake. */ +void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id); + +/* Sends an MQTT handshake with optional parameters. */ +void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id, + struct mg_send_mqtt_handshake_opts); + +/* Publishes a message to a given topic. */ +void mg_mqtt_publish(struct mg_connection *nc, const char *topic, + uint16_t message_id, int flags, const void *data, + size_t len); + +/* Subscribes to a bunch of topics. */ +void mg_mqtt_subscribe(struct mg_connection *nc, + const struct mg_mqtt_topic_expression *topics, + size_t topics_len, uint16_t message_id); + +/* Unsubscribes from a bunch of topics. */ +void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics, + size_t topics_len, uint16_t message_id); + +/* Sends a DISCONNECT command. */ +void mg_mqtt_disconnect(struct mg_connection *nc); + +/* Sends a CONNACK command with a given `return_code`. */ +void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code); + +/* Sends a PUBACK command with a given `message_id`. */ +void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id); + +/* Sends a PUBREC command with a given `message_id`. */ +void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id); + +/* Sends a PUBREL command with a given `message_id`. */ +void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id); + +/* Sends a PUBCOMP command with a given `message_id`. */ +void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id); + +/* + * Sends a SUBACK command with a given `message_id` + * and a sequence of granted QoSs. + */ +void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len, + uint16_t message_id); + +/* Sends a UNSUBACK command with a given `message_id`. */ +void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id); + +/* Sends a PINGREQ command. */ +void mg_mqtt_ping(struct mg_connection *nc); + +/* Sends a PINGRESP command. */ +void mg_mqtt_pong(struct mg_connection *nc); + +/* + * Extracts the next topic expression from a SUBSCRIBE command payload. + * + * The topic expression name will point to a string in the payload buffer. + * Returns the pos of the next topic expression or -1 when the list + * of topics is exhausted. + */ +int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg, + struct mg_str *topic, uint8_t *qos, int pos); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_MONGOOSE_SRC_MQTT_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/mqtt_server.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +/* + * === MQTT Server API reference + */ + +#ifndef CS_MONGOOSE_SRC_MQTT_BROKER_H_ +#define CS_MONGOOSE_SRC_MQTT_BROKER_H_ + +#if MG_ENABLE_MQTT_BROKER + +/* Amalgamated: #include "common/queue.h" */ +/* Amalgamated: #include "mongoose/src/mqtt.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MG_MQTT_MAX_SESSION_SUBSCRIPTIONS 512; + +struct mg_mqtt_broker; + +/* MQTT session (Broker side). */ +struct mg_mqtt_session { + struct mg_mqtt_broker *brk; /* Broker */ + LIST_ENTRY(mg_mqtt_session) link; /* mg_mqtt_broker::sessions linkage */ + struct mg_connection *nc; /* Connection with the client */ + size_t num_subscriptions; /* Size of `subscriptions` array */ + void *user_data; /* User data */ + struct mg_mqtt_topic_expression *subscriptions; +}; + +/* MQTT broker. */ +struct mg_mqtt_broker { + LIST_HEAD(_mg_sesshead, mg_mqtt_session) sessions; /* Session list */ + void *user_data; /* User data */ +}; + +/* Initialises a MQTT broker. */ +void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data); + +/* + * Processes a MQTT broker message. + * + * The listening connection expects a pointer to an initialised + * `mg_mqtt_broker` structure in the `user_data` field. + * + * Basic usage: + * + * ```c + * mg_mqtt_broker_init(&brk, NULL); + * + * if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) { + * // fail; + * } + * nc->user_data = &brk; + * ``` + * + * New incoming connections will receive a `mg_mqtt_session` structure + * in the connection `user_data`. The original `user_data` will be stored + * in the `user_data` field of the session structure. This allows the user + * handler to store user data before `mg_mqtt_broker` creates the session. + * + * Since only the MG_EV_ACCEPT message is processed by the listening socket, + * for most events the `user_data` will thus point to a `mg_mqtt_session`. + */ +void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data); + +/* + * Iterates over all MQTT session connections. Example: + * + * ```c + * struct mg_mqtt_session *s; + * for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) { + * // Do something + * } + * ``` + */ +struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk, + struct mg_mqtt_session *s); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_MQTT_BROKER */ +#endif /* CS_MONGOOSE_SRC_MQTT_BROKER_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/dns.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * === DNS API reference + */ + +#ifndef CS_MONGOOSE_SRC_DNS_H_ +#define CS_MONGOOSE_SRC_DNS_H_ + +/* Amalgamated: #include "mongoose/src/net.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MG_DNS_A_RECORD 0x01 /* Lookup IP address */ +#define MG_DNS_CNAME_RECORD 0x05 /* Lookup CNAME */ +#define MG_DNS_PTR_RECORD 0x0c /* Lookup PTR */ +#define MG_DNS_TXT_RECORD 0x10 /* Lookup TXT */ +#define MG_DNS_AAAA_RECORD 0x1c /* Lookup IPv6 address */ +#define MG_DNS_SRV_RECORD 0x21 /* Lookup SRV */ +#define MG_DNS_MX_RECORD 0x0f /* Lookup mail server for domain */ + +#define MG_MAX_DNS_QUESTIONS 32 +#define MG_MAX_DNS_ANSWERS 32 + +#define MG_DNS_MESSAGE 100 /* High-level DNS message event */ + +enum mg_dns_resource_record_kind { + MG_DNS_INVALID_RECORD = 0, + MG_DNS_QUESTION, + MG_DNS_ANSWER +}; + +/* DNS resource record. */ +struct mg_dns_resource_record { + struct mg_str name; /* buffer with compressed name */ + int rtype; + int rclass; + int ttl; + enum mg_dns_resource_record_kind kind; + struct mg_str rdata; /* protocol data (can be a compressed name) */ +}; + +/* DNS message (request and response). */ +struct mg_dns_message { + struct mg_str pkt; /* packet body */ + uint16_t flags; + uint16_t transaction_id; + int num_questions; + int num_answers; + struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS]; + struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS]; +}; + +struct mg_dns_resource_record *mg_dns_next_record( + struct mg_dns_message *msg, int query, struct mg_dns_resource_record *prev); + +/* + * Parses the record data from a DNS resource record. + * + * - A: struct in_addr *ina + * - AAAA: struct in6_addr *ina + * - CNAME: char buffer + * + * Returns -1 on error. + * + * TODO(mkm): MX + */ +int mg_dns_parse_record_data(struct mg_dns_message *msg, + struct mg_dns_resource_record *rr, void *data, + size_t data_len); + +/* + * Sends a DNS query to the remote end. + */ +void mg_send_dns_query(struct mg_connection *nc, const char *name, + int query_type); + +/* + * Inserts a DNS header to an IO buffer. + * + * Returns the number of bytes inserted. + */ +int mg_dns_insert_header(struct mbuf *io, size_t pos, + struct mg_dns_message *msg); + +/* + * Appends already encoded questions from an existing message. + * + * This is useful when generating a DNS reply message which includes + * all question records. + * + * Returns the number of appended bytes. + */ +int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg); + +/* + * Encodes and appends a DNS resource record to an IO buffer. + * + * The record metadata is taken from the `rr` parameter, while the name and data + * are taken from the parameters, encoded in the appropriate format depending on + * record type and stored in the IO buffer. The encoded values might contain + * offsets within the IO buffer. It's thus important that the IO buffer doesn't + * get trimmed while a sequence of records are encoded while preparing a DNS + * reply. + * + * This function doesn't update the `name` and `rdata` pointers in the `rr` + * struct because they might be invalidated as soon as the IO buffer grows + * again. + * + * Returns the number of bytes appened or -1 in case of error. + */ +int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr, + const char *name, size_t nlen, const void *rdata, + size_t rlen); + +/* + * Encodes a DNS name. + */ +int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len); + +/* Low-level: parses a DNS response. */ +int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg); + +/* + * Uncompresses a DNS compressed name. + * + * The containing DNS message is required because of the compressed encoding + * and reference suffixes present elsewhere in the packet. + * + * If the name is less than `dst_len` characters long, the remainder + * of `dst` is terminated with `\0` characters. Otherwise, `dst` is not + * terminated. + * + * If `dst_len` is 0 `dst` can be NULL. + * Returns the uncompressed name length. + */ +size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name, + char *dst, int dst_len); + +/* + * Attaches a built-in DNS event handler to the given listening connection. + * + * The DNS event handler parses the incoming UDP packets, treating them as DNS + * requests. If an incoming packet gets successfully parsed by the DNS event + * handler, a user event handler will receive an `MG_DNS_REQUEST` event, with + * `ev_data` pointing to the parsed `struct mg_dns_message`. + * + * See + * [captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server) + * example on how to handle DNS request and send DNS reply. + */ +void mg_set_protocol_dns(struct mg_connection *nc); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* CS_MONGOOSE_SRC_DNS_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/dns_server.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * === DNS server API reference + * + * Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`. + */ + +#ifndef CS_MONGOOSE_SRC_DNS_SERVER_H_ +#define CS_MONGOOSE_SRC_DNS_SERVER_H_ + +#if MG_ENABLE_DNS_SERVER + +/* Amalgamated: #include "mongoose/src/dns.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MG_DNS_SERVER_DEFAULT_TTL 3600 + +struct mg_dns_reply { + struct mg_dns_message *msg; + struct mbuf *io; + size_t start; +}; + +/* + * Creates a DNS reply. + * + * The reply will be based on an existing query message `msg`. + * The query body will be appended to the output buffer. + * "reply + recursion allowed" will be added to the message flags and the + * message's num_answers will be set to 0. + * + * Answer records can be appended with `mg_dns_send_reply` or by lower + * level function defined in the DNS API. + * + * In order to send a reply use `mg_dns_send_reply`. + * It's possible to use a connection's send buffer as reply buffer, + * and it will work for both UDP and TCP connections. + * + * Example: + * + * ```c + * reply = mg_dns_create_reply(&nc->send_mbuf, msg); + * for (i = 0; i < msg->num_questions; i++) { + * rr = &msg->questions[i]; + * if (rr->rtype == MG_DNS_A_RECORD) { + * mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4); + * } + * } + * mg_dns_send_reply(nc, &reply); + * ``` + */ +struct mg_dns_reply mg_dns_create_reply(struct mbuf *io, + struct mg_dns_message *msg); + +/* + * Appends a DNS reply record to the IO buffer and to the DNS message. + * + * The message's num_answers field will be incremented. It's the caller's duty + * to ensure num_answers is properly initialised. + * + * Returns -1 on error. + */ +int mg_dns_reply_record(struct mg_dns_reply *reply, + struct mg_dns_resource_record *question, + const char *name, int rtype, int ttl, const void *rdata, + size_t rdata_len); + +/* + * Sends a DNS reply through a connection. + * + * The DNS data is stored in an IO buffer pointed by reply structure in `r`. + * This function mutates the content of that buffer in order to ensure that + * the DNS header reflects the size and flags of the message, that might have + * been updated either with `mg_dns_reply_record` or by direct manipulation of + * `r->message`. + * + * Once sent, the IO buffer will be trimmed unless the reply IO buffer + * is the connection's send buffer and the connection is not in UDP mode. + */ +void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_DNS_SERVER */ +#endif /* CS_MONGOOSE_SRC_DNS_SERVER_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/resolv.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * === API reference + */ + +#ifndef CS_MONGOOSE_SRC_RESOLV_H_ +#define CS_MONGOOSE_SRC_RESOLV_H_ + +/* Amalgamated: #include "mongoose/src/dns.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum mg_resolve_err { + MG_RESOLVE_OK = 0, + MG_RESOLVE_NO_ANSWERS = 1, + MG_RESOLVE_EXCEEDED_RETRY_COUNT = 2, + MG_RESOLVE_TIMEOUT = 3 +}; + +typedef void (*mg_resolve_callback_t)(struct mg_dns_message *dns_message, + void *user_data, enum mg_resolve_err); + +/* Options for `mg_resolve_async_opt`. */ +struct mg_resolve_async_opts { + const char *nameserver_url; + int max_retries; /* defaults to 2 if zero */ + int timeout; /* in seconds; defaults to 5 if zero */ + int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */ + int only_literal; /* only resolves literal addrs; sync cb invocation */ + struct mg_connection **dns_conn; /* return DNS connection */ +}; + +/* See `mg_resolve_async_opt()` */ +int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query, + mg_resolve_callback_t cb, void *data); + +/* + * Resolved a DNS name asynchronously. + * + * Upon successful resolution, the user callback will be invoked + * with the full DNS response message and a pointer to the user's + * context `data`. + * + * In case of timeout while performing the resolution the callback + * will receive a NULL `msg`. + * + * The DNS answers can be extracted with `mg_next_record` and + * `mg_dns_parse_record_data`: + * + * [source,c] + * ---- + * struct in_addr ina; + * struct mg_dns_resource_record *rr = mg_next_record(msg, MG_DNS_A_RECORD, + * NULL); + * mg_dns_parse_record_data(msg, rr, &ina, sizeof(ina)); + * ---- + */ +int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query, + mg_resolve_callback_t cb, void *data, + struct mg_resolve_async_opts opts); + +/* + * Resolve a name from `/etc/hosts`. + * + * Returns 0 on success, -1 on failure. + */ +int mg_resolve_from_hosts_file(const char *host, union socket_address *usa); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* CS_MONGOOSE_SRC_RESOLV_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/coap.h" +#endif +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +/* + * === CoAP API reference + * + * CoAP message format: + * + * ``` + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + * |Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + * | Options (if any) ... |1 1 1 1 1 1 1 1| Payload (if any) ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + * ``` + */ + +#ifndef CS_MONGOOSE_SRC_COAP_H_ +#define CS_MONGOOSE_SRC_COAP_H_ + +#if MG_ENABLE_COAP + +#define MG_COAP_MSG_TYPE_FIELD 0x2 +#define MG_COAP_CODE_CLASS_FIELD 0x4 +#define MG_COAP_CODE_DETAIL_FIELD 0x8 +#define MG_COAP_MSG_ID_FIELD 0x10 +#define MG_COAP_TOKEN_FIELD 0x20 +#define MG_COAP_OPTIOMG_FIELD 0x40 +#define MG_COAP_PAYLOAD_FIELD 0x80 + +#define MG_COAP_ERROR 0x10000 +#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000) +#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000) +#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000) +#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000) + +#define MG_COAP_MSG_CON 0 +#define MG_COAP_MSG_NOC 1 +#define MG_COAP_MSG_ACK 2 +#define MG_COAP_MSG_RST 3 +#define MG_COAP_MSG_MAX 3 + +#define MG_COAP_CODECLASS_REQUEST 0 +#define MG_COAP_CODECLASS_RESP_OK 2 +#define MG_COAP_CODECLASS_CLIENT_ERR 4 +#define MG_COAP_CODECLASS_SRV_ERR 5 + +#define MG_COAP_EVENT_BASE 300 +#define MG_EV_COAP_CON (MG_COAP_EVENT_BASE + MG_COAP_MSG_CON) +#define MG_EV_COAP_NOC (MG_COAP_EVENT_BASE + MG_COAP_MSG_NOC) +#define MG_EV_COAP_ACK (MG_COAP_EVENT_BASE + MG_COAP_MSG_ACK) +#define MG_EV_COAP_RST (MG_COAP_EVENT_BASE + MG_COAP_MSG_RST) + +/* + * CoAP options. + * Use mg_coap_add_option and mg_coap_free_options + * for creation and destruction. + */ +struct mg_coap_option { + struct mg_coap_option *next; + uint32_t number; + struct mg_str value; +}; + +/* CoAP message. See RFC 7252 for details. */ +struct mg_coap_message { + uint32_t flags; + uint8_t msg_type; + uint8_t code_class; + uint8_t code_detail; + uint16_t msg_id; + struct mg_str token; + struct mg_coap_option *options; + struct mg_str payload; + struct mg_coap_option *optiomg_tail; +}; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Sets CoAP protocol handler - triggers CoAP specific events. */ +int mg_set_protocol_coap(struct mg_connection *nc); + +/* + * Adds a new option to mg_coap_message structure. + * Returns pointer to the newly created option. + * Note: options must be freed by using mg_coap_free_options + */ +struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm, + uint32_t number, char *value, + size_t len); + +/* + * Frees the memory allocated for options. + * If the cm paramater doesn't contain any option it does nothing. + */ +void mg_coap_free_options(struct mg_coap_message *cm); + +/* + * Composes a CoAP message from `mg_coap_message` + * and sends it into `nc` connection. + * Returns 0 on success. On error, it is a bitmask: + * + * - `#define MG_COAP_ERROR 0x10000` + * - `#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)` + * - `#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)` + * - `#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)` + * - `#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)` + */ +uint32_t mg_coap_send_message(struct mg_connection *nc, + struct mg_coap_message *cm); + +/* + * Composes CoAP acknowledgement from `mg_coap_message` + * and sends it into `nc` connection. + * Return value: see `mg_coap_send_message()` + */ +uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id); + +/* + * Parses CoAP message and fills mg_coap_message and returns cm->flags. + * This is a helper function. + * + * NOTE: usually CoAP works over UDP, so lack of data means format error. + * But, in theory, it is possible to use CoAP over TCP (according to RFC) + * + * The caller has to check results and treat COAP_NOT_ENOUGH_DATA according to + * underlying protocol: + * + * - in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR, + * - in case of TCP client can try to receive more data + * + * Return value: see `mg_coap_send_message()` + */ +uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm); + +/* + * Composes CoAP message from mg_coap_message structure. + * This is a helper function. + * Return value: see `mg_coap_send_message()` + */ +uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_COAP */ + +#endif /* CS_MONGOOSE_SRC_COAP_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/sntp.h" +#endif +/* + * Copyright (c) 2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_SNTP_H_ +#define CS_MONGOOSE_SRC_SNTP_H_ + +#if MG_ENABLE_SNTP + +#define MG_SNTP_EVENT_BASE 500 + +/* + * Received reply from time server. Event handler parameter contains + * pointer to mg_sntp_message structure + */ +#define MG_SNTP_REPLY (MG_SNTP_EVENT_BASE + 1) + +/* Received malformed SNTP packet */ +#define MG_SNTP_MALFORMED_REPLY (MG_SNTP_EVENT_BASE + 2) + +/* Failed to get time from server (timeout etc) */ +#define MG_SNTP_FAILED (MG_SNTP_EVENT_BASE + 3) + +struct mg_sntp_message { + /* if server sends this flags, user should not send requests to it */ + int kiss_of_death; + /* usual mg_time */ + double time; +}; + +/* Establishes connection to given sntp server */ +struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, + mg_event_handler_t event_handler, + const char *sntp_server_name); + +/* Sends time request to given connection */ +void mg_sntp_send_request(struct mg_connection *c); + +/* + * Helper function + * Establishes connection to time server, tries to send request + * repeats sending SNTP_ATTEMPTS times every SNTP_TIMEOUT sec + * (if needed) + * See sntp_client example + */ +struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr, + mg_event_handler_t event_handler, + const char *sntp_server_name); + +#endif + +#endif /* CS_MONGOOSE_SRC_SNTP_H_ */ diff --git a/build_http/main.cpp b/build_http/main.cpp new file mode 100644 index 0000000..0d2f071 --- /dev/null +++ b/build_http/main.cpp @@ -0,0 +1,349 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "mongoose.h" +#include +#include + +#define SERIAL_PORT "/dev/ttyS0" +#define BAUD_RATE B115200 +#define FILE_PWD "/etc/DeviceID" + +char hexData[1024]; + +int get_return(int serialPort) +{ + usleep(10000); + ssize_t size; + unsigned char ch; + char buffer[1024]; + hexData[1024]={0}; + + size = read(serialPort, buffer, sizeof(buffer)); + if (size > 0){ + std::vector byteArray; + int i; + for (i = 0; i < size; i++) { + snprintf(&hexData[i * 2], sizeof(hexData) - i * 2, "%02X", buffer[i]); + byteArray.push_back(static_cast(buffer[i])); + } + + printf("Received result: %s\n", hexData); + for (unsigned char c : byteArray) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(c) << " "; + } + std::cout << std::endl; + + return 0; + }else{ + return -1; + } + +} + +// 用于处理GET请求的事件处理函数 +static void get_handler_10000(struct mg_connection *nc, int ev, void *ev_data) { + if (ev == MG_EV_HTTP_REQUEST) { + struct http_message *hm = (struct http_message *) ev_data; + + // 检查HTTP请求方法是否为POST + if (mg_vcmp(&hm->method, "GET") == 0) { + // 解析POST请求的参数 + struct mg_str param_str = hm->query_string; + // printf("param: %.*s\n", (int) hm->query_string.len, hm->query_string.p); + + char value_buf[256]; + int result = mg_get_http_var(¶m_str, "DeviceID", value_buf, sizeof(value_buf)); + if (result > 0) { + // 参数找到并存储在 value_buf 中 + printf("DeviceID: %.*s\n", result, value_buf); + std::string data = value_buf; + FILE *file = fopen(FILE_PWD, "wb"); // 使用二进制模式打开文件 + + // 检查文件是否成功打开 + if (file) { + // 将数据写入文件 + size_t bytes_written = fwrite(value_buf, 1, strlen(value_buf), file); + + // 检查写入是否成功 + if (bytes_written == data.length()) { + printf("Data written to %s successfully.\n", FILE_PWD); + } else { + printf("Error writing data to %s.\n", FILE_PWD); + } + + // 关闭文件 + fclose(file); + } else { + printf("Error opening file %s for writing.\n", FILE_PWD); + } + } else { + // 参数未找到 + mg_http_send_error(nc, 405, "Parameter Not Allowed"); + printf("Parameter not found\n"); + } + + // // 提取POST请求的数据 + // char post_data[1024]; // 假设数据大小不超过 1024 字节 + // memcpy(post_data, hm->body.p, hm->body.len); + // post_data[hm->body.len] = '\0'; // 添加字符串结束符 + // // 处理POST请求数据,这里可以根据需要进行处理 + // printf("Received POST data: %s\n", post_data); + + + + // 发送HTTP响应 + mg_printf(nc, "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n\r\n" + "POST data received and processed\r\n", + (int) strlen("POST data received and processed")); + + nc->flags |= MG_F_SEND_AND_CLOSE; // 关闭连接 + } else { + // 如果不是POST请求,可以返回错误响应 + mg_http_send_error(nc, 405, "Method Not Allowed"); + } + } +} + +// 用于处理GET请求的事件处理函数 气压计 +static void get_handler_11000(struct mg_connection *nc, int ev, void *ev_data) { + if (ev == MG_EV_HTTP_REQUEST) { + sem_t *my_semaphore = sem_open("/my_semaphore", O_CREAT, 0644, 1); + + struct timespec abs_timeout; + clock_gettime(CLOCK_REALTIME, &abs_timeout); + abs_timeout.tv_sec += 5; // 增加 5 秒的超时时间 + + int serialPort = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + if (serialPort == -1) { + printf("Failed to open serial port: %s\n", SERIAL_PORT); + } + + struct termios tty; + memset(&tty, 0, sizeof(tty)); + if (tcgetattr(serialPort, &tty) != 0) { + printf("Failed to get serial port attributes\n"); + close(serialPort); + } + cfsetospeed(&tty, BAUD_RATE); + cfsetispeed(&tty, BAUD_RATE); + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; + tty.c_cflag &= ~(PARENB | PARODD); + tty.c_cflag &= ~CSTOPB; + tty.c_cflag |= CREAD | CLOCAL; + tty.c_iflag = IGNPAR; + tty.c_oflag = 0; + tty.c_lflag = 0; + if (tcsetattr(serialPort, TCSANOW, &tty) != 0) { + printf("Failed to set serial port attributes\n"); + close(serialPort); + } + + char buffer[300]; + ssize_t bytesRead; + + + struct http_message *hm = (struct http_message *) ev_data; + + // 检查HTTP请求方法是否为POST + if (mg_vcmp(&hm->method, "GET") == 0) { + // 解析POST请求的参数 + struct mg_str param_str = hm->query_string; + // printf("param: %.*s\n", (int) hm->query_string.len, hm->query_string.p); + + char value_buf[256]; + int result = mg_get_http_var(¶m_str, "barometer", value_buf, sizeof(value_buf)); + if (result > 0) { + // 参数找到并存储在 value_buf 中 + printf("barometer: %.*s\n", result, value_buf); + } else { + // 参数未找到 + mg_http_send_error(nc, 405, "Parameter Not Allowed"); + printf("Parameter not found\n"); + } + + // 转换成16进制 + std::string hex_string = value_buf; + + std::vector response; + + // 使用std::stringstream来解析整个16进制字符串 + std::stringstream ss(hex_string); + for (int i = 0; i < hex_string.length(); i += 2){ + char byte_str[3]; // 两个字符表示一个字节 + ss.read(byte_str, 2); + byte_str[2] = '\0'; // 添加字符串终止符 + unsigned int byte; + std::stringstream(byte_str) >> std::hex >> byte; + response.push_back(static_cast(byte)); + } + + // 打印转换后的结果 + std::cout << "转换后的结果:" << std::endl; + for (const auto &byte : response) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(byte) << " "; + } + std::cout << std::endl; + + if (sem_timedwait(my_semaphore, &abs_timeout) == -1) { + if (errno == ETIMEDOUT) { + // 在这里处理等待超时的情况 + printf("等待超时\n"); + mg_http_send_error(nc, 406, "写入超时,请稍后再试"); + } else { + perror("sem_timedwait"); + mg_http_send_error(nc, 407, "未知错误"); + } + }else{ + write(serialPort, response.data(), response.size()); + int read_limit = 0; + int res = -1; + do { + res = get_return(serialPort); + read_limit++; + printf("res: %d i=%d\n",res,read_limit); + } while ((res != 0) && (read_limit < 100)); + sem_post(my_semaphore); + // 发送HTTP响应 + mg_printf(nc, "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n\r\n" + "%s\r\n", + (int) strlen(hexData),hexData); + nc->flags |= MG_F_SEND_AND_CLOSE; // 关闭连接 + } + + } else { + // 如果不是POST请求,可以返回错误响应 + mg_http_send_error(nc, 405, "Method Not Allowed"); + } + close(serialPort); + } +} + + + +int main(void) { + struct mg_mgr mgr; + struct mg_connection *nc1,*nc2; + + mg_mgr_init(&mgr, NULL); + nc1 = mg_bind(&mgr, "10000", get_handler_10000); // 用于接收设备id + nc2 = mg_bind(&mgr, "11000", get_handler_11000); // 用于接收设备id + + // 设置HTTP和WebSocket协议 + mg_set_protocol_http_websocket(nc1); + mg_set_protocol_http_websocket(nc2); + + printf("Starting web server on port 10000 and 11000\n"); + for (;;) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; +} + +// #include "mongoose.h" + +// static void handle_multipart(struct mg_connection *nc, struct http_message *hm) { +// char var_name[256]; +// char file_name[256]; +// const char *data; +// size_t data_len; + +// size_t pos = mg_parse_multipart( +// hm->body.p, hm->body.len, var_name, sizeof(var_name), +// file_name, sizeof(file_name), &data, &data_len +// ); + +// // 遍历各个部分,处理每个字段的数据 +// while (pos > 0) { +// // 在这里处理字段数据 +// // printf("File Name: %s\n", file_name); +// printf("Field Name: %s\n", var_name); +// printf("Field Data: %.*s\n", (int) data_len, data); + +// FILE *file = fopen(var_name, "wb"); // 使用二进制模式打开文件 + +// // 检查文件是否成功打开 +// if (file) { +// // 将数据写入文件 +// size_t bytes_written = fwrite(data, 1, data_len, file); + +// // 检查写入是否成功 +// if (bytes_written == data_len) { +// printf("Data written to %s successfully.\n", var_name); +// } else { +// printf("Error writing data to %s.\n", var_name); +// } + +// // 关闭文件 +// fclose(file); +// } else { +// printf("Error opening file %s for writing.\n", var_name); +// } + + + +// // 继续解析下一个部分 +// pos = mg_parse_multipart( +// hm->body.p + pos, hm->body.len - pos, var_name, sizeof(var_name), +// file_name, sizeof(file_name), &data, &data_len +// ); +// } +// } + +// static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { +// if (ev == MG_EV_HTTP_REQUEST) { +// struct http_message *hm = (struct http_message *)ev_data; + +// // 检查Content-Type是否为multipart/form-data +// // if (mg_vcmp(&hm->header.content_type, "multipart/form-data") == 0) { +// // 调用处理multipart请求的函数 +// handle_multipart(nc, hm); +// // } else { + +// // mg_http_send_error(nc, 400, "Bad Request"); +// // } +// mg_printf(nc, "HTTP/1.1 200 OK\r\n" +// "Content-Type: text/plain\r\n" +// "Content-Length: %d\r\n\r\n" +// "POST data received and processed\r\n", +// (int) strlen("POST data received and processed")); + +// nc->flags |= MG_F_SEND_AND_CLOSE; // 关闭连接 +// } +// } + +// int main(void) { +// struct mg_mgr mgr; +// struct mg_connection *nc; + +// mg_mgr_init(&mgr, NULL); +// nc = mg_bind(&mgr, "8080", ev_handler); +// mg_set_protocol_http_websocket(nc); + +// printf("Starting web server on port 8080\n"); +// for (;;) { +// mg_mgr_poll(&mgr, 1000); +// } +// mg_mgr_free(&mgr); + +// return 0; +// } \ No newline at end of file diff --git a/build_http/mongoose.c b/build_http/mongoose.c new file mode 100644 index 0000000..7e55896 --- /dev/null +++ b/build_http/mongoose.c @@ -0,0 +1,15081 @@ +#include "mongoose.h" +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/internal.h" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_INTERNAL_H_ +#define CS_MONGOOSE_SRC_INTERNAL_H_ + +#ifndef MG_MALLOC +#define MG_MALLOC malloc +#endif + +#ifndef MG_CALLOC +#define MG_CALLOC calloc +#endif + +#ifndef MG_REALLOC +#define MG_REALLOC realloc +#endif + +#ifndef MG_FREE +#define MG_FREE free +#endif + +#ifndef MBUF_REALLOC +#define MBUF_REALLOC MG_REALLOC +#endif + +#ifndef MBUF_FREE +#define MBUF_FREE MG_FREE +#endif + +#define MG_SET_PTRPTR(_ptr, _v) \ + do { \ + if (_ptr) *(_ptr) = _v; \ + } while (0) + +#ifndef MG_INTERNAL +#define MG_INTERNAL static +#endif + +#ifdef PICOTCP +#define NO_LIBC +#define MG_DISABLE_PFS +#endif + +/* Amalgamated: #include "mongoose/src/net.h" */ +/* Amalgamated: #include "mongoose/src/http.h" */ +/* Amalgamated: #include "common/cs_dbg.h" */ + +#define MG_CTL_MSG_MESSAGE_SIZE 8192 + +/* internals that need to be accessible in unit tests */ +MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc, + int proto, + union socket_address *sa); + +MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, + int *proto, char *host, size_t host_len); +MG_INTERNAL void mg_call(struct mg_connection *nc, + mg_event_handler_t ev_handler, int ev, void *ev_data); +void mg_forward(struct mg_connection *from, struct mg_connection *to); +MG_INTERNAL void mg_add_conn(struct mg_mgr *mgr, struct mg_connection *c); +MG_INTERNAL void mg_remove_conn(struct mg_connection *c); +MG_INTERNAL struct mg_connection *mg_create_connection( + struct mg_mgr *mgr, mg_event_handler_t callback, + struct mg_add_sock_opts opts); +#ifdef _WIN32 +/* Retur value is the same as for MultiByteToWideChar. */ +int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len); +#endif + +struct ctl_msg { + mg_event_handler_t callback; + char message[MG_CTL_MSG_MESSAGE_SIZE]; +}; + +#if MG_ENABLE_MQTT +struct mg_mqtt_message; +MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm); +#endif + +/* Forward declarations for testing. */ +extern void *(*test_malloc)(size_t size); +extern void *(*test_calloc)(size_t count, size_t size); + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#if MG_ENABLE_HTTP +struct mg_serve_http_opts; + +/* + * Reassemble the content of the buffer (buf, blen) which should be + * in the HTTP chunked encoding, by collapsing data chunks to the + * beginning of the buffer. + * + * If chunks get reassembled, modify hm->body to point to the reassembled + * body and fire MG_EV_HTTP_CHUNK event. If handler sets MG_F_DELETE_CHUNK + * in nc->flags, delete reassembled body from the mbuf. + * + * Return reassembled body size. + */ +MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, + struct http_message *hm, char *buf, + size_t blen); + +MG_INTERNAL int mg_http_common_url_parse(const char *url, const char *schema, + const char *schema_tls, int *use_ssl, + char **user, char **pass, char **addr, + int *port_i, const char **path); + +#if MG_ENABLE_FILESYSTEM +MG_INTERNAL int mg_uri_to_local_path(struct http_message *hm, + const struct mg_serve_http_opts *opts, + char **local_path, + struct mg_str *remainder); +MG_INTERNAL time_t mg_parse_date_string(const char *datetime); +MG_INTERNAL int mg_is_not_modified(struct http_message *hm, cs_stat_t *st); +#endif +#if MG_ENABLE_HTTP_CGI +MG_INTERNAL void mg_handle_cgi(struct mg_connection *nc, const char *prog, + const struct mg_str *path_info, + const struct http_message *hm, + const struct mg_serve_http_opts *opts); +struct mg_http_proto_data_cgi; +MG_INTERNAL void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d); +#endif +#if MG_ENABLE_HTTP_SSI +MG_INTERNAL void mg_handle_ssi_request(struct mg_connection *nc, + struct http_message *hm, + const char *path, + const struct mg_serve_http_opts *opts); +#endif +#if MG_ENABLE_HTTP_WEBDAV +MG_INTERNAL int mg_is_dav_request(const struct mg_str *s); +MG_INTERNAL void mg_handle_propfind(struct mg_connection *nc, const char *path, + cs_stat_t *stp, struct http_message *hm, + struct mg_serve_http_opts *opts); +MG_INTERNAL void mg_handle_lock(struct mg_connection *nc, const char *path); +MG_INTERNAL void mg_handle_mkcol(struct mg_connection *nc, const char *path, + struct http_message *hm); +MG_INTERNAL void mg_handle_move(struct mg_connection *c, + const struct mg_serve_http_opts *opts, + const char *path, struct http_message *hm); +MG_INTERNAL void mg_handle_delete(struct mg_connection *nc, + const struct mg_serve_http_opts *opts, + const char *path); +MG_INTERNAL void mg_handle_put(struct mg_connection *nc, const char *path, + struct http_message *hm); +#endif +#if MG_ENABLE_HTTP_WEBSOCKET +MG_INTERNAL void mg_ws_handler(struct mg_connection *nc, int ev, void *ev_data); +MG_INTERNAL void mg_ws_handshake(struct mg_connection *nc, + const struct mg_str *key); +#endif +#endif /* MG_ENABLE_HTTP */ + +MG_INTERNAL int mg_get_errno(void); + +MG_INTERNAL void mg_close_conn(struct mg_connection *conn); + +MG_INTERNAL int mg_http_common_url_parse(const char *url, const char *schema, + const char *schema_tls, int *use_ssl, + char **user, char **pass, char **addr, + int *port_i, const char **path); + +#if MG_ENABLE_SNTP +MG_INTERNAL int mg_sntp_parse_reply(const char *buf, int len, + struct mg_sntp_message *msg); +#endif + +#endif /* CS_MONGOOSE_SRC_INTERNAL_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/cs_dbg.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_CS_DBG_H_ +#define CS_COMMON_CS_DBG_H_ + +/* Amalgamated: #include "common/platform.h" */ + +#if CS_ENABLE_STDIO +#include +#endif + +#ifndef CS_ENABLE_DEBUG +#define CS_ENABLE_DEBUG 0 +#endif + +#ifndef CS_LOG_ENABLE_TS_DIFF +#define CS_LOG_ENABLE_TS_DIFF 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum cs_log_level { + LL_NONE = -1, + LL_ERROR = 0, + LL_WARN = 1, + LL_INFO = 2, + LL_DEBUG = 3, + LL_VERBOSE_DEBUG = 4, + + _LL_MIN = -2, + _LL_MAX = 5, +}; + +void cs_log_set_level(enum cs_log_level level); + +#if CS_ENABLE_STDIO + +void cs_log_set_file(FILE *file); +extern enum cs_log_level cs_log_level; +void cs_log_print_prefix(const char *func); +void cs_log_printf(const char *fmt, ...); + +#define LOG(l, x) \ + do { \ + if (cs_log_level >= l) { \ + cs_log_print_prefix(__func__); \ + cs_log_printf x; \ + } \ + } while (0) + +#ifndef CS_NDEBUG + +#define DBG(x) \ + do { \ + if (cs_log_level >= LL_VERBOSE_DEBUG) { \ + cs_log_print_prefix(__func__); \ + cs_log_printf x; \ + } \ + } while (0) + +#else /* NDEBUG */ + +#define DBG(x) + +#endif + +#else /* CS_ENABLE_STDIO */ + +#define LOG(l, x) +#define DBG(x) + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_CS_DBG_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/cs_dbg.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "common/cs_dbg.h" */ + +#include +#include + +/* Amalgamated: #include "common/cs_time.h" */ + +enum cs_log_level cs_log_level WEAK = +#if CS_ENABLE_DEBUG + LL_VERBOSE_DEBUG; +#else + LL_ERROR; +#endif + +#if CS_ENABLE_STDIO + +FILE *cs_log_file WEAK = NULL; + +#if CS_LOG_ENABLE_TS_DIFF +double cs_log_ts WEAK; +#endif + +void cs_log_print_prefix(const char *func) WEAK; +void cs_log_print_prefix(const char *func) { + if (cs_log_file == NULL) cs_log_file = stderr; + fprintf(cs_log_file, "%-20s ", func); +#if CS_LOG_ENABLE_TS_DIFF + { + double now = cs_time(); + fprintf(cs_log_file, "%7u ", (unsigned int) ((now - cs_log_ts) * 1000000)); + cs_log_ts = now; + } +#endif +} + +void cs_log_printf(const char *fmt, ...) WEAK; +void cs_log_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vfprintf(cs_log_file, fmt, ap); + va_end(ap); + fputc('\n', cs_log_file); + fflush(cs_log_file); +} + +void cs_log_set_file(FILE *file) WEAK; +void cs_log_set_file(FILE *file) { + cs_log_file = file; +} + +#endif /* CS_ENABLE_STDIO */ + +void cs_log_set_level(enum cs_log_level level) WEAK; +void cs_log_set_level(enum cs_log_level level) { + cs_log_level = level; +#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO + cs_log_ts = cs_time(); +#endif +} +#ifdef MG_MODULE_LINES +#line 1 "common/base64.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef EXCLUDE_COMMON + +/* Amalgamated: #include "common/base64.h" */ + +#include + +/* Amalgamated: #include "common/cs_dbg.h" */ + +/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */ + +#define NUM_UPPERCASES ('Z' - 'A' + 1) +#define NUM_LETTERS (NUM_UPPERCASES * 2) +#define NUM_DIGITS ('9' - '0' + 1) + +/* + * Emit a base64 code char. + * + * Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps + */ +static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) { + if (v < NUM_UPPERCASES) { + ctx->b64_putc(v + 'A', ctx->user_data); + } else if (v < (NUM_LETTERS)) { + ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data); + } else if (v < (NUM_LETTERS + NUM_DIGITS)) { + ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data); + } else { + ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/', + ctx->user_data); + } +} + +static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) { + int a, b, c; + + a = ctx->chunk[0]; + b = ctx->chunk[1]; + c = ctx->chunk[2]; + + cs_base64_emit_code(ctx, a >> 2); + cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4)); + if (ctx->chunk_size > 1) { + cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6)); + } + if (ctx->chunk_size > 2) { + cs_base64_emit_code(ctx, c & 63); + } +} + +void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc, + void *user_data) { + ctx->chunk_size = 0; + ctx->b64_putc = b64_putc; + ctx->user_data = user_data; +} + +void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) { + const unsigned char *src = (const unsigned char *) str; + size_t i; + for (i = 0; i < len; i++) { + ctx->chunk[ctx->chunk_size++] = src[i]; + if (ctx->chunk_size == 3) { + cs_base64_emit_chunk(ctx); + ctx->chunk_size = 0; + } + } +} + +void cs_base64_finish(struct cs_base64_ctx *ctx) { + if (ctx->chunk_size > 0) { + int i; + memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size); + cs_base64_emit_chunk(ctx); + for (i = 0; i < (3 - ctx->chunk_size); i++) { + ctx->b64_putc('=', ctx->user_data); + } + } +} + +#define BASE64_ENCODE_BODY \ + static const char *b64 = \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \ + int i, j, a, b, c; \ + \ + for (i = j = 0; i < src_len; i += 3) { \ + a = src[i]; \ + b = i + 1 >= src_len ? 0 : src[i + 1]; \ + c = i + 2 >= src_len ? 0 : src[i + 2]; \ + \ + BASE64_OUT(b64[a >> 2]); \ + BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \ + if (i + 1 < src_len) { \ + BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \ + } \ + if (i + 2 < src_len) { \ + BASE64_OUT(b64[c & 63]); \ + } \ + } \ + \ + while (j % 4 != 0) { \ + BASE64_OUT('='); \ + } \ + BASE64_FLUSH() + +#define BASE64_OUT(ch) \ + do { \ + dst[j++] = (ch); \ + } while (0) + +#define BASE64_FLUSH() \ + do { \ + dst[j++] = '\0'; \ + } while (0) + +void cs_base64_encode(const unsigned char *src, int src_len, char *dst) { + BASE64_ENCODE_BODY; +} + +#undef BASE64_OUT +#undef BASE64_FLUSH + +#if CS_ENABLE_STDIO +#define BASE64_OUT(ch) \ + do { \ + fprintf(f, "%c", (ch)); \ + j++; \ + } while (0) + +#define BASE64_FLUSH() + +void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) { + BASE64_ENCODE_BODY; +} + +#undef BASE64_OUT +#undef BASE64_FLUSH +#endif /* CS_ENABLE_STDIO */ + +/* Convert one byte of encoded base64 input stream to 6-bit chunk */ +static unsigned char from_b64(unsigned char ch) { + /* Inverse lookup map */ + static const unsigned char tab[128] = { + 255, 255, 255, 255, + 255, 255, 255, 255, /* 0 */ + 255, 255, 255, 255, + 255, 255, 255, 255, /* 8 */ + 255, 255, 255, 255, + 255, 255, 255, 255, /* 16 */ + 255, 255, 255, 255, + 255, 255, 255, 255, /* 24 */ + 255, 255, 255, 255, + 255, 255, 255, 255, /* 32 */ + 255, 255, 255, 62, + 255, 255, 255, 63, /* 40 */ + 52, 53, 54, 55, + 56, 57, 58, 59, /* 48 */ + 60, 61, 255, 255, + 255, 200, 255, 255, /* 56 '=' is 200, on index 61 */ + 255, 0, 1, 2, + 3, 4, 5, 6, /* 64 */ + 7, 8, 9, 10, + 11, 12, 13, 14, /* 72 */ + 15, 16, 17, 18, + 19, 20, 21, 22, /* 80 */ + 23, 24, 25, 255, + 255, 255, 255, 255, /* 88 */ + 255, 26, 27, 28, + 29, 30, 31, 32, /* 96 */ + 33, 34, 35, 36, + 37, 38, 39, 40, /* 104 */ + 41, 42, 43, 44, + 45, 46, 47, 48, /* 112 */ + 49, 50, 51, 255, + 255, 255, 255, 255, /* 120 */ + }; + return tab[ch & 127]; +} + +int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len) { + unsigned char a, b, c, d; + int orig_len = len; + char *orig_dst = dst; + while (len >= 4 && (a = from_b64(s[0])) != 255 && + (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 && + (d = from_b64(s[3])) != 255) { + s += 4; + len -= 4; + if (a == 200 || b == 200) break; /* '=' can't be there */ + *dst++ = a << 2 | b >> 4; + if (c == 200) break; + *dst++ = b << 4 | c >> 2; + if (d == 200) break; + *dst++ = c << 6 | d; + } + *dst = 0; + if (dec_len != NULL) *dec_len = (dst - orig_dst); + return orig_len - len; +} + +#endif /* EXCLUDE_COMMON */ +#ifdef MG_MODULE_LINES +#line 1 "common/cs_dirent.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_CS_DIRENT_H_ +#define CS_COMMON_CS_DIRENT_H_ + +/* Amalgamated: #include "common/platform.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef CS_ENABLE_SPIFFS +#define CS_ENABLE_SPIFFS 0 +#endif + +#if CS_ENABLE_SPIFFS + +#include + +typedef struct { + spiffs_DIR dh; + struct spiffs_dirent de; +} DIR; + +#define d_name name +#define dirent spiffs_dirent + +int rmdir(const char *path); +int mkdir(const char *path, mode_t mode); + +#endif + +#if defined(_WIN32) +struct dirent { + char d_name[MAX_PATH]; +}; + +typedef struct DIR { + HANDLE handle; + WIN32_FIND_DATAW info; + struct dirent result; +} DIR; +#endif + +#if CS_ENABLE_SPIFFS +extern spiffs *cs_spiffs_get_fs(void); +#endif + +#if defined(_WIN32) || CS_ENABLE_SPIFFS +DIR *opendir(const char *dir_name); +int closedir(DIR *dir); +struct dirent *readdir(DIR *dir); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_CS_DIRENT_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/cs_dirent.c" +#endif +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + */ + +#ifndef EXCLUDE_COMMON + +/* Amalgamated: #include "common/cs_dirent.h" */ + +/* + * This file contains POSIX opendir/closedir/readdir API implementation + * for systems which do not natively support it (e.g. Windows). + */ + +#ifndef MG_FREE +#define MG_FREE free +#endif + +#ifndef MG_MALLOC +#define MG_MALLOC malloc +#endif + +#ifdef _WIN32 +DIR *opendir(const char *name) { + DIR *dir = NULL; + wchar_t wpath[MAX_PATH]; + DWORD attrs; + + if (name == NULL) { + SetLastError(ERROR_BAD_ARGUMENTS); + } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } else { + to_wchar(name, wpath, ARRAY_SIZE(wpath)); + attrs = GetFileAttributesW(wpath); + if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) { + (void) wcscat(wpath, L"\\*"); + dir->handle = FindFirstFileW(wpath, &dir->info); + dir->result.d_name[0] = '\0'; + } else { + MG_FREE(dir); + dir = NULL; + } + } + + return dir; +} + +int closedir(DIR *dir) { + int result = 0; + + if (dir != NULL) { + if (dir->handle != INVALID_HANDLE_VALUE) + result = FindClose(dir->handle) ? 0 : -1; + MG_FREE(dir); + } else { + result = -1; + SetLastError(ERROR_BAD_ARGUMENTS); + } + + return result; +} + +struct dirent *readdir(DIR *dir) { + struct dirent *result = NULL; + + if (dir) { + if (dir->handle != INVALID_HANDLE_VALUE) { + result = &dir->result; + (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1, + result->d_name, sizeof(result->d_name), NULL, + NULL); + + if (!FindNextFileW(dir->handle, &dir->info)) { + (void) FindClose(dir->handle); + dir->handle = INVALID_HANDLE_VALUE; + } + + } else { + SetLastError(ERROR_FILE_NOT_FOUND); + } + } else { + SetLastError(ERROR_BAD_ARGUMENTS); + } + + return result; +} +#endif + +#if CS_ENABLE_SPIFFS + +DIR *opendir(const char *dir_name) { + DIR *dir = NULL; + spiffs *fs = cs_spiffs_get_fs(); + + if (dir_name == NULL || fs == NULL || + (dir = (DIR *) calloc(1, sizeof(*dir))) == NULL) { + return NULL; + } + + if (SPIFFS_opendir(fs, dir_name, &dir->dh) == NULL) { + free(dir); + dir = NULL; + } + + return dir; +} + +int closedir(DIR *dir) { + if (dir != NULL) { + SPIFFS_closedir(&dir->dh); + free(dir); + } + return 0; +} + +struct dirent *readdir(DIR *dir) { + return SPIFFS_readdir(&dir->dh, &dir->de); +} + +/* SPIFFs doesn't support directory operations */ +int rmdir(const char *path) { + (void) path; + return ENOTSUP; +} + +int mkdir(const char *path, mode_t mode) { + (void) path; + (void) mode; + /* for spiffs supports only root dir, which comes from mongoose as '.' */ + return (strlen(path) == 1 && *path == '.') ? 0 : ENOTSUP; +} + +#endif /* CS_ENABLE_SPIFFS */ + +#endif /* EXCLUDE_COMMON */ + +/* ISO C requires a translation unit to contain at least one declaration */ +typedef int cs_dirent_dummy; +#ifdef MG_MODULE_LINES +#line 1 "common/cs_time.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "common/cs_time.h" */ + +#ifndef _WIN32 +#include +/* + * There is no sys/time.h on ARMCC. + */ +#if !(defined(__ARMCC_VERSION) || defined(__ICCARM__)) && \ + !defined(__TI_COMPILER_VERSION__) && \ + (!defined(CS_PLATFORM) || CS_PLATFORM != CS_P_NXP_LPC) +#include +#endif +#else +#include +#endif + +double cs_time(void) WEAK; +double cs_time(void) { + double now; +#ifndef _WIN32 + struct timeval tv; + if (gettimeofday(&tv, NULL /* tz */) != 0) return 0; + now = (double) tv.tv_sec + (((double) tv.tv_usec) / 1000000.0); +#else + SYSTEMTIME sysnow; + FILETIME ftime; + GetLocalTime(&sysnow); + SystemTimeToFileTime(&sysnow, &ftime); + /* + * 1. VC 6.0 doesn't support conversion uint64 -> double, so, using int64 + * This should not cause a problems in this (21th) century + * 2. Windows FILETIME is a number of 100-nanosecond intervals since January + * 1, 1601 while time_t is a number of _seconds_ since January 1, 1970 UTC, + * thus, we need to convert to seconds and adjust amount (subtract 11644473600 + * seconds) + */ + now = (double) (((int64_t) ftime.dwLowDateTime + + ((int64_t) ftime.dwHighDateTime << 32)) / + 10000000.0) - + 11644473600; +#endif /* _WIN32 */ + return now; +} +#ifdef MG_MODULE_LINES +#line 1 "common/cs_endian.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_CS_ENDIAN_H_ +#define CS_COMMON_CS_ENDIAN_H_ + +/* + * clang with std=-c99 uses __LITTLE_ENDIAN, by default + * while for ex, RTOS gcc - LITTLE_ENDIAN, by default + * it depends on __USE_BSD, but let's have everything + */ +#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER) +#define BYTE_ORDER __BYTE_ORDER +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#endif /* LITTLE_ENDIAN */ +#ifndef BIG_ENDIAN +#define BIG_ENDIAN __LITTLE_ENDIAN +#endif /* BIG_ENDIAN */ +#endif /* BYTE_ORDER */ + +#endif /* CS_COMMON_CS_ENDIAN_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/md5.c" +#endif +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* Amalgamated: #include "common/md5.h" */ +/* Amalgamated: #include "common/str_util.h" */ + +#if !defined(EXCLUDE_COMMON) +#if !DISABLE_MD5 + +/* Amalgamated: #include "common/cs_endian.h" */ + +static void byteReverse(unsigned char *buf, unsigned longs) { +/* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */ +#if BYTE_ORDER == BIG_ENDIAN + do { + uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32_t *) buf = t; + buf += 4; + } while (--longs); +#else + (void) buf; + (void) longs; +#endif +} + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x) + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5_Init(MD5_CTX *ctx) { + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { + register uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) { + uint32_t t; + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; + ctx->bits[1] += (uint32_t) len >> 29; + + t = (t >> 3) & 0x3f; + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += t; + len -= t; + } + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += 64; + len -= 64; + } + + memcpy(ctx->in, buf, len); +} + +void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) { + unsigned count; + unsigned char *p; + uint32_t *a; + + count = (ctx->bits[0] >> 3) & 0x3F; + + p = ctx->in + count; + *p++ = 0x80; + count = 64 - 1 - count; + if (count < 8) { + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + memset(ctx->in, 0, 56); + } else { + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + a = (uint32_t *) ctx->in; + a[14] = ctx->bits[0]; + a[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset((char *) ctx, 0, sizeof(*ctx)); +} +#endif /* DISABLE_MD5 */ + +char *cs_md5(char buf[33], ...) { + unsigned char hash[16]; + const unsigned char *p; + va_list ap; + MD5_CTX ctx; + + MD5_Init(&ctx); + + va_start(ap, buf); + while ((p = va_arg(ap, const unsigned char *) ) != NULL) { + size_t len = va_arg(ap, size_t); + MD5_Update(&ctx, p, len); + } + va_end(ap); + + MD5_Final(hash, &ctx); + cs_to_hex(buf, hash, sizeof(hash)); + + return buf; +} + +#endif /* EXCLUDE_COMMON */ +#ifdef MG_MODULE_LINES +#line 1 "common/mbuf.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef EXCLUDE_COMMON + +#include +#include +/* Amalgamated: #include "common/mbuf.h" */ + +#ifndef MBUF_REALLOC +#define MBUF_REALLOC realloc +#endif + +#ifndef MBUF_FREE +#define MBUF_FREE free +#endif + +void mbuf_init(struct mbuf *mbuf, size_t initial_size) WEAK; +void mbuf_init(struct mbuf *mbuf, size_t initial_size) { + mbuf->len = mbuf->size = 0; + mbuf->buf = NULL; + mbuf_resize(mbuf, initial_size); +} + +void mbuf_free(struct mbuf *mbuf) WEAK; +void mbuf_free(struct mbuf *mbuf) { + if (mbuf->buf != NULL) { + MBUF_FREE(mbuf->buf); + mbuf_init(mbuf, 0); + } +} + +void mbuf_resize(struct mbuf *a, size_t new_size) WEAK; +void mbuf_resize(struct mbuf *a, size_t new_size) { + if (new_size > a->size || (new_size < a->size && new_size >= a->len)) { + char *buf = (char *) MBUF_REALLOC(a->buf, new_size); + /* + * In case realloc fails, there's not much we can do, except keep things as + * they are. Note that NULL is a valid return value from realloc when + * size == 0, but that is covered too. + */ + if (buf == NULL && new_size != 0) return; + a->buf = buf; + a->size = new_size; + } +} + +void mbuf_trim(struct mbuf *mbuf) WEAK; +void mbuf_trim(struct mbuf *mbuf) { + mbuf_resize(mbuf, mbuf->len); +} + +size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t) WEAK; +size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) { + char *p = NULL; + + assert(a != NULL); + assert(a->len <= a->size); + assert(off <= a->len); + + /* check overflow */ + if (~(size_t) 0 - (size_t) a->buf < len) return 0; + + if (a->len + len <= a->size) { + memmove(a->buf + off + len, a->buf + off, a->len - off); + if (buf != NULL) { + memcpy(a->buf + off, buf, len); + } + a->len += len; + } else { + size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER); + if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) { + a->buf = p; + memmove(a->buf + off + len, a->buf + off, a->len - off); + if (buf != NULL) memcpy(a->buf + off, buf, len); + a->len += len; + a->size = new_size; + } else { + len = 0; + } + } + + return len; +} + +size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) WEAK; +size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) { + return mbuf_insert(a, a->len, buf, len); +} + +void mbuf_remove(struct mbuf *mb, size_t n) WEAK; +void mbuf_remove(struct mbuf *mb, size_t n) { + if (n > 0 && n <= mb->len) { + memmove(mb->buf, mb->buf + n, mb->len - n); + mb->len -= n; + } +} + +#endif /* EXCLUDE_COMMON */ +#ifdef MG_MODULE_LINES +#line 1 "common/mg_str.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "common/mg_str.h" */ + +#include +#include + +int mg_ncasecmp(const char *s1, const char *s2, size_t len) WEAK; + +struct mg_str mg_mk_str(const char *s) WEAK; +struct mg_str mg_mk_str(const char *s) { + struct mg_str ret = {s, 0}; + if (s != NULL) ret.len = strlen(s); + return ret; +} + +struct mg_str mg_mk_str_n(const char *s, size_t len) WEAK; +struct mg_str mg_mk_str_n(const char *s, size_t len) { + struct mg_str ret = {s, len}; + return ret; +} + +int mg_vcmp(const struct mg_str *str1, const char *str2) WEAK; +int mg_vcmp(const struct mg_str *str1, const char *str2) { + size_t n2 = strlen(str2), n1 = str1->len; + int r = memcmp(str1->p, str2, (n1 < n2) ? n1 : n2); + if (r == 0) { + return n1 - n2; + } + return r; +} + +int mg_vcasecmp(const struct mg_str *str1, const char *str2) WEAK; +int mg_vcasecmp(const struct mg_str *str1, const char *str2) { + size_t n2 = strlen(str2), n1 = str1->len; + int r = mg_ncasecmp(str1->p, str2, (n1 < n2) ? n1 : n2); + if (r == 0) { + return n1 - n2; + } + return r; +} + +struct mg_str mg_strdup(const struct mg_str s) WEAK; +struct mg_str mg_strdup(const struct mg_str s) { + struct mg_str r = {NULL, 0}; + if (s.len > 0 && s.p != NULL) { + r.p = (char *) malloc(s.len); + if (r.p != NULL) { + memcpy((char *) r.p, s.p, s.len); + r.len = s.len; + } + } + return r; +} + +int mg_strcmp(const struct mg_str str1, const struct mg_str str2) WEAK; +int mg_strcmp(const struct mg_str str1, const struct mg_str str2) { + size_t i = 0; + while (i < str1.len && i < str2.len) { + if (str1.p[i] < str2.p[i]) return -1; + if (str1.p[i] > str2.p[i]) return 1; + i++; + } + if (i < str1.len) return 1; + if (i < str2.len) return -1; + return 0; +} + +int mg_strncmp(const struct mg_str, const struct mg_str, size_t n) WEAK; +int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n) { + struct mg_str s1 = str1; + struct mg_str s2 = str2; + + if (s1.len > n) { + s1.len = n; + } + if (s2.len > n) { + s2.len = n; + } + return mg_strcmp(s1, s2); +} +#ifdef MG_MODULE_LINES +#line 1 "common/sha1.c" +#endif +/* Copyright(c) By Steve Reid */ +/* 100% Public Domain */ + +/* Amalgamated: #include "common/sha1.h" */ + +#if !DISABLE_SHA1 && !defined(EXCLUDE_COMMON) + +/* Amalgamated: #include "common/cs_endian.h" */ + +#define SHA1HANDSOFF +#if defined(__sun) +/* Amalgamated: #include "common/solarisfixes.h" */ +#endif + +union char64long16 { + unsigned char c[64]; + uint32_t l[16]; +}; + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +static uint32_t blk0(union char64long16 *block, int i) { +/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */ +#if BYTE_ORDER == LITTLE_ENDIAN + block->l[i] = + (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF); +#endif + return block->l[i]; +} + +/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */ +#undef blk +#undef R0 +#undef R1 +#undef R2 +#undef R3 +#undef R4 + +#define blk(i) \ + (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \ + block->l[(i + 2) & 15] ^ block->l[i & 15], \ + 1)) +#define R0(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R1(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R2(v, w, x, y, z, i) \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ + w = rol(w, 30); +#define R3(v, w, x, y, z, i) \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); +#define R4(v, w, x, y, z, i) \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w = rol(w, 30); + +void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) { + uint32_t a, b, c, d, e; + union char64long16 block[1]; + + memcpy(block, buffer, 64); + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Erase working structures. The order of operations is important, + * used to ensure that compiler doesn't optimize those out. */ + memset(block, 0, sizeof(block)); + a = b = c = d = e = 0; + (void) a; + (void) b; + (void) c; + (void) d; + (void) e; +} + +void cs_sha1_init(cs_sha1_ctx *context) { + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + +void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data, + uint32_t len) { + uint32_t i, j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) context->count[1]++; + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64 - j)); + cs_sha1_transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) { + cs_sha1_transform(context->state, &data[i]); + } + j = 0; + } else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + +void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) { + unsigned i; + unsigned char finalcount[8], c; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> + ((3 - (i & 3)) * 8)) & + 255); + } + c = 0200; + cs_sha1_update(context, &c, 1); + while ((context->count[0] & 504) != 448) { + c = 0000; + cs_sha1_update(context, &c, 1); + } + cs_sha1_update(context, finalcount, 8); + for (i = 0; i < 20; i++) { + digest[i] = + (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +void cs_hmac_sha1(const unsigned char *key, size_t keylen, + const unsigned char *data, size_t datalen, + unsigned char out[20]) { + cs_sha1_ctx ctx; + unsigned char buf1[64], buf2[64], tmp_key[20], i; + + if (keylen > sizeof(buf1)) { + cs_sha1_init(&ctx); + cs_sha1_update(&ctx, key, keylen); + cs_sha1_final(tmp_key, &ctx); + key = tmp_key; + keylen = sizeof(tmp_key); + } + + memset(buf1, 0, sizeof(buf1)); + memset(buf2, 0, sizeof(buf2)); + memcpy(buf1, key, keylen); + memcpy(buf2, key, keylen); + + for (i = 0; i < sizeof(buf1); i++) { + buf1[i] ^= 0x36; + buf2[i] ^= 0x5c; + } + + cs_sha1_init(&ctx); + cs_sha1_update(&ctx, buf1, sizeof(buf1)); + cs_sha1_update(&ctx, data, datalen); + cs_sha1_final(out, &ctx); + + cs_sha1_init(&ctx); + cs_sha1_update(&ctx, buf2, sizeof(buf2)); + cs_sha1_update(&ctx, out, 20); + cs_sha1_final(out, &ctx); +} + +#endif /* EXCLUDE_COMMON */ +#ifdef MG_MODULE_LINES +#line 1 "common/str_util.c" +#endif +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + */ + +#ifndef EXCLUDE_COMMON + +/* Amalgamated: #include "common/platform.h" */ +/* Amalgamated: #include "common/str_util.h" */ + +#ifndef C_DISABLE_BUILTIN_SNPRINTF +#define C_DISABLE_BUILTIN_SNPRINTF 0 +#endif + +#ifndef MG_MALLOC +#define MG_MALLOC malloc +#endif + +#ifndef MG_FREE +#define MG_FREE free +#endif + +size_t c_strnlen(const char *s, size_t maxlen) WEAK; +size_t c_strnlen(const char *s, size_t maxlen) { + size_t l = 0; + for (; l < maxlen && s[l] != '\0'; l++) { + } + return l; +} + +#define C_SNPRINTF_APPEND_CHAR(ch) \ + do { \ + if (i < (int) buf_size) buf[i] = ch; \ + i++; \ + } while (0) + +#define C_SNPRINTF_FLAG_ZERO 1 + +#if C_DISABLE_BUILTIN_SNPRINTF +int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) WEAK; +int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) { + return vsnprintf(buf, buf_size, fmt, ap); +} +#else +static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags, + int field_width) { + char tmp[40]; + int i = 0, k = 0, neg = 0; + + if (num < 0) { + neg++; + num = -num; + } + + /* Print into temporary buffer - in reverse order */ + do { + int rem = num % base; + if (rem < 10) { + tmp[k++] = '0' + rem; + } else { + tmp[k++] = 'a' + (rem - 10); + } + num /= base; + } while (num > 0); + + /* Zero padding */ + if (flags && C_SNPRINTF_FLAG_ZERO) { + while (k < field_width && k < (int) sizeof(tmp) - 1) { + tmp[k++] = '0'; + } + } + + /* And sign */ + if (neg) { + tmp[k++] = '-'; + } + + /* Now output */ + while (--k >= 0) { + C_SNPRINTF_APPEND_CHAR(tmp[k]); + } + + return i; +} + +int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) WEAK; +int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) { + int ch, i = 0, len_mod, flags, precision, field_width; + + while ((ch = *fmt++) != '\0') { + if (ch != '%') { + C_SNPRINTF_APPEND_CHAR(ch); + } else { + /* + * Conversion specification: + * zero or more flags (one of: # 0 - + ') + * an optional minimum field width (digits) + * an optional precision (. followed by digits, or *) + * an optional length modifier (one of: hh h l ll L q j z t) + * conversion specifier (one of: d i o u x X e E f F g G a A c s p n) + */ + flags = field_width = precision = len_mod = 0; + + /* Flags. only zero-pad flag is supported. */ + if (*fmt == '0') { + flags |= C_SNPRINTF_FLAG_ZERO; + } + + /* Field width */ + while (*fmt >= '0' && *fmt <= '9') { + field_width *= 10; + field_width += *fmt++ - '0'; + } + /* Dynamic field width */ + if (*fmt == '*') { + field_width = va_arg(ap, int); + fmt++; + } + + /* Precision */ + if (*fmt == '.') { + fmt++; + if (*fmt == '*') { + precision = va_arg(ap, int); + fmt++; + } else { + while (*fmt >= '0' && *fmt <= '9') { + precision *= 10; + precision += *fmt++ - '0'; + } + } + } + + /* Length modifier */ + switch (*fmt) { + case 'h': + case 'l': + case 'L': + case 'I': + case 'q': + case 'j': + case 'z': + case 't': + len_mod = *fmt++; + if (*fmt == 'h') { + len_mod = 'H'; + fmt++; + } + if (*fmt == 'l') { + len_mod = 'q'; + fmt++; + } + break; + } + + ch = *fmt++; + if (ch == 's') { + const char *s = va_arg(ap, const char *); /* Always fetch parameter */ + int j; + int pad = field_width - (precision >= 0 ? c_strnlen(s, precision) : 0); + for (j = 0; j < pad; j++) { + C_SNPRINTF_APPEND_CHAR(' '); + } + + /* `s` may be NULL in case of %.*s */ + if (s != NULL) { + /* Ignore negative and 0 precisions */ + for (j = 0; (precision <= 0 || j < precision) && s[j] != '\0'; j++) { + C_SNPRINTF_APPEND_CHAR(s[j]); + } + } + } else if (ch == 'c') { + ch = va_arg(ap, int); /* Always fetch parameter */ + C_SNPRINTF_APPEND_CHAR(ch); + } else if (ch == 'd' && len_mod == 0) { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, int), 10, flags, + field_width); + } else if (ch == 'd' && len_mod == 'l') { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, long), 10, flags, + field_width); +#ifdef SSIZE_MAX + } else if (ch == 'd' && len_mod == 'z') { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, ssize_t), 10, flags, + field_width); +#endif + } else if (ch == 'd' && len_mod == 'q') { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, int64_t), 10, flags, + field_width); + } else if ((ch == 'x' || ch == 'u') && len_mod == 0) { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned), + ch == 'x' ? 16 : 10, flags, field_width); + } else if ((ch == 'x' || ch == 'u') && len_mod == 'l') { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned long), + ch == 'x' ? 16 : 10, flags, field_width); + } else if ((ch == 'x' || ch == 'u') && len_mod == 'z') { + i += c_itoa(buf + i, buf_size - i, va_arg(ap, size_t), + ch == 'x' ? 16 : 10, flags, field_width); + } else if (ch == 'p') { + unsigned long num = (unsigned long) (uintptr_t) va_arg(ap, void *); + C_SNPRINTF_APPEND_CHAR('0'); + C_SNPRINTF_APPEND_CHAR('x'); + i += c_itoa(buf + i, buf_size - i, num, 16, flags, 0); + } else { +#ifndef NO_LIBC + /* + * TODO(lsm): abort is not nice in a library, remove it + * Also, ESP8266 SDK doesn't have it + */ + abort(); +#endif + } + } + } + + /* Zero-terminate the result */ + if (buf_size > 0) { + buf[i < (int) buf_size ? i : (int) buf_size - 1] = '\0'; + } + + return i; +} +#endif + +int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) WEAK; +int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = c_vsnprintf(buf, buf_size, fmt, ap); + va_end(ap); + return result; +} + +#ifdef _WIN32 +int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) { + int ret; + char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p; + + strncpy(buf, path, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + + /* Trim trailing slashes. Leave backslash for paths like "X:\" */ + p = buf + strlen(buf) - 1; + while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0'; + + memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); + ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len); + + /* + * Convert back to Unicode. If doubly-converted string does not match the + * original, something is fishy, reject. + */ + WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2), + NULL, NULL); + if (strcmp(buf, buf2) != 0) { + wbuf[0] = L'\0'; + ret = 0; + } + + return ret; +} +#endif /* _WIN32 */ + +/* The simplest O(mn) algorithm. Better implementation are GPLed */ +const char *c_strnstr(const char *s, const char *find, size_t slen) WEAK; +const char *c_strnstr(const char *s, const char *find, size_t slen) { + size_t find_length = strlen(find); + size_t i; + + for (i = 0; i < slen; i++) { + if (i + find_length > slen) { + return NULL; + } + + if (strncmp(&s[i], find, find_length) == 0) { + return &s[i]; + } + } + + return NULL; +} + +#if CS_ENABLE_STRDUP +char *strdup(const char *src) WEAK; +char *strdup(const char *src) { + size_t len = strlen(src) + 1; + char *ret = malloc(len); + if (ret != NULL) { + strcpy(ret, src); + } + return ret; +} +#endif + +void cs_to_hex(char *to, const unsigned char *p, size_t len) WEAK; +void cs_to_hex(char *to, const unsigned char *p, size_t len) { + static const char *hex = "0123456789abcdef"; + + for (; len--; p++) { + *to++ = hex[p[0] >> 4]; + *to++ = hex[p[0] & 0x0f]; + } + *to = '\0'; +} + +static int fourbit(int ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + return ch - 'A' + 10; + } + return 0; +} + +void cs_from_hex(char *to, const char *p, size_t len) WEAK; +void cs_from_hex(char *to, const char *p, size_t len) { + size_t i; + + for (i = 0; i < len; i += 2) { + *to++ = (fourbit(p[i]) << 4) + fourbit(p[i + 1]); + } + *to = '\0'; +} + +#if CS_ENABLE_TO64 +int64_t cs_to64(const char *s) WEAK; +int64_t cs_to64(const char *s) { + int64_t result = 0; + int64_t neg = 1; + while (*s && isspace((unsigned char) *s)) s++; + if (*s == '-') { + neg = -1; + s++; + } + while (isdigit((unsigned char) *s)) { + result *= 10; + result += (*s - '0'); + s++; + } + return result * neg; +} +#endif + +static int str_util_lowercase(const char *s) { + return tolower(*(const unsigned char *) s); +} + +int mg_ncasecmp(const char *s1, const char *s2, size_t len) WEAK; +int mg_ncasecmp(const char *s1, const char *s2, size_t len) { + int diff = 0; + + if (len > 0) do { + diff = str_util_lowercase(s1++) - str_util_lowercase(s2++); + } while (diff == 0 && s1[-1] != '\0' && --len > 0); + + return diff; +} + +int mg_casecmp(const char *s1, const char *s2) WEAK; +int mg_casecmp(const char *s1, const char *s2) { + return mg_ncasecmp(s1, s2, (size_t) ~0); +} + +int mg_asprintf(char **buf, size_t size, const char *fmt, ...) WEAK; +int mg_asprintf(char **buf, size_t size, const char *fmt, ...) { + int ret; + va_list ap; + va_start(ap, fmt); + ret = mg_avprintf(buf, size, fmt, ap); + va_end(ap); + return ret; +} + +int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap) WEAK; +int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap) { + va_list ap_copy; + int len; + + va_copy(ap_copy, ap); + len = vsnprintf(*buf, size, fmt, ap_copy); + va_end(ap_copy); + + if (len < 0) { + /* eCos and Windows are not standard-compliant and return -1 when + * the buffer is too small. Keep allocating larger buffers until we + * succeed or out of memory. */ + *buf = NULL; /* LCOV_EXCL_START */ + while (len < 0) { + MG_FREE(*buf); + size *= 2; + if ((*buf = (char *) MG_MALLOC(size)) == NULL) break; + va_copy(ap_copy, ap); + len = vsnprintf(*buf, size, fmt, ap_copy); + va_end(ap_copy); + } + /* LCOV_EXCL_STOP */ + } else if (len >= (int) size) { + /* Standard-compliant code path. Allocate a buffer that is large enough. */ + if ((*buf = (char *) MG_MALLOC(len + 1)) == NULL) { + len = -1; /* LCOV_EXCL_LINE */ + } else { /* LCOV_EXCL_LINE */ + va_copy(ap_copy, ap); + len = vsnprintf(*buf, len + 1, fmt, ap_copy); + va_end(ap_copy); + } + } + + return len; +} + +#endif /* EXCLUDE_COMMON */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/tun.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_TUN_H_ +#define CS_MONGOOSE_SRC_TUN_H_ + +#if MG_ENABLE_TUN + +/* Amalgamated: #include "mongoose/src/net.h" */ +/* Amalgamated: #include "common/mg_str.h" */ + +#ifndef MG_TUN_RECONNECT_INTERVAL +#define MG_TUN_RECONNECT_INTERVAL 1 +#endif + +#define MG_TUN_PROTO_NAME "mg_tun" + +#define MG_TUN_DATA_FRAME 0x0 +#define MG_TUN_F_END_STREAM 0x1 + +/* + * MG TUN frame format is loosely based on HTTP/2. + * However since the communication happens via WebSocket + * there is no need to encode the frame length, since that's + * solved by WebSocket framing. + * + * TODO(mkm): Detailed description of the protocol. + */ +struct mg_tun_frame { + uint8_t type; + uint8_t flags; + uint32_t stream_id; /* opaque stream identifier */ + struct mg_str body; +}; + +struct mg_tun_ssl_opts { +#if MG_ENABLE_SSL + const char *ssl_cert; + const char *ssl_key; + const char *ssl_ca_cert; +#else + int dummy; /* some compilers don't like empty structs */ +#endif +}; + +struct mg_tun_client { + struct mg_mgr *mgr; + struct mg_iface *iface; + const char *disp_url; + struct mg_tun_ssl_opts ssl; + + uint32_t last_stream_id; /* stream id of most recently accepted connection */ + + struct mg_connection *disp; + struct mg_connection *listener; + struct mg_connection *reconnect; +}; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct mg_connection *mg_tun_bind_opt(struct mg_mgr *mgr, + const char *dispatcher, + mg_event_handler_t handler, + struct mg_bind_opts opts); + +int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame); + +void mg_tun_send_frame(struct mg_connection *ws, uint32_t stream_id, + uint8_t type, uint8_t flags, struct mg_str msg); + +void mg_tun_destroy_client(struct mg_tun_client *client); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_TUN */ + +#endif /* CS_MONGOOSE_SRC_TUN_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +/* Amalgamated: #include "common/cs_time.h" */ +/* Amalgamated: #include "mongoose/src/dns.h" */ +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/resolv.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ +/* Amalgamated: #include "mongoose/src/tun.h" */ + +#define MG_MAX_HOST_LEN 200 + +#define MG_COPY_COMMON_CONNECTION_OPTIONS(dst, src) \ + memcpy(dst, src, sizeof(*dst)); + +/* Which flags can be pre-set by the user at connection creation time. */ +#define _MG_ALLOWED_CONNECT_FLAGS_MASK \ + (MG_F_USER_1 | MG_F_USER_2 | MG_F_USER_3 | MG_F_USER_4 | MG_F_USER_5 | \ + MG_F_USER_6 | MG_F_WEBSOCKET_NO_DEFRAG | MG_F_ENABLE_BROADCAST) +/* Which flags should be modifiable by user's callbacks. */ +#define _MG_CALLBACK_MODIFIABLE_FLAGS_MASK \ + (MG_F_USER_1 | MG_F_USER_2 | MG_F_USER_3 | MG_F_USER_4 | MG_F_USER_5 | \ + MG_F_USER_6 | MG_F_WEBSOCKET_NO_DEFRAG | MG_F_SEND_AND_CLOSE | \ + MG_F_CLOSE_IMMEDIATELY | MG_F_IS_WEBSOCKET | MG_F_DELETE_CHUNK) + +#ifndef intptr_t +#define intptr_t long +#endif + +MG_INTERNAL void mg_add_conn(struct mg_mgr *mgr, struct mg_connection *c) { + DBG(("%p %p", mgr, c)); + c->mgr = mgr; + c->next = mgr->active_connections; + mgr->active_connections = c; + c->prev = NULL; + if (c->next != NULL) c->next->prev = c; + if (c->sock != INVALID_SOCKET) { + c->iface->vtable->add_conn(c); + } +} + +MG_INTERNAL void mg_remove_conn(struct mg_connection *conn) { + if (conn->prev == NULL) conn->mgr->active_connections = conn->next; + if (conn->prev) conn->prev->next = conn->next; + if (conn->next) conn->next->prev = conn->prev; + conn->iface->vtable->remove_conn(conn); +} + +MG_INTERNAL void mg_call(struct mg_connection *nc, + mg_event_handler_t ev_handler, int ev, void *ev_data) { + if (ev_handler == NULL) { + /* + * If protocol handler is specified, call it. Otherwise, call user-specified + * event handler. + */ + ev_handler = nc->proto_handler ? nc->proto_handler : nc->handler; + } + if (ev != MG_EV_POLL) { + DBG(("%p %s ev=%d ev_data=%p flags=%lu rmbl=%d smbl=%d", nc, + ev_handler == nc->handler ? "user" : "proto", ev, ev_data, nc->flags, + (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); + } + +#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP + /* LCOV_EXCL_START */ + if (nc->mgr->hexdump_file != NULL && ev != MG_EV_POLL && + ev != MG_EV_SEND /* handled separately */) { + if (ev == MG_EV_RECV) { + mg_hexdump_connection(nc, nc->mgr->hexdump_file, nc->recv_mbuf.buf, + *(int *) ev_data, ev); + } else { + mg_hexdump_connection(nc, nc->mgr->hexdump_file, NULL, 0, ev); + } + } +/* LCOV_EXCL_STOP */ +#endif + if (ev_handler != NULL) { + unsigned long flags_before = nc->flags; + size_t recv_mbuf_before = nc->recv_mbuf.len, recved; + ev_handler(nc, ev, ev_data); + recved = (recv_mbuf_before - nc->recv_mbuf.len); + /* Prevent user handler from fiddling with system flags. */ + if (ev_handler == nc->handler && nc->flags != flags_before) { + nc->flags = (flags_before & ~_MG_CALLBACK_MODIFIABLE_FLAGS_MASK) | + (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); + } + if (recved > 0 && !(nc->flags & MG_F_UDP)) { + nc->iface->vtable->recved(nc, recved); + } + } + if (ev != MG_EV_POLL) { + DBG(("%p after %s flags=%lu rmbl=%d smbl=%d", nc, + ev_handler == nc->handler ? "user" : "proto", nc->flags, + (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); + } +} + +void mg_if_timer(struct mg_connection *c, double now) { + if (c->ev_timer_time > 0 && now >= c->ev_timer_time) { + double old_value = c->ev_timer_time; + mg_call(c, NULL, MG_EV_TIMER, &now); + /* + * To prevent timer firing all the time, reset the timer after delivery. + * However, in case user sets it to new value, do not reset. + */ + if (c->ev_timer_time == old_value) { + c->ev_timer_time = 0; + } + } +} + +void mg_if_poll(struct mg_connection *nc, time_t now) { + if (!(nc->flags & MG_F_SSL) || (nc->flags & MG_F_SSL_HANDSHAKE_DONE)) { + mg_call(nc, NULL, MG_EV_POLL, &now); + } +} + +static void mg_destroy_conn(struct mg_connection *conn, int destroy_if) { + if (destroy_if) conn->iface->vtable->destroy_conn(conn); + if (conn->proto_data != NULL && conn->proto_data_destructor != NULL) { + conn->proto_data_destructor(conn->proto_data); + } +#if MG_ENABLE_SSL + mg_ssl_if_conn_free(conn); +#endif + mbuf_free(&conn->recv_mbuf); + mbuf_free(&conn->send_mbuf); + + memset(conn, 0, sizeof(*conn)); + MG_FREE(conn); +} + +void mg_close_conn(struct mg_connection *conn) { + DBG(("%p %lu %d", conn, conn->flags, conn->sock)); + mg_remove_conn(conn); + conn->iface->vtable->destroy_conn(conn); + mg_call(conn, NULL, MG_EV_CLOSE, NULL); + mg_destroy_conn(conn, 0 /* destroy_if */); +} + +void mg_mgr_init(struct mg_mgr *m, void *user_data) { + struct mg_mgr_init_opts opts; + memset(&opts, 0, sizeof(opts)); + mg_mgr_init_opt(m, user_data, opts); +} + +void mg_mgr_init_opt(struct mg_mgr *m, void *user_data, + struct mg_mgr_init_opts opts) { + memset(m, 0, sizeof(*m)); +#if MG_ENABLE_BROADCAST + m->ctl[0] = m->ctl[1] = INVALID_SOCKET; +#endif + m->user_data = user_data; + +#ifdef _WIN32 + { + WSADATA data; + WSAStartup(MAKEWORD(2, 2), &data); + } +#elif defined(__unix__) + /* Ignore SIGPIPE signal, so if client cancels the request, it + * won't kill the whole process. */ + signal(SIGPIPE, SIG_IGN); +#endif + +#if MG_ENABLE_SSL + { + static int init_done; + if (!init_done) { + mg_ssl_if_init(); + init_done++; + } + } +#endif + { + int i; + if (opts.num_ifaces == 0) { + opts.num_ifaces = mg_num_ifaces; + opts.ifaces = mg_ifaces; + } + if (opts.main_iface != NULL) { + opts.ifaces[MG_MAIN_IFACE] = opts.main_iface; + } + m->num_ifaces = opts.num_ifaces; + m->ifaces = + (struct mg_iface **) MG_MALLOC(sizeof(*m->ifaces) * opts.num_ifaces); + for (i = 0; i < mg_num_ifaces; i++) { + m->ifaces[i] = mg_if_create_iface(opts.ifaces[i], m); + m->ifaces[i]->vtable->init(m->ifaces[i]); + } + } + DBG(("==================================")); + DBG(("init mgr=%p", m)); +} + +#if MG_ENABLE_JAVASCRIPT +static enum v7_err mg_send_js(struct v7 *v7, v7_val_t *res) { + v7_val_t arg0 = v7_arg(v7, 0); + v7_val_t arg1 = v7_arg(v7, 1); + struct mg_connection *c = (struct mg_connection *) v7_get_ptr(v7, arg0); + size_t len = 0; + + if (v7_is_string(arg1)) { + const char *data = v7_get_string(v7, &arg1, &len); + mg_send(c, data, len); + } + + *res = v7_mk_number(v7, len); + + return V7_OK; +} + +enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7, + const char *init_file_name) { + v7_val_t v; + m->v7 = v7; + v7_set_method(v7, v7_get_global(v7), "mg_send", mg_send_js); + return v7_exec_file(v7, init_file_name, &v); +} +#endif + +void mg_mgr_free(struct mg_mgr *m) { + struct mg_connection *conn, *tmp_conn; + + DBG(("%p", m)); + if (m == NULL) return; + /* Do one last poll, see https://github.com/cesanta/mongoose/issues/286 */ + mg_mgr_poll(m, 0); + +#if MG_ENABLE_BROADCAST + if (m->ctl[0] != INVALID_SOCKET) closesocket(m->ctl[0]); + if (m->ctl[1] != INVALID_SOCKET) closesocket(m->ctl[1]); + m->ctl[0] = m->ctl[1] = INVALID_SOCKET; +#endif + + for (conn = m->active_connections; conn != NULL; conn = tmp_conn) { + tmp_conn = conn->next; + mg_close_conn(conn); + } + + { + int i; + for (i = 0; i < m->num_ifaces; i++) { + m->ifaces[i]->vtable->free(m->ifaces[i]); + MG_FREE(m->ifaces[i]); + } + MG_FREE(m->ifaces); + } +} + +time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { + int i; + time_t now = 0; /* oh GCC, seriously ? */ + + if (m->num_ifaces == 0) { + LOG(LL_ERROR, ("cannot poll: no interfaces")); + return 0; + } + + for (i = 0; i < m->num_ifaces; i++) { + now = m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms); + } + return now; +} + +int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap) { + char mem[MG_VPRINTF_BUFFER_SIZE], *buf = mem; + int len; + + if ((len = mg_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) { + mg_send(nc, buf, len); + } + if (buf != mem && buf != NULL) { + MG_FREE(buf); /* LCOV_EXCL_LINE */ + } /* LCOV_EXCL_LINE */ + + return len; +} + +int mg_printf(struct mg_connection *conn, const char *fmt, ...) { + int len; + va_list ap; + va_start(ap, fmt); + len = mg_vprintf(conn, fmt, ap); + va_end(ap); + return len; +} + +#if MG_ENABLE_SYNC_RESOLVER +/* TODO(lsm): use non-blocking resolver */ +static int mg_resolve2(const char *host, struct in_addr *ina) { +#if MG_ENABLE_GETADDRINFO + int rv = 0; + struct addrinfo hints, *servinfo, *p; + struct sockaddr_in *h = NULL; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + if ((rv = getaddrinfo(host, NULL, NULL, &servinfo)) != 0) { + DBG(("getaddrinfo(%s) failed: %s", host, strerror(mg_get_errno()))); + return 0; + } + for (p = servinfo; p != NULL; p = p->ai_next) { + memcpy(&h, &p->ai_addr, sizeof(struct sockaddr_in *)); + memcpy(ina, &h->sin_addr, sizeof(ina)); + } + freeaddrinfo(servinfo); + return 1; +#else + struct hostent *he; + if ((he = gethostbyname(host)) == NULL) { + DBG(("gethostbyname(%s) failed: %s", host, strerror(mg_get_errno()))); + } else { + memcpy(ina, he->h_addr_list[0], sizeof(*ina)); + return 1; + } + return 0; +#endif /* MG_ENABLE_GETADDRINFO */ +} + +int mg_resolve(const char *host, char *buf, size_t n) { + struct in_addr ad; + return mg_resolve2(host, &ad) ? snprintf(buf, n, "%s", inet_ntoa(ad)) : 0; +} +#endif /* MG_ENABLE_SYNC_RESOLVER */ + +MG_INTERNAL struct mg_connection *mg_create_connection_base( + struct mg_mgr *mgr, mg_event_handler_t callback, + struct mg_add_sock_opts opts) { + struct mg_connection *conn; + + if ((conn = (struct mg_connection *) MG_CALLOC(1, sizeof(*conn))) != NULL) { + conn->sock = INVALID_SOCKET; + conn->handler = callback; + conn->mgr = mgr; + conn->last_io_time = (time_t) mg_time(); + conn->iface = + (opts.iface != NULL ? opts.iface : mgr->ifaces[MG_MAIN_IFACE]); + conn->flags = opts.flags & _MG_ALLOWED_CONNECT_FLAGS_MASK; + conn->user_data = opts.user_data; + /* + * SIZE_MAX is defined as a long long constant in + * system headers on some platforms and so it + * doesn't compile with pedantic ansi flags. + */ + conn->recv_mbuf_limit = ~0; + } else { + MG_SET_PTRPTR(opts.error_string, "failed to create connection"); + } + + return conn; +} + +MG_INTERNAL struct mg_connection *mg_create_connection( + struct mg_mgr *mgr, mg_event_handler_t callback, + struct mg_add_sock_opts opts) { + struct mg_connection *conn = mg_create_connection_base(mgr, callback, opts); + + if (conn != NULL && !conn->iface->vtable->create_conn(conn)) { + MG_FREE(conn); + conn = NULL; + } + if (conn == NULL) { + MG_SET_PTRPTR(opts.error_string, "failed to init connection"); + } + + return conn; +} + +/* + * Address format: [PROTO://][HOST]:PORT + * + * HOST could be IPv4/IPv6 address or a host name. + * `host` is a destination buffer to hold parsed HOST part. Shoud be at least + * MG_MAX_HOST_LEN bytes long. + * `proto` is a returned socket type, either SOCK_STREAM or SOCK_DGRAM + * + * Return: + * -1 on parse error + * 0 if HOST needs DNS lookup + * >0 length of the address string + */ +MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, + int *proto, char *host, size_t host_len) { + unsigned int a, b, c, d, port = 0; + int ch, len = 0; +#if MG_ENABLE_IPV6 + char buf[100]; +#endif + + /* + * MacOS needs that. If we do not zero it, subsequent bind() will fail. + * Also, all-zeroes in the socket address means binding to all addresses + * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). + */ + memset(sa, 0, sizeof(*sa)); + sa->sin.sin_family = AF_INET; + + *proto = SOCK_STREAM; + + if (strncmp(str, "udp://", 6) == 0) { + str += 6; + *proto = SOCK_DGRAM; + } else if (strncmp(str, "tcp://", 6) == 0) { + str += 6; + } + + if (sscanf(str, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len) == 5) { + /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */ + sa->sin.sin_addr.s_addr = + htonl(((uint32_t) a << 24) | ((uint32_t) b << 16) | c << 8 | d); + sa->sin.sin_port = htons((uint16_t) port); +#if MG_ENABLE_IPV6 + } else if (sscanf(str, "[%99[^]]]:%u%n", buf, &port, &len) == 2 && + inet_pton(AF_INET6, buf, &sa->sin6.sin6_addr)) { + /* IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080 */ + sa->sin6.sin6_family = AF_INET6; + sa->sin.sin_port = htons((uint16_t) port); +#endif +#if MG_ENABLE_ASYNC_RESOLVER + } else if (strlen(str) < host_len && + sscanf(str, "%[^ :]:%u%n", host, &port, &len) == 2) { + sa->sin.sin_port = htons((uint16_t) port); + if (mg_resolve_from_hosts_file(host, sa) != 0) { + /* + * if resolving from hosts file failed and the host + * we are trying to resolve is `localhost` - we should + * try to resolve it using `gethostbyname` and do not try + * to resolve it via DNS server if gethostbyname has failed too + */ + if (mg_ncasecmp(host, "localhost", 9) != 0) { + return 0; + } + +#if MG_ENABLE_SYNC_RESOLVER + if (!mg_resolve2(host, &sa->sin.sin_addr)) { + return -1; + } +#else + return -1; +#endif + } +#endif + } else if (sscanf(str, ":%u%n", &port, &len) == 1 || + sscanf(str, "%u%n", &port, &len) == 1) { + /* If only port is specified, bind to IPv4, INADDR_ANY */ + sa->sin.sin_port = htons((uint16_t) port); + } else { + return -1; + } + + /* Required for MG_ENABLE_ASYNC_RESOLVER=0 */ + (void) host; + (void) host_len; + + ch = str[len]; /* Character that follows the address */ + return port < 0xffffUL && (ch == '\0' || ch == ',' || isspace(ch)) ? len : -1; +} + +struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc) { + struct mg_add_sock_opts opts; + struct mg_connection *nc; + memset(&opts, 0, sizeof(opts)); + nc = mg_create_connection(lc->mgr, lc->handler, opts); + if (nc == NULL) return NULL; + nc->listener = lc; + nc->proto_handler = lc->proto_handler; + nc->user_data = lc->user_data; + nc->recv_mbuf_limit = lc->recv_mbuf_limit; + nc->iface = lc->iface; + if (lc->flags & MG_F_SSL) nc->flags |= MG_F_SSL; + mg_add_conn(nc->mgr, nc); + DBG(("%p %p %d %d", lc, nc, nc->sock, (int) nc->flags)); + return nc; +} + +void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa, + size_t sa_len) { + (void) sa_len; + nc->sa = *sa; + mg_call(nc, NULL, MG_EV_ACCEPT, &nc->sa); +} + +void mg_send(struct mg_connection *nc, const void *buf, int len) { + nc->last_io_time = (time_t) mg_time(); + if (nc->flags & MG_F_UDP) { + nc->iface->vtable->udp_send(nc, buf, len); + } else { + nc->iface->vtable->tcp_send(nc, buf, len); + } +#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP + if (nc->mgr && nc->mgr->hexdump_file != NULL) { + mg_hexdump_connection(nc, nc->mgr->hexdump_file, buf, len, MG_EV_SEND); + } +#endif +} + +void mg_if_sent_cb(struct mg_connection *nc, int num_sent) { + if (num_sent < 0) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } + mg_call(nc, NULL, MG_EV_SEND, &num_sent); +} + +MG_INTERNAL void mg_recv_common(struct mg_connection *nc, void *buf, int len, + int own) { + DBG(("%p %d %u", nc, len, (unsigned int) nc->recv_mbuf.len)); + if (nc->flags & MG_F_CLOSE_IMMEDIATELY) { + DBG(("%p discarded %d bytes", nc, len)); + /* + * This connection will not survive next poll. Do not deliver events, + * send data to /dev/null without acking. + */ + if (own) { + MG_FREE(buf); + } + return; + } + nc->last_io_time = (time_t) mg_time(); + if (!own) { + mbuf_append(&nc->recv_mbuf, buf, len); + } else if (nc->recv_mbuf.len == 0) { + /* Adopt buf as recv_mbuf's backing store. */ + mbuf_free(&nc->recv_mbuf); + nc->recv_mbuf.buf = (char *) buf; + nc->recv_mbuf.size = nc->recv_mbuf.len = len; + } else { + mbuf_append(&nc->recv_mbuf, buf, len); + MG_FREE(buf); + } + mg_call(nc, NULL, MG_EV_RECV, &len); +} + +void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len, int own) { + mg_recv_common(nc, buf, len, own); +} + +void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, + union socket_address *sa, size_t sa_len) { + assert(nc->flags & MG_F_UDP); + DBG(("%p %u", nc, (unsigned int) len)); + if (nc->flags & MG_F_LISTENING) { + struct mg_connection *lc = nc; + /* + * Do we have an existing connection for this source? + * This is very inefficient for long connection lists. + */ + for (nc = mg_next(lc->mgr, NULL); nc != NULL; nc = mg_next(lc->mgr, nc)) { + if (memcmp(&nc->sa.sa, &sa->sa, sa_len) == 0 && nc->listener == lc) { + break; + } + } + if (nc == NULL) { + struct mg_add_sock_opts opts; + memset(&opts, 0, sizeof(opts)); + /* Create fake connection w/out sock initialization */ + nc = mg_create_connection_base(lc->mgr, lc->handler, opts); + if (nc != NULL) { + nc->sock = lc->sock; + nc->listener = lc; + nc->sa = *sa; + nc->proto_handler = lc->proto_handler; + nc->user_data = lc->user_data; + nc->recv_mbuf_limit = lc->recv_mbuf_limit; + nc->flags = MG_F_UDP; + /* + * Long-lived UDP "connections" i.e. interactions that involve more + * than one request and response are rare, most are transactional: + * response is sent and the "connection" is closed. Or - should be. + * But users (including ourselves) tend to forget about that part, + * because UDP is connectionless and one does not think about + * processing a UDP request as handling a connection that needs to be + * closed. Thus, we begin with SEND_AND_CLOSE flag set, which should + * be a reasonable default for most use cases, but it is possible to + * turn it off the connection should be kept alive after processing. + */ + nc->flags |= MG_F_SEND_AND_CLOSE; + mg_add_conn(lc->mgr, nc); + mg_call(nc, NULL, MG_EV_ACCEPT, &nc->sa); + } else { + DBG(("OOM")); + /* No return here, we still need to drop on the floor */ + } + } + } + if (nc != NULL) { + mg_recv_common(nc, buf, len, 1); + } else { + /* Drop on the floor. */ + MG_FREE(buf); + nc->iface->vtable->recved(nc, len); + } +} + +/* + * Schedules an async connect for a resolved address and proto. + * Called from two places: `mg_connect_opt()` and from async resolver. + * When called from the async resolver, it must trigger `MG_EV_CONNECT` event + * with a failure flag to indicate connection failure. + */ +MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc, + int proto, + union socket_address *sa) { + DBG(("%p %s://%s:%hu", nc, proto == SOCK_DGRAM ? "udp" : "tcp", + inet_ntoa(sa->sin.sin_addr), ntohs(sa->sin.sin_port))); + + nc->flags |= MG_F_CONNECTING; + if (proto == SOCK_DGRAM) { + nc->iface->vtable->connect_udp(nc); + } else { + nc->iface->vtable->connect_tcp(nc, sa); + } + mg_add_conn(nc->mgr, nc); + return nc; +} + +void mg_if_connect_cb(struct mg_connection *nc, int err) { + DBG(("%p connect, err=%d", nc, err)); + nc->flags &= ~MG_F_CONNECTING; + if (err != 0) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } + mg_call(nc, NULL, MG_EV_CONNECT, &err); +} + +#if MG_ENABLE_ASYNC_RESOLVER +/* + * Callback for the async resolver on mg_connect_opt() call. + * Main task of this function is to trigger MG_EV_CONNECT event with + * either failure (and dealloc the connection) + * or success (and proceed with connect() + */ +static void resolve_cb(struct mg_dns_message *msg, void *data, + enum mg_resolve_err e) { + struct mg_connection *nc = (struct mg_connection *) data; + int i; + int failure = -1; + + nc->flags &= ~MG_F_RESOLVING; + if (msg != NULL) { + /* + * Take the first DNS A answer and run... + */ + for (i = 0; i < msg->num_answers; i++) { + if (msg->answers[i].rtype == MG_DNS_A_RECORD) { + /* + * Async resolver guarantees that there is at least one answer. + * TODO(lsm): handle IPv6 answers too + */ + mg_dns_parse_record_data(msg, &msg->answers[i], &nc->sa.sin.sin_addr, + 4); + mg_do_connect(nc, nc->flags & MG_F_UDP ? SOCK_DGRAM : SOCK_STREAM, + &nc->sa); + return; + } + } + } + + if (e == MG_RESOLVE_TIMEOUT) { + double now = mg_time(); + mg_call(nc, NULL, MG_EV_TIMER, &now); + } + + /* + * If we get there was no MG_DNS_A_RECORD in the answer + */ + mg_call(nc, NULL, MG_EV_CONNECT, &failure); + mg_call(nc, NULL, MG_EV_CLOSE, NULL); + mg_destroy_conn(nc, 1 /* destroy_if */); +} +#endif + +struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address, + mg_event_handler_t callback) { + struct mg_connect_opts opts; + memset(&opts, 0, sizeof(opts)); + return mg_connect_opt(mgr, address, callback, opts); +} + +struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, + mg_event_handler_t callback, + struct mg_connect_opts opts) { + struct mg_connection *nc = NULL; + int proto, rc; + struct mg_add_sock_opts add_sock_opts; + char host[MG_MAX_HOST_LEN]; + + MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts); + + if ((nc = mg_create_connection(mgr, callback, add_sock_opts)) == NULL) { + return NULL; + } + + if ((rc = mg_parse_address(address, &nc->sa, &proto, host, sizeof(host))) < + 0) { + /* Address is malformed */ + MG_SET_PTRPTR(opts.error_string, "cannot parse address"); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + + nc->flags |= opts.flags & _MG_ALLOWED_CONNECT_FLAGS_MASK; + nc->flags |= (proto == SOCK_DGRAM) ? MG_F_UDP : 0; + nc->user_data = opts.user_data; + +#if MG_ENABLE_SSL + DBG(("%p %s %s,%s,%s", nc, address, (opts.ssl_cert ? opts.ssl_cert : "-"), + (opts.ssl_key ? opts.ssl_key : "-"), + (opts.ssl_ca_cert ? opts.ssl_ca_cert : "-"))); + + if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) { + const char *err_msg = NULL; + struct mg_ssl_if_conn_params params; + if (nc->flags & MG_F_UDP) { + MG_SET_PTRPTR(opts.error_string, "SSL for UDP is not supported"); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + memset(¶ms, 0, sizeof(params)); + params.cert = opts.ssl_cert; + params.key = opts.ssl_key; + params.ca_cert = opts.ssl_ca_cert; + params.cipher_suites = opts.ssl_cipher_suites; + if (opts.ssl_ca_cert != NULL) { + if (opts.ssl_server_name != NULL) { + if (strcmp(opts.ssl_server_name, "*") != 0) { + params.server_name = opts.ssl_server_name; + } + } else if (rc == 0) { /* If it's a DNS name, use host. */ + params.server_name = host; + } + } + if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) { + MG_SET_PTRPTR(opts.error_string, err_msg); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + nc->flags |= MG_F_SSL; + } +#endif /* MG_ENABLE_SSL */ + + if (rc == 0) { +#if MG_ENABLE_ASYNC_RESOLVER + /* + * DNS resolution is required for host. + * mg_parse_address() fills port in nc->sa, which we pass to resolve_cb() + */ + struct mg_connection *dns_conn = NULL; + struct mg_resolve_async_opts o; + memset(&o, 0, sizeof(o)); + o.dns_conn = &dns_conn; + if (mg_resolve_async_opt(nc->mgr, host, MG_DNS_A_RECORD, resolve_cb, nc, + o) != 0) { + MG_SET_PTRPTR(opts.error_string, "cannot schedule DNS lookup"); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + nc->priv_2 = dns_conn; + nc->flags |= MG_F_RESOLVING; + return nc; +#else + MG_SET_PTRPTR(opts.error_string, "Resolver is disabled"); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; +#endif + } else { + /* Address is parsed and resolved to IP. proceed with connect() */ + return mg_do_connect(nc, proto, &nc->sa); + } +} + +struct mg_connection *mg_bind(struct mg_mgr *srv, const char *address, + mg_event_handler_t event_handler) { + struct mg_bind_opts opts; + memset(&opts, 0, sizeof(opts)); + return mg_bind_opt(srv, address, event_handler, opts); +} + +struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, + mg_event_handler_t callback, + struct mg_bind_opts opts) { + union socket_address sa; + struct mg_connection *nc = NULL; + int proto, rc; + struct mg_add_sock_opts add_sock_opts; + char host[MG_MAX_HOST_LEN]; + + MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts); + +#if MG_ENABLE_TUN + if (mg_strncmp(mg_mk_str(address), mg_mk_str("ws://"), 5) == 0 || + mg_strncmp(mg_mk_str(address), mg_mk_str("wss://"), 6) == 0) { + return mg_tun_bind_opt(mgr, address, callback, opts); + } +#endif + + if (mg_parse_address(address, &sa, &proto, host, sizeof(host)) <= 0) { + MG_SET_PTRPTR(opts.error_string, "cannot parse address"); + return NULL; + } + + nc = mg_create_connection(mgr, callback, add_sock_opts); + if (nc == NULL) { + return NULL; + } + + nc->sa = sa; + nc->flags |= MG_F_LISTENING; + if (proto == SOCK_DGRAM) nc->flags |= MG_F_UDP; + +#if MG_ENABLE_SSL + DBG(("%p %s %s,%s,%s", nc, address, (opts.ssl_cert ? opts.ssl_cert : "-"), + (opts.ssl_key ? opts.ssl_key : "-"), + (opts.ssl_ca_cert ? opts.ssl_ca_cert : "-"))); + + if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) { + const char *err_msg = NULL; + struct mg_ssl_if_conn_params params; + if (nc->flags & MG_F_UDP) { + MG_SET_PTRPTR(opts.error_string, "SSL for UDP is not supported"); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + memset(¶ms, 0, sizeof(params)); + params.cert = opts.ssl_cert; + params.key = opts.ssl_key; + params.ca_cert = opts.ssl_ca_cert; + params.cipher_suites = opts.ssl_cipher_suites; + if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) { + MG_SET_PTRPTR(opts.error_string, err_msg); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + nc->flags |= MG_F_SSL; + } +#endif /* MG_ENABLE_SSL */ + + if (nc->flags & MG_F_UDP) { + rc = nc->iface->vtable->listen_udp(nc, &nc->sa); + } else { + rc = nc->iface->vtable->listen_tcp(nc, &nc->sa); + } + if (rc != 0) { + DBG(("Failed to open listener: %d", rc)); + MG_SET_PTRPTR(opts.error_string, "failed to open listener"); + mg_destroy_conn(nc, 1 /* destroy_if */); + return NULL; + } + mg_add_conn(nc->mgr, nc); + + return nc; +} + +struct mg_connection *mg_next(struct mg_mgr *s, struct mg_connection *conn) { + return conn == NULL ? s->active_connections : conn->next; +} + +#if MG_ENABLE_BROADCAST +void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data, + size_t len) { + struct ctl_msg ctl_msg; + + /* + * Mongoose manager has a socketpair, `struct mg_mgr::ctl`, + * where `mg_broadcast()` pushes the message. + * `mg_mgr_poll()` wakes up, reads a message from the socket pair, and calls + * specified callback for each connection. Thus the callback function executes + * in event manager thread. + */ + if (mgr->ctl[0] != INVALID_SOCKET && data != NULL && + len < sizeof(ctl_msg.message)) { + size_t dummy; + + ctl_msg.callback = cb; + memcpy(ctl_msg.message, data, len); + dummy = MG_SEND_FUNC(mgr->ctl[0], (char *) &ctl_msg, + offsetof(struct ctl_msg, message) + len, 0); + dummy = MG_RECV_FUNC(mgr->ctl[0], (char *) &len, 1, 0); + (void) dummy; /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509 */ + } +} +#endif /* MG_ENABLE_BROADCAST */ + +static int isbyte(int n) { + return n >= 0 && n <= 255; +} + +static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) { + int n, a, b, c, d, slash = 32, len = 0; + + if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 || + sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && + isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 && + slash < 33) { + len = n; + *net = + ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) | d; + *mask = slash ? 0xffffffffU << (32 - slash) : 0; + } + + return len; +} + +int mg_check_ip_acl(const char *acl, uint32_t remote_ip) { + int allowed, flag; + uint32_t net, mask; + struct mg_str vec; + + /* If any ACL is set, deny by default */ + allowed = (acl == NULL || *acl == '\0') ? '+' : '-'; + + while ((acl = mg_next_comma_list_entry(acl, &vec, NULL)) != NULL) { + flag = vec.p[0]; + if ((flag != '+' && flag != '-') || + parse_net(&vec.p[1], &net, &mask) == 0) { + return -1; + } + + if (net == (remote_ip & mask)) { + allowed = flag; + } + } + + DBG(("%08x %c", remote_ip, allowed)); + return allowed == '+'; +} + +/* Move data from one connection to another */ +void mg_forward(struct mg_connection *from, struct mg_connection *to) { + mg_send(to, from->recv_mbuf.buf, from->recv_mbuf.len); + mbuf_remove(&from->recv_mbuf, from->recv_mbuf.len); +} + +double mg_set_timer(struct mg_connection *c, double timestamp) { + double result = c->ev_timer_time; + c->ev_timer_time = timestamp; + /* + * If this connection is resolving, it's not in the list of active + * connections, so not processed yet. It has a DNS resolver connection + * linked to it. Set up a timer for the DNS connection. + */ + DBG(("%p %p %d -> %lu", c, c->priv_2, c->flags & MG_F_RESOLVING, + (unsigned long) timestamp)); + if ((c->flags & MG_F_RESOLVING) && c->priv_2 != NULL) { + ((struct mg_connection *) c->priv_2)->ev_timer_time = timestamp; + } + return result; +} + +void mg_sock_set(struct mg_connection *nc, sock_t sock) { + if (sock != INVALID_SOCKET) { + nc->iface->vtable->sock_set(nc, sock); + } +} + +void mg_if_get_conn_addr(struct mg_connection *nc, int remote, + union socket_address *sa) { + nc->iface->vtable->get_conn_addr(nc, remote, sa); +} + +struct mg_connection *mg_add_sock_opt(struct mg_mgr *s, sock_t sock, + mg_event_handler_t callback, + struct mg_add_sock_opts opts) { + struct mg_connection *nc = mg_create_connection_base(s, callback, opts); + if (nc != NULL) { + mg_sock_set(nc, sock); + mg_add_conn(nc->mgr, nc); + } + return nc; +} + +struct mg_connection *mg_add_sock(struct mg_mgr *s, sock_t sock, + mg_event_handler_t callback) { + struct mg_add_sock_opts opts; + memset(&opts, 0, sizeof(opts)); + return mg_add_sock_opt(s, sock, callback, opts); +} + +double mg_time(void) { + return cs_time(); +} +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net_if_socket.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_NET_IF_SOCKET_H_ +#define CS_MONGOOSE_SRC_NET_IF_SOCKET_H_ + +/* Amalgamated: #include "mongoose/src/net_if.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MG_ENABLE_NET_IF_SOCKET +#define MG_ENABLE_NET_IF_SOCKET MG_NET_IF == MG_NET_IF_SOCKET +#endif + +extern struct mg_iface_vtable mg_socket_iface_vtable; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_MONGOOSE_SRC_NET_IF_SOCKET_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net_if_tun.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_MONGOOSE_SRC_NET_IF_TUN_H_ +#define CS_MONGOOSE_SRC_NET_IF_TUN_H_ + +#if MG_ENABLE_TUN + +/* Amalgamated: #include "mongoose/src/net_if.h" */ + +struct mg_tun_client; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern struct mg_iface_vtable mg_tun_iface_vtable; + +struct mg_connection *mg_tun_if_find_conn(struct mg_tun_client *client, + uint32_t stream_id); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MG_ENABLE_TUN */ + +#endif /* CS_MONGOOSE_SRC_NET_IF_TUN_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net_if.c" +#endif +/* Amalgamated: #include "mongoose/src/net_if.h" */ +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/net_if_socket.h" */ +/* Amalgamated: #include "mongoose/src/net_if_tun.h" */ + +extern struct mg_iface_vtable mg_default_iface_vtable; + +#if MG_ENABLE_TUN +struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable, + &mg_tun_iface_vtable}; +#else +struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable}; +#endif + +int mg_num_ifaces = (int) (sizeof(mg_ifaces) / sizeof(mg_ifaces[0])); + +struct mg_iface *mg_if_create_iface(struct mg_iface_vtable *vtable, + struct mg_mgr *mgr) { + struct mg_iface *iface = (struct mg_iface *) MG_CALLOC(1, sizeof(*iface)); + iface->mgr = mgr; + iface->data = NULL; + iface->vtable = vtable; + return iface; +} + +struct mg_iface *mg_find_iface(struct mg_mgr *mgr, + struct mg_iface_vtable *vtable, + struct mg_iface *from) { + int i = 0; + if (from != NULL) { + for (i = 0; i < mgr->num_ifaces; i++) { + if (mgr->ifaces[i] == from) { + i++; + break; + } + } + } + + for (; i < mgr->num_ifaces; i++) { + if (mgr->ifaces[i]->vtable == vtable) { + return mgr->ifaces[i]; + } + } + return NULL; +} +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net_if_socket.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_NET_IF_SOCKET + +/* Amalgamated: #include "mongoose/src/net_if_socket.h" */ +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +#define MG_TCP_RECV_BUFFER_SIZE 1024 +#define MG_UDP_RECV_BUFFER_SIZE 1500 + +static sock_t mg_open_listening_socket(union socket_address *sa, int type, + int proto); +#if MG_ENABLE_SSL +static void mg_ssl_begin(struct mg_connection *nc); +#endif + +void mg_set_non_blocking_mode(sock_t sock) { +#ifdef _WIN32 + unsigned long on = 1; + ioctlsocket(sock, FIONBIO, &on); +#else + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); +#endif +} + +static int mg_is_error(int n) { + int err = mg_get_errno(); + return (n < 0 && err != EINPROGRESS && err != EWOULDBLOCK +#ifndef WINCE + && err != EAGAIN && err != EINTR +#endif +#ifdef _WIN32 + && WSAGetLastError() != WSAEINTR && + WSAGetLastError() != WSAEWOULDBLOCK +#endif + ); +} + +void mg_socket_if_connect_tcp(struct mg_connection *nc, + const union socket_address *sa) { + int rc, proto = 0; + nc->sock = socket(AF_INET, SOCK_STREAM, proto); + if (nc->sock == INVALID_SOCKET) { + nc->err = mg_get_errno() ? mg_get_errno() : 1; + return; + } +#if !defined(MG_ESP8266) + mg_set_non_blocking_mode(nc->sock); +#endif + rc = connect(nc->sock, &sa->sa, sizeof(sa->sin)); + nc->err = mg_is_error(rc) ? mg_get_errno() : 0; + DBG(("%p sock %d rc %d errno %d err %d", nc, nc->sock, rc, mg_get_errno(), + nc->err)); +} + +void mg_socket_if_connect_udp(struct mg_connection *nc) { + nc->sock = socket(AF_INET, SOCK_DGRAM, 0); + if (nc->sock == INVALID_SOCKET) { + nc->err = mg_get_errno() ? mg_get_errno() : 1; + return; + } + if (nc->flags & MG_F_ENABLE_BROADCAST) { + int optval = 1; + setsockopt(nc->sock, SOL_SOCKET, SO_BROADCAST, (const char *) &optval, + sizeof(optval)); + } + nc->err = 0; +} + +int mg_socket_if_listen_tcp(struct mg_connection *nc, + union socket_address *sa) { + int proto = 0; + sock_t sock = mg_open_listening_socket(sa, SOCK_STREAM, proto); + if (sock == INVALID_SOCKET) { + return (mg_get_errno() ? mg_get_errno() : 1); + } + mg_sock_set(nc, sock); + return 0; +} + +int mg_socket_if_listen_udp(struct mg_connection *nc, + union socket_address *sa) { + sock_t sock = mg_open_listening_socket(sa, SOCK_DGRAM, 0); + if (sock == INVALID_SOCKET) return (mg_get_errno() ? mg_get_errno() : 1); + mg_sock_set(nc, sock); + return 0; +} + +void mg_socket_if_tcp_send(struct mg_connection *nc, const void *buf, + size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); +} + +void mg_socket_if_udp_send(struct mg_connection *nc, const void *buf, + size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); +} + +void mg_socket_if_recved(struct mg_connection *nc, size_t len) { + (void) nc; + (void) len; +} + +int mg_socket_if_create_conn(struct mg_connection *nc) { + (void) nc; + return 1; +} + +void mg_socket_if_destroy_conn(struct mg_connection *nc) { + if (nc->sock == INVALID_SOCKET) return; + if (!(nc->flags & MG_F_UDP)) { + closesocket(nc->sock); + } else { + /* Only close outgoing UDP sockets or listeners. */ + if (nc->listener == NULL) closesocket(nc->sock); + } + nc->sock = INVALID_SOCKET; +} + +static int mg_accept_conn(struct mg_connection *lc) { + struct mg_connection *nc; + union socket_address sa; + socklen_t sa_len = sizeof(sa); + /* NOTE(lsm): on Windows, sock is always > FD_SETSIZE */ + sock_t sock = accept(lc->sock, &sa.sa, &sa_len); + if (sock == INVALID_SOCKET) { + if (mg_is_error(-1)) DBG(("%p: failed to accept: %d", lc, mg_get_errno())); + return 0; + } + nc = mg_if_accept_new_conn(lc); + if (nc == NULL) { + closesocket(sock); + return 0; + } + DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr), + ntohs(sa.sin.sin_port))); + mg_sock_set(nc, sock); +#if MG_ENABLE_SSL + if (lc->flags & MG_F_SSL) { + if (mg_ssl_if_conn_accept(nc, lc) != MG_SSL_OK) mg_close_conn(nc); + } else +#endif + { + mg_if_accept_tcp_cb(nc, &sa, sa_len); + } + return 1; +} + +/* 'sa' must be an initialized address to bind to */ +static sock_t mg_open_listening_socket(union socket_address *sa, int type, + int proto) { + socklen_t sa_len = + (sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6); + sock_t sock = INVALID_SOCKET; +#if !MG_LWIP + int on = 1; +#endif + + if ((sock = socket(sa->sa.sa_family, type, proto)) != INVALID_SOCKET && +#if !MG_LWIP /* LWIP doesn't support either */ +#if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) && !defined(WINCE) + /* "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" http://goo.gl/RmrFTm */ + !setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on, + sizeof(on)) && +#endif + +#if !defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE) + /* + * SO_RESUSEADDR is not enabled on Windows because the semantics of + * SO_REUSEADDR on UNIX and Windows is different. On Windows, + * SO_REUSEADDR allows to bind a socket to a port without error even if + * the port is already open by another program. This is not the behavior + * SO_REUSEADDR was designed for, and leads to hard-to-track failure + * scenarios. Therefore, SO_REUSEADDR was disabled on Windows unless + * SO_EXCLUSIVEADDRUSE is supported and set on a socket. + */ + !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)) && +#endif +#endif /* !MG_LWIP */ + + !bind(sock, &sa->sa, sa_len) && + (type == SOCK_DGRAM || listen(sock, SOMAXCONN) == 0)) { +#if !MG_LWIP + mg_set_non_blocking_mode(sock); + /* In case port was set to 0, get the real port number */ + (void) getsockname(sock, &sa->sa, &sa_len); +#endif + } else if (sock != INVALID_SOCKET) { + closesocket(sock); + sock = INVALID_SOCKET; + } + + return sock; +} + +static void mg_write_to_socket(struct mg_connection *nc) { + struct mbuf *io = &nc->send_mbuf; + int n = 0; + +#if MG_LWIP + /* With LWIP we don't know if the socket is ready */ + if (io->len == 0) return; +#endif + + assert(io->len > 0); + + if (nc->flags & MG_F_UDP) { + int n = + sendto(nc->sock, io->buf, io->len, 0, &nc->sa.sa, sizeof(nc->sa.sin)); + DBG(("%p %d %d %d %s:%hu", nc, nc->sock, n, mg_get_errno(), + inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port))); + if (n > 0) { + mbuf_remove(io, n); + mg_if_sent_cb(nc, n); + } + return; + } + +#if MG_ENABLE_SSL + if (nc->flags & MG_F_SSL) { + if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { + n = mg_ssl_if_write(nc, io->buf, io->len); + DBG(("%p %d bytes -> %d (SSL)", nc, n, nc->sock)); + if (n < 0) { + if (n != MG_SSL_WANT_READ && n != MG_SSL_WANT_WRITE) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } + return; + } else { + /* Successful SSL operation, clear off SSL wait flags */ + nc->flags &= ~(MG_F_WANT_READ | MG_F_WANT_WRITE); + } + } else { + mg_ssl_begin(nc); + return; + } + } else +#endif + { + n = (int) MG_SEND_FUNC(nc->sock, io->buf, io->len, 0); + DBG(("%p %d bytes -> %d", nc, n, nc->sock)); + if (n < 0 && mg_is_error(n)) { + /* Something went wrong, drop the connection. */ + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + return; + } + } + + if (n > 0) { + mbuf_remove(io, n); + mg_if_sent_cb(nc, n); + } +} + +MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max) { + size_t avail; + if (conn->recv_mbuf_limit < conn->recv_mbuf.len) return 0; + avail = conn->recv_mbuf_limit - conn->recv_mbuf.len; + return avail > max ? max : avail; +} + +static void mg_handle_tcp_read(struct mg_connection *conn) { + int n = 0; + char *buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE); + + if (buf == NULL) { + DBG(("OOM")); + return; + } + +#if MG_ENABLE_SSL + if (conn->flags & MG_F_SSL) { + if (conn->flags & MG_F_SSL_HANDSHAKE_DONE) { + /* SSL library may have more bytes ready to read than we ask to read. + * Therefore, read in a loop until we read everything. Without the loop, + * we skip to the next select() cycle which can just timeout. */ + while ((n = mg_ssl_if_read(conn, buf, MG_TCP_RECV_BUFFER_SIZE)) > 0) { + DBG(("%p %d bytes <- %d (SSL)", conn, n, conn->sock)); + mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */); + buf = NULL; + if (conn->flags & MG_F_CLOSE_IMMEDIATELY) break; + /* buf has been freed, we need a new one. */ + buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE); + if (buf == NULL) break; + } + MG_FREE(buf); + if (n < 0 && n != MG_SSL_WANT_READ) conn->flags |= MG_F_CLOSE_IMMEDIATELY; + } else { + MG_FREE(buf); + mg_ssl_begin(conn); + return; + } + } else +#endif + { + n = (int) MG_RECV_FUNC(conn->sock, buf, + recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0); + DBG(("%p %d bytes (PLAIN) <- %d", conn, n, conn->sock)); + if (n > 0) { + mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */); + } else { + MG_FREE(buf); + } + if (n == 0) { + /* Orderly shutdown of the socket, try flushing output. */ + conn->flags |= MG_F_SEND_AND_CLOSE; + } else if (mg_is_error(n)) { + conn->flags |= MG_F_CLOSE_IMMEDIATELY; + } + } +} + +static int mg_recvfrom(struct mg_connection *nc, union socket_address *sa, + socklen_t *sa_len, char **buf) { + int n; + *buf = (char *) MG_MALLOC(MG_UDP_RECV_BUFFER_SIZE); + if (*buf == NULL) { + DBG(("Out of memory")); + return -ENOMEM; + } + n = recvfrom(nc->sock, *buf, MG_UDP_RECV_BUFFER_SIZE, 0, &sa->sa, sa_len); + if (n <= 0) { + DBG(("%p recvfrom: %s", nc, strerror(mg_get_errno()))); + MG_FREE(*buf); + } + return n; +} + +static void mg_handle_udp_read(struct mg_connection *nc) { + char *buf = NULL; + union socket_address sa; + socklen_t sa_len = sizeof(sa); + int n = mg_recvfrom(nc, &sa, &sa_len, &buf); + DBG(("%p %d bytes from %s:%d", nc, n, inet_ntoa(nc->sa.sin.sin_addr), + ntohs(nc->sa.sin.sin_port))); + mg_if_recv_udp_cb(nc, buf, n, &sa, sa_len); +} + +#if MG_ENABLE_SSL +static void mg_ssl_begin(struct mg_connection *nc) { + int server_side = (nc->listener != NULL); + enum mg_ssl_if_result res = mg_ssl_if_handshake(nc); + DBG(("%p %d res %d", nc, server_side, res)); + + if (res == MG_SSL_OK) { + nc->flags |= MG_F_SSL_HANDSHAKE_DONE; + nc->flags &= ~(MG_F_WANT_READ | MG_F_WANT_WRITE); + + if (server_side) { + union socket_address sa; + socklen_t sa_len = sizeof(sa); + (void) getpeername(nc->sock, &sa.sa, &sa_len); + mg_if_accept_tcp_cb(nc, &sa, sa_len); + } else { + mg_if_connect_cb(nc, 0); + } + } else if (res != MG_SSL_WANT_READ && res != MG_SSL_WANT_WRITE) { + if (!server_side) { + mg_if_connect_cb(nc, res); + } + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } +} +#endif /* MG_ENABLE_SSL */ + +#define _MG_F_FD_CAN_READ 1 +#define _MG_F_FD_CAN_WRITE 1 << 1 +#define _MG_F_FD_ERROR 1 << 2 + +void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) { + int worth_logging = + fd_flags != 0 || (nc->flags & (MG_F_WANT_READ | MG_F_WANT_WRITE)); + if (worth_logging) { + DBG(("%p fd=%d fd_flags=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, + fd_flags, nc->flags, (int) nc->recv_mbuf.len, + (int) nc->send_mbuf.len)); + } + + if (nc->flags & MG_F_CONNECTING) { + if (fd_flags != 0) { + int err = 0; +#if !defined(MG_ESP8266) + if (!(nc->flags & MG_F_UDP)) { + socklen_t len = sizeof(err); + int ret = + getsockopt(nc->sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len); + if (ret != 0) { + err = 1; + } else if (err == EAGAIN || err == EWOULDBLOCK) { + err = 0; + } + } +#else + /* + * On ESP8266 we use blocking connect. + */ + err = nc->err; +#endif +#if MG_ENABLE_SSL + if ((nc->flags & MG_F_SSL) && err == 0) { + mg_ssl_begin(nc); + } else { + mg_if_connect_cb(nc, err); + } +#else + mg_if_connect_cb(nc, err); +#endif + } else if (nc->err != 0) { + mg_if_connect_cb(nc, nc->err); + } + } + + if (fd_flags & _MG_F_FD_CAN_READ) { + if (nc->flags & MG_F_UDP) { + mg_handle_udp_read(nc); + } else { + if (nc->flags & MG_F_LISTENING) { + /* + * We're not looping here, and accepting just one connection at + * a time. The reason is that eCos does not respect non-blocking + * flag on a listening socket and hangs in a loop. + */ + mg_accept_conn(nc); + } else { + mg_handle_tcp_read(nc); + } + } + } + + if (!(nc->flags & MG_F_CLOSE_IMMEDIATELY)) { + if ((fd_flags & _MG_F_FD_CAN_WRITE) && nc->send_mbuf.len > 0) { + mg_write_to_socket(nc); + } + mg_if_poll(nc, (time_t) now); + mg_if_timer(nc, now); + } + + if (worth_logging) { + DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags, + (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); + } +} + +#if MG_ENABLE_BROADCAST +static void mg_mgr_handle_ctl_sock(struct mg_mgr *mgr) { + struct ctl_msg ctl_msg; + int len = + (int) MG_RECV_FUNC(mgr->ctl[1], (char *) &ctl_msg, sizeof(ctl_msg), 0); + size_t dummy = MG_SEND_FUNC(mgr->ctl[1], ctl_msg.message, 1, 0); + DBG(("read %d from ctl socket", len)); + (void) dummy; /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509 */ + if (len >= (int) sizeof(ctl_msg.callback) && ctl_msg.callback != NULL) { + struct mg_connection *nc; + for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { + ctl_msg.callback(nc, MG_EV_POLL, ctl_msg.message); + } + } +} +#endif + +/* Associate a socket to a connection. */ +void mg_socket_if_sock_set(struct mg_connection *nc, sock_t sock) { + mg_set_non_blocking_mode(sock); + mg_set_close_on_exec(sock); + nc->sock = sock; + DBG(("%p %d", nc, sock)); +} + +void mg_socket_if_init(struct mg_iface *iface) { + (void) iface; + DBG(("%p using select()", iface->mgr)); +#if MG_ENABLE_BROADCAST + do { + mg_socketpair(iface->mgr->ctl, SOCK_DGRAM); + } while (iface->mgr->ctl[0] == INVALID_SOCKET); +#endif +} + +void mg_socket_if_free(struct mg_iface *iface) { + (void) iface; +} + +void mg_socket_if_add_conn(struct mg_connection *nc) { + (void) nc; +} + +void mg_socket_if_remove_conn(struct mg_connection *nc) { + (void) nc; +} + +void mg_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) { + if (sock != INVALID_SOCKET +#ifdef __unix__ + && sock < FD_SETSIZE +#endif + ) { + FD_SET(sock, set); + if (*max_fd == INVALID_SOCKET || sock > *max_fd) { + *max_fd = sock; + } + } +} + +time_t mg_socket_if_poll(struct mg_iface *iface, int timeout_ms) { + struct mg_mgr *mgr = iface->mgr; + double now = mg_time(); + double min_timer; + struct mg_connection *nc, *tmp; + struct timeval tv; + fd_set read_set, write_set, err_set; + sock_t max_fd = INVALID_SOCKET; + int num_fds, num_ev, num_timers = 0; +#ifdef __unix__ + int try_dup = 1; +#endif + + FD_ZERO(&read_set); + FD_ZERO(&write_set); + FD_ZERO(&err_set); +#if MG_ENABLE_BROADCAST + mg_add_to_set(mgr->ctl[1], &read_set, &max_fd); +#endif + + /* + * Note: it is ok to have connections with sock == INVALID_SOCKET in the list, + * e.g. timer-only "connections". + */ + min_timer = 0; + for (nc = mgr->active_connections, num_fds = 0; nc != NULL; nc = tmp) { + tmp = nc->next; + + if (nc->sock != INVALID_SOCKET) { + num_fds++; + +#ifdef __unix__ + /* A hack to make sure all our file descriptos fit into FD_SETSIZE. */ + if (nc->sock >= FD_SETSIZE && try_dup) { + int new_sock = dup(nc->sock); + if (new_sock >= 0 && new_sock < FD_SETSIZE) { + closesocket(nc->sock); + DBG(("new sock %d -> %d", nc->sock, new_sock)); + nc->sock = new_sock; + } else { + try_dup = 0; + } + } +#endif + + if (!(nc->flags & MG_F_WANT_WRITE) && + nc->recv_mbuf.len < nc->recv_mbuf_limit && + (!(nc->flags & MG_F_UDP) || nc->listener == NULL)) { + mg_add_to_set(nc->sock, &read_set, &max_fd); + } + + if (((nc->flags & MG_F_CONNECTING) && !(nc->flags & MG_F_WANT_READ)) || + (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING))) { + mg_add_to_set(nc->sock, &write_set, &max_fd); + mg_add_to_set(nc->sock, &err_set, &max_fd); + } + } + + if (nc->ev_timer_time > 0) { + if (num_timers == 0 || nc->ev_timer_time < min_timer) { + min_timer = nc->ev_timer_time; + } + num_timers++; + } + } + + /* + * If there is a timer to be fired earlier than the requested timeout, + * adjust the timeout. + */ + if (num_timers > 0) { + double timer_timeout_ms = (min_timer - mg_time()) * 1000 + 1 /* rounding */; + if (timer_timeout_ms < timeout_ms) { + timeout_ms = (int) timer_timeout_ms; + } + } + if (timeout_ms < 0) timeout_ms = 0; + + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + + num_ev = select((int) max_fd + 1, &read_set, &write_set, &err_set, &tv); + now = mg_time(); +#if 0 + DBG(("select @ %ld num_ev=%d of %d, timeout=%d", (long) now, num_ev, num_fds, + timeout_ms)); +#endif + +#if MG_ENABLE_BROADCAST + if (num_ev > 0 && mgr->ctl[1] != INVALID_SOCKET && + FD_ISSET(mgr->ctl[1], &read_set)) { + mg_mgr_handle_ctl_sock(mgr); + } +#endif + + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + int fd_flags = 0; + if (nc->sock != INVALID_SOCKET) { + if (num_ev > 0) { + fd_flags = (FD_ISSET(nc->sock, &read_set) && + (!(nc->flags & MG_F_UDP) || nc->listener == NULL) + ? _MG_F_FD_CAN_READ + : 0) | + (FD_ISSET(nc->sock, &write_set) ? _MG_F_FD_CAN_WRITE : 0) | + (FD_ISSET(nc->sock, &err_set) ? _MG_F_FD_ERROR : 0); + } +#if MG_LWIP + /* With LWIP socket emulation layer, we don't get write events for UDP */ + if ((nc->flags & MG_F_UDP) && nc->listener == NULL) { + fd_flags |= _MG_F_FD_CAN_WRITE; + } +#endif + } + tmp = nc->next; + mg_mgr_handle_conn(nc, fd_flags, now); + } + + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + tmp = nc->next; + if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) || + (nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) { + mg_close_conn(nc); + } + } + + return (time_t) now; +} + +#if MG_ENABLE_BROADCAST +int mg_socketpair(sock_t sp[2], int sock_type) { + union socket_address sa; + sock_t sock; + socklen_t len = sizeof(sa.sin); + int ret = 0; + + sock = sp[0] = sp[1] = INVALID_SOCKET; + + (void) memset(&sa, 0, sizeof(sa)); + sa.sin.sin_family = AF_INET; + sa.sin.sin_port = htons(0); + sa.sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + + if ((sock = socket(AF_INET, sock_type, 0)) == INVALID_SOCKET) { + } else if (bind(sock, &sa.sa, len) != 0) { + } else if (sock_type == SOCK_STREAM && listen(sock, 1) != 0) { + } else if (getsockname(sock, &sa.sa, &len) != 0) { + } else if ((sp[0] = socket(AF_INET, sock_type, 0)) == INVALID_SOCKET) { + } else if (connect(sp[0], &sa.sa, len) != 0) { + } else if (sock_type == SOCK_DGRAM && + (getsockname(sp[0], &sa.sa, &len) != 0 || + connect(sock, &sa.sa, len) != 0)) { + } else if ((sp[1] = (sock_type == SOCK_DGRAM ? sock + : accept(sock, &sa.sa, &len))) == + INVALID_SOCKET) { + } else { + mg_set_close_on_exec(sp[0]); + mg_set_close_on_exec(sp[1]); + if (sock_type == SOCK_STREAM) closesocket(sock); + ret = 1; + } + + if (!ret) { + if (sp[0] != INVALID_SOCKET) closesocket(sp[0]); + if (sp[1] != INVALID_SOCKET) closesocket(sp[1]); + if (sock != INVALID_SOCKET) closesocket(sock); + sock = sp[0] = sp[1] = INVALID_SOCKET; + } + + return ret; +} +#endif /* MG_ENABLE_BROADCAST */ + +static void mg_sock_get_addr(sock_t sock, int remote, + union socket_address *sa) { + socklen_t slen = sizeof(*sa); + memset(sa, 0, slen); + if (remote) { + getpeername(sock, &sa->sa, &slen); + } else { + getsockname(sock, &sa->sa, &slen); + } +} + +void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags) { + union socket_address sa; + mg_sock_get_addr(sock, flags & MG_SOCK_STRINGIFY_REMOTE, &sa); + mg_sock_addr_to_str(&sa, buf, len, flags); +} + +void mg_socket_if_get_conn_addr(struct mg_connection *nc, int remote, + union socket_address *sa) { + mg_sock_get_addr(nc->sock, remote, sa); +} + +/* clang-format off */ +#define MG_SOCKET_IFACE_VTABLE \ + { \ + mg_socket_if_init, \ + mg_socket_if_free, \ + mg_socket_if_add_conn, \ + mg_socket_if_remove_conn, \ + mg_socket_if_poll, \ + mg_socket_if_listen_tcp, \ + mg_socket_if_listen_udp, \ + mg_socket_if_connect_tcp, \ + mg_socket_if_connect_udp, \ + mg_socket_if_tcp_send, \ + mg_socket_if_udp_send, \ + mg_socket_if_recved, \ + mg_socket_if_create_conn, \ + mg_socket_if_destroy_conn, \ + mg_socket_if_sock_set, \ + mg_socket_if_get_conn_addr, \ + } +/* clang-format on */ + +struct mg_iface_vtable mg_socket_iface_vtable = MG_SOCKET_IFACE_VTABLE; +#if MG_NET_IF == MG_NET_IF_SOCKET +struct mg_iface_vtable mg_default_iface_vtable = MG_SOCKET_IFACE_VTABLE; +#endif + +#endif /* MG_ENABLE_NET_IF_SOCKET */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/net_if_tun.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_TUN + +/* Amalgamated: #include "common/cs_dbg.h" */ +/* Amalgamated: #include "common/cs_time.h" */ +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/net_if_tun.h" */ +/* Amalgamated: #include "mongoose/src/tun.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +#define MG_TCP_RECV_BUFFER_SIZE 1024 +#define MG_UDP_RECV_BUFFER_SIZE 1500 + +void mg_tun_if_connect_tcp(struct mg_connection *nc, + const union socket_address *sa) { + (void) nc; + (void) sa; +} + +void mg_tun_if_connect_udp(struct mg_connection *nc) { + (void) nc; +} + +int mg_tun_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) { + (void) nc; + (void) sa; + return 0; +} + +int mg_tun_if_listen_udp(struct mg_connection *nc, union socket_address *sa) { + (void) nc; + (void) sa; + return -1; +} + +void mg_tun_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) { + struct mg_tun_client *client = (struct mg_tun_client *) nc->iface->data; + uint32_t stream_id = (uint32_t)(uintptr_t) nc->mgr_data; + struct mg_str msg = {(char *) buf, len}; +#if MG_ENABLE_HEXDUMP + char hex[512]; + mg_hexdump(buf, len, hex, sizeof(hex)); + LOG(LL_DEBUG, ("sending to stream %zu:\n%s", stream_id, hex)); +#endif + + mg_tun_send_frame(client->disp, stream_id, MG_TUN_DATA_FRAME, 0, msg); +} + +void mg_tun_if_udp_send(struct mg_connection *nc, const void *buf, size_t len) { + (void) nc; + (void) buf; + (void) len; +} + +void mg_tun_if_recved(struct mg_connection *nc, size_t len) { + (void) nc; + (void) len; +} + +int mg_tun_if_create_conn(struct mg_connection *nc) { + (void) nc; + return 1; +} + +void mg_tun_if_destroy_conn(struct mg_connection *nc) { + struct mg_tun_client *client = (struct mg_tun_client *) nc->iface->data; + + if (nc->flags & MG_F_LISTENING) { + mg_tun_destroy_client(client); + } else if (client->disp) { + uint32_t stream_id = (uint32_t)(uintptr_t) nc->mgr_data; + struct mg_str msg = {NULL, 0}; + + LOG(LL_DEBUG, ("closing %zu:", stream_id)); + mg_tun_send_frame(client->disp, stream_id, MG_TUN_DATA_FRAME, + MG_TUN_F_END_STREAM, msg); + } +} + +/* Associate a socket to a connection. */ +void mg_tun_if_sock_set(struct mg_connection *nc, sock_t sock) { + (void) nc; + (void) sock; +} + +void mg_tun_if_init(struct mg_iface *iface) { + (void) iface; +} + +void mg_tun_if_free(struct mg_iface *iface) { + (void) iface; +} + +void mg_tun_if_add_conn(struct mg_connection *nc) { + nc->sock = INVALID_SOCKET; +} + +void mg_tun_if_remove_conn(struct mg_connection *nc) { + (void) nc; +} + +time_t mg_tun_if_poll(struct mg_iface *iface, int timeout_ms) { + (void) iface; + (void) timeout_ms; + return (time_t) cs_time(); +} + +void mg_tun_if_get_conn_addr(struct mg_connection *nc, int remote, + union socket_address *sa) { + (void) nc; + (void) remote; + (void) sa; +} + +struct mg_connection *mg_tun_if_find_conn(struct mg_tun_client *client, + uint32_t stream_id) { + struct mg_connection *nc = NULL; + + for (nc = client->mgr->active_connections; nc != NULL; nc = nc->next) { + if (nc->iface != client->iface || (nc->flags & MG_F_LISTENING)) { + continue; + } + if (stream_id == (uint32_t)(uintptr_t) nc->mgr_data) { + return nc; + } + } + + if (stream_id > client->last_stream_id) { + /* create a new connection */ + LOG(LL_DEBUG, ("new stream 0x%lx, accepting", stream_id)); + nc = mg_if_accept_new_conn(client->listener); + nc->mgr_data = (void *) (uintptr_t) stream_id; + client->last_stream_id = stream_id; + } else { + LOG(LL_DEBUG, ("Ignoring stream 0x%lx (last_stream_id 0x%lx)", stream_id, + client->last_stream_id)); + } + + return nc; +} + +/* clang-format off */ +#define MG_TUN_IFACE_VTABLE \ + { \ + mg_tun_if_init, \ + mg_tun_if_free, \ + mg_tun_if_add_conn, \ + mg_tun_if_remove_conn, \ + mg_tun_if_poll, \ + mg_tun_if_listen_tcp, \ + mg_tun_if_listen_udp, \ + mg_tun_if_connect_tcp, \ + mg_tun_if_connect_udp, \ + mg_tun_if_tcp_send, \ + mg_tun_if_udp_send, \ + mg_tun_if_recved, \ + mg_tun_if_create_conn, \ + mg_tun_if_destroy_conn, \ + mg_tun_if_sock_set, \ + mg_tun_if_get_conn_addr, \ + } +/* clang-format on */ + +struct mg_iface_vtable mg_tun_iface_vtable = MG_TUN_IFACE_VTABLE; + +#endif /* MG_ENABLE_TUN */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/ssl_if_openssl.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_OPENSSL + +#ifdef __APPLE__ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +#include + +struct mg_ssl_if_ctx { + SSL *ssl; + SSL_CTX *ssl_ctx; +}; + +void mg_ssl_if_init() { + SSL_library_init(); +} + +enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc, + struct mg_connection *lc) { + struct mg_ssl_if_ctx *ctx = + (struct mg_ssl_if_ctx *) MG_CALLOC(1, sizeof(*ctx)); + struct mg_ssl_if_ctx *lc_ctx = (struct mg_ssl_if_ctx *) lc->ssl_if_data; + nc->ssl_if_data = ctx; + if (ctx == NULL || lc_ctx == NULL) return MG_SSL_ERROR; + ctx->ssl_ctx = lc_ctx->ssl_ctx; + if ((ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) { + return MG_SSL_ERROR; + } + return MG_SSL_OK; +} + +static enum mg_ssl_if_result mg_use_cert(SSL_CTX *ctx, const char *cert, + const char *key, const char **err_msg); +static enum mg_ssl_if_result mg_use_ca_cert(SSL_CTX *ctx, const char *cert); +static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx, const char *cl); + +enum mg_ssl_if_result mg_ssl_if_conn_init( + struct mg_connection *nc, const struct mg_ssl_if_conn_params *params, + const char **err_msg) { + struct mg_ssl_if_ctx *ctx = + (struct mg_ssl_if_ctx *) MG_CALLOC(1, sizeof(*ctx)); + DBG(("%p %s,%s,%s", nc, (params->cert ? params->cert : ""), + (params->key ? params->key : ""), + (params->ca_cert ? params->ca_cert : ""))); + if (ctx == NULL) { + MG_SET_PTRPTR(err_msg, "Out of memory"); + return MG_SSL_ERROR; + } + nc->ssl_if_data = ctx; + if (nc->flags & MG_F_LISTENING) { + ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + } else { + ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + } + if (ctx->ssl_ctx == NULL) { + MG_SET_PTRPTR(err_msg, "Failed to create SSL context"); + return MG_SSL_ERROR; + } + + if (params->cert != NULL && + mg_use_cert(ctx->ssl_ctx, params->cert, params->key, err_msg) != + MG_SSL_OK) { + return MG_SSL_ERROR; + } + + if (params->ca_cert != NULL && + mg_use_ca_cert(ctx->ssl_ctx, params->ca_cert) != MG_SSL_OK) { + MG_SET_PTRPTR(err_msg, "Invalid SSL CA cert"); + return MG_SSL_ERROR; + } + + if (params->server_name != NULL) { +#ifdef KR_VERSION + SSL_CTX_kr_set_verify_name(ctx->ssl_ctx, params->server_name); +#else +/* TODO(rojer): Implement server name verification on OpenSSL. */ +#endif + } + + if (mg_set_cipher_list(ctx->ssl_ctx, params->cipher_suites) != MG_SSL_OK) { + MG_SET_PTRPTR(err_msg, "Invalid cipher suite list"); + return MG_SSL_ERROR; + } + + if (!(nc->flags & MG_F_LISTENING) && + (ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) { + MG_SET_PTRPTR(err_msg, "Failed to create SSL session"); + return MG_SSL_ERROR; + } + + nc->flags |= MG_F_SSL; + + return MG_SSL_OK; +} + +static enum mg_ssl_if_result mg_ssl_if_ssl_err(struct mg_connection *nc, + int res) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int err = SSL_get_error(ctx->ssl, res); + if (err == SSL_ERROR_WANT_READ) return MG_SSL_WANT_READ; + if (err == SSL_ERROR_WANT_WRITE) return MG_SSL_WANT_WRITE; + DBG(("%p %p SSL error: %d %d", nc, ctx->ssl_ctx, res, err)); + nc->err = err; + return MG_SSL_ERROR; +} + +enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int server_side = (nc->listener != NULL); + int res; + /* If descriptor is not yet set, do it now. */ + if (SSL_get_fd(ctx->ssl) < 0) { + if (SSL_set_fd(ctx->ssl, nc->sock) != 1) return MG_SSL_ERROR; + } + res = server_side ? SSL_accept(ctx->ssl) : SSL_connect(ctx->ssl); + if (res != 1) return mg_ssl_if_ssl_err(nc, res); + return MG_SSL_OK; +} + +int mg_ssl_if_read(struct mg_connection *nc, void *buf, size_t buf_size) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int n = SSL_read(ctx->ssl, buf, buf_size); + DBG(("%p %d -> %d", nc, (int) buf_size, n)); + if (n < 0) return mg_ssl_if_ssl_err(nc, n); + if (n == 0) nc->flags |= MG_F_CLOSE_IMMEDIATELY; + return n; +} + +int mg_ssl_if_write(struct mg_connection *nc, const void *data, size_t len) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int n = SSL_write(ctx->ssl, data, len); + DBG(("%p %d -> %d", nc, (int) len, n)); + if (n <= 0) return mg_ssl_if_ssl_err(nc, n); + return n; +} + +void mg_ssl_if_conn_free(struct mg_connection *nc) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + if (ctx == NULL) return; + nc->ssl_if_data = NULL; + if (ctx->ssl != NULL) SSL_free(ctx->ssl); + if (ctx->ssl_ctx != NULL && nc->listener == NULL) SSL_CTX_free(ctx->ssl_ctx); + memset(ctx, 0, sizeof(*ctx)); + MG_FREE(ctx); +} + +/* + * Cipher suite options used for TLS negotiation. + * https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations + */ +static const char mg_s_cipher_list[] = +#if defined(MG_SSL_CRYPTO_MODERN) + "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:" + "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:" + "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:" + "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:" + "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:" + "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:" + "!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK" +#elif defined(MG_SSL_CRYPTO_OLD) + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:" + "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:" + "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:" + "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:" + "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:" + "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:" + "ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:" + "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:" + "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:" + "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" +#else /* Default - intermediate. */ + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:" + "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:" + "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:" + "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:" + "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:" + "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:" + "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:" + "DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:" + "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" +#endif + ; + +/* + * Default DH params for PFS cipher negotiation. This is a 2048-bit group. + * Will be used if none are provided by the user in the certificate file. + */ +#if !MG_DISABLE_PFS && !defined(KR_VERSION) +static const char mg_s_default_dh_params[] = + "\ +-----BEGIN DH PARAMETERS-----\n\ +MIIBCAKCAQEAlvbgD/qh9znWIlGFcV0zdltD7rq8FeShIqIhkQ0C7hYFThrBvF2E\n\ +Z9bmgaP+sfQwGpVlv9mtaWjvERbu6mEG7JTkgmVUJrUt/wiRzwTaCXBqZkdUO8Tq\n\ ++E6VOEQAilstG90ikN1Tfo+K6+X68XkRUIlgawBTKuvKVwBhuvlqTGerOtnXWnrt\n\ +ym//hd3cd5PBYGBix0i7oR4xdghvfR2WLVu0LgdThTBb6XP7gLd19cQ1JuBtAajZ\n\ +wMuPn7qlUkEFDIkAZy59/Hue/H2Q2vU/JsvVhHWCQBL4F1ofEAt50il6ZxR1QfFK\n\ +9VGKDC4oOgm9DlxwwBoC2FjqmvQlqVV3kwIBAg==\n\ +-----END DH PARAMETERS-----\n"; +#endif + +static enum mg_ssl_if_result mg_use_ca_cert(SSL_CTX *ctx, const char *cert) { + if (cert == NULL || strcmp(cert, "*") == 0) { + return MG_SSL_OK; + } + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + return SSL_CTX_load_verify_locations(ctx, cert, NULL) == 1 ? MG_SSL_OK + : MG_SSL_ERROR; +} + +static enum mg_ssl_if_result mg_use_cert(SSL_CTX *ctx, const char *cert, + const char *key, + const char **err_msg) { + if (key == NULL) key = cert; + if (cert == NULL || cert[0] == '\0' || key == NULL || key[0] == '\0') { + return MG_SSL_OK; + } else if (SSL_CTX_use_certificate_file(ctx, cert, 1) == 0) { + MG_SET_PTRPTR(err_msg, "Invalid SSL cert"); + return MG_SSL_ERROR; + } else if (SSL_CTX_use_PrivateKey_file(ctx, key, 1) == 0) { + MG_SET_PTRPTR(err_msg, "Invalid SSL key"); + return MG_SSL_ERROR; + } else if (SSL_CTX_use_certificate_chain_file(ctx, cert) == 0) { + MG_SET_PTRPTR(err_msg, "Invalid CA bundle"); + return MG_SSL_ERROR; + } else { + SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); +#if !MG_DISABLE_PFS && !defined(KR_VERSION) + BIO *bio = NULL; + DH *dh = NULL; + + /* Try to read DH parameters from the cert/key file. */ + bio = BIO_new_file(cert, "r"); + if (bio != NULL) { + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + /* + * If there are no DH params in the file, fall back to hard-coded ones. + * Not ideal, but better than nothing. + */ + if (dh == NULL) { + bio = BIO_new_mem_buf((void *) mg_s_default_dh_params, -1); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + if (dh != NULL) { + SSL_CTX_set_tmp_dh(ctx, dh); + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); + DH_free(dh); + } +#if OPENSSL_VERSION_NUMBER > 0x10002000L + SSL_CTX_set_ecdh_auto(ctx, 1); +#endif +#endif + } + return MG_SSL_OK; +} + +static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx, const char *cl) { + return (SSL_CTX_set_cipher_list(ctx, cl ? cl : mg_s_cipher_list) == 1 + ? MG_SSL_OK + : MG_SSL_ERROR); +} + +const char *mg_set_ssl(struct mg_connection *nc, const char *cert, + const char *ca_cert) { + const char *err_msg = NULL; + struct mg_ssl_if_conn_params params; + memset(¶ms, 0, sizeof(params)); + params.cert = cert; + params.ca_cert = ca_cert; + if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) { + return err_msg; + } + return NULL; +} + +#endif /* MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_OPENSSL */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/ssl_if_mbedtls.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_MBEDTLS + +#include +#include +#include +#include +#include + +static void mg_ssl_mbed_log(void *ctx, int level, const char *file, int line, + const char *str) { + enum cs_log_level cs_level; + switch (level) { + case 1: + cs_level = LL_ERROR; + break; + case 2: + case 3: + cs_level = LL_DEBUG; + break; + default: + cs_level = LL_VERBOSE_DEBUG; + } + /* mbedTLS passes strings with \n at the end, strip it. */ + LOG(cs_level, ("%p %.*s", ctx, (int) (strlen(str) - 1), str)); + (void) file; + (void) line; +} + +struct mg_ssl_if_ctx { + mbedtls_ssl_config *conf; + mbedtls_ssl_context *ssl; + mbedtls_x509_crt *cert; + mbedtls_pk_context *key; + mbedtls_x509_crt *ca_cert; + struct mbuf cipher_suites; +}; + +/* Must be provided by the platform. ctx is struct mg_connection. */ +extern int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len); + +void mg_ssl_if_init() { +} + +enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc, + struct mg_connection *lc) { + struct mg_ssl_if_ctx *ctx = + (struct mg_ssl_if_ctx *) MG_CALLOC(1, sizeof(*ctx)); + struct mg_ssl_if_ctx *lc_ctx = (struct mg_ssl_if_ctx *) lc->ssl_if_data; + nc->ssl_if_data = ctx; + if (ctx == NULL || lc_ctx == NULL) return MG_SSL_ERROR; + ctx->ssl = MG_CALLOC(1, sizeof(*ctx->ssl)); + if (mbedtls_ssl_setup(ctx->ssl, lc_ctx->conf) != 0) { + return MG_SSL_ERROR; + } + return MG_SSL_OK; +} + +static enum mg_ssl_if_result mg_use_cert(struct mg_ssl_if_ctx *ctx, + const char *cert, const char *key, + const char **err_msg); +static enum mg_ssl_if_result mg_use_ca_cert(struct mg_ssl_if_ctx *ctx, + const char *cert); +static enum mg_ssl_if_result mg_set_cipher_list(struct mg_ssl_if_ctx *ctx, + const char *ciphers); + +enum mg_ssl_if_result mg_ssl_if_conn_init( + struct mg_connection *nc, const struct mg_ssl_if_conn_params *params, + const char **err_msg) { + struct mg_ssl_if_ctx *ctx = + (struct mg_ssl_if_ctx *) MG_CALLOC(1, sizeof(*ctx)); + DBG(("%p %s,%s,%s", nc, (params->cert ? params->cert : ""), + (params->key ? params->key : ""), + (params->ca_cert ? params->ca_cert : ""))); + + if (ctx == NULL) { + MG_SET_PTRPTR(err_msg, "Out of memory"); + return MG_SSL_ERROR; + } + nc->ssl_if_data = ctx; + ctx->conf = MG_CALLOC(1, sizeof(*ctx->conf)); + mbuf_init(&ctx->cipher_suites, 0); + mbedtls_ssl_config_init(ctx->conf); + mbedtls_ssl_conf_dbg(ctx->conf, mg_ssl_mbed_log, nc); + if (mbedtls_ssl_config_defaults( + ctx->conf, (nc->flags & MG_F_LISTENING ? MBEDTLS_SSL_IS_SERVER + : MBEDTLS_SSL_IS_CLIENT), + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + MG_SET_PTRPTR(err_msg, "Failed to init SSL config"); + return MG_SSL_ERROR; + } + /* TLS 1.2 and up */ + mbedtls_ssl_conf_min_version(ctx->conf, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_3); + mbedtls_ssl_conf_rng(ctx->conf, mg_ssl_if_mbed_random, nc); + + if (params->cert != NULL && + mg_use_cert(ctx, params->cert, params->key, err_msg) != MG_SSL_OK) { + return MG_SSL_ERROR; + } + + if (params->ca_cert != NULL && + mg_use_ca_cert(ctx, params->ca_cert) != MG_SSL_OK) { + MG_SET_PTRPTR(err_msg, "Invalid SSL CA cert"); + return MG_SSL_ERROR; + } + + if (mg_set_cipher_list(ctx, params->cipher_suites) != MG_SSL_OK) { + MG_SET_PTRPTR(err_msg, "Invalid cipher suite list"); + return MG_SSL_ERROR; + } + + if (!(nc->flags & MG_F_LISTENING)) { + ctx->ssl = MG_CALLOC(1, sizeof(*ctx->ssl)); + mbedtls_ssl_init(ctx->ssl); + if (mbedtls_ssl_setup(ctx->ssl, ctx->conf) != 0) { + MG_SET_PTRPTR(err_msg, "Failed to create SSL session"); + return MG_SSL_ERROR; + } + if (params->server_name != NULL && + mbedtls_ssl_set_hostname(ctx->ssl, params->server_name) != 0) { + return MG_SSL_ERROR; + } + } + + nc->flags |= MG_F_SSL; + + return MG_SSL_OK; +} + +#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL +int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len); +int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len); +#else +static int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len) { + struct mg_connection *nc = (struct mg_connection *) ctx; + int n = (int) MG_SEND_FUNC(nc->sock, buf, len, 0); + DBG(("%p %d -> %d", nc, (int) len, n)); + if (n >= 0) return n; + n = mg_get_errno(); + return ((n == EAGAIN || n == EINPROGRESS) ? MBEDTLS_ERR_SSL_WANT_WRITE : -1); +} + +static int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) { + struct mg_connection *nc = (struct mg_connection *) ctx; + int n = (int) MG_RECV_FUNC(nc->sock, buf, len, 0); + DBG(("%p %d <- %d", nc, (int) len, n)); + if (n >= 0) return n; + n = mg_get_errno(); + return ((n == EAGAIN || n == EINPROGRESS) ? MBEDTLS_ERR_SSL_WANT_READ : -1); +} +#endif + +static enum mg_ssl_if_result mg_ssl_if_mbed_err(struct mg_connection *nc, + int ret) { + if (ret == MBEDTLS_ERR_SSL_WANT_READ) return MG_SSL_WANT_READ; + if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) return MG_SSL_WANT_WRITE; + if (ret != + MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { /* CLOSE_NOTIFY = Normal shutdown */ + LOG(LL_ERROR, ("%p SSL error: %d", nc, ret)); + } + nc->err = ret; + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + return MG_SSL_ERROR; +} + +static void mg_ssl_if_mbed_free_certs_and_keys(struct mg_ssl_if_ctx *ctx) { + if (ctx->cert != NULL) { + mbedtls_x509_crt_free(ctx->cert); + MG_FREE(ctx->cert); + ctx->cert = NULL; + mbedtls_pk_free(ctx->key); + MG_FREE(ctx->key); + ctx->key = NULL; + } + if (ctx->ca_cert != NULL) { + mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL); + mbedtls_x509_crt_free(ctx->ca_cert); + MG_FREE(ctx->ca_cert); + ctx->ca_cert = NULL; + } +} + +enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int err; + /* If bio is not yet set, do it now. */ + if (ctx->ssl->p_bio == NULL) { + mbedtls_ssl_set_bio(ctx->ssl, nc, ssl_socket_send, ssl_socket_recv, NULL); + } + err = mbedtls_ssl_handshake(ctx->ssl); + if (err != 0) return mg_ssl_if_mbed_err(nc, err); +#ifdef MG_SSL_IF_MBEDTLS_FREE_CERTS + /* + * Free the peer certificate, we don't need it after handshake. + * Note that this effectively disables renegotiation. + */ + mbedtls_x509_crt_free(ctx->ssl->session->peer_cert); + mbedtls_free(ctx->ssl->session->peer_cert); + ctx->ssl->session->peer_cert = NULL; + /* On a client connection we can also free our own and CA certs. */ + if (nc->listener == NULL) { + if (ctx->conf->key_cert != NULL) { + /* Note that this assumes one key_cert entry, which matches our init. */ + MG_FREE(ctx->conf->key_cert); + ctx->conf->key_cert = NULL; + } + mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL); + mg_ssl_if_mbed_free_certs_and_keys(ctx); + } +#endif + return MG_SSL_OK; +} + +int mg_ssl_if_read(struct mg_connection *nc, void *buf, size_t buf_size) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int n = mbedtls_ssl_read(ctx->ssl, buf, buf_size); + DBG(("%p %d -> %d", nc, (int) buf_size, n)); + if (n < 0) return mg_ssl_if_mbed_err(nc, n); + if (n == 0) nc->flags |= MG_F_CLOSE_IMMEDIATELY; + return n; +} + +int mg_ssl_if_write(struct mg_connection *nc, const void *data, size_t len) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + int n = mbedtls_ssl_write(ctx->ssl, data, len); + DBG(("%p %d -> %d", nc, (int) len, n)); + if (n < 0) return mg_ssl_if_mbed_err(nc, n); + return n; +} + +void mg_ssl_if_conn_free(struct mg_connection *nc) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + if (ctx == NULL) return; + nc->ssl_if_data = NULL; + if (ctx->ssl != NULL) { + mbedtls_ssl_free(ctx->ssl); + MG_FREE(ctx->ssl); + } + mg_ssl_if_mbed_free_certs_and_keys(ctx); + if (ctx->conf != NULL) { + mbedtls_ssl_config_free(ctx->conf); + MG_FREE(ctx->conf); + } + mbuf_free(&ctx->cipher_suites); + memset(ctx, 0, sizeof(*ctx)); + MG_FREE(ctx); +} + +static enum mg_ssl_if_result mg_use_ca_cert(struct mg_ssl_if_ctx *ctx, + const char *ca_cert) { + if (ca_cert == NULL || strcmp(ca_cert, "*") == 0) { + return MG_SSL_OK; + } + ctx->ca_cert = MG_CALLOC(1, sizeof(*ctx->ca_cert)); + mbedtls_x509_crt_init(ctx->ca_cert); + if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) { + return MG_SSL_ERROR; + } + mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL); + mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + return MG_SSL_OK; +} + +static enum mg_ssl_if_result mg_use_cert(struct mg_ssl_if_ctx *ctx, + const char *cert, const char *key, + const char **err_msg) { + if (key == NULL) key = cert; + if (cert == NULL || cert[0] == '\0' || key == NULL || key[0] == '\0') { + return MG_SSL_OK; + } + ctx->cert = MG_CALLOC(1, sizeof(*ctx->cert)); + mbedtls_x509_crt_init(ctx->cert); + ctx->key = MG_CALLOC(1, sizeof(*ctx->key)); + mbedtls_pk_init(ctx->key); + if (mbedtls_x509_crt_parse_file(ctx->cert, cert) != 0) { + MG_SET_PTRPTR(err_msg, "Invalid SSL cert"); + return MG_SSL_ERROR; + } + if (mbedtls_pk_parse_keyfile(ctx->key, key, NULL) != 0) { + MG_SET_PTRPTR(err_msg, "Invalid SSL key"); + return MG_SSL_ERROR; + } + if (mbedtls_ssl_conf_own_cert(ctx->conf, ctx->cert, ctx->key) != 0) { + MG_SET_PTRPTR(err_msg, "Invalid SSL key or cert"); + return MG_SSL_ERROR; + } + return MG_SSL_OK; +} + +static const int mg_s_cipher_list[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, 0}; + +/* + * Ciphers can be specified as a colon-separated list of cipher suite names. + * These can be found in + * https://github.com/ARMmbed/mbedtls/blob/development/library/ssl_ciphersuites.c#L267 + * E.g.: TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-CCM + */ +static enum mg_ssl_if_result mg_set_cipher_list(struct mg_ssl_if_ctx *ctx, + const char *ciphers) { + if (ciphers != NULL) { + int l, id; + const char *s = ciphers; + char *e, tmp[50]; + while (s != NULL) { + e = strchr(s, ':'); + l = (e != NULL ? (e - s) : (int) strlen(s)); + strncpy(tmp, s, l); + tmp[l] = '\0'; + id = mbedtls_ssl_get_ciphersuite_id(tmp); + DBG(("%s -> %04x", tmp, id)); + if (id != 0) { + mbuf_append(&ctx->cipher_suites, &id, sizeof(id)); + } + s = (e != NULL ? e + 1 : NULL); + } + if (ctx->cipher_suites.len == 0) return MG_SSL_ERROR; + id = 0; + mbuf_append(&ctx->cipher_suites, &id, sizeof(id)); + mbedtls_ssl_conf_ciphersuites(ctx->conf, + (const int *) ctx->cipher_suites.buf); + } else { + mbedtls_ssl_conf_ciphersuites(ctx->conf, mg_s_cipher_list); + } + return MG_SSL_OK; +} + +const char *mg_set_ssl(struct mg_connection *nc, const char *cert, + const char *ca_cert) { + const char *err_msg = NULL; + struct mg_ssl_if_conn_params params; + memset(¶ms, 0, sizeof(params)); + params.cert = cert; + params.ca_cert = ca_cert; + if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) { + return err_msg; + } + return NULL; +} + +/* Lazy RNG. Warning: it would be a bad idea to do this in production! */ +#ifdef MG_SSL_MBED_DUMMY_RANDOM +int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len) { + (void) ctx; + while (len--) *buf++ = rand(); + return 0; +} +#endif + +#endif /* MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_MBEDTLS */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/multithreading.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +#if MG_ENABLE_THREADS + +static void multithreaded_ev_handler(struct mg_connection *c, int ev, void *p); + +/* + * This thread function executes user event handler. + * It runs an event manager that has only one connection, until that + * connection is alive. + */ +static void *per_connection_thread_function(void *param) { + struct mg_connection *c = (struct mg_connection *) param; + struct mg_mgr m; + /* mgr_data can be used subsequently, store its value */ + int poll_timeout = (intptr_t) c->mgr_data; + + mg_mgr_init(&m, NULL); + mg_add_conn(&m, c); + mg_call(c, NULL, MG_EV_ACCEPT, &c->sa); + + while (m.active_connections != NULL) { + mg_mgr_poll(&m, poll_timeout ? poll_timeout : 1000); + } + mg_mgr_free(&m); + + return param; +} + +static void link_conns(struct mg_connection *c1, struct mg_connection *c2) { + c1->priv_2 = c2; + c2->priv_2 = c1; +} + +static void unlink_conns(struct mg_connection *c) { + struct mg_connection *peer = (struct mg_connection *) c->priv_2; + if (peer != NULL) { + peer->flags |= MG_F_SEND_AND_CLOSE; + peer->priv_2 = NULL; + } + c->priv_2 = NULL; +} + +static void forwarder_ev_handler(struct mg_connection *c, int ev, void *p) { + (void) p; + if (ev == MG_EV_RECV && c->priv_2) { + mg_forward(c, (struct mg_connection *) c->priv_2); + } else if (ev == MG_EV_CLOSE) { + unlink_conns(c); + } +} + +static void spawn_handling_thread(struct mg_connection *nc) { + struct mg_mgr dummy; + sock_t sp[2]; + struct mg_connection *c[2]; + int poll_timeout; + /* + * Create a socket pair, and wrap each socket into the connection with + * dummy event manager. + * c[0] stays in this thread, c[1] goes to another thread. + */ + mg_mgr_init(&dummy, NULL); + mg_socketpair(sp, SOCK_STREAM); + + c[0] = mg_add_sock(&dummy, sp[0], forwarder_ev_handler); + c[1] = mg_add_sock(&dummy, sp[1], nc->listener->priv_1.f); + + /* link_conns replaces priv_2, storing its value */ + poll_timeout = (intptr_t) nc->priv_2; + + /* Interlink client connection with c[0] */ + link_conns(c[0], nc); + + /* + * Switch c[0] manager from the dummy one to the real one. c[1] manager + * will be set in another thread, allocated on stack of that thread. + */ + mg_add_conn(nc->mgr, c[0]); + + /* + * Dress c[1] as nc. + * TODO(lsm): code in accept_conn() looks similar. Refactor. + */ + c[1]->listener = nc->listener; + c[1]->proto_handler = nc->proto_handler; + c[1]->user_data = nc->user_data; + c[1]->sa = nc->sa; + c[1]->flags = nc->flags; + + /* priv_2 is used, so, put timeout to mgr_data */ + c[1]->mgr_data = (void *) (intptr_t) poll_timeout; + + mg_start_thread(per_connection_thread_function, c[1]); +} + +static void multithreaded_ev_handler(struct mg_connection *c, int ev, void *p) { + (void) p; + if (ev == MG_EV_ACCEPT) { + spawn_handling_thread(c); + c->handler = forwarder_ev_handler; + } +} + +void mg_enable_multithreading_opt(struct mg_connection *nc, + struct mg_multithreading_opts opts) { + /* Wrap user event handler into our multithreaded_ev_handler */ + nc->priv_1.f = nc->handler; + /* + * We put timeout to `priv_2` member of the main + * (listening) connection, mt is not enabled yet, + * and this member is not used + */ + nc->priv_2 = (void *) (intptr_t) opts.poll_timeout; + nc->handler = multithreaded_ev_handler; +} + +void mg_enable_multithreading(struct mg_connection *nc) { + struct mg_multithreading_opts opts; + memset(&opts, 0, sizeof(opts)); + mg_enable_multithreading_opt(nc, opts); +} + +#endif +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/uri.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/uri.h" */ + +/* + * scan string until `sep`, keeping track of component boundaries in `res`. + * + * `p` will point to the char after the separator or it will be `end`. + */ +static void parse_uri_component(const char **p, const char *end, char sep, + struct mg_str *res) { + res->p = *p; + for (; *p < end; (*p)++) { + if (**p == sep) { + break; + } + } + res->len = (*p) - res->p; + if (*p < end) (*p)++; +} + +int mg_parse_uri(struct mg_str uri, struct mg_str *scheme, + struct mg_str *user_info, struct mg_str *host, + unsigned int *port, struct mg_str *path, struct mg_str *query, + struct mg_str *fragment) { + struct mg_str rscheme = {0, 0}, ruser_info = {0, 0}, rhost = {0, 0}, + rpath = {0, 0}, rquery = {0, 0}, rfragment = {0, 0}; + unsigned int rport = 0; + enum { + P_START, + P_SCHEME_OR_PORT, + P_USER_INFO, + P_HOST, + P_PORT, + P_REST + } state = P_START; + + const char *p = uri.p, *end = p + uri.len; + while (p < end) { + switch (state) { + case P_START: + /* + * expecting on of: + * - `scheme://xxxx` + * - `xxxx:port` + * - `xxxx/path` + */ + for (; p < end; p++) { + if (*p == ':') { + state = P_SCHEME_OR_PORT; + break; + } else if (*p == '/') { + state = P_REST; + break; + } + } + if (state == P_START || state == P_REST) { + rhost.p = uri.p; + rhost.len = p - uri.p; + } + break; + case P_SCHEME_OR_PORT: + if (end - p >= 3 && strncmp(p, "://", 3) == 0) { + rscheme.p = uri.p; + rscheme.len = p - uri.p; + state = P_USER_INFO; + p += 2; /* point to last separator char */ + } else { + rhost.p = uri.p; + rhost.len = p - uri.p; + state = P_PORT; + } + break; + case P_USER_INFO: + p++; + ruser_info.p = p; + for (; p < end; p++) { + if (*p == '@') { + state = P_HOST; + break; + } else if (*p == '/') { + break; + } + } + if (p == end || *p == '/') { + /* backtrack and parse as host */ + state = P_HOST; + p = ruser_info.p; + } + ruser_info.len = p - ruser_info.p; + break; + case P_HOST: + if (*p == '@') p++; + rhost.p = p; + for (; p < end; p++) { + if (*p == ':') { + state = P_PORT; + break; + } else if (*p == '/') { + state = P_REST; + break; + } + } + rhost.len = p - rhost.p; + break; + case P_PORT: + p++; + for (; p < end; p++) { + if (*p == '/') { + state = P_REST; + break; + } + rport *= 10; + rport += *p - '0'; + } + break; + case P_REST: + /* `p` points to separator. `path` includes the separator */ + parse_uri_component(&p, end, '?', &rpath); + parse_uri_component(&p, end, '#', &rquery); + parse_uri_component(&p, end, '\0', &rfragment); + break; + } + } + + if (scheme != 0) *scheme = rscheme; + if (user_info != 0) *user_info = ruser_info; + if (host != 0) *host = rhost; + if (port != 0) *port = rport; + if (path != 0) *path = rpath; + if (query != 0) *query = rquery; + if (fragment != 0) *fragment = rfragment; + + return 0; +} + +/* Normalize the URI path. Remove/resolve "." and "..". */ +int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out) { + const char *s = in->p, *se = s + in->len; + char *cp = (char *) out->p, *d; + + if (in->len == 0 || *s != '/') { + out->len = 0; + return 0; + } + + d = cp; + + while (s < se) { + const char *next = s; + struct mg_str component; + parse_uri_component(&next, se, '/', &component); + if (mg_vcmp(&component, ".") == 0) { + /* Yum. */ + } else if (mg_vcmp(&component, "..") == 0) { + /* Backtrack to previous slash. */ + if (d > cp + 1 && *(d - 1) == '/') d--; + while (d > cp && *(d - 1) != '/') d--; + } else { + memmove(d, s, next - s); + d += next - s; + } + s = next; + } + if (d == cp) *d++ = '/'; + + out->p = cp; + out->len = d - cp; + return 1; +} +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_HTTP + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ +/* Amalgamated: #include "common/sha1.h" */ +/* Amalgamated: #include "common/md5.h" */ + +static const char *mg_version_header = "Mongoose/" MG_VERSION; + +enum mg_http_proto_data_type { DATA_NONE, DATA_FILE, DATA_PUT }; + +struct mg_http_proto_data_file { + FILE *fp; /* Opened file. */ + int64_t cl; /* Content-Length. How many bytes to send. */ + int64_t sent; /* How many bytes have been already sent. */ + int keepalive; /* Keep connection open after sending. */ + enum mg_http_proto_data_type type; +}; + +#if MG_ENABLE_HTTP_CGI +struct mg_http_proto_data_cgi { + struct mg_connection *cgi_nc; +}; +#endif + +struct mg_http_proto_data_chuncked { + int64_t body_len; /* How many bytes of chunked body was reassembled. */ +}; + +struct mg_http_endpoint { + struct mg_http_endpoint *next; + const char *name; + size_t name_len; + mg_event_handler_t handler; +}; + +enum mg_http_multipart_stream_state { + MPS_BEGIN, + MPS_WAITING_FOR_BOUNDARY, + MPS_WAITING_FOR_CHUNK, + MPS_GOT_CHUNK, + MPS_GOT_BOUNDARY, + MPS_FINALIZE, + MPS_FINISHED +}; + +struct mg_http_multipart_stream { + const char *boundary; + int boundary_len; + const char *var_name; + const char *file_name; + void *user_data; + int prev_io_len; + enum mg_http_multipart_stream_state state; + int processing_part; +}; + +struct mg_reverse_proxy_data { + struct mg_connection *linked_conn; +}; + +struct mg_http_proto_data { +#if MG_ENABLE_FILESYSTEM + struct mg_http_proto_data_file file; +#endif +#if MG_ENABLE_HTTP_CGI + struct mg_http_proto_data_cgi cgi; +#endif +#if MG_ENABLE_HTTP_STREAMING_MULTIPART + struct mg_http_multipart_stream mp_stream; +#endif + struct mg_http_proto_data_chuncked chunk; + struct mg_http_endpoint *endpoints; + mg_event_handler_t endpoint_handler; + struct mg_reverse_proxy_data reverse_proxy_data; +}; + +static void mg_http_conn_destructor(void *proto_data); +struct mg_connection *mg_connect_http_base( + struct mg_mgr *mgr, mg_event_handler_t ev_handler, + struct mg_connect_opts opts, const char *schema, const char *schema_ssl, + const char *url, const char **path, char **user, char **pass, char **addr); + +static struct mg_http_proto_data *mg_http_get_proto_data( + struct mg_connection *c) { + if (c->proto_data == NULL) { + c->proto_data = MG_CALLOC(1, sizeof(struct mg_http_proto_data)); + c->proto_data_destructor = mg_http_conn_destructor; + } + + return (struct mg_http_proto_data *) c->proto_data; +} + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART +static void mg_http_free_proto_data_mp_stream( + struct mg_http_multipart_stream *mp) { + free((void *) mp->boundary); + free((void *) mp->var_name); + free((void *) mp->file_name); + memset(mp, 0, sizeof(*mp)); +} +#endif + +#if MG_ENABLE_FILESYSTEM +static void mg_http_free_proto_data_file(struct mg_http_proto_data_file *d) { + if (d != NULL) { + if (d->fp != NULL) { + fclose(d->fp); + } + memset(d, 0, sizeof(struct mg_http_proto_data_file)); + } +} +#endif + +static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep) { + struct mg_http_endpoint *current = *ep; + + while (current != NULL) { + struct mg_http_endpoint *tmp = current->next; + free((void *) current->name); + free(current); + current = tmp; + } + + ep = NULL; +} + +static void mg_http_free_reverse_proxy_data(struct mg_reverse_proxy_data *rpd) { + if (rpd->linked_conn != NULL) { + /* + * Connection has linked one, we have to unlink & close it + * since _this_ connection is going to die and + * it doesn't make sense to keep another one + */ + struct mg_http_proto_data *pd = mg_http_get_proto_data(rpd->linked_conn); + if (pd->reverse_proxy_data.linked_conn != NULL) { + pd->reverse_proxy_data.linked_conn->flags |= MG_F_SEND_AND_CLOSE; + pd->reverse_proxy_data.linked_conn = NULL; + } + rpd->linked_conn = NULL; + } +} + +static void mg_http_conn_destructor(void *proto_data) { + struct mg_http_proto_data *pd = (struct mg_http_proto_data *) proto_data; +#if MG_ENABLE_FILESYSTEM + mg_http_free_proto_data_file(&pd->file); +#endif +#if MG_ENABLE_HTTP_CGI + mg_http_free_proto_data_cgi(&pd->cgi); +#endif +#if MG_ENABLE_HTTP_STREAMING_MULTIPART + mg_http_free_proto_data_mp_stream(&pd->mp_stream); +#endif + mg_http_free_proto_data_endpoints(&pd->endpoints); + mg_http_free_reverse_proxy_data(&pd->reverse_proxy_data); + free(proto_data); +} + +#if MG_ENABLE_FILESYSTEM + +#define MIME_ENTRY(_ext, _type) \ + { _ext, sizeof(_ext) - 1, _type } +static const struct { + const char *extension; + size_t ext_len; + const char *mime_type; +} mg_static_builtin_mime_types[] = { + MIME_ENTRY("html", "text/html"), + MIME_ENTRY("html", "text/html"), + MIME_ENTRY("htm", "text/html"), + MIME_ENTRY("shtm", "text/html"), + MIME_ENTRY("shtml", "text/html"), + MIME_ENTRY("css", "text/css"), + MIME_ENTRY("js", "application/x-javascript"), + MIME_ENTRY("ico", "image/x-icon"), + MIME_ENTRY("gif", "image/gif"), + MIME_ENTRY("jpg", "image/jpeg"), + MIME_ENTRY("jpeg", "image/jpeg"), + MIME_ENTRY("png", "image/png"), + MIME_ENTRY("svg", "image/svg+xml"), + MIME_ENTRY("txt", "text/plain"), + MIME_ENTRY("torrent", "application/x-bittorrent"), + MIME_ENTRY("wav", "audio/x-wav"), + MIME_ENTRY("mp3", "audio/x-mp3"), + MIME_ENTRY("mid", "audio/mid"), + MIME_ENTRY("m3u", "audio/x-mpegurl"), + MIME_ENTRY("ogg", "application/ogg"), + MIME_ENTRY("ram", "audio/x-pn-realaudio"), + MIME_ENTRY("xml", "text/xml"), + MIME_ENTRY("ttf", "application/x-font-ttf"), + MIME_ENTRY("json", "application/json"), + MIME_ENTRY("xslt", "application/xml"), + MIME_ENTRY("xsl", "application/xml"), + MIME_ENTRY("ra", "audio/x-pn-realaudio"), + MIME_ENTRY("doc", "application/msword"), + MIME_ENTRY("exe", "application/octet-stream"), + MIME_ENTRY("zip", "application/x-zip-compressed"), + MIME_ENTRY("xls", "application/excel"), + MIME_ENTRY("tgz", "application/x-tar-gz"), + MIME_ENTRY("tar", "application/x-tar"), + MIME_ENTRY("gz", "application/x-gunzip"), + MIME_ENTRY("arj", "application/x-arj-compressed"), + MIME_ENTRY("rar", "application/x-rar-compressed"), + MIME_ENTRY("rtf", "application/rtf"), + MIME_ENTRY("pdf", "application/pdf"), + MIME_ENTRY("swf", "application/x-shockwave-flash"), + MIME_ENTRY("mpg", "video/mpeg"), + MIME_ENTRY("webm", "video/webm"), + MIME_ENTRY("mpeg", "video/mpeg"), + MIME_ENTRY("mov", "video/quicktime"), + MIME_ENTRY("mp4", "video/mp4"), + MIME_ENTRY("m4v", "video/x-m4v"), + MIME_ENTRY("asf", "video/x-ms-asf"), + MIME_ENTRY("avi", "video/x-msvideo"), + MIME_ENTRY("bmp", "image/bmp"), + {NULL, 0, NULL}}; + +static struct mg_str mg_get_mime_type(const char *path, const char *dflt, + const struct mg_serve_http_opts *opts) { + const char *ext, *overrides; + size_t i, path_len; + struct mg_str r, k, v; + + path_len = strlen(path); + + overrides = opts->custom_mime_types; + while ((overrides = mg_next_comma_list_entry(overrides, &k, &v)) != NULL) { + ext = path + (path_len - k.len); + if (path_len > k.len && mg_vcasecmp(&k, ext) == 0) { + return v; + } + } + + for (i = 0; mg_static_builtin_mime_types[i].extension != NULL; i++) { + ext = path + (path_len - mg_static_builtin_mime_types[i].ext_len); + if (path_len > mg_static_builtin_mime_types[i].ext_len && ext[-1] == '.' && + mg_casecmp(ext, mg_static_builtin_mime_types[i].extension) == 0) { + r.p = mg_static_builtin_mime_types[i].mime_type; + r.len = strlen(r.p); + return r; + } + } + + r.p = dflt; + r.len = strlen(r.p); + return r; +} +#endif + +/* + * Check whether full request is buffered. Return: + * -1 if request is malformed + * 0 if request is not yet fully buffered + * >0 actual request length, including last \r\n\r\n + */ +static int mg_http_get_request_len(const char *s, int buf_len) { + const unsigned char *buf = (unsigned char *) s; + int i; + + for (i = 0; i < buf_len; i++) { + if (!isprint(buf[i]) && buf[i] != '\r' && buf[i] != '\n' && buf[i] < 128) { + return -1; + } else if (buf[i] == '\n' && i + 1 < buf_len && buf[i + 1] == '\n') { + return i + 2; + } else if (buf[i] == '\n' && i + 2 < buf_len && buf[i + 1] == '\r' && + buf[i + 2] == '\n') { + return i + 3; + } + } + + return 0; +} + +static const char *mg_http_parse_headers(const char *s, const char *end, + int len, struct http_message *req) { + int i = 0; + while (i < (int) ARRAY_SIZE(req->header_names) - 1) { + struct mg_str *k = &req->header_names[i], *v = &req->header_values[i]; + + s = mg_skip(s, end, ": ", k); + s = mg_skip(s, end, "\r\n", v); + + while (v->len > 0 && v->p[v->len - 1] == ' ') { + v->len--; /* Trim trailing spaces in header value */ + } + + /* + * If header value is empty - skip it and go to next (if any). + * NOTE: Do not add it to headers_values because such addition changes API + * behaviour + */ + if (k->len != 0 && v->len == 0) { + continue; + } + + if (k->len == 0 || v->len == 0) { + k->p = v->p = NULL; + k->len = v->len = 0; + break; + } + + if (!mg_ncasecmp(k->p, "Content-Length", 14)) { + req->body.len = (size_t) to64(v->p); + req->message.len = len + req->body.len; + } + + i++; + } + + return s; +} + +int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req) { + const char *end, *qs; + int len = mg_http_get_request_len(s, n); + + if (len <= 0) return len; + + memset(hm, 0, sizeof(*hm)); + hm->message.p = s; + hm->body.p = s + len; + hm->message.len = hm->body.len = (size_t) ~0; + end = s + len; + + /* Request is fully buffered. Skip leading whitespaces. */ + while (s < end && isspace(*(unsigned char *) s)) s++; + + if (is_req) { + /* Parse request line: method, URI, proto */ + s = mg_skip(s, end, " ", &hm->method); + s = mg_skip(s, end, " ", &hm->uri); + s = mg_skip(s, end, "\r\n", &hm->proto); + if (hm->uri.p <= hm->method.p || hm->proto.p <= hm->uri.p) return -1; + + /* If URI contains '?' character, initialize query_string */ + if ((qs = (char *) memchr(hm->uri.p, '?', hm->uri.len)) != NULL) { + hm->query_string.p = qs + 1; + hm->query_string.len = &hm->uri.p[hm->uri.len] - (qs + 1); + hm->uri.len = qs - hm->uri.p; + } + } else { + s = mg_skip(s, end, " ", &hm->proto); + if (end - s < 4 || s[3] != ' ') return -1; + hm->resp_code = atoi(s); + if (hm->resp_code < 100 || hm->resp_code >= 600) return -1; + s += 4; + s = mg_skip(s, end, "\r\n", &hm->resp_status_msg); + } + + s = mg_http_parse_headers(s, end, len, hm); + + /* + * mg_parse_http() is used to parse both HTTP requests and HTTP + * responses. If HTTP response does not have Content-Length set, then + * body is read until socket is closed, i.e. body.len is infinite (~0). + * + * For HTTP requests though, according to + * http://tools.ietf.org/html/rfc7231#section-8.1.3, + * only POST and PUT methods have defined body semantics. + * Therefore, if Content-Length is not specified and methods are + * not one of PUT or POST, set body length to 0. + * + * So, + * if it is HTTP request, and Content-Length is not set, + * and method is not (PUT or POST) then reset body length to zero. + */ + if (hm->body.len == (size_t) ~0 && is_req && + mg_vcasecmp(&hm->method, "PUT") != 0 && + mg_vcasecmp(&hm->method, "POST") != 0) { + hm->body.len = 0; + hm->message.len = len; + } + + return len; +} + +struct mg_str *mg_get_http_header(struct http_message *hm, const char *name) { + size_t i, len = strlen(name); + + for (i = 0; hm->header_names[i].len > 0; i++) { + struct mg_str *h = &hm->header_names[i], *v = &hm->header_values[i]; + if (h->p != NULL && h->len == len && !mg_ncasecmp(h->p, name, len)) + return v; + } + + return NULL; +} + +#if MG_ENABLE_FILESYSTEM +static void mg_http_transfer_file_data(struct mg_connection *nc) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + char buf[MG_MAX_HTTP_SEND_MBUF]; + size_t n = 0, to_read = 0, left = (size_t)(pd->file.cl - pd->file.sent); + + if (pd->file.type == DATA_FILE) { + struct mbuf *io = &nc->send_mbuf; + if (io->len < sizeof(buf)) { + to_read = sizeof(buf) - io->len; + } + + if (left > 0 && to_read > left) { + to_read = left; + } + + if (to_read == 0) { + /* Rate limiting. send_mbuf is too full, wait until it's drained. */ + } else if (pd->file.sent < pd->file.cl && + (n = fread(buf, 1, to_read, pd->file.fp)) > 0) { + mg_send(nc, buf, n); + pd->file.sent += n; + } else { + if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE; + mg_http_free_proto_data_file(&pd->file); + } + } else if (pd->file.type == DATA_PUT) { + struct mbuf *io = &nc->recv_mbuf; + size_t to_write = left <= 0 ? 0 : left < io->len ? (size_t) left : io->len; + size_t n = fwrite(io->buf, 1, to_write, pd->file.fp); + if (n > 0) { + mbuf_remove(io, n); + pd->file.sent += n; + } + if (n == 0 || pd->file.sent >= pd->file.cl) { + if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE; + mg_http_free_proto_data_file(&pd->file); + } + } +#if MG_ENABLE_HTTP_CGI + else if (pd->cgi.cgi_nc != NULL) { + /* This is POST data that needs to be forwarded to the CGI process */ + if (pd->cgi.cgi_nc != NULL) { + mg_forward(nc, pd->cgi.cgi_nc); + } else { + nc->flags |= MG_F_SEND_AND_CLOSE; + } + } +#endif +} +#endif /* MG_ENABLE_FILESYSTEM */ + +/* + * Parse chunked-encoded buffer. Return 0 if the buffer is not encoded, or + * if it's incomplete. If the chunk is fully buffered, return total number of + * bytes in a chunk, and store data in `data`, `data_len`. + */ +static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data, + size_t *chunk_len) { + unsigned char *s = (unsigned char *) buf; + size_t n = 0; /* scanned chunk length */ + size_t i = 0; /* index in s */ + + /* Scan chunk length. That should be a hexadecimal number. */ + while (i < len && isxdigit(s[i])) { + n *= 16; + n += (s[i] >= '0' && s[i] <= '9') ? s[i] - '0' : tolower(s[i]) - 'a' + 10; + i++; + } + + /* Skip new line */ + if (i == 0 || i + 2 > len || s[i] != '\r' || s[i + 1] != '\n') { + return 0; + } + i += 2; + + /* Record where the data is */ + *chunk_data = (char *) s + i; + *chunk_len = n; + + /* Skip data */ + i += n; + + /* Skip new line */ + if (i == 0 || i + 2 > len || s[i] != '\r' || s[i + 1] != '\n') { + return 0; + } + return i + 2; +} + +MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, + struct http_message *hm, char *buf, + size_t blen) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + char *data; + size_t i, n, data_len, body_len, zero_chunk_received = 0; + /* Find out piece of received data that is not yet reassembled */ + body_len = (size_t) pd->chunk.body_len; + assert(blen >= body_len); + + /* Traverse all fully buffered chunks */ + for (i = body_len; + (n = mg_http_parse_chunk(buf + i, blen - i, &data, &data_len)) > 0; + i += n) { + /* Collapse chunk data to the rest of HTTP body */ + memmove(buf + body_len, data, data_len); + body_len += data_len; + hm->body.len = body_len; + + if (data_len == 0) { + zero_chunk_received = 1; + i += n; + break; + } + } + + if (i > body_len) { + /* Shift unparsed content to the parsed body */ + assert(i <= blen); + memmove(buf + body_len, buf + i, blen - i); + memset(buf + body_len + blen - i, 0, i - body_len); + nc->recv_mbuf.len -= i - body_len; + pd->chunk.body_len = body_len; + + /* Send MG_EV_HTTP_CHUNK event */ + nc->flags &= ~MG_F_DELETE_CHUNK; + mg_call(nc, nc->handler, MG_EV_HTTP_CHUNK, hm); + + /* Delete processed data if user set MG_F_DELETE_CHUNK flag */ + if (nc->flags & MG_F_DELETE_CHUNK) { + memset(buf, 0, body_len); + memmove(buf, buf + body_len, blen - i); + nc->recv_mbuf.len -= body_len; + hm->body.len = 0; + pd->chunk.body_len = 0; + } + + if (zero_chunk_received) { + hm->message.len = (size_t) pd->chunk.body_len + blen - i; + } + } + + return body_len; +} + +static mg_event_handler_t mg_http_get_endpoint_handler( + struct mg_connection *nc, struct mg_str *uri_path) { + struct mg_http_proto_data *pd; + mg_event_handler_t ret = NULL; + int matched, matched_max = 0; + struct mg_http_endpoint *ep; + + if (nc == NULL) { + return NULL; + } + + pd = mg_http_get_proto_data(nc); + + ep = pd->endpoints; + while (ep != NULL) { + const struct mg_str name_s = {ep->name, ep->name_len}; + if ((matched = mg_match_prefix_n(name_s, *uri_path)) != -1) { + if (matched > matched_max) { + /* Looking for the longest suitable handler */ + ret = ep->handler; + matched_max = matched; + } + } + + ep = ep->next; + } + + return ret; +} + +static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev, + struct http_message *hm) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + + if (pd->endpoint_handler == NULL || ev == MG_EV_HTTP_REQUEST) { + pd->endpoint_handler = + ev == MG_EV_HTTP_REQUEST + ? mg_http_get_endpoint_handler(nc->listener, &hm->uri) + : NULL; + } + mg_call(nc, pd->endpoint_handler ? pd->endpoint_handler : nc->handler, ev, + hm); +} + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART +static void mg_http_multipart_continue(struct mg_connection *nc); + +static void mg_http_multipart_begin(struct mg_connection *nc, + struct http_message *hm, int req_len); + +#endif + +/* + * lx106 compiler has a bug (TODO(mkm) report and insert tracking bug here) + * If a big structure is declared in a big function, lx106 gcc will make it + * even bigger (round up to 4k, from 700 bytes of actual size). + */ +#ifdef __xtensa__ +static void mg_http_handler2(struct mg_connection *nc, int ev, void *ev_data, + struct http_message *hm) __attribute__((noinline)); + +void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message hm; + mg_http_handler2(nc, ev, ev_data, &hm); +} + +static void mg_http_handler2(struct mg_connection *nc, int ev, void *ev_data, + struct http_message *hm) { +#else /* !__XTENSA__ */ +void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message shm; + struct http_message *hm = &shm; +#endif /* __XTENSA__ */ + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + struct mbuf *io = &nc->recv_mbuf; + int req_len; + const int is_req = (nc->listener != NULL); +#if MG_ENABLE_HTTP_WEBSOCKET + struct mg_str *vec; +#endif + if (ev == MG_EV_CLOSE) { +#if MG_ENABLE_HTTP_STREAMING_MULTIPART + if (pd->mp_stream.boundary != NULL) { + /* + * Multipart message is in progress, but connection is closed. + * Finish part and request with an error flag. + */ + struct mg_http_multipart_part mp; + memset(&mp, 0, sizeof(mp)); + mp.status = -1; + mp.var_name = pd->mp_stream.var_name; + mp.file_name = pd->mp_stream.file_name; + mg_call(nc, (pd->endpoint_handler ? pd->endpoint_handler : nc->handler), + MG_EV_HTTP_PART_END, &mp); + mp.var_name = NULL; + mp.file_name = NULL; + mg_call(nc, (pd->endpoint_handler ? pd->endpoint_handler : nc->handler), + MG_EV_HTTP_MULTIPART_REQUEST_END, &mp); + } else +#endif + if (io->len > 0 && mg_parse_http(io->buf, io->len, hm, is_req) > 0) { + /* + * For HTTP messages without Content-Length, always send HTTP message + * before MG_EV_CLOSE message. + */ + int ev2 = is_req ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY; + hm->message.len = io->len; + hm->body.len = io->buf + io->len - hm->body.p; + mg_http_call_endpoint_handler(nc, ev2, hm); + } + } + +#if MG_ENABLE_FILESYSTEM + if (pd->file.fp != NULL) { + mg_http_transfer_file_data(nc); + } +#endif + + mg_call(nc, nc->handler, ev, ev_data); + + if (ev == MG_EV_RECV) { + struct mg_str *s; + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART + if (pd->mp_stream.boundary != NULL) { + mg_http_multipart_continue(nc); + return; + } +#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */ + + req_len = mg_parse_http(io->buf, io->len, hm, is_req); + + if (req_len > 0 && + (s = mg_get_http_header(hm, "Transfer-Encoding")) != NULL && + mg_vcasecmp(s, "chunked") == 0) { + mg_handle_chunked(nc, hm, io->buf + req_len, io->len - req_len); + } + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART + if (req_len > 0 && (s = mg_get_http_header(hm, "Content-Type")) != NULL && + s->len >= 9 && strncmp(s->p, "multipart", 9) == 0) { + mg_http_multipart_begin(nc, hm, req_len); + mg_http_multipart_continue(nc); + return; + } +#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */ + + /* TODO(alashkin): refactor this ifelseifelseifelseifelse */ + if ((req_len < 0 || + (req_len == 0 && io->len >= MG_MAX_HTTP_REQUEST_SIZE))) { + DBG(("invalid request")); + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } else if (req_len == 0) { + /* Do nothing, request is not yet fully buffered */ + } +#if MG_ENABLE_HTTP_WEBSOCKET + else if (nc->listener == NULL && + mg_get_http_header(hm, "Sec-WebSocket-Accept")) { + /* We're websocket client, got handshake response from server. */ + /* TODO(lsm): check the validity of accept Sec-WebSocket-Accept */ + mbuf_remove(io, req_len); + nc->proto_handler = mg_ws_handler; + nc->flags |= MG_F_IS_WEBSOCKET; + mg_call(nc, nc->handler, MG_EV_WEBSOCKET_HANDSHAKE_DONE, NULL); + mg_ws_handler(nc, MG_EV_RECV, ev_data); + } else if (nc->listener != NULL && + (vec = mg_get_http_header(hm, "Sec-WebSocket-Key")) != NULL) { + mg_event_handler_t handler; + + /* This is a websocket request. Switch protocol handlers. */ + mbuf_remove(io, req_len); + nc->proto_handler = mg_ws_handler; + nc->flags |= MG_F_IS_WEBSOCKET; + + /* + * If we have a handler set up with mg_register_http_endpoint(), + * deliver subsequent websocket events to this handler after the + * protocol switch. + */ + handler = mg_http_get_endpoint_handler(nc->listener, &hm->uri); + if (handler != NULL) { + nc->handler = handler; + } + + /* Send handshake */ + mg_call(nc, nc->handler, MG_EV_WEBSOCKET_HANDSHAKE_REQUEST, hm); + if (!(nc->flags & (MG_F_CLOSE_IMMEDIATELY | MG_F_SEND_AND_CLOSE))) { + if (nc->send_mbuf.len == 0) { + mg_ws_handshake(nc, vec); + } + mg_call(nc, nc->handler, MG_EV_WEBSOCKET_HANDSHAKE_DONE, NULL); + mg_ws_handler(nc, MG_EV_RECV, ev_data); + } + } +#endif /* MG_ENABLE_HTTP_WEBSOCKET */ + else if (hm->message.len <= io->len) { + int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY; + +/* Whole HTTP message is fully buffered, call event handler */ + +#if MG_ENABLE_JAVASCRIPT + v7_val_t v1, v2, headers, req, args, res; + struct v7 *v7 = nc->mgr->v7; + const char *ev_name = trigger_ev == MG_EV_HTTP_REPLY ? "onsnd" : "onrcv"; + int i, js_callback_handled_request = 0; + + if (v7 != NULL) { + /* Lookup JS callback */ + v1 = v7_get(v7, v7_get_global(v7), "Http", ~0); + v2 = v7_get(v7, v1, ev_name, ~0); + + /* Create callback params. TODO(lsm): own/disown those */ + args = v7_mk_array(v7); + req = v7_mk_object(v7); + headers = v7_mk_object(v7); + + /* Populate request object */ + v7_set(v7, req, "method", ~0, + v7_mk_string(v7, hm->method.p, hm->method.len, 1)); + v7_set(v7, req, "uri", ~0, v7_mk_string(v7, hm->uri.p, hm->uri.len, 1)); + v7_set(v7, req, "body", ~0, + v7_mk_string(v7, hm->body.p, hm->body.len, 1)); + v7_set(v7, req, "headers", ~0, headers); + for (i = 0; hm->header_names[i].len > 0; i++) { + const struct mg_str *name = &hm->header_names[i]; + const struct mg_str *value = &hm->header_values[i]; + v7_set(v7, headers, name->p, name->len, + v7_mk_string(v7, value->p, value->len, 1)); + } + + /* Invoke callback. TODO(lsm): report errors */ + v7_array_push(v7, args, v7_mk_foreign(v7, nc)); + v7_array_push(v7, args, req); + if (v7_apply(v7, v2, V7_UNDEFINED, args, &res) == V7_OK && + v7_is_truthy(v7, res)) { + js_callback_handled_request++; + } + } + + /* If JS callback returns true, stop request processing */ + if (js_callback_handled_request) { + nc->flags |= MG_F_SEND_AND_CLOSE; + } else { + mg_http_call_endpoint_handler(nc, trigger_ev, hm); + } +#else + mg_http_call_endpoint_handler(nc, trigger_ev, hm); +#endif + mbuf_remove(io, hm->message.len); + } + } + (void) pd; +} + +static size_t mg_get_line_len(const char *buf, size_t buf_len) { + size_t len = 0; + while (len < buf_len && buf[len] != '\n') len++; + return len == buf_len ? 0 : len + 1; +} + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART +static void mg_http_multipart_begin(struct mg_connection *nc, + struct http_message *hm, int req_len) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + struct mg_str *ct; + struct mbuf *io = &nc->recv_mbuf; + + char boundary[100]; + int boundary_len; + + if (nc->listener == NULL) { + /* No streaming for replies now */ + goto exit_mp; + } + + ct = mg_get_http_header(hm, "Content-Type"); + if (ct == NULL) { + /* We need more data - or it isn't multipart mesage */ + goto exit_mp; + } + + /* Content-type should start with "multipart" */ + if (ct->len < 9 || strncmp(ct->p, "multipart", 9) != 0) { + goto exit_mp; + } + + boundary_len = + mg_http_parse_header(ct, "boundary", boundary, sizeof(boundary)); + if (boundary_len == 0) { + /* + * Content type is multipart, but there is no boundary, + * probably malformed request + */ + nc->flags = MG_F_CLOSE_IMMEDIATELY; + DBG(("invalid request")); + goto exit_mp; + } + + /* If we reach this place - that is multipart request */ + + if (pd->mp_stream.boundary != NULL) { + /* + * Another streaming request was in progress, + * looks like protocol error + */ + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } else { + pd->mp_stream.state = MPS_BEGIN; + pd->mp_stream.boundary = strdup(boundary); + pd->mp_stream.boundary_len = strlen(boundary); + pd->mp_stream.var_name = pd->mp_stream.file_name = NULL; + + pd->endpoint_handler = mg_http_get_endpoint_handler(nc->listener, &hm->uri); + if (pd->endpoint_handler == NULL) { + pd->endpoint_handler = nc->handler; + } + + mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_MULTIPART_REQUEST, hm); + + mbuf_remove(io, req_len); + } +exit_mp: + ; +} + +#define CONTENT_DISPOSITION "Content-Disposition: " + +static void mg_http_multipart_call_handler(struct mg_connection *c, int ev, + const char *data, size_t data_len) { + struct mg_http_multipart_part mp; + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + memset(&mp, 0, sizeof(mp)); + + mp.var_name = pd->mp_stream.var_name; + mp.file_name = pd->mp_stream.file_name; + mp.user_data = pd->mp_stream.user_data; + mp.data.p = data; + mp.data.len = data_len; + mg_call(c, pd->endpoint_handler, ev, &mp); + pd->mp_stream.user_data = mp.user_data; +} + +static int mg_http_multipart_got_chunk(struct mg_connection *c) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + struct mbuf *io = &c->recv_mbuf; + + mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_DATA, io->buf, + pd->mp_stream.prev_io_len); + mbuf_remove(io, pd->mp_stream.prev_io_len); + pd->mp_stream.prev_io_len = 0; + pd->mp_stream.state = MPS_WAITING_FOR_CHUNK; + + return 0; +} + +static int mg_http_multipart_finalize(struct mg_connection *c) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + + mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_END, NULL, 0); + free((void *) pd->mp_stream.file_name); + pd->mp_stream.file_name = NULL; + free((void *) pd->mp_stream.var_name); + pd->mp_stream.var_name = NULL; + mg_http_multipart_call_handler(c, MG_EV_HTTP_MULTIPART_REQUEST_END, NULL, 0); + mg_http_free_proto_data_mp_stream(&pd->mp_stream); + pd->mp_stream.state = MPS_FINISHED; + + return 1; +} + +static int mg_http_multipart_wait_for_boundary(struct mg_connection *c) { + const char *boundary; + struct mbuf *io = &c->recv_mbuf; + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + + if ((int) io->len < pd->mp_stream.boundary_len + 2) { + return 0; + } + + boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len); + if (boundary != NULL) { + const char *boundary_end = (boundary + pd->mp_stream.boundary_len); + if (io->len - (boundary_end - io->buf) < 4) { + return 0; + } + if (strncmp(boundary_end, "--\r\n", 4) == 0) { + pd->mp_stream.state = MPS_FINALIZE; + mbuf_remove(io, (boundary_end - io->buf) + 4); + } else { + pd->mp_stream.state = MPS_GOT_BOUNDARY; + } + } else { + return 0; + } + + return 1; +} + +static int mg_http_multipart_process_boundary(struct mg_connection *c) { + int data_size; + const char *boundary, *block_begin; + struct mbuf *io = &c->recv_mbuf; + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + char file_name[100], var_name[100]; + int line_len; + boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len); + block_begin = boundary + pd->mp_stream.boundary_len + 2; + data_size = io->len - (block_begin - io->buf); + + while (data_size > 0 && + (line_len = mg_get_line_len(block_begin, data_size)) != 0) { + if (line_len > (int) sizeof(CONTENT_DISPOSITION) && + mg_ncasecmp(block_begin, CONTENT_DISPOSITION, + sizeof(CONTENT_DISPOSITION) - 1) == 0) { + struct mg_str header; + + header.p = block_begin + sizeof(CONTENT_DISPOSITION) - 1; + header.len = line_len - sizeof(CONTENT_DISPOSITION) - 1; + mg_http_parse_header(&header, "name", var_name, sizeof(var_name) - 2); + mg_http_parse_header(&header, "filename", file_name, + sizeof(file_name) - 2); + block_begin += line_len; + data_size -= line_len; + continue; + } + + if (line_len == 2 && mg_ncasecmp(block_begin, "\r\n", 2) == 0) { + mbuf_remove(io, block_begin - io->buf + 2); + + if (pd->mp_stream.processing_part != 0) { + mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_END, NULL, 0); + } + + free((void *) pd->mp_stream.file_name); + pd->mp_stream.file_name = strdup(file_name); + free((void *) pd->mp_stream.var_name); + pd->mp_stream.var_name = strdup(var_name); + + mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_BEGIN, NULL, 0); + pd->mp_stream.state = MPS_WAITING_FOR_CHUNK; + pd->mp_stream.processing_part++; + return 1; + } + + block_begin += line_len; + } + + pd->mp_stream.state = MPS_WAITING_FOR_BOUNDARY; + + return 0; +} + +static int mg_http_multipart_continue_wait_for_chunk(struct mg_connection *c) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + struct mbuf *io = &c->recv_mbuf; + + const char *boundary; + if ((int) io->len < pd->mp_stream.boundary_len + 6 /* \r\n, --, -- */) { + return 0; + } + + boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len); + if (boundary == NULL && pd->mp_stream.prev_io_len == 0) { + pd->mp_stream.prev_io_len = io->len; + return 0; + } else if (boundary == NULL && + (int) io->len > + pd->mp_stream.prev_io_len + pd->mp_stream.boundary_len + 4) { + pd->mp_stream.state = MPS_GOT_CHUNK; + return 1; + } else if (boundary != NULL) { + int data_size = (boundary - io->buf - 4); + mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_DATA, io->buf, data_size); + mbuf_remove(io, (boundary - io->buf)); + pd->mp_stream.prev_io_len = 0; + pd->mp_stream.state = MPS_WAITING_FOR_BOUNDARY; + return 1; + } else { + return 0; + } +} + +static void mg_http_multipart_continue(struct mg_connection *c) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(c); + while (1) { + switch (pd->mp_stream.state) { + case MPS_BEGIN: { + pd->mp_stream.state = MPS_WAITING_FOR_BOUNDARY; + break; + } + case MPS_WAITING_FOR_BOUNDARY: { + if (mg_http_multipart_wait_for_boundary(c) == 0) { + return; + } + break; + } + case MPS_GOT_BOUNDARY: { + if (mg_http_multipart_process_boundary(c) == 0) { + return; + } + break; + } + case MPS_WAITING_FOR_CHUNK: { + if (mg_http_multipart_continue_wait_for_chunk(c) == 0) { + return; + } + break; + } + case MPS_GOT_CHUNK: { + if (mg_http_multipart_got_chunk(c) == 0) { + return; + } + break; + } + case MPS_FINALIZE: { + if (mg_http_multipart_finalize(c) == 0) { + return; + } + break; + } + case MPS_FINISHED: { + mbuf_remove(&c->recv_mbuf, c->recv_mbuf.len); + return; + } + } + } +} + +struct file_upload_state { + char *lfn; + size_t num_recd; + FILE *fp; +}; + +#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */ + +void mg_set_protocol_http_websocket(struct mg_connection *nc) { + nc->proto_handler = mg_http_handler; +} + +const char *mg_status_message(int status_code) { + switch (status_code) { + case 206: + return "Partial Content"; + case 301: + return "Moved"; + case 302: + return "Found"; + case 400: + return "Bad Request"; + case 401: + return "Unauthorized"; + case 403: + return "Forbidden"; + case 404: + return "Not Found"; + case 416: + return "Requested Range Not Satisfiable"; + case 418: + return "I'm a teapot"; + case 500: + return "Internal Server Error"; + case 502: + return "Bad Gateway"; + case 503: + return "Service Unavailable"; + +#if MG_ENABLE_EXTRA_ERRORS_DESC + case 100: + return "Continue"; + case 101: + return "Switching Protocols"; + case 102: + return "Processing"; + case 200: + return "OK"; + case 201: + return "Created"; + case 202: + return "Accepted"; + case 203: + return "Non-Authoritative Information"; + case 204: + return "No Content"; + case 205: + return "Reset Content"; + case 207: + return "Multi-Status"; + case 208: + return "Already Reported"; + case 226: + return "IM Used"; + case 300: + return "Multiple Choices"; + case 303: + return "See Other"; + case 304: + return "Not Modified"; + case 305: + return "Use Proxy"; + case 306: + return "Switch Proxy"; + case 307: + return "Temporary Redirect"; + case 308: + return "Permanent Redirect"; + case 402: + return "Payment Required"; + case 405: + return "Method Not Allowed"; + case 406: + return "Not Acceptable"; + case 407: + return "Proxy Authentication Required"; + case 408: + return "Request Timeout"; + case 409: + return "Conflict"; + case 410: + return "Gone"; + case 411: + return "Length Required"; + case 412: + return "Precondition Failed"; + case 413: + return "Payload Too Large"; + case 414: + return "URI Too Long"; + case 415: + return "Unsupported Media Type"; + case 417: + return "Expectation Failed"; + case 422: + return "Unprocessable Entity"; + case 423: + return "Locked"; + case 424: + return "Failed Dependency"; + case 426: + return "Upgrade Required"; + case 428: + return "Precondition Required"; + case 429: + return "Too Many Requests"; + case 431: + return "Request Header Fields Too Large"; + case 451: + return "Unavailable For Legal Reasons"; + case 501: + return "Not Implemented"; + case 504: + return "Gateway Timeout"; + case 505: + return "HTTP Version Not Supported"; + case 506: + return "Variant Also Negotiates"; + case 507: + return "Insufficient Storage"; + case 508: + return "Loop Detected"; + case 510: + return "Not Extended"; + case 511: + return "Network Authentication Required"; +#endif /* MG_ENABLE_EXTRA_ERRORS_DESC */ + + default: + return "OK"; + } +} + +void mg_send_response_line_s(struct mg_connection *nc, int status_code, + const struct mg_str extra_headers) { + mg_printf(nc, "HTTP/1.1 %d %s\r\nServer: %s\r\n", status_code, + mg_status_message(status_code), mg_version_header); + if (extra_headers.len > 0) { + mg_printf(nc, "%.*s\r\n", (int) extra_headers.len, extra_headers.p); + } +} + +void mg_send_response_line(struct mg_connection *nc, int status_code, + const char *extra_headers) { + mg_send_response_line_s(nc, status_code, mg_mk_str(extra_headers)); +} + +void mg_http_send_redirect(struct mg_connection *nc, int status_code, + const struct mg_str location, + const struct mg_str extra_headers) { + char bbody[100], *pbody = bbody; + int bl = mg_asprintf(&pbody, sizeof(bbody), + "

Moved here.\r\n", + (int) location.len, location.p); + char bhead[150], *phead = bhead; + mg_asprintf(&phead, sizeof(bhead), + "Location: %.*s\r\n" + "Content-Type: text/html\r\n" + "Content-Length: %d\r\n" + "Cache-Control: no-cache\r\n" + "%.*s%s", + (int) location.len, location.p, bl, (int) extra_headers.len, + extra_headers.p, (extra_headers.len > 0 ? "\r\n" : "")); + mg_send_response_line(nc, status_code, phead); + if (phead != bhead) MG_FREE(phead); + mg_send(nc, pbody, bl); + if (pbody != bbody) MG_FREE(pbody); +} + +void mg_send_head(struct mg_connection *c, int status_code, + int64_t content_length, const char *extra_headers) { + mg_send_response_line(c, status_code, extra_headers); + if (content_length < 0) { + mg_printf(c, "%s", "Transfer-Encoding: chunked\r\n"); + } else { + mg_printf(c, "Content-Length: %" INT64_FMT "\r\n", content_length); + } + mg_send(c, "\r\n", 2); +} + +void mg_http_send_error(struct mg_connection *nc, int code, + const char *reason) { + if (!reason) reason = mg_status_message(code); + LOG(LL_DEBUG, ("%p %d %s", nc, code, reason)); + mg_send_head(nc, code, strlen(reason), + "Content-Type: text/plain\r\nConnection: close"); + mg_send(nc, reason, strlen(reason)); + nc->flags |= MG_F_SEND_AND_CLOSE; +} + +#if MG_ENABLE_FILESYSTEM +static void mg_http_construct_etag(char *buf, size_t buf_len, + const cs_stat_t *st) { + snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"", (unsigned long) st->st_mtime, + (int64_t) st->st_size); +} + +#ifndef WINCE +static void mg_gmt_time_string(char *buf, size_t buf_len, time_t *t) { + strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t)); +} +#else +/* Look wince_lib.c for WindowsCE implementation */ +static void mg_gmt_time_string(char *buf, size_t buf_len, time_t *t); +#endif + +static int mg_http_parse_range_header(const struct mg_str *header, int64_t *a, + int64_t *b) { + /* + * There is no snscanf. Headers are not guaranteed to be NUL-terminated, + * so we have this. Ugh. + */ + int result; + char *p = (char *) MG_MALLOC(header->len + 1); + if (p == NULL) return 0; + memcpy(p, header->p, header->len); + p[header->len] = '\0'; + result = sscanf(p, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b); + MG_FREE(p); + return result; +} + +void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm, + const char *path, const struct mg_str mime_type, + const struct mg_str extra_headers) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + cs_stat_t st; + LOG(LL_DEBUG, ("%p [%s] %.*s", nc, path, (int) mime_type.len, mime_type.p)); + if (mg_stat(path, &st) != 0 || (pd->file.fp = mg_fopen(path, "rb")) == NULL) { + int code, err = mg_get_errno(); + switch (err) { + case EACCES: + code = 403; + break; + case ENOENT: + code = 404; + break; + default: + code = 500; + }; + mg_http_send_error(nc, code, "Open failed"); + } else { + char etag[50], current_time[50], last_modified[50], range[70]; + time_t t = (time_t) mg_time(); + int64_t r1 = 0, r2 = 0, cl = st.st_size; + struct mg_str *range_hdr = mg_get_http_header(hm, "Range"); + int n, status_code = 200; + + /* Handle Range header */ + range[0] = '\0'; + if (range_hdr != NULL && + (n = mg_http_parse_range_header(range_hdr, &r1, &r2)) > 0 && r1 >= 0 && + r2 >= 0) { + /* If range is specified like "400-", set second limit to content len */ + if (n == 1) { + r2 = cl - 1; + } + if (r1 > r2 || r2 >= cl) { + status_code = 416; + cl = 0; + snprintf(range, sizeof(range), + "Content-Range: bytes */%" INT64_FMT "\r\n", + (int64_t) st.st_size); + } else { + status_code = 206; + cl = r2 - r1 + 1; + snprintf(range, sizeof(range), "Content-Range: bytes %" INT64_FMT + "-%" INT64_FMT "/%" INT64_FMT "\r\n", + r1, r1 + cl - 1, (int64_t) st.st_size); +#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \ + _XOPEN_SOURCE >= 600 + fseeko(pd->file.fp, r1, SEEK_SET); +#else + fseek(pd->file.fp, (long) r1, SEEK_SET); +#endif + } + } + +#if !MG_DISABLE_HTTP_KEEP_ALIVE + { + struct mg_str *conn_hdr = mg_get_http_header(hm, "Connection"); + if (conn_hdr != NULL) { + pd->file.keepalive = (mg_vcasecmp(conn_hdr, "keep-alive") == 0); + } else { + pd->file.keepalive = (mg_vcmp(&hm->proto, "HTTP/1.1") == 0); + } + } +#endif + + mg_http_construct_etag(etag, sizeof(etag), &st); + mg_gmt_time_string(current_time, sizeof(current_time), &t); + mg_gmt_time_string(last_modified, sizeof(last_modified), &st.st_mtime); + /* + * Content length casted to size_t because: + * 1) that's the maximum buffer size anyway + * 2) ESP8266 RTOS SDK newlib vprintf cannot contain a 64bit arg at non-last + * position + * TODO(mkm): fix ESP8266 RTOS SDK + */ + mg_send_response_line_s(nc, status_code, extra_headers); + mg_printf(nc, + "Date: %s\r\n" + "Last-Modified: %s\r\n" + "Accept-Ranges: bytes\r\n" + "Content-Type: %.*s\r\n" + "Connection: %s\r\n" + "Content-Length: %" SIZE_T_FMT + "\r\n" + "%sEtag: %s\r\n\r\n", + current_time, last_modified, (int) mime_type.len, mime_type.p, + (pd->file.keepalive ? "keep-alive" : "close"), (size_t) cl, range, + etag); + + pd->file.cl = cl; + pd->file.type = DATA_FILE; + mg_http_transfer_file_data(nc); + } +} + +static void mg_http_serve_file2(struct mg_connection *nc, const char *path, + struct http_message *hm, + struct mg_serve_http_opts *opts) { +#if MG_ENABLE_HTTP_SSI + if (mg_match_prefix(opts->ssi_pattern, strlen(opts->ssi_pattern), path) > 0) { + mg_handle_ssi_request(nc, hm, path, opts); + return; + } +#endif + mg_http_serve_file(nc, hm, path, mg_get_mime_type(path, "text/plain", opts), + mg_mk_str(opts->extra_headers)); +} + +#endif + +int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, + int is_form_url_encoded) { + int i, j, a, b; +#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W') + + for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { + if (src[i] == '%') { + if (i < src_len - 2 && isxdigit(*(const unsigned char *) (src + i + 1)) && + isxdigit(*(const unsigned char *) (src + i + 2))) { + a = tolower(*(const unsigned char *) (src + i + 1)); + b = tolower(*(const unsigned char *) (src + i + 2)); + dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b)); + i += 2; + } else { + return -1; + } + } else if (is_form_url_encoded && src[i] == '+') { + dst[j] = ' '; + } else { + dst[j] = src[i]; + } + } + + dst[j] = '\0'; /* Null-terminate the destination */ + + return i >= src_len ? j : -1; +} + +int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst, + size_t dst_len) { + const char *p, *e, *s; + size_t name_len; + int len; + + if (dst == NULL || dst_len == 0) { + len = -2; + } else if (buf->p == NULL || name == NULL || buf->len == 0) { + len = -1; + dst[0] = '\0'; + } else { + name_len = strlen(name); + e = buf->p + buf->len; + len = -1; + dst[0] = '\0'; + + for (p = buf->p; p + name_len < e; p++) { + if ((p == buf->p || p[-1] == '&') && p[name_len] == '=' && + !mg_ncasecmp(name, p, name_len)) { + p += name_len + 1; + s = (const char *) memchr(p, '&', (size_t)(e - p)); + if (s == NULL) { + s = e; + } + len = mg_url_decode(p, (size_t)(s - p), dst, dst_len, 1); + if (len == -1) { + len = -2; + } + break; + } + } + } + + return len; +} + +void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len) { + char chunk_size[50]; + int n; + + n = snprintf(chunk_size, sizeof(chunk_size), "%lX\r\n", (unsigned long) len); + mg_send(nc, chunk_size, n); + mg_send(nc, buf, len); + mg_send(nc, "\r\n", 2); +} + +void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...) { + char mem[MG_VPRINTF_BUFFER_SIZE], *buf = mem; + int len; + va_list ap; + + va_start(ap, fmt); + len = mg_avprintf(&buf, sizeof(mem), fmt, ap); + va_end(ap); + + if (len >= 0) { + mg_send_http_chunk(nc, buf, len); + } + + /* LCOV_EXCL_START */ + if (buf != mem && buf != NULL) { + MG_FREE(buf); + } + /* LCOV_EXCL_STOP */ +} + +void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...) { + char mem[MG_VPRINTF_BUFFER_SIZE], *buf = mem; + int i, j, len; + va_list ap; + + va_start(ap, fmt); + len = mg_avprintf(&buf, sizeof(mem), fmt, ap); + va_end(ap); + + if (len >= 0) { + for (i = j = 0; i < len; i++) { + if (buf[i] == '<' || buf[i] == '>') { + mg_send(nc, buf + j, i - j); + mg_send(nc, buf[i] == '<' ? "<" : ">", 4); + j = i + 1; + } + } + mg_send(nc, buf + j, i - j); + } + + /* LCOV_EXCL_START */ + if (buf != mem && buf != NULL) { + MG_FREE(buf); + } + /* LCOV_EXCL_STOP */ +} + +int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf, + size_t buf_size) { + int ch = ' ', ch1 = ',', len = 0, n = strlen(var_name); + const char *p, *end = hdr ? hdr->p + hdr->len : NULL, *s = NULL; + + if (buf != NULL && buf_size > 0) buf[0] = '\0'; + if (hdr == NULL) return 0; + + /* Find where variable starts */ + for (s = hdr->p; s != NULL && s + n < end; s++) { + if ((s == hdr->p || s[-1] == ch || s[-1] == ch1) && s[n] == '=' && + !strncmp(s, var_name, n)) + break; + } + + if (s != NULL && &s[n + 1] < end) { + s += n + 1; + if (*s == '"' || *s == '\'') { + ch = ch1 = *s++; + } + p = s; + while (p < end && p[0] != ch && p[0] != ch1 && len < (int) buf_size) { + if (ch != ' ' && p[0] == '\\' && p[1] == ch) p++; + buf[len++] = *p++; + } + if (len >= (int) buf_size || (ch != ' ' && *p != ch)) { + len = 0; + } else { + if (len > 0 && s[len - 1] == ',') len--; + if (len > 0 && s[len - 1] == ';') len--; + buf[len] = '\0'; + } + } + + return len; +} + +int mg_get_http_basic_auth(struct http_message *hm, char *user, size_t user_len, + char *pass, size_t pass_len) { + struct mg_str *hdr = mg_get_http_header(hm, "Authorization"); + if (hdr == NULL) return -1; + return mg_parse_http_basic_auth(hdr, user, user_len, pass, pass_len); +} + +int mg_parse_http_basic_auth(struct mg_str *hdr, char *user, size_t user_len, + char *pass, size_t pass_len) { + char *buf = NULL; + char fmt[64]; + int res = 0; + + if (mg_strncmp(*hdr, mg_mk_str("Basic "), 6) != 0) return -1; + + buf = (char *) MG_MALLOC(hdr->len); + cs_base64_decode((unsigned char *) hdr->p + 6, hdr->len, buf, NULL); + + /* e.g. "%123[^:]:%321[^\n]" */ + snprintf(fmt, sizeof(fmt), "%%%" SIZE_T_FMT "[^:]:%%%" SIZE_T_FMT "[^\n]", + user_len - 1, pass_len - 1); + if (sscanf(buf, fmt, user, pass) == 0) { + res = -1; + } + + MG_FREE(buf); + return res; +} + +#if MG_ENABLE_FILESYSTEM +static int mg_is_file_hidden(const char *path, + const struct mg_serve_http_opts *opts, + int exclude_specials) { + const char *p1 = opts->per_directory_auth_file; + const char *p2 = opts->hidden_file_pattern; + + /* Strip directory path from the file name */ + const char *pdir = strrchr(path, DIRSEP); + if (pdir != NULL) { + path = pdir + 1; + } + + return (exclude_specials && (!strcmp(path, ".") || !strcmp(path, ".."))) || + (p1 != NULL && + mg_match_prefix(p1, strlen(p1), path) == (int) strlen(p1)) || + (p2 != NULL && mg_match_prefix(p2, strlen(p2), path) > 0); +} + +#if !MG_DISABLE_HTTP_DIGEST_AUTH +static void mg_mkmd5resp(const char *method, size_t method_len, const char *uri, + size_t uri_len, const char *ha1, size_t ha1_len, + const char *nonce, size_t nonce_len, const char *nc, + size_t nc_len, const char *cnonce, size_t cnonce_len, + const char *qop, size_t qop_len, char *resp) { + static const char colon[] = ":"; + static const size_t one = 1; + char ha2[33]; + + cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL); + cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc, + nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len, + colon, one, ha2, sizeof(ha2) - 1, NULL); +} + +int mg_http_create_digest_auth_header(char *buf, size_t buf_len, + const char *method, const char *uri, + const char *auth_domain, const char *user, + const char *passwd) { + static const char colon[] = ":", qop[] = "auth"; + static const size_t one = 1; + char ha1[33], resp[33], cnonce[40]; + + snprintf(cnonce, sizeof(cnonce), "%x", (unsigned int) mg_time()); + cs_md5(ha1, user, (size_t) strlen(user), colon, one, auth_domain, + (size_t) strlen(auth_domain), colon, one, passwd, + (size_t) strlen(passwd), NULL); + mg_mkmd5resp(method, strlen(method), uri, strlen(uri), ha1, sizeof(ha1) - 1, + cnonce, strlen(cnonce), "1", one, cnonce, strlen(cnonce), qop, + sizeof(qop) - 1, resp); + return snprintf(buf, buf_len, + "Authorization: Digest username=\"%s\"," + "realm=\"%s\",uri=\"%s\",qop=%s,nc=1,cnonce=%s," + "nonce=%s,response=%s\r\n", + user, auth_domain, uri, qop, cnonce, cnonce, resp); +} + +/* + * Check for authentication timeout. + * Clients send time stamp encoded in nonce. Make sure it is not too old, + * to prevent replay attacks. + * Assumption: nonce is a hexadecimal number of seconds since 1970. + */ +static int mg_check_nonce(const char *nonce) { + unsigned long now = (unsigned long) mg_time(); + unsigned long val = (unsigned long) strtoul(nonce, NULL, 16); + return now < val || now - val < 3600; +} + +int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain, + FILE *fp) { + struct mg_str *hdr; + char buf[128], f_user[sizeof(buf)], f_ha1[sizeof(buf)], f_domain[sizeof(buf)]; + char user[50], cnonce[33], response[40], uri[200], qop[20], nc[20], nonce[30]; + char expected_response[33]; + + /* Parse "Authorization:" header, fail fast on parse error */ + if (hm == NULL || fp == NULL || + (hdr = mg_get_http_header(hm, "Authorization")) == NULL || + mg_http_parse_header(hdr, "username", user, sizeof(user)) == 0 || + mg_http_parse_header(hdr, "cnonce", cnonce, sizeof(cnonce)) == 0 || + mg_http_parse_header(hdr, "response", response, sizeof(response)) == 0 || + mg_http_parse_header(hdr, "uri", uri, sizeof(uri)) == 0 || + mg_http_parse_header(hdr, "qop", qop, sizeof(qop)) == 0 || + mg_http_parse_header(hdr, "nc", nc, sizeof(nc)) == 0 || + mg_http_parse_header(hdr, "nonce", nonce, sizeof(nonce)) == 0 || + mg_check_nonce(nonce) == 0) { + return 0; + } + + /* + * Read passwords file line by line. If should have htdigest format, + * i.e. each line should be a colon-separated sequence: + * USER_NAME:DOMAIN_NAME:HA1_HASH_OF_USER_DOMAIN_AND_PASSWORD + */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (sscanf(buf, "%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3 && + strcmp(user, f_user) == 0 && + /* NOTE(lsm): due to a bug in MSIE, we do not compare URIs */ + strcmp(auth_domain, f_domain) == 0) { + /* User and domain matched, check the password */ + mg_mkmd5resp( + hm->method.p, hm->method.len, hm->uri.p, + hm->uri.len + (hm->query_string.len ? hm->query_string.len + 1 : 0), + f_ha1, strlen(f_ha1), nonce, strlen(nonce), nc, strlen(nc), cnonce, + strlen(cnonce), qop, strlen(qop), expected_response); + return mg_casecmp(response, expected_response) == 0; + } + } + + /* None of the entries in the passwords file matched - return failure */ + return 0; +} + +static int mg_is_authorized(struct http_message *hm, const char *path, + int is_directory, const char *domain, + const char *passwords_file, + int is_global_pass_file) { + char buf[MG_MAX_PATH]; + const char *p; + FILE *fp; + int authorized = 1; + + if (domain != NULL && passwords_file != NULL) { + if (is_global_pass_file) { + fp = mg_fopen(passwords_file, "r"); + } else if (is_directory) { + snprintf(buf, sizeof(buf), "%s%c%s", path, DIRSEP, passwords_file); + fp = mg_fopen(buf, "r"); + } else { + p = strrchr(path, DIRSEP); + if (p == NULL) p = path; + snprintf(buf, sizeof(buf), "%.*s%c%s", (int) (p - path), path, DIRSEP, + passwords_file); + fp = mg_fopen(buf, "r"); + } + + if (fp != NULL) { + authorized = mg_http_check_digest_auth(hm, domain, fp); + fclose(fp); + } + } + + LOG(LL_DEBUG, ("%s '%s' %d %d", path, passwords_file ? passwords_file : "", + is_global_pass_file, authorized)); + return authorized; +} +#else +static int mg_is_authorized(struct http_message *hm, const char *path, + int is_directory, const char *domain, + const char *passwords_file, + int is_global_pass_file) { + (void) hm; + (void) path; + (void) is_directory; + (void) domain; + (void) passwords_file; + (void) is_global_pass_file; + return 1; +} +#endif + +#if MG_ENABLE_DIRECTORY_LISTING +static size_t mg_url_encode(const char *src, size_t s_len, char *dst, + size_t dst_len) { + static const char *dont_escape = "._-$,;~()/"; + static const char *hex = "0123456789abcdef"; + size_t i = 0, j = 0; + + for (i = j = 0; dst_len > 0 && i < s_len && j + 2 < dst_len - 1; i++, j++) { + if (isalnum(*(const unsigned char *) (src + i)) || + strchr(dont_escape, *(const unsigned char *) (src + i)) != NULL) { + dst[j] = src[i]; + } else if (j + 3 < dst_len) { + dst[j] = '%'; + dst[j + 1] = hex[(*(const unsigned char *) (src + i)) >> 4]; + dst[j + 2] = hex[(*(const unsigned char *) (src + i)) & 0xf]; + j += 2; + } + } + + dst[j] = '\0'; + return j; +} + +static void mg_escape(const char *src, char *dst, size_t dst_len) { + size_t n = 0; + while (*src != '\0' && n + 5 < dst_len) { + unsigned char ch = *(unsigned char *) src++; + if (ch == '<') { + n += snprintf(dst + n, dst_len - n, "%s", "<"); + } else { + dst[n++] = ch; + } + } + dst[n] = '\0'; +} + +static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name, + cs_stat_t *stp) { + char size[64], mod[64], href[MAX_PATH_SIZE * 3], path[MAX_PATH_SIZE]; + int64_t fsize = stp->st_size; + int is_dir = S_ISDIR(stp->st_mode); + const char *slash = is_dir ? "/" : ""; + + if (is_dir) { + snprintf(size, sizeof(size), "%s", "[DIRECTORY]"); + } else { + /* + * We use (double) cast below because MSVC 6 compiler cannot + * convert unsigned __int64 to double. + */ + if (fsize < 1024) { + snprintf(size, sizeof(size), "%d", (int) fsize); + } else if (fsize < 0x100000) { + snprintf(size, sizeof(size), "%.1fk", (double) fsize / 1024.0); + } else if (fsize < 0x40000000) { + snprintf(size, sizeof(size), "%.1fM", (double) fsize / 1048576); + } else { + snprintf(size, sizeof(size), "%.1fG", (double) fsize / 1073741824); + } + } + strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime)); + mg_escape(file_name, path, sizeof(path)); + mg_url_encode(file_name, strlen(file_name), href, sizeof(href)); + mg_printf_http_chunk(nc, + "%s%s" + "%s%s\n", + href, slash, path, slash, mod, is_dir ? -1 : fsize, + size); +} + +static void mg_scan_directory(struct mg_connection *nc, const char *dir, + const struct mg_serve_http_opts *opts, + void (*func)(struct mg_connection *, const char *, + cs_stat_t *)) { + char path[MAX_PATH_SIZE]; + cs_stat_t st; + struct dirent *dp; + DIR *dirp; + + LOG(LL_DEBUG, ("%p [%s]", nc, dir)); + if ((dirp = (opendir(dir))) != NULL) { + while ((dp = readdir(dirp)) != NULL) { + /* Do not show current dir and hidden files */ + if (mg_is_file_hidden((const char *) dp->d_name, opts, 1)) { + continue; + } + snprintf(path, sizeof(path), "%s/%s", dir, dp->d_name); + if (mg_stat(path, &st) == 0) { + func(nc, (const char *) dp->d_name, &st); + } + } + closedir(dirp); + } else { + LOG(LL_DEBUG, ("%p opendir(%s) -> %d", nc, dir, mg_get_errno())); + } +} + +static void mg_send_directory_listing(struct mg_connection *nc, const char *dir, + struct http_message *hm, + struct mg_serve_http_opts *opts) { + static const char *sort_js_code = + ""; + + mg_send_response_line(nc, 200, opts->extra_headers); + mg_printf(nc, "%s: %s\r\n%s: %s\r\n\r\n", "Transfer-Encoding", "chunked", + "Content-Type", "text/html; charset=utf-8"); + + mg_printf_http_chunk( + nc, + "Index of %.*s%s%s" + "\n" + "

Index of %.*s

\n" + "" + "\n" + "\n" + "", + (int) hm->uri.len, hm->uri.p, sort_js_code, sort_js_code2, + (int) hm->uri.len, hm->uri.p); + mg_scan_directory(nc, dir, opts, mg_print_dir_entry); + mg_printf_http_chunk(nc, + "\n" + "
Name" + "Modified" + "Size


\n" + "
%s
\n" + "", + mg_version_header); + mg_send_http_chunk(nc, "", 0); + /* TODO(rojer): Remove when cesanta/dev/issues/197 is fixed. */ + nc->flags |= MG_F_SEND_AND_CLOSE; +} +#endif /* MG_ENABLE_DIRECTORY_LISTING */ + +/* + * Given a directory path, find one of the files specified in the + * comma-separated list of index files `list`. + * First found index file wins. If an index file is found, then gets + * appended to the `path`, stat-ed, and result of `stat()` passed to `stp`. + * If index file is not found, then `path` and `stp` remain unchanged. + */ +MG_INTERNAL void mg_find_index_file(const char *path, const char *list, + char **index_file, cs_stat_t *stp) { + struct mg_str vec; + size_t path_len = strlen(path); + int found = 0; + *index_file = NULL; + + /* Traverse index files list. For each entry, append it to the given */ + /* path and see if the file exists. If it exists, break the loop */ + while ((list = mg_next_comma_list_entry(list, &vec, NULL)) != NULL) { + cs_stat_t st; + size_t len = path_len + 1 + vec.len + 1; + *index_file = (char *) MG_REALLOC(*index_file, len); + if (*index_file == NULL) break; + snprintf(*index_file, len, "%s%c%.*s", path, DIRSEP, (int) vec.len, vec.p); + + /* Does it exist? Is it a file? */ + if (mg_stat(*index_file, &st) == 0 && S_ISREG(st.st_mode)) { + /* Yes it does, break the loop */ + *stp = st; + found = 1; + break; + } + } + if (!found) { + MG_FREE(*index_file); + *index_file = NULL; + } + LOG(LL_DEBUG, ("[%s] [%s]", path, (*index_file ? *index_file : ""))); +} + +#if MG_ENABLE_HTTP_URL_REWRITES +static int mg_http_send_port_based_redirect( + struct mg_connection *c, struct http_message *hm, + const struct mg_serve_http_opts *opts) { + const char *rewrites = opts->url_rewrites; + struct mg_str a, b; + char local_port[20] = {'%'}; + + mg_conn_addr_to_str(c, local_port + 1, sizeof(local_port) - 1, + MG_SOCK_STRINGIFY_PORT); + + while ((rewrites = mg_next_comma_list_entry(rewrites, &a, &b)) != NULL) { + if (mg_vcmp(&a, local_port) == 0) { + mg_send_response_line(c, 301, NULL); + mg_printf(c, "Content-Length: 0\r\nLocation: %.*s%.*s\r\n\r\n", + (int) b.len, b.p, (int) (hm->proto.p - hm->uri.p - 1), + hm->uri.p); + return 1; + } + } + + return 0; +} + +static void mg_reverse_proxy_handler(struct mg_connection *nc, int ev, + void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + + if (pd == NULL || pd->reverse_proxy_data.linked_conn == NULL) { + DBG(("%p: upstream closed", nc)); + return; + } + + switch (ev) { + case MG_EV_CONNECT: + if (*(int *) ev_data != 0) { + mg_http_send_error(pd->reverse_proxy_data.linked_conn, 502, NULL); + } + break; + /* TODO(mkm): handle streaming */ + case MG_EV_HTTP_REPLY: + mg_send(pd->reverse_proxy_data.linked_conn, hm->message.p, + hm->message.len); + pd->reverse_proxy_data.linked_conn->flags |= MG_F_SEND_AND_CLOSE; + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + case MG_EV_CLOSE: + pd->reverse_proxy_data.linked_conn->flags |= MG_F_SEND_AND_CLOSE; + break; + } +} + +void mg_http_reverse_proxy(struct mg_connection *nc, + const struct http_message *hm, struct mg_str mount, + struct mg_str upstream) { + struct mg_connection *be; + char burl[256], *purl = burl; + char *addr = NULL; + const char *path = NULL; + int i; + const char *error; + struct mg_connect_opts opts; + memset(&opts, 0, sizeof(opts)); + opts.error_string = &error; + + mg_asprintf(&purl, sizeof(burl), "%.*s%.*s", (int) upstream.len, upstream.p, + (int) (hm->uri.len - mount.len), hm->uri.p + mount.len); + + be = mg_connect_http_base(nc->mgr, mg_reverse_proxy_handler, opts, "http://", + "https://", purl, &path, NULL /* user */, + NULL /* pass */, &addr); + LOG(LL_DEBUG, ("Proxying %.*s to %s (rule: %.*s)", (int) hm->uri.len, + hm->uri.p, purl, (int) mount.len, mount.p)); + + if (be == NULL) { + LOG(LL_ERROR, ("Error connecting to %s: %s", purl, error)); + mg_http_send_error(nc, 502, NULL); + goto cleanup; + } + + /* link connections to each other, they must live and die together */ + mg_http_get_proto_data(be)->reverse_proxy_data.linked_conn = nc; + mg_http_get_proto_data(nc)->reverse_proxy_data.linked_conn = be; + + /* send request upstream */ + mg_printf(be, "%.*s %s HTTP/1.1\r\n", (int) hm->method.len, hm->method.p, + path); + + mg_printf(be, "Host: %s\r\n", addr); + for (i = 0; i < MG_MAX_HTTP_HEADERS && hm->header_names[i].len > 0; i++) { + struct mg_str hn = hm->header_names[i]; + struct mg_str hv = hm->header_values[i]; + + /* we rewrite the host header */ + if (mg_vcasecmp(&hn, "Host") == 0) continue; + /* + * Don't pass chunked transfer encoding to the client because hm->body is + * already dechunked when we arrive here. + */ + if (mg_vcasecmp(&hn, "Transfer-encoding") == 0 && + mg_vcasecmp(&hv, "chunked") == 0) { + mg_printf(be, "Content-Length: %" SIZE_T_FMT "\r\n", hm->body.len); + continue; + } + /* We don't support proxying Expect: 100-continue. */ + if (mg_vcasecmp(&hn, "Expect") == 0 && + mg_vcasecmp(&hv, "100-continue") == 0) { + continue; + } + + mg_printf(be, "%.*s: %.*s\r\n", (int) hn.len, hn.p, (int) hv.len, hv.p); + } + + mg_send(be, "\r\n", 2); + mg_send(be, hm->body.p, hm->body.len); + +cleanup: + if (purl != burl) MG_FREE(purl); +} + +static int mg_http_handle_forwarding(struct mg_connection *nc, + struct http_message *hm, + const struct mg_serve_http_opts *opts) { + const char *rewrites = opts->url_rewrites; + struct mg_str a, b; + struct mg_str p1 = MG_MK_STR("http://"), p2 = MG_MK_STR("https://"); + + while ((rewrites = mg_next_comma_list_entry(rewrites, &a, &b)) != NULL) { + if (mg_strncmp(a, hm->uri, a.len) == 0) { + if (mg_strncmp(b, p1, p1.len) == 0 || mg_strncmp(b, p2, p2.len) == 0) { + mg_http_reverse_proxy(nc, hm, a, b); + return 1; + } + } + } + + return 0; +} +#endif + +MG_INTERNAL int mg_uri_to_local_path(struct http_message *hm, + const struct mg_serve_http_opts *opts, + char **local_path, + struct mg_str *remainder) { + int ok = 1; + const char *cp = hm->uri.p, *cp_end = hm->uri.p + hm->uri.len; + struct mg_str root = {NULL, 0}; + const char *file_uri_start = cp; + *local_path = NULL; + remainder->p = NULL; + remainder->len = 0; + + { /* 1. Determine which root to use. */ + +#if MG_ENABLE_HTTP_URL_REWRITES + const char *rewrites = opts->url_rewrites; +#else + const char *rewrites = ""; +#endif + struct mg_str *hh = mg_get_http_header(hm, "Host"); + struct mg_str a, b; + /* Check rewrites first. */ + while ((rewrites = mg_next_comma_list_entry(rewrites, &a, &b)) != NULL) { + if (a.len > 1 && a.p[0] == '@') { + /* Host rewrite. */ + if (hh != NULL && hh->len == a.len - 1 && + mg_ncasecmp(a.p + 1, hh->p, a.len - 1) == 0) { + root = b; + break; + } + } else { + /* Regular rewrite, URI=directory */ + int match_len = mg_match_prefix_n(a, hm->uri); + if (match_len > 0) { + file_uri_start = hm->uri.p + match_len; + if (*file_uri_start == '/' || file_uri_start == cp_end) { + /* Match ended at component boundary, ok. */ + } else if (*(file_uri_start - 1) == '/') { + /* Pattern ends with '/', backtrack. */ + file_uri_start--; + } else { + /* No match: must fall on the component boundary. */ + continue; + } + root = b; + break; + } + } + } + /* If no rewrite rules matched, use DAV or regular document root. */ + if (root.p == NULL) { +#if MG_ENABLE_HTTP_WEBDAV + if (opts->dav_document_root != NULL && mg_is_dav_request(&hm->method)) { + root.p = opts->dav_document_root; + root.len = strlen(opts->dav_document_root); + } else +#endif + { + root.p = opts->document_root; + root.len = strlen(opts->document_root); + } + } + assert(root.p != NULL && root.len > 0); + } + + { /* 2. Find where in the canonical URI path the local path ends. */ + const char *u = file_uri_start + 1; + char *lp = (char *) MG_MALLOC(root.len + hm->uri.len + 1); + char *lp_end = lp + root.len + hm->uri.len + 1; + char *p = lp, *ps; + int exists = 1; + if (lp == NULL) { + ok = 0; + goto out; + } + memcpy(p, root.p, root.len); + p += root.len; + if (*(p - 1) == DIRSEP) p--; + *p = '\0'; + ps = p; + + /* Chop off URI path components one by one and build local path. */ + while (u <= cp_end) { + const char *next = u; + struct mg_str component; + if (exists) { + cs_stat_t st; + exists = (mg_stat(lp, &st) == 0); + if (exists && S_ISREG(st.st_mode)) { + /* We found the terminal, the rest of the URI (if any) is path_info. + */ + if (*(u - 1) == '/') u--; + break; + } + } + if (u >= cp_end) break; + parse_uri_component((const char **) &next, cp_end, '/', &component); + if (component.len > 0) { + int len; + memmove(p + 1, component.p, component.len); + len = mg_url_decode(p + 1, component.len, p + 1, lp_end - p - 1, 0); + if (len <= 0) { + ok = 0; + break; + } + component.p = p + 1; + component.len = len; + if (mg_vcmp(&component, ".") == 0) { + /* Yum. */ + } else if (mg_vcmp(&component, "..") == 0) { + while (p > ps && *p != DIRSEP) p--; + *p = '\0'; + } else { + size_t i; +#ifdef _WIN32 + /* On Windows, make sure it's valid Unicode (no funny stuff). */ + wchar_t buf[MG_MAX_PATH * 2]; + if (to_wchar(component.p, buf, MG_MAX_PATH) == 0) { + DBG(("[%.*s] smells funny", (int) component.len, component.p)); + ok = 0; + break; + } +#endif + *p++ = DIRSEP; + /* No NULs and DIRSEPs in the component (percent-encoded). */ + for (i = 0; i < component.len; i++, p++) { + if (*p == '\0' || *p == DIRSEP +#ifdef _WIN32 + /* On Windows, "/" is also accepted, so check for that too. */ + || + *p == '/' +#endif + ) { + ok = 0; + break; + } + } + } + } + u = next; + } + if (ok) { + *local_path = lp; + if (u > cp_end) u = cp_end; + remainder->p = u; + remainder->len = cp_end - u; + } else { + MG_FREE(lp); + } + } + +out: + LOG(LL_DEBUG, + ("'%.*s' -> '%s' + '%.*s'", (int) hm->uri.len, hm->uri.p, + *local_path ? *local_path : "", (int) remainder->len, remainder->p)); + return ok; +} + +static int mg_get_month_index(const char *s) { + static const char *month_names[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + size_t i; + + for (i = 0; i < ARRAY_SIZE(month_names); i++) + if (!strcmp(s, month_names[i])) return (int) i; + + return -1; +} + +static int mg_num_leap_years(int year) { + return year / 4 - year / 100 + year / 400; +} + +/* Parse UTC date-time string, and return the corresponding time_t value. */ +MG_INTERNAL time_t mg_parse_date_string(const char *datetime) { + static const unsigned short days_before_month[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + char month_str[32]; + int second, minute, hour, day, month, year, leap_days, days; + time_t result = (time_t) 0; + + if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d", &day, month_str, &year, &hour, + &minute, &second) == 6) || + (sscanf(datetime, "%d %3s %d %d:%d:%d", &day, month_str, &year, &hour, + &minute, &second) == 6) || + (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year, + &hour, &minute, &second) == 6) || + (sscanf(datetime, "%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour, + &minute, &second) == 6)) && + year > 1970 && (month = mg_get_month_index(month_str)) != -1) { + leap_days = mg_num_leap_years(year) - mg_num_leap_years(1970); + year -= 1970; + days = year * 365 + days_before_month[month] + (day - 1) + leap_days; + result = days * 24 * 3600 + hour * 3600 + minute * 60 + second; + } + + return result; +} + +MG_INTERNAL int mg_is_not_modified(struct http_message *hm, cs_stat_t *st) { + struct mg_str *hdr; + if ((hdr = mg_get_http_header(hm, "If-None-Match")) != NULL) { + char etag[64]; + mg_http_construct_etag(etag, sizeof(etag), st); + return mg_vcasecmp(hdr, etag) == 0; + } else if ((hdr = mg_get_http_header(hm, "If-Modified-Since")) != NULL) { + return st->st_mtime <= mg_parse_date_string(hdr->p); + } else { + return 0; + } +} + +static void mg_http_send_digest_auth_request(struct mg_connection *c, + const char *domain) { + mg_printf(c, + "HTTP/1.1 401 Unauthorized\r\n" + "WWW-Authenticate: Digest qop=\"auth\", " + "realm=\"%s\", nonce=\"%lu\"\r\n" + "Content-Length: 0\r\n\r\n", + domain, (unsigned long) mg_time()); +} + +static void mg_http_send_options(struct mg_connection *nc) { + mg_printf(nc, "%s", + "HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, CONNECT, OPTIONS" +#if MG_ENABLE_HTTP_WEBDAV + ", MKCOL, PUT, DELETE, PROPFIND, MOVE\r\nDAV: 1,2" +#endif + "\r\n\r\n"); + nc->flags |= MG_F_SEND_AND_CLOSE; +} + +static int mg_is_creation_request(const struct http_message *hm) { + return mg_vcmp(&hm->method, "MKCOL") == 0 || mg_vcmp(&hm->method, "PUT") == 0; +} + +MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path, + const struct mg_str *path_info, + struct http_message *hm, + struct mg_serve_http_opts *opts) { + int exists, is_directory, is_cgi; +#if MG_ENABLE_HTTP_WEBDAV + int is_dav = mg_is_dav_request(&hm->method); +#else + int is_dav = 0; +#endif + char *index_file = NULL; + cs_stat_t st; + + exists = (mg_stat(path, &st) == 0); + is_directory = exists && S_ISDIR(st.st_mode); + + if (is_directory) + mg_find_index_file(path, opts->index_files, &index_file, &st); + + is_cgi = + (mg_match_prefix(opts->cgi_file_pattern, strlen(opts->cgi_file_pattern), + index_file ? index_file : path) > 0); + + LOG(LL_DEBUG, + ("%p %.*s [%s] exists=%d is_dir=%d is_dav=%d is_cgi=%d index=%s", nc, + (int) hm->method.len, hm->method.p, path, exists, is_directory, is_dav, + is_cgi, index_file ? index_file : "")); + + if (is_directory && hm->uri.p[hm->uri.len - 1] != '/' && !is_dav) { + mg_printf(nc, + "HTTP/1.1 301 Moved\r\nLocation: %.*s/\r\n" + "Content-Length: 0\r\n\r\n", + (int) hm->uri.len, hm->uri.p); + MG_FREE(index_file); + return; + } + + /* If we have path_info, the only way to handle it is CGI. */ + if (path_info->len > 0 && !is_cgi) { + mg_http_send_error(nc, 501, NULL); + MG_FREE(index_file); + return; + } + + if (is_dav && opts->dav_document_root == NULL) { + mg_http_send_error(nc, 501, NULL); + } else if (!mg_is_authorized(hm, path, is_directory, opts->auth_domain, + opts->global_auth_file, 1) || + !mg_is_authorized(hm, path, is_directory, opts->auth_domain, + opts->per_directory_auth_file, 0)) { + mg_http_send_digest_auth_request(nc, opts->auth_domain); + } else if (is_cgi) { +#if MG_ENABLE_HTTP_CGI + mg_handle_cgi(nc, index_file ? index_file : path, path_info, hm, opts); +#else + mg_http_send_error(nc, 501, NULL); +#endif /* MG_ENABLE_HTTP_CGI */ + } else if ((!exists || + mg_is_file_hidden(path, opts, 0 /* specials are ok */)) && + !mg_is_creation_request(hm)) { + mg_http_send_error(nc, 404, NULL); +#if MG_ENABLE_HTTP_WEBDAV + } else if (!mg_vcmp(&hm->method, "PROPFIND")) { + mg_handle_propfind(nc, path, &st, hm, opts); +#if !MG_DISABLE_DAV_AUTH + } else if (is_dav && + (opts->dav_auth_file == NULL || + (strcmp(opts->dav_auth_file, "-") != 0 && + !mg_is_authorized(hm, path, is_directory, opts->auth_domain, + opts->dav_auth_file, 1)))) { + mg_http_send_digest_auth_request(nc, opts->auth_domain); +#endif + } else if (!mg_vcmp(&hm->method, "MKCOL")) { + mg_handle_mkcol(nc, path, hm); + } else if (!mg_vcmp(&hm->method, "DELETE")) { + mg_handle_delete(nc, opts, path); + } else if (!mg_vcmp(&hm->method, "PUT")) { + mg_handle_put(nc, path, hm); + } else if (!mg_vcmp(&hm->method, "MOVE")) { + mg_handle_move(nc, opts, path, hm); +#if MG_ENABLE_FAKE_DAVLOCK + } else if (!mg_vcmp(&hm->method, "LOCK")) { + mg_handle_lock(nc, path); +#endif +#endif /* MG_ENABLE_HTTP_WEBDAV */ + } else if (!mg_vcmp(&hm->method, "OPTIONS")) { + mg_http_send_options(nc); + } else if (is_directory && index_file == NULL) { +#if MG_ENABLE_DIRECTORY_LISTING + if (strcmp(opts->enable_directory_listing, "yes") == 0) { + mg_send_directory_listing(nc, path, hm, opts); + } else { + mg_http_send_error(nc, 403, NULL); + } +#else + mg_http_send_error(nc, 501, NULL); +#endif + } else if (mg_is_not_modified(hm, &st)) { + mg_http_send_error(nc, 304, "Not Modified"); + } else { + mg_http_serve_file2(nc, index_file ? index_file : path, hm, opts); + } + MG_FREE(index_file); +} + +void mg_serve_http(struct mg_connection *nc, struct http_message *hm, + struct mg_serve_http_opts opts) { + char *path = NULL; + struct mg_str *hdr, path_info; + uint32_t remote_ip = ntohl(*(uint32_t *) &nc->sa.sin.sin_addr); + + if (mg_check_ip_acl(opts.ip_acl, remote_ip) != 1) { + /* Not allowed to connect */ + mg_http_send_error(nc, 403, NULL); + nc->flags |= MG_F_SEND_AND_CLOSE; + return; + } + +#if MG_ENABLE_HTTP_URL_REWRITES + if (mg_http_handle_forwarding(nc, hm, &opts)) { + return; + } + + if (mg_http_send_port_based_redirect(nc, hm, &opts)) { + return; + } +#endif + + if (opts.document_root == NULL) { + opts.document_root = "."; + } + if (opts.per_directory_auth_file == NULL) { + opts.per_directory_auth_file = ".htpasswd"; + } + if (opts.enable_directory_listing == NULL) { + opts.enable_directory_listing = "yes"; + } + if (opts.cgi_file_pattern == NULL) { + opts.cgi_file_pattern = "**.cgi$|**.php$"; + } + if (opts.ssi_pattern == NULL) { + opts.ssi_pattern = "**.shtml$|**.shtm$"; + } + if (opts.index_files == NULL) { + opts.index_files = "index.html,index.htm,index.shtml,index.cgi,index.php"; + } + /* Normalize path - resolve "." and ".." (in-place). */ + if (!mg_normalize_uri_path(&hm->uri, &hm->uri)) { + mg_http_send_error(nc, 400, NULL); + return; + } + if (mg_uri_to_local_path(hm, &opts, &path, &path_info) == 0) { + mg_http_send_error(nc, 404, NULL); + return; + } + mg_send_http_file(nc, path, &path_info, hm, &opts); + + MG_FREE(path); + path = NULL; + + /* Close connection for non-keep-alive requests */ + if (mg_vcmp(&hm->proto, "HTTP/1.1") != 0 || + ((hdr = mg_get_http_header(hm, "Connection")) != NULL && + mg_vcmp(hdr, "keep-alive") != 0)) { +#if 0 + nc->flags |= MG_F_SEND_AND_CLOSE; +#endif + } +} + +#if MG_ENABLE_HTTP_STREAMING_MULTIPART +void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data, + mg_fu_fname_fn local_name_fn) { + switch (ev) { + case MG_EV_HTTP_PART_BEGIN: { + struct mg_http_multipart_part *mp = + (struct mg_http_multipart_part *) ev_data; + struct file_upload_state *fus = + (struct file_upload_state *) calloc(1, sizeof(*fus)); + mp->user_data = NULL; + + struct mg_str lfn = local_name_fn(nc, mg_mk_str(mp->file_name)); + if (lfn.p == NULL || lfn.len == 0) { + LOG(LL_ERROR, ("%p Not allowed to upload %s", nc, mp->file_name)); + mg_printf(nc, + "HTTP/1.1 403 Not Allowed\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n" + "Not allowed to upload %s\r\n", + mp->file_name); + nc->flags |= MG_F_SEND_AND_CLOSE; + return; + } + fus->lfn = (char *) malloc(lfn.len + 1); + memcpy(fus->lfn, lfn.p, lfn.len); + fus->lfn[lfn.len] = '\0'; + if (lfn.p != mp->file_name) free((char *) lfn.p); + LOG(LL_DEBUG, + ("%p Receiving file %s -> %s", nc, mp->file_name, fus->lfn)); + fus->fp = mg_fopen(fus->lfn, "w"); + if (fus->fp == NULL) { + mg_printf(nc, + "HTTP/1.1 500 Internal Server Error\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + LOG(LL_ERROR, ("Failed to open %s: %d\n", fus->lfn, mg_get_errno())); + mg_printf(nc, "Failed to open %s: %d\n", fus->lfn, mg_get_errno()); + /* Do not close the connection just yet, discard remainder of the data. + * This is because at the time of writing some browsers (Chrome) fail to + * render response before all the data is sent. */ + } + mp->user_data = (void *) fus; + break; + } + case MG_EV_HTTP_PART_DATA: { + struct mg_http_multipart_part *mp = + (struct mg_http_multipart_part *) ev_data; + struct file_upload_state *fus = + (struct file_upload_state *) mp->user_data; + if (fus == NULL || fus->fp == NULL) break; + if (fwrite(mp->data.p, 1, mp->data.len, fus->fp) != mp->data.len) { + LOG(LL_ERROR, ("Failed to write to %s: %d, wrote %d", fus->lfn, + mg_get_errno(), (int) fus->num_recd)); + if (mg_get_errno() == ENOSPC +#ifdef SPIFFS_ERR_FULL + || mg_get_errno() == SPIFFS_ERR_FULL +#endif + ) { + mg_printf(nc, + "HTTP/1.1 413 Payload Too Large\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + mg_printf(nc, "Failed to write to %s: no space left; wrote %d\r\n", + fus->lfn, (int) fus->num_recd); + } else { + mg_printf(nc, + "HTTP/1.1 500 Internal Server Error\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + mg_printf(nc, "Failed to write to %s: %d, wrote %d", mp->file_name, + mg_get_errno(), (int) fus->num_recd); + } + fclose(fus->fp); + remove(fus->lfn); + fus->fp = NULL; + /* Do not close the connection just yet, discard remainder of the data. + * This is because at the time of writing some browsers (Chrome) fail to + * render response before all the data is sent. */ + return; + } + fus->num_recd += mp->data.len; + LOG(LL_DEBUG, ("%p rec'd %d bytes, %d total", nc, (int) mp->data.len, + (int) fus->num_recd)); + break; + } + case MG_EV_HTTP_PART_END: { + struct mg_http_multipart_part *mp = + (struct mg_http_multipart_part *) ev_data; + struct file_upload_state *fus = + (struct file_upload_state *) mp->user_data; + if (fus == NULL) break; + if (mp->status >= 0 && fus->fp != NULL) { + LOG(LL_DEBUG, ("%p Uploaded %s (%s), %d bytes", nc, mp->file_name, + fus->lfn, (int) fus->num_recd)); + mg_printf(nc, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n" + "Ok, %s - %d bytes.\r\n", + mp->file_name, (int) fus->num_recd); + } else { + LOG(LL_ERROR, ("Failed to store %s (%s)", mp->file_name, fus->lfn)); + /* + * mp->status < 0 means connection was terminated, so no reason to send + * HTTP reply + */ + } + if (fus->fp != NULL) fclose(fus->fp); + free(fus->lfn); + free(fus); + mp->user_data = NULL; + nc->flags |= MG_F_SEND_AND_CLOSE; + break; + } + } +} + +#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */ +#endif /* MG_ENABLE_FILESYSTEM */ + +/* returns 0 on success, -1 on error */ +MG_INTERNAL int mg_http_common_url_parse(const char *url, const char *schema, + const char *schema_tls, int *use_ssl, + char **user, char **pass, char **addr, + int *port_i, const char **path) { + int addr_len = 0; + int auth_sep_pos = -1; + int user_sep_pos = -1; + int port_pos = -1; + (void) user; + (void) pass; + + if (strncmp(url, schema, strlen(schema)) == 0) { + url += strlen(schema); + } else if (strncmp(url, schema_tls, strlen(schema_tls)) == 0) { + url += strlen(schema_tls); + *use_ssl = 1; +#if !MG_ENABLE_SSL + return -1; /* SSL is not enabled, cannot do HTTPS URLs */ +#endif + } + + while (*url != '\0') { + *addr = (char *) MG_REALLOC(*addr, addr_len + 6 /* space for port too. */); + if (*addr == NULL) { + DBG(("OOM")); + return -1; + } + if (*url == '/') { + break; + } + if (*url == '@') { + auth_sep_pos = addr_len; + user_sep_pos = port_pos; + port_pos = -1; + } + if (*url == ':') port_pos = addr_len; + (*addr)[addr_len++] = *url; + (*addr)[addr_len] = '\0'; + url++; + } + + if (addr_len == 0) goto cleanup; + if (port_pos < 0) { + *port_i = addr_len; + addr_len += sprintf(*addr + addr_len, ":%d", *use_ssl ? 443 : 80); + } else { + *port_i = -1; + } + + if (*path == NULL) *path = url; + + if (**path == '\0') *path = "/"; + + if (user != NULL && pass != NULL) { + if (auth_sep_pos == -1) { + *user = NULL; + *pass = NULL; + } else { + /* user is from 0 to user_sep_pos */ + *user = (char *) MG_MALLOC(user_sep_pos + 1); + memcpy(*user, *addr, user_sep_pos); + (*user)[user_sep_pos] = '\0'; + /* pass is from user_sep_pos + 1 to auth_sep_pos */ + *pass = (char *) MG_MALLOC(auth_sep_pos - user_sep_pos - 1 + 1); + memcpy(*pass, *addr + user_sep_pos + 1, auth_sep_pos - user_sep_pos - 1); + (*pass)[auth_sep_pos - user_sep_pos - 1] = '\0'; + + /* move address proper to the front */ + memmove(*addr, *addr + auth_sep_pos + 1, addr_len - auth_sep_pos); + } + } + + DBG(("%s %s", *addr, *path)); + + return 0; + +cleanup: + MG_FREE(*addr); + return -1; +} + +struct mg_connection *mg_connect_http_base( + struct mg_mgr *mgr, mg_event_handler_t ev_handler, + struct mg_connect_opts opts, const char *schema, const char *schema_ssl, + const char *url, const char **path, char **user, char **pass, char **addr) { + struct mg_connection *nc = NULL; + int port_i = -1; + int use_ssl = 0; + + if (mg_http_common_url_parse(url, schema, schema_ssl, &use_ssl, user, pass, + addr, &port_i, path) < 0) { + MG_SET_PTRPTR(opts.error_string, "cannot parse url"); + return NULL; + } + + LOG(LL_DEBUG, ("%s use_ssl? %d", url, use_ssl)); + if (use_ssl) { +#if MG_ENABLE_SSL + /* + * Schema requires SSL, but no SSL parameters were provided in opts. + * In order to maintain backward compatibility, use a faux-SSL with no + * verification. + */ + if (opts.ssl_ca_cert == NULL) { + opts.ssl_ca_cert = "*"; + } +#else + MG_SET_PTRPTR(opts.error_string, "ssl is disabled"); + if (user != NULL) MG_FREE(*user); + if (pass != NULL) MG_FREE(*pass); + MG_FREE(*addr); + return NULL; +#endif + } + + if ((nc = mg_connect_opt(mgr, *addr, ev_handler, opts)) != NULL) { + mg_set_protocol_http_websocket(nc); + /* If the port was addred by us, restore the original host. */ + if (port_i >= 0) (*addr)[port_i] = '\0'; + } + + return nc; +} + +struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr, + mg_event_handler_t ev_handler, + struct mg_connect_opts opts, + const char *url, + const char *extra_headers, + const char *post_data) { + char *user = NULL, *pass = NULL, *addr = NULL; + const char *path = NULL; + struct mbuf auth; + struct mg_connection *nc = + mg_connect_http_base(mgr, ev_handler, opts, "http://", "https://", url, + &path, &user, &pass, &addr); + + if (nc == NULL) { + return NULL; + } + + mbuf_init(&auth, 0); + if (user != NULL) { + mg_basic_auth_header(user, pass, &auth); + } + + mg_printf(nc, "%s %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %" SIZE_T_FMT + "\r\n%.*s%s\r\n%s", + post_data == NULL ? "GET" : "POST", path, addr, + post_data == NULL ? 0 : strlen(post_data), (int) auth.len, + (auth.buf == NULL ? "" : auth.buf), + extra_headers == NULL ? "" : extra_headers, + post_data == NULL ? "" : post_data); + + mbuf_free(&auth); + MG_FREE(user); + MG_FREE(pass); + MG_FREE(addr); + return nc; +} + +struct mg_connection *mg_connect_http(struct mg_mgr *mgr, + mg_event_handler_t ev_handler, + const char *url, + const char *extra_headers, + const char *post_data) { + struct mg_connect_opts opts; + memset(&opts, 0, sizeof(opts)); + return mg_connect_http_opt(mgr, ev_handler, opts, url, extra_headers, + post_data); +} + +size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, + size_t var_name_len, char *file_name, + size_t file_name_len, const char **data, + size_t *data_len) { + static const char cd[] = "Content-Disposition: "; + size_t hl, bl, n, ll, pos, cdl = sizeof(cd) - 1; + + if (buf == NULL || buf_len <= 0) return 0; + if ((hl = mg_http_get_request_len(buf, buf_len)) <= 0) return 0; + if (buf[0] != '-' || buf[1] != '-' || buf[2] == '\n') return 0; + + /* Get boundary length */ + bl = mg_get_line_len(buf, buf_len); + + /* Loop through headers, fetch variable name and file name */ + var_name[0] = file_name[0] = '\0'; + for (n = bl; (ll = mg_get_line_len(buf + n, hl - n)) > 0; n += ll) { + if (mg_ncasecmp(cd, buf + n, cdl) == 0) { + struct mg_str header; + header.p = buf + n + cdl; + header.len = ll - (cdl + 2); + mg_http_parse_header(&header, "name", var_name, var_name_len); + mg_http_parse_header(&header, "filename", file_name, file_name_len); + } + } + + /* Scan through the body, search for terminating boundary */ + for (pos = hl; pos + (bl - 2) < buf_len; pos++) { + if (buf[pos] == '-' && !strncmp(buf, &buf[pos], bl - 2)) { + if (data_len != NULL) *data_len = (pos - 2) - hl; + if (data != NULL) *data = buf + hl; + return pos; + } + } + + return 0; +} + +void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, + mg_event_handler_t handler) { + struct mg_http_proto_data *pd = NULL; + struct mg_http_endpoint *new_ep = NULL; + + if (nc == NULL) return; + new_ep = (struct mg_http_endpoint *) calloc(1, sizeof(*new_ep)); + if (new_ep == NULL) return; + + pd = mg_http_get_proto_data(nc); + new_ep->name = strdup(uri_path); + new_ep->name_len = strlen(new_ep->name); + new_ep->handler = handler; + new_ep->next = pd->endpoints; + pd->endpoints = new_ep; +} + +#endif /* MG_ENABLE_HTTP */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http_cgi.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_CGI + +#ifndef MG_MAX_CGI_ENVIR_VARS +#define MG_MAX_CGI_ENVIR_VARS 64 +#endif + +#ifndef MG_ENV_EXPORT_TO_CGI +#define MG_ENV_EXPORT_TO_CGI "MONGOOSE_CGI" +#endif + +/* + * This structure helps to create an environment for the spawned CGI program. + * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings, + * last element must be NULL. + * However, on Windows there is a requirement that all these VARIABLE=VALUE\0 + * strings must reside in a contiguous buffer. The end of the buffer is + * marked by two '\0' characters. + * We satisfy both worlds: we create an envp array (which is vars), all + * entries are actually pointers inside buf. + */ +struct mg_cgi_env_block { + struct mg_connection *nc; + char buf[MG_CGI_ENVIRONMENT_SIZE]; /* Environment buffer */ + const char *vars[MG_MAX_CGI_ENVIR_VARS]; /* char *envp[] */ + int len; /* Space taken */ + int nvars; /* Number of variables in envp[] */ +}; + +#ifdef _WIN32 +struct mg_threadparam { + sock_t s; + HANDLE hPipe; +}; + +static int mg_wait_until_ready(sock_t sock, int for_read) { + fd_set set; + FD_ZERO(&set); + FD_SET(sock, &set); + return select(sock + 1, for_read ? &set : 0, for_read ? 0 : &set, 0, 0) == 1; +} + +static void *mg_push_to_stdin(void *arg) { + struct mg_threadparam *tp = (struct mg_threadparam *) arg; + int n, sent, stop = 0; + DWORD k; + char buf[BUFSIZ]; + + while (!stop && mg_wait_until_ready(tp->s, 1) && + (n = recv(tp->s, buf, sizeof(buf), 0)) > 0) { + if (n == -1 && GetLastError() == WSAEWOULDBLOCK) continue; + for (sent = 0; !stop && sent < n; sent += k) { + if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) stop = 1; + } + } + DBG(("%s", "FORWARED EVERYTHING TO CGI")); + CloseHandle(tp->hPipe); + MG_FREE(tp); + return NULL; +} + +static void *mg_pull_from_stdout(void *arg) { + struct mg_threadparam *tp = (struct mg_threadparam *) arg; + int k = 0, stop = 0; + DWORD n, sent; + char buf[BUFSIZ]; + + while (!stop && ReadFile(tp->hPipe, buf, sizeof(buf), &n, NULL)) { + for (sent = 0; !stop && sent < n; sent += k) { + if (mg_wait_until_ready(tp->s, 0) && + (k = send(tp->s, buf + sent, n - sent, 0)) <= 0) + stop = 1; + } + } + DBG(("%s", "EOF FROM CGI")); + CloseHandle(tp->hPipe); + shutdown(tp->s, 2); // Without this, IO thread may get truncated data + closesocket(tp->s); + MG_FREE(tp); + return NULL; +} + +static void mg_spawn_stdio_thread(sock_t sock, HANDLE hPipe, + void *(*func)(void *)) { + struct mg_threadparam *tp = (struct mg_threadparam *) MG_MALLOC(sizeof(*tp)); + if (tp != NULL) { + tp->s = sock; + tp->hPipe = hPipe; + mg_start_thread(func, tp); + } +} + +static void mg_abs_path(const char *utf8_path, char *abs_path, size_t len) { + wchar_t buf[MAX_PATH_SIZE], buf2[MAX_PATH_SIZE]; + to_wchar(utf8_path, buf, ARRAY_SIZE(buf)); + GetFullPathNameW(buf, ARRAY_SIZE(buf2), buf2, NULL); + WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0); +} + +static int mg_start_process(const char *interp, const char *cmd, + const char *env, const char *envp[], + const char *dir, sock_t sock) { + STARTUPINFOW si; + PROCESS_INFORMATION pi; + HANDLE a[2], b[2], me = GetCurrentProcess(); + wchar_t wcmd[MAX_PATH_SIZE], full_dir[MAX_PATH_SIZE]; + char buf[MAX_PATH_SIZE], buf2[MAX_PATH_SIZE], buf5[MAX_PATH_SIZE], + buf4[MAX_PATH_SIZE], cmdline[MAX_PATH_SIZE]; + DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS; + FILE *fp; + + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + CreatePipe(&a[0], &a[1], NULL, 0); + CreatePipe(&b[0], &b[1], NULL, 0); + DuplicateHandle(me, a[0], me, &si.hStdInput, 0, TRUE, flags); + DuplicateHandle(me, b[1], me, &si.hStdOutput, 0, TRUE, flags); + + if (interp == NULL && (fp = mg_fopen(cmd, "r")) != NULL) { + buf[0] = buf[1] = '\0'; + fgets(buf, sizeof(buf), fp); + buf[sizeof(buf) - 1] = '\0'; + if (buf[0] == '#' && buf[1] == '!') { + interp = buf + 2; + /* Trim leading spaces: https://github.com/cesanta/mongoose/issues/489 */ + while (*interp != '\0' && isspace(*(unsigned char *) interp)) { + interp++; + } + } + fclose(fp); + } + + snprintf(buf, sizeof(buf), "%s/%s", dir, cmd); + mg_abs_path(buf, buf2, ARRAY_SIZE(buf2)); + + mg_abs_path(dir, buf5, ARRAY_SIZE(buf5)); + to_wchar(dir, full_dir, ARRAY_SIZE(full_dir)); + + if (interp != NULL) { + mg_abs_path(interp, buf4, ARRAY_SIZE(buf4)); + snprintf(cmdline, sizeof(cmdline), "%s \"%s\"", buf4, buf2); + } else { + snprintf(cmdline, sizeof(cmdline), "\"%s\"", buf2); + } + to_wchar(cmdline, wcmd, ARRAY_SIZE(wcmd)); + + if (CreateProcessW(NULL, wcmd, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, + (void *) env, full_dir, &si, &pi) != 0) { + mg_spawn_stdio_thread(sock, a[1], mg_push_to_stdin); + mg_spawn_stdio_thread(sock, b[0], mg_pull_from_stdout); + + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdInput); + + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } else { + CloseHandle(a[1]); + CloseHandle(b[0]); + closesocket(sock); + } + DBG(("CGI command: [%ls] -> %p", wcmd, pi.hProcess)); + + /* Not closing a[0] and b[1] because we've used DUPLICATE_CLOSE_SOURCE */ + (void) envp; + return (pi.hProcess != NULL); +} +#else +static int mg_start_process(const char *interp, const char *cmd, + const char *env, const char *envp[], + const char *dir, sock_t sock) { + char buf[500]; + pid_t pid = fork(); + (void) env; + + if (pid == 0) { + /* + * In Linux `chdir` declared with `warn_unused_result` attribute + * To shutup compiler we have yo use result in some way + */ + int tmp = chdir(dir); + (void) tmp; + (void) dup2(sock, 0); + (void) dup2(sock, 1); + closesocket(sock); + + /* + * After exec, all signal handlers are restored to their default values, + * with one exception of SIGCHLD. According to POSIX.1-2001 and Linux's + * implementation, SIGCHLD's handler will leave unchanged after exec + * if it was set to be ignored. Restore it to default action. + */ + signal(SIGCHLD, SIG_DFL); + + if (interp == NULL) { + execle(cmd, cmd, (char *) 0, envp); /* (char *) 0 to squash warning */ + } else { + execle(interp, interp, cmd, (char *) 0, envp); + } + snprintf(buf, sizeof(buf), + "Status: 500\r\n\r\n" + "500 Server Error: %s%s%s: %s", + interp == NULL ? "" : interp, interp == NULL ? "" : " ", cmd, + strerror(errno)); + send(1, buf, strlen(buf), 0); + exit(EXIT_FAILURE); /* exec call failed */ + } + + return (pid != 0); +} +#endif /* _WIN32 */ + +/* + * Append VARIABLE=VALUE\0 string to the buffer, and add a respective + * pointer into the vars array. + */ +static char *mg_addenv(struct mg_cgi_env_block *block, const char *fmt, ...) { + int n, space; + char *added = block->buf + block->len; + va_list ap; + + /* Calculate how much space is left in the buffer */ + space = sizeof(block->buf) - (block->len + 2); + if (space > 0) { + /* Copy VARIABLE=VALUE\0 string into the free space */ + va_start(ap, fmt); + n = vsnprintf(added, (size_t) space, fmt, ap); + va_end(ap); + + /* Make sure we do not overflow buffer and the envp array */ + if (n > 0 && n + 1 < space && + block->nvars < (int) ARRAY_SIZE(block->vars) - 2) { + /* Append a pointer to the added string into the envp array */ + block->vars[block->nvars++] = added; + /* Bump up used length counter. Include \0 terminator */ + block->len += n + 1; + } + } + + return added; +} + +static void mg_addenv2(struct mg_cgi_env_block *blk, const char *name) { + const char *s; + if ((s = getenv(name)) != NULL) mg_addenv(blk, "%s=%s", name, s); +} + +static void mg_prepare_cgi_environment(struct mg_connection *nc, + const char *prog, + const struct mg_str *path_info, + const struct http_message *hm, + const struct mg_serve_http_opts *opts, + struct mg_cgi_env_block *blk) { + const char *s; + struct mg_str *h; + char *p; + size_t i; + char buf[100]; + + blk->len = blk->nvars = 0; + blk->nc = nc; + + if ((s = getenv("SERVER_NAME")) != NULL) { + mg_addenv(blk, "SERVER_NAME=%s", s); + } else { + mg_sock_to_str(nc->sock, buf, sizeof(buf), 3); + mg_addenv(blk, "SERVER_NAME=%s", buf); + } + mg_addenv(blk, "SERVER_ROOT=%s", opts->document_root); + mg_addenv(blk, "DOCUMENT_ROOT=%s", opts->document_root); + mg_addenv(blk, "SERVER_SOFTWARE=%s/%s", "Mongoose", MG_VERSION); + + /* Prepare the environment block */ + mg_addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1"); + mg_addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1"); + mg_addenv(blk, "%s", "REDIRECT_STATUS=200"); /* For PHP */ + + mg_addenv(blk, "REQUEST_METHOD=%.*s", (int) hm->method.len, hm->method.p); + + mg_addenv(blk, "REQUEST_URI=%.*s%s%.*s", (int) hm->uri.len, hm->uri.p, + hm->query_string.len == 0 ? "" : "?", (int) hm->query_string.len, + hm->query_string.p); + + mg_conn_addr_to_str(nc, buf, sizeof(buf), + MG_SOCK_STRINGIFY_REMOTE | MG_SOCK_STRINGIFY_IP); + mg_addenv(blk, "REMOTE_ADDR=%s", buf); + mg_conn_addr_to_str(nc, buf, sizeof(buf), MG_SOCK_STRINGIFY_PORT); + mg_addenv(blk, "SERVER_PORT=%s", buf); + + s = hm->uri.p + hm->uri.len - path_info->len - 1; + if (*s == '/') { + const char *base_name = strrchr(prog, DIRSEP); + mg_addenv(blk, "SCRIPT_NAME=%.*s/%s", (int) (s - hm->uri.p), hm->uri.p, + (base_name != NULL ? base_name + 1 : prog)); + } else { + mg_addenv(blk, "SCRIPT_NAME=%.*s", (int) (s - hm->uri.p + 1), hm->uri.p); + } + mg_addenv(blk, "SCRIPT_FILENAME=%s", prog); + + if (path_info != NULL && path_info->len > 0) { + mg_addenv(blk, "PATH_INFO=%.*s", (int) path_info->len, path_info->p); + /* Not really translated... */ + mg_addenv(blk, "PATH_TRANSLATED=%.*s", (int) path_info->len, path_info->p); + } + +#if MG_ENABLE_SSL + mg_addenv(blk, "HTTPS=%s", (nc->flags & MG_F_SSL ? "on" : "off")); +#else + mg_addenv(blk, "HTTPS=off"); +#endif + + if ((h = mg_get_http_header((struct http_message *) hm, "Content-Type")) != + NULL) { + mg_addenv(blk, "CONTENT_TYPE=%.*s", (int) h->len, h->p); + } + + if (hm->query_string.len > 0) { + mg_addenv(blk, "QUERY_STRING=%.*s", (int) hm->query_string.len, + hm->query_string.p); + } + + if ((h = mg_get_http_header((struct http_message *) hm, "Content-Length")) != + NULL) { + mg_addenv(blk, "CONTENT_LENGTH=%.*s", (int) h->len, h->p); + } + + mg_addenv2(blk, "PATH"); + mg_addenv2(blk, "TMP"); + mg_addenv2(blk, "TEMP"); + mg_addenv2(blk, "TMPDIR"); + mg_addenv2(blk, "PERLLIB"); + mg_addenv2(blk, MG_ENV_EXPORT_TO_CGI); + +#ifdef _WIN32 + mg_addenv2(blk, "COMSPEC"); + mg_addenv2(blk, "SYSTEMROOT"); + mg_addenv2(blk, "SystemDrive"); + mg_addenv2(blk, "ProgramFiles"); + mg_addenv2(blk, "ProgramFiles(x86)"); + mg_addenv2(blk, "CommonProgramFiles(x86)"); +#else + mg_addenv2(blk, "LD_LIBRARY_PATH"); +#endif /* _WIN32 */ + + /* Add all headers as HTTP_* variables */ + for (i = 0; hm->header_names[i].len > 0; i++) { + p = mg_addenv(blk, "HTTP_%.*s=%.*s", (int) hm->header_names[i].len, + hm->header_names[i].p, (int) hm->header_values[i].len, + hm->header_values[i].p); + + /* Convert variable name into uppercase, and change - to _ */ + for (; *p != '=' && *p != '\0'; p++) { + if (*p == '-') *p = '_'; + *p = (char) toupper(*(unsigned char *) p); + } + } + + blk->vars[blk->nvars++] = NULL; + blk->buf[blk->len++] = '\0'; +} + +static void mg_cgi_ev_handler(struct mg_connection *cgi_nc, int ev, + void *ev_data) { + struct mg_connection *nc = (struct mg_connection *) cgi_nc->user_data; + (void) ev_data; + + if (nc == NULL) return; + + switch (ev) { + case MG_EV_RECV: + /* + * CGI script does not output reply line, like "HTTP/1.1 CODE XXXXX\n" + * It outputs headers, then body. Headers might include "Status" + * header, which changes CODE, and it might include "Location" header + * which changes CODE to 302. + * + * Therefore we do not send the output from the CGI script to the user + * until all CGI headers are received. + * + * Here we parse the output from the CGI script, and if all headers has + * been received, send appropriate reply line, and forward all + * received headers to the client. + */ + if (nc->flags & MG_F_USER_1) { + struct mbuf *io = &cgi_nc->recv_mbuf; + int len = mg_http_get_request_len(io->buf, io->len); + + if (len == 0) break; + if (len < 0 || io->len > MG_MAX_HTTP_REQUEST_SIZE) { + cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY; + mg_http_send_error(nc, 500, "Bad headers"); + } else { + struct http_message hm; + struct mg_str *h; + mg_http_parse_headers(io->buf, io->buf + io->len, io->len, &hm); + if (mg_get_http_header(&hm, "Location") != NULL) { + mg_printf(nc, "%s", "HTTP/1.1 302 Moved\r\n"); + } else if ((h = mg_get_http_header(&hm, "Status")) != NULL) { + mg_printf(nc, "HTTP/1.1 %.*s\r\n", (int) h->len, h->p); + } else { + mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\n"); + } + } + nc->flags &= ~MG_F_USER_1; + } + if (!(nc->flags & MG_F_USER_1)) { + mg_forward(cgi_nc, nc); + } + break; + case MG_EV_CLOSE: + mg_http_free_proto_data_cgi(&mg_http_get_proto_data(cgi_nc)->cgi); + nc->flags |= MG_F_SEND_AND_CLOSE; + break; + } +} + +MG_INTERNAL void mg_handle_cgi(struct mg_connection *nc, const char *prog, + const struct mg_str *path_info, + const struct http_message *hm, + const struct mg_serve_http_opts *opts) { + struct mg_cgi_env_block blk; + char dir[MAX_PATH_SIZE]; + const char *p; + sock_t fds[2]; + + DBG(("%p [%s]", nc, prog)); + mg_prepare_cgi_environment(nc, prog, path_info, hm, opts, &blk); + /* + * CGI must be executed in its own directory. 'dir' must point to the + * directory containing executable program, 'p' must point to the + * executable program name relative to 'dir'. + */ + if ((p = strrchr(prog, DIRSEP)) == NULL) { + snprintf(dir, sizeof(dir), "%s", "."); + } else { + snprintf(dir, sizeof(dir), "%.*s", (int) (p - prog), prog); + prog = p + 1; + } + + /* + * Try to create socketpair in a loop until success. mg_socketpair() + * can be interrupted by a signal and fail. + * TODO(lsm): use sigaction to restart interrupted syscall + */ + do { + mg_socketpair(fds, SOCK_STREAM); + } while (fds[0] == INVALID_SOCKET); + + if (mg_start_process(opts->cgi_interpreter, prog, blk.buf, blk.vars, dir, + fds[1]) != 0) { + size_t n = nc->recv_mbuf.len - (hm->message.len - hm->body.len); + struct mg_connection *cgi_nc = + mg_add_sock(nc->mgr, fds[0], mg_cgi_ev_handler); + struct mg_http_proto_data *cgi_pd = mg_http_get_proto_data(cgi_nc); + cgi_pd->cgi.cgi_nc = cgi_nc; + cgi_pd->cgi.cgi_nc->user_data = nc; + nc->flags |= MG_F_USER_1; + /* Push POST data to the CGI */ + if (n > 0 && n < nc->recv_mbuf.len) { + mg_send(cgi_pd->cgi.cgi_nc, hm->body.p, n); + } + mbuf_remove(&nc->recv_mbuf, nc->recv_mbuf.len); + } else { + closesocket(fds[0]); + mg_http_send_error(nc, 500, "CGI failure"); + } + +#ifndef _WIN32 + closesocket(fds[1]); /* On Windows, CGI stdio thread closes that socket */ +#endif +} + +MG_INTERNAL void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d) { + if (d != NULL) { + if (d->cgi_nc != NULL) d->cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY; + memset(d, 0, sizeof(struct mg_http_proto_data_cgi)); + } +} + +#endif /* MG_ENABLE_HTTP && MG_ENABLE_HTTP_CGI */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http_ssi.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_SSI && MG_ENABLE_FILESYSTEM + +static void mg_send_ssi_file(struct mg_connection *nc, struct http_message *hm, + const char *path, FILE *fp, int include_level, + const struct mg_serve_http_opts *opts); + +static void mg_send_file_data(struct mg_connection *nc, FILE *fp) { + char buf[BUFSIZ]; + size_t n; + while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { + mg_send(nc, buf, n); + } +} + +static void mg_do_ssi_include(struct mg_connection *nc, struct http_message *hm, + const char *ssi, char *tag, int include_level, + const struct mg_serve_http_opts *opts) { + char file_name[BUFSIZ], path[MAX_PATH_SIZE], *p; + FILE *fp; + + /* + * sscanf() is safe here, since send_ssi_file() also uses buffer + * of size MG_BUF_LEN to get the tag. So strlen(tag) is always < MG_BUF_LEN. + */ + if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) { + /* File name is relative to the webserver root */ + snprintf(path, sizeof(path), "%s/%s", opts->document_root, file_name); + } else if (sscanf(tag, " abspath=\"%[^\"]\"", file_name) == 1) { + /* + * File name is relative to the webserver working directory + * or it is absolute system path + */ + snprintf(path, sizeof(path), "%s", file_name); + } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 || + sscanf(tag, " \"%[^\"]\"", file_name) == 1) { + /* File name is relative to the currect document */ + snprintf(path, sizeof(path), "%s", ssi); + if ((p = strrchr(path, DIRSEP)) != NULL) { + p[1] = '\0'; + } + snprintf(path + strlen(path), sizeof(path) - strlen(path), "%s", file_name); + } else { + mg_printf(nc, "Bad SSI #include: [%s]", tag); + return; + } + + if ((fp = mg_fopen(path, "rb")) == NULL) { + mg_printf(nc, "SSI include error: mg_fopen(%s): %s", path, + strerror(mg_get_errno())); + } else { + mg_set_close_on_exec((sock_t) fileno(fp)); + if (mg_match_prefix(opts->ssi_pattern, strlen(opts->ssi_pattern), path) > + 0) { + mg_send_ssi_file(nc, hm, path, fp, include_level + 1, opts); + } else { + mg_send_file_data(nc, fp); + } + fclose(fp); + } +} + +#if MG_ENABLE_HTTP_SSI_EXEC +static void do_ssi_exec(struct mg_connection *nc, char *tag) { + char cmd[BUFSIZ]; + FILE *fp; + + if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) { + mg_printf(nc, "Bad SSI #exec: [%s]", tag); + } else if ((fp = popen(cmd, "r")) == NULL) { + mg_printf(nc, "Cannot SSI #exec: [%s]: %s", cmd, strerror(mg_get_errno())); + } else { + mg_send_file_data(nc, fp); + pclose(fp); + } +} +#endif /* MG_ENABLE_HTTP_SSI_EXEC */ + +/* + * SSI directive has the following format: + * + */ +static void mg_send_ssi_file(struct mg_connection *nc, struct http_message *hm, + const char *path, FILE *fp, int include_level, + const struct mg_serve_http_opts *opts) { + static const struct mg_str btag = MG_MK_STR(" */ + buf[i--] = '\0'; + while (i > 0 && buf[i] == ' ') { + buf[i--] = '\0'; + } + + /* Handle known SSI directives */ + if (strncmp(p, d_include.p, d_include.len) == 0) { + mg_do_ssi_include(nc, hm, path, p + d_include.len + 1, include_level, + opts); + } else if (strncmp(p, d_call.p, d_call.len) == 0) { + struct mg_ssi_call_ctx cctx; + memset(&cctx, 0, sizeof(cctx)); + cctx.req = hm; + cctx.file = mg_mk_str(path); + cctx.arg = mg_mk_str(p + d_call.len + 1); + mg_call(nc, NULL, MG_EV_SSI_CALL, + (void *) cctx.arg.p); /* NUL added above */ + mg_call(nc, NULL, MG_EV_SSI_CALL_CTX, &cctx); +#if MG_ENABLE_HTTP_SSI_EXEC + } else if (strncmp(p, d_exec.p, d_exec.len) == 0) { + do_ssi_exec(nc, p + d_exec.len + 1); +#endif + } else { + /* Silently ignore unknown SSI directive. */ + } + len = 0; + } else if (ch == '<') { + in_ssi_tag = 1; + if (len > 0) { + mg_send(nc, buf, (size_t) len); + } + len = 0; + buf[len++] = ch & 0xff; + } else if (in_ssi_tag) { + if (len == (int) btag.len && strncmp(buf, btag.p, btag.len) != 0) { + /* Not an SSI tag */ + in_ssi_tag = 0; + } else if (len == (int) sizeof(buf) - 2) { + mg_printf(nc, "%s: SSI tag is too large", path); + len = 0; + } + buf[len++] = ch & 0xff; + } else { + buf[len++] = ch & 0xff; + if (len == (int) sizeof(buf)) { + mg_send(nc, buf, (size_t) len); + len = 0; + } + } + } + + /* Send the rest of buffered data */ + if (len > 0) { + mg_send(nc, buf, (size_t) len); + } +} + +MG_INTERNAL void mg_handle_ssi_request(struct mg_connection *nc, + struct http_message *hm, + const char *path, + const struct mg_serve_http_opts *opts) { + FILE *fp; + struct mg_str mime_type; + DBG(("%p %s", nc, path)); + + if ((fp = mg_fopen(path, "rb")) == NULL) { + mg_http_send_error(nc, 404, NULL); + } else { + mg_set_close_on_exec((sock_t) fileno(fp)); + + mime_type = mg_get_mime_type(path, "text/plain", opts); + mg_send_response_line(nc, 200, opts->extra_headers); + mg_printf(nc, + "Content-Type: %.*s\r\n" + "Connection: close\r\n\r\n", + (int) mime_type.len, mime_type.p); + mg_send_ssi_file(nc, hm, path, fp, 0, opts); + fclose(fp); + nc->flags |= MG_F_SEND_AND_CLOSE; + } +} + +#endif /* MG_ENABLE_HTTP_SSI && MG_ENABLE_HTTP && MG_ENABLE_FILESYSTEM */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http_webdav.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBDAV + +MG_INTERNAL int mg_is_dav_request(const struct mg_str *s) { + static const char *methods[] = { + "PUT", + "DELETE", + "MKCOL", + "PROPFIND", + "MOVE" +#if MG_ENABLE_FAKE_DAVLOCK + , + "LOCK", + "UNLOCK" +#endif + }; + size_t i; + + for (i = 0; i < ARRAY_SIZE(methods); i++) { + if (mg_vcmp(s, methods[i]) == 0) { + return 1; + } + } + + return 0; +} + +static int mg_mkdir(const char *path, uint32_t mode) { +#ifndef _WIN32 + return mkdir(path, mode); +#else + (void) mode; + return _mkdir(path); +#endif +} + +static void mg_print_props(struct mg_connection *nc, const char *name, + cs_stat_t *stp) { + char mtime[64], buf[MAX_PATH_SIZE * 3]; + time_t t = stp->st_mtime; /* store in local variable for NDK compile */ + mg_gmt_time_string(mtime, sizeof(mtime), &t); + mg_url_encode(name, strlen(name), buf, sizeof(buf)); + mg_printf(nc, + "" + "%s" + "" + "" + "%s" + "%" INT64_FMT + "" + "%s" + "" + "HTTP/1.1 200 OK" + "" + "\n", + buf, S_ISDIR(stp->st_mode) ? "" : "", + (int64_t) stp->st_size, mtime); +} + +MG_INTERNAL void mg_handle_propfind(struct mg_connection *nc, const char *path, + cs_stat_t *stp, struct http_message *hm, + struct mg_serve_http_opts *opts) { + static const char header[] = + "HTTP/1.1 207 Multi-Status\r\n" + "Connection: close\r\n" + "Content-Type: text/xml; charset=utf-8\r\n\r\n" + "" + "\n"; + static const char footer[] = "\n"; + const struct mg_str *depth = mg_get_http_header(hm, "Depth"); + + /* Print properties for the requested resource itself */ + if (S_ISDIR(stp->st_mode) && + strcmp(opts->enable_directory_listing, "yes") != 0) { + mg_printf(nc, "%s", "HTTP/1.1 403 Directory Listing Denied\r\n\r\n"); + } else { + char uri[MAX_PATH_SIZE]; + mg_send(nc, header, sizeof(header) - 1); + snprintf(uri, sizeof(uri), "%.*s", (int) hm->uri.len, hm->uri.p); + mg_print_props(nc, uri, stp); + if (S_ISDIR(stp->st_mode) && (depth == NULL || mg_vcmp(depth, "0") != 0)) { + mg_scan_directory(nc, path, opts, mg_print_props); + } + mg_send(nc, footer, sizeof(footer) - 1); + nc->flags |= MG_F_SEND_AND_CLOSE; + } +} + +#if MG_ENABLE_FAKE_DAVLOCK +/* + * Windows explorer (probably there are another WebDav clients like it) + * requires LOCK support in webdav. W/out this, it still works, but fails + * to save file: shows error message and offers "Save As". + * "Save as" works, but this message is very annoying. + * This is fake lock, which doesn't lock something, just returns LOCK token, + * UNLOCK always answers "OK". + * With this fake LOCK Windows Explorer looks happy and saves file. + * NOTE: that is not DAV LOCK imlementation, it is just a way to shut up + * Windows native DAV client. This is why FAKE LOCK is not enabed by default + */ +MG_INTERNAL void mg_handle_lock(struct mg_connection *nc, const char *path) { + static const char *reply = + "HTTP/1.1 207 Multi-Status\r\n" + "Connection: close\r\n" + "Content-Type: text/xml; charset=utf-8\r\n\r\n" + "" + "\n" + "\n" + "\n" + "\n" + "\n" + "opaquelocktoken:%s%u" + "" + "" + "\n" + "" + "\n"; + mg_printf(nc, reply, path, (unsigned int) mg_time()); + nc->flags |= MG_F_SEND_AND_CLOSE; +} +#endif + +MG_INTERNAL void mg_handle_mkcol(struct mg_connection *nc, const char *path, + struct http_message *hm) { + int status_code = 500; + if (hm->body.len != (size_t) ~0 && hm->body.len > 0) { + status_code = 415; + } else if (!mg_mkdir(path, 0755)) { + status_code = 201; + } else if (errno == EEXIST) { + status_code = 405; + } else if (errno == EACCES) { + status_code = 403; + } else if (errno == ENOENT) { + status_code = 409; + } else { + status_code = 500; + } + mg_http_send_error(nc, status_code, NULL); +} + +static int mg_remove_directory(const struct mg_serve_http_opts *opts, + const char *dir) { + char path[MAX_PATH_SIZE]; + struct dirent *dp; + cs_stat_t st; + DIR *dirp; + + if ((dirp = opendir(dir)) == NULL) return 0; + + while ((dp = readdir(dirp)) != NULL) { + if (mg_is_file_hidden((const char *) dp->d_name, opts, 1)) { + continue; + } + snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name); + mg_stat(path, &st); + if (S_ISDIR(st.st_mode)) { + mg_remove_directory(opts, path); + } else { + remove(path); + } + } + closedir(dirp); + rmdir(dir); + + return 1; +} + +MG_INTERNAL void mg_handle_move(struct mg_connection *c, + const struct mg_serve_http_opts *opts, + const char *path, struct http_message *hm) { + const struct mg_str *dest = mg_get_http_header(hm, "Destination"); + if (dest == NULL) { + mg_http_send_error(c, 411, NULL); + } else { + const char *p = (char *) memchr(dest->p, '/', dest->len); + if (p != NULL && p[1] == '/' && + (p = (char *) memchr(p + 2, '/', dest->p + dest->len - p)) != NULL) { + char buf[MAX_PATH_SIZE]; + snprintf(buf, sizeof(buf), "%s%.*s", opts->dav_document_root, + (int) (dest->p + dest->len - p), p); + if (rename(path, buf) == 0) { + mg_http_send_error(c, 200, NULL); + } else { + mg_http_send_error(c, 418, NULL); + } + } else { + mg_http_send_error(c, 500, NULL); + } + } +} + +MG_INTERNAL void mg_handle_delete(struct mg_connection *nc, + const struct mg_serve_http_opts *opts, + const char *path) { + cs_stat_t st; + if (mg_stat(path, &st) != 0) { + mg_http_send_error(nc, 404, NULL); + } else if (S_ISDIR(st.st_mode)) { + mg_remove_directory(opts, path); + mg_http_send_error(nc, 204, NULL); + } else if (remove(path) == 0) { + mg_http_send_error(nc, 204, NULL); + } else { + mg_http_send_error(nc, 423, NULL); + } +} + +/* Return -1 on error, 1 on success. */ +static int mg_create_itermediate_directories(const char *path) { + const char *s; + + /* Create intermediate directories if they do not exist */ + for (s = path + 1; *s != '\0'; s++) { + if (*s == '/') { + char buf[MAX_PATH_SIZE]; + cs_stat_t st; + snprintf(buf, sizeof(buf), "%.*s", (int) (s - path), path); + buf[sizeof(buf) - 1] = '\0'; + if (mg_stat(buf, &st) != 0 && mg_mkdir(buf, 0755) != 0) { + return -1; + } + } + } + + return 1; +} + +MG_INTERNAL void mg_handle_put(struct mg_connection *nc, const char *path, + struct http_message *hm) { + struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + cs_stat_t st; + const struct mg_str *cl_hdr = mg_get_http_header(hm, "Content-Length"); + int rc, status_code = mg_stat(path, &st) == 0 ? 200 : 201; + + mg_http_free_proto_data_file(&pd->file); + if ((rc = mg_create_itermediate_directories(path)) == 0) { + mg_printf(nc, "HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code); + } else if (rc == -1) { + mg_http_send_error(nc, 500, NULL); + } else if (cl_hdr == NULL) { + mg_http_send_error(nc, 411, NULL); + } else if ((pd->file.fp = mg_fopen(path, "w+b")) == NULL) { + mg_http_send_error(nc, 500, NULL); + } else { + const struct mg_str *range_hdr = mg_get_http_header(hm, "Content-Range"); + int64_t r1 = 0, r2 = 0; + pd->file.type = DATA_PUT; + mg_set_close_on_exec((sock_t) fileno(pd->file.fp)); + pd->file.cl = to64(cl_hdr->p); + if (range_hdr != NULL && + mg_http_parse_range_header(range_hdr, &r1, &r2) > 0) { + status_code = 206; + fseeko(pd->file.fp, r1, SEEK_SET); + pd->file.cl = r2 > r1 ? r2 - r1 + 1 : pd->file.cl - r1; + } + mg_printf(nc, "HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code); + /* Remove HTTP request from the mbuf, leave only payload */ + mbuf_remove(&nc->recv_mbuf, hm->message.len - hm->body.len); + mg_http_transfer_file_data(nc); + } +} + +#endif /* MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBDAV */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/http_websocket.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBSOCKET + +#ifndef MG_WEBSOCKET_PING_INTERVAL_SECONDS +#define MG_WEBSOCKET_PING_INTERVAL_SECONDS 5 +#endif + +#define MG_WS_NO_HOST_HEADER_MAGIC ((char *) 0x1) + +static int mg_is_ws_fragment(unsigned char flags) { + return (flags & 0x80) == 0 || (flags & 0x0f) == 0; +} + +static int mg_is_ws_first_fragment(unsigned char flags) { + return (flags & 0x80) == 0 && (flags & 0x0f) != 0; +} + +static void mg_handle_incoming_websocket_frame(struct mg_connection *nc, + struct websocket_message *wsm) { + if (wsm->flags & 0x8) { + mg_call(nc, nc->handler, MG_EV_WEBSOCKET_CONTROL_FRAME, wsm); + } else { + mg_call(nc, nc->handler, MG_EV_WEBSOCKET_FRAME, wsm); + } +} + +static int mg_deliver_websocket_data(struct mg_connection *nc) { + /* Using unsigned char *, cause of integer arithmetic below */ + uint64_t i, data_len = 0, frame_len = 0, buf_len = nc->recv_mbuf.len, len, + mask_len = 0, header_len = 0; + unsigned char *p = (unsigned char *) nc->recv_mbuf.buf, *buf = p, + *e = p + buf_len; + unsigned *sizep = (unsigned *) &p[1]; /* Size ptr for defragmented frames */ + int ok, reass = buf_len > 0 && mg_is_ws_fragment(p[0]) && + !(nc->flags & MG_F_WEBSOCKET_NO_DEFRAG); + + /* If that's a continuation frame that must be reassembled, handle it */ + if (reass && !mg_is_ws_first_fragment(p[0]) && + buf_len >= 1 + sizeof(*sizep) && buf_len >= 1 + sizeof(*sizep) + *sizep) { + buf += 1 + sizeof(*sizep) + *sizep; + buf_len -= 1 + sizeof(*sizep) + *sizep; + } + + if (buf_len >= 2) { + len = buf[1] & 127; + mask_len = buf[1] & 128 ? 4 : 0; + if (len < 126 && buf_len >= mask_len) { + data_len = len; + header_len = 2 + mask_len; + } else if (len == 126 && buf_len >= 4 + mask_len) { + header_len = 4 + mask_len; + data_len = ntohs(*(uint16_t *) &buf[2]); + } else if (buf_len >= 10 + mask_len) { + header_len = 10 + mask_len; + data_len = (((uint64_t) ntohl(*(uint32_t *) &buf[2])) << 32) + + ntohl(*(uint32_t *) &buf[6]); + } + } + + frame_len = header_len + data_len; + ok = frame_len > 0 && frame_len <= buf_len; + + if (ok) { + struct websocket_message wsm; + + wsm.size = (size_t) data_len; + wsm.data = buf + header_len; + wsm.flags = buf[0]; + + /* Apply mask if necessary */ + if (mask_len > 0) { + for (i = 0; i < data_len; i++) { + buf[i + header_len] ^= (buf + header_len - mask_len)[i % 4]; + } + } + + if (reass) { + /* On first fragmented frame, nullify size */ + if (mg_is_ws_first_fragment(wsm.flags)) { + mbuf_resize(&nc->recv_mbuf, nc->recv_mbuf.size + sizeof(*sizep)); + p[0] &= ~0x0f; /* Next frames will be treated as continuation */ + buf = p + 1 + sizeof(*sizep); + *sizep = 0; /* TODO(lsm): fix. this can stomp over frame data */ + } + + /* Append this frame to the reassembled buffer */ + memmove(buf, wsm.data, e - wsm.data); + (*sizep) += wsm.size; + nc->recv_mbuf.len -= wsm.data - buf; + + /* On last fragmented frame - call user handler and remove data */ + if (wsm.flags & 0x80) { + wsm.data = p + 1 + sizeof(*sizep); + wsm.size = *sizep; + mg_handle_incoming_websocket_frame(nc, &wsm); + mbuf_remove(&nc->recv_mbuf, 1 + sizeof(*sizep) + *sizep); + } + } else { + /* TODO(lsm): properly handle OOB control frames during defragmentation */ + mg_handle_incoming_websocket_frame(nc, &wsm); + mbuf_remove(&nc->recv_mbuf, (size_t) frame_len); /* Cleanup frame */ + } + + /* If client closes, close too */ + if ((buf[0] & 0x0f) == WEBSOCKET_OP_CLOSE) { + nc->flags |= MG_F_SEND_AND_CLOSE; + } + } + + return ok; +} + +struct ws_mask_ctx { + size_t pos; /* zero means unmasked */ + uint32_t mask; +}; + +static uint32_t mg_ws_random_mask(void) { + uint32_t mask; +/* + * The spec requires WS client to generate hard to + * guess mask keys. From RFC6455, Section 5.3: + * + * The unpredictability of the masking key is essential to prevent + * authors of malicious applications from selecting the bytes that appear on + * the wire. + * + * Hence this feature is essential when the actual end user of this API + * is untrusted code that wouldn't have access to a lower level net API + * anyway (e.g. web browsers). Hence this feature is low prio for most + * mongoose use cases and thus can be disabled, e.g. when porting to a platform + * that lacks rand(). + */ +#if MG_DISABLE_WS_RANDOM_MASK + mask = 0xefbeadde; /* generated with a random number generator, I swear */ +#else + if (sizeof(long) >= 4) { + mask = (uint32_t) rand(); + } else if (sizeof(long) == 2) { + mask = (uint32_t) rand() << 16 | (uint32_t) rand(); + } +#endif + return mask; +} + +static void mg_send_ws_header(struct mg_connection *nc, int op, size_t len, + struct ws_mask_ctx *ctx) { + int header_len; + unsigned char header[10]; + + header[0] = (op & WEBSOCKET_DONT_FIN ? 0x0 : 0x80) + (op & 0x0f); + if (len < 126) { + header[1] = (unsigned char) len; + header_len = 2; + } else if (len < 65535) { + uint16_t tmp = htons((uint16_t) len); + header[1] = 126; + memcpy(&header[2], &tmp, sizeof(tmp)); + header_len = 4; + } else { + uint32_t tmp; + header[1] = 127; + tmp = htonl((uint32_t)((uint64_t) len >> 32)); + memcpy(&header[2], &tmp, sizeof(tmp)); + tmp = htonl((uint32_t)(len & 0xffffffff)); + memcpy(&header[6], &tmp, sizeof(tmp)); + header_len = 10; + } + + /* client connections enable masking */ + if (nc->listener == NULL) { + header[1] |= 1 << 7; /* set masking flag */ + mg_send(nc, header, header_len); + ctx->mask = mg_ws_random_mask(); + mg_send(nc, &ctx->mask, sizeof(ctx->mask)); + ctx->pos = nc->send_mbuf.len; + } else { + mg_send(nc, header, header_len); + ctx->pos = 0; + } +} + +static void mg_ws_mask_frame(struct mbuf *mbuf, struct ws_mask_ctx *ctx) { + size_t i; + if (ctx->pos == 0) return; + for (i = 0; i < (mbuf->len - ctx->pos); i++) { + mbuf->buf[ctx->pos + i] ^= ((char *) &ctx->mask)[i % 4]; + } +} + +void mg_send_websocket_frame(struct mg_connection *nc, int op, const void *data, + size_t len) { + struct ws_mask_ctx ctx; + DBG(("%p %d %d", nc, op, (int) len)); + mg_send_ws_header(nc, op, len, &ctx); + mg_send(nc, data, len); + + mg_ws_mask_frame(&nc->send_mbuf, &ctx); + + if (op == WEBSOCKET_OP_CLOSE) { + nc->flags |= MG_F_SEND_AND_CLOSE; + } +} + +void mg_send_websocket_framev(struct mg_connection *nc, int op, + const struct mg_str *strv, int strvcnt) { + struct ws_mask_ctx ctx; + int i; + int len = 0; + for (i = 0; i < strvcnt; i++) { + len += strv[i].len; + } + + mg_send_ws_header(nc, op, len, &ctx); + + for (i = 0; i < strvcnt; i++) { + mg_send(nc, strv[i].p, strv[i].len); + } + + mg_ws_mask_frame(&nc->send_mbuf, &ctx); + + if (op == WEBSOCKET_OP_CLOSE) { + nc->flags |= MG_F_SEND_AND_CLOSE; + } +} + +void mg_printf_websocket_frame(struct mg_connection *nc, int op, + const char *fmt, ...) { + char mem[MG_VPRINTF_BUFFER_SIZE], *buf = mem; + va_list ap; + int len; + + va_start(ap, fmt); + if ((len = mg_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) { + mg_send_websocket_frame(nc, op, buf, len); + } + va_end(ap); + + if (buf != mem && buf != NULL) { + MG_FREE(buf); + } +} + +MG_INTERNAL void mg_ws_handler(struct mg_connection *nc, int ev, + void *ev_data) { + mg_call(nc, nc->handler, ev, ev_data); + + switch (ev) { + case MG_EV_RECV: + do { + } while (mg_deliver_websocket_data(nc)); + break; + case MG_EV_POLL: + /* Ping idle websocket connections */ + { + time_t now = *(time_t *) ev_data; + if (nc->flags & MG_F_IS_WEBSOCKET && + now > nc->last_io_time + MG_WEBSOCKET_PING_INTERVAL_SECONDS) { + mg_send_websocket_frame(nc, WEBSOCKET_OP_PING, "", 0); + } + } + break; + default: + break; + } +} + +#ifndef MG_EXT_SHA1 +static void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[], + const size_t *msg_lens, uint8_t *digest) { + size_t i; + cs_sha1_ctx sha_ctx; + cs_sha1_init(&sha_ctx); + for (i = 0; i < num_msgs; i++) { + cs_sha1_update(&sha_ctx, msgs[i], msg_lens[i]); + } + cs_sha1_final(digest, &sha_ctx); +} +#else +extern void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[], + const size_t *msg_lens, uint8_t *digest); +#endif + +MG_INTERNAL void mg_ws_handshake(struct mg_connection *nc, + const struct mg_str *key) { + static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + const uint8_t *msgs[2] = {(const uint8_t *) key->p, (const uint8_t *) magic}; + const size_t msg_lens[2] = {key->len, 36}; + unsigned char sha[20]; + char b64_sha[30]; + + mg_hash_sha1_v(2, msgs, msg_lens, sha); + mg_base64_encode(sha, sizeof(sha), b64_sha); + mg_printf(nc, "%s%s%s", + "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: ", + b64_sha, "\r\n\r\n"); + DBG(("%p %.*s %s", nc, (int) key->len, key->p, b64_sha)); +} + +void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path, + const char *host, const char *protocol, + const char *extra_headers) { + mg_send_websocket_handshake3(nc, path, host, protocol, extra_headers, NULL, + NULL); +} + +void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path, + const char *host, const char *protocol, + const char *extra_headers, const char *user, + const char *pass) { + struct mbuf auth; + char key[25]; + uint32_t nonce[4]; + nonce[0] = mg_ws_random_mask(); + nonce[1] = mg_ws_random_mask(); + nonce[2] = mg_ws_random_mask(); + nonce[3] = mg_ws_random_mask(); + mg_base64_encode((unsigned char *) &nonce, sizeof(nonce), key); + + mbuf_init(&auth, 0); + if (user != NULL) { + mg_basic_auth_header(user, pass, &auth); + } + + /* + * NOTE: the (auth.buf == NULL ? "" : auth.buf) is because cc3200 libc is + * broken: it doesn't like zero length to be passed to %.*s + * i.e. sprintf("f%.*so", (int)0, NULL), yields `f\0o`. + * because it handles NULL specially (and incorrectly). + */ + mg_printf(nc, + "GET %s HTTP/1.1\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "%.*s" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Key: %s\r\n", + path, (int) auth.len, (auth.buf == NULL ? "" : auth.buf), key); + + /* TODO(mkm): take default hostname from http proto data if host == NULL */ + if (host != MG_WS_NO_HOST_HEADER_MAGIC) { + mg_printf(nc, "Host: %s\r\n", host); + } + if (protocol != NULL) { + mg_printf(nc, "Sec-WebSocket-Protocol: %s\r\n", protocol); + } + if (extra_headers != NULL) { + mg_printf(nc, "%s", extra_headers); + } + mg_printf(nc, "\r\n"); + + mbuf_free(&auth); +} + +void mg_send_websocket_handshake(struct mg_connection *nc, const char *path, + const char *extra_headers) { + mg_send_websocket_handshake2(nc, path, MG_WS_NO_HOST_HEADER_MAGIC, NULL, + extra_headers); +} + +struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr, + mg_event_handler_t ev_handler, + struct mg_connect_opts opts, + const char *url, const char *protocol, + const char *extra_headers) { + char *user = NULL, *pass = NULL, *addr = NULL; + const char *path = NULL; + struct mg_connection *nc = + mg_connect_http_base(mgr, ev_handler, opts, "ws://", "wss://", url, &path, + &user, &pass, &addr); + + if (nc != NULL) { + mg_send_websocket_handshake3(nc, path, addr, protocol, extra_headers, user, + pass); + } + + MG_FREE(addr); + MG_FREE(user); + MG_FREE(pass); + return nc; +} + +struct mg_connection *mg_connect_ws(struct mg_mgr *mgr, + mg_event_handler_t ev_handler, + const char *url, const char *protocol, + const char *extra_headers) { + struct mg_connect_opts opts; + memset(&opts, 0, sizeof(opts)); + return mg_connect_ws_opt(mgr, ev_handler, opts, url, protocol, extra_headers); +} +#endif /* MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBSOCKET */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/util.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "common/base64.h" */ +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +/* For platforms with limited libc */ +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +const char *mg_skip(const char *s, const char *end, const char *delims, + struct mg_str *v) { + v->p = s; + while (s < end && strchr(delims, *(unsigned char *) s) == NULL) s++; + v->len = s - v->p; + while (s < end && strchr(delims, *(unsigned char *) s) != NULL) s++; + return s; +} + +static int lowercase(const char *s) { + return tolower(*(const unsigned char *) s); +} + +#if MG_ENABLE_FILESYSTEM +int mg_stat(const char *path, cs_stat_t *st) { +#ifdef _WIN32 + wchar_t wpath[MAX_PATH_SIZE]; + to_wchar(path, wpath, ARRAY_SIZE(wpath)); + DBG(("[%ls] -> %d", wpath, _wstati64(wpath, st))); + return _wstati64(wpath, st); +#else + return stat(path, st); +#endif +} + +FILE *mg_fopen(const char *path, const char *mode) { +#ifdef _WIN32 + wchar_t wpath[MAX_PATH_SIZE], wmode[10]; + to_wchar(path, wpath, ARRAY_SIZE(wpath)); + to_wchar(mode, wmode, ARRAY_SIZE(wmode)); + return _wfopen(wpath, wmode); +#else + return fopen(path, mode); +#endif +} + +int mg_open(const char *path, int flag, int mode) { /* LCOV_EXCL_LINE */ +#if defined(_WIN32) && !defined(WINCE) + wchar_t wpath[MAX_PATH_SIZE]; + to_wchar(path, wpath, ARRAY_SIZE(wpath)); + return _wopen(wpath, flag, mode); +#else + return open(path, flag, mode); /* LCOV_EXCL_LINE */ +#endif +} +#endif + +void mg_base64_encode(const unsigned char *src, int src_len, char *dst) { + cs_base64_encode(src, src_len, dst); +} + +int mg_base64_decode(const unsigned char *s, int len, char *dst) { + return cs_base64_decode(s, len, dst, NULL); +} + +#if MG_ENABLE_THREADS +void *mg_start_thread(void *(*f)(void *), void *p) { +#ifdef WINCE + return (void *) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) f, p, 0, NULL); +#elif defined(_WIN32) + return (void *) _beginthread((void(__cdecl *) (void *) ) f, 0, p); +#else + pthread_t thread_id = (pthread_t) 0; + pthread_attr_t attr; + + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + +#if defined(MG_STACK_SIZE) && MG_STACK_SIZE > 1 + (void) pthread_attr_setstacksize(&attr, MG_STACK_SIZE); +#endif + + pthread_create(&thread_id, &attr, f, p); + pthread_attr_destroy(&attr); + + return (void *) thread_id; +#endif +} +#endif /* MG_ENABLE_THREADS */ + +/* Set close-on-exec bit for a given socket. */ +void mg_set_close_on_exec(sock_t sock) { +#if defined(_WIN32) && !defined(WINCE) + (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0); +#elif defined(__unix__) + fcntl(sock, F_SETFD, FD_CLOEXEC); +#else + (void) sock; +#endif +} + +void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len, + int flags) { + int is_v6; + if (buf == NULL || len <= 0) return; + buf[0] = '\0'; +#if MG_ENABLE_IPV6 + is_v6 = sa->sa.sa_family == AF_INET6; +#else + is_v6 = 0; +#endif + if (flags & MG_SOCK_STRINGIFY_IP) { +#if MG_ENABLE_IPV6 + const void *addr = NULL; + char *start = buf; + socklen_t capacity = len; + if (!is_v6) { + addr = &sa->sin.sin_addr; + } else { + addr = (void *) &sa->sin6.sin6_addr; + if (flags & MG_SOCK_STRINGIFY_PORT) { + *buf = '['; + start++; + capacity--; + } + } + if (inet_ntop(sa->sa.sa_family, addr, start, capacity) == NULL) { + *buf = '\0'; + } +#elif defined(_WIN32) || MG_LWIP || (MG_NET_IF == MG_NET_IF_PIC32) + /* Only Windoze Vista (and newer) have inet_ntop() */ + strncpy(buf, inet_ntoa(sa->sin.sin_addr), len); +#else + inet_ntop(AF_INET, (void *) &sa->sin.sin_addr, buf, len); +#endif + } + if (flags & MG_SOCK_STRINGIFY_PORT) { + int port = ntohs(sa->sin.sin_port); + if (flags & MG_SOCK_STRINGIFY_IP) { + snprintf(buf + strlen(buf), len - (strlen(buf) + 1), "%s:%d", + (is_v6 ? "]" : ""), port); + } else { + snprintf(buf, len, "%d", port); + } + } +} + +void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len, + int flags) { + union socket_address sa; + memset(&sa, 0, sizeof(sa)); + mg_if_get_conn_addr(nc, flags & MG_SOCK_STRINGIFY_REMOTE, &sa); + mg_sock_addr_to_str(&sa, buf, len, flags); +} + +#if MG_ENABLE_HEXDUMP +int mg_hexdump(const void *buf, int len, char *dst, int dst_len) { + const unsigned char *p = (const unsigned char *) buf; + char ascii[17] = ""; + int i, idx, n = 0; + + for (i = 0; i < len; i++) { + idx = i % 16; + if (idx == 0) { + if (i > 0) n += snprintf(dst + n, MAX(dst_len - n, 0), " %s\n", ascii); + n += snprintf(dst + n, MAX(dst_len - n, 0), "%04x ", i); + } + if (dst_len - n < 0) { + return n; + } + n += snprintf(dst + n, MAX(dst_len - n, 0), " %02x", p[i]); + ascii[idx] = p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]; + ascii[idx + 1] = '\0'; + } + + while (i++ % 16) n += snprintf(dst + n, MAX(dst_len - n, 0), "%s", " "); + n += snprintf(dst + n, MAX(dst_len - n, 0), " %s\n\n", ascii); + + return n; +} + +void mg_hexdump_connection(struct mg_connection *nc, const char *path, + const void *buf, int num_bytes, int ev) { + FILE *fp = NULL; + char *hexbuf, src[60], dst[60]; + int buf_size = num_bytes * 5 + 100; + + if (strcmp(path, "-") == 0) { + fp = stdout; + } else if (strcmp(path, "--") == 0) { + fp = stderr; +#if MG_ENABLE_FILESYSTEM + } else { + fp = mg_fopen(path, "a"); +#endif + } + if (fp == NULL) return; + + mg_conn_addr_to_str(nc, src, sizeof(src), + MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); + mg_conn_addr_to_str(nc, dst, sizeof(dst), MG_SOCK_STRINGIFY_IP | + MG_SOCK_STRINGIFY_PORT | + MG_SOCK_STRINGIFY_REMOTE); + fprintf( + fp, "%lu %p %s %s %s %d\n", (unsigned long) mg_time(), (void *) nc, src, + ev == MG_EV_RECV ? "<-" : ev == MG_EV_SEND + ? "->" + : ev == MG_EV_ACCEPT + ? "" : "XX", + dst, num_bytes); + if (num_bytes > 0 && (hexbuf = (char *) MG_MALLOC(buf_size)) != NULL) { + mg_hexdump(buf, num_bytes, hexbuf, buf_size); + fprintf(fp, "%s", hexbuf); + MG_FREE(hexbuf); + } + if (fp != stdin && fp != stdout) fclose(fp); +} +#endif + +int mg_is_big_endian(void) { + static const int n = 1; + /* TODO(mkm) use compiletime check with 4-byte char literal */ + return ((char *) &n)[0] == 0; +} + +const char *mg_next_comma_list_entry(const char *list, struct mg_str *val, + struct mg_str *eq_val) { + if (list == NULL || *list == '\0') { + /* End of the list */ + list = NULL; + } else { + val->p = list; + if ((list = strchr(val->p, ',')) != NULL) { + /* Comma found. Store length and shift the list ptr */ + val->len = list - val->p; + list++; + } else { + /* This value is the last one */ + list = val->p + strlen(val->p); + val->len = list - val->p; + } + + if (eq_val != NULL) { + /* Value has form "x=y", adjust pointers and lengths */ + /* so that val points to "x", and eq_val points to "y". */ + eq_val->len = 0; + eq_val->p = (const char *) memchr(val->p, '=', val->len); + if (eq_val->p != NULL) { + eq_val->p++; /* Skip over '=' character */ + eq_val->len = val->p + val->len - eq_val->p; + val->len = (eq_val->p - val->p) - 1; + } + } + } + + return list; +} + +int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) { + const char *or_str; + size_t len, i = 0, j = 0; + int res; + + if ((or_str = (const char *) memchr(pattern.p, '|', pattern.len)) != NULL) { + struct mg_str pstr = {pattern.p, (size_t)(or_str - pattern.p)}; + res = mg_match_prefix_n(pstr, str); + if (res > 0) return res; + pstr.p = or_str + 1; + pstr.len = (pattern.p + pattern.len) - (or_str + 1); + return mg_match_prefix_n(pstr, str); + } + + for (; i < pattern.len; i++, j++) { + if (pattern.p[i] == '?' && j != str.len) { + continue; + } else if (pattern.p[i] == '$') { + return j == str.len ? (int) j : -1; + } else if (pattern.p[i] == '*') { + i++; + if (pattern.p[i] == '*') { + i++; + len = str.len - j; + } else { + len = 0; + while (j + len != str.len && str.p[j + len] != '/') { + len++; + } + } + if (i == pattern.len) { + return j + len; + } + do { + const struct mg_str pstr = {pattern.p + i, pattern.len - i}; + const struct mg_str sstr = {str.p + j + len, str.len - j - len}; + res = mg_match_prefix_n(pstr, sstr); + } while (res == -1 && len-- > 0); + return res == -1 ? -1 : (int) (j + res + len); + } else if (lowercase(&pattern.p[i]) != lowercase(&str.p[j])) { + return -1; + } + } + return j; +} + +int mg_match_prefix(const char *pattern, int pattern_len, const char *str) { + const struct mg_str pstr = {pattern, (size_t) pattern_len}; + return mg_match_prefix_n(pstr, mg_mk_str(str)); +} + +DO_NOT_WARN_UNUSED MG_INTERNAL int mg_get_errno(void) { +#ifndef WINCE + return errno; +#else + /* TODO(alashkin): translate error codes? */ + return GetLastError(); +#endif +} + +void mg_mbuf_append_base64_putc(char ch, void *user_data) { + struct mbuf *mbuf = (struct mbuf *) user_data; + mbuf_append(mbuf, &ch, sizeof(ch)); +} + +void mg_mbuf_append_base64(struct mbuf *mbuf, const void *data, size_t len) { + struct cs_base64_ctx ctx; + cs_base64_init(&ctx, mg_mbuf_append_base64_putc, mbuf); + cs_base64_update(&ctx, (const char *) data, len); + cs_base64_finish(&ctx); +} + +void mg_basic_auth_header(const char *user, const char *pass, + struct mbuf *buf) { + const char *header_prefix = "Authorization: Basic "; + const char *header_suffix = "\r\n"; + + struct cs_base64_ctx ctx; + cs_base64_init(&ctx, mg_mbuf_append_base64_putc, buf); + + mbuf_append(buf, header_prefix, strlen(header_prefix)); + + cs_base64_update(&ctx, user, strlen(user)); + if (pass != NULL) { + cs_base64_update(&ctx, ":", 1); + cs_base64_update(&ctx, pass, strlen(pass)); + } + cs_base64_finish(&ctx); + mbuf_append(buf, header_suffix, strlen(header_suffix)); +} +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/mqtt.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_MQTT + +#include + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/mqtt.h" */ + +static uint16_t getu16(const char *p) { + const uint8_t *up = (const uint8_t *) p; + return (up[0] << 8) + up[1]; +} + +static const char *scanto(const char *p, struct mg_str *s) { + s->len = getu16(p); + s->p = p + 2; + return s->p + s->len; +} + +MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { + uint8_t header; + size_t len = 0; + int cmd; + const char *p = &io->buf[1], *end; + + if (io->len < 2) return -1; + header = io->buf[0]; + cmd = header >> 4; + + /* decode mqtt variable length */ + do { + len += (*p & 127) << 7 * (p - &io->buf[1]); + } while ((*p++ & 128) != 0 && ((size_t)(p - io->buf) <= io->len)); + + end = p + len; + if (end > io->buf + io->len + 1) { + return -1; + } + + mm->cmd = cmd; + mm->qos = MG_MQTT_GET_QOS(header); + + switch (cmd) { + case MG_MQTT_CMD_CONNECT: { + p = scanto(p, &mm->protocol_name); + mm->protocol_version = *(uint8_t *) p++; + mm->connect_flags = *(uint8_t *) p++; + mm->keep_alive_timer = getu16(p); + p += 2; + if (p < end) p = scanto(p, &mm->client_id); + if (p < end && (mm->connect_flags & MG_MQTT_HAS_WILL)) + p = scanto(p, &mm->will_topic); + if (p < end && (mm->connect_flags & MG_MQTT_HAS_WILL)) + p = scanto(p, &mm->will_message); + if (p < end && (mm->connect_flags & MG_MQTT_HAS_USER_NAME)) + p = scanto(p, &mm->user_name); + if (p < end && (mm->connect_flags & MG_MQTT_HAS_PASSWORD)) + p = scanto(p, &mm->password); + + LOG(LL_DEBUG, + ("%d %2x %d proto [%.*s] client_id [%.*s] will_topic [%.*s] " + "will_msg [%.*s] user_name [%.*s] password [%.*s]", + len, (int) mm->connect_flags, (int) mm->keep_alive_timer, + (int) mm->protocol_name.len, mm->protocol_name.p, + (int) mm->client_id.len, mm->client_id.p, (int) mm->will_topic.len, + mm->will_topic.p, (int) mm->will_message.len, mm->will_message.p, + (int) mm->user_name.len, mm->user_name.p, (int) mm->password.len, + mm->password.p)); + break; + } + case MG_MQTT_CMD_CONNACK: + mm->connack_ret_code = p[1]; + break; + case MG_MQTT_CMD_PUBACK: + case MG_MQTT_CMD_PUBREC: + case MG_MQTT_CMD_PUBREL: + case MG_MQTT_CMD_PUBCOMP: + case MG_MQTT_CMD_SUBACK: + mm->message_id = getu16(p); + break; + case MG_MQTT_CMD_PUBLISH: { + if (MG_MQTT_GET_QOS(header) > 0) { + mm->message_id = getu16(p); + p += 2; + } + p = scanto(p, &mm->topic); + + mm->payload.p = p; + mm->payload.len = end - p; + break; + } + case MG_MQTT_CMD_SUBSCRIBE: + mm->message_id = getu16(p); + p += 2; + /* + * topic expressions are left in the payload and can be parsed with + * `mg_mqtt_next_subscribe_topic` + */ + mm->payload.p = p; + mm->payload.len = end - p; + break; + default: + /* Unhandled command */ + break; + } + + return end - io->buf; +} + +static void mqtt_handler(struct mg_connection *nc, int ev, void *ev_data) { + int len; + struct mbuf *io = &nc->recv_mbuf; + struct mg_mqtt_message mm; + memset(&mm, 0, sizeof(mm)); + + nc->handler(nc, ev, ev_data); + + switch (ev) { + case MG_EV_RECV: + len = parse_mqtt(io, &mm); + if (len == -1) break; /* not fully buffered */ + nc->handler(nc, MG_MQTT_EVENT_BASE + mm.cmd, &mm); + mbuf_remove(io, len); + break; + } +} + +static void mg_mqtt_proto_data_destructor(void *proto_data) { + MG_FREE(proto_data); +} + +void mg_set_protocol_mqtt(struct mg_connection *nc) { + nc->proto_handler = mqtt_handler; + nc->proto_data = MG_CALLOC(1, sizeof(struct mg_mqtt_proto_data)); + nc->proto_data_destructor = mg_mqtt_proto_data_destructor; +} + +void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id) { + static struct mg_send_mqtt_handshake_opts opts; + mg_send_mqtt_handshake_opt(nc, client_id, opts); +} + +void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id, + struct mg_send_mqtt_handshake_opts opts) { + uint8_t header = MG_MQTT_CMD_CONNECT << 4; + uint8_t rem_len; + uint16_t keep_alive; + uint16_t len; + struct mg_mqtt_proto_data *pd = (struct mg_mqtt_proto_data *) nc->proto_data; + + /* + * 9: version_header(len, magic_string, version_number), 1: flags, 2: + * keep-alive timer, + * 2: client_identifier_len, n: client_id + */ + rem_len = 9 + 1 + 2 + 2 + (uint8_t) strlen(client_id); + + if (opts.user_name != NULL) { + opts.flags |= MG_MQTT_HAS_USER_NAME; + rem_len += (uint8_t) strlen(opts.user_name) + 2; + } + if (opts.password != NULL) { + opts.flags |= MG_MQTT_HAS_PASSWORD; + rem_len += (uint8_t) strlen(opts.password) + 2; + } + if (opts.will_topic != NULL && opts.will_message != NULL) { + opts.flags |= MG_MQTT_HAS_WILL; + rem_len += (uint8_t) strlen(opts.will_topic) + 2; + rem_len += (uint8_t) strlen(opts.will_message) + 2; + } + + mg_send(nc, &header, 1); + mg_send(nc, &rem_len, 1); + mg_send(nc, "\00\06MQIsdp\03", 9); + mg_send(nc, &opts.flags, 1); + + if (opts.keep_alive == 0) { + opts.keep_alive = 60; + } + + keep_alive = htons(opts.keep_alive); + mg_send(nc, &keep_alive, 2); + + len = htons((uint16_t) strlen(client_id)); + mg_send(nc, &len, 2); + mg_send(nc, client_id, strlen(client_id)); + + if (opts.flags & MG_MQTT_HAS_WILL) { + len = htons((uint16_t) strlen(opts.will_topic)); + mg_send(nc, &len, 2); + mg_send(nc, opts.will_topic, strlen(opts.will_topic)); + + len = htons((uint16_t) strlen(opts.will_message)); + mg_send(nc, &len, 2); + mg_send(nc, opts.will_message, strlen(opts.will_message)); + } + + if (opts.flags & MG_MQTT_HAS_USER_NAME) { + len = htons((uint16_t) strlen(opts.user_name)); + mg_send(nc, &len, 2); + mg_send(nc, opts.user_name, strlen(opts.user_name)); + } + if (opts.flags & MG_MQTT_HAS_PASSWORD) { + len = htons((uint16_t) strlen(opts.password)); + mg_send(nc, &len, 2); + mg_send(nc, opts.password, strlen(opts.password)); + } + + if (pd != NULL) { + pd->keep_alive = opts.keep_alive; + } +} + +static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd, + uint8_t flags, size_t len) { + size_t off = nc->send_mbuf.len - len; + uint8_t header = cmd << 4 | (uint8_t) flags; + + uint8_t buf[1 + sizeof(size_t)]; + uint8_t *vlen = &buf[1]; + + assert(nc->send_mbuf.len >= len); + + buf[0] = header; + + /* mqtt variable length encoding */ + do { + *vlen = len % 0x80; + len /= 0x80; + if (len > 0) *vlen |= 0x80; + vlen++; + } while (len > 0); + + mbuf_insert(&nc->send_mbuf, off, buf, vlen - buf); +} + +void mg_mqtt_publish(struct mg_connection *nc, const char *topic, + uint16_t message_id, int flags, const void *data, + size_t len) { + size_t old_len = nc->send_mbuf.len; + + uint16_t topic_len = htons((uint16_t) strlen(topic)); + uint16_t message_id_net = htons(message_id); + + mg_send(nc, &topic_len, 2); + mg_send(nc, topic, strlen(topic)); + if (MG_MQTT_GET_QOS(flags) > 0) { + mg_send(nc, &message_id_net, 2); + } + mg_send(nc, data, len); + + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_PUBLISH, flags, + nc->send_mbuf.len - old_len); +} + +void mg_mqtt_subscribe(struct mg_connection *nc, + const struct mg_mqtt_topic_expression *topics, + size_t topics_len, uint16_t message_id) { + size_t old_len = nc->send_mbuf.len; + + uint16_t message_id_n = htons(message_id); + size_t i; + + mg_send(nc, (char *) &message_id_n, 2); + for (i = 0; i < topics_len; i++) { + uint16_t topic_len_n = htons((uint16_t) strlen(topics[i].topic)); + mg_send(nc, &topic_len_n, 2); + mg_send(nc, topics[i].topic, strlen(topics[i].topic)); + mg_send(nc, &topics[i].qos, 1); + } + + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_SUBSCRIBE, MG_MQTT_QOS(1), + nc->send_mbuf.len - old_len); +} + +int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg, + struct mg_str *topic, uint8_t *qos, int pos) { + unsigned char *buf = (unsigned char *) msg->payload.p + pos; + + if ((size_t) pos >= msg->payload.len) { + return -1; + } + + topic->len = buf[0] << 8 | buf[1]; + topic->p = (char *) buf + 2; + *qos = buf[2 + topic->len]; + return pos + 2 + topic->len + 1; +} + +void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics, + size_t topics_len, uint16_t message_id) { + size_t old_len = nc->send_mbuf.len; + + uint16_t message_id_n = htons(message_id); + size_t i; + + mg_send(nc, (char *) &message_id_n, 2); + for (i = 0; i < topics_len; i++) { + uint16_t topic_len_n = htons((uint16_t) strlen(topics[i])); + mg_send(nc, &topic_len_n, 2); + mg_send(nc, topics[i], strlen(topics[i])); + } + + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_UNSUBSCRIBE, MG_MQTT_QOS(1), + nc->send_mbuf.len - old_len); +} + +void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code) { + uint8_t unused = 0; + mg_send(nc, &unused, 1); + mg_send(nc, &return_code, 1); + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_CONNACK, 0, 2); +} + +/* + * Sends a command which contains only a `message_id` and a QoS level of 1. + * + * Helper function. + */ +static void mg_send_mqtt_short_command(struct mg_connection *nc, uint8_t cmd, + uint16_t message_id) { + uint16_t message_id_net = htons(message_id); + mg_send(nc, &message_id_net, 2); + mg_mqtt_prepend_header(nc, cmd, MG_MQTT_QOS(1), 2); +} + +void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id) { + mg_send_mqtt_short_command(nc, MG_MQTT_CMD_PUBACK, message_id); +} + +void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id) { + mg_send_mqtt_short_command(nc, MG_MQTT_CMD_PUBREC, message_id); +} + +void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id) { + mg_send_mqtt_short_command(nc, MG_MQTT_CMD_PUBREL, message_id); +} + +void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id) { + mg_send_mqtt_short_command(nc, MG_MQTT_CMD_PUBCOMP, message_id); +} + +void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len, + uint16_t message_id) { + size_t i; + uint16_t message_id_net = htons(message_id); + mg_send(nc, &message_id_net, 2); + for (i = 0; i < qoss_len; i++) { + mg_send(nc, &qoss[i], 1); + } + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_SUBACK, MG_MQTT_QOS(1), 2 + qoss_len); +} + +void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id) { + mg_send_mqtt_short_command(nc, MG_MQTT_CMD_UNSUBACK, message_id); +} + +void mg_mqtt_ping(struct mg_connection *nc) { + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_PINGREQ, 0, 0); +} + +void mg_mqtt_pong(struct mg_connection *nc) { + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_PINGRESP, 0, 0); +} + +void mg_mqtt_disconnect(struct mg_connection *nc) { + mg_mqtt_prepend_header(nc, MG_MQTT_CMD_DISCONNECT, 0, 0); +} + +#endif /* MG_ENABLE_MQTT */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/mqtt_server.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/mqtt-server.h" */ + +#if MG_ENABLE_MQTT_BROKER + +static void mg_mqtt_session_init(struct mg_mqtt_broker *brk, + struct mg_mqtt_session *s, + struct mg_connection *nc) { + s->brk = brk; + s->subscriptions = NULL; + s->num_subscriptions = 0; + s->nc = nc; +} + +static void mg_mqtt_add_session(struct mg_mqtt_session *s) { + LIST_INSERT_HEAD(&s->brk->sessions, s, link); +} + +static void mg_mqtt_remove_session(struct mg_mqtt_session *s) { + LIST_REMOVE(s, link); +} + +static void mg_mqtt_destroy_session(struct mg_mqtt_session *s) { + size_t i; + for (i = 0; i < s->num_subscriptions; i++) { + MG_FREE((void *) s->subscriptions[i].topic); + } + MG_FREE(s->subscriptions); + MG_FREE(s); +} + +static void mg_mqtt_close_session(struct mg_mqtt_session *s) { + mg_mqtt_remove_session(s); + mg_mqtt_destroy_session(s); +} + +void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data) { + LIST_INIT(&brk->sessions); + brk->user_data = user_data; +} + +static void mg_mqtt_broker_handle_connect(struct mg_mqtt_broker *brk, + struct mg_connection *nc) { + struct mg_mqtt_session *s = (struct mg_mqtt_session *) calloc(1, sizeof *s); + if (s == NULL) { + /* LCOV_EXCL_START */ + mg_mqtt_connack(nc, MG_EV_MQTT_CONNACK_SERVER_UNAVAILABLE); + return; + /* LCOV_EXCL_STOP */ + } + + /* TODO(mkm): check header (magic and version) */ + + mg_mqtt_session_init(brk, s, nc); + s->user_data = nc->user_data; + nc->user_data = s; + mg_mqtt_add_session(s); + + mg_mqtt_connack(nc, MG_EV_MQTT_CONNACK_ACCEPTED); +} + +static void mg_mqtt_broker_handle_subscribe(struct mg_connection *nc, + struct mg_mqtt_message *msg) { + struct mg_mqtt_session *ss = (struct mg_mqtt_session *) nc->user_data; + uint8_t qoss[512]; + size_t qoss_len = 0; + struct mg_str topic; + uint8_t qos; + int pos; + struct mg_mqtt_topic_expression *te; + + for (pos = 0; + (pos = mg_mqtt_next_subscribe_topic(msg, &topic, &qos, pos)) != -1;) { + qoss[qoss_len++] = qos; + } + + ss->subscriptions = (struct mg_mqtt_topic_expression *) realloc( + ss->subscriptions, sizeof(*ss->subscriptions) * qoss_len); + for (pos = 0; + (pos = mg_mqtt_next_subscribe_topic(msg, &topic, &qos, pos)) != -1; + ss->num_subscriptions++) { + te = &ss->subscriptions[ss->num_subscriptions]; + te->topic = (char *) malloc(topic.len + 1); + te->qos = qos; + strncpy((char *) te->topic, topic.p, topic.len + 1); + } + + mg_mqtt_suback(nc, qoss, qoss_len, msg->message_id); +} + +/* + * Matches a topic against a topic expression + * + * See http://goo.gl/iWk21X + * + * Returns 1 if it matches; 0 otherwise. + */ +static int mg_mqtt_match_topic_expression(const char *exp, + const struct mg_str *topic) { + /* TODO(mkm): implement real matching */ + size_t len = strlen(exp); + if (strchr(exp, '#')) { + len -= 2; + if (topic->len < len) { + len = topic->len; + } + } + return strncmp(topic->p, exp, len) == 0; +} + +static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk, + struct mg_mqtt_message *msg) { + struct mg_mqtt_session *s; + size_t i; + + for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) { + for (i = 0; i < s->num_subscriptions; i++) { + if (mg_mqtt_match_topic_expression(s->subscriptions[i].topic, + &msg->topic)) { + char buf[100], *p = buf; + mg_asprintf(&p, sizeof(buf), "%.*s", (int) msg->topic.len, + msg->topic.p); + if (p == NULL) { + return; + } + mg_mqtt_publish(s->nc, p, 0, 0, msg->payload.p, msg->payload.len); + if (p != buf) { + MG_FREE(p); + } + break; + } + } + } +} + +void mg_mqtt_broker(struct mg_connection *nc, int ev, void *data) { + struct mg_mqtt_message *msg = (struct mg_mqtt_message *) data; + struct mg_mqtt_broker *brk; + + if (nc->listener) { + brk = (struct mg_mqtt_broker *) nc->listener->user_data; + } else { + brk = (struct mg_mqtt_broker *) nc->user_data; + } + + switch (ev) { + case MG_EV_ACCEPT: + mg_set_protocol_mqtt(nc); + nc->user_data = NULL; /* Clear up the inherited pointer to broker */ + break; + case MG_EV_MQTT_CONNECT: + mg_mqtt_broker_handle_connect(brk, nc); + break; + case MG_EV_MQTT_SUBSCRIBE: + mg_mqtt_broker_handle_subscribe(nc, msg); + break; + case MG_EV_MQTT_PUBLISH: + mg_mqtt_broker_handle_publish(brk, msg); + break; + case MG_EV_CLOSE: + if (nc->listener && nc->user_data != NULL) { + mg_mqtt_close_session((struct mg_mqtt_session *) nc->user_data); + } + break; + } +} + +struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk, + struct mg_mqtt_session *s) { + return s == NULL ? LIST_FIRST(&brk->sessions) : LIST_NEXT(s, link); +} + +#endif /* MG_ENABLE_MQTT_BROKER */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/dns.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_DNS + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/dns.h" */ + +static int mg_dns_tid = 0xa0; + +struct mg_dns_header { + uint16_t transaction_id; + uint16_t flags; + uint16_t num_questions; + uint16_t num_answers; + uint16_t num_authority_prs; + uint16_t num_other_prs; +}; + +struct mg_dns_resource_record *mg_dns_next_record( + struct mg_dns_message *msg, int query, + struct mg_dns_resource_record *prev) { + struct mg_dns_resource_record *rr; + + for (rr = (prev == NULL ? msg->answers : prev + 1); + rr - msg->answers < msg->num_answers; rr++) { + if (rr->rtype == query) { + return rr; + } + } + return NULL; +} + +int mg_dns_parse_record_data(struct mg_dns_message *msg, + struct mg_dns_resource_record *rr, void *data, + size_t data_len) { + switch (rr->rtype) { + case MG_DNS_A_RECORD: + if (data_len < sizeof(struct in_addr)) { + return -1; + } + if (rr->rdata.p + data_len > msg->pkt.p + msg->pkt.len) { + return -1; + } + memcpy(data, rr->rdata.p, data_len); + return 0; +#if MG_ENABLE_IPV6 + case MG_DNS_AAAA_RECORD: + if (data_len < sizeof(struct in6_addr)) { + return -1; /* LCOV_EXCL_LINE */ + } + memcpy(data, rr->rdata.p, data_len); + return 0; +#endif + case MG_DNS_CNAME_RECORD: + mg_dns_uncompress_name(msg, &rr->rdata, (char *) data, data_len); + return 0; + } + + return -1; +} + +int mg_dns_insert_header(struct mbuf *io, size_t pos, + struct mg_dns_message *msg) { + struct mg_dns_header header; + + memset(&header, 0, sizeof(header)); + header.transaction_id = msg->transaction_id; + header.flags = htons(msg->flags); + header.num_questions = htons(msg->num_questions); + header.num_answers = htons(msg->num_answers); + + return mbuf_insert(io, pos, &header, sizeof(header)); +} + +int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg) { + unsigned char *begin, *end; + struct mg_dns_resource_record *last_q; + if (msg->num_questions <= 0) return 0; + begin = (unsigned char *) msg->pkt.p + sizeof(struct mg_dns_header); + last_q = &msg->questions[msg->num_questions - 1]; + end = (unsigned char *) last_q->name.p + last_q->name.len + 4; + return mbuf_append(io, begin, end - begin); +} + +int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len) { + const char *s; + unsigned char n; + size_t pos = io->len; + + do { + if ((s = strchr(name, '.')) == NULL) { + s = name + len; + } + + if (s - name > 127) { + return -1; /* TODO(mkm) cover */ + } + n = s - name; /* chunk length */ + mbuf_append(io, &n, 1); /* send length */ + mbuf_append(io, name, n); + + if (*s == '.') { + n++; + } + + name += n; + len -= n; + } while (*s != '\0'); + mbuf_append(io, "\0", 1); /* Mark end of host name */ + + return io->len - pos; +} + +int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr, + const char *name, size_t nlen, const void *rdata, + size_t rlen) { + size_t pos = io->len; + uint16_t u16; + uint32_t u32; + + if (rr->kind == MG_DNS_INVALID_RECORD) { + return -1; /* LCOV_EXCL_LINE */ + } + + if (mg_dns_encode_name(io, name, nlen) == -1) { + return -1; + } + + u16 = htons(rr->rtype); + mbuf_append(io, &u16, 2); + u16 = htons(rr->rclass); + mbuf_append(io, &u16, 2); + + if (rr->kind == MG_DNS_ANSWER) { + u32 = htonl(rr->ttl); + mbuf_append(io, &u32, 4); + + if (rr->rtype == MG_DNS_CNAME_RECORD) { + int clen; + /* fill size after encoding */ + size_t off = io->len; + mbuf_append(io, &u16, 2); + if ((clen = mg_dns_encode_name(io, (const char *) rdata, rlen)) == -1) { + return -1; + } + u16 = clen; + io->buf[off] = u16 >> 8; + io->buf[off + 1] = u16 & 0xff; + } else { + u16 = htons((uint16_t) rlen); + mbuf_append(io, &u16, 2); + mbuf_append(io, rdata, rlen); + } + } + + return io->len - pos; +} + +void mg_send_dns_query(struct mg_connection *nc, const char *name, + int query_type) { + struct mg_dns_message *msg = + (struct mg_dns_message *) MG_CALLOC(1, sizeof(*msg)); + struct mbuf pkt; + struct mg_dns_resource_record *rr = &msg->questions[0]; + + DBG(("%s %d", name, query_type)); + + mbuf_init(&pkt, 64 /* Start small, it'll grow as needed. */); + + msg->transaction_id = ++mg_dns_tid; + msg->flags = 0x100; + msg->num_questions = 1; + + mg_dns_insert_header(&pkt, 0, msg); + + rr->rtype = query_type; + rr->rclass = 1; /* Class: inet */ + rr->kind = MG_DNS_QUESTION; + + if (mg_dns_encode_record(&pkt, rr, name, strlen(name), NULL, 0) == -1) { + /* TODO(mkm): return an error code */ + goto cleanup; /* LCOV_EXCL_LINE */ + } + + /* TCP DNS requires messages to be prefixed with len */ + if (!(nc->flags & MG_F_UDP)) { + uint16_t len = htons((uint16_t) pkt.len); + mbuf_insert(&pkt, 0, &len, 2); + } + + mg_send(nc, pkt.buf, pkt.len); + mbuf_free(&pkt); + +cleanup: + MG_FREE(msg); +} + +static unsigned char *mg_parse_dns_resource_record( + unsigned char *data, unsigned char *end, struct mg_dns_resource_record *rr, + int reply) { + unsigned char *name = data; + int chunk_len, data_len; + + while (data < end && (chunk_len = *data)) { + if (((unsigned char *) data)[0] & 0xc0) { + data += 1; + break; + } + data += chunk_len + 1; + } + + if (data > end - 5) { + return NULL; + } + + rr->name.p = (char *) name; + rr->name.len = data - name + 1; + data++; + + rr->rtype = data[0] << 8 | data[1]; + data += 2; + + rr->rclass = data[0] << 8 | data[1]; + data += 2; + + rr->kind = reply ? MG_DNS_ANSWER : MG_DNS_QUESTION; + if (reply) { + if (data >= end - 6) { + return NULL; + } + + rr->ttl = (uint32_t) data[0] << 24 | (uint32_t) data[1] << 16 | + data[2] << 8 | data[3]; + data += 4; + + data_len = *data << 8 | *(data + 1); + data += 2; + + rr->rdata.p = (char *) data; + rr->rdata.len = data_len; + data += data_len; + } + return data; +} + +int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg) { + struct mg_dns_header *header = (struct mg_dns_header *) buf; + unsigned char *data = (unsigned char *) buf + sizeof(*header); + unsigned char *end = (unsigned char *) buf + len; + int i; + + memset(msg, 0, sizeof(*msg)); + msg->pkt.p = buf; + msg->pkt.len = len; + + if (len < (int) sizeof(*header)) return -1; + + msg->transaction_id = header->transaction_id; + msg->flags = ntohs(header->flags); + msg->num_questions = ntohs(header->num_questions); + if (msg->num_questions > (int) ARRAY_SIZE(msg->questions)) { + msg->num_questions = (int) ARRAY_SIZE(msg->questions); + } + msg->num_answers = ntohs(header->num_answers); + if (msg->num_answers > (int) ARRAY_SIZE(msg->answers)) { + msg->num_answers = (int) ARRAY_SIZE(msg->answers); + } + + for (i = 0; i < msg->num_questions; i++) { + data = mg_parse_dns_resource_record(data, end, &msg->questions[i], 0); + if (data == NULL) return -1; + } + + for (i = 0; i < msg->num_answers; i++) { + data = mg_parse_dns_resource_record(data, end, &msg->answers[i], 1); + if (data == NULL) return -1; + } + + return 0; +} + +size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name, + char *dst, int dst_len) { + int chunk_len; + char *old_dst = dst; + const unsigned char *data = (unsigned char *) name->p; + const unsigned char *end = (unsigned char *) msg->pkt.p + msg->pkt.len; + + if (data >= end) { + return 0; + } + + while ((chunk_len = *data++)) { + int leeway = dst_len - (dst - old_dst); + if (data >= end) { + return 0; + } + + if (chunk_len & 0xc0) { + uint16_t off = (data[-1] & (~0xc0)) << 8 | data[0]; + if (off >= msg->pkt.len) { + return 0; + } + data = (unsigned char *) msg->pkt.p + off; + continue; + } + if (chunk_len > leeway) { + chunk_len = leeway; + } + + if (data + chunk_len >= end) { + return 0; + } + + memcpy(dst, data, chunk_len); + data += chunk_len; + dst += chunk_len; + leeway -= chunk_len; + if (leeway == 0) { + return dst - old_dst; + } + *dst++ = '.'; + } + + if (dst != old_dst) { + *--dst = 0; + } + return dst - old_dst; +} + +static void dns_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct mbuf *io = &nc->recv_mbuf; + struct mg_dns_message msg; + + /* Pass low-level events to the user handler */ + nc->handler(nc, ev, ev_data); + + switch (ev) { + case MG_EV_RECV: + if (!(nc->flags & MG_F_UDP)) { + mbuf_remove(&nc->recv_mbuf, 2); + } + if (mg_parse_dns(nc->recv_mbuf.buf, nc->recv_mbuf.len, &msg) == -1) { + /* reply + recursion allowed + format error */ + memset(&msg, 0, sizeof(msg)); + msg.flags = 0x8081; + mg_dns_insert_header(io, 0, &msg); + if (!(nc->flags & MG_F_UDP)) { + uint16_t len = htons((uint16_t) io->len); + mbuf_insert(io, 0, &len, 2); + } + mg_send(nc, io->buf, io->len); + } else { + /* Call user handler with parsed message */ + nc->handler(nc, MG_DNS_MESSAGE, &msg); + } + mbuf_remove(io, io->len); + break; + } +} + +void mg_set_protocol_dns(struct mg_connection *nc) { + nc->proto_handler = dns_handler; +} + +#endif /* MG_ENABLE_DNS */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/dns_server.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_DNS_SERVER + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/dns-server.h" */ + +struct mg_dns_reply mg_dns_create_reply(struct mbuf *io, + struct mg_dns_message *msg) { + struct mg_dns_reply rep; + rep.msg = msg; + rep.io = io; + rep.start = io->len; + + /* reply + recursion allowed */ + msg->flags |= 0x8080; + mg_dns_copy_questions(io, msg); + + msg->num_answers = 0; + return rep; +} + +void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r) { + size_t sent = r->io->len - r->start; + mg_dns_insert_header(r->io, r->start, r->msg); + if (!(nc->flags & MG_F_UDP)) { + uint16_t len = htons((uint16_t) sent); + mbuf_insert(r->io, r->start, &len, 2); + } + + if (&nc->send_mbuf != r->io) { + mg_send(nc, r->io->buf + r->start, r->io->len - r->start); + r->io->len = r->start; + } +} + +int mg_dns_reply_record(struct mg_dns_reply *reply, + struct mg_dns_resource_record *question, + const char *name, int rtype, int ttl, const void *rdata, + size_t rdata_len) { + struct mg_dns_message *msg = (struct mg_dns_message *) reply->msg; + char rname[512]; + struct mg_dns_resource_record *ans = &msg->answers[msg->num_answers]; + if (msg->num_answers >= MG_MAX_DNS_ANSWERS) { + return -1; /* LCOV_EXCL_LINE */ + } + + if (name == NULL) { + name = rname; + rname[511] = 0; + mg_dns_uncompress_name(msg, &question->name, rname, sizeof(rname) - 1); + } + + *ans = *question; + ans->kind = MG_DNS_ANSWER; + ans->rtype = rtype; + ans->ttl = ttl; + + if (mg_dns_encode_record(reply->io, ans, name, strlen(name), rdata, + rdata_len) == -1) { + return -1; /* LCOV_EXCL_LINE */ + }; + + msg->num_answers++; + return 0; +} + +#endif /* MG_ENABLE_DNS_SERVER */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/resolv.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_ASYNC_RESOLVER + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/resolv.h" */ + +#ifndef MG_DEFAULT_NAMESERVER +#define MG_DEFAULT_NAMESERVER "8.8.8.8" +#endif + +static const char *mg_default_dns_server = "udp://" MG_DEFAULT_NAMESERVER ":53"; + +MG_INTERNAL char mg_dns_server[256]; + +struct mg_resolve_async_request { + char name[1024]; + int query; + mg_resolve_callback_t callback; + void *data; + time_t timeout; + int max_retries; + enum mg_resolve_err err; + + /* state */ + time_t last_time; + int retries; +}; + +/* + * Find what nameserver to use. + * + * Return 0 if OK, -1 if error + */ +static int mg_get_ip_address_of_nameserver(char *name, size_t name_len) { + int ret = -1; + +#ifdef _WIN32 + int i; + LONG err; + HKEY hKey, hSub; + wchar_t subkey[512], value[128], + *key = L"SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"; + + if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey)) != + ERROR_SUCCESS) { + fprintf(stderr, "cannot open reg key %S: %ld\n", key, err); + ret = -1; + } else { + for (ret = -1, i = 0; 1; i++) { + DWORD subkey_size = sizeof(subkey), type, len = sizeof(value); + if (RegEnumKeyExW(hKey, i, subkey, &subkey_size, NULL, NULL, NULL, + NULL) != ERROR_SUCCESS) { + break; + } + if (RegOpenKeyExW(hKey, subkey, 0, KEY_READ, &hSub) == ERROR_SUCCESS && + (RegQueryValueExW(hSub, L"NameServer", 0, &type, (void *) value, + &len) == ERROR_SUCCESS || + RegQueryValueExW(hSub, L"DhcpNameServer", 0, &type, (void *) value, + &len) == ERROR_SUCCESS)) { + /* + * See https://github.com/cesanta/mongoose/issues/176 + * The value taken from the registry can be empty, a single + * IP address, or multiple IP addresses separated by comma. + * If it's empty, check the next interface. + * If it's multiple IP addresses, take the first one. + */ + wchar_t *comma = wcschr(value, ','); + if (value[0] == '\0') { + continue; + } + if (comma != NULL) { + *comma = '\0'; + } + snprintf(name, name_len, "udp://%S:53", value); + ret = 0; + RegCloseKey(hSub); + break; + } + } + RegCloseKey(hKey); + } +#elif MG_ENABLE_FILESYSTEM + FILE *fp; + char line[512]; + + if ((fp = mg_fopen("/etc/resolv.conf", "r")) == NULL) { + ret = -1; + } else { + /* Try to figure out what nameserver to use */ + for (ret = -1; fgets(line, sizeof(line), fp) != NULL;) { + unsigned int a, b, c, d; + if (sscanf(line, "nameserver %u.%u.%u.%u", &a, &b, &c, &d) == 4) { + snprintf(name, name_len, "udp://%u.%u.%u.%u:53", a, b, c, d); + ret = 0; + break; + } + } + (void) fclose(fp); + } +#else + snprintf(name, name_len, "%s", mg_default_dns_server); +#endif /* _WIN32 */ + + return ret; +} + +int mg_resolve_from_hosts_file(const char *name, union socket_address *usa) { +#if MG_ENABLE_FILESYSTEM + /* TODO(mkm) cache /etc/hosts */ + FILE *fp; + char line[1024]; + char *p; + char alias[256]; + unsigned int a, b, c, d; + int len = 0; + + if ((fp = mg_fopen("/etc/hosts", "r")) == NULL) { + return -1; + } + + for (; fgets(line, sizeof(line), fp) != NULL;) { + if (line[0] == '#') continue; + + if (sscanf(line, "%u.%u.%u.%u%n", &a, &b, &c, &d, &len) == 0) { + /* TODO(mkm): handle ipv6 */ + continue; + } + for (p = line + len; sscanf(p, "%s%n", alias, &len) == 1; p += len) { + if (strcmp(alias, name) == 0) { + usa->sin.sin_addr.s_addr = htonl(a << 24 | b << 16 | c << 8 | d); + fclose(fp); + return 0; + } + } + } + + fclose(fp); +#else + (void) name; + (void) usa; +#endif + + return -1; +} + +static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data) { + time_t now = (time_t) mg_time(); + struct mg_resolve_async_request *req; + struct mg_dns_message *msg; + int first = 0; + + DBG(("ev=%d user_data=%p", ev, nc->user_data)); + + req = (struct mg_resolve_async_request *) nc->user_data; + + if (req == NULL) { + return; + } + + switch (ev) { + case MG_EV_CONNECT: + /* don't depend on timer not being at epoch for sending out first req */ + first = 1; + /* fallthrough */ + case MG_EV_POLL: + if (req->retries > req->max_retries) { + req->err = MG_RESOLVE_EXCEEDED_RETRY_COUNT; + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + } + if (first || now - req->last_time >= req->timeout) { + mg_send_dns_query(nc, req->name, req->query); + req->last_time = now; + req->retries++; + } + break; + case MG_EV_RECV: + msg = (struct mg_dns_message *) MG_MALLOC(sizeof(*msg)); + if (mg_parse_dns(nc->recv_mbuf.buf, *(int *) data, msg) == 0 && + msg->num_answers > 0) { + req->callback(msg, req->data, MG_RESOLVE_OK); + nc->user_data = NULL; + MG_FREE(req); + } else { + req->err = MG_RESOLVE_NO_ANSWERS; + } + MG_FREE(msg); + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + case MG_EV_SEND: + /* + * If a send error occurs, prevent closing of the connection by the core. + * We will retry after timeout. + */ + nc->flags &= ~MG_F_CLOSE_IMMEDIATELY; + mbuf_remove(&nc->send_mbuf, nc->send_mbuf.len); + break; + case MG_EV_TIMER: + req->err = MG_RESOLVE_TIMEOUT; + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + case MG_EV_CLOSE: + /* If we got here with request still not done, fire an error callback. */ + if (req != NULL) { + req->callback(NULL, req->data, req->err); + nc->user_data = NULL; + MG_FREE(req); + } + break; + } +} + +int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query, + mg_resolve_callback_t cb, void *data) { + struct mg_resolve_async_opts opts; + memset(&opts, 0, sizeof(opts)); + return mg_resolve_async_opt(mgr, name, query, cb, data, opts); +} + +int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query, + mg_resolve_callback_t cb, void *data, + struct mg_resolve_async_opts opts) { + struct mg_resolve_async_request *req; + struct mg_connection *dns_nc; + const char *nameserver = opts.nameserver_url; + + DBG(("%s %d %p", name, query, opts.dns_conn)); + + /* resolve with DNS */ + req = (struct mg_resolve_async_request *) MG_CALLOC(1, sizeof(*req)); + if (req == NULL) { + return -1; + } + + strncpy(req->name, name, sizeof(req->name)); + req->query = query; + req->callback = cb; + req->data = data; + /* TODO(mkm): parse defaults out of resolve.conf */ + req->max_retries = opts.max_retries ? opts.max_retries : 2; + req->timeout = opts.timeout ? opts.timeout : 5; + + /* Lazily initialize dns server */ + if (nameserver == NULL && mg_dns_server[0] == '\0' && + mg_get_ip_address_of_nameserver(mg_dns_server, sizeof(mg_dns_server)) == + -1) { + strncpy(mg_dns_server, mg_default_dns_server, sizeof(mg_dns_server)); + } + + if (nameserver == NULL) { + nameserver = mg_dns_server; + } + + dns_nc = mg_connect(mgr, nameserver, mg_resolve_async_eh); + if (dns_nc == NULL) { + free(req); + return -1; + } + dns_nc->user_data = req; + if (opts.dns_conn != NULL) { + *opts.dns_conn = dns_nc; + } + + return 0; +} + +#endif /* MG_ENABLE_ASYNC_RESOLVER */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/coap.c" +#endif +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/coap.h" */ + +#if MG_ENABLE_COAP + +void mg_coap_free_options(struct mg_coap_message *cm) { + while (cm->options != NULL) { + struct mg_coap_option *next = cm->options->next; + MG_FREE(cm->options); + cm->options = next; + } +} + +struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm, + uint32_t number, char *value, + size_t len) { + struct mg_coap_option *new_option = + (struct mg_coap_option *) MG_CALLOC(1, sizeof(*new_option)); + + new_option->number = number; + new_option->value.p = value; + new_option->value.len = len; + + if (cm->options == NULL) { + cm->options = cm->optiomg_tail = new_option; + } else { + /* + * A very simple attention to help clients to compose options: + * CoAP wants to see options ASC ordered. + * Could be change by using sort in coap_compose + */ + if (cm->optiomg_tail->number <= new_option->number) { + /* if option is already ordered just add it */ + cm->optiomg_tail = cm->optiomg_tail->next = new_option; + } else { + /* looking for appropriate position */ + struct mg_coap_option *current_opt = cm->options; + struct mg_coap_option *prev_opt = 0; + + while (current_opt != NULL) { + if (current_opt->number > new_option->number) { + break; + } + prev_opt = current_opt; + current_opt = current_opt->next; + } + + if (prev_opt != NULL) { + prev_opt->next = new_option; + new_option->next = current_opt; + } else { + /* insert new_option to the beginning */ + new_option->next = cm->options; + cm->options = new_option; + } + } + } + + return new_option; +} + +/* + * Fills CoAP header in mg_coap_message. + * + * Helper function. + */ +static char *coap_parse_header(char *ptr, struct mbuf *io, + struct mg_coap_message *cm) { + if (io->len < sizeof(uint32_t)) { + cm->flags |= MG_COAP_NOT_ENOUGH_DATA; + return NULL; + } + + /* + * Version (Ver): 2-bit unsigned integer. Indicates the CoAP version + * number. Implementations of this specification MUST set this field + * to 1 (01 binary). Other values are reserved for future versions. + * Messages with unknown version numbers MUST be silently ignored. + */ + if (((uint8_t) *ptr >> 6) != 1) { + cm->flags |= MG_COAP_IGNORE; + return NULL; + } + + /* + * Type (T): 2-bit unsigned integer. Indicates if this message is of + * type Confirmable (0), Non-confirmable (1), Acknowledgement (2), or + * Reset (3). + */ + cm->msg_type = ((uint8_t) *ptr & 0x30) >> 4; + cm->flags |= MG_COAP_MSG_TYPE_FIELD; + + /* + * Token Length (TKL): 4-bit unsigned integer. Indicates the length of + * the variable-length Token field (0-8 bytes). Lengths 9-15 are + * reserved, MUST NOT be sent, and MUST be processed as a message + * format error. + */ + cm->token.len = *ptr & 0x0F; + if (cm->token.len > 8) { + cm->flags |= MG_COAP_FORMAT_ERROR; + return NULL; + } + + ptr++; + + /* + * Code: 8-bit unsigned integer, split into a 3-bit class (most + * significant bits) and a 5-bit detail (least significant bits) + */ + cm->code_class = (uint8_t) *ptr >> 5; + cm->code_detail = *ptr & 0x1F; + cm->flags |= (MG_COAP_CODE_CLASS_FIELD | MG_COAP_CODE_DETAIL_FIELD); + + ptr++; + + /* Message ID: 16-bit unsigned integer in network byte order. */ + cm->msg_id = (uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1); + cm->flags |= MG_COAP_MSG_ID_FIELD; + + ptr += 2; + + return ptr; +} + +/* + * Fills token information in mg_coap_message. + * + * Helper function. + */ +static char *coap_get_token(char *ptr, struct mbuf *io, + struct mg_coap_message *cm) { + if (cm->token.len != 0) { + if (ptr + cm->token.len > io->buf + io->len) { + cm->flags |= MG_COAP_NOT_ENOUGH_DATA; + return NULL; + } else { + cm->token.p = ptr; + ptr += cm->token.len; + cm->flags |= MG_COAP_TOKEN_FIELD; + } + } + + return ptr; +} + +/* + * Returns Option Delta or Length. + * + * Helper function. + */ +static int coap_get_ext_opt(char *ptr, struct mbuf *io, uint16_t *opt_info) { + int ret = 0; + + if (*opt_info == 13) { + /* + * 13: An 8-bit unsigned integer follows the initial byte and + * indicates the Option Delta/Length minus 13. + */ + if (ptr < io->buf + io->len) { + *opt_info = (uint8_t) *ptr + 13; + ret = sizeof(uint8_t); + } else { + ret = -1; /* LCOV_EXCL_LINE */ + } + } else if (*opt_info == 14) { + /* + * 14: A 16-bit unsigned integer in network byte order follows the + * initial byte and indicates the Option Delta/Length minus 269. + */ + if (ptr + sizeof(uint8_t) < io->buf + io->len) { + *opt_info = ((uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1)) + 269; + ret = sizeof(uint16_t); + } else { + ret = -1; /* LCOV_EXCL_LINE */ + } + } + + return ret; +} + +/* + * Fills options in mg_coap_message. + * + * Helper function. + * + * General options format: + * +---------------+---------------+ + * | Option Delta | Option Length | 1 byte + * +---------------+---------------+ + * \ Option Delta (extended) \ 0-2 bytes + * +-------------------------------+ + * / Option Length (extended) \ 0-2 bytes + * +-------------------------------+ + * \ Option Value \ 0 or more bytes + * +-------------------------------+ + */ +static char *coap_get_options(char *ptr, struct mbuf *io, + struct mg_coap_message *cm) { + uint16_t prev_opt = 0; + + if (ptr == io->buf + io->len) { + /* end of packet, ok */ + return NULL; + } + + /* 0xFF is payload marker */ + while (ptr < io->buf + io->len && (uint8_t) *ptr != 0xFF) { + uint16_t option_delta, option_lenght; + int optinfo_len; + + /* Option Delta: 4-bit unsigned integer */ + option_delta = ((uint8_t) *ptr & 0xF0) >> 4; + /* Option Length: 4-bit unsigned integer */ + option_lenght = *ptr & 0x0F; + + if (option_delta == 15 || option_lenght == 15) { + /* + * 15: Reserved for future use. If the field is set to this value, + * it MUST be processed as a message format error + */ + cm->flags |= MG_COAP_FORMAT_ERROR; + break; + } + + ptr++; + + /* check for extended option delta */ + optinfo_len = coap_get_ext_opt(ptr, io, &option_delta); + if (optinfo_len == -1) { + cm->flags |= MG_COAP_NOT_ENOUGH_DATA; /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + ptr += optinfo_len; + + /* check or extended option lenght */ + optinfo_len = coap_get_ext_opt(ptr, io, &option_lenght); + if (optinfo_len == -1) { + cm->flags |= MG_COAP_NOT_ENOUGH_DATA; /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + ptr += optinfo_len; + + /* + * Instead of specifying the Option Number directly, the instances MUST + * appear in order of their Option Numbers and a delta encoding is used + * between them. + */ + option_delta += prev_opt; + + mg_coap_add_option(cm, option_delta, ptr, option_lenght); + + prev_opt = option_delta; + + if (ptr + option_lenght > io->buf + io->len) { + cm->flags |= MG_COAP_NOT_ENOUGH_DATA; /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ + } + + ptr += option_lenght; + } + + if ((cm->flags & MG_COAP_ERROR) != 0) { + mg_coap_free_options(cm); + return NULL; + } + + cm->flags |= MG_COAP_OPTIOMG_FIELD; + + if (ptr == io->buf + io->len) { + /* end of packet, ok */ + return NULL; + } + + ptr++; + + return ptr; +} + +uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm) { + char *ptr; + + memset(cm, 0, sizeof(*cm)); + + if ((ptr = coap_parse_header(io->buf, io, cm)) == NULL) { + return cm->flags; + } + + if ((ptr = coap_get_token(ptr, io, cm)) == NULL) { + return cm->flags; + } + + if ((ptr = coap_get_options(ptr, io, cm)) == NULL) { + return cm->flags; + } + + /* the rest is payload */ + cm->payload.len = io->len - (ptr - io->buf); + if (cm->payload.len != 0) { + cm->payload.p = ptr; + cm->flags |= MG_COAP_PAYLOAD_FIELD; + } + + return cm->flags; +} + +/* + * Calculates extended size of given Opt Number/Length in coap message. + * + * Helper function. + */ +static size_t coap_get_ext_opt_size(uint32_t value) { + int ret = 0; + + if (value >= 13 && value <= 0xFF + 13) { + ret = sizeof(uint8_t); + } else if (value > 0xFF + 13 && value <= 0xFFFF + 269) { + ret = sizeof(uint16_t); + } + + return ret; +} + +/* + * Splits given Opt Number/Length into base and ext values. + * + * Helper function. + */ +static int coap_split_opt(uint32_t value, uint8_t *base, uint16_t *ext) { + int ret = 0; + + if (value < 13) { + *base = value; + } else if (value >= 13 && value <= 0xFF + 13) { + *base = 13; + *ext = value - 13; + ret = sizeof(uint8_t); + } else if (value > 0xFF + 13 && value <= 0xFFFF + 269) { + *base = 14; + *ext = value - 269; + ret = sizeof(uint16_t); + } + + return ret; +} + +/* + * Puts uint16_t (in network order) into given char stream. + * + * Helper function. + */ +static char *coap_add_uint16(char *ptr, uint16_t val) { + *ptr = val >> 8; + ptr++; + *ptr = val & 0x00FF; + ptr++; + return ptr; +} + +/* + * Puts extended value of Opt Number/Length into given char stream. + * + * Helper function. + */ +static char *coap_add_opt_info(char *ptr, uint16_t val, size_t len) { + if (len == sizeof(uint8_t)) { + *ptr = (char) val; + ptr++; + } else if (len == sizeof(uint16_t)) { + ptr = coap_add_uint16(ptr, val); + } + + return ptr; +} + +/* + * Verifies given mg_coap_message and calculates message size for it. + * + * Helper function. + */ +static uint32_t coap_calculate_packet_size(struct mg_coap_message *cm, + size_t *len) { + struct mg_coap_option *opt; + uint32_t prev_opt_number; + + *len = 4; /* header */ + if (cm->msg_type > MG_COAP_MSG_MAX) { + return MG_COAP_ERROR | MG_COAP_MSG_TYPE_FIELD; + } + if (cm->token.len > 8) { + return MG_COAP_ERROR | MG_COAP_TOKEN_FIELD; + } + if (cm->code_class > 7) { + return MG_COAP_ERROR | MG_COAP_CODE_CLASS_FIELD; + } + if (cm->code_detail > 31) { + return MG_COAP_ERROR | MG_COAP_CODE_DETAIL_FIELD; + } + + *len += cm->token.len; + if (cm->payload.len != 0) { + *len += cm->payload.len + 1; /* ... + 1; add payload marker */ + } + + opt = cm->options; + prev_opt_number = 0; + while (opt != NULL) { + *len += 1; /* basic delta/length */ + *len += coap_get_ext_opt_size(opt->number - prev_opt_number); + *len += coap_get_ext_opt_size((uint32_t) opt->value.len); + /* + * Current implementation performs check if + * option_number > previous option_number and produces an error + * TODO(alashkin): write design doc with limitations + * May be resorting is more suitable solution. + */ + if ((opt->next != NULL && opt->number > opt->next->number) || + opt->value.len > 0xFFFF + 269 || + opt->number - prev_opt_number > 0xFFFF + 269) { + return MG_COAP_ERROR | MG_COAP_OPTIOMG_FIELD; + } + *len += opt->value.len; + prev_opt_number = opt->number; + opt = opt->next; + } + + return 0; +} + +uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io) { + struct mg_coap_option *opt; + uint32_t res, prev_opt_number; + size_t prev_io_len, packet_size; + char *ptr; + + res = coap_calculate_packet_size(cm, &packet_size); + if (res != 0) { + return res; + } + + /* saving previous lenght to handle non-empty mbuf */ + prev_io_len = io->len; + mbuf_append(io, NULL, packet_size); + ptr = io->buf + prev_io_len; + + /* + * since cm is verified, it is possible to use bits shift operator + * without additional zeroing of unused bits + */ + + /* ver: 2 bits, msg_type: 2 bits, toklen: 4 bits */ + *ptr = (1 << 6) | (cm->msg_type << 4) | (uint8_t)(cm->token.len); + ptr++; + + /* code class: 3 bits, code detail: 5 bits */ + *ptr = (cm->code_class << 5) | (cm->code_detail); + ptr++; + + ptr = coap_add_uint16(ptr, cm->msg_id); + + if (cm->token.len != 0) { + memcpy(ptr, cm->token.p, cm->token.len); + ptr += cm->token.len; + } + + opt = cm->options; + prev_opt_number = 0; + while (opt != NULL) { + uint8_t delta_base = 0, length_base = 0; + uint16_t delta_ext = 0, length_ext = 0; + + size_t opt_delta_len = + coap_split_opt(opt->number - prev_opt_number, &delta_base, &delta_ext); + size_t opt_lenght_len = + coap_split_opt((uint32_t) opt->value.len, &length_base, &length_ext); + + *ptr = (delta_base << 4) | length_base; + ptr++; + + ptr = coap_add_opt_info(ptr, delta_ext, opt_delta_len); + ptr = coap_add_opt_info(ptr, length_ext, opt_lenght_len); + + if (opt->value.len != 0) { + memcpy(ptr, opt->value.p, opt->value.len); + ptr += opt->value.len; + } + + prev_opt_number = opt->number; + opt = opt->next; + } + + if (cm->payload.len != 0) { + *ptr = (char) -1; + ptr++; + memcpy(ptr, cm->payload.p, cm->payload.len); + } + + return 0; +} + +uint32_t mg_coap_send_message(struct mg_connection *nc, + struct mg_coap_message *cm) { + struct mbuf packet_out; + uint32_t compose_res; + + mbuf_init(&packet_out, 0); + compose_res = mg_coap_compose(cm, &packet_out); + if (compose_res != 0) { + return compose_res; /* LCOV_EXCL_LINE */ + } + + mg_send(nc, packet_out.buf, (int) packet_out.len); + mbuf_free(&packet_out); + + return 0; +} + +uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id) { + struct mg_coap_message cm; + memset(&cm, 0, sizeof(cm)); + cm.msg_type = MG_COAP_MSG_ACK; + cm.msg_id = msg_id; + + return mg_coap_send_message(nc, &cm); +} + +static void coap_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct mbuf *io = &nc->recv_mbuf; + struct mg_coap_message cm; + uint32_t parse_res; + + memset(&cm, 0, sizeof(cm)); + + nc->handler(nc, ev, ev_data); + + switch (ev) { + case MG_EV_RECV: + parse_res = mg_coap_parse(io, &cm); + if ((parse_res & MG_COAP_IGNORE) == 0) { + if ((cm.flags & MG_COAP_NOT_ENOUGH_DATA) != 0) { + /* + * Since we support UDP only + * MG_COAP_NOT_ENOUGH_DATA == MG_COAP_FORMAT_ERROR + */ + cm.flags |= MG_COAP_FORMAT_ERROR; /* LCOV_EXCL_LINE */ + } /* LCOV_EXCL_LINE */ + nc->handler(nc, MG_COAP_EVENT_BASE + cm.msg_type, &cm); + } + + mg_coap_free_options(&cm); + mbuf_remove(io, io->len); + break; + } +} +/* + * Attach built-in CoAP event handler to the given connection. + * + * The user-defined event handler will receive following extra events: + * + * - MG_EV_COAP_CON + * - MG_EV_COAP_NOC + * - MG_EV_COAP_ACK + * - MG_EV_COAP_RST + */ +int mg_set_protocol_coap(struct mg_connection *nc) { + /* supports UDP only */ + if ((nc->flags & MG_F_UDP) == 0) { + return -1; + } + + nc->proto_handler = coap_handler; + + return 0; +} + +#endif /* MG_ENABLE_COAP */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/tun.c" +#endif +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_TUN + +/* Amalgamated: #include "common/cs_dbg.h" */ +/* Amalgamated: #include "mongoose/src/http.h" */ +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/net.h" */ +/* Amalgamated: #include "mongoose/src/net_if_tun.h" */ +/* Amalgamated: #include "mongoose/src/tun.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +static void mg_tun_reconnect(struct mg_tun_client *client, int timeout); + +static void mg_tun_init_client(struct mg_tun_client *client, struct mg_mgr *mgr, + struct mg_iface *iface, const char *dispatcher, + struct mg_tun_ssl_opts ssl) { + client->mgr = mgr; + client->iface = iface; + client->disp_url = dispatcher; + client->last_stream_id = 0; + client->ssl = ssl; + + client->disp = NULL; /* will be set by mg_tun_reconnect */ + client->listener = NULL; /* will be set by mg_do_bind */ + client->reconnect = NULL; /* will be set by mg_tun_reconnect */ +} + +void mg_tun_log_frame(struct mg_tun_frame *frame) { + LOG(LL_DEBUG, ("Got TUN frame: type=0x%x, flags=0x%x stream_id=0x%lx, " + "len=%zu", + frame->type, frame->flags, frame->stream_id, frame->body.len)); +#if MG_ENABLE_HEXDUMP + { + char hex[512]; + mg_hexdump(frame->body.p, frame->body.len, hex, sizeof(hex) - 1); + hex[sizeof(hex) - 1] = '\0'; + LOG(LL_DEBUG, ("body:\n%s", hex)); + } +#else + LOG(LL_DEBUG, ("body: '%.*s'", (int) frame->body.len, frame->body.p)); +#endif +} + +static void mg_tun_close_all(struct mg_tun_client *client) { + struct mg_connection *nc; + for (nc = client->mgr->active_connections; nc != NULL; nc = nc->next) { + if (nc->iface == client->iface && !(nc->flags & MG_F_LISTENING)) { + LOG(LL_DEBUG, ("Closing tunneled connection %p", nc)); + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + /* mg_close_conn(nc); */ + } + } +} + +static void mg_tun_client_handler(struct mg_connection *nc, int ev, + void *ev_data) { + struct mg_tun_client *client = (struct mg_tun_client *) nc->user_data; + + switch (ev) { + case MG_EV_CONNECT: { + int err = *(int *) ev_data; + + if (err) { + LOG(LL_ERROR, ("Cannot connect to the tunnel dispatcher: %d", err)); + } else { + LOG(LL_INFO, ("Connected to the tunnel dispatcher")); + } + break; + } + case MG_EV_HTTP_REPLY: { + struct http_message *hm = (struct http_message *) ev_data; + + if (hm->resp_code != 200) { + LOG(LL_ERROR, + ("Tunnel dispatcher reply non-OK status code %d", hm->resp_code)); + } + break; + } + case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { + LOG(LL_INFO, ("Tunnel dispatcher handshake done")); + break; + } + case MG_EV_WEBSOCKET_FRAME: { + struct websocket_message *wm = (struct websocket_message *) ev_data; + struct mg_connection *tc; + struct mg_tun_frame frame; + + if (mg_tun_parse_frame(wm->data, wm->size, &frame) == -1) { + LOG(LL_ERROR, ("Got invalid tun frame dropping", wm->size)); + break; + } + + mg_tun_log_frame(&frame); + + tc = mg_tun_if_find_conn(client, frame.stream_id); + if (tc == NULL) { + if (frame.body.len > 0) { + LOG(LL_DEBUG, ("Got frame after receiving end has been closed")); + } + break; + } + if (frame.body.len > 0) { + mg_if_recv_tcp_cb(tc, (void *) frame.body.p, frame.body.len, + 0 /* own */); + } + if (frame.flags & MG_TUN_F_END_STREAM) { + LOG(LL_DEBUG, ("Closing tunneled connection because got end of stream " + "from other end")); + tc->flags |= MG_F_CLOSE_IMMEDIATELY; + mg_close_conn(tc); + } + break; + } + case MG_EV_CLOSE: { + LOG(LL_DEBUG, ("Closing all tunneled connections")); + /* + * The client might have been already freed when the listening socket is + * closed. + */ + if (client != NULL) { + mg_tun_close_all(client); + client->disp = NULL; + LOG(LL_INFO, ("Dispatcher connection is no more, reconnecting")); + /* TODO(mkm): implement exp back off */ + mg_tun_reconnect(client, MG_TUN_RECONNECT_INTERVAL); + } + break; + } + default: + break; + } +} + +static void mg_tun_do_reconnect(struct mg_tun_client *client) { + struct mg_connection *dc; + struct mg_connect_opts opts; + memset(&opts, 0, sizeof(opts)); +#if MG_ENABLE_SSL + opts.ssl_cert = client->ssl.ssl_cert; + opts.ssl_key = client->ssl.ssl_key; + opts.ssl_ca_cert = client->ssl.ssl_ca_cert; +#endif + /* HTTP/Websocket listener */ + if ((dc = mg_connect_ws_opt(client->mgr, mg_tun_client_handler, opts, + client->disp_url, MG_TUN_PROTO_NAME, NULL)) == + NULL) { + LOG(LL_ERROR, + ("Cannot connect to WS server on addr [%s]\n", client->disp_url)); + return; + } + + client->disp = dc; + dc->user_data = client; +} + +void mg_tun_reconnect_ev_handler(struct mg_connection *nc, int ev, + void *ev_data) { + struct mg_tun_client *client = (struct mg_tun_client *) nc->user_data; + (void) ev_data; + + switch (ev) { + case MG_EV_TIMER: + if (!(client->listener->flags & MG_F_TUN_DO_NOT_RECONNECT)) { + mg_tun_do_reconnect(client); + } else { + /* Reconnecting is suppressed, we'll check again at the next poll */ + mg_tun_reconnect(client, 0); + } + break; + } +} + +static void mg_tun_reconnect(struct mg_tun_client *client, int timeout) { + if (client->reconnect == NULL) { + client->reconnect = + mg_add_sock(client->mgr, INVALID_SOCKET, mg_tun_reconnect_ev_handler); + client->reconnect->user_data = client; + } + client->reconnect->ev_timer_time = mg_time() + timeout; +} + +static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr, + const char *dispatcher, + struct mg_tun_ssl_opts ssl) { + struct mg_tun_client *client = NULL; + struct mg_iface *iface = mg_find_iface(mgr, &mg_tun_iface_vtable, NULL); + if (iface == NULL) { + LOG(LL_ERROR, ("The tun feature requires the manager to have a tun " + "interface enabled")); + return NULL; + } + + client = (struct mg_tun_client *) MG_MALLOC(sizeof(*client)); + mg_tun_init_client(client, mgr, iface, dispatcher, ssl); + iface->data = client; + + /* + * We need to give application a chance to set MG_F_TUN_DO_NOT_RECONNECT on a + * listening connection right after mg_tun_bind_opt() returned it, so we + * should use mg_tun_reconnect() here, instead of mg_tun_do_reconnect() + */ + mg_tun_reconnect(client, 0); + return client; +} + +void mg_tun_destroy_client(struct mg_tun_client *client) { + /* + * NOTE: + * `client` is NULL in case of OOM + * `client->disp` is NULL if connection failed + * `client->iface is NULL is `mg_find_iface` failed + */ + + if (client != NULL && client->disp != NULL) { + /* the dispatcher connection handler will in turn close all tunnels */ + client->disp->flags |= MG_F_CLOSE_IMMEDIATELY; + /* this is used as a signal to other tun handlers that the party is over */ + client->disp->user_data = NULL; + } + + if (client != NULL && client->reconnect != NULL) { + client->reconnect->flags |= MG_F_CLOSE_IMMEDIATELY; + } + + if (client != NULL && client->iface != NULL) { + client->iface->data = NULL; + } + + MG_FREE(client); +} + +static struct mg_connection *mg_tun_do_bind(struct mg_tun_client *client, + mg_event_handler_t handler, + struct mg_bind_opts opts) { + struct mg_connection *lc; + opts.iface = client->iface; + lc = mg_bind_opt(client->mgr, ":1234" /* dummy port */, handler, opts); + client->listener = lc; + return lc; +} + +struct mg_connection *mg_tun_bind_opt(struct mg_mgr *mgr, + const char *dispatcher, + mg_event_handler_t handler, + struct mg_bind_opts opts) { +#if MG_ENABLE_SSL + struct mg_tun_ssl_opts ssl = {opts.ssl_cert, opts.ssl_key, opts.ssl_ca_cert}; +#else + struct mg_tun_ssl_opts ssl = {0}; +#endif + struct mg_tun_client *client = mg_tun_create_client(mgr, dispatcher, ssl); + if (client == NULL) { + return NULL; + } +#if MG_ENABLE_SSL + /* these options don't make sense in the local mouth of the tunnel */ + opts.ssl_cert = NULL; + opts.ssl_key = NULL; + opts.ssl_ca_cert = NULL; +#endif + return mg_tun_do_bind(client, handler, opts); +} + +int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame) { + const size_t header_size = sizeof(uint32_t) + sizeof(uint8_t) * 2; + if (len < header_size) { + return -1; + } + + frame->type = *(uint8_t *) (data); + frame->flags = *(uint8_t *) ((char *) data + 1); + memcpy(&frame->stream_id, (char *) data + 2, sizeof(uint32_t)); + frame->stream_id = ntohl(frame->stream_id); + frame->body.p = (char *) data + header_size; + frame->body.len = len - header_size; + return 0; +} + +void mg_tun_send_frame(struct mg_connection *ws, uint32_t stream_id, + uint8_t type, uint8_t flags, struct mg_str msg) { + stream_id = htonl(stream_id); + { + struct mg_str parts[] = { + {(char *) &type, sizeof(type)}, + {(char *) &flags, sizeof(flags)}, + {(char *) &stream_id, sizeof(stream_id)}, + {msg.p, msg.len} /* vc6 doesn't like just `msg` here */}; + mg_send_websocket_framev(ws, WEBSOCKET_OP_BINARY, parts, + sizeof(parts) / sizeof(parts[0])); + } +} + +#endif /* MG_ENABLE_TUN */ +#ifdef MG_MODULE_LINES +#line 1 "mongoose/src/sntp.c" +#endif +/* + * Copyright (c) 2016 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/sntp.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +#if MG_ENABLE_SNTP + +#define SNTP_TIME_OFFSET 2208988800 + +#ifndef SNTP_TIMEOUT +#define SNTP_TIMEOUT 10 +#endif + +#ifndef SNTP_ATTEMPTS +#define SNTP_ATTEMPTS 3 +#endif + +static uint64_t mg_get_sec(uint64_t val) { + return (val & 0xFFFFFFFF00000000) >> 32; +} + +static uint64_t mg_get_usec(uint64_t val) { + uint64_t tmp = (val & 0x00000000FFFFFFFF); + tmp *= 1000000; + tmp >>= 32; + return tmp; +} + +static void mg_ntp_to_tv(uint64_t val, struct timeval *tv) { + uint64_t tmp; + tmp = mg_get_sec(val); + tmp -= SNTP_TIME_OFFSET; + tv->tv_sec = tmp; + tv->tv_usec = mg_get_usec(val); +} + +static void mg_get_ntp_ts(const char *ntp, uint64_t *val) { + uint32_t tmp; + memcpy(&tmp, ntp, sizeof(tmp)); + tmp = ntohl(tmp); + *val = (uint64_t) tmp << 32; + memcpy(&tmp, ntp + 4, sizeof(tmp)); + tmp = ntohl(tmp); + *val |= tmp; +} + +void mg_sntp_send_request(struct mg_connection *c) { + char buf[48] = {0}; + /* + * header - 8 bit: + * LI (2 bit) - 3 (not in sync), VN (3 bit) - 4 (version), + * mode (3 bit) - 3 (client) + */ + buf[0] = (3 << 6) | (4 << 3) | 3; + +/* + * Next fields should be empty in client request + * stratum, 8 bit + * poll interval, 8 bit + * rrecision, 8 bit + * root delay, 32 bit + * root dispersion, 32 bit + * ref id, 32 bit + * ref timestamp, 64 bit + * originate Timestamp, 64 bit + * receive Timestamp, 64 bit +*/ + +/* + * convert time to sntp format (sntp starts from 00:00:00 01.01.1900) + * according to rfc868 it is 2208988800L sec + * this information is used to correct roundtrip delay + * but if local clock is absolutely broken (and doesn't work even + * as simple timer), it is better to disable it +*/ +#ifndef MG_SNMP_NO_DELAY_CORRECTION + uint32_t sec; + sec = htonl(mg_time() + SNTP_TIME_OFFSET); + memcpy(&buf[40], &sec, sizeof(sec)); +#endif + + mg_send(c, buf, sizeof(buf)); +} + +#ifndef MG_SNMP_NO_DELAY_CORRECTION +static uint64_t mg_calculate_delay(uint64_t t1, uint64_t t2, uint64_t t3) { + /* roundloop delay = (T4 - T1) - (T3 - T2) */ + uint64_t d1 = ((mg_time() + SNTP_TIME_OFFSET) * 1000000) - + (mg_get_sec(t1) * 1000000 + mg_get_usec(t1)); + uint64_t d2 = (mg_get_sec(t3) * 1000000 + mg_get_usec(t3)) - + (mg_get_sec(t2) * 1000000 + mg_get_usec(t2)); + + return (d1 > d2) ? d1 - d2 : 0; +} +#endif + +MG_INTERNAL int mg_sntp_parse_reply(const char *buf, int len, + struct mg_sntp_message *msg) { + uint8_t hdr; + uint64_t orig_ts_T1, recv_ts_T2, trsm_ts_T3, delay = 0; + int mode; + struct timeval tv; + + (void) orig_ts_T1; + (void) recv_ts_T2; + if (len < 48) { + return -1; + } + + hdr = buf[0]; + + if ((hdr & 0x38) >> 3 != 4) { + /* Wrong version */ + return -1; + } + + mode = hdr & 0x7; + if (mode != 4 && mode != 5) { + /* Not a server reply */ + return -1; + } + + memset(msg, 0, sizeof(*msg)); + + msg->kiss_of_death = (buf[1] == 0); /* Server asks to not send requests */ + + mg_get_ntp_ts(&buf[40], &trsm_ts_T3); + +#ifndef MG_SNMP_NO_DELAY_CORRECTION + mg_get_ntp_ts(&buf[24], &orig_ts_T1); + mg_get_ntp_ts(&buf[32], &recv_ts_T2); + delay = mg_calculate_delay(orig_ts_T1, recv_ts_T2, trsm_ts_T3); +#endif + + mg_ntp_to_tv(trsm_ts_T3, &tv); + + msg->time = (double) tv.tv_sec + (((double) tv.tv_usec + delay) / 1000000.0); + + return 0; +} + +static void mg_sntp_handler(struct mg_connection *c, int ev, void *ev_data) { + struct mbuf *io = &c->recv_mbuf; + struct mg_sntp_message msg; + + c->handler(c, ev, ev_data); + + switch (ev) { + case MG_EV_RECV: { + if (mg_sntp_parse_reply(io->buf, io->len, &msg) < 0) { + DBG(("Invalid SNTP packet received (%d)", (int) io->len)); + c->handler(c, MG_SNTP_MALFORMED_REPLY, NULL); + } else { + c->handler(c, MG_SNTP_REPLY, (void *) &msg); + } + + mbuf_remove(io, io->len); + break; + } + } +} + +int mg_set_protocol_sntp(struct mg_connection *c) { + if ((c->flags & MG_F_UDP) == 0) { + return -1; + } + + c->proto_handler = mg_sntp_handler; + + return 0; +} + +struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, + mg_event_handler_t event_handler, + const char *sntp_server_name) { + struct mg_connection *c = NULL; + char url[100], *p_url = url; + const char *proto = "", *port = "", *tmp; + + /* If port is not specified, use default (123) */ + tmp = strchr(sntp_server_name, ':'); + if (tmp != NULL && *(tmp + 1) == '/') { + tmp = strchr(tmp + 1, ':'); + } + + if (tmp == NULL) { + port = ":123"; + } + + /* Add udp:// if needed */ + if (strncmp(sntp_server_name, "udp://", 6) != 0) { + proto = "udp://"; + } + + mg_asprintf(&p_url, sizeof(url), "%s%s%s", proto, sntp_server_name, port); + + c = mg_connect(mgr, p_url, event_handler); + + if (c == NULL) { + goto cleanup; + } + + mg_set_protocol_sntp(c); + +cleanup: + if (p_url != url) { + MG_FREE(p_url); + } + + return c; +} + +struct sntp_data { + mg_event_handler_t hander; + int count; +}; + +static void mg_sntp_util_ev_handler(struct mg_connection *c, int ev, + void *ev_data) { + struct sntp_data *sd = (struct sntp_data *) c->user_data; + + switch (ev) { + case MG_EV_CONNECT: + if (*(int *) ev_data != 0) { + mg_call(c, sd->hander, MG_SNTP_FAILED, NULL); + break; + } + /* fallthrough */ + case MG_EV_TIMER: + if (sd->count <= SNTP_ATTEMPTS) { + mg_sntp_send_request(c); + mg_set_timer(c, mg_time() + 10); + sd->count++; + } else { + mg_call(c, sd->hander, MG_SNTP_FAILED, NULL); + c->flags |= MG_F_CLOSE_IMMEDIATELY; + } + break; + case MG_SNTP_MALFORMED_REPLY: + mg_call(c, sd->hander, MG_SNTP_FAILED, NULL); + c->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + case MG_SNTP_REPLY: + mg_call(c, sd->hander, MG_SNTP_REPLY, ev_data); + c->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + case MG_EV_CLOSE: + MG_FREE(c->user_data); + c->user_data = NULL; + break; + } +} + +struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr, + mg_event_handler_t event_handler, + const char *sntp_server_name) { + struct mg_connection *c; + struct sntp_data *sd = (struct sntp_data *) MG_CALLOC(1, sizeof(*sd)); + if (sd == NULL) { + return NULL; + } + + c = mg_sntp_connect(mgr, mg_sntp_util_ev_handler, sntp_server_name); + if (c == NULL) { + MG_FREE(sd); + return NULL; + } + + sd->hander = event_handler; + c->user_data = sd; + + return c; +} + +#endif /* MG_ENABLE_SNTP */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/cc3200/cc3200_libc.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if CS_PLATFORM == CS_P_CC3200 + +#include +#include + +#ifndef __TI_COMPILER_VERSION__ +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define CONSOLE_UART UARTA0_BASE + +#ifdef __TI_COMPILER_VERSION__ +int asprintf(char **strp, const char *fmt, ...) { + va_list ap; + int len; + + *strp = malloc(BUFSIZ); + if (*strp == NULL) return -1; + + va_start(ap, fmt); + len = vsnprintf(*strp, BUFSIZ, fmt, ap); + va_end(ap); + + if (len > 0) { + *strp = realloc(*strp, len + 1); + if (*strp == NULL) return -1; + } + + if (len >= BUFSIZ) { + va_start(ap, fmt); + len = vsnprintf(*strp, len + 1, fmt, ap); + va_end(ap); + } + + return len; +} + +#if MG_TI_NO_HOST_INTERFACE +time_t HOSTtime() { + struct timeval tp; + gettimeofday(&tp, NULL); + return tp.tv_sec; +} +#endif + +#endif /* __TI_COMPILER_VERSION__ */ + +#ifndef __TI_COMPILER_VERSION__ +int _gettimeofday_r(struct _reent *r, struct timeval *tp, void *tzp) { +#else +int gettimeofday(struct timeval *tp, void *tzp) { +#endif + unsigned long long r1 = 0, r2; + /* Achieve two consecutive reads of the same value. */ + do { + r2 = r1; + r1 = PRCMSlowClkCtrFastGet(); + } while (r1 != r2); + /* This is a 32768 Hz counter. */ + tp->tv_sec = (r1 >> 15); + /* 1/32768-th of a second is 30.517578125 microseconds, approx. 31, + * but we round down so it doesn't overflow at 32767 */ + tp->tv_usec = (r1 & 0x7FFF) * 30; + return 0; +} + +void fprint_str(FILE *fp, const char *str) { + while (*str != '\0') { + if (*str == '\n') MAP_UARTCharPut(CONSOLE_UART, '\r'); + MAP_UARTCharPut(CONSOLE_UART, *str++); + } +} + +void _exit(int status) { + fprint_str(stderr, "_exit\n"); + /* cause an unaligned access exception, that will drop you into gdb */ + *(int *) 1 = status; + while (1) + ; /* avoid gcc warning because stdlib abort() has noreturn attribute */ +} + +void _not_implemented(const char *what) { + fprint_str(stderr, what); + fprint_str(stderr, " is not implemented\n"); + _exit(42); +} + +int _kill(int pid, int sig) { + (void) pid; + (void) sig; + _not_implemented("_kill"); + return -1; +} + +int _getpid() { + fprint_str(stderr, "_getpid is not implemented\n"); + return 42; +} + +int _isatty(int fd) { + /* 0, 1 and 2 are TTYs. */ + return fd < 2; +} + +#endif /* CS_PLATFORM == CS_P_CC3200 */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/msp432/msp432_libc.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if CS_PLATFORM == CS_P_MSP432 + +#include +#include + +int gettimeofday(struct timeval *tp, void *tzp) { + uint32_t ticks = Clock_getTicks(); + tp->tv_sec = ticks / 1000; + tp->tv_usec = (ticks % 1000) * 1000; + return 0; +} + +#endif /* CS_PLATFORM == CS_P_MSP432 */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/nrf5/nrf5_libc.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if (CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52) && \ + defined(__ARMCC_VERSION) +int gettimeofday(struct timeval *tp, void *tzp) { + /* TODO */ + tp->tv_sec = 0; + tp->tv_usec = 0; + return 0; +} +#endif +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_fs_slfs.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_ +#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_ + +#if defined(MG_FS_SLFS) + +#include +#ifndef __TI_COMPILER_VERSION__ +#include +#include +#endif + +#define MAX_OPEN_SLFS_FILES 8 + +/* Indirect libc interface - same functions, different names. */ +int fs_slfs_open(const char *pathname, int flags, mode_t mode); +int fs_slfs_close(int fd); +ssize_t fs_slfs_read(int fd, void *buf, size_t count); +ssize_t fs_slfs_write(int fd, const void *buf, size_t count); +int fs_slfs_stat(const char *pathname, struct stat *s); +int fs_slfs_fstat(int fd, struct stat *s); +off_t fs_slfs_lseek(int fd, off_t offset, int whence); +int fs_slfs_unlink(const char *filename); +int fs_slfs_rename(const char *from, const char *to); + +void fs_slfs_set_new_file_size(const char *name, size_t size); + +#endif /* defined(MG_FS_SLFS) */ + +#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_fs_slfs.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +/* Standard libc interface to TI SimpleLink FS. */ + +#if defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS) + +/* Amalgamated: #include "common/platforms/simplelink/sl_fs_slfs.h" */ + +#include + +#if CS_PLATFORM == CS_P_CC3200 +#include +#endif +#include +#include + +/* Amalgamated: #include "common/cs_dbg.h" */ + +/* From sl_fs.c */ +extern int set_errno(int e); +static const char *drop_dir(const char *fname, bool *is_slfs); + +/* + * With SLFS, you have to pre-declare max file size. Yes. Really. + * 64K should be enough for everyone. Right? + */ +#ifndef FS_SLFS_MAX_FILE_SIZE +#define FS_SLFS_MAX_FILE_SIZE (64 * 1024) +#endif + +struct sl_file_size_hint { + char *name; + size_t size; +}; + +struct sl_fd_info { + _i32 fh; + _off_t pos; + size_t size; +}; + +static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES]; +static struct sl_file_size_hint s_sl_file_size_hints[MAX_OPEN_SLFS_FILES]; + +static int sl_fs_to_errno(_i32 r) { + DBG(("SL error: %d", (int) r)); + switch (r) { + case SL_FS_OK: + return 0; + case SL_FS_FILE_NAME_EXIST: + return EEXIST; + case SL_FS_WRONG_FILE_NAME: + return EINVAL; + case SL_FS_ERR_NO_AVAILABLE_NV_INDEX: + case SL_FS_ERR_NO_AVAILABLE_BLOCKS: + return ENOSPC; + case SL_FS_ERR_FAILED_TO_ALLOCATE_MEM: + return ENOMEM; + case SL_FS_ERR_FILE_NOT_EXISTS: + return ENOENT; + case SL_FS_ERR_NOT_SUPPORTED: + return ENOTSUP; + } + return ENXIO; +} + +int fs_slfs_open(const char *pathname, int flags, mode_t mode) { + int fd; + for (fd = 0; fd < MAX_OPEN_SLFS_FILES; fd++) { + if (s_sl_fds[fd].fh <= 0) break; + } + if (fd >= MAX_OPEN_SLFS_FILES) return set_errno(ENOMEM); + struct sl_fd_info *fi = &s_sl_fds[fd]; + + /* + * Apply path manipulations again, in case we got here directly + * (via TI libc's "add_device"). + */ + pathname = drop_dir(pathname, NULL); + + _u32 am = 0; + fi->size = (size_t) -1; + int rw = (flags & 3); + if (rw == O_RDONLY) { + SlFsFileInfo_t sl_fi; + _i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi); + if (r == SL_FS_OK) { + fi->size = sl_fi.FileLen; + } + am = FS_MODE_OPEN_READ; + } else { + if (!(flags & O_TRUNC) || (flags & O_APPEND)) { + // FailFS files cannot be opened for append and will be truncated + // when opened for write. + return set_errno(ENOTSUP); + } + if (flags & O_CREAT) { + size_t i, size = FS_SLFS_MAX_FILE_SIZE; + for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) { + if (s_sl_file_size_hints[i].name != NULL && + strcmp(s_sl_file_size_hints[i].name, pathname) == 0) { + size = s_sl_file_size_hints[i].size; + free(s_sl_file_size_hints[i].name); + s_sl_file_size_hints[i].name = NULL; + break; + } + } + DBG(("creating %s with max size %d", pathname, (int) size)); + am = FS_MODE_OPEN_CREATE(size, 0); + } else { + am = FS_MODE_OPEN_WRITE; + } + } + _i32 r = sl_FsOpen((_u8 *) pathname, am, NULL, &fi->fh); + DBG(("sl_FsOpen(%s, 0x%x) = %d, %d", pathname, (int) am, (int) r, + (int) fi->fh)); + if (r == SL_FS_OK) { + fi->pos = 0; + r = fd; + } else { + fi->fh = -1; + r = set_errno(sl_fs_to_errno(r)); + } + return r; +} + +int fs_slfs_close(int fd) { + struct sl_fd_info *fi = &s_sl_fds[fd]; + if (fi->fh <= 0) return set_errno(EBADF); + _i32 r = sl_FsClose(fi->fh, NULL, NULL, 0); + DBG(("sl_FsClose(%d) = %d", (int) fi->fh, (int) r)); + s_sl_fds[fd].fh = -1; + return set_errno(sl_fs_to_errno(r)); +} + +ssize_t fs_slfs_read(int fd, void *buf, size_t count) { + struct sl_fd_info *fi = &s_sl_fds[fd]; + if (fi->fh <= 0) return set_errno(EBADF); + /* Simulate EOF. sl_FsRead @ file_size return SL_FS_ERR_OFFSET_OUT_OF_RANGE. + */ + if (fi->pos == fi->size) return 0; + _i32 r = sl_FsRead(fi->fh, fi->pos, buf, count); + DBG(("sl_FsRead(%d, %d, %d) = %d", (int) fi->fh, (int) fi->pos, (int) count, + (int) r)); + if (r >= 0) { + fi->pos += r; + return r; + } + return set_errno(sl_fs_to_errno(r)); +} + +ssize_t fs_slfs_write(int fd, const void *buf, size_t count) { + struct sl_fd_info *fi = &s_sl_fds[fd]; + if (fi->fh <= 0) return set_errno(EBADF); + _i32 r = sl_FsWrite(fi->fh, fi->pos, (_u8 *) buf, count); + DBG(("sl_FsWrite(%d, %d, %d) = %d", (int) fi->fh, (int) fi->pos, (int) count, + (int) r)); + if (r >= 0) { + fi->pos += r; + return r; + } + return set_errno(sl_fs_to_errno(r)); +} + +int fs_slfs_stat(const char *pathname, struct stat *s) { + SlFsFileInfo_t sl_fi; + /* + * Apply path manipulations again, in case we got here directly + * (via TI libc's "add_device"). + */ + pathname = drop_dir(pathname, NULL); + _i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi); + if (r == SL_FS_OK) { + s->st_mode = S_IFREG | 0666; + s->st_nlink = 1; + s->st_size = sl_fi.FileLen; + return 0; + } + return set_errno(sl_fs_to_errno(r)); +} + +int fs_slfs_fstat(int fd, struct stat *s) { + struct sl_fd_info *fi = &s_sl_fds[fd]; + if (fi->fh <= 0) return set_errno(EBADF); + s->st_mode = 0666; + s->st_mode = S_IFREG | 0666; + s->st_nlink = 1; + s->st_size = fi->size; + return 0; +} + +off_t fs_slfs_lseek(int fd, off_t offset, int whence) { + if (s_sl_fds[fd].fh <= 0) return set_errno(EBADF); + switch (whence) { + case SEEK_SET: + s_sl_fds[fd].pos = offset; + break; + case SEEK_CUR: + s_sl_fds[fd].pos += offset; + break; + case SEEK_END: + return set_errno(ENOTSUP); + } + return 0; +} + +int fs_slfs_unlink(const char *pathname) { + /* + * Apply path manipulations again, in case we got here directly + * (via TI libc's "add_device"). + */ + pathname = drop_dir(pathname, NULL); + return set_errno(sl_fs_to_errno(sl_FsDel((const _u8 *) pathname, 0))); +} + +int fs_slfs_rename(const char *from, const char *to) { + return set_errno(ENOTSUP); +} + +void fs_slfs_set_new_file_size(const char *name, size_t size) { + int i; + for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) { + if (s_sl_file_size_hints[i].name == NULL) { + DBG(("File size hint: %s %d", name, (int) size)); + s_sl_file_size_hints[i].name = strdup(name); + s_sl_file_size_hints[i].size = size; + break; + } + } +} + +#endif /* defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS) */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_fs.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_NET_IF == MG_NET_IF_SIMPLELINK && \ + (defined(MG_FS_SLFS) || defined(MG_FS_SPIFFS)) + +#include +#include +#include +#include +#include +#ifdef __TI_COMPILER_VERSION__ +#include +#endif + +/* Amalgamated: #include "common/cs_dbg.h" */ +/* Amalgamated: #include "common/platform.h" */ + +#ifdef CC3200_FS_SPIFFS +/* Amalgamated: #include "cc3200_fs_spiffs.h" */ +#endif + +#ifdef MG_FS_SLFS +/* Amalgamated: #include "sl_fs_slfs.h" */ +#endif + +#define NUM_SYS_FDS 3 +#define SPIFFS_FD_BASE 10 +#define SLFS_FD_BASE 100 + +#ifndef MG_UART_CHAR_PUT +#if CS_PLATFORM == CS_P_CC3200 +#include +#include +#include +#include +#include +#define MG_UART_CHAR_PUT(fd, c) MAP_UARTCharPut(UARTA0_BASE, c); +#else +#define MG_UART_CHAR_PUT(fd, c) +#endif /* CS_PLATFORM == CS_P_CC3200 */ +#endif /* !MG_UART_CHAR_PUT */ + +int set_errno(int e) { + errno = e; + return (e == 0 ? 0 : -1); +} + +static const char *drop_dir(const char *fname, bool *is_slfs) { + if (is_slfs != NULL) { + *is_slfs = (strncmp(fname, "SL:", 3) == 0); + if (*is_slfs) fname += 3; + } + /* Drop "./", if any */ + if (fname[0] == '.' && fname[1] == '/') { + fname += 2; + } + /* + * Drop / if it is the only one in the path. + * This allows use of /pretend/directories but serves /file.txt as normal. + */ + if (fname[0] == '/' && strchr(fname + 1, '/') == NULL) { + fname++; + } + return fname; +} + +enum fd_type { + FD_INVALID, + FD_SYS, +#ifdef CC3200_FS_SPIFFS + FD_SPIFFS, +#endif +#ifdef MG_FS_SLFS + FD_SLFS +#endif +}; +static int fd_type(int fd) { + if (fd >= 0 && fd < NUM_SYS_FDS) return FD_SYS; +#ifdef CC3200_FS_SPIFFS + if (fd >= SPIFFS_FD_BASE && fd < SPIFFS_FD_BASE + MAX_OPEN_SPIFFS_FILES) { + return FD_SPIFFS; + } +#endif +#ifdef MG_FS_SLFS + if (fd >= SLFS_FD_BASE && fd < SLFS_FD_BASE + MAX_OPEN_SLFS_FILES) { + return FD_SLFS; + } +#endif + return FD_INVALID; +} + +#if MG_TI_NO_HOST_INTERFACE +int open(const char *pathname, unsigned flags, int mode) { +#else +int _open(const char *pathname, int flags, mode_t mode) { +#endif + int fd = -1; + bool is_sl; + const char *fname = drop_dir(pathname, &is_sl); + if (is_sl) { +#ifdef MG_FS_SLFS + fd = fs_slfs_open(fname, flags, mode); + if (fd >= 0) fd += SLFS_FD_BASE; +#endif + } else { +#ifdef CC3200_FS_SPIFFS + fd = fs_spiffs_open(fname, flags, mode); + if (fd >= 0) fd += SPIFFS_FD_BASE; +#endif + } + LOG(LL_DEBUG, + ("open(%s, 0x%x) = %d, fname = %s", pathname, flags, fd, fname)); + return fd; +} + +int _stat(const char *pathname, struct stat *st) { + int res = -1; + bool is_sl; + const char *fname = drop_dir(pathname, &is_sl); + memset(st, 0, sizeof(*st)); + /* Simulate statting the root directory. */ + if (fname[0] == '\0' || strcmp(fname, ".") == 0) { + st->st_ino = 0; + st->st_mode = S_IFDIR | 0777; + st->st_nlink = 1; + st->st_size = 0; + return 0; + } + if (is_sl) { +#ifdef MG_FS_SLFS + res = fs_slfs_stat(fname, st); +#endif + } else { +#ifdef CC3200_FS_SPIFFS + res = fs_spiffs_stat(fname, st); +#endif + } + LOG(LL_DEBUG, ("stat(%s) = %d; fname = %s", pathname, res, fname)); + return res; +} + +#if MG_TI_NO_HOST_INTERFACE +int close(int fd) { +#else +int _close(int fd) { +#endif + int r = -1; + switch (fd_type(fd)) { + case FD_INVALID: + r = set_errno(EBADF); + break; + case FD_SYS: + r = set_errno(EACCES); + break; +#ifdef CC3200_FS_SPIFFS + case FD_SPIFFS: + r = fs_spiffs_close(fd - SPIFFS_FD_BASE); + break; +#endif +#ifdef MG_FS_SLFS + case FD_SLFS: + r = fs_slfs_close(fd - SLFS_FD_BASE); + break; +#endif + } + DBG(("close(%d) = %d", fd, r)); + return r; +} + +#if MG_TI_NO_HOST_INTERFACE +off_t lseek(int fd, off_t offset, int whence) { +#else +off_t _lseek(int fd, off_t offset, int whence) { +#endif + int r = -1; + switch (fd_type(fd)) { + case FD_INVALID: + r = set_errno(EBADF); + break; + case FD_SYS: + r = set_errno(ESPIPE); + break; +#ifdef CC3200_FS_SPIFFS + case FD_SPIFFS: + r = fs_spiffs_lseek(fd - SPIFFS_FD_BASE, offset, whence); + break; +#endif +#ifdef MG_FS_SLFS + case FD_SLFS: + r = fs_slfs_lseek(fd - SLFS_FD_BASE, offset, whence); + break; +#endif + } + DBG(("lseek(%d, %d, %d) = %d", fd, (int) offset, whence, r)); + return r; +} + +int _fstat(int fd, struct stat *s) { + int r = -1; + memset(s, 0, sizeof(*s)); + switch (fd_type(fd)) { + case FD_INVALID: + r = set_errno(EBADF); + break; + case FD_SYS: { + /* Create barely passable stats for STD{IN,OUT,ERR}. */ + memset(s, 0, sizeof(*s)); + s->st_ino = fd; + s->st_mode = S_IFCHR | 0666; + r = 0; + break; + } +#ifdef CC3200_FS_SPIFFS + case FD_SPIFFS: + r = fs_spiffs_fstat(fd - SPIFFS_FD_BASE, s); + break; +#endif +#ifdef MG_FS_SLFS + case FD_SLFS: + r = fs_slfs_fstat(fd - SLFS_FD_BASE, s); + break; +#endif + } + DBG(("fstat(%d) = %d", fd, r)); + return r; +} + +#if MG_TI_NO_HOST_INTERFACE +int read(int fd, char *buf, unsigned count) { +#else +ssize_t _read(int fd, void *buf, size_t count) { +#endif + int r = -1; + switch (fd_type(fd)) { + case FD_INVALID: + r = set_errno(EBADF); + break; + case FD_SYS: { + if (fd != 0) { + r = set_errno(EACCES); + break; + } + /* Should we allow reading from stdin = uart? */ + r = set_errno(ENOTSUP); + break; + } +#ifdef CC3200_FS_SPIFFS + case FD_SPIFFS: + r = fs_spiffs_read(fd - SPIFFS_FD_BASE, buf, count); + break; +#endif +#ifdef MG_FS_SLFS + case FD_SLFS: + r = fs_slfs_read(fd - SLFS_FD_BASE, buf, count); + break; +#endif + } + DBG(("read(%d, %u) = %d", fd, count, r)); + return r; +} + +#if MG_TI_NO_HOST_INTERFACE +int write(int fd, const char *buf, unsigned count) { +#else +ssize_t _write(int fd, const void *buf, size_t count) { +#endif + int r = -1; + size_t i = 0; + switch (fd_type(fd)) { + case FD_INVALID: + r = set_errno(EBADF); + break; + case FD_SYS: { + if (fd == 0) { + r = set_errno(EACCES); + break; + } + for (i = 0; i < count; i++) { + const char c = ((const char *) buf)[i]; + if (c == '\n') MG_UART_CHAR_PUT(fd, '\r'); + MG_UART_CHAR_PUT(fd, c); + } + r = count; + break; + } +#ifdef CC3200_FS_SPIFFS + case FD_SPIFFS: + r = fs_spiffs_write(fd - SPIFFS_FD_BASE, buf, count); + break; +#endif +#ifdef MG_FS_SLFS + case FD_SLFS: + r = fs_slfs_write(fd - SLFS_FD_BASE, buf, count); + break; +#endif + } + return r; +} + +/* + * On Newlib we override rename directly too, because the default + * implementation using _link and _unlink doesn't work for us. + */ +#if MG_TI_NO_HOST_INTERFACE || defined(_NEWLIB_VERSION) +int rename(const char *frompath, const char *topath) { + int r = -1; + bool is_sl_from, is_sl_to; + const char *from = drop_dir(frompath, &is_sl_from); + const char *to = drop_dir(topath, &is_sl_to); + if (is_sl_from || is_sl_to) { + set_errno(ENOTSUP); + } else { +#ifdef CC3200_FS_SPIFFS + r = fs_spiffs_rename(from, to); +#endif + } + DBG(("rename(%s, %s) = %d", from, to, r)); + return r; +} +#endif /* MG_TI_NO_HOST_INTERFACE || defined(_NEWLIB_VERSION) */ + +#if MG_TI_NO_HOST_INTERFACE +int unlink(const char *pathname) { +#else +int _unlink(const char *pathname) { +#endif + int r = -1; + bool is_sl; + const char *fname = drop_dir(pathname, &is_sl); + if (is_sl) { +#ifdef MG_FS_SLFS + r = fs_slfs_unlink(fname); +#endif + } else { +#ifdef CC3200_FS_SPIFFS + r = fs_spiffs_unlink(fname); +#endif + } + DBG(("unlink(%s) = %d, fname = %s", pathname, r, fname)); + return r; +} + +#ifdef CC3200_FS_SPIFFS /* FailFS does not support listing files. */ +DIR *opendir(const char *dir_name) { + DIR *r = NULL; + bool is_sl; + drop_dir(dir_name, &is_sl); + if (is_sl) { + r = NULL; + set_errno(ENOTSUP); + } else { + r = fs_spiffs_opendir(dir_name); + } + DBG(("opendir(%s) = %p", dir_name, r)); + return r; +} + +struct dirent *readdir(DIR *dir) { + struct dirent *res = fs_spiffs_readdir(dir); + DBG(("readdir(%p) = %p", dir, res)); + return res; +} + +int closedir(DIR *dir) { + int res = fs_spiffs_closedir(dir); + DBG(("closedir(%p) = %d", dir, res)); + return res; +} + +int rmdir(const char *path) { + return fs_spiffs_rmdir(path); +} + +int mkdir(const char *path, mode_t mode) { + (void) path; + (void) mode; + /* for spiffs supports only root dir, which comes from mongoose as '.' */ + return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR; +} +#endif + +int sl_fs_init(void) { + int ret = 1; +#ifdef __TI_COMPILER_VERSION__ +#ifdef MG_FS_SLFS +#pragma diag_push +#pragma diag_suppress 169 /* Nothing we can do about the prototype mismatch. \ + */ + ret = (add_device("SL", _MSA, fs_slfs_open, fs_slfs_close, fs_slfs_read, + fs_slfs_write, fs_slfs_lseek, fs_slfs_unlink, + fs_slfs_rename) == 0); +#pragma diag_pop +#endif +#endif + return ret; +} + +#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK && (defined(MG_FS_SLFS) || \ + defined(MG_FS_SPIFFS)) */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_socket.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_NET_IF == MG_NET_IF_SIMPLELINK + +#include +#include + +/* Amalgamated: #include "common/platform.h" */ + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { + int res; + struct in_addr *in = (struct in_addr *) src; + if (af != AF_INET) { + errno = EAFNOSUPPORT; + return NULL; + } + res = snprintf(dst, size, "%lu.%lu.%lu.%lu", SL_IPV4_BYTE(in->s_addr, 0), + SL_IPV4_BYTE(in->s_addr, 1), SL_IPV4_BYTE(in->s_addr, 2), + SL_IPV4_BYTE(in->s_addr, 3)); + return res > 0 ? dst : NULL; +} + +char *inet_ntoa(struct in_addr n) { + static char a[16]; + return (char *) inet_ntop(AF_INET, &n, a, sizeof(a)); +} + +int inet_pton(int af, const char *src, void *dst) { + uint32_t a0, a1, a2, a3; + uint8_t *db = (uint8_t *) dst; + if (af != AF_INET) { + errno = EAFNOSUPPORT; + return 0; + } + if (sscanf(src, "%lu.%lu.%lu.%lu", &a0, &a1, &a2, &a3) != 4) { + return 0; + } + *db = a3; + *(db + 1) = a2; + *(db + 2) = a1; + *(db + 3) = a0; + return 1; +} + +#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_mg_task.c" +#endif +#if MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(MG_SIMPLELINK_NO_OSI) + +/* Amalgamated: #include "mg_task.h" */ + +#include + +enum mg_q_msg_type { + MG_Q_MSG_CB, +}; +struct mg_q_msg { + enum mg_q_msg_type type; + void (*cb)(struct mg_mgr *mgr, void *arg); + void *arg; +}; +static OsiMsgQ_t s_mg_q; +static void mg_task(void *arg); + +bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init) { + if (osi_MsgQCreate(&s_mg_q, "MG", sizeof(struct mg_q_msg), 16) != OSI_OK) { + return false; + } + if (osi_TaskCreate(mg_task, (const signed char *) "MG", stack_size, + (void *) mg_init, priority, NULL) != OSI_OK) { + return false; + } + return true; +} + +static void mg_task(void *arg) { + struct mg_mgr mgr; + mg_init_cb mg_init = (mg_init_cb) arg; + mg_mgr_init(&mgr, NULL); + mg_init(&mgr); + while (1) { + struct mg_q_msg msg; + mg_mgr_poll(&mgr, 1); + if (osi_MsgQRead(&s_mg_q, &msg, 1) != OSI_OK) continue; + switch (msg.type) { + case MG_Q_MSG_CB: { + msg.cb(&mgr, msg.arg); + } + } + } +} + +void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg) { + struct mg_q_msg msg = {MG_Q_MSG_CB, cb, cb_arg}; + osi_MsgQWrite(&s_mg_q, &msg, OSI_NO_WAIT); +} + +#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(MG_SIMPLELINK_NO_OSI) \ + */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_net_if.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_ +#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_ + +/* Amalgamated: #include "mongoose/src/net_if.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MG_ENABLE_NET_IF_SIMPLELINK +#define MG_ENABLE_NET_IF_SIMPLELINK MG_NET_IF == MG_NET_IF_SIMPLELINK +#endif + +extern struct mg_iface_vtable mg_simplelink_iface_vtable; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_net_if.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +/* Amalgamated: #include "common/platforms/simplelink/sl_net_if.h" */ + +#if MG_ENABLE_NET_IF_SIMPLELINK + +/* Amalgamated: #include "mongoose/src/internal.h" */ +/* Amalgamated: #include "mongoose/src/util.h" */ + +#define MG_TCP_RECV_BUFFER_SIZE 1024 +#define MG_UDP_RECV_BUFFER_SIZE 1500 + +static sock_t mg_open_listening_socket(union socket_address *sa, int type, + int proto); + +int sl_set_ssl_opts(struct mg_connection *nc); + +void mg_set_non_blocking_mode(sock_t sock) { + SlSockNonblocking_t opt; + opt.NonblockingEnabled = 1; + sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &opt, sizeof(opt)); +} + +static int mg_is_error(int n) { + return (n < 0 && n != SL_EALREADY && n != SL_EAGAIN); +} + +void mg_sl_if_connect_tcp(struct mg_connection *nc, + const union socket_address *sa) { + int proto = 0; + if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET; + sock_t sock = sl_Socket(AF_INET, SOCK_STREAM, proto); + if (sock < 0) { + nc->err = sock; + goto out; + } + mg_sock_set(nc, sock); +#if MG_ENABLE_SSL + nc->err = sl_set_ssl_opts(nc); + if (nc->err != 0) goto out; +#endif + nc->err = sl_Connect(sock, &sa->sa, sizeof(sa->sin)); +out: + DBG(("%p to %s:%d sock %d %d err %d", nc, inet_ntoa(sa->sin.sin_addr), + ntohs(sa->sin.sin_port), nc->sock, proto, nc->err)); +} + +void mg_sl_if_connect_udp(struct mg_connection *nc) { + sock_t sock = sl_Socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + nc->err = sock; + return; + } + mg_sock_set(nc, sock); + nc->err = 0; +} + +int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) { + int proto = 0; + if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET; + sock_t sock = mg_open_listening_socket(sa, SOCK_STREAM, proto); + if (sock < 0) return sock; + mg_sock_set(nc, sock); +#if MG_ENABLE_SSL + return sl_set_ssl_opts(nc); +#else + return 0; +#endif +} + +int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa) { + sock_t sock = mg_open_listening_socket(sa, SOCK_DGRAM, 0); + if (sock == INVALID_SOCKET) return (errno ? errno : 1); + mg_sock_set(nc, sock); + return 0; +} + +void mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); +} + +void mg_sl_if_udp_send(struct mg_connection *nc, const void *buf, size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); +} + +void mg_sl_if_recved(struct mg_connection *nc, size_t len) { + (void) nc; + (void) len; +} + +int mg_sl_if_create_conn(struct mg_connection *nc) { + (void) nc; + return 1; +} + +void mg_sl_if_destroy_conn(struct mg_connection *nc) { + if (nc->sock == INVALID_SOCKET) return; + /* For UDP, only close outgoing sockets or listeners. */ + if (!(nc->flags & MG_F_UDP) || nc->listener == NULL) { + sl_Close(nc->sock); + } + nc->sock = INVALID_SOCKET; +} + +static int mg_accept_conn(struct mg_connection *lc) { + struct mg_connection *nc; + union socket_address sa; + socklen_t sa_len = sizeof(sa); + sock_t sock = sl_Accept(lc->sock, &sa.sa, &sa_len); + if (sock < 0) { + DBG(("%p: failed to accept: %d", lc, sock)); + return 0; + } + nc = mg_if_accept_new_conn(lc); + if (nc == NULL) { + sl_Close(sock); + return 0; + } + DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr), + ntohs(sa.sin.sin_port))); + mg_sock_set(nc, sock); + if (nc->flags & MG_F_SSL) nc->flags |= MG_F_SSL_HANDSHAKE_DONE; + mg_if_accept_tcp_cb(nc, &sa, sa_len); + return 1; +} + +/* 'sa' must be an initialized address to bind to */ +static sock_t mg_open_listening_socket(union socket_address *sa, int type, + int proto) { + int r; + socklen_t sa_len = + (sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6); + sock_t sock = sl_Socket(sa->sa.sa_family, type, proto); + if (sock < 0) return sock; + if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) { + sl_Close(sock); + return r; + } + if (type != SOCK_DGRAM && (r = sl_Listen(sock, SOMAXCONN)) < 0) { + sl_Close(sock); + return r; + } + mg_set_non_blocking_mode(sock); + return sock; +} + +static void mg_write_to_socket(struct mg_connection *nc) { + struct mbuf *io = &nc->send_mbuf; + int n = 0; + + if (nc->flags & MG_F_UDP) { + n = sl_SendTo(nc->sock, io->buf, io->len, 0, &nc->sa.sa, + sizeof(nc->sa.sin)); + DBG(("%p %d %d %d %s:%hu", nc, nc->sock, n, errno, + inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port))); + } else { + n = (int) sl_Send(nc->sock, io->buf, io->len, 0); + DBG(("%p %d bytes -> %d", nc, n, nc->sock)); + } + + if (n > 0) { + mbuf_remove(io, n); + mg_if_sent_cb(nc, n); + } else if (n < 0 && mg_is_error(n)) { + /* Something went wrong, drop the connection. */ + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } +} + +MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max) { + size_t avail; + if (conn->recv_mbuf_limit < conn->recv_mbuf.len) return 0; + avail = conn->recv_mbuf_limit - conn->recv_mbuf.len; + return avail > max ? max : avail; +} + +static void mg_handle_tcp_read(struct mg_connection *conn) { + int n = 0; + char *buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE); + + if (buf == NULL) { + DBG(("OOM")); + return; + } + + n = (int) sl_Recv(conn->sock, buf, + recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0); + DBG(("%p %d bytes <- %d", conn, n, conn->sock)); + if (n > 0) { + mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */); + } else { + MG_FREE(buf); + } + if (n == 0) { + /* Orderly shutdown of the socket, try flushing output. */ + conn->flags |= MG_F_SEND_AND_CLOSE; + } else if (mg_is_error(n)) { + conn->flags |= MG_F_CLOSE_IMMEDIATELY; + } +} + +static void mg_handle_udp_read(struct mg_connection *nc) { + char *buf = (char *) MG_MALLOC(MG_UDP_RECV_BUFFER_SIZE); + if (buf == NULL) return; + union socket_address sa; + socklen_t sa_len = sizeof(sa); + int n = sl_RecvFrom(nc->sock, buf, MG_UDP_RECV_BUFFER_SIZE, 0, + (SlSockAddr_t *) &sa, &sa_len); + DBG(("%p %d bytes from %s:%d", nc, n, inet_ntoa(nc->sa.sin.sin_addr), + ntohs(nc->sa.sin.sin_port))); + if (n > 0) { + mg_if_recv_udp_cb(nc, buf, n, &sa, sa_len); + } else { + MG_FREE(buf); + } +} + +#define _MG_F_FD_CAN_READ 1 +#define _MG_F_FD_CAN_WRITE 1 << 1 +#define _MG_F_FD_ERROR 1 << 2 + +void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) { + DBG(("%p fd=%d fd_flags=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, + fd_flags, nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); + + if (nc->flags & MG_F_CONNECTING) { + if (nc->flags & MG_F_UDP || nc->err != SL_EALREADY) { + mg_if_connect_cb(nc, nc->err); + } else { + /* In SimpleLink, to get status of non-blocking connect() we need to wait + * until socket is writable and repeat the call to sl_Connect again, + * which will now return the real status. */ + if (fd_flags & _MG_F_FD_CAN_WRITE) { + nc->err = sl_Connect(nc->sock, &nc->sa.sa, sizeof(nc->sa.sin)); + DBG(("%p conn res=%d", nc, nc->err)); + if (nc->err == SL_ESECSNOVERIFY || + /* TODO(rojer): Provide API to set the date for verification. */ + nc->err == SL_ESECDATEERROR) { + nc->err = 0; + } + if (nc->flags & MG_F_SSL && nc->err == 0) { + nc->flags |= MG_F_SSL_HANDSHAKE_DONE; + } + mg_if_connect_cb(nc, nc->err); + } + } + /* Ignore read/write in further processing, we've handled it. */ + fd_flags &= ~(_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE); + } + + if (fd_flags & _MG_F_FD_CAN_READ) { + if (nc->flags & MG_F_UDP) { + mg_handle_udp_read(nc); + } else { + if (nc->flags & MG_F_LISTENING) { + mg_accept_conn(nc); + } else { + mg_handle_tcp_read(nc); + } + } + } + + if (!(nc->flags & MG_F_CLOSE_IMMEDIATELY)) { + if ((fd_flags & _MG_F_FD_CAN_WRITE) && nc->send_mbuf.len > 0) { + mg_write_to_socket(nc); + } + + if (!(fd_flags & (_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE))) { + mg_if_poll(nc, now); + } + mg_if_timer(nc, now); + } + + DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags, + (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); +} + +/* Associate a socket to a connection. */ +void mg_sl_if_sock_set(struct mg_connection *nc, sock_t sock) { + mg_set_non_blocking_mode(sock); + nc->sock = sock; + DBG(("%p %d", nc, sock)); +} + +void mg_sl_if_init(struct mg_iface *iface) { + (void) iface; + DBG(("%p using sl_Select()", iface->mgr)); +} + +void mg_sl_if_free(struct mg_iface *iface) { + (void) iface; +} + +void mg_sl_if_add_conn(struct mg_connection *nc) { + (void) nc; +} + +void mg_sl_if_remove_conn(struct mg_connection *nc) { + (void) nc; +} + +time_t mg_sl_if_poll(struct mg_iface *iface, int timeout_ms) { + struct mg_mgr *mgr = iface->mgr; + double now = mg_time(); + double min_timer; + struct mg_connection *nc, *tmp; + struct SlTimeval_t tv; + SlFdSet_t read_set, write_set, err_set; + sock_t max_fd = INVALID_SOCKET; + int num_fds, num_ev = 0, num_timers = 0; + + SL_FD_ZERO(&read_set); + SL_FD_ZERO(&write_set); + SL_FD_ZERO(&err_set); + + /* + * Note: it is ok to have connections with sock == INVALID_SOCKET in the list, + * e.g. timer-only "connections". + */ + min_timer = 0; + for (nc = mgr->active_connections, num_fds = 0; nc != NULL; nc = tmp) { + tmp = nc->next; + + if (nc->sock != INVALID_SOCKET) { + num_fds++; + + if (!(nc->flags & MG_F_WANT_WRITE) && + nc->recv_mbuf.len < nc->recv_mbuf_limit && + (!(nc->flags & MG_F_UDP) || nc->listener == NULL)) { + SL_FD_SET(nc->sock, &read_set); + if (max_fd == INVALID_SOCKET || nc->sock > max_fd) max_fd = nc->sock; + } + + if (((nc->flags & MG_F_CONNECTING) && !(nc->flags & MG_F_WANT_READ)) || + (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING))) { + SL_FD_SET(nc->sock, &write_set); + SL_FD_SET(nc->sock, &err_set); + if (max_fd == INVALID_SOCKET || nc->sock > max_fd) max_fd = nc->sock; + } + } + + if (nc->ev_timer_time > 0) { + if (num_timers == 0 || nc->ev_timer_time < min_timer) { + min_timer = nc->ev_timer_time; + } + num_timers++; + } + } + + /* + * If there is a timer to be fired earlier than the requested timeout, + * adjust the timeout. + */ + if (num_timers > 0) { + double timer_timeout_ms = (min_timer - mg_time()) * 1000 + 1 /* rounding */; + if (timer_timeout_ms < timeout_ms) { + timeout_ms = timer_timeout_ms; + } + } + if (timeout_ms < 0) timeout_ms = 0; + + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + + if (num_fds > 0) { + num_ev = sl_Select((int) max_fd + 1, &read_set, &write_set, &err_set, &tv); + } + + now = mg_time(); + DBG(("sl_Select @ %ld num_ev=%d of %d, timeout=%d", (long) now, num_ev, + num_fds, timeout_ms)); + + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + int fd_flags = 0; + if (nc->sock != INVALID_SOCKET) { + if (num_ev > 0) { + fd_flags = + (SL_FD_ISSET(nc->sock, &read_set) && + (!(nc->flags & MG_F_UDP) || nc->listener == NULL) + ? _MG_F_FD_CAN_READ + : 0) | + (SL_FD_ISSET(nc->sock, &write_set) ? _MG_F_FD_CAN_WRITE : 0) | + (SL_FD_ISSET(nc->sock, &err_set) ? _MG_F_FD_ERROR : 0); + } + /* SimpleLink does not report UDP sockets as writeable. */ + if (nc->flags & MG_F_UDP && nc->send_mbuf.len > 0) { + fd_flags |= _MG_F_FD_CAN_WRITE; + } + } + tmp = nc->next; + mg_mgr_handle_conn(nc, fd_flags, now); + } + + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + tmp = nc->next; + if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) || + (nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) { + mg_close_conn(nc); + } + } + + return now; +} + +void mg_sl_if_get_conn_addr(struct mg_connection *nc, int remote, + union socket_address *sa) { + /* SimpleLink does not provide a way to get socket's peer address after + * accept or connect. Address hould have been preserved in the connection, + * so we do our best here by using it. */ + if (remote) memcpy(sa, &nc->sa, sizeof(*sa)); +} + +void sl_restart_cb(struct mg_mgr *mgr) { + /* + * SimpleLink has been restarted, meaning all sockets have been invalidated. + * We try our best - we'll restart the listeners, but for outgoing + * connections we have no option but to terminate. + */ + struct mg_connection *nc; + for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { + if (nc->sock == INVALID_SOCKET) continue; /* Could be a timer */ + if (nc->flags & MG_F_LISTENING) { + DBG(("restarting %p %s:%d", nc, inet_ntoa(nc->sa.sin.sin_addr), + ntohs(nc->sa.sin.sin_port))); + int res = (nc->flags & MG_F_UDP ? mg_sl_if_listen_udp(nc, &nc->sa) + : mg_sl_if_listen_tcp(nc, &nc->sa)); + if (res == 0) continue; + /* Well, we tried and failed. Fall through to closing. */ + } + nc->sock = INVALID_SOCKET; + DBG(("terminating %p %s:%d", nc, inet_ntoa(nc->sa.sin.sin_addr), + ntohs(nc->sa.sin.sin_port))); + /* TODO(rojer): Outgoing UDP? */ + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + } +} + +/* clang-format off */ +#define MG_SL_IFACE_VTABLE \ + { \ + mg_sl_if_init, \ + mg_sl_if_free, \ + mg_sl_if_add_conn, \ + mg_sl_if_remove_conn, \ + mg_sl_if_poll, \ + mg_sl_if_listen_tcp, \ + mg_sl_if_listen_udp, \ + mg_sl_if_connect_tcp, \ + mg_sl_if_connect_udp, \ + mg_sl_if_tcp_send, \ + mg_sl_if_udp_send, \ + mg_sl_if_recved, \ + mg_sl_if_create_conn, \ + mg_sl_if_destroy_conn, \ + mg_sl_if_sock_set, \ + mg_sl_if_get_conn_addr, \ + } +/* clang-format on */ + +struct mg_iface_vtable mg_simplelink_iface_vtable = MG_SL_IFACE_VTABLE; +#if MG_NET_IF == MG_NET_IF_SIMPLELINK +struct mg_iface_vtable mg_default_iface_vtable = MG_SL_IFACE_VTABLE; +#endif + +#endif /* MG_ENABLE_NET_IF_SIMPLELINK */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/simplelink/sl_ssl_if.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK + +struct mg_ssl_if_ctx { + char *ssl_cert; + char *ssl_key; + char *ssl_ca_cert; + char *ssl_server_name; +}; + +void mg_ssl_if_init() { +} + +enum mg_ssl_if_result mg_ssl_if_conn_init( + struct mg_connection *nc, const struct mg_ssl_if_conn_params *params, + const char **err_msg) { + struct mg_ssl_if_ctx *ctx = + (struct mg_ssl_if_ctx *) MG_CALLOC(1, sizeof(*ctx)); + if (ctx == NULL) { + MG_SET_PTRPTR(err_msg, "Out of memory"); + return MG_SSL_ERROR; + } + nc->ssl_if_data = ctx; + + if (params->cert != NULL || params->key != NULL) { + if (params->cert != NULL && params->key != NULL) { + ctx->ssl_cert = strdup(params->cert); + ctx->ssl_key = strdup(params->key); + } else { + MG_SET_PTRPTR(err_msg, "Both cert and key are required."); + return MG_SSL_ERROR; + } + } + if (params->ca_cert != NULL && strcmp(params->ca_cert, "*") != 0) { + ctx->ssl_ca_cert = strdup(params->ca_cert); + } + /* TODO(rojer): cipher_suites. */ + if (params->server_name != NULL) { + ctx->ssl_server_name = strdup(params->server_name); + } + return MG_SSL_OK; +} + +void mg_ssl_if_conn_free(struct mg_connection *nc) { + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + if (ctx == NULL) return; + nc->ssl_if_data = NULL; + MG_FREE(ctx->ssl_cert); + MG_FREE(ctx->ssl_key); + MG_FREE(ctx->ssl_ca_cert); + MG_FREE(ctx->ssl_server_name); + memset(ctx, 0, sizeof(*ctx)); + MG_FREE(ctx); +} + +bool pem_to_der(const char *pem_file, const char *der_file) { + bool ret = false; + FILE *pf = NULL, *df = NULL; + bool writing = false; + pf = fopen(pem_file, "r"); + if (pf == NULL) goto clean; + remove(der_file); + fs_slfs_set_new_file_size(der_file + 3, 2048); + df = fopen(der_file, "w"); + if (df == NULL) goto clean; + while (1) { + char pem_buf[70]; + char der_buf[48]; + if (!fgets(pem_buf, sizeof(pem_buf), pf)) break; + if (writing) { + if (strstr(pem_buf, "-----END ") != NULL) { + ret = true; + break; + } + int l = 0; + while (!isspace((unsigned int) pem_buf[l])) l++; + int der_len = 0; + cs_base64_decode((const unsigned char *) pem_buf, sizeof(pem_buf), + der_buf, &der_len); + if (der_len <= 0) break; + if (fwrite(der_buf, 1, der_len, df) != der_len) break; + } else if (strstr(pem_buf, "-----BEGIN ") != NULL) { + writing = true; + } + } + +clean: + if (pf != NULL) fclose(pf); + if (df != NULL) { + fclose(df); + if (!ret) remove(der_file); + } + return ret; +} + +#if MG_ENABLE_FILESYSTEM && defined(MG_FS_SLFS) +/* If the file's extension is .pem, convert it to DER format and put on SLFS. */ +static char *sl_pem2der(const char *pem_file) { + const char *pem_ext = strstr(pem_file, ".pem"); + if (pem_ext == NULL || *(pem_ext + 4) != '\0') { + return strdup(pem_file); + } + char *der_file = NULL; + /* DER file must be located on SLFS, add prefix. */ + int l = mg_asprintf(&der_file, 0, "SL:%.*s.der", (int) (pem_ext - pem_file), + pem_file); + if (der_file == NULL) return NULL; + bool result = false; + cs_stat_t st; + if (mg_stat(der_file, &st) != 0) { + result = pem_to_der(pem_file, der_file); + LOG(LL_DEBUG, ("%s -> %s = %d", pem_file, der_file, result)); + } else { + /* File exists, assume it's already been converted. */ + result = true; + } + if (result) { + /* Strip the SL: prefix we added since NWP does not expect it. */ + memmove(der_file, der_file + 3, l - 2 /* including \0 */); + } else { + free(der_file); + der_file = NULL; + } + return der_file; +} +#else +static char *sl_pem2der(const char *pem_file) { + return strdup(pem_file); +} +#endif + +int sl_set_ssl_opts(struct mg_connection *nc) { + int err; + struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; + DBG(("%p ssl ctx: %p", nc, ctx)); + + if (ctx != NULL) { + DBG(("%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert : "-"), + (ctx->ssl_key ? ctx->ssl_cert : "-"), + (ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"), + (ctx->ssl_server_name ? ctx->ssl_server_name : "-"))); + if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) { + char *ssl_cert = sl_pem2der(ctx->ssl_cert); + char *ssl_key = sl_pem2der(ctx->ssl_key); + if (ssl_cert != NULL && ssl_key != NULL) { + err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, + SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert, + strlen(ssl_cert)); + LOG(LL_INFO, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err)); + err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, + SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key, + strlen(ssl_key)); + LOG(LL_INFO, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err)); + } else { + err = -1; + } + free(ssl_cert); + free(ssl_key); + if (err != 0) return err; + } + if (ctx->ssl_ca_cert != NULL) { + if (ctx->ssl_ca_cert[0] != '\0') { + char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert); + if (ssl_ca_cert != NULL) { + err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, + SL_SO_SECURE_FILES_CA_FILE_NAME, ssl_ca_cert, + strlen(ssl_ca_cert)); + LOG(LL_INFO, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err)); + } else { + err = -1; + } + free(ssl_ca_cert); + if (err != 0) return err; + } + } + if (ctx->ssl_server_name != NULL) { + err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, + SO_SECURE_DOMAIN_NAME_VERIFICATION, + ctx->ssl_server_name, strlen(ctx->ssl_server_name)); + DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err)); + /* Domain name verificationw as added in a NWP service pack, older + * versions return SL_ENOPROTOOPT. There isn't much we can do about it, + * so we ignore the error. */ + if (err != 0 && err != SL_ENOPROTOOPT) return err; + } + } + return 0; +} + +#endif /* MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/lwip/mg_lwip_net_if.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_ +#define CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_ + +#ifndef MG_ENABLE_NET_IF_LWIP_LOW_LEVEL +#define MG_ENABLE_NET_IF_LWIP_LOW_LEVEL MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL +#endif + +#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL + +#include + +extern struct mg_iface_vtable mg_lwip_iface_vtable; + +struct mg_lwip_conn_state { + struct mg_connection *nc; + union { + struct tcp_pcb *tcp; + struct udp_pcb *udp; + } pcb; + err_t err; + size_t num_sent; /* Number of acknowledged bytes to be reported to the core */ + struct pbuf *rx_chain; /* Chain of incoming data segments. */ + size_t rx_offset; /* Offset within the first pbuf (if partially consumed) */ + /* Last SSL write size, for retries. */ + int last_ssl_write_size; +}; + +enum mg_sig_type { + MG_SIG_CONNECT_RESULT = 1, + MG_SIG_RECV = 2, + MG_SIG_SENT_CB = 3, + MG_SIG_CLOSE_CONN = 4, + MG_SIG_TOMBSTONE = 5, +}; + +void mg_lwip_post_signal(enum mg_sig_type sig, struct mg_connection *nc); + +/* To be implemented by the platform. */ +void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr); + +#endif /* MG_ENABLE_NET_IF_LWIP_LOW_LEVEL */ + +#endif /* CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/lwip/mg_lwip_net_if.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL + +#include +#include +#if CS_PLATFORM != CS_P_STM32 +#include +#endif +#include + +/* Amalgamated: #include "common/cs_dbg.h" */ + +/* + * Depending on whether Mongoose is compiled with ipv6 support, use right + * lwip functions + */ +#if MG_ENABLE_IPV6 +#define TCP_NEW tcp_new_ip6 +#define TCP_BIND tcp_bind_ip6 +#define UDP_BIND udp_bind_ip6 +#define IPADDR_NTOA(x) ip6addr_ntoa((const ip6_addr_t *)(x)) +#define SET_ADDR(dst, src) \ + memcpy((dst)->sin6.sin6_addr.s6_addr, (src)->ip6.addr, \ + sizeof((dst)->sin6.sin6_addr.s6_addr)) +#else +#define TCP_NEW tcp_new +#define TCP_BIND tcp_bind +#define UDP_BIND udp_bind +#define IPADDR_NTOA ipaddr_ntoa +#define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = GET_IPV4(src) +#endif + +/* + * If lwip is compiled with ipv6 support, then API changes even for ipv4 + */ +#if !defined(LWIP_IPV6) || !LWIP_IPV6 +#define GET_IPV4(ipX_addr) ((ipX_addr)->addr) +#else +#define GET_IPV4(ipX_addr) ((ipX_addr)->ip4.addr) +#endif + +void mg_lwip_ssl_do_hs(struct mg_connection *nc); +void mg_lwip_ssl_send(struct mg_connection *nc); +void mg_lwip_ssl_recv(struct mg_connection *nc); + +void mg_lwip_if_init(struct mg_iface *iface); +void mg_lwip_if_free(struct mg_iface *iface); +void mg_lwip_if_add_conn(struct mg_connection *nc); +void mg_lwip_if_remove_conn(struct mg_connection *nc); +time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms); + +#if LWIP_TCP_KEEPALIVE +void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle, + int interval, int count) { + if (nc->sock == INVALID_SOCKET || nc->flags & MG_F_UDP) { + return; + } + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct tcp_pcb *tpcb = cs->pcb.tcp; + if (idle > 0 && interval > 0 && count > 0) { + tpcb->keep_idle = idle * 1000; + tpcb->keep_intvl = interval * 1000; + tpcb->keep_cnt = count; + tpcb->so_options |= SOF_KEEPALIVE; + } else { + tpcb->so_options &= ~SOF_KEEPALIVE; + } +} +#elif !defined(MG_NO_LWIP_TCP_KEEPALIVE) +#warning LWIP TCP keepalive is disabled. Please consider enabling it. +#endif /* LWIP_TCP_KEEPALIVE */ + +static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err) { + struct mg_connection *nc = (struct mg_connection *) arg; + DBG(("%p connect to %s:%u = %d", nc, IPADDR_NTOA(&tpcb->remote_ip), + tpcb->remote_port, err)); + if (nc == NULL) { + tcp_abort(tpcb); + return ERR_ARG; + } + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + cs->err = err; +#if LWIP_TCP_KEEPALIVE + if (err == 0) mg_lwip_set_keepalive_params(nc, 60, 10, 6); +#endif + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); + return ERR_OK; +} + +static void mg_lwip_tcp_error_cb(void *arg, err_t err) { + struct mg_connection *nc = (struct mg_connection *) arg; + DBG(("%p conn error %d", nc, err)); + if (nc == NULL) return; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + cs->pcb.tcp = NULL; /* Has already been deallocated */ + if (nc->flags & MG_F_CONNECTING) { + cs->err = err; + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); + } else { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + } +} + +static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err) { + struct mg_connection *nc = (struct mg_connection *) arg; + DBG(("%p %p %u %d", nc, tpcb, (p != NULL ? p->tot_len : 0), err)); + if (p == NULL) { + if (nc != NULL) { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + } else { + /* Tombstoned connection, do nothing. */ + } + return ERR_OK; + } else if (nc == NULL) { + tcp_abort(tpcb); + return ERR_ARG; + } + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + /* + * If we get a chain of more than one segment at once, we need to bump + * refcount on the subsequent bufs to make them independent. + */ + if (p->next != NULL) { + struct pbuf *q = p->next; + for (; q != NULL; q = q->next) pbuf_ref(q); + } + if (cs->rx_chain == NULL) { + cs->rx_chain = p; + cs->rx_offset = 0; + } else { + if (pbuf_clen(cs->rx_chain) >= 4) { + /* ESP SDK has a limited pool of 5 pbufs. We must not hog them all or RX + * will be completely blocked. We already have at least 4 in the chain, + * this one is, so we have to make a copy and release this one. */ + struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (np != NULL) { + pbuf_copy(np, p); + pbuf_free(p); + p = np; + } + } + pbuf_chain(cs->rx_chain, p); + } + mg_lwip_post_signal(MG_SIG_RECV, nc); + return ERR_OK; +} + +static void mg_lwip_handle_recv(struct mg_connection *nc) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + +#if MG_ENABLE_SSL + if (nc->flags & MG_F_SSL) { + if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { + mg_lwip_ssl_recv(nc); + } else { + mg_lwip_ssl_do_hs(nc); + } + return; + } +#endif + + while (cs->rx_chain != NULL) { + struct pbuf *seg = cs->rx_chain; + size_t len = (seg->len - cs->rx_offset); + char *data = (char *) malloc(len); + if (data == NULL) { + DBG(("OOM")); + return; + } + pbuf_copy_partial(seg, data, len, cs->rx_offset); + mg_if_recv_tcp_cb(nc, data, len, 1 /* own */); + cs->rx_offset += len; + if (cs->rx_offset == cs->rx_chain->len) { + cs->rx_chain = pbuf_dechain(cs->rx_chain); + pbuf_free(seg); + cs->rx_offset = 0; + } + } + + if (nc->send_mbuf.len > 0) { + mg_lwip_mgr_schedule_poll(nc->mgr); + } +} + +static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, + u16_t num_sent) { + struct mg_connection *nc = (struct mg_connection *) arg; + DBG(("%p %p %u", nc, tpcb, num_sent)); + if (nc == NULL) { + tcp_abort(tpcb); + return ERR_ABRT; + } + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + cs->num_sent += num_sent; + + mg_lwip_post_signal(MG_SIG_SENT_CB, nc); + return ERR_OK; +} + +void mg_lwip_if_connect_tcp(struct mg_connection *nc, + const union socket_address *sa) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct tcp_pcb *tpcb = TCP_NEW(); + cs->pcb.tcp = tpcb; + ip_addr_t *ip = (ip_addr_t *) &sa->sin.sin_addr.s_addr; + u16_t port = ntohs(sa->sin.sin_port); + tcp_arg(tpcb, nc); + tcp_err(tpcb, mg_lwip_tcp_error_cb); + tcp_sent(tpcb, mg_lwip_tcp_sent_cb); + tcp_recv(tpcb, mg_lwip_tcp_recv_cb); + cs->err = TCP_BIND(tpcb, IP_ADDR_ANY, 0 /* any port */); + DBG(("%p tcp_bind = %d", nc, cs->err)); + if (cs->err != ERR_OK) { + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); + return; + } + cs->err = tcp_connect(tpcb, ip, port, mg_lwip_tcp_conn_cb); + DBG(("%p tcp_connect %p = %d", nc, tpcb, cs->err)); + if (cs->err != ERR_OK) { + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); + return; + } +} + +/* + * Lwip included in the SDKs for nRF5x chips has different type for the + * callback of `udp_recv()` + */ +#if CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52 || \ + CS_PLATFORM == CS_P_STM32 +static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) +#else +static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port) +#endif +{ + struct mg_connection *nc = (struct mg_connection *) arg; + size_t len = p->len; + char *data = (char *) malloc(len); + union socket_address sa; + (void) pcb; + DBG(("%p %s:%u %u", nc, IPADDR_NTOA(addr), port, p->len)); + if (data == NULL) { + DBG(("OOM")); + pbuf_free(p); + return; + } + sa.sin.sin_addr.s_addr = addr->addr; + sa.sin.sin_port = htons(port); + pbuf_copy_partial(p, data, len, 0); + pbuf_free(p); + mg_if_recv_udp_cb(nc, data, len, &sa, sizeof(sa.sin)); +} + +void mg_lwip_if_connect_udp(struct mg_connection *nc) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct udp_pcb *upcb = udp_new(); + cs->err = UDP_BIND(upcb, IP_ADDR_ANY, 0 /* any port */); + DBG(("%p udp_bind %p = %d", nc, upcb, cs->err)); + if (cs->err == ERR_OK) { + udp_recv(upcb, mg_lwip_udp_recv_cb, nc); + cs->pcb.udp = upcb; + } else { + udp_remove(upcb); + } + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); +} + +void mg_lwip_accept_conn(struct mg_connection *nc, struct tcp_pcb *tpcb) { + union socket_address sa; + SET_ADDR(&sa, &tpcb->remote_ip); + sa.sin.sin_port = htons(tpcb->remote_port); + mg_if_accept_tcp_cb(nc, &sa, sizeof(sa.sin)); +} + +static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err) { + struct mg_connection *lc = (struct mg_connection *) arg; + (void) err; + DBG(("%p conn %p from %s:%u", lc, newtpcb, IPADDR_NTOA(&newtpcb->remote_ip), + newtpcb->remote_port)); + struct mg_connection *nc = mg_if_accept_new_conn(lc); + if (nc == NULL) { + tcp_abort(newtpcb); + return ERR_ABRT; + } + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + cs->pcb.tcp = newtpcb; + tcp_arg(newtpcb, nc); + tcp_err(newtpcb, mg_lwip_tcp_error_cb); + tcp_sent(newtpcb, mg_lwip_tcp_sent_cb); + tcp_recv(newtpcb, mg_lwip_tcp_recv_cb); +#if LWIP_TCP_KEEPALIVE + mg_lwip_set_keepalive_params(nc, 60, 10, 6); +#endif +#if MG_ENABLE_SSL + if (lc->flags & MG_F_SSL) { + if (mg_ssl_if_conn_accept(nc, lc) != MG_SSL_OK) { + LOG(LL_ERROR, ("SSL error")); + tcp_close(newtpcb); + } + } else +#endif + { + mg_lwip_accept_conn(nc, newtpcb); + } + return ERR_OK; +} + +int mg_lwip_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct tcp_pcb *tpcb = TCP_NEW(); + ip_addr_t *ip = (ip_addr_t *) &sa->sin.sin_addr.s_addr; + u16_t port = ntohs(sa->sin.sin_port); + cs->err = TCP_BIND(tpcb, ip, port); + DBG(("%p tcp_bind(%s:%u) = %d", nc, IPADDR_NTOA(ip), port, cs->err)); + if (cs->err != ERR_OK) { + tcp_close(tpcb); + return -1; + } + tcp_arg(tpcb, nc); + tpcb = tcp_listen(tpcb); + cs->pcb.tcp = tpcb; + tcp_accept(tpcb, mg_lwip_accept_cb); + return 0; +} + +int mg_lwip_if_listen_udp(struct mg_connection *nc, union socket_address *sa) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct udp_pcb *upcb = udp_new(); + ip_addr_t *ip = (ip_addr_t *) &sa->sin.sin_addr.s_addr; + u16_t port = ntohs(sa->sin.sin_port); + cs->err = UDP_BIND(upcb, ip, port); + DBG(("%p udb_bind(%s:%u) = %d", nc, IPADDR_NTOA(ip), port, cs->err)); + if (cs->err != ERR_OK) { + udp_remove(upcb); + return -1; + } + udp_recv(upcb, mg_lwip_udp_recv_cb, nc); + cs->pcb.udp = upcb; + return 0; +} + +int mg_lwip_tcp_write(struct mg_connection *nc, const void *data, + uint16_t len) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct tcp_pcb *tpcb = cs->pcb.tcp; + len = MIN(tpcb->mss, MIN(len, tpcb->snd_buf)); + if (len == 0) { + DBG(("%p no buf avail %u %u %u %p %p", tpcb, tpcb->acked, tpcb->snd_buf, + tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); + tcp_output(tpcb); + return 0; + } +/* + * On ESP8266 we only allow one TCP segment in flight at any given time. + * This may increase latency and reduce efficiency of tcp windowing, + * but memory is scarce and precious on that platform so we do this to + * reduce footprint. + */ +#if CS_PLATFORM == CS_P_ESP8266 + if (tpcb->unacked != NULL) { + return 0; + } + if (tpcb->unsent != NULL) { + len = MIN(len, (TCP_MSS - tpcb->unsent->len)); + } +#endif + err_t err = tcp_write(tpcb, data, len, TCP_WRITE_FLAG_COPY); + DBG(("%p tcp_write %u = %d", tpcb, len, err)); + if (err != ERR_OK) { + /* + * We ignore ERR_MEM because memory will be freed up when the data is sent + * and we'll retry. + */ + return (err == ERR_MEM ? 0 : -1); + } + return len; +} + +static void mg_lwip_send_more(struct mg_connection *nc) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) { + DBG(("%p invalid socket", nc)); + return; + } + int num_written = mg_lwip_tcp_write(nc, nc->send_mbuf.buf, nc->send_mbuf.len); + DBG(("%p mg_lwip_tcp_write %u = %d", nc, nc->send_mbuf.len, num_written)); + if (num_written == 0) return; + if (num_written < 0) { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + } + mbuf_remove(&nc->send_mbuf, num_written); + mbuf_trim(&nc->send_mbuf); +} + +void mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, + size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); + mg_lwip_mgr_schedule_poll(nc->mgr); +} + +void mg_lwip_if_udp_send(struct mg_connection *nc, const void *buf, + size_t len) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + if (nc->sock == INVALID_SOCKET || cs->pcb.udp == NULL) { + /* + * In case of UDP, this usually means, what + * async DNS resolve is still in progress and connection + * is not ready yet + */ + DBG(("%p socket is not connected", nc)); + return; + } + struct udp_pcb *upcb = cs->pcb.udp; + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + ip_addr_t *ip = (ip_addr_t *) &nc->sa.sin.sin_addr.s_addr; + u16_t port = ntohs(nc->sa.sin.sin_port); + memcpy(p->payload, buf, len); + cs->err = udp_sendto(upcb, p, (ip_addr_t *) ip, port); + DBG(("%p udp_sendto = %d", nc, cs->err)); + pbuf_free(p); + if (cs->err != ERR_OK) { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + } else { + cs->num_sent += len; + mg_lwip_post_signal(MG_SIG_SENT_CB, nc); + } +} + +void mg_lwip_if_recved(struct mg_connection *nc, size_t len) { + if (nc->flags & MG_F_UDP) return; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) { + DBG(("%p invalid socket", nc)); + return; + } + DBG(("%p %p %u", nc, cs->pcb.tcp, len)); +/* Currently SSL acknowledges data immediately. + * TODO(rojer): Find a way to propagate mg_lwip_if_recved. */ +#if MG_ENABLE_SSL + if (!(nc->flags & MG_F_SSL)) { + tcp_recved(cs->pcb.tcp, len); + } +#else + tcp_recved(cs->pcb.tcp, len); +#endif + mbuf_trim(&nc->recv_mbuf); +} + +int mg_lwip_if_create_conn(struct mg_connection *nc) { + struct mg_lwip_conn_state *cs = + (struct mg_lwip_conn_state *) calloc(1, sizeof(*cs)); + if (cs == NULL) return 0; + cs->nc = nc; + nc->sock = (intptr_t) cs; + return 1; +} + +void mg_lwip_if_destroy_conn(struct mg_connection *nc) { + if (nc->sock == INVALID_SOCKET) return; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + if (!(nc->flags & MG_F_UDP)) { + struct tcp_pcb *tpcb = cs->pcb.tcp; + if (tpcb != NULL) { + tcp_arg(tpcb, NULL); + DBG(("%p tcp_close %p", nc, tpcb)); + tcp_arg(tpcb, NULL); + tcp_close(tpcb); + } + while (cs->rx_chain != NULL) { + struct pbuf *seg = cs->rx_chain; + cs->rx_chain = pbuf_dechain(cs->rx_chain); + pbuf_free(seg); + } + memset(cs, 0, sizeof(*cs)); + free(cs); + } else if (nc->listener == NULL) { + /* Only close outgoing UDP pcb or listeners. */ + struct udp_pcb *upcb = cs->pcb.udp; + if (upcb != NULL) { + DBG(("%p udp_remove %p", nc, upcb)); + udp_remove(upcb); + } + memset(cs, 0, sizeof(*cs)); + free(cs); + } + nc->sock = INVALID_SOCKET; +} + +void mg_lwip_if_get_conn_addr(struct mg_connection *nc, int remote, + union socket_address *sa) { + memset(sa, 0, sizeof(*sa)); + if (nc->sock == INVALID_SOCKET) return; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + if (nc->flags & MG_F_UDP) { + struct udp_pcb *upcb = cs->pcb.udp; + if (remote) { + memcpy(sa, &nc->sa, sizeof(*sa)); + } else { + sa->sin.sin_port = htons(upcb->local_port); + SET_ADDR(sa, &upcb->local_ip); + } + } else { + struct tcp_pcb *tpcb = cs->pcb.tcp; + if (remote) { + sa->sin.sin_port = htons(tpcb->remote_port); + SET_ADDR(sa, &tpcb->remote_ip); + } else { + sa->sin.sin_port = htons(tpcb->local_port); + SET_ADDR(sa, &tpcb->local_ip); + } + } +} + +void mg_lwip_if_sock_set(struct mg_connection *nc, sock_t sock) { + nc->sock = sock; +} + +/* clang-format off */ +#define MG_LWIP_IFACE_VTABLE \ + { \ + mg_lwip_if_init, \ + mg_lwip_if_free, \ + mg_lwip_if_add_conn, \ + mg_lwip_if_remove_conn, \ + mg_lwip_if_poll, \ + mg_lwip_if_listen_tcp, \ + mg_lwip_if_listen_udp, \ + mg_lwip_if_connect_tcp, \ + mg_lwip_if_connect_udp, \ + mg_lwip_if_tcp_send, \ + mg_lwip_if_udp_send, \ + mg_lwip_if_recved, \ + mg_lwip_if_create_conn, \ + mg_lwip_if_destroy_conn, \ + mg_lwip_if_sock_set, \ + mg_lwip_if_get_conn_addr, \ + } +/* clang-format on */ + +struct mg_iface_vtable mg_lwip_iface_vtable = MG_LWIP_IFACE_VTABLE; +#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL +struct mg_iface_vtable mg_default_iface_vtable = MG_LWIP_IFACE_VTABLE; +#endif + +#endif /* MG_ENABLE_NET_IF_LWIP_LOW_LEVEL */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/lwip/mg_lwip_ev_mgr.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL + +#ifndef MG_SIG_QUEUE_LEN +#define MG_SIG_QUEUE_LEN 16 +#endif + +struct mg_ev_mgr_lwip_signal { + int sig; + struct mg_connection *nc; +}; + +struct mg_ev_mgr_lwip_data { + struct mg_ev_mgr_lwip_signal sig_queue[MG_SIG_QUEUE_LEN]; + int sig_queue_len; + int start_index; +}; + +void mg_lwip_post_signal(enum mg_sig_type sig, struct mg_connection *nc) { + struct mg_ev_mgr_lwip_data *md = + (struct mg_ev_mgr_lwip_data *) nc->iface->data; + if (md->sig_queue_len >= MG_SIG_QUEUE_LEN) return; + int end_index = (md->start_index + md->sig_queue_len) % MG_SIG_QUEUE_LEN; + md->sig_queue[end_index].sig = sig; + md->sig_queue[end_index].nc = nc; + md->sig_queue_len++; +} + +void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) { + struct mg_ev_mgr_lwip_data *md = + (struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data; + while (md->sig_queue_len > 0) { + struct mg_connection *nc = md->sig_queue[md->start_index].nc; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + switch (md->sig_queue[md->start_index].sig) { + case MG_SIG_CONNECT_RESULT: { +#if MG_ENABLE_SSL + if (cs->err == 0 && (nc->flags & MG_F_SSL) && + !(nc->flags & MG_F_SSL_HANDSHAKE_DONE)) { + mg_lwip_ssl_do_hs(nc); + } else +#endif + { + mg_if_connect_cb(nc, cs->err); + } + break; + } + case MG_SIG_CLOSE_CONN: { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + mg_close_conn(nc); + break; + } + case MG_SIG_RECV: { + mg_lwip_handle_recv(nc); + break; + } + case MG_SIG_SENT_CB: { + if (cs->num_sent > 0) mg_if_sent_cb(nc, cs->num_sent); + cs->num_sent = 0; + break; + } + case MG_SIG_TOMBSTONE: { + break; + } + } + md->start_index = (md->start_index + 1) % MG_SIG_QUEUE_LEN; + md->sig_queue_len--; + } +} + +void mg_lwip_if_init(struct mg_iface *iface) { + LOG(LL_INFO, ("%p Mongoose init")); + iface->data = MG_CALLOC(1, sizeof(struct mg_ev_mgr_lwip_data)); +} + +void mg_lwip_if_free(struct mg_iface *iface) { + MG_FREE(iface->data); + iface->data = NULL; +} + +void mg_lwip_if_add_conn(struct mg_connection *nc) { + (void) nc; +} + +void mg_lwip_if_remove_conn(struct mg_connection *nc) { + struct mg_ev_mgr_lwip_data *md = + (struct mg_ev_mgr_lwip_data *) nc->iface->data; + /* Walk the queue and null-out further signals for this conn. */ + for (int i = 0; i < MG_SIG_QUEUE_LEN; i++) { + if (md->sig_queue[i].nc == nc) { + md->sig_queue[i].sig = MG_SIG_TOMBSTONE; + } + } +} + +time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { + struct mg_mgr *mgr = iface->mgr; + int n = 0; + double now = mg_time(); + struct mg_connection *nc, *tmp; + double min_timer = 0; + int num_timers = 0; +#if 0 + DBG(("begin poll @%u", (unsigned int) (now * 1000))); +#endif + mg_ev_mgr_lwip_process_signals(mgr); + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + tmp = nc->next; + n++; + if (nc->flags & MG_F_CLOSE_IMMEDIATELY) { + mg_close_conn(nc); + continue; + } + mg_if_poll(nc, now); + mg_if_timer(nc, now); + if (nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE) && + !(nc->flags & MG_F_WANT_WRITE)) { + mg_close_conn(nc); + continue; + } +#if MG_ENABLE_SSL + if ((nc->flags & MG_F_SSL) && cs != NULL && cs->pcb.tcp != NULL && + cs->pcb.tcp->state == ESTABLISHED) { + if (((nc->flags & MG_F_WANT_WRITE) || + (nc->send_mbuf.len > 0) && (nc->flags & MG_F_SSL_HANDSHAKE_DONE)) && + cs->pcb.tcp->snd_buf > 0) { + /* Can write more. */ + if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { + if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_send(nc); + } else { + mg_lwip_ssl_do_hs(nc); + } + } + if (cs->rx_chain != NULL || (nc->flags & MG_F_WANT_READ)) { + if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { + if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_recv(nc); + } else { + mg_lwip_ssl_do_hs(nc); + } + } + } else +#endif /* MG_ENABLE_SSL */ + { + if (!(nc->flags & (MG_F_CONNECTING | MG_F_UDP))) { + if (nc->send_mbuf.len > 0) mg_lwip_send_more(nc); + } + } + if (nc->sock != INVALID_SOCKET && + !(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != NULL && + cs->pcb.tcp->unsent != NULL) { + tcp_output(cs->pcb.tcp); + } + if (nc->ev_timer_time > 0) { + if (num_timers == 0 || nc->ev_timer_time < min_timer) { + min_timer = nc->ev_timer_time; + } + num_timers++; + } + } +#if 0 + DBG(("end poll @%u, %d conns, %d timers (min %u), next in %d ms", + (unsigned int) (now * 1000), n, num_timers, + (unsigned int) (min_timer * 1000), timeout_ms)); +#endif + (void) timeout_ms; + return now; +} + +uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) { + struct mg_connection *nc; + double now = mg_time(); + double min_timer = 0; + int num_timers = 0; + mg_ev_mgr_lwip_process_signals(mgr); + for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { + if (nc->ev_timer_time > 0) { + if (num_timers == 0 || nc->ev_timer_time < min_timer) { + min_timer = nc->ev_timer_time; + } + num_timers++; + } + } + uint32_t timeout_ms = ~0; + if (num_timers > 0) { + double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */; + if (timer_timeout_ms < timeout_ms) { + timeout_ms = timer_timeout_ms; + } + } + return timeout_ms; +} + +#endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/lwip/mg_lwip_ssl_if.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_SSL && MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL + +/* Amalgamated: #include "common/cs_dbg.h" */ + +#include +#include + +#ifndef MG_LWIP_SSL_IO_SIZE +#define MG_LWIP_SSL_IO_SIZE 1024 +#endif + +/* + * Stop processing incoming SSL traffic when recv_mbuf.size is this big. + * It'a a uick solution for SSL recv pushback. + */ +#ifndef MG_LWIP_SSL_RECV_MBUF_LIMIT +#define MG_LWIP_SSL_RECV_MBUF_LIMIT 3072 +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +void mg_lwip_ssl_do_hs(struct mg_connection *nc) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + int server_side = (nc->listener != NULL); + enum mg_ssl_if_result res; + if (nc->flags & MG_F_CLOSE_IMMEDIATELY) return; + res = mg_ssl_if_handshake(nc); + DBG(("%p %d %d %d", nc, nc->flags, server_side, res)); + if (res != MG_SSL_OK) { + if (res == MG_SSL_WANT_WRITE) { + nc->flags |= MG_F_WANT_WRITE; + cs->err = 0; + } else if (res == MG_SSL_WANT_READ) { + /* + * Nothing to do in particular, we are callback-driven. + * What we definitely do not need anymore is SSL reading (nothing left). + */ + nc->flags &= ~MG_F_WANT_READ; + cs->err = 0; + } else { + cs->err = res; + if (server_side) { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + } else { + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); + } + } + } else { + cs->err = 0; + nc->flags &= ~MG_F_WANT_WRITE; + /* + * Handshake is done. Schedule a read immediately to consume app data + * which may already be waiting. + */ + nc->flags |= (MG_F_SSL_HANDSHAKE_DONE | MG_F_WANT_READ); + if (server_side) { + mg_lwip_accept_conn(nc, cs->pcb.tcp); + } else { + mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); + } + } +} + +void mg_lwip_ssl_send(struct mg_connection *nc) { + if (nc->sock == INVALID_SOCKET) { + DBG(("%p invalid socket", nc)); + return; + } + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + /* It's ok if the buffer is empty. Return value of 0 may also be valid. */ + int len = cs->last_ssl_write_size; + if (len == 0) { + len = MIN(MG_LWIP_SSL_IO_SIZE, nc->send_mbuf.len); + } + int ret = mg_ssl_if_write(nc, nc->send_mbuf.buf, len); + DBG(("%p SSL_write %u = %d, %d", nc, len, ret)); + if (ret > 0) { + mbuf_remove(&nc->send_mbuf, ret); + mbuf_trim(&nc->send_mbuf); + cs->last_ssl_write_size = 0; + } else if (ret < 0) { + /* This is tricky. We must remember the exact data we were sending to retry + * exactly the same send next time. */ + cs->last_ssl_write_size = len; + } + if (ret == len) { + nc->flags &= ~MG_F_WANT_WRITE; + } else if (ret == MG_SSL_WANT_WRITE) { + nc->flags |= MG_F_WANT_WRITE; + } else { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + } +} + +void mg_lwip_ssl_recv(struct mg_connection *nc) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + /* Don't deliver data before connect callback */ + if (nc->flags & MG_F_CONNECTING) return; + while (nc->recv_mbuf.len < MG_LWIP_SSL_RECV_MBUF_LIMIT) { + char *buf = (char *) malloc(MG_LWIP_SSL_IO_SIZE); + if (buf == NULL) return; + int ret = mg_ssl_if_read(nc, buf, MG_LWIP_SSL_IO_SIZE); + DBG(("%p %p SSL_read %u = %d", nc, cs->rx_chain, MG_LWIP_SSL_IO_SIZE, ret)); + if (ret <= 0) { + free(buf); + if (ret == MG_SSL_WANT_WRITE) { + nc->flags |= MG_F_WANT_WRITE; + return; + } else if (ret == MG_SSL_WANT_READ) { + /* + * Nothing to do in particular, we are callback-driven. + * What we definitely do not need anymore is SSL reading (nothing left). + */ + nc->flags &= ~MG_F_WANT_READ; + cs->err = 0; + return; + } else { + mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); + return; + } + } else { + mg_if_recv_tcp_cb(nc, buf, ret, 1 /* own */); + } + } +} + +#ifdef KR_VERSION + +ssize_t kr_send(int fd, const void *buf, size_t len) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd; + int ret = mg_lwip_tcp_write(cs->nc, buf, len); + DBG(("%p mg_lwip_tcp_write %u = %d", cs->nc, len, ret)); + if (ret == 0) ret = KR_IO_WOULDBLOCK; + return ret; +} + +ssize_t kr_recv(int fd, void *buf, size_t len) { + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd; + struct pbuf *seg = cs->rx_chain; + if (seg == NULL) { + DBG(("%u - nothing to read", len)); + return KR_IO_WOULDBLOCK; + } + size_t seg_len = (seg->len - cs->rx_offset); + DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len)); + len = MIN(len, seg_len); + pbuf_copy_partial(seg, buf, len, cs->rx_offset); + cs->rx_offset += len; + tcp_recved(cs->pcb.tcp, len); + if (cs->rx_offset == cs->rx_chain->len) { + cs->rx_chain = pbuf_dechain(cs->rx_chain); + pbuf_free(seg); + cs->rx_offset = 0; + } + return len; +} + +#elif MG_SSL_IF == MG_SSL_IF_MBEDTLS + +int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len) { + struct mg_connection *nc = (struct mg_connection *) ctx; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + int ret = mg_lwip_tcp_write(cs->nc, buf, len); + DBG(("%p mg_lwip_tcp_write %u = %d", cs->nc, len, ret)); + if (ret == 0) ret = MBEDTLS_ERR_SSL_WANT_WRITE; + return ret; +} + +int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) { + struct mg_connection *nc = (struct mg_connection *) ctx; + struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; + struct pbuf *seg = cs->rx_chain; + if (seg == NULL) { + DBG(("%u - nothing to read", len)); + return MBEDTLS_ERR_SSL_WANT_READ; + } + size_t seg_len = (seg->len - cs->rx_offset); + DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len)); + len = MIN(len, seg_len); + pbuf_copy_partial(seg, buf, len, cs->rx_offset); + cs->rx_offset += len; + /* TCP PCB may be NULL if connection has already been closed + * but we still have data to deliver to SSL. */ + if (cs->pcb.tcp != NULL) tcp_recved(cs->pcb.tcp, len); + if (cs->rx_offset == cs->rx_chain->len) { + cs->rx_chain = pbuf_dechain(cs->rx_chain); + pbuf_free(seg); + cs->rx_offset = 0; + } + return len; +} + +#endif + +#endif /* MG_ENABLE_SSL && MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/wince/wince_libc.c" +#endif +/* + * Copyright (c) 2016 Cesanta Software Limited + * All rights reserved + */ + +#ifdef WINCE + +const char *strerror(int err) { + /* + * TODO(alashkin): there is no strerror on WinCE; + * look for similar wce_xxxx function + */ + static char buf[10]; + snprintf(buf, sizeof(buf), "%d", err); + return buf; +} + +int open(const char *filename, int oflag, int pmode) { + /* + * TODO(alashkin): mg_open function is not used in mongoose + * but exists in documentation as utility function + * Shall we delete it at all or implement for WinCE as well? + */ + DebugBreak(); + return 0; /* for compiler */ +} + +int _wstati64(const wchar_t *path, cs_stat_t *st) { + DWORD fa = GetFileAttributesW(path); + if (fa == INVALID_FILE_ATTRIBUTES) { + return -1; + } + memset(st, 0, sizeof(*st)); + if ((fa & FILE_ATTRIBUTE_DIRECTORY) == 0) { + HANDLE h; + FILETIME ftime; + st->st_mode |= _S_IFREG; + h = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) { + return -1; + } + st->st_size = GetFileSize(h, NULL); + GetFileTime(h, NULL, NULL, &ftime); + st->st_mtime = (uint32_t)((((uint64_t) ftime.dwLowDateTime + + ((uint64_t) ftime.dwHighDateTime << 32)) / + 10000000.0) - + 11644473600); + CloseHandle(h); + } else { + st->st_mode |= _S_IFDIR; + } + return 0; +} + +/* Windows CE doesn't have neither gmtime nor strftime */ +static void mg_gmt_time_string(char *buf, size_t buf_len, time_t *t) { + FILETIME ft; + SYSTEMTIME systime; + if (t != NULL) { + uint64_t filetime = (*t + 11644473600) * 10000000; + ft.dwLowDateTime = filetime & 0xFFFFFFFF; + ft.dwHighDateTime = (filetime & 0xFFFFFFFF00000000) >> 32; + FileTimeToSystemTime(&ft, &systime); + } else { + GetSystemTime(&systime); + } + /* There is no PRIu16 in WinCE SDK */ + snprintf(buf, buf_len, "%d.%d.%d %d:%d:%d GMT", (int) systime.wYear, + (int) systime.wMonth, (int) systime.wDay, (int) systime.wHour, + (int) systime.wMinute, (int) systime.wSecond); +} + +#endif +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/pic32/pic32_net_if.h" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#ifndef CS_COMMON_PLATFORMS_PIC32_NET_IF_H_ +#define CS_COMMON_PLATFORMS_PIC32_NET_IF_H_ + +/* Amalgamated: #include "mongoose/src/net_if.h" */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MG_ENABLE_NET_IF_PIC32 +#define MG_ENABLE_NET_IF_PIC32 MG_NET_IF == MG_NET_IF_PIC32 +#endif + +extern struct mg_iface_vtable mg_pic32_iface_vtable; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CS_COMMON_PLATFORMS_PIC32_NET_IF_H_ */ +#ifdef MG_MODULE_LINES +#line 1 "common/platforms/pic32/pic32_net_if.c" +#endif +/* + * Copyright (c) 2014-2016 Cesanta Software Limited + * All rights reserved + */ + +#if MG_ENABLE_NET_IF_PIC32 + +int mg_pic32_if_create_conn(struct mg_connection *nc) { + (void) nc; + return 1; +} + +void mg_pic32_if_recved(struct mg_connection *nc, size_t len) { + (void) nc; + (void) len; +} + +void mg_pic32_if_add_conn(struct mg_connection *nc) { + (void) nc; +} + +void mg_pic32_if_init(struct mg_iface *iface) { + (void) iface; + (void) mg_get_errno(); /* Shutup compiler */ +} + +void mg_pic32_if_free(struct mg_iface *iface) { + (void) iface; +} + +void mg_pic32_if_remove_conn(struct mg_connection *nc) { + (void) nc; +} + +void mg_pic32_if_destroy_conn(struct mg_connection *nc) { + if (nc->sock == INVALID_SOCKET) return; + /* For UDP, only close outgoing sockets or listeners. */ + if (!(nc->flags & MG_F_UDP)) { + /* Close TCP */ + TCPIP_TCP_Close((TCP_SOCKET) nc->sock); + } else if (nc->listener == NULL) { + /* Only close outgoing UDP or listeners. */ + TCPIP_UDP_Close((UDP_SOCKET) nc->sock); + } + + nc->sock = INVALID_SOCKET; +} + +int mg_pic32_if_listen_udp(struct mg_connection *nc, union socket_address *sa) { + nc->sock = TCPIP_UDP_ServerOpen( + sa->sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4 + : IP_ADDRESS_TYPE_IPV6, + ntohs(sa->sin.sin_port), + sa->sin.sin_addr.s_addr == 0 ? 0 : (IP_MULTI_ADDRESS *) &sa->sin); + if (nc->sock == INVALID_SOCKET) { + return -1; + } + return 0; +} + +void mg_pic32_if_udp_send(struct mg_connection *nc, const void *buf, + size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); +} + +void mg_pic32_if_tcp_send(struct mg_connection *nc, const void *buf, + size_t len) { + mbuf_append(&nc->send_mbuf, buf, len); +} + +int mg_pic32_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) { + nc->sock = TCPIP_TCP_ServerOpen( + sa->sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4 + : IP_ADDRESS_TYPE_IPV6, + ntohs(sa->sin.sin_port), + sa->sin.sin_addr.s_addr == 0 ? 0 : (IP_MULTI_ADDRESS *) &sa->sin); + memcpy(&nc->sa, sa, sizeof(*sa)); + if (nc->sock == INVALID_SOCKET) { + return -1; + } + return 0; +} + +static int mg_accept_conn(struct mg_connection *lc) { + struct mg_connection *nc; + TCP_SOCKET_INFO si; + union socket_address sa; + + nc = mg_if_accept_new_conn(lc); + + if (nc == NULL) { + return 0; + } + + nc->sock = lc->sock; + nc->flags &= ~MG_F_LISTENING; + + if (!TCPIP_TCP_SocketInfoGet((TCP_SOCKET) nc->sock, &si)) { + return 0; + } + + if (si.addressType == IP_ADDRESS_TYPE_IPV4) { + sa.sin.sin_family = AF_INET; + sa.sin.sin_port = htons(si.remotePort); + sa.sin.sin_addr.s_addr = si.remoteIPaddress.v4Add.Val; + } else { + /* TODO(alashkin): do something with _potential_ IPv6 */ + memset(&sa, 0, sizeof(sa)); + } + + mg_if_accept_tcp_cb(nc, (union socket_address *) &sa, sizeof(sa)); + + return mg_pic32_if_listen_tcp(lc, &lc->sa) >= 0; +} + +char *inet_ntoa(struct in_addr in) { + static char addr[17]; + snprintf(addr, sizeof(addr), "%d.%d.%d.%d", (int) in.S_un.S_un_b.s_b1, + (int) in.S_un.S_un_b.s_b2, (int) in.S_un.S_un_b.s_b3, + (int) in.S_un.S_un_b.s_b4); + return addr; +} + +static void mg_handle_send(struct mg_connection *nc) { + uint16_t bytes_written = 0; + if (nc->flags & MG_F_UDP) { + if (!TCPIP_UDP_RemoteBind( + (UDP_SOCKET) nc->sock, + nc->sa.sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4 + : IP_ADDRESS_TYPE_IPV6, + ntohs(nc->sa.sin.sin_port), (IP_MULTI_ADDRESS *) &nc->sa.sin)) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + return; + } + bytes_written = TCPIP_UDP_TxPutIsReady((UDP_SOCKET) nc->sock, 0); + if (bytes_written >= nc->send_mbuf.len) { + if (TCPIP_UDP_ArrayPut((UDP_SOCKET) nc->sock, + (uint8_t *) nc->send_mbuf.buf, + nc->send_mbuf.len) != nc->send_mbuf.len) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + bytes_written = 0; + } + } + } else { + bytes_written = TCPIP_TCP_FifoTxFreeGet((TCP_SOCKET) nc->sock); + if (bytes_written != 0) { + if (bytes_written > nc->send_mbuf.len) { + bytes_written = nc->send_mbuf.len; + } + if (TCPIP_TCP_ArrayPut((TCP_SOCKET) nc->sock, + (uint8_t *) nc->send_mbuf.buf, + bytes_written) != bytes_written) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + bytes_written = 0; + } + } + } + + if (bytes_written != 0) { + mbuf_remove(&nc->send_mbuf, bytes_written); + mg_if_sent_cb(nc, bytes_written); + } +} + +static void mg_handle_recv(struct mg_connection *nc) { + uint16_t bytes_read = 0; + uint8_t *buf = NULL; + if (nc->flags & MG_F_UDP) { + bytes_read = TCPIP_UDP_GetIsReady((UDP_SOCKET) nc->sock); + if (bytes_read != 0 && + (nc->recv_mbuf_limit == -1 || + nc->recv_mbuf.len + bytes_read < nc->recv_mbuf_limit)) { + buf = (uint8_t *) MG_MALLOC(bytes_read); + if (TCPIP_UDP_ArrayGet((UDP_SOCKET) nc->sock, buf, bytes_read) != + bytes_read) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + bytes_read = 0; + MG_FREE(buf); + } + } + } else { + bytes_read = TCPIP_TCP_GetIsReady((TCP_SOCKET) nc->sock); + if (bytes_read != 0) { + if (nc->recv_mbuf_limit != -1 && + nc->recv_mbuf_limit - nc->recv_mbuf.len > bytes_read) { + bytes_read = nc->recv_mbuf_limit - nc->recv_mbuf.len; + } + buf = (uint8_t *) MG_MALLOC(bytes_read); + if (TCPIP_TCP_ArrayGet((TCP_SOCKET) nc->sock, buf, bytes_read) != + bytes_read) { + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + MG_FREE(buf); + bytes_read = 0; + } + } + } + + if (bytes_read != 0) { + mg_if_recv_tcp_cb(nc, buf, bytes_read, 1 /* own */); + } +} + +time_t mg_pic32_if_poll(struct mg_iface *iface, int timeout_ms) { + struct mg_mgr *mgr = iface->mgr; + double now = mg_time(); + struct mg_connection *nc, *tmp; + + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + tmp = nc->next; + + if (nc->flags & MG_F_CONNECTING) { + /* processing connections */ + if (nc->flags & MG_F_UDP || + TCPIP_TCP_IsConnected((TCP_SOCKET) nc->sock)) { + mg_if_connect_cb(nc, 0); + } + } else if (nc->flags & MG_F_LISTENING) { + if (TCPIP_TCP_IsConnected((TCP_SOCKET) nc->sock)) { + /* accept new connections */ + mg_accept_conn(nc); + } + } else { + if (nc->send_mbuf.len != 0) { + mg_handle_send(nc); + } + + if (nc->recv_mbuf_limit == -1 || + nc->recv_mbuf.len < nc->recv_mbuf_limit) { + mg_handle_recv(nc); + } + } + } + + for (nc = mgr->active_connections; nc != NULL; nc = tmp) { + tmp = nc->next; + if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) || + (nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) { + mg_close_conn(nc); + } + } + + return now; +} + +void mg_pic32_if_sock_set(struct mg_connection *nc, sock_t sock) { + nc->sock = sock; +} + +void mg_pic32_if_get_conn_addr(struct mg_connection *nc, int remote, + union socket_address *sa) { + /* TODO(alaskin): not implemented yet */ +} + +void mg_pic32_if_connect_tcp(struct mg_connection *nc, + const union socket_address *sa) { + nc->sock = TCPIP_TCP_ClientOpen( + sa->sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4 + : IP_ADDRESS_TYPE_IPV6, + ntohs(sa->sin.sin_port), (IP_MULTI_ADDRESS *) &sa->sin); + nc->err = (nc->sock == INVALID_SOCKET) ? -1 : 0; +} + +void mg_pic32_if_connect_udp(struct mg_connection *nc) { + nc->sock = TCPIP_UDP_ClientOpen(IP_ADDRESS_TYPE_ANY, 0, NULL); + nc->err = (nc->sock == INVALID_SOCKET) ? -1 : 0; +} + +/* clang-format off */ +#define MG_PIC32_IFACE_VTABLE \ + { \ + mg_pic32_if_init, \ + mg_pic32_if_free, \ + mg_pic32_if_add_conn, \ + mg_pic32_if_remove_conn, \ + mg_pic32_if_poll, \ + mg_pic32_if_listen_tcp, \ + mg_pic32_if_listen_udp, \ + mg_pic32_if_connect_tcp, \ + mg_pic32_if_connect_udp, \ + mg_pic32_if_tcp_send, \ + mg_pic32_if_udp_send, \ + mg_pic32_if_recved, \ + mg_pic32_if_create_conn, \ + mg_pic32_if_destroy_conn, \ + mg_pic32_if_sock_set, \ + mg_pic32_if_get_conn_addr, \ + } +/* clang-format on */ + +struct mg_iface_vtable mg_pic32_iface_vtable = MG_PIC32_IFACE_VTABLE; +#if MG_NET_IF == MG_NET_IF_PIC32 +struct mg_iface_vtable mg_default_iface_vtable = MG_PIC32_IFACE_VTABLE; +#endif + +#endif /* MG_ENABLE_NET_IF_PIC32 */ diff --git a/build_http/readme.md b/build_http/readme.md new file mode 100644 index 0000000..a6877f4 --- /dev/null +++ b/build_http/readme.md @@ -0,0 +1,6 @@ +此工程文件夹是用于构建http服务的 +功能: +1、接收APP分配下来的设备ID,保存与DEVICE_ID文件中 + 端口:10000 +2、接收APP下发的用于透传给传感器的气压计校准命令,并将传感器应答返回给APP + 端口:11000 \ No newline at end of file diff --git a/chuankou2/build.sh b/chuankou2/build.sh new file mode 100644 index 0000000..4eaa1a0 --- /dev/null +++ b/chuankou2/build.sh @@ -0,0 +1 @@ +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -o testprogram chuankou.cpp -I/home/atk/curl/libcurl/include -L/home/atk/curl/libcurl/lib -lcurl -lrt -lpthread \ No newline at end of file diff --git a/chuankou2/chuankou.cpp b/chuankou2/chuankou.cpp new file mode 100644 index 0000000..0b8a8ad --- /dev/null +++ b/chuankou2/chuankou.cpp @@ -0,0 +1,376 @@ +/* +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -o testprogram chuankou.c -I/home/atk/curl/libcurl/include -L/home/atk/curl/libcurl/lib -lcurl +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -o testprogram chuankou.cpp -I/home/atk/curl/libcurl/include -L/home/atk/curl/libcurl/lib -lcurl +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include +#include + +#define SERIAL_PORT "/dev/ttyS0" +#define BAUD_RATE B115200 +#define pipeName "/tmp/Elevator_pipe" + +std::string BASE_URL_string; +#define URL_FILE "/demo/bin/URL/SerialUploaderURL" +#define API_ENDPOINT "/system/redis/test" +static bool quit = false; + +// 函数用于读取文件并将其内容保存在全局字符串变量中 +void readFileAndStoreInGlobal(const std::string& filename, std::string& destination) { + std::ifstream file(filename); + + if (file.is_open()) { + std::getline(file, destination); // 读取一行并存储在全局字符串中 + file.close(); + } else { + std::cerr << "无法打开文件: " << filename << std::endl; + } +} + + + +size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::vector* response) { + size_t totalSize = size * nmemb; + unsigned char* data = static_cast(contents); + response->insert(response->end(), data, data + totalSize); + return totalSize; +} + +void sendToServer(const char* hexData) { + char command[1024]; + snprintf(command, sizeof(command), "curl -s -X POST -H 'Content-Type: text/plain' -d '%s' http://192.168.0.190:5000/receive_hex -o res.txt", hexData); + system(command); +} + +void uploadByteArray(const std::vector& byteArray) { + // 初始化CURL对象 + CURL* curl = curl_easy_init(); + if (!curl) { + // 处理初始化失败的情况 + return; + } + + // 创建表单数据 + struct curl_httppost* form = nullptr; + struct curl_httppost* last = nullptr; + + // 添加字节数组作为表单字段 + curl_formadd(&form, &last, + CURLFORM_COPYNAME, "name", // 字段名 + CURLFORM_PTRCONTENTS, byteArray.data(), // 字节数组的数据指针 + CURLFORM_CONTENTSLENGTH, byteArray.size(), // 字节数组的长度 + CURLFORM_END); + + // 设置请求URL + curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/upload"); + + // 设置POST请求和表单数据 + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_HTTPPOST, form); + + // 执行请求 + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + // 处理请求执行失败的情况 + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + } + + // 清理资源 + curl_easy_cleanup(curl); + curl_formfree(form); +} + +void curlToServer(const char* hexData, std::vector& response) { + CURL *curl; + CURLcode res; + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + if(curl) + { + char postData[512];//建立缓冲区 + sprintf(postData, "%s", hexData); //把hexData写入缓冲区 + // curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.190:5000/receive_hex"); + curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.68.173:9080/system/redis/test"); + + /* Now specify the POST data */ + struct curl_slist *plist = NULL; + plist = curl_slist_append(plist, "Content-Type:application/json;charset=UTF-8"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, plist); + + + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData); + // std::cout << szJsonData << std::endl; + + // 设置响应回调函数和缓冲区 + // 创建一个用于存储返回数据的 unsigned char 数组 + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + std::cout <(c) << " "; + } + std::cout << std::endl; + } + // /* always cleanup */ + curl_easy_cleanup(curl); + } +} +//判断管道是否存在 +bool isPipeExists(const char* pipe_Name) { + return (access(pipe_Name, F_OK) == 0); +} + +//通过命名管道的方式 +int updateElevatorStatus(const char* status){ + // const char* pipeName = "/tmp/Elevator_pipe"; // 定义命名管道的路径 + // 创建命名管道 + // if(!isPipeExists(pipeName)){ + // mkfifo(pipeName, 0777); + // } + // 打开管道进行写入 + int fd = open(pipeName, O_WRONLY); + + if (fd == -1) { + std::cerr << "Failed to open the pipe for writing." << std::endl; + return 1; + } + std::string message = status; + write(fd, message.c_str(), strlen(message.c_str()) + 1); + std::cout << "Hello, Process B!" <& response) { + CURL *curl; + CURLcode res; + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + if(curl) + { + char postData[512];//建立缓冲区 + sprintf(postData, "%s", hexData); //把hexData写入缓冲区 + // curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.190:5000/receive_hex"); + // curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.68.173:9080/system/redis/test"); + // std::string uploader_url = BASE_URL_string + API_ENDPOINT; + std::string uploader_url = BASE_URL_string; + std::cout<< uploader_url << std::endl; + // curl_easy_setopt(curl, CURLOPT_URL, "http://36.108.213.190:10004/system/redis/test"); + curl_easy_setopt(curl, CURLOPT_URL, uploader_url.c_str()); + + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); + + struct curl_httppost* form = NULL; + struct curl_httppost* lastptr = NULL; + curl_formadd(&form, &lastptr, + CURLFORM_COPYNAME, "name", + CURLFORM_COPYCONTENTS, postData, + CURLFORM_END); + + struct curl_slist* headers = NULL; + headers = curl_slist_append(headers, "Content-Type: multipart/form-data"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + curl_easy_setopt(curl, CURLOPT_HTTPPOST, form); + // 设置响应回调函数和缓冲区 + // 创建一个用于存储返回数据的 unsigned char 数组 + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + fprintf(stderr, "res: %s\n", curl_easy_strerror(res)); + /* Check for errors */ + if(res != CURLE_OK){ + fprintf(stderr, "curl_easy_perform() passmessage failed: %s\n",curl_easy_strerror(res)); + } else { + for (unsigned char c : response) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(c) << " "; + } + std::cout << std::endl; + } + // /* always cleanup */ + curl_easy_cleanup(curl); + } +} + +void signal_handler(int signo) { + if (signo == SIGINT || signo == SIGTERM) { + quit = true; + } +} + +int main() { + signal(SIGINT, signal_handler); // SIGINT 对应Ctrl+C + signal(SIGTERM, signal_handler); // SIGTERM 对应kill或pkill + + readFileAndStoreInGlobal(URL_FILE, BASE_URL_string); + + struct timespec abs_timeout; + + + // 打开或创建命名信号量 + sem_t *my_semaphore = sem_open("/my_semaphore", O_CREAT, 0644, 1); + // sem_t *my_semaphore = sem_open("/my_semaphore", 0); + + if (my_semaphore == SEM_FAILED) { + perror("sem_open"); + } + + int serialPort = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + if (serialPort == -1) { + printf("Failed to open serial port: %s\n", SERIAL_PORT); + return 1; + } + + struct termios tty; + memset(&tty, 0, sizeof(tty)); + if (tcgetattr(serialPort, &tty) != 0) { + printf("Failed to get serial port attributes\n"); + close(serialPort); + return 1; + } + cfsetospeed(&tty, BAUD_RATE); + cfsetispeed(&tty, BAUD_RATE); + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; + tty.c_cflag &= ~(PARENB | PARODD); + tty.c_cflag &= ~CSTOPB; + tty.c_cflag |= CREAD | CLOCAL; + tty.c_iflag = IGNPAR; + tty.c_oflag = 0; + tty.c_lflag = 0; + if (tcsetattr(serialPort, TCSANOW, &tty) != 0) { + printf("Failed to set serial port attributes\n"); + close(serialPort); + return 1; + } + + char buffer[255]; + ssize_t bytesRead; + + // 创建命名管道 + if(!isPipeExists(pipeName)){ + mkfifo(pipeName, 0777); + } + int i = 50001; + while (!quit) { + + // if(sleep(0.1) != 0){ + // printf("被中断\n"); + // } + + clock_gettime(CLOCK_REALTIME, &abs_timeout); + abs_timeout.tv_sec += 5; // 增加 5 秒的超时时间 + + if (sem_timedwait(my_semaphore, &abs_timeout) == -1) { + if (errno == ETIMEDOUT) { + // 在这里处理等待超时的情况 + printf("等待超时\n"); + // perror("sem_timedwait"); + } else { + perror("sem_timedwait"); + } + continue; + + } + + // sem_wait(my_semaphore); + + + bytesRead = read(serialPort, buffer, sizeof(buffer)); + i++; + if(i%50000==0){ + // printf(".\n"); + i = 50001; + } + + + + + if (bytesRead > 0) { + // 将二进制数据转换为十六进制字符串 + char hexData[1024]; + std::vector byteArray; + int i; + for (i = 0; i < bytesRead; i++) { + snprintf(&hexData[i * 2], sizeof(hexData) - i * 2, "%02X", buffer[i]); + byteArray.push_back(static_cast(buffer[i])); + } + + printf("Received data: %s\n", hexData); + for (unsigned char c : byteArray) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(c) << " "; + } + std::cout << std::endl; + + //解析部分 + if (byteArray.size() >= 16 && byteArray[15] == 0x01) { + // 第15个字节是1 + // 在这里编写处理逻辑 + std::cout << "功能码为0x01 数据上传" <= 24 && byteArray[23] == 0x00){ + // updateElevatorStatus("01"); + } + // else if (byteArray.size() >=24 && byteArray[23] == 0x80){ + + // } + } else if (byteArray.size() >= 16 && byteArray[15] == 0x02) + { + // 第15个字节不是1 + // 在这里编写处理逻辑 + std::cout << "功能码为0x02 心跳包" <= 16 && byteArray[15] == 0x03) + { + // 第15个字节不是1 + // 在这里编写处理逻辑 + std::cout << "功能码为0x03 版本号上传" < response; + // curlToServer(hexData,response); + curlToServer_GET(hexData,response); + // write(serialPort, response.data(), response.size()); + } + sem_post(my_semaphore); + // printf("出锁"); + } + + close(serialPort); + sem_close(my_semaphore); + printf("close serialPort and semaphore\n"); + + return 0; +} diff --git a/chuankou2/readme.md b/chuankou2/readme.md new file mode 100644 index 0000000..06ee3cf --- /dev/null +++ b/chuankou2/readme.md @@ -0,0 +1,5 @@ +此工程文件夹是用于构建串口透传服务的 +功能: + 读取串口信息,转发给服务器 +编译: + ./build.sh \ No newline at end of file diff --git a/chuankou2/testprogram b/chuankou2/testprogram new file mode 100644 index 0000000..1748874 Binary files /dev/null and b/chuankou2/testprogram differ diff --git a/rknn_yolo_demo/CMakeLists.txt b/rknn_yolo_demo/CMakeLists.txt new file mode 100644 index 0000000..426f102 --- /dev/null +++ b/rknn_yolo_demo/CMakeLists.txt @@ -0,0 +1,125 @@ +cmake_minimum_required(VERSION 3.8) + +project(rknn_yolo_demo_linux) +set(CMAKE_CXX_STANDARD 11) +add_definitions(-g -O0 -ggdb -gdwarf -funwind-tables -rdynamic) +add_definitions(-Wno-write-strings -Wno-return-type) + + +set(TOOLCHAIN_DIR /opt/atk-dlrv1126-toolchain) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-g++) +set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-gcc) +set(SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot/usr/include) +set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread") + +# for linux +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# for android +if (${TARGET_SOC} STREQUAL "RK3399PRO") + set(LIB_ARCH lib64) +endif() + +# rga +set(RGA_DIR ${MZ_ROOT}/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga) +include_directories(${RGA_DIR}/include) + +# drm +set(DRM_DIR ${MZ_ROOT}/libs/common/drm) +include_directories(${DRM_DIR}/include) +include_directories(${DRM_DIR}/include/libdrm) + +#stb +set(STB_DIR ${MZ_ROOT}/libs/common/) +include_directories(${STB_DIR}) + +# rknn api +if (${TARGET_SOC} STREQUAL "RK3399PRO") + set(RKNN_API_PATH ${MZ_ROOT}/libs/rklibs/RK3399Pro_npu/rknn-api/librknn_api) + include_directories(${RKNN_API_PATH}/include) + set(RKNN_API_LIB ${RKNN_API_PATH}/${CMAKE_SYSTEM_NAME}/${LIB_ARCH}/librknn_api.so) +else() + set(RKNN_API_PATH ${MZ_ROOT}/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api) + include_directories(${RKNN_API_PATH}/include) + set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) +endif() + +# libjpeg +set(LIBJPEG_DIR ${MZ_ROOT}/libs/platform/${TARGET_SOC}/libjpeg) +include_directories(${LIBJPEG_DIR}/include) +set(LIBJPEG_LIB ${LIBJPEG_DIR}/lib/${CMAKE_SYSTEM_NAME}/libjpeg.a) + +# libpng +set(LIBPNG_DIR ${MZ_ROOT}/libs/platform/${TARGET_SOC}/libpng) +include_directories(${LIBPNG_DIR}/include) +set(LIBPNG_LIB ${LIBPNG_DIR}/lib/${CMAKE_SYSTEM_NAME}/libpng.a) + +# zlib(used by libpng) +set(ZLIB_DIR ${MZ_ROOT}/libs/platform/${TARGET_SOC}/zlib) +include_directories(${ZLIB_DIR}/include) +set(ZLIB_LIB ${ZLIB_DIR}/lib/${CMAKE_SYSTEM_NAME}/libz.a) + +# #curl +include_directories(${CMAKE_SOURCE_DIR}/include) +# set(CURL_LIB /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so) + +link_directories(/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib) +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIR}) +message("CURL_LIBRARIES: ${CURL_LIBRARIES}") +message("CURL_INCLUDE_DIR: ${CURL_INCLUDE_DIR}") +find_package(OpenCV REQUIRED) + +set(OPENCV_LIBS opencv_core opencv_imgcodecs opencv_imgproc opencv_features2d opencv_flann opencv_highgui opencv_freetype) +set(RKNN_LIBS easymedia rga rkaiq sample_common_isp) + +link_directories(include lib) +link_directories(include ./include/librtsp) + +include_directories(${SYSROOT}) +include_directories(${SYSROOT}/rga) +include_directories(${SYSROOT}/easymedia) +include_directories(${SYSROOT}/rkaiq/uAPI) +include_directories(${SYSROOT}/rkaiq/xcore) +include_directories(${SYSROOT}/rkaiq/algos) +include_directories(${SYSROOT}/rkaiq/common) +include_directories(${SYSROOT}/rkaiq/iq_parser) +include_directories(./include/librtsp) + + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_yolo_demo_test + src/drm_func.c + src/rga_func.c + src/yolo.cc + src/main.cpp + ) + +target_link_libraries(rknn_yolo_demo_test + ${RKNN_API_LIB} + ${LIBJPEG_LIB} + ${LIBPNG_LIB} + ${ZLIB_LIB} + ${OPENCV_LIBS} + ${CURL_LIBRARIES} + librtsp.a + ${RKNN_LIBS} + dl +) +add_definitions(-DRKAIQ) +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_yolo_demo_test) +install(TARGETS rknn_yolo_demo_test DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) + + + diff --git a/rknn_yolo_demo/README.md b/rknn_yolo_demo/README.md new file mode 100644 index 0000000..130703f --- /dev/null +++ b/rknn_yolo_demo/README.md @@ -0,0 +1,2 @@ +由瑞芯微官方仓库rknn-model-zoo中的CV中的C-demo修改而来,由图片检测修改为视频检测,并按所需通信协议对服务器进行报警。 + diff --git a/rknn_yolo_demo/build.sh b/rknn_yolo_demo/build.sh new file mode 100644 index 0000000..4ee5777 --- /dev/null +++ b/rknn_yolo_demo/build.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +RV1109_TOOL_CHAIN="/opt/atk-dlrv1126-toolchain" + + +# for rv1109/rv1126 armhf +GCC_COMPILER=${RV1109_TOOL_CHAIN}/usr/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# model_zoo_path root path +MZ_ROOT=$(pwd | sed 's/\(rknn_model_zoo-main\).*/\1/g') +echo $MZ_ROOT +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ \ + -DMZ_ROOT=${MZ_ROOT} \ + -DTARGET_SOC=RV1109_1126 \ + -DCMAKE_SYSTEM_NAME=Linux +make -j4 +make install +cd .. + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ \ + -DMZ_ROOT=${MZ_ROOT} \ + -DTARGET_SOC=RV1109_1126 \ + -DCMAKE_SYSTEM_NAME=Linux +make -j4 +make install + diff --git a/rknn_yolo_demo/build/CMakeCache.txt b/rknn_yolo_demo/build/CMakeCache.txt new file mode 100644 index 0000000..308ffdb --- /dev/null +++ b/rknn_yolo_demo/build/CMakeCache.txt @@ -0,0 +1,466 @@ +# This is the CMakeCache file. +# For build in directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//No help, variable specified on the command line. +CMAKE_CXX_COMPILER:UNINITIALIZED=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ar + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ranlib + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//No help, variable specified on the command line. +CMAKE_C_COMPILER:UNINITIALIZED=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ar + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ranlib + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/pkgRedirects + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=rknn_yolo_demo_linux + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Linux + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//The directory containing a CMake configuration file for CURL. +CURL_DIR:PATH=CURL_DIR-NOTFOUND + +//Path to a file. +CURL_INCLUDE_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +//Path to a library. +CURL_LIBRARY_DEBUG:FILEPATH=CURL_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +CURL_LIBRARY_RELEASE:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so + +//No help, variable specified on the command line. +MZ_ROOT:UNINITIALIZED=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo + +//Path to a library. +OPENCV_CORE_LIBRARY:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_core.so + +//The directory containing a CMake configuration file for OpenCV. +OpenCV_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV + +//Arguments to supply to pkg-config +PKG_CONFIG_ARGN:STRING= + +//pkg-config executable +PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config + +//No help, variable specified on the command line. +TARGET_SOC:UNINITIALIZED=RV1109_1126 + +//Path to a library. +pkgcfg_lib_PC_CURL_curl:FILEPATH=/usr/lib/x86_64-linux-gnu/libcurl.so + +//Value Computed by CMake +rknn_yolo_demo_linux_BINARY_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build + +//Value Computed by CMake +rknn_yolo_demo_linux_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +rknn_yolo_demo_linux_SOURCE_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=16 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=3 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.16 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_DIR +CURL_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_INCLUDE_DIR +CURL_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_DEBUG +CURL_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_RELEASE +CURL_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//Details about finding CURL +FIND_PACKAGE_MESSAGE_DETAILS_CURL:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so][/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include][c ][v7.68.0()] +//Details about finding OpenCV +FIND_PACKAGE_MESSAGE_DETAILS_OpenCV:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr][v3.4.12()] +PC_CURL_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_CFLAGS_I:INTERNAL= +PC_CURL_CFLAGS_OTHER:INTERNAL= +PC_CURL_FOUND:INTERNAL=1 +PC_CURL_INCLUDEDIR:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lcurl +PC_CURL_LDFLAGS_OTHER:INTERNAL= +PC_CURL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBRARIES:INTERNAL=curl +PC_CURL_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBS:INTERNAL= +PC_CURL_LIBS_L:INTERNAL= +PC_CURL_LIBS_OTHER:INTERNAL= +PC_CURL_LIBS_PATHS:INTERNAL= +PC_CURL_MODULE_NAME:INTERNAL=libcurl +PC_CURL_PREFIX:INTERNAL=/usr +PC_CURL_STATIC_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_CFLAGS_I:INTERNAL= +PC_CURL_STATIC_CFLAGS_OTHER:INTERNAL= +PC_CURL_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-L/usr/lib/x86_64-linux-gnu/mit-krb5;-lcurl;-lnghttp2;-lidn2;-lrtmp;-lssh;-lpsl;-lssl;-lcrypto;-lssl;-lcrypto;-Wl,-Bsymbolic-functions;-Wl,-z,relro;-lgssapi_krb5;-lkrb5;-lk5crypto;-lcom_err;-llber;-lldap;-llber;-lbrotlidec;-lz +PC_CURL_STATIC_LDFLAGS_OTHER:INTERNAL=-Wl,-Bsymbolic-functions;-Wl,-z,relro +PC_CURL_STATIC_LIBDIR:INTERNAL= +PC_CURL_STATIC_LIBRARIES:INTERNAL=curl;nghttp2;idn2;rtmp;ssh;psl;ssl;crypto;ssl;crypto;gssapi_krb5;krb5;k5crypto;com_err;lber;ldap;lber;brotlidec;z +PC_CURL_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu;/usr/lib/x86_64-linux-gnu/mit-krb5 +PC_CURL_STATIC_LIBS:INTERNAL= +PC_CURL_STATIC_LIBS_L:INTERNAL= +PC_CURL_STATIC_LIBS_OTHER:INTERNAL= +PC_CURL_STATIC_LIBS_PATHS:INTERNAL= +PC_CURL_VERSION:INTERNAL=7.68.0 +PC_CURL_libcurl_INCLUDEDIR:INTERNAL= +PC_CURL_libcurl_LIBDIR:INTERNAL= +PC_CURL_libcurl_PREFIX:INTERNAL= +PC_CURL_libcurl_VERSION:INTERNAL= +//ADVANCED property for variable: PKG_CONFIG_ARGN +PKG_CONFIG_ARGN-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE +PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1 +//linker supports push/pop state +_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED:INTERNAL=TRUE +__pkg_config_arguments_PC_CURL:INTERNAL=QUIET;libcurl +__pkg_config_checked_PC_CURL:INTERNAL=1 +//ADVANCED property for variable: pkgcfg_lib_PC_CURL_curl +pkgcfg_lib_PC_CURL_curl-ADVANCED:INTERNAL=1 +prefix_result:INTERNAL=SSL;IPv6;UnixSockets;libz;brotli;AsynchDNS;IDN;GSS-API;PSL;SPNEGO;Kerberos;NTLM;NTLM_WB;TLS-SRP;HTTP2;HTTPS-proxy + diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeCCompiler.cmake b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeCCompiler.cmake new file mode 100644 index 0000000..fa3e4fd --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeCCompiler.cmake @@ -0,0 +1,76 @@ +set(CMAKE_C_COMPILER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "8.3.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_C_SIMULATE_VERSION "") + + + +set(CMAKE_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ar") +set(CMAKE_C_COMPILER_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ar") +set(CMAKE_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ranlib") +set(CMAKE_LINKER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "4") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeCXXCompiler.cmake b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..8414d6b --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeCXXCompiler.cmake @@ -0,0 +1,88 @@ +set(CMAKE_CXX_COMPILER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "8.3.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + +set(CMAKE_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ar") +set(CMAKE_CXX_COMPILER_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ar") +set(CMAKE_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ranlib") +set(CMAKE_LINKER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "4") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_C.bin b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000..cce5297 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_C.bin differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_CXX.bin b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_CXX.bin new file mode 100644 index 0000000..a2d15bb Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeSystem.cmake b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeSystem.cmake new file mode 100644 index 0000000..d54a30d --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-5.15.0-91-generic") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "5.15.0-91-generic") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "") +set(CMAKE_SYSTEM_PROCESSOR "") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/CMakeCCompilerId.c b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..d884b50 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,671 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if !defined(__STDC__) +# if (defined(_MSC_VER) && !defined(__clang__)) \ + || (defined(__ibmxl__) || defined(__IBMC__)) +# define C_DIALECT "90" +# else +# define C_DIALECT +# endif +#elif __STDC_VERSION__ >= 201000L +# define C_DIALECT "11" +#elif __STDC_VERSION__ >= 199901L +# define C_DIALECT "99" +#else +# define C_DIALECT "90" +#endif +const char* info_language_dialect_default = + "INFO" ":" "dialect_default[" C_DIALECT "]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/a.out b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/a.out new file mode 100644 index 0000000..ab75ad5 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/a.out differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/CMakeCXXCompilerId.cpp b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..69cfdba --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,660 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_dialect_default = "INFO" ":" "dialect_default[" +#if CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} diff --git a/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/a.out b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/a.out new file mode 100644 index 0000000..dadc702 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/a.out differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake new file mode 100644 index 0000000..bdf3452 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake @@ -0,0 +1,73 @@ +set(CMAKE_C_COMPILER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "8.3.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + +set(CMAKE_C_COMPILER_SYSROOT "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr") +set(CMAKE_COMPILER_SYSROOT "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr") + + +set(CMAKE_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ar") +set(CMAKE_C_COMPILER_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ar") +set(CMAKE_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ranlib") +set(CMAKE_LINKER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "4") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..c6b46f0 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake @@ -0,0 +1,84 @@ +set(CMAKE_CXX_COMPILER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "8.3.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + +set(CMAKE_CXX_COMPILER_SYSROOT "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr") +set(CMAKE_COMPILER_SYSROOT "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr") + + +set(CMAKE_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ar") +set(CMAKE_CXX_COMPILER_AR "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ar") +set(CMAKE_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc-ranlib") +set(CMAKE_LINKER "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "4") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000..6c79fe1 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin new file mode 100644 index 0000000..91be81a Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeSystem.cmake b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeSystem.cmake new file mode 100644 index 0000000..77bcd91 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-5.15.0-82-generic") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "5.15.0-82-generic") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "") +set(CMAKE_SYSTEM_PROCESSOR "") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..88155ff --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,866 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/a.out b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/a.out new file mode 100644 index 0000000..22cb443 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/a.out differ diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..746b167 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,855 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out new file mode 100644 index 0000000..dd60782 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out differ diff --git a/rknn_yolo_demo/build/CMakeFiles/CMakeConfigureLog.yaml b/rknn_yolo_demo/build/CMakeFiles/CMakeConfigureLog.yaml new file mode 100644 index 0000000..a79d845 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/CMakeConfigureLog.yaml @@ -0,0 +1,506 @@ + +--- +events: + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineSystem.cmake:199 (message)" + - "CMakeLists.txt:3 (project)" + message: | + The target system is: Linux - - + The host system is: Linux - 5.15.0-82-generic - x86_64 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCCompiler.cmake:123 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:3 (project)" + message: | + Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. + Compiler: /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + + The C compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdC/a.out + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:3 (project)" + message: | + Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. + Compiler: /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + + The CXX compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + checks: + - "Detecting C compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R" + cmakeVariables: + CMAKE_C_FLAGS: "" + CMAKE_C_FLAGS_DEBUG: "-g" + CMAKE_EXE_LINKER_FLAGS: "" + buildResult: + variable: "CMAKE_C_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_e6ce6/fast && /usr/bin/make -f CMakeFiles/cmTC_e6ce6.dir/build.make CMakeFiles/cmTC_e6ce6.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R' + Building C object CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v -o CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c + Using built-in specs. + COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc + Target: arm-linux-gnueabihf + Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' + Thread model: posix + gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1 -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -version -o /tmp/ccknitAp.s + GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include" + ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include" + #include "..." search starts here: + #include <...> search starts here: + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include + End of search list. + GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 7f73d02f5a647c367ef9cbd0ddc0248c + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o /tmp/ccknitAp.s + GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321 + COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ + LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + Linking C executable cmTC_e6ce6 + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_e6ce6.dir/link.txt --verbose=1 + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -o cmTC_e6ce6 + Using built-in specs. + COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc + COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper + Target: arm-linux-gnueabihf + Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' + Thread model: posix + gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) + COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ + LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_e6ce6' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cczMZgNQ.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_e6ce6 /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_e6ce6' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + message: | + Parsed C implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + end of search list found + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + implicit include dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + message: | + Parsed C implicit link information: + link line regex: [^( *|.*[/\\])(arm-linux-gnueabihf-ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_e6ce6/fast && /usr/bin/make -f CMakeFiles/cmTC_e6ce6.dir/build.make CMakeFiles/cmTC_e6ce6.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-83S79R'] + ignore line: [Building C object CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v -o CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1 -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -version -o /tmp/ccknitAp.s] + ignore line: [GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include"] + ignore line: [ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + ignore line: [End of search list.] + ignore line: [GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 7f73d02f5a647c367ef9cbd0ddc0248c] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o /tmp/ccknitAp.s] + ignore line: [GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [Linking C executable cmTC_e6ce6] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_e6ce6.dir/link.txt --verbose=1] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -o cmTC_e6ce6 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc] + ignore line: [COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_e6ce6' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + link line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cczMZgNQ.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_e6ce6 /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/cczMZgNQ.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib/ld-linux-armhf.so.3] ==> ignore + arg [-X] ==> ignore + arg [-m] ==> ignore + arg [armelf_linux_eabi] ==> ignore + arg [-o] ==> ignore + arg [cmTC_e6ce6] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] + arg [CMakeFiles/cmTC_e6ce6.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crt1.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crti.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crtn.o] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit objs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crt1.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crti.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crtn.o] + implicit dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit fwks: [] + + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + checks: + - "Detecting CXX compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT" + cmakeVariables: + CMAKE_CXX_FLAGS: "" + CMAKE_CXX_FLAGS_DEBUG: "-g" + CMAKE_EXE_LINKER_FLAGS: "" + buildResult: + variable: "CMAKE_CXX_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_8e35f/fast && /usr/bin/make -f CMakeFiles/cmTC_8e35f.dir/build.make CMakeFiles/cmTC_8e35f.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT' + Building CXX object CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v -o CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp + Using built-in specs. + COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ + Target: arm-linux-gnueabihf + Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' + Thread model: posix + gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1plus -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -version -o /tmp/cc6T7Bpz.s + GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include" + ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed" + ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include" + #include "..." search starts here: + #include <...> search starts here: + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0 + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include + End of search list. + GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 8a85cb0d2d2ff66df776d19db4ea2416 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o /tmp/cc6T7Bpz.s + GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321 + COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ + LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + Linking CXX executable cmTC_8e35f + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_8e35f.dir/link.txt --verbose=1 + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_8e35f + Using built-in specs. + COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ + COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper + Target: arm-linux-gnueabihf + Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' + Thread model: posix + gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) + COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ + LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_8e35f' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccYjJyEY.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_8e35f /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_8e35f' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + message: | + Parsed CXX implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + end of search list found + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + implicit include dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + message: | + Parsed CXX implicit link information: + link line regex: [^( *|.*[/\\])(arm-linux-gnueabihf-ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_8e35f/fast && /usr/bin/make -f CMakeFiles/cmTC_8e35f.dir/build.make CMakeFiles/cmTC_8e35f.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeScratch/TryCompile-mxtKhT'] + ignore line: [Building CXX object CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v -o CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1plus -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -version -o /tmp/cc6T7Bpz.s] + ignore line: [GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include"] + ignore line: [ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 8a85cb0d2d2ff66df776d19db4ea2416] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o /tmp/cc6T7Bpz.s] + ignore line: [GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [Linking CXX executable cmTC_8e35f] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_8e35f.dir/link.txt --verbose=1] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_8e35f ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++] + ignore line: [COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_8e35f' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + link line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccYjJyEY.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_8e35f /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccYjJyEY.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib/ld-linux-armhf.so.3] ==> ignore + arg [-X] ==> ignore + arg [-m] ==> ignore + arg [armelf_linux_eabi] ==> ignore + arg [-o] ==> ignore + arg [cmTC_8e35f] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] + arg [CMakeFiles/cmTC_8e35f.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] ==> obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crt1.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crti.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] + collapse obj [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crtn.o] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit objs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crt1.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crti.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/crtn.o] + implicit dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit fwks: [] + + +... diff --git a/rknn_yolo_demo/build/CMakeFiles/CMakeDirectoryInformation.cmake b/rknn_yolo_demo/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..b1271fd --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/rknn_yolo_demo/build/CMakeFiles/CMakeOutput.log b/rknn_yolo_demo/build/CMakeFiles/CMakeOutput.log new file mode 100644 index 0000000..5541f9d --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/CMakeOutput.log @@ -0,0 +1,432 @@ +The target system is: Linux - - +The host system is: Linux - 5.15.0-91-generic - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + +The C compiler identification is GNU, found in "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdC/a.out" + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + +The CXX compiler identification is GNU, found in "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/3.16.3/CompilerIdCXX/a.out" + +Determining if the C compiler works passed with the following output: +Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/make cmTC_0bc5f/fast && /usr/bin/make -f CMakeFiles/cmTC_0bc5f.dir/build.make CMakeFiles/cmTC_0bc5f.dir/build +make[1]: 进入目录“/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp” +Building C object CMakeFiles/cmTC_0bc5f.dir/testCCompiler.c.o +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -o CMakeFiles/cmTC_0bc5f.dir/testCCompiler.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp/testCCompiler.c +Linking C executable cmTC_0bc5f +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_0bc5f.dir/link.txt --verbose=1 +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc CMakeFiles/cmTC_0bc5f.dir/testCCompiler.c.o -o cmTC_0bc5f +make[1]: 离开目录“/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp” + + + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/make cmTC_4c510/fast && /usr/bin/make -f CMakeFiles/cmTC_4c510.dir/build.make CMakeFiles/cmTC_4c510.dir/build +make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v -o CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c +Using built-in specs. +COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +Target: arm-linux-gnueabihf +Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' +Thread model: posix +gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1 -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -version -o /tmp/cc7a1OOf.s +GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include" +ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include" +#include "..." search starts here: +#include <...> search starts here: + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include +End of search list. +GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: 7f73d02f5a647c367ef9cbd0ddc0248c +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o /tmp/cc7a1OOf.s +GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321 +COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ +LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' +Linking C executable cmTC_4c510 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_4c510.dir/link.txt --verbose=1 +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -o cmTC_4c510 +Using built-in specs. +COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper +Target: arm-linux-gnueabihf +Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' +Thread model: posix +gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) +COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ +LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_4c510' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccmWBFwI.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_4c510 /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_4c510' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' +make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp' + + + +Parsed C implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + end of search list found + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + implicit include dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(arm-linux-gnueabihf-ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/usr/bin/make cmTC_4c510/fast && /usr/bin/make -f CMakeFiles/cmTC_4c510.dir/build.make CMakeFiles/cmTC_4c510.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp'] + ignore line: [Building C object CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v -o CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1 -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc /usr/share/cmake-3.16/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -version -o /tmp/cc7a1OOf.s] + ignore line: [GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include"] + ignore line: [ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + ignore line: [End of search list.] + ignore line: [GNU C17 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 7f73d02f5a647c367ef9cbd0ddc0248c] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o /tmp/cc7a1OOf.s] + ignore line: [GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o' '-c' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [Linking C executable cmTC_4c510] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_4c510.dir/link.txt --verbose=1] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc -v CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -o cmTC_4c510 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc] + ignore line: [COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_4c510' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + link line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccmWBFwI.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_4c510 /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccmWBFwI.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib/ld-linux-armhf.so.3] ==> ignore + arg [-X] ==> ignore + arg [-m] ==> ignore + arg [armelf_linux_eabi] ==> ignore + arg [-o] ==> ignore + arg [cmTC_4c510] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] ==> ignore + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] + arg [CMakeFiles/cmTC_4c510.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] ==> ignore + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit fwks: [] + + +Determining if the CXX compiler works passed with the following output: +Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/make cmTC_7572c/fast && /usr/bin/make -f CMakeFiles/cmTC_7572c.dir/build.make CMakeFiles/cmTC_7572c.dir/build +make[1]: 进入目录“/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp” +Building CXX object CMakeFiles/cmTC_7572c.dir/testCXXCompiler.cxx.o +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -o CMakeFiles/cmTC_7572c.dir/testCXXCompiler.cxx.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx +Linking CXX executable cmTC_7572c +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_7572c.dir/link.txt --verbose=1 +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ CMakeFiles/cmTC_7572c.dir/testCXXCompiler.cxx.o -o cmTC_7572c +make[1]: 离开目录“/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp” + + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp + +Run Build Command(s):/usr/bin/make cmTC_cd1e3/fast && /usr/bin/make -f CMakeFiles/cmTC_cd1e3.dir/build.make CMakeFiles/cmTC_cd1e3.dir/build +make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp' +Building CXX object CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v -o CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp +Using built-in specs. +COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +Target: arm-linux-gnueabihf +Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' +Thread model: posix +gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1plus -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc -D_GNU_SOURCE /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -version -o /tmp/ccnM2oYf.s +GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include" +ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed" +ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include" +#include "..." search starts here: +#include <...> search starts here: + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0 + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include +End of search list. +GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf) + compiled by GNU C version 4.8.1, GMP version 4.3.2, MPFR version 3.1.6, MPC version 0.8.2, isl version isl-0.15-1-g835ea3a-GMP + +GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +Compiler executable checksum: 8a85cb0d2d2ff66df776d19db4ea2416 +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccnM2oYf.s +GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321 +COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ +LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' +Linking CXX executable cmTC_cd1e3 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_cd1e3.dir/link.txt --verbose=1 +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_cd1e3 +Using built-in specs. +COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper +Target: arm-linux-gnueabihf +Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)' +Thread model: posix +gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) +COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ +LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_cd1e3' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccGfF3jI.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_cd1e3 /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_cd1e3' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd' +make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp' + + + +Parsed CXX implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + add: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + end of search list found + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include] + collapse include dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + implicit include dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include] + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(arm-linux-gnueabihf-ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/usr/bin/make cmTC_cd1e3/fast && /usr/bin/make -f CMakeFiles/cmTC_cd1e3.dir/build.make CMakeFiles/cmTC_cd1e3.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/CMakeTmp'] + ignore line: [Building CXX object CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v -o CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1plus -quiet -v -iprefix /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc -D_GNU_SOURCE /usr/share/cmake-3.16/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd -auxbase-strip CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -version -o /tmp/ccnM2oYf.s] + ignore line: [GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include"] + ignore line: [ignoring nonexistent directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed"] + ignore line: [ignoring duplicate directory "/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include/c++/8.3.0/backward] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++14 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) version 8.3.0 (arm-linux-gnueabihf)] + ignore line: [ compiled by GNU C version 4.8.1 GMP version 4.3.2 MPFR version 3.1.6 MPC version 0.8.2 isl version isl-0.15-1-g835ea3a-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 8a85cb0d2d2ff66df776d19db4ea2416] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/as -v -march=armv7-a -mfloat-abi=hard -mfpu=neon -meabi=5 -o CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccnM2oYf.s] + ignore line: [GNU assembler version 2.32.0 (arm-linux-gnueabihf) using BFD version (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 2.32.0.20190321] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + ignore line: [Linking CXX executable cmTC_cd1e3] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_cd1e3.dir/link.txt --verbose=1] + ignore line: [/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -v CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_cd1e3 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++] + ignore line: [COLLECT_LTO_WRAPPER=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] + ignore line: [Target: arm-linux-gnueabihf] + ignore line: [Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c c++ fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'] + ignore line: [Thread model: posix] + ignore line: [gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) ] + ignore line: [COMPILER_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/] + ignore line: [LIBRARY_PATH=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_cd1e3' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'] + link line: [ /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2 -plugin /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so -plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccGfF3jI.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X -m armelf_linux_eabi -o cmTC_cd1e3 /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0 -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib -L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccGfF3jI.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--sysroot=/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib/ld-linux-armhf.so.3] ==> ignore + arg [-X] ==> ignore + arg [-m] ==> ignore + arg [armelf_linux_eabi] ==> ignore + arg [-o] ==> ignore + arg [cmTC_cd1e3] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crt1.o] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crti.o] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtbegin.o] ==> ignore + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] + arg [-L/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] + arg [CMakeFiles/cmTC_cd1e3.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/crtend.o] ==> ignore + arg [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/crtn.o] ==> ignore + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib] + collapse library dir [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib] ==> [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit dirs: [/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib;/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib] + implicit fwks: [] + + diff --git a/rknn_yolo_demo/build/CMakeFiles/Makefile.cmake b/rknn_yolo_demo/build/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..bba8de0 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,58 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/3.16.3/CMakeCCompiler.cmake" + "CMakeFiles/3.16.3/CMakeCXXCompiler.cmake" + "CMakeFiles/3.16.3/CMakeSystem.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVConfig-version.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVConfig.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVModules-release.cmake" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/share/OpenCV/OpenCVModules.cmake" + "/usr/share/cmake-3.16/Modules/CMakeCInformation.cmake" + "/usr/share/cmake-3.16/Modules/CMakeCXXInformation.cmake" + "/usr/share/cmake-3.16/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake" + "/usr/share/cmake-3.16/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake-3.16/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake-3.16/Modules/CMakeInitializeConfigs.cmake" + "/usr/share/cmake-3.16/Modules/CMakeLanguageInformation.cmake" + "/usr/share/cmake-3.16/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake-3.16/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/share/cmake-3.16/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/usr/share/cmake-3.16/Modules/Compiler/GNU-C.cmake" + "/usr/share/cmake-3.16/Modules/Compiler/GNU-CXX.cmake" + "/usr/share/cmake-3.16/Modules/Compiler/GNU.cmake" + "/usr/share/cmake-3.16/Modules/FindCURL.cmake" + "/usr/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake" + "/usr/share/cmake-3.16/Modules/FindPackageMessage.cmake" + "/usr/share/cmake-3.16/Modules/FindPkgConfig.cmake" + "/usr/share/cmake-3.16/Modules/Internal/CMakeCheckCompilerFlag.cmake" + "/usr/share/cmake-3.16/Modules/Platform/Linux-GNU-C.cmake" + "/usr/share/cmake-3.16/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/share/cmake-3.16/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake-3.16/Modules/Platform/Linux.cmake" + "/usr/share/cmake-3.16/Modules/Platform/UnixPaths.cmake" + "/usr/share/cmake-3.16/Modules/SelectLibraryConfigurations.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/rknn_yolo_demo_test.dir/DependInfo.cmake" + ) diff --git a/rknn_yolo_demo/build/CMakeFiles/Makefile2 b/rknn_yolo_demo/build/CMakeFiles/Makefile2 new file mode 100644 index 0000000..d76cf12 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/Makefile2 @@ -0,0 +1,106 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/rknn_yolo_demo_test.dir/all + +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: + +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/rknn_yolo_demo_test.dir/clean + +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/rknn_yolo_demo_test.dir + +# All Build rule for target. +CMakeFiles/rknn_yolo_demo_test.dir/all: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/depend + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles --progress-num=1,2,3,4,5 "Built target rknn_yolo_demo_test" +.PHONY : CMakeFiles/rknn_yolo_demo_test.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/rknn_yolo_demo_test.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles 5 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/rknn_yolo_demo_test.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles 0 +.PHONY : CMakeFiles/rknn_yolo_demo_test.dir/rule + +# Convenience name for target. +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/rule + +.PHONY : rknn_yolo_demo_test + +# clean rule for target. +CMakeFiles/rknn_yolo_demo_test.dir/clean: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/clean +.PHONY : CMakeFiles/rknn_yolo_demo_test.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/rknn_yolo_demo/build/CMakeFiles/TargetDirectories.txt b/rknn_yolo_demo/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..4475659 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,7 @@ +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/install/strip.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/install/local.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/install.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/list_install_components.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rebuild_cache.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/edit_cache.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir diff --git a/rknn_yolo_demo/build/CMakeFiles/cmake.check_cache b/rknn_yolo_demo/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/rknn_yolo_demo/build/CMakeFiles/progress.marks b/rknn_yolo_demo/build/CMakeFiles/progress.marks new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/progress.marks @@ -0,0 +1 @@ +5 diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/C.includecache b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/C.includecache new file mode 100644 index 0000000..8e54ca9 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/C.includecache @@ -0,0 +1,8 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/CXX.includecache b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/CXX.includecache new file mode 100644 index 0000000..088fdd4 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/CXX.includecache @@ -0,0 +1,3708 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/curl/curl.h +curlver.h +../include/curl/curlver.h +system.h +../include/curl/system.h +stdio.h +- +limits.h +- +osreldate.h +- +sys/types.h +- +time.h +- +winsock2.h +- +ws2tcpip.h +- +sys/select.h +- +sys/socket.h +- +sys/time.h +- +support/SupportDefs.h +- +easy.h +../include/curl/easy.h +multi.h +../include/curl/multi.h +urlapi.h +../include/curl/urlapi.h +typecheck-gcc.h +../include/curl/typecheck-gcc.h + +../include/curl/curlver.h + +../include/curl/easy.h + +../include/curl/multi.h +curl.h +../include/curl/curl.h + +../include/curl/system.h +winsock2.h +- +windows.h +- +ws2tcpip.h +- +sys/types.h +- +sys/socket.h +- +sys/poll.h +- + +../include/curl/typecheck-gcc.h + +../include/curl/urlapi.h +curl.h +../include/curl/curl.h + +../include/drm_func.h +stdint.h +- +stdio.h +- +stdlib.h +- +string.h +- +sys/fcntl.h +- +unistd.h +- +errno.h +- +sys/mman.h +- +linux/input.h +- +libdrm/drm_fourcc.h +../include/libdrm/drm_fourcc.h +xf86drm.h +../include/xf86drm.h + +../include/librtsp/rtsp_demo.h +stdint.h +- + +../include/rga_func.h +dlfcn.h +- +RgaApi.h +../include/RgaApi.h + +../include/yolo.h +stdint.h +- +rknn_api.h +../include/rknn_api.h +rga_func.h +../include/rga_func.h + +../libs/common/CImg/CImg.h +cstdio +- +cstdlib +- +cstdarg +- +cstring +- +cmath +- +cfloat +- +climits +- +ctime +- +exception +- +algorithm +- +stdio.h +- +sys/types.h +- +sys/time.h +- +sys/stat.h +- +unistd.h +- +dirent.h +- +fnmatch.h +- +windows.h +- +shlobj.h +- +process.h +- +io.h +- +initializer_list +- +utility +- +omp.h +- +X11/Xlib.h +- +X11/Xutil.h +- +X11/keysym.h +- +pthread.h +- +sys/ipc.h +- +sys/shm.h +- +X11/extensions/XShm.h +- +X11/extensions/Xrandr.h +- +cstddef +- +opencv2/opencv.hpp +- +png.h +../libs/common/CImg/png.h +jpeglib.h +../libs/common/CImg/jpeglib.h +setjmp.h +../libs/common/CImg/setjmp.h +tiffio.h +../libs/common/CImg/tiffio.h +libheif/heif_cxx.h +- +minc_io_simple_volume.h +../libs/common/CImg/minc_io_simple_volume.h +minc_1_simple.h +../libs/common/CImg/minc_1_simple.h +minc_1_simple_rw.h +../libs/common/CImg/minc_1_simple_rw.h +zlib.h +../libs/common/CImg/zlib.h +curl/curl.h +../libs/common/CImg/curl/curl.h +Magick++.h +../libs/common/CImg/Magick++.h +fftw3.h +../libs/common/CImg/fftw3.h +Board.h +../libs/common/CImg/Board.h +ImfRgbaFile.h +../libs/common/CImg/ImfRgbaFile.h +ImfInputFile.h +../libs/common/CImg/ImfInputFile.h +ImfChannelList.h +../libs/common/CImg/ImfChannelList.h +ImfMatrixAttribute.h +../libs/common/CImg/ImfMatrixAttribute.h +ImfArray.h +../libs/common/CImg/ImfArray.h +tinyexr.h +../libs/common/CImg/tinyexr.h +CImg.h +../libs/common/CImg/CImg.h + +../libs/common/drm/include/libdrm/drm.h +linux/types.h +- +asm/ioctl.h +- +stdint.h +- +sys/ioccom.h +- +sys/types.h +- +drm_mode.h +../libs/common/drm/include/libdrm/drm_mode.h + +../libs/common/drm/include/libdrm/drm_fourcc.h +drm.h +../libs/common/drm/include/libdrm/drm.h + +../libs/common/drm/include/libdrm/drm_mode.h +drm.h +../libs/common/drm/include/libdrm/drm.h + +../libs/common/drm/include/xf86drm.h +stdarg.h +- +sys/types.h +- +stdint.h +- +drm.h +- +sys/ioccom.h +- +ia64intrin.h +- + +../libs/common/stb/stb_image.h +stb_image.h +../libs/common/stb/stb_image.h +stdio.h +- +stdlib.h +- +stdarg.h +- +stddef.h +- +stdlib.h +- +string.h +- +limits.h +- +math.h +- +stdio.h +- +assert.h +- +stdint.h +- +emmintrin.h +- +intrin.h +- +arm_neon.h +- + +../libs/common/stb/stb_image_resize.h +stb_image_resize.h +../libs/common/stb/stb_image_resize.h +stdint.h +- +assert.h +- +string.h +- +math.h +- +stdlib.h +- + +../libs/common/stb/stb_image_write.h +stdlib.h +- +stdio.h +- +stdarg.h +- +stdlib.h +- +string.h +- +math.h +- +assert.h +- + +../libs/platform/RV1109_1126/libjpeg/include/jconfig.h + +../libs/platform/RV1109_1126/libjpeg/include/jerror.h + +../libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h + +../libs/platform/RV1109_1126/libjpeg/include/jpeglib.h +jconfig.h +../libs/platform/RV1109_1126/libjpeg/include/jconfig.h +jmorecfg.h +../libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h +jpegint.h +../libs/platform/RV1109_1126/libjpeg/include/jpegint.h +jerror.h +../libs/platform/RV1109_1126/libjpeg/include/jerror.h + +../libs/platform/RV1109_1126/libpng/include/png.h +pnglibconf.h +../libs/platform/RV1109_1126/libpng/include/pnglibconf.h +pngconf.h +../libs/platform/RV1109_1126/libpng/include/pngconf.h + +../libs/platform/RV1109_1126/libpng/include/pngconf.h +limits.h +- +stddef.h +- +stdio.h +- +setjmp.h +- +time.h +- + +../libs/platform/RV1109_1126/libpng/include/pnglibconf.h + +../libs/platform/RV1109_1126/zlib/include/zconf.h +stddef.h +- +windows.h +- +limits.h +- +sys/types.h +- +stdarg.h +- +stddef.h +- +unistd.h +- +unixio.h +- + +../libs/platform/RV1109_1126/zlib/include/zlib.h +zconf.h +../libs/platform/RV1109_1126/zlib/include/zconf.h + +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h +stdint.h +- +sys/types.h +- +stdlib.h +- +stdio.h +- +string.h +- +errno.h +- +time.h +- +unistd.h +- +sys/mman.h +- +linux/stddef.h +- +drmrga.h +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h +RockchipRgaMacro.h +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h +stdint.h +- +sys/cdefs.h +- +rga.h +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h +RockchipRgaMacro.h +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + +../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h +stdint.h +- + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp +main.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h +iostream +- +chrono +- +thread +- +fstream +- +cstdio +- +stdio.h +- +stdlib.h +- +string.h +- +sys/time.h +- +dlfcn.h +- +vector +- +string +- +stdbool.h +- +stb/stb_image.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/stb/stb_image.h +stb/stb_image_resize.h +- +stb/stb_image_write.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/stb/stb_image_write.h +CImg/CImg.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/CImg/CImg.h +drm_func.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.h +rga_func.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.h +rknn_api.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rknn_api.h +yolo.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.h + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h +getopt.h +- +math.h +- +pthread.h +- +signal.h +- +stdbool.h +- +stdio.h +- +stdlib.h +- +string.h +- +unistd.h +- +malloc.h +- +dlfcn.h +- +curl/curl.h +- +im2d.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/im2d.h +rga.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga.h +drm_func.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.h +rga_func.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.h +rknn_api.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rknn_api.h +rkmedia_api.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rkmedia_api.h +rkmedia_venc.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rkmedia_venc.h +sample_common.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/sample_common.h +opencv2/opencv.hpp +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/opencv2/opencv.hpp +librtsp/rtsp_demo.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/librtsp/rtsp_demo.h +rk_aiq_user_api_sysctl.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rk_aiq_user_api_sysctl.h +rk_aiq_user_api_afec.h +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rk_aiq_user_api_afec.h +opencv2/core.hpp +- +opencv2/imgproc.hpp +- +opencv2/imgcodecs.hpp +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/opencv2/imgcodecs.hpp +opencv2/freetype.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h +features.h +- +stddef.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h +asm-generic/errno-base.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h +asm/bitsperlong.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h +linux/ioctl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h +asm/bitsperlong.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h +asm/sockios.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h +asm-generic/bitsperlong.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h +asm-generic/errno.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h +asm-generic/ioctl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h +asm-generic/ioctls.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h +asm-generic/posix_types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h +asm-generic/socket.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h +asm-generic/sockios.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h +asm-generic/int-ll64.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h +features.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h +features.h +- +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h +bits/wordsize.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h +linux/errno.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h +bits/fcntl-linux.h +- +bits/types/struct_iovec.h +- +linux/falloc.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h +bits/fcntl-linux.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl2.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h +features.h +- +bits/long-double.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h +bits/floatn-common.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h +bits/getopt_core.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h +asm/ioctls.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h +asm/ioctls.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ipc.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ipctypes.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h +features.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h +linux/limits.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-finite.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h +bits/libm-simd-decl-stubs.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathinline.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h +bits/mman-shared.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h +bits/mman-linux.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/poll.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/poll2.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h +bits/wordsize.h +- +bits/local_lim.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h +endian.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h +bits/thread-shared-types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h +bits/types/struct_sched_param.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp2.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/shm.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h +asm/sigcontext.h +- +stddef.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h +bits/siginfo-arch.h +- +bits/siginfo-consts-arch.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h +bits/signum-generic.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h +bits/types/__sigset_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h +stddef.h +- +sys/types.h +- +bits/socket_type.h +- +bits/sockaddr.h +- +asm/socket.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket2.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h +bits/strings_fortified.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h +bits/pthreadtypes-arch.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h +bits/types.h +- +bits/timex.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h +bits/types.h +- +bits/types/struct_timeval.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h +features.h +- +bits/wordsize.h +- +bits/typesizes.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h +bits/types.h +- +bits/types/__mbstate_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h +bits/types.h +- +bits/types/__mbstate_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h +bits/types/__locale_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h +bits/wordsize.h +- +bits/types.h +- +bits/types/__sigval_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h +bits/wordsize.h +- +bits/types.h +- +bits/types/__sigval_t.h +- +bits/siginfo-arch.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h +bits/types/__sigset_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h +bits/types/__sigval_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h +stddef.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h +stddef.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h +bits/types.h +- +bits/types/struct_timespec.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h +bits/types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h +bits/uio_lim.h +- +bits/wordsize.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h +features.h +- +bits/types.h +- +bits/dirent.h +- +bits/types.h +- +bits/posix1_lim.h +- +stddef.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h +features.h +- +stddef.h +- +bits/dlfcn.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h +stddef.h +- +rkmedia_adec.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h +rkmedia_aenc.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h +rkmedia_ai.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h +rkmedia_ao.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h +rkmedia_buffer.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h +rkmedia_event.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h +rkmedia_move_detection.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h +rkmedia_muxer.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h +rkmedia_occlusion_detection.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h +rkmedia_rga.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h +rkmedia_vdec.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h +rkmedia_venc.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h +rkmedia_vi.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h +rkmedia_vmix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h +rkmedia_vo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h +stddef.h +- +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h +assert.h +- +fcntl.h +- +signal.h +- +stdbool.h +- +stdio.h +- +stdlib.h +- +time.h +- +unistd.h +- +rkmedia_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h +rk_aiq_user_api_imgproc.h +- +rk_aiq_user_api_sysctl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h +features.h +- +bits/endian.h +- +bits/byteswap.h +- +bits/uintn-identity.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h +features.h +- +bits/errno.h +- +bits/types/error_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h +features.h +- +bits/types.h +- +bits/fcntl.h +- +bits/types/struct_timespec.h +- +bits/stat.h +- +bits/fcntl2.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h +stdc-predef.h +- +sys/cdefs.h +- +gnu/stubs.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h +features.h +- +bits/getopt_core.h +- +bits/getopt_ext.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h +gnu/stubs-soft.h +- +gnu/stubs-hard.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h +bits/libc-header-start.h +- +bits/wordsize.h +- +bits/posix1_lim.h +- +bits/posix2_lim.h +- +bits/xopen_lim.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h +asm/errno.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h +sys/time.h +- +sys/ioctl.h +- +sys/types.h +- +linux/types.h +- +input-event-codes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h +asm/ioctl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h +linux/stddef.h +- +asm/posix_types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h +asm/types.h +- +linux/posix_types.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h +features.h +- +stddef.h +- +stdio.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h +bits/libc-header-start.h +- +bits/types.h +- +bits/math-vector.h +- +bits/floatn.h +- +bits/flt-eval-method.h +- +bits/fp-logb.h +- +bits/fp-fast.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-helper-functions.h +- +bits/mathcalls.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/mathcalls-narrow.h +- +bits/iscanonical.h +- +bits/mathinline.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- +bits/math-finite.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv/cxcore.h +opencv2/core/core_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv/opencv2/core/core_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/features2d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/features2d.hpp +opencv2/core/affine.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/affine.hpp +opencv2/calib3d/calib3d_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/calib3d/calib3d_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/cvdef.h +opencv2/core/version.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/version.hpp +opencv2/core/base.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/base.hpp +opencv2/core/cvstd.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/cvstd.hpp +opencv2/core/traits.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/traits.hpp +opencv2/core/matx.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/matx.hpp +opencv2/core/types.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/types.hpp +opencv2/core/mat.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/mat.hpp +opencv2/core/persistence.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/persistence.hpp +opencv2/core/operations.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/operations.hpp +opencv2/core/cvstd.inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/cvstd.inl.hpp +opencv2/core/utility.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/utility.hpp +opencv2/core/optim.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/optim.hpp +opencv2/core/ovx.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core/ovx.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp +opencv2/core.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp +opencv2/core/mat.hpp +- +chrono +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/opencv_modules.hpp +climits +- +algorithm +- +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +opencv2/core/cvstd.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvstd.hpp +opencv2/core/neon_utils.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/neon_utils.hpp +opencv2/core/vsx_utils.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/vsx_utils.hpp +opencv2/core/check.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/check.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp +opencv2/core/base.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core.hpp +opencv2/core/cuda_types.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cuda_types.hpp +opencv2/opencv.hpp +- +opencv2/core/cuda.inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cuda.inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp +opencv2/core/cuda.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cuda.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h +cvconfig.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvconfig.h +limits +- +limits.h +- +opencv2/core/hal/interface.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/hal/interface.h +cv_cpu_dispatch.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cv_cpu_dispatch.h +intrin.h +- +array +- +cstdint +- +stdint.h +- +stdint.h +- +opencv2/core/fast_math.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/fast_math.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +cstddef +- +cstring +- +cctype +- +string +- +algorithm +- +utility +- +cstdlib +- +cmath +- +opencv2/core/ptr.inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/ptr.inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp +complex +- +ostream +- +sstream +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +cmath +- +fastmath.h +- +math.h +- +emmintrin.h +- +altivec.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp +opencv2/core/matx.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/matx.hpp +opencv2/core/types.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/types.hpp +opencv2/core/bufferpool.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/bufferpool.hpp +type_traits +- +opencv2/core/mat.inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/mat.inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +opencv2/core/base.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/base.hpp +opencv2/core/traits.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/traits.hpp +opencv2/core/saturate.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/saturate.hpp +initializer_list +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp +cstdio +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp +cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp +opencv2/core/types.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/types.hpp +opencv2/core/mat.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/mat.hpp +opencv2/opencv.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/opencv.hpp +time.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp +algorithm +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +opencv2/core/fast_math.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/fast_math.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp +climits +- +cfloat +- +vector +- +limits +- +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +opencv2/core/cvstd.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvstd.hpp +opencv2/core/matx.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/matx.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core.hpp +ostream +- +functional +- +opencv2/core/utils/instrumentation.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/utils/instrumentation.hpp +opencv2/core/core_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/core_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utils/instrumentation.hpp +opencv2/core/utility.hpp +- +opencv2/core/utils/tls.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utils/tls.hpp +opencv2/core/utility.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/opencv2/core/cvdef.h +assert.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp +opencv2/dnn/dnn.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp +opencv2/core.hpp +- +map +- +ostream +- +opencv2/dnn/dnn.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp +vector +- +opencv2/core.hpp +- +opencv2/core/async.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/opencv2/core/async.hpp +opencv2/dnn/dict.hpp +- +opencv2/dnn/layer.hpp +- +opencv2/dnn/dnn.inl.hpp +- +opencv2/dnn/utils/inference_engine.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp +opencv2/dnn.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp +opencv2/dnn.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp +../dnn.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/opencv_modules.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/flann/miniflann.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/flann/miniflann.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/flann/miniflann.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/flann/miniflann.hpp +opencv2/flann/flann_base.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/flann/flann_base.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +kdtree_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h +kdtree_single_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h +kmeans_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h +composite_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h +linear_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h +hierarchical_clustering_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h +lsh_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h +autotuned_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +stdlib.h +- +stdio.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h +defines.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h +stdexcept +- +ostream +- +typeinfo +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h +sstream +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +ground_truth.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h +index_testing.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h +sampling.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h +kdtree_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h +kdtree_single_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h +kmeans_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h +composite_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h +linear_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h +logger.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +kdtree_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h +kmeans_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h +config.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/config.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h +cmath +- +cstdlib +- +string.h +- +stdint.h +- +defines.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h +Intrin.h +- +arm_neon.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/arm_neon.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h +boost/dynamic_bitset.hpp +- +limits.h +- +dist.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp +vector +- +cstdio +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +params.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h +saving.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h +all_indices.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h +dist.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +algorithm +- +vector +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h +algorithm +- +map +- +limits +- +cmath +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +dist.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +heap.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +allocator.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +random.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +saving.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h +cstring +- +cmath +- +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +logger.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h +timer.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h +algorithm +- +map +- +cstring +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +dynamic_bitset.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +heap.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +allocator.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +random.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +saving.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h +algorithm +- +map +- +cstring +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +heap.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +allocator.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +random.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +saving.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h +algorithm +- +map +- +limits +- +cmath +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +dist.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +heap.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +allocator.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +random.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +saving.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h +logger.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h +stdio.h +- +stdarg.h +- +defines.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h +algorithm +- +cstring +- +map +- +vector +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +heap.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +lsh_table.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h +allocator.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +random.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +saving.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h +algorithm +- +iostream +- +iomanip +- +limits.h +- +unordered_map +- +map +- +math.h +- +stddef.h +- +dynamic_bitset.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +stdio.h +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/opencv2/core.hpp +opencv2/flann/defines.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/opencv2/flann/defines.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +result_set.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +params.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h +any.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +iostream +- +map +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +algorithm +- +cstdlib +- +vector +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +algorithm +- +cstring +- +iostream +- +limits +- +set +- +vector +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h +matrix.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +random.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h +cstring +- +vector +- +general.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +nn_index.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h +time.h +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/opencv2/core.hpp +opencv2/core/utility.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/opencv2/core/utility.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/freetype.hpp +opencv2/core.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/imgcodecs.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/imgcodecs.hpp +opencv2/videoio.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/videoio.hpp +opencv2/highgui/highgui_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/highgui/highgui_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/imgproc/imgproc_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/imgproc/imgproc_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +float.h +- +map +- +iostream +- +opencv2/ml/ml.inl.hpp +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/objdetect/detection_based_tracker.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/objdetect/detection_based_tracker.hpp +opencv2/objdetect/objdetect_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/objdetect/objdetect_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp +opencv2/core.hpp +- +vector +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h +opencv2/core/core_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/opencv2/core/core_c.h +deque +- +vector +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/opencv_modules.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/calib3d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/calib3d.hpp +opencv2/features2d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/features2d.hpp +opencv2/dnn.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/dnn.hpp +opencv2/flann.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/flann.hpp +opencv2/highgui.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/highgui.hpp +opencv2/imgcodecs.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/imgcodecs.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/imgproc.hpp +opencv2/ml.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/ml.hpp +opencv2/objdetect.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/objdetect.hpp +opencv2/photo.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/photo.hpp +opencv2/shape.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/shape.hpp +opencv2/stitching.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching.hpp +opencv2/superres.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/superres.hpp +opencv2/video.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/video.hpp +opencv2/videoio.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/videoio.hpp +opencv2/videostab.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/videostab.hpp +opencv2/viz.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/viz.hpp +opencv2/cudaarithm.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudaarithm.hpp +opencv2/cudabgsegm.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudabgsegm.hpp +opencv2/cudacodec.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudacodec.hpp +opencv2/cudafeatures2d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudafeatures2d.hpp +opencv2/cudafilters.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudafilters.hpp +opencv2/cudaimgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudaimgproc.hpp +opencv2/cudaobjdetect.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudaobjdetect.hpp +opencv2/cudaoptflow.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudaoptflow.hpp +opencv2/cudastereo.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudastereo.hpp +opencv2/cudawarping.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/cudawarping.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/imgproc.hpp +opencv2/photo/photo_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/photo/photo_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h +opencv2/core/core_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/opencv2/core/core_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp +opencv2/shape/emdL1.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/shape/emdL1.hpp +opencv2/shape/shape_transformer.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/shape/shape_transformer.hpp +opencv2/shape/hist_cost.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/shape/hist_cost.hpp +opencv2/shape/shape_distance.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/shape/shape_distance.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/imgproc.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/core.hpp +opencv2/shape/hist_cost.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/shape/hist_cost.hpp +opencv2/shape/shape_transformer.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/shape/shape_transformer.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp +vector +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/core.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/opencv2/imgproc.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/features2d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/features2d.hpp +opencv2/stitching/warpers.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/warpers.hpp +opencv2/stitching/detail/matchers.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/detail/matchers.hpp +opencv2/stitching/detail/motion_estimators.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/detail/motion_estimators.hpp +opencv2/stitching/detail/exposure_compensate.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/detail/exposure_compensate.hpp +opencv2/stitching/detail/seam_finders.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/detail/seam_finders.hpp +opencv2/stitching/detail/blenders.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/detail/blenders.hpp +opencv2/stitching/detail/camera.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/stitching/detail/camera.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +opencv2/core/cuda.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core/cuda.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +opencv2/features2d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/features2d.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/opencv_modules.hpp +opencv2/xfeatures2d/cuda.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/xfeatures2d/cuda.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +matchers.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp +util.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp +camera.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp +set +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/opencv_modules.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp +list +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +util_inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp +queue +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +util.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +opencv2/core/cuda.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core/cuda.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/imgproc.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/opencv_modules.hpp +warpers_inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/opencv2/core.hpp +warpers.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp +limits +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp +opencv2/stitching/detail/warpers.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/opencv2/stitching/detail/warpers.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp +opencv2/superres/optical_flow.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/superres/optical_flow.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp +opencv2/video/tracking.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/video/tracking.hpp +opencv2/video/background_segm.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/video/background_segm.hpp +opencv2/video/tracking_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/video/tracking_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/opencv2/core.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/opencv2/imgproc.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h +opencv2/imgproc/types_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/opencv2/imgproc/types_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp +opencv2/videostab/stabilizer.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/videostab/stabilizer.hpp +opencv2/videostab/ring_buffer.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv2/videostab/ring_buffer.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp +vector +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp +cmath +- +queue +- +algorithm +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +fast_marching_inl.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp +opencv2/videostab/fast_marching.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/fast_marching.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp +vector +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp +vector +- +fstream +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/features2d.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/features2d.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/opencv_modules.hpp +opencv2/videostab/optical_flow.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/optical_flow.hpp +opencv2/videostab/motion_core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/motion_core.hpp +opencv2/videostab/outlier_rejection.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/outlier_rejection.hpp +opencv2/cudaimgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/cudaimgproc.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp +vector +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/videostab/optical_flow.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/optical_flow.hpp +opencv2/videostab/fast_marching.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/fast_marching.hpp +opencv2/videostab/global_motion.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/global_motion.hpp +opencv2/photo.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/photo.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp +cmath +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp +vector +- +utility +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/videostab/global_motion.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/global_motion.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/opencv_modules.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/opencv_modules.hpp +opencv2/cudaoptflow.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/cudaoptflow.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp +vector +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/videostab/motion_core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/motion_core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp +vector +- +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/imgproc.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp +vector +- +ctime +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/imgproc.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/imgproc.hpp +opencv2/videostab/global_motion.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/global_motion.hpp +opencv2/videostab/motion_stabilizing.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/motion_stabilizing.hpp +opencv2/videostab/frame_source.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/frame_source.hpp +opencv2/videostab/log.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/log.hpp +opencv2/videostab/inpainting.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/inpainting.hpp +opencv2/videostab/deblurring.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/deblurring.hpp +opencv2/videostab/wobble_suppression.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/wobble_suppression.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp +vector +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core.hpp +opencv2/core/cuda.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/core/cuda.hpp +opencv2/videostab/global_motion.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/global_motion.hpp +opencv2/videostab/log.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/opencv2/videostab/log.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h +features.h +- +endian.h +- +sched.h +- +time.h +- +bits/pthreadtypes.h +- +bits/setjmp.h +- +bits/wordsize.h +- +bits/types/struct_timespec.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h +a3dlut/rk_aiq_types_a3dlut_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/a3dlut/rk_aiq_types_a3dlut_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h +rk_aiq_types_a3dlut_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_algo_des.h +a3dlut/rk_aiq_types_a3dlut_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/a3dlut/rk_aiq_types_a3dlut_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h +ablc/rk_aiq_types_ablc_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/ablc/rk_aiq_types_ablc_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h +ablc/rk_aiq_types_ablc_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/ablc/rk_aiq_types_ablc_algo.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/RkAiqCalibDbTypes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h +accm/rk_aiq_types_accm_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/accm/rk_aiq_types_accm_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/RkAiqCalibDbTypes.h +accm/rk_aiq_types_accm_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/accm/rk_aiq_types_accm_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_algo_des.h +accm/rk_aiq_types_accm_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/accm/rk_aiq_types_accm_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_algo_des.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h +adegamma/rk_aiq_types_adegamma_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/adegamma/rk_aiq_types_adegamma_algo.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/RkAiqCalibDbTypes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h +adehaze/rk_aiq_types_adehaze_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/adehaze/rk_aiq_types_adehaze_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/RkAiqCalibDbTypes.h +adehaze/rk_aiq_types_adehaze_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/adehaze/rk_aiq_types_adehaze_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_algo_des.h +adehaze/rk_aiq_types_adehaze_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/adehaze/rk_aiq_types_adehaze_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h +adpcc/rk_aiq_types_adpcc_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/adpcc/rk_aiq_types_adpcc_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/RkAiqCalibDbTypes.h +adpcc/rk_aiq_types_adpcc_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/adpcc/rk_aiq_types_adpcc_algo.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/base/xcam_common.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h +rk_aiq_types_ae_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_comm.h +math.h +- +string.h +- +stdlib.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/RkAiqCalibDbTypes.h +rk_aiq_types_ae_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h +awb/rk_aiq_types_awb_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/awb/rk_aiq_types_awb_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_algo_des.h +rk_aiq_uapi_ae_int_types.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_algo_des.h +rk_aiq_types_ae_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_af_hw_v200.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h +rk_aiq_types_af_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_algo_des.h +af/rk_aiq_types_af_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/af/rk_aiq_types_af_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h +rk_aiq_types_afec_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_algo_des.h +afec/rk_aiq_types_afec_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/afec/rk_aiq_types_afec_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h +agamma/rk_aiq_types_agamma_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/agamma/rk_aiq_types_agamma_algo.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/RkAiqCalibDbTypes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_algo_des.h +agamma/rk_aiq_types_agamma_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/agamma/rk_aiq_types_agamma_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h +rk_aiq_types_ahdr_stat_v200.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/RkAiqCalibDbTypes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_algo_des.h +rk_aiq_types_ahdr_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h +rk_aiq_types_aie_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h +rk_aiq_types_aldch_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_algo_des.h +aldch/rk_aiq_types_aldch_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/aldch/rk_aiq_types_aldch_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h +alsc/rk_aiq_types_alsc_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/alsc/rk_aiq_types_alsc_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h +alsc/rk_aiq_types_alsc_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/alsc/rk_aiq_types_alsc_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_algo_des.h +alsc/rk_aiq_types_alsc_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/alsc/rk_aiq_types_alsc_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h +anr/rk_aiq_types_anr_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/anr/rk_aiq_types_anr_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h +math.h +- +string.h +- +stdlib.h +- +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_comm.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/RkAiqCalibDbTypes.h +anr/rk_aiq_types_anr_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/anr/rk_aiq_types_anr_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_algo_des.h +anr/rk_aiq_types_anr_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/anr/rk_aiq_types_anr_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h +asharp/rk_aiq_types_asharp_hw.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/asharp/rk_aiq_types_asharp_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_comm.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/RkAiqCalibDbTypes.h +asharp/rk_aiq_types_asharp_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/asharp/rk_aiq_types_asharp_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_algo_des.h +asharp/rk_aiq_types_asharp_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/asharp/rk_aiq_types_asharp_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h +rk_aiq_types_awb_stat_v200.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h +rk_aiq_types_awb_stat_v201.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h +awb/rk_aiq_types_awb_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/awb/rk_aiq_types_awb_algo.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/RkAiqCalibDbTypes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h +rk_aiq_types_awb_stat_v2xx.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h +rk_aiq_types_awb_stat_v2xx.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/base/xcam_common.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_algo_des.h +awb/rk_aiq_types_awb_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/awb/rk_aiq_types_awb_algo_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h +RkAiqCalibDbTypes.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/RkAiqCalibDbTypes.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/base/xcam_common.h +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_comm.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h +opencv2/core/types_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/opencv2/core/types_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h +opencv2/core/types_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/opencv2/core/types_c.h +cxcore.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cxcore.h +cxcore.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cxcore.h +opencv2/core/utility.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/opencv2/core/utility.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h +cv_cpu_config.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_config.h +cv_cpu_helper.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_helper.h +emmintrin.h +- +pmmintrin.h +- +tmmintrin.h +- +smmintrin.h +- +nmmintrin.h +- +nmmintrin.h +- +popcntintrin.h +- +immintrin.h +- +arm_neon.h +- +immintrin.h +- +immintrin.h +- +immintrin.h +- +Intrin.h +- +arm_neon.h +- +arm_neon.h +- +arm_neon.h +- +altivec.h +- +hal/msa_macros.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/msa_macros.h +wasm_simd128.h +- +emmintrin.h +- +Intrin.h +- +arm_neon.h +- +arm_neon.h +- +altivec.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_helper.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h +cvconfig.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvconfig.h +limits.h +- +opencv2/core/hal/interface.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/opencv2/core/hal/interface.h +cv_cpu_dispatch.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h +intrin.h +- +array +- +cstdint +- +stdint.h +- +stdint.h +- +opencv2/core/fast_math.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/opencv2/core/fast_math.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h +cstddef +- +stddef.h +- +stdbool.h +- +cstdint +- +stdint.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/msa_macros.h +msa.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/msa.h +stdint.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h +ipl.h +- +ipl/ipl.h +- +opencv2/core/cvdef.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/opencv2/core/cvdef.h +assert.h +- +stdlib.h +- +string.h +- +float.h +- +opencv2/core.hpp +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/opencv2/core.hpp + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h +config.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h +opencv2/core/core_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/opencv2/core/core_c.h +opencv2/imgproc/imgproc_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/opencv2/imgproc/imgproc_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h +opencv2/imgproc/types_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/opencv2/imgproc/types_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h +opencv2/core/core_c.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/opencv2/core/core_c.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/base/xcam_common.h +rk_aiq_types.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h +stdint.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h +stdint.h +- +stdlib.h +- +stdio.h +- +rk_aiq_comm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h +adebayer/rk_aiq_types_algo_adebayer.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/adebayer/rk_aiq_types_algo_adebayer.h +ae/rk_aiq_types_ae_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/ae/rk_aiq_types_ae_algo.h +awb/rk_aiq_types_awb_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/awb/rk_aiq_types_awb_algo.h +alsc/rk_aiq_types_alsc_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/alsc/rk_aiq_types_alsc_algo.h +accm/rk_aiq_types_accm_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/accm/rk_aiq_types_accm_algo.h +a3dlut/rk_aiq_types_a3dlut_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/a3dlut/rk_aiq_types_a3dlut_algo.h +ahdr/rk_aiq_types_ahdr_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/ahdr/rk_aiq_types_ahdr_algo_int.h +ahdr/rk_aiq_types_ahdr_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/ahdr/rk_aiq_types_ahdr_algo.h +awdr/rk_aiq_types_awdr_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/awdr/rk_aiq_types_awdr_algo_int.h +agamma/rk_aiq_types_agamma_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/agamma/rk_aiq_types_agamma_algo_int.h +adegamma/rk_aiq_types_adegamma_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/adegamma/rk_aiq_types_adegamma_algo_int.h +adehaze/rk_aiq_types_adehaze_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/adehaze/rk_aiq_types_adehaze_algo.h +acp/rk_aiq_types_acp_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/acp/rk_aiq_types_acp_algo.h +aie/rk_aiq_types_aie_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/aie/rk_aiq_types_aie_algo_int.h +aorb/rk_aiq_types_orb_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/aorb/rk_aiq_types_orb_algo.h +asd/rk_aiq_types_asd_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/asd/rk_aiq_types_asd_algo.h +anr/rk_aiq_types_anr_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/anr/rk_aiq_types_anr_algo.h +anr/rk_aiq_types_anr_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/anr/rk_aiq_types_anr_algo_int.h +asharp/rk_aiq_types_asharp_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/asharp/rk_aiq_types_asharp_algo.h +asharp/rk_aiq_types_asharp_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/asharp/rk_aiq_types_asharp_algo_int.h +adpcc/rk_aiq_types_adpcc_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/adpcc/rk_aiq_types_adpcc_algo.h +adpcc/rk_aiq_types_adpcc_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/adpcc/rk_aiq_types_adpcc_algo_int.h +ablc/rk_aiq_types_ablc_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/ablc/rk_aiq_types_ablc_algo.h +ablc/rk_aiq_types_ablc_algo_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/ablc/rk_aiq_types_ablc_algo_int.h +agic/rk_aiq_types_algo_agic.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/agic/rk_aiq_types_algo_agic.h +aldch/rk_aiq_types_aldch_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/aldch/rk_aiq_types_aldch_algo.h +afec/rk_aiq_types_afec_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/afec/rk_aiq_types_afec_algo.h +simulator/isp20_hw_simulator.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/simulator/isp20_hw_simulator.h +af/rk_aiq_af_hw_v200.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/af/rk_aiq_af_hw_v200.h +af/rk_aiq_types_af_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/af/rk_aiq_types_af_algo.h +adehaze/rk_aiq_types_adehaze_algo.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/adehaze/rk_aiq_types_adehaze_algo.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/rk_aiq_algo_des.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h +a3dlut/rk_aiq_uapi_a3dlut_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/a3dlut/rk_aiq_uapi_a3dlut_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h +accm/rk_aiq_uapi_accm_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/accm/rk_aiq_uapi_accm_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h +acp/rk_aiq_uapi_acp_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/acp/rk_aiq_uapi_acp_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h +adehaze/rk_aiq_uapi_adehaze_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/adehaze/rk_aiq_uapi_adehaze_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h +ae/rk_aiq_uapi_ae_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/ae/rk_aiq_uapi_ae_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h +af/rk_aiq_uapi_af_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/af/rk_aiq_uapi_af_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h +afec/rk_aiq_uapi_afec_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/afec/rk_aiq_uapi_afec_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h +agamma/rk_aiq_uapi_agamma_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/agamma/rk_aiq_uapi_agamma_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h +ahdr/rk_aiq_uapi_ahdr_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/ahdr/rk_aiq_uapi_ahdr_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h +aldch/rk_aiq_uapi_aldch_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/aldch/rk_aiq_uapi_aldch_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h +alsc/rk_aiq_uapi_alsc_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/alsc/rk_aiq_uapi_alsc_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h +anr/rk_aiq_uapi_anr_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/anr/rk_aiq_uapi_anr_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h +asharp/rk_aiq_uapi_asharp_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/asharp/rk_aiq_uapi_asharp_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h +awb/rk_aiq_uapi_awb_int.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/awb/rk_aiq_uapi_awb_int.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h +base/xcam_common.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/base/xcam_common.h +rk_aiq_user_api_sysctl.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h +rk_aiq_user_api_awb.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h +rk_aiq_user_api_ae.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h +rk_aiq_user_api_af.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h +rk_aiq_user_api_anr.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h +rk_aiq_user_api_ahdr.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h +rk_aiq_user_api_adehaze.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h +rk_aiq_user_api_alsc.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h +rk_aiq_user_api_accm.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h +rk_aiq_user_api_a3dlut.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h +rk_aiq_user_api_asharp.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h +rk_aiq_user_api_agamma.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h +rk_aiq_user_api_afec.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h +rk_aiq_user_api_aldch.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h +rk_aiq_user_api_acp.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h +rk_aiq.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq.h +rk_aiq_algo_des.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_algo_des.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h +string.h +- +stddef.h +- +stdio.h +- +stdint.h +- +stdlib.h +- +stdbool.h +- +errno.h +- +assert.h +- +math.h +- +xcam_defs.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h +pthread.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h +unistd.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/unistd.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h +features.h +- +bits/types.h +- +stddef.h +- +bits/types/time_t.h +- +bits/types/struct_timespec.h +- +time.h +- +bits/sched.h +- +bits/cpu-set.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h +features.h +- +bits/setjmp.h +- +bits/types/__sigset_t.h +- +bits/setjmp2.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h +features.h +- +bits/types.h +- +bits/signum.h +- +bits/types/sig_atomic_t.h +- +bits/types/sigset_t.h +- +bits/types/struct_timespec.h +- +bits/types/siginfo_t.h +- +bits/siginfo-consts.h +- +bits/types/sigval_t.h +- +bits/types/sigevent_t.h +- +bits/sigevent-consts.h +- +bits/sigaction.h +- +bits/sigcontext.h +- +stddef.h +- +bits/types/stack_t.h +- +sys/ucontext.h +- +bits/sigstack.h +- +bits/ss_flags.h +- +bits/types/struct_sigstack.h +- +bits/pthreadtypes.h +- +bits/sigthread.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h +bits/libc-header-start.h +- +bits/types.h +- +bits/wchar.h +- +bits/wordsize.h +- +bits/stdint-intn.h +- +bits/stdint-uintn.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h +bits/libc-header-start.h +- +stddef.h +- +stdarg.h +- +bits/types.h +- +bits/types/__fpos_t.h +- +bits/types/__fpos64_t.h +- +bits/types/__FILE.h +- +bits/types/FILE.h +- +bits/types/struct_FILE.h +- +bits/types/cookie_io_functions_t.h +- +stdarg.h +- +bits/stdio_lim.h +- +bits/sys_errlist.h +- +bits/getopt_posix.h +- +bits/stdio.h +- +bits/stdio2.h +- +bits/stdio-ldbl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h +bits/libc-header-start.h +- +stddef.h +- +bits/waitflags.h +- +bits/waitstatus.h +- +bits/floatn.h +- +bits/types/locale_t.h +- +sys/types.h +- +alloca.h +- +bits/stdlib-bsearch.h +- +bits/stdlib-float.h +- +bits/stdlib.h +- +bits/stdlib-ldbl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h +bits/libc-header-start.h +- +stddef.h +- +bits/types/locale_t.h +- +strings.h +- +bits/string_fortified.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h +features.h +- +stddef.h +- +bits/types/locale_t.h +- +bits/strings_fortified.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h +features.h +- +bits/wordsize.h +- +bits/long-double.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h +fcntl.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h +features.h +- +bits/ioctls.h +- +bits/ioctl-types.h +- +sys/ttydefaults.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ipc.h +features.h +- +bits/ipctypes.h +- +bits/ipc.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h +features.h +- +bits/types.h +- +stddef.h +- +bits/mman.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/poll.h +features.h +- +bits/poll.h +- +bits/types/__sigset_t.h +- +bits/types/struct_timespec.h +- +bits/poll2.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h +features.h +- +bits/types.h +- +bits/select.h +- +bits/types/sigset_t.h +- +bits/types/time_t.h +- +bits/types/struct_timeval.h +- +bits/types/struct_timespec.h +- +bits/select2.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/shm.h +features.h +- +stddef.h +- +sys/ipc.h +- +bits/shm.h +- +bits/types/time_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h +features.h +- +bits/types/struct_iovec.h +- +stddef.h +- +bits/socket.h +- +bits/types/struct_osockaddr.h +- +bits/socket2.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h +features.h +- +bits/types.h +- +bits/types/struct_timespec.h +- +bits/types/time_t.h +- +bits/stat.h +- +bits/statx.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h +features.h +- +bits/types.h +- +bits/types/time_t.h +- +bits/types/struct_timeval.h +- +sys/select.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h +features.h +- +bits/types.h +- +bits/types/clock_t.h +- +bits/types/clockid_t.h +- +bits/types/time_t.h +- +bits/types/timer_t.h +- +stddef.h +- +bits/stdint-intn.h +- +endian.h +- +sys/select.h +- +bits/pthreadtypes.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h +features.h +- +bits/types/sigset_t.h +- +bits/types/stack_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiff.h +tiffconf.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffconf.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffconf.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffio.h +tiff.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiff.h +tiffvers.h +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffvers.h +windows.h +- +stdio.h +- +stdarg.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffvers.h + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h +features.h +- +stddef.h +- +bits/time.h +- +bits/types/clock_t.h +- +bits/types/time_t.h +- +bits/types/struct_tm.h +- +bits/types/struct_timespec.h +- +bits/types/clockid_t.h +- +bits/types/timer_t.h +- +bits/types/struct_itimerspec.h +- +bits/types/locale_t.h +- + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h +features.h +- +bits/posix_opt.h +- +bits/environments.h +- +bits/types.h +- +stddef.h +- +bits/confname.h +- +bits/getopt_posix.h +- +bits/unistd.h +- + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/DependInfo.cmake b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/DependInfo.cmake new file mode 100644 index 0000000..6a66f03 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/DependInfo.cmake @@ -0,0 +1,79 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + "CXX" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c" "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c" "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "RKAIQ" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include" + "../libs/common/drm/include" + "../libs/common/drm/include/libdrm" + "../libs/common" + "../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include" + "../libs/platform/RV1109_1126/libjpeg/include" + "../libs/platform/RV1109_1126/libpng/include" + "../libs/platform/RV1109_1126/zlib/include" + "../include" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser" + ".././include/librtsp" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv" + ) +set(CMAKE_DEPENDS_CHECK_CXX + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp" "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc" "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o" + ) +set(CMAKE_CXX_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_CXX + "RKAIQ" + ) + +# The include file search paths: +set(CMAKE_CXX_TARGET_INCLUDE_PATH + "../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include" + "../libs/common/drm/include" + "../libs/common/drm/include/libdrm" + "../libs/common" + "../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include" + "../libs/platform/RV1109_1126/libjpeg/include" + "../libs/platform/RV1109_1126/libpng/include" + "../libs/platform/RV1109_1126/zlib/include" + "../include" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser" + ".././include/librtsp" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include" + "/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/build.make b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/build.make new file mode 100644 index 0000000..58e306a --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/build.make @@ -0,0 +1,156 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build + +# Include any dependencies generated for this target. +include CMakeFiles/rknn_yolo_demo_test.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/rknn_yolo_demo_test.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/rknn_yolo_demo_test.dir/flags.make + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: CMakeFiles/rknn_yolo_demo_test.dir/flags.make +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../src/drm_func.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c > CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.i + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c -o CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.s + +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: CMakeFiles/rknn_yolo_demo_test.dir/flags.make +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../src/rga_func.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c + +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c > CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.i + +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c -o CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.s + +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: CMakeFiles/rknn_yolo_demo_test.dir/flags.make +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../src/yolo.cc + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc + +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc > CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.i + +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc -o CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.s + +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: CMakeFiles/rknn_yolo_demo_test.dir/flags.make +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../src/main.cpp + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp + +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp > CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.i + +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp -o CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.s + +# Object files for target rknn_yolo_demo_test +rknn_yolo_demo_test_OBJECTS = \ +"CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o" \ +"CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o" \ +"CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o" \ +"CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o" + +# External object files for target rknn_yolo_demo_test +rknn_yolo_demo_test_EXTERNAL_OBJECTS = + +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/build.make +rknn_yolo_demo_test: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib/librknn_api.so +rknn_yolo_demo_test: ../libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.a +rknn_yolo_demo_test: ../libs/platform/RV1109_1126/libpng/lib/Linux/libpng.a +rknn_yolo_demo_test: ../libs/platform/RV1109_1126/zlib/lib/Linux/libz.a +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_features2d.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_flann.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_highgui.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_freetype.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_videoio.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_imgcodecs.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_imgproc.so.3.4.12 +rknn_yolo_demo_test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_core.so.3.4.12 +rknn_yolo_demo_test: CMakeFiles/rknn_yolo_demo_test.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Linking CXX executable rknn_yolo_demo_test" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/rknn_yolo_demo_test.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/rknn_yolo_demo_test.dir/build: rknn_yolo_demo_test + +.PHONY : CMakeFiles/rknn_yolo_demo_test.dir/build + +CMakeFiles/rknn_yolo_demo_test.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/rknn_yolo_demo_test.dir/cmake_clean.cmake +.PHONY : CMakeFiles/rknn_yolo_demo_test.dir/clean + +CMakeFiles/rknn_yolo_demo_test.dir/depend: + cd /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/rknn_yolo_demo_test.dir/depend + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/cmake_clean.cmake b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/cmake_clean.cmake new file mode 100644 index 0000000..9a3bbf9 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/cmake_clean.cmake @@ -0,0 +1,13 @@ +file(REMOVE_RECURSE + "CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o" + "CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o" + "CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o" + "CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o" + "rknn_yolo_demo_test" + "rknn_yolo_demo_test.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C CXX) + include(CMakeFiles/rknn_yolo_demo_test.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.internal b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.internal new file mode 100644 index 0000000..45cebbb --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.internal @@ -0,0 +1,978 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curlver.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/system.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/easy.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/multi.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/urlapi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstddef + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_neon.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_fp16.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/climits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/algorithm + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algo.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/algorithmfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_heap.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tempbuf.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uniform_int_dist.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/limits + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cfloat + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/float.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/complex + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/functional + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/refwrap.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_function.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/chrono + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ratio + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/parse_numbers.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/map + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tree.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/aligned_buffer.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_map.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multimap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/set + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_set.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multiset.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/unordered_map + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable_policy.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unordered_map.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/deque + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_deque.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/deque.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_list.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocated_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/list.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/queue + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_queue.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/librtsp/rtsp_demo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/thread + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/memory + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_raw_storage_iter.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/concurrence.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_atomic.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_lockfree_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/auto_ptr.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_resize.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_write.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/CImg/CImg.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdarg + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.make b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.make new file mode 100644 index 0000000..d58bce2 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.make @@ -0,0 +1,2216 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curlver.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/easy.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/multi.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstddef \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_neon.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_fp16.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/climits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/algorithm \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algo.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/algorithmfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_heap.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tempbuf.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uniform_int_dist.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/limits \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cfloat \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/float.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/complex \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/functional \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/refwrap.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_function.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/chrono \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ratio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/parse_numbers.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/map \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tree.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/aligned_buffer.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_map.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multimap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/set \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_set.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multiset.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/unordered_map \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable_policy.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unordered_map.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/deque \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_deque.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/deque.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_list.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocated_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/list.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/queue \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_queue.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/librtsp/rtsp_demo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/thread \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/memory \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_raw_storage_iter.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/concurrence.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_atomic.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_lockfree_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/auto_ptr.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_resize.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_write.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/CImg/CImg.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdarg \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/CImg/CImg.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_write.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_resize.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/auto_ptr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_lockfree_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_atomic.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/concurrence.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/memory: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/librtsp/rtsp_demo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_queue.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/queue: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/list.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocated_ptr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/unordered_map: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multiset.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curlver.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_map.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstddef: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/urlapi.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable_policy.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/list: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/algorithm: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tempbuf.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tree.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_heap.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/thread: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/system.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/algorithmfwd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uniform_int_dist.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/climits: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/aligned_buffer.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_raw_storage_iter.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_neon.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_fp16.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdarg: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/refwrap.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algo.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/map: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cfloat: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/float.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/complex: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/functional: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_function.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_list.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/limits: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/set: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/chrono: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ratio: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/parse_numbers.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multimap.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_set.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/easy.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/deque.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unordered_map.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/deque: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/multi.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_deque.h: diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.ts b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.ts new file mode 100644 index 0000000..b107980 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for rknn_yolo_demo_test. diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/depend.internal b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/depend.internal new file mode 100644 index 0000000..568dce1 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/depend.internal @@ -0,0 +1,803 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o + ../include/drm_func.h + ../libs/common/drm/include/libdrm/drm.h + ../libs/common/drm/include/libdrm/drm_fourcc.h + ../libs/common/drm/include/libdrm/drm_mode.h + ../libs/common/drm/include/xf86drm.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o + ../include/rga_func.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o + ../include/curl/curl.h + ../include/curl/curlver.h + ../include/curl/easy.h + ../include/curl/multi.h + ../include/curl/system.h + ../include/curl/typecheck-gcc.h + ../include/curl/urlapi.h + ../include/drm_func.h + ../include/librtsp/rtsp_demo.h + ../include/rga_func.h + ../include/yolo.h + ../libs/common/CImg/CImg.h + ../libs/common/drm/include/libdrm/drm.h + ../libs/common/drm/include/libdrm/drm_fourcc.h + ../libs/common/drm/include/libdrm/drm_mode.h + ../libs/common/drm/include/xf86drm.h + ../libs/common/stb/stb_image.h + ../libs/common/stb/stb_image_resize.h + ../libs/common/stb/stb_image_write.h + ../libs/platform/RV1109_1126/libjpeg/include/jconfig.h + ../libs/platform/RV1109_1126/libjpeg/include/jerror.h + ../libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h + ../libs/platform/RV1109_1126/libjpeg/include/jpeglib.h + ../libs/platform/RV1109_1126/libpng/include/png.h + ../libs/platform/RV1109_1126/libpng/include/pngconf.h + ../libs/platform/RV1109_1126/libpng/include/pnglibconf.h + ../libs/platform/RV1109_1126/zlib/include/zconf.h + ../libs/platform/RV1109_1126/zlib/include/zlib.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ipc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ipctypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-finite.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathinline.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/poll.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/poll2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/shm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv/cxcore.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utils/instrumentation.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utils/tls.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/freetype.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_af_hw_v200.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_helper.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/msa_macros.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ipc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/poll.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/shm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiff.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffconf.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffvers.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o + ../include/rga_func.h + ../include/yolo.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h + ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-finite.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathinline.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/depend.make b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/depend.make new file mode 100644 index 0000000..a48ae26 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/depend.make @@ -0,0 +1,803 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../include/drm_func.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../libs/common/drm/include/libdrm/drm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../libs/common/drm/include/libdrm/drm_fourcc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../libs/common/drm/include/libdrm/drm_mode.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../libs/common/drm/include/xf86drm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: ../src/drm_func.c +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../include/rga_func.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: ../src/rga_func.c +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/curl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/curlver.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/easy.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/multi.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/system.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/typecheck-gcc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/curl/urlapi.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/drm_func.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/librtsp/rtsp_demo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/rga_func.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../include/yolo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/CImg/CImg.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/drm/include/libdrm/drm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/drm/include/libdrm/drm_fourcc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/drm/include/libdrm/drm_mode.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/drm/include/xf86drm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/stb/stb_image.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/stb/stb_image_resize.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/common/stb/stb_image_write.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libjpeg/include/jconfig.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libjpeg/include/jerror.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libjpeg/include/jpeglib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libpng/include/png.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libpng/include/pngconf.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/libpng/include/pnglibconf.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/zlib/include/zconf.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/platform/RV1109_1126/zlib/include/zlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../src/main.cpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: ../src/main.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ipc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ipctypes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-finite.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathinline.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/poll.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/poll2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/shm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv/cxcore.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utils/instrumentation.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utils/tls.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/freetype.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_af_hw_v200.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_helper.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/msa_macros.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ipc.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/poll.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/shm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiff.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffconf.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/tiffvers.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../include/rga_func.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../include/yolo.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: ../src/yolo.cc +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-finite.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathinline.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio2.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-bsearch.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-ldbl.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/string_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/strings_fortified.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/unistd.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/flags.make b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/flags.make new file mode 100644 index 0000000..81283e6 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/flags.make @@ -0,0 +1,17 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# compile C with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +# compile CXX with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +C_FLAGS = -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + +C_DEFINES = -DRKAIQ + +C_INCLUDES = -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/./include/librtsp -isystem /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include -isystem /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv + +CXX_FLAGS = -std=c++11 -pthread -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type -std=gnu++11 + +CXX_DEFINES = -DRKAIQ + +CXX_INCLUDES = -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/./include/librtsp -isystem /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include -isystem /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/link.txt b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/link.txt new file mode 100644 index 0000000..e0e2153 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/link.txt @@ -0,0 +1 @@ +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot -std=c++11 -pthread CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o -o rknn_yolo_demo_test -L/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/lib -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/./include/librtsp -Wl,-rpath,/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib:/usr/lib:/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include:/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/lib:/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/./include/librtsp: ../libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib/librknn_api.so ../libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.a ../libs/platform/RV1109_1126/libpng/lib/Linux/libpng.a ../libs/platform/RV1109_1126/zlib/lib/Linux/libz.a /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_features2d.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_flann.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_highgui.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_freetype.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so -Wl,-Bstatic -lrtsp -Wl,-Bdynamic -leasymedia -lrga -lrkaiq -lsample_common_isp -ldl /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_videoio.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_imgcodecs.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_imgproc.so.3.4.12 /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libopencv_core.so.3.4.12 diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/progress.make b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/progress.make new file mode 100644 index 0000000..33e6bff --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/progress.make @@ -0,0 +1,6 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 +CMAKE_PROGRESS_4 = 4 +CMAKE_PROGRESS_5 = 5 + diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o new file mode 100644 index 0000000..cca60b0 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o differ diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o.d b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o.d new file mode 100644 index 0000000..51b5f5f --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o.d @@ -0,0 +1,106 @@ +CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/drm_func.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o new file mode 100644 index 0000000..35a39e2 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o differ diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o.d b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o.d new file mode 100644 index 0000000..7ec31f4 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o.d @@ -0,0 +1,637 @@ +CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/main.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/malloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curlver.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/easy.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/multi.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/curl.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rga/im2d.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/drm_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/input-event-codes.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/xf86drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_api.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_adec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_aenc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ai.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_ao.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_buffer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_event.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_move_detection.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_muxer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_occlusion_detection.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_rga.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vdec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vmix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_vo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/rkmedia_venc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/easymedia/sample_common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_imgproc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/xcore/base/xcam_defs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adebayer/rk_aiq_types_algo_adebayer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/rk_aiq_comm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v200.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v2xx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_stat_v201.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/iq_parser/RkAiqCalibDbTypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/rk_aiq_algo_des.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_stat_v200.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awdr/rk_aiq_types_awdr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_types_agamma_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adegamma/rk_aiq_types_adegamma_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_types_acp_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aie/rk_aiq_types_aie_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aorb/rk_aiq_types_orb_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asd/rk_aiq_types_asd_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_types_anr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_types_asharp_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adpcc/rk_aiq_types_adpcc_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_hw.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ablc/rk_aiq_types_ablc_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agic/rk_aiq_types_algo_agic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_awb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_uapi_awb_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/awb/rk_aiq_types_awb_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ae.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_uapi_ae_int_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ae/rk_aiq_types_ae_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_af.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_uapi_af_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/af/rk_aiq_types_af_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_anr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/anr/rk_aiq_uapi_anr_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_ahdr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_uapi_ahdr_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/ahdr/rk_aiq_types_ahdr_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_adehaze.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_uapi_adehaze_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/adehaze/rk_aiq_types_adehaze_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_alsc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_uapi_alsc_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/alsc/rk_aiq_types_alsc_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_accm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_uapi_accm_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/accm/rk_aiq_types_accm_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_a3dlut.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_uapi_a3dlut_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/a3dlut/rk_aiq_types_a3dlut_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_asharp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/asharp/rk_aiq_uapi_asharp_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_agamma.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/agamma/rk_aiq_uapi_agamma_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_uapi_afec_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/afec/rk_aiq_types_afec_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_aldch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_uapi_aldch_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/aldch/rk_aiq_types_aldch_algo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_acp.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/algos/acp/rk_aiq_uapi_acp_int.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_sysctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/opencv_modules.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cvdef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/hal/interface.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstddef \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/cv_cpu_dispatch.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_neon.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/arm_fp16.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/version.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/base.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/climits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/algorithm \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algo.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/algorithmfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_heap.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tempbuf.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uniform_int_dist.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/limits \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cmath \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ptr.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/neon_utils.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/vsx_utils.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/check.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/traits.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/matx.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/saturate.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/fast_math.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/types.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cfloat \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/float.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/bufferpool.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/mat.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/persistence.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/operations.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvstd.inl.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/complex \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/sstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/sstream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/utility.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/functional \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/refwrap.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_function.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/core_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/core/types_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/optim.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/ovx.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cvdef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/calib3d.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/features2d.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/miniflann.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/defines.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/flann/config.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/affine.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/calib3d/calib3d_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/async.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/chrono \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ratio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/parse_numbers.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dict.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/map \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_tree.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/aligned_buffer.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_map.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multimap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/layer.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/utils/inference_engine.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/dnn/dnn.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/flann_base.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/general.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/matrix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/params.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/any.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/saving.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/nn_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/result_set.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/set \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_set.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_multiset.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/all_indices.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dynamic_bitset.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/dist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/heap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/allocator.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/random.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kdtree_single_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/kmeans_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/logger.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/composite_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/linear_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/hierarchical_clustering_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/lsh_table.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/unordered_map \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hashtable_policy.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unordered_map.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/autotuned_index.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/ground_truth.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/index_testing.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/timer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/flann/sampling.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/highgui.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgcodecs.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videoio.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/highgui/highgui_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/imgproc_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/common/opencv2/imgproc/types_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/imgproc.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/ml/ml.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/detection_based_tracker.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/objdetect/objdetect_c.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/deque \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_deque.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/deque.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/photo/photo_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/emdL1.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_transformer.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/hist_cost.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/shape/shape_distance.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/warpers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda_types.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/core/cuda.inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers_inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/warpers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/motion_estimators.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/matchers.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_list.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocated_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/list.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/util_inl.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/queue \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_queue.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/exposure_compensate.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/seam_finders.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/blenders.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/stitching/detail/camera.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/superres/optical_flow.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/background_segm.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/video/tracking_c.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/stabilizer.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/global_motion.hpp \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/optical_flow.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_core.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/outlier_rejection.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/motion_stabilizing.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/frame_source.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/log.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/inpainting.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/fast_marching_inl.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/deblurring.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/wobble_suppression.hpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/opencv2/videostab/ring_buffer.hpp \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/librtsp/rtsp_demo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/rkaiq/uAPI/rk_aiq_user_api_afec.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/thread \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/memory \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_raw_storage_iter.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/concurrence.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/shared_ptr_atomic.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/atomic_lockfree_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/auto_ptr.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_resize.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/stb/stb_image_write.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/common/CImg/CImg.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdarg \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fnmatch.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/setjmp.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o new file mode 100644 index 0000000..1a4a790 Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o differ diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o.d b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o.d new file mode 100644 index 0000000..7ae726c --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o.d @@ -0,0 +1,85 @@ +CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/rga_func.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdbool.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o new file mode 100644 index 0000000..b55157f Binary files /dev/null and b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o differ diff --git a/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o.d b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o.d new file mode 100644 index 0000000..ead5709 --- /dev/null +++ b/rknn_yolo_demo/build/CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o.d @@ -0,0 +1,143 @@ +CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/src/yolo.cc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/math.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/math-vector.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libm-simd-decl-stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/flt-eval-method.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-logb.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fp-fast.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-helper-functions.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mathcalls-narrow.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/iscanonical.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/yolo.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include/rga_func.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dlfcn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dlfcn.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/mman-shared.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h diff --git a/rknn_yolo_demo/build/Makefile b/rknn_yolo_demo/build/Makefile new file mode 100644 index 0000000..dc3d997 --- /dev/null +++ b/rknn_yolo_demo/build/Makefile @@ -0,0 +1,318 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles/progress.marks + $(MAKE) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named rknn_yolo_demo_test + +# Build rule for target. +rknn_yolo_demo_test: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 rknn_yolo_demo_test +.PHONY : rknn_yolo_demo_test + +# fast build rule for target. +rknn_yolo_demo_test/fast: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/build +.PHONY : rknn_yolo_demo_test/fast + +src/drm_func.o: src/drm_func.c.o + +.PHONY : src/drm_func.o + +# target to build an object file +src/drm_func.c.o: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.o +.PHONY : src/drm_func.c.o + +src/drm_func.i: src/drm_func.c.i + +.PHONY : src/drm_func.i + +# target to preprocess a source file +src/drm_func.c.i: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.i +.PHONY : src/drm_func.c.i + +src/drm_func.s: src/drm_func.c.s + +.PHONY : src/drm_func.s + +# target to generate assembly for a file +src/drm_func.c.s: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/drm_func.c.s +.PHONY : src/drm_func.c.s + +src/main.o: src/main.cpp.o + +.PHONY : src/main.o + +# target to build an object file +src/main.cpp.o: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.o +.PHONY : src/main.cpp.o + +src/main.i: src/main.cpp.i + +.PHONY : src/main.i + +# target to preprocess a source file +src/main.cpp.i: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.i +.PHONY : src/main.cpp.i + +src/main.s: src/main.cpp.s + +.PHONY : src/main.s + +# target to generate assembly for a file +src/main.cpp.s: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/main.cpp.s +.PHONY : src/main.cpp.s + +src/rga_func.o: src/rga_func.c.o + +.PHONY : src/rga_func.o + +# target to build an object file +src/rga_func.c.o: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.o +.PHONY : src/rga_func.c.o + +src/rga_func.i: src/rga_func.c.i + +.PHONY : src/rga_func.i + +# target to preprocess a source file +src/rga_func.c.i: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.i +.PHONY : src/rga_func.c.i + +src/rga_func.s: src/rga_func.c.s + +.PHONY : src/rga_func.s + +# target to generate assembly for a file +src/rga_func.c.s: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/rga_func.c.s +.PHONY : src/rga_func.c.s + +src/yolo.o: src/yolo.cc.o + +.PHONY : src/yolo.o + +# target to build an object file +src/yolo.cc.o: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.o +.PHONY : src/yolo.cc.o + +src/yolo.i: src/yolo.cc.i + +.PHONY : src/yolo.i + +# target to preprocess a source file +src/yolo.cc.i: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.i +.PHONY : src/yolo.cc.i + +src/yolo.s: src/yolo.cc.s + +.PHONY : src/yolo.s + +# target to generate assembly for a file +src/yolo.cc.s: + $(MAKE) -f CMakeFiles/rknn_yolo_demo_test.dir/build.make CMakeFiles/rknn_yolo_demo_test.dir/src/yolo.cc.s +.PHONY : src/yolo.cc.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... install/strip" + @echo "... install/local" + @echo "... install" + @echo "... list_install_components" + @echo "... rebuild_cache" + @echo "... edit_cache" + @echo "... rknn_yolo_demo_test" + @echo "... src/drm_func.o" + @echo "... src/drm_func.i" + @echo "... src/drm_func.s" + @echo "... src/main.o" + @echo "... src/main.i" + @echo "... src/main.s" + @echo "... src/rga_func.o" + @echo "... src/rga_func.i" + @echo "... src/rga_func.s" + @echo "... src/yolo.o" + @echo "... src/yolo.i" + @echo "... src/yolo.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/rknn_yolo_demo/build/cmake_install.cmake b/rknn_yolo_demo/build/cmake_install.cmake new file mode 100644 index 0000000..834db6c --- /dev/null +++ b/rknn_yolo_demo/build/cmake_install.cmake @@ -0,0 +1,77 @@ +# Install script for directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "TRUE") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test" + RPATH "lib") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/." TYPE EXECUTABLE FILES "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/rknn_yolo_demo_test") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test") + file(RPATH_CHANGE + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test" + OLD_RPATH "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib:/usr/lib:/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/include:/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/lib:/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/./include/librtsp:" + NEW_RPATH "lib") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./rknn_yolo_demo_test") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/./" TYPE DIRECTORY FILES "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/model") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE PROGRAM FILES "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib/librknn_api.so") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/build/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/rknn_yolo_demo/build/install_manifest.txt b/rknn_yolo_demo/build/install_manifest.txt new file mode 100644 index 0000000..5c3922d --- /dev/null +++ b/rknn_yolo_demo/build/install_manifest.txt @@ -0,0 +1,9 @@ +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/./rknn_yolo_demo_test +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/coco_80_labels_list.txt +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/coco_dataset_path.txt +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/bus.jpg +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/RK_anchors_yolov5.txt +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/dog.jpg +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/RK_anchors_yolov7.txt +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/.//model/bus640.jpg +/home/atk/RV1126/rv1126_ai/by_cmake/720P/rknn_yolo_demo/install/rknn_yolo_demo_test/lib/librknn_api.so \ No newline at end of file diff --git a/rknn_yolo_demo/build/rknn_yolo_demo_test b/rknn_yolo_demo/build/rknn_yolo_demo_test new file mode 100644 index 0000000..eed153c Binary files /dev/null and b/rknn_yolo_demo/build/rknn_yolo_demo_test differ diff --git a/rknn_yolo_demo/include/curl/curl.h b/rknn_yolo_demo/include/curl/curl.h new file mode 100644 index 0000000..a9754fd --- /dev/null +++ b/rknn_yolo_demo/include/curl/curl.h @@ -0,0 +1,2897 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * https://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ + !defined(WIN32) && !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, + CURLSSLBACKEND_BEARSSL = 13 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or WolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1<<2) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_IMMEDIATELY (1<<0) + +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif + +#ifdef CURL_ISOCPP +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define SLISTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +/* handy aliases that make no run-time difference */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* + * This macro-mania below setups the CURLOPT_[what] enum, to be used with + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] + * word. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(WRITEDATA, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CINIT(USERPWD, STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CINIT(PROXYUSERPWD, STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(READDATA, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CINIT(HTTPHEADER, SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, STRINGPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(HEADERDATA, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, SLISTPOINT, 39), + + CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, SLISTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, STRINGPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CINIT(COOKIELIST, STRINGPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, STRINGPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, STRINGPOINT, 173), + CINIT(PASSWORD, STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, STRINGPOINT, 175), + CINIT(PROXYPASSWORD, STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */ + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, STRINGPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CINIT(SSL_OPTIONS, LONG, 216), + + /* Set the SMTP auth originator */ + CINIT(MAIL_AUTH, STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CINIT(SASL_IR, LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CINIT(XOAUTH2_BEARER, STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_INTERFACE, STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223), + + /* Set authentication options directly */ + CINIT(LOGIN_OPTIONS, STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_NPN, LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_ALPN, LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CINIT(PROXYHEADER, SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CINIT(SSL_VERIFYSTATUS, LONG, 232), + + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + + /* Do not squash dot-dot sequences */ + CINIT(PATH_AS_IS, LONG, 234), + + /* Proxy Service Name */ + CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235), + + /* Service Name */ + CINIT(SERVICE_NAME, STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CINIT(PIPEWAIT, LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CINIT(STREAM_WEIGHT, LONG, 239), + + /* Set stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS, OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CINIT(TFTP_NO_OPTIONS, LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CINIT(CONNECT_TO, SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CINIT(TCP_FASTOPEN, LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CINIT(KEEP_SENDING_ON_ERROR, LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAINFO, STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAPATH, STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CINIT(PROXY_SSL_VERIFYPEER, LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CINIT(PROXY_SSL_VERIFYHOST, LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CINIT(PROXY_SSLVERSION, LONG, 250), + + /* Set a username for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CINIT(PROXY_SSLCERT, STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CINIT(PROXY_SSLKEY, STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259), + + /* CRL file for proxy */ + CINIT(PROXY_CRLFILE, STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CINIT(PROXY_SSL_OPTIONS, LONG, 261), + + /* Name of pre proxy to use. */ + CINIT(PRE_PROXY, STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265), + + /* The request target, instead of extracted from the URL */ + CINIT(REQUEST_TARGET, STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CINIT(SOCKS5_AUTH, LONG, 267), + + /* Enable/disable SSH compression */ + CINIT(SSH_COMPRESSION, LONG, 268), + + /* Post MIME data. */ + CINIT(MIMEPOST, OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CINIT(TIMEVALUE_LARGE, OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271), + + /* Function that will be called before a resolver request is made */ + CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CINIT(HAPROXYPROTOCOL, LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CINIT(TLS13_CIPHERS, STRINGPOINT, 276), + CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278), + + /* DNS-over-HTTPS URL */ + CINIT(DOH_URL, STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CINIT(UPLOAD_BUFFERSIZE, LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CINIT(UPKEEP_INTERVAL_MS, LONG, 281), + + /* Specify URL using CURL URL API. */ + CINIT(CURLU, OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CINIT(TRAILERDATA, OBJECTPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CINIT(HTTP09_ALLOWED, LONG, 285), + + /* alt-svc control bitmask */ + CINIT(ALTSVC_CTRL, LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CINIT(ALTSVC, STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CINIT(MAXAGE_CONN, LONG, 288), + + /* SASL authorisation identity */ + CINIT(SASL_AUTHZID, STRINGPOINT, 289), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + CURL_HTTP_VERSION_3 = 30, /* Makes use of explicit HTTP/3 without fallback. + Use CURLOPT_ALTSVC to enable HTTP/3 upgrade */ + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a zero-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime_s curl_mime; /* Mime context. */ +typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +/* Old form API. */ +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CFINIT(STREAM), + CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +typedef struct { + curl_sslbackend id; + const char *name; +} curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS + and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + /* Fill in new entries below here! */ + + /* Preferably these would be defined conditionally based on the + sizeof curl_off_t being 64-bits */ + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + + CURLINFO_LASTONE = 57 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_SIXTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_SIXTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ + +#define CURL_VERSION_ESNI (1<<26) /* ESNI support */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* CURLINC_CURL_H */ diff --git a/rknn_yolo_demo/include/curl/curlver.h b/rknn_yolo_demo/include/curl/curlver.h new file mode 100644 index 0000000..85b9355 --- /dev/null +++ b/rknn_yolo_demo/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.68.0" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 68 +#define LIBCURL_VERSION_PATCH 0 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074400 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "2020-01-08" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* CURLINC_CURLVER_H */ diff --git a/rknn_yolo_demo/include/curl/easy.h b/rknn_yolo_demo/include/curl/easy.h new file mode 100644 index 0000000..592f5d3 --- /dev/null +++ b/rknn_yolo_demo/include/curl/easy.h @@ -0,0 +1,112 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rknn_yolo_demo/include/curl/libcurl.so b/rknn_yolo_demo/include/curl/libcurl.so new file mode 100644 index 0000000..753de06 --- /dev/null +++ b/rknn_yolo_demo/include/curl/libcurl.so @@ -0,0 +1 @@ +libcurl.so.4.6.0 \ No newline at end of file diff --git a/rknn_yolo_demo/include/curl/mprintf.h b/rknn_yolo_demo/include/curl/mprintf.h new file mode 100644 index 0000000..f615ed7 --- /dev/null +++ b/rknn_yolo_demo/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/rknn_yolo_demo/include/curl/multi.h b/rknn_yolo_demo/include/curl/multi.h new file mode 100644 index 0000000..04996ff --- /dev/null +++ b/rknn_yolo_demo/include/curl/multi.h @@ -0,0 +1,468 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a zero-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +#undef CINIT /* re-using the same name as in curl.h */ + +#ifdef CURL_ISOCPP +#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLMOPT_/**/name = type + number +#endif + +typedef enum { + /* This is the socket callback function pointer */ + CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CINIT(SOCKETDATA, OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CINIT(PIPELINING, LONG, 3), + + /* This is the timer callback function pointer */ + CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CINIT(TIMERDATA, OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CINIT(MAXCONNECTS, LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CINIT(MAX_HOST_CONNECTIONS, LONG, 7), + + /* maximum number of requests in a pipeline */ + CINIT(MAX_PIPELINE_LENGTH, LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10), + + /* a list of site names(+port) that are blacklisted from + pipelining */ + CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11), + + /* a list of server types that are blacklisted from + pipelining */ + CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13), + + /* This is the server push callback function pointer */ + CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CINIT(PUSHDATA, OBJECTPOINT, 15), + + /* maximum number of concurrent streams to support on a connection */ + CINIT(MAX_CONCURRENT_STREAMS, LONG, 16), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. + * + * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/rknn_yolo_demo/include/curl/stdcheaders.h b/rknn_yolo_demo/include/curl/stdcheaders.h new file mode 100644 index 0000000..a6bdc1a --- /dev/null +++ b/rknn_yolo_demo/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* CURLINC_STDCHEADERS_H */ diff --git a/rknn_yolo_demo/include/curl/system.h b/rknn_yolo_demo/include/curl/system.h new file mode 100644 index 0000000..867af61 --- /dev/null +++ b/rknn_yolo_demo/include/curl/system.h @@ -0,0 +1,504 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# if defined(__e2k__) /* MCST eLbrus C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# else /* Local (or Little) C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + defined(__e2k__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define CURLINC_OFF_T_C_HLPR2(x) x +# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* CURLINC_SYSTEM_H */ diff --git a/rknn_yolo_demo/include/curl/typecheck-gcc.h b/rknn_yolo_demo/include/curl/typecheck-gcc.h new file mode 100644 index 0000000..03c84fc --- /dev/null +++ b/rknn_yolo_demo/include/curl/typecheck-gcc.h @@ -0,0 +1,699 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(curlcheck_sometype_option(_curl_opt)) + * if(!curlcheck_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define curlcheck_sometype_option, curlcheck_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(curlcheck_long_option(_curl_opt)) \ + if(!curlcheck_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(curlcheck_off_t_option(_curl_opt)) \ + if(!curlcheck_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(curlcheck_string_option(_curl_opt)) \ + if(!curlcheck_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(curlcheck_write_cb_option(_curl_opt)) \ + if(!curlcheck_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!curlcheck_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!curlcheck_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!curlcheck_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!curlcheck_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!curlcheck_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!curlcheck_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!curlcheck_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!curlcheck_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(curlcheck_conv_cb_option(_curl_opt)) \ + if(!curlcheck_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!curlcheck_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(curlcheck_cb_data_option(_curl_opt)) \ + if(!curlcheck_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!curlcheck_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!curlcheck_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(curlcheck_postfields_option(_curl_opt)) \ + if(!curlcheck_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!curlcheck_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!curlcheck_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(curlcheck_slist_option(_curl_opt)) \ + if(!curlcheck_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!curlcheck_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ + }) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ + __extension__({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(curlcheck_string_info(_curl_info)) \ + if(!curlcheck_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(curlcheck_long_info(_curl_info)) \ + if(!curlcheck_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(curlcheck_double_info(_curl_info)) \ + if(!curlcheck_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(curlcheck_slist_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(curlcheck_tlssessioninfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(curlcheck_certinfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(curlcheck_socket_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(curlcheck_off_t_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ + }) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define CURLWARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +CURLWARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +CURLWARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +CURLWARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +CURLWARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +CURLWARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +CURLWARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +CURLWARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define curlcheck_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define curlcheck_off_t_option(option) \ + ((option) > CURLOPTTYPE_OFF_T) + +/* evaluates to true if option takes a char* argument */ +#define curlcheck_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SASL_AUTHZID || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define curlcheck_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define curlcheck_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define curlcheck_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PRIVATE || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define curlcheck_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define curlcheck_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define curlcheck_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define curlcheck_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define curlcheck_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define curlcheck_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define curlcheck_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define curlcheck_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define curlcheck_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define curlcheck_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define curlcheck_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define curlcheck_ptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define curlcheck_arr(expr, type) \ + (curlcheck_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define curlcheck_string(expr) \ + (curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), signed char) || \ + curlcheck_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define curlcheck_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define curlcheck_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define curlcheck_error_buffer(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define curlcheck_cb_data(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_ptr((expr), FILE)) +#else /* be less strict */ +#define curlcheck_cb_data(expr) \ + curlcheck_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define curlcheck_FILE(expr) \ + (curlcheck_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define curlcheck_postfields(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define curlcheck_cb_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define curlcheck_resolver_start_callback(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define curlcheck_read_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fread) *) || \ + curlcheck_cb_compatible((expr), curl_read_callback) || \ + curlcheck_cb_compatible((expr), _curl_read_callback1) || \ + curlcheck_cb_compatible((expr), _curl_read_callback2) || \ + curlcheck_cb_compatible((expr), _curl_read_callback3) || \ + curlcheck_cb_compatible((expr), _curl_read_callback4) || \ + curlcheck_cb_compatible((expr), _curl_read_callback5) || \ + curlcheck_cb_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define curlcheck_write_cb(expr) \ + (curlcheck_read_cb(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \ + curlcheck_cb_compatible((expr), curl_write_callback) || \ + curlcheck_cb_compatible((expr), _curl_write_callback1) || \ + curlcheck_cb_compatible((expr), _curl_write_callback2) || \ + curlcheck_cb_compatible((expr), _curl_write_callback3) || \ + curlcheck_cb_compatible((expr), _curl_write_callback4) || \ + curlcheck_cb_compatible((expr), _curl_write_callback5) || \ + curlcheck_cb_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define curlcheck_ioctl_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ioctl_callback) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define curlcheck_sockopt_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sockopt_callback) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define curlcheck_opensocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_opensocket_callback) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define curlcheck_progress_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_progress_callback) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback1) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define curlcheck_debug_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_debug_callback) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback1) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback2) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback3) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback4) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback5) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback6) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback7) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define curlcheck_ssl_ctx_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define curlcheck_conv_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_conv_callback) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback1) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback2) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback3) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define curlcheck_seek_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_seek_callback) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback1) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* CURLINC_TYPECHECK_GCC_H */ diff --git a/rknn_yolo_demo/include/curl/urlapi.h b/rknn_yolo_demo/include/curl/urlapi.h new file mode 100644 index 0000000..f2d0677 --- /dev/null +++ b/rknn_yolo_demo/include/curl/urlapi.h @@ -0,0 +1,125 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ +#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the + scheme is unknown. */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_URLAPI_H */ diff --git a/rknn_yolo_demo/include/drm_func.h b/rknn_yolo_demo/include/drm_func.h new file mode 100644 index 0000000..624b49d --- /dev/null +++ b/rknn_yolo_demo/include/drm_func.h @@ -0,0 +1,39 @@ +#ifndef __DRM_FUNC_H__ +#define __DRM_FUNC_H__ +#include +#include +#include +#include +#include // open function +#include // close function +#include +#include + + +#include +#include "libdrm/drm_fourcc.h" +#include "xf86drm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (* FUNC_DRM_IOCTL)(int fd, unsigned long request, void *arg); + +typedef struct _drm_context{ + void *drm_handle; + FUNC_DRM_IOCTL io_func; +} drm_context; + +int drm_init(drm_context *drm_ctx); + +void* drm_buf_alloc(drm_context *drm_ctx,int drm_fd, int TexWidth, int TexHeight,int bpp,int *fd,unsigned int *handle,size_t *actual_size); + +int drm_buf_destroy(drm_context *drm_ctx,int drm_fd,int buf_fd, int handle,void *drm_buf,size_t size); + +void drm_deinit(drm_context *drm_ctx, int drm_fd); + +#ifdef __cplusplus +} +#endif +#endif /*__DRM_FUNC_H__*/ \ No newline at end of file diff --git a/rknn_yolo_demo/include/librtsp/librtsp.a b/rknn_yolo_demo/include/librtsp/librtsp.a new file mode 100644 index 0000000..78e7f99 Binary files /dev/null and b/rknn_yolo_demo/include/librtsp/librtsp.a differ diff --git a/rknn_yolo_demo/include/librtsp/rtsp_demo.h b/rknn_yolo_demo/include/librtsp/rtsp_demo.h new file mode 100644 index 0000000..4e0e79e --- /dev/null +++ b/rknn_yolo_demo/include/librtsp/rtsp_demo.h @@ -0,0 +1,64 @@ +// Copyright 2020 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef __RTSP_DEMO_H__ +#define __RTSP_DEMO_H__ +/* + * a simple RTSP server demo + * RTP over UDP/TCP H264/G711a + * */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum rtsp_codec_id { + RTSP_CODEC_ID_NONE = 0, + RTSP_CODEC_ID_VIDEO_H264 = 0x0001, /*codec_data is SPS + PPS frames*/ + RTSP_CODEC_ID_VIDEO_H265, /*codec_data is VPS + SPS + PPS frames*/ + RTSP_CODEC_ID_VIDEO_MPEG4, /*now not support*/ + RTSP_CODEC_ID_AUDIO_G711A = 0x4001, /*codec_data is NULL*/ + RTSP_CODEC_ID_AUDIO_G711U, /*codec_data is NULL*/ + RTSP_CODEC_ID_AUDIO_G726, /*codec_data is bitrate (int)*/ + RTSP_CODEC_ID_AUDIO_MP3, /*codec_data is audio specific config (2bytes). frame + type is MP3*/ +}; + +typedef void *rtsp_demo_handle; +typedef void *rtsp_session_handle; + +rtsp_demo_handle rtsp_new_demo(int port); +rtsp_demo_handle create_rtsp_demo(int port); +int rtsp_do_event(rtsp_demo_handle demo); +rtsp_session_handle rtsp_new_session(rtsp_demo_handle demo, const char *path); +rtsp_session_handle create_rtsp_session(rtsp_demo_handle demo, + const char *path); +int rtsp_set_video(rtsp_session_handle session, int codec_id, + const uint8_t *codec_data, int data_len); + +int rtsp_set_audio(rtsp_session_handle session, int codec_id, + const uint8_t *codec_data, int data_len); + +int rtsp_sever_tx_video(rtsp_demo_handle demo, rtsp_session_handle session, + const uint8_t *frame, int len, uint64_t ts); +int rtsp_tx_video(rtsp_session_handle session, const uint8_t *frame, int len, + uint64_t ts); +int rtsp_tx_audio(rtsp_session_handle session, const uint8_t *frame, int len, + uint64_t ts); +void rtsp_del_session(rtsp_session_handle session); +void rtsp_del_demo(rtsp_demo_handle demo); + +uint64_t rtsp_get_reltime(void); +uint64_t rtsp_get_ntptime(void); +int rtsp_sync_video_ts(rtsp_session_handle session, uint64_t ts, + uint64_t ntptime); +int rtsp_sync_audio_ts(rtsp_session_handle session, uint64_t ts, + uint64_t ntptime); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/rknn_yolo_demo/include/rga_func.h b/rknn_yolo_demo/include/rga_func.h new file mode 100644 index 0000000..d053015 --- /dev/null +++ b/rknn_yolo_demo/include/rga_func.h @@ -0,0 +1,34 @@ +#ifndef __RGA_FUNC_H__ +#define __RGA_FUNC_H__ + +#include +#include "RgaApi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(* FUNC_RGA_INIT)(); +typedef void(* FUNC_RGA_DEINIT)(); +typedef int(* FUNC_RGA_BLIT)(rga_info_t *, rga_info_t *, rga_info_t *); + +typedef struct _rga_context{ + void *rga_handle; + FUNC_RGA_INIT init_func; + FUNC_RGA_DEINIT deinit_func; + FUNC_RGA_BLIT blit_func; +} rga_context; + +int RGA_init(rga_context* rga_ctx); + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h); + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h, int w_offset, + int h_offset, RgaSURF_FORMAT color, bool add_extra_sz_w, bool add_extra_sz_h); + +int RGA_deinit(rga_context* rga_ctx); + +#ifdef __cplusplus +} +#endif +#endif/*__RGA_FUNC_H__*/ diff --git a/rknn_yolo_demo/include/yolo.h b/rknn_yolo_demo/include/yolo.h new file mode 100644 index 0000000..1d3fa26 --- /dev/null +++ b/rknn_yolo_demo/include/yolo.h @@ -0,0 +1,106 @@ +#ifndef _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ +#define _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ + +#include +#include "rknn_api.h" +#include "rga_func.h" + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 200 +#define OBJ_CLASS_NUM 7 +#define PROP_BOX_SIZE (5+OBJ_CLASS_NUM) +#define NMS_THRESHOLD 0.45 +#define CONF_THRESHOLD 0.25 + +typedef enum +{ + YOLOX = 0, + YOLOV5, + YOLOV7 +} MODEL_TYPE; + + +typedef enum +{ + U8 = 0, + FP = 1, +} POST_PROCESS_TYPE; + +typedef enum +{ + SINGLE_IMG = 0, + MULTI_IMG +} INPUT_SOURCE; + + +typedef struct _MODEL_INFO{ + MODEL_TYPE m_type; + POST_PROCESS_TYPE post_type; + INPUT_SOURCE in_source; + + char* m_path = nullptr; + char* in_path = nullptr; + + int channel; + int height; + int width; + RgaSURF_FORMAT color_expect; + + int anchors[18]; + int anchor_per_branch; + + int in_nodes; + rknn_tensor_attr* in_attr = nullptr; + + int out_nodes = 3; + rknn_tensor_attr* out_attr = nullptr; + + int strides[3] = {8,16,32}; + +} MODEL_INFO; + +typedef struct _LETTER_BOX{ + int in_width, in_height; + int target_width, target_height; + + float img_wh_ratio, target_wh_ratio, resize_scale; + int resize_width, resize_height; + int h_pad, w_pad; + bool add_extra_sz_h_pad = false; + bool add_extra_sz_w_pad = false; +} LETTER_BOX; + + +typedef struct _BOX_RECT +{ + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t +{ + char name[OBJ_NAME_MAX_SIZE]; + int class_index; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t +{ + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + + +int readLines(const char *fileName, char *lines[], int max_line); + +int compute_letter_box(LETTER_BOX* lb); + +int post_process(rknn_output* rk_outputs, MODEL_INFO* m, LETTER_BOX* lb, detect_result_group_t* group); + +int readFloats(const char *fileName, float *result, int max_line, int* valid_number); + +#endif //_RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/lib/librknn_api.so b/rknn_yolo_demo/install/rknn_yolo_demo_test/lib/librknn_api.so new file mode 100644 index 0000000..ae3b0d1 Binary files /dev/null and b/rknn_yolo_demo/install/rknn_yolo_demo_test/lib/librknn_api.so differ diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/RK_anchors_yolov5.txt b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/RK_anchors_yolov5.txt new file mode 100644 index 0000000..680a13e --- /dev/null +++ b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/RK_anchors_yolov5.txt @@ -0,0 +1,18 @@ +10.0 +13.0 +16.0 +30.0 +33.0 +23.0 +30.0 +61.0 +62.0 +45.0 +59.0 +119.0 +116.0 +90.0 +156.0 +198.0 +373.0 +326.0 diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/RK_anchors_yolov7.txt b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/RK_anchors_yolov7.txt new file mode 100644 index 0000000..8705e92 --- /dev/null +++ b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/RK_anchors_yolov7.txt @@ -0,0 +1,18 @@ +12.0 +16.0 +19.0 +36.0 +40.0 +28.0 +36.0 +75.0 +76.0 +55.0 +72.0 +146.0 +142.0 +110.0 +192.0 +243.0 +459.0 +401.0 diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/bus.jpg b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/bus.jpg new file mode 100644 index 0000000..b43e311 Binary files /dev/null and b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/bus.jpg differ diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/bus640.jpg b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/bus640.jpg new file mode 100644 index 0000000..d8ef30b Binary files /dev/null and b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/bus640.jpg differ diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/coco_80_labels_list.txt b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/coco_80_labels_list.txt new file mode 100644 index 0000000..941cb4e --- /dev/null +++ b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/coco_80_labels_list.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +dining table +toilet +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/coco_dataset_path.txt b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/coco_dataset_path.txt new file mode 100644 index 0000000..a75fea5 --- /dev/null +++ b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/coco_dataset_path.txt @@ -0,0 +1,5000 @@ +/userdata/val2017/000000490515.jpg +/userdata/val2017/000000355257.jpg +/userdata/val2017/000000237864.jpg +/userdata/val2017/000000062353.jpg +/userdata/val2017/000000183049.jpg +/userdata/val2017/000000382743.jpg +/userdata/val2017/000000287649.jpg +/userdata/val2017/000000409198.jpg +/userdata/val2017/000000266082.jpg +/userdata/val2017/000000580294.jpg +/userdata/val2017/000000511384.jpg +/userdata/val2017/000000134322.jpg +/userdata/val2017/000000015660.jpg +/userdata/val2017/000000243344.jpg +/userdata/val2017/000000132622.jpg +/userdata/val2017/000000018150.jpg +/userdata/val2017/000000472678.jpg +/userdata/val2017/000000354829.jpg +/userdata/val2017/000000395801.jpg +/userdata/val2017/000000017115.jpg +/userdata/val2017/000000572900.jpg +/userdata/val2017/000000290592.jpg +/userdata/val2017/000000088485.jpg +/userdata/val2017/000000086483.jpg +/userdata/val2017/000000543528.jpg +/userdata/val2017/000000097994.jpg +/userdata/val2017/000000240049.jpg +/userdata/val2017/000000107087.jpg +/userdata/val2017/000000526256.jpg +/userdata/val2017/000000402783.jpg +/userdata/val2017/000000368335.jpg +/userdata/val2017/000000567640.jpg +/userdata/val2017/000000121591.jpg +/userdata/val2017/000000126216.jpg +/userdata/val2017/000000575372.jpg +/userdata/val2017/000000537053.jpg +/userdata/val2017/000000170955.jpg +/userdata/val2017/000000292155.jpg +/userdata/val2017/000000489339.jpg +/userdata/val2017/000000357459.jpg +/userdata/val2017/000000124659.jpg +/userdata/val2017/000000377635.jpg +/userdata/val2017/000000163155.jpg +/userdata/val2017/000000263796.jpg +/userdata/val2017/000000048564.jpg +/userdata/val2017/000000201072.jpg +/userdata/val2017/000000155451.jpg +/userdata/val2017/000000359677.jpg +/userdata/val2017/000000076468.jpg +/userdata/val2017/000000384651.jpg +/userdata/val2017/000000393056.jpg +/userdata/val2017/000000439522.jpg +/userdata/val2017/000000167572.jpg +/userdata/val2017/000000525286.jpg +/userdata/val2017/000000253835.jpg +/userdata/val2017/000000443844.jpg +/userdata/val2017/000000357978.jpg +/userdata/val2017/000000515025.jpg +/userdata/val2017/000000471869.jpg +/userdata/val2017/000000066817.jpg +/userdata/val2017/000000166478.jpg +/userdata/val2017/000000133087.jpg +/userdata/val2017/000000212453.jpg +/userdata/val2017/000000127494.jpg +/userdata/val2017/000000068765.jpg +/userdata/val2017/000000188592.jpg +/userdata/val2017/000000237928.jpg +/userdata/val2017/000000513484.jpg +/userdata/val2017/000000570471.jpg +/userdata/val2017/000000198928.jpg +/userdata/val2017/000000572555.jpg +/userdata/val2017/000000009914.jpg +/userdata/val2017/000000313130.jpg +/userdata/val2017/000000302165.jpg +/userdata/val2017/000000342295.jpg +/userdata/val2017/000000038829.jpg +/userdata/val2017/000000459195.jpg +/userdata/val2017/000000527029.jpg +/userdata/val2017/000000055167.jpg +/userdata/val2017/000000209829.jpg +/userdata/val2017/000000523175.jpg +/userdata/val2017/000000362520.jpg +/userdata/val2017/000000463802.jpg +/userdata/val2017/000000525155.jpg +/userdata/val2017/000000225405.jpg +/userdata/val2017/000000222299.jpg +/userdata/val2017/000000446005.jpg +/userdata/val2017/000000186345.jpg +/userdata/val2017/000000093717.jpg +/userdata/val2017/000000031817.jpg +/userdata/val2017/000000136033.jpg +/userdata/val2017/000000434996.jpg +/userdata/val2017/000000226130.jpg +/userdata/val2017/000000286458.jpg +/userdata/val2017/000000399560.jpg +/userdata/val2017/000000246522.jpg +/userdata/val2017/000000289516.jpg +/userdata/val2017/000000322163.jpg +/userdata/val2017/000000014831.jpg +/userdata/val2017/000000425227.jpg +/userdata/val2017/000000533206.jpg +/userdata/val2017/000000149622.jpg +/userdata/val2017/000000057150.jpg +/userdata/val2017/000000341828.jpg +/userdata/val2017/000000045090.jpg +/userdata/val2017/000000263463.jpg +/userdata/val2017/000000327592.jpg +/userdata/val2017/000000061658.jpg +/userdata/val2017/000000578489.jpg +/userdata/val2017/000000166747.jpg +/userdata/val2017/000000087144.jpg +/userdata/val2017/000000457884.jpg +/userdata/val2017/000000162092.jpg +/userdata/val2017/000000478420.jpg +/userdata/val2017/000000068387.jpg +/userdata/val2017/000000514914.jpg +/userdata/val2017/000000186042.jpg +/userdata/val2017/000000357941.jpg +/userdata/val2017/000000468577.jpg +/userdata/val2017/000000273232.jpg +/userdata/val2017/000000186296.jpg +/userdata/val2017/000000061960.jpg +/userdata/val2017/000000568584.jpg +/userdata/val2017/000000314251.jpg +/userdata/val2017/000000386352.jpg +/userdata/val2017/000000545407.jpg +/userdata/val2017/000000519208.jpg +/userdata/val2017/000000393838.jpg +/userdata/val2017/000000103548.jpg +/userdata/val2017/000000234607.jpg +/userdata/val2017/000000519688.jpg +/userdata/val2017/000000146363.jpg +/userdata/val2017/000000380203.jpg +/userdata/val2017/000000052462.jpg +/userdata/val2017/000000289343.jpg +/userdata/val2017/000000098520.jpg +/userdata/val2017/000000250127.jpg +/userdata/val2017/000000192699.jpg +/userdata/val2017/000000162366.jpg +/userdata/val2017/000000019742.jpg +/userdata/val2017/000000193348.jpg +/userdata/val2017/000000054628.jpg +/userdata/val2017/000000506707.jpg +/userdata/val2017/000000146498.jpg +/userdata/val2017/000000310862.jpg +/userdata/val2017/000000181542.jpg +/userdata/val2017/000000285894.jpg +/userdata/val2017/000000025181.jpg +/userdata/val2017/000000004795.jpg +/userdata/val2017/000000077460.jpg +/userdata/val2017/000000157756.jpg +/userdata/val2017/000000163562.jpg +/userdata/val2017/000000407614.jpg +/userdata/val2017/000000076416.jpg +/userdata/val2017/000000429281.jpg +/userdata/val2017/000000324818.jpg +/userdata/val2017/000000282296.jpg +/userdata/val2017/000000092053.jpg +/userdata/val2017/000000038210.jpg +/userdata/val2017/000000504635.jpg +/userdata/val2017/000000493442.jpg +/userdata/val2017/000000508482.jpg +/userdata/val2017/000000311295.jpg +/userdata/val2017/000000121506.jpg +/userdata/val2017/000000243626.jpg +/userdata/val2017/000000462629.jpg +/userdata/val2017/000000372307.jpg +/userdata/val2017/000000309964.jpg +/userdata/val2017/000000264968.jpg +/userdata/val2017/000000104424.jpg +/userdata/val2017/000000206027.jpg +/userdata/val2017/000000110884.jpg +/userdata/val2017/000000484760.jpg +/userdata/val2017/000000214224.jpg +/userdata/val2017/000000200961.jpg +/userdata/val2017/000000311190.jpg +/userdata/val2017/000000253695.jpg +/userdata/val2017/000000052413.jpg +/userdata/val2017/000000560911.jpg +/userdata/val2017/000000156372.jpg +/userdata/val2017/000000350003.jpg +/userdata/val2017/000000268831.jpg +/userdata/val2017/000000229849.jpg +/userdata/val2017/000000296284.jpg +/userdata/val2017/000000196843.jpg +/userdata/val2017/000000008762.jpg +/userdata/val2017/000000288862.jpg +/userdata/val2017/000000075612.jpg +/userdata/val2017/000000384468.jpg +/userdata/val2017/000000312213.jpg +/userdata/val2017/000000112298.jpg +/userdata/val2017/000000439525.jpg +/userdata/val2017/000000251572.jpg +/userdata/val2017/000000520531.jpg +/userdata/val2017/000000099039.jpg +/userdata/val2017/000000279278.jpg +/userdata/val2017/000000168458.jpg +/userdata/val2017/000000154431.jpg +/userdata/val2017/000000499622.jpg +/userdata/val2017/000000000285.jpg +/userdata/val2017/000000458325.jpg +/userdata/val2017/000000059635.jpg +/userdata/val2017/000000210708.jpg +/userdata/val2017/000000259571.jpg +/userdata/val2017/000000303499.jpg +/userdata/val2017/000000485972.jpg +/userdata/val2017/000000172083.jpg +/userdata/val2017/000000393226.jpg +/userdata/val2017/000000221708.jpg +/userdata/val2017/000000516038.jpg +/userdata/val2017/000000229221.jpg +/userdata/val2017/000000033114.jpg +/userdata/val2017/000000486438.jpg +/userdata/val2017/000000107226.jpg +/userdata/val2017/000000136915.jpg +/userdata/val2017/000000284743.jpg +/userdata/val2017/000000347265.jpg +/userdata/val2017/000000519522.jpg +/userdata/val2017/000000282298.jpg +/userdata/val2017/000000021903.jpg +/userdata/val2017/000000004495.jpg +/userdata/val2017/000000011699.jpg +/userdata/val2017/000000293804.jpg +/userdata/val2017/000000335177.jpg +/userdata/val2017/000000291490.jpg +/userdata/val2017/000000493772.jpg +/userdata/val2017/000000537355.jpg +/userdata/val2017/000000096960.jpg +/userdata/val2017/000000407524.jpg +/userdata/val2017/000000367386.jpg +/userdata/val2017/000000311789.jpg +/userdata/val2017/000000005193.jpg +/userdata/val2017/000000311928.jpg +/userdata/val2017/000000192191.jpg +/userdata/val2017/000000547854.jpg +/userdata/val2017/000000404249.jpg +/userdata/val2017/000000459467.jpg +/userdata/val2017/000000383337.jpg +/userdata/val2017/000000516601.jpg +/userdata/val2017/000000240250.jpg +/userdata/val2017/000000503841.jpg +/userdata/val2017/000000569700.jpg +/userdata/val2017/000000465129.jpg +/userdata/val2017/000000231580.jpg +/userdata/val2017/000000263068.jpg +/userdata/val2017/000000066841.jpg +/userdata/val2017/000000286849.jpg +/userdata/val2017/000000418062.jpg +/userdata/val2017/000000414385.jpg +/userdata/val2017/000000438269.jpg +/userdata/val2017/000000392818.jpg +/userdata/val2017/000000308545.jpg +/userdata/val2017/000000573094.jpg +/userdata/val2017/000000567825.jpg +/userdata/val2017/000000415716.jpg +/userdata/val2017/000000353027.jpg +/userdata/val2017/000000074860.jpg +/userdata/val2017/000000131938.jpg +/userdata/val2017/000000158660.jpg +/userdata/val2017/000000448256.jpg +/userdata/val2017/000000486046.jpg +/userdata/val2017/000000031118.jpg +/userdata/val2017/000000205647.jpg +/userdata/val2017/000000009590.jpg +/userdata/val2017/000000557884.jpg +/userdata/val2017/000000575187.jpg +/userdata/val2017/000000206831.jpg +/userdata/val2017/000000114049.jpg +/userdata/val2017/000000378116.jpg +/userdata/val2017/000000454750.jpg +/userdata/val2017/000000504439.jpg +/userdata/val2017/000000385029.jpg +/userdata/val2017/000000460333.jpg +/userdata/val2017/000000479126.jpg +/userdata/val2017/000000221872.jpg +/userdata/val2017/000000339870.jpg +/userdata/val2017/000000372317.jpg +/userdata/val2017/000000266768.jpg +/userdata/val2017/000000366611.jpg +/userdata/val2017/000000462728.jpg +/userdata/val2017/000000547816.jpg +/userdata/val2017/000000319184.jpg +/userdata/val2017/000000347163.jpg +/userdata/val2017/000000163257.jpg +/userdata/val2017/000000248112.jpg +/userdata/val2017/000000097022.jpg +/userdata/val2017/000000176847.jpg +/userdata/val2017/000000501023.jpg +/userdata/val2017/000000119233.jpg +/userdata/val2017/000000577539.jpg +/userdata/val2017/000000520301.jpg +/userdata/val2017/000000433134.jpg +/userdata/val2017/000000056127.jpg +/userdata/val2017/000000500716.jpg +/userdata/val2017/000000002431.jpg +/userdata/val2017/000000356432.jpg +/userdata/val2017/000000574520.jpg +/userdata/val2017/000000499313.jpg +/userdata/val2017/000000231549.jpg +/userdata/val2017/000000508312.jpg +/userdata/val2017/000000251140.jpg +/userdata/val2017/000000479155.jpg +/userdata/val2017/000000579091.jpg +/userdata/val2017/000000194832.jpg +/userdata/val2017/000000281754.jpg +/userdata/val2017/000000017905.jpg +/userdata/val2017/000000490936.jpg +/userdata/val2017/000000304560.jpg +/userdata/val2017/000000560256.jpg +/userdata/val2017/000000013774.jpg +/userdata/val2017/000000328337.jpg +/userdata/val2017/000000166509.jpg +/userdata/val2017/000000249129.jpg +/userdata/val2017/000000243199.jpg +/userdata/val2017/000000289222.jpg +/userdata/val2017/000000456662.jpg +/userdata/val2017/000000058384.jpg +/userdata/val2017/000000077595.jpg +/userdata/val2017/000000412887.jpg +/userdata/val2017/000000377368.jpg +/userdata/val2017/000000571264.jpg +/userdata/val2017/000000344909.jpg +/userdata/val2017/000000489046.jpg +/userdata/val2017/000000448448.jpg +/userdata/val2017/000000122927.jpg +/userdata/val2017/000000407646.jpg +/userdata/val2017/000000183716.jpg +/userdata/val2017/000000250758.jpg +/userdata/val2017/000000390246.jpg +/userdata/val2017/000000217614.jpg +/userdata/val2017/000000206135.jpg +/userdata/val2017/000000356968.jpg +/userdata/val2017/000000348216.jpg +/userdata/val2017/000000468501.jpg +/userdata/val2017/000000345941.jpg +/userdata/val2017/000000309484.jpg +/userdata/val2017/000000245311.jpg +/userdata/val2017/000000059044.jpg +/userdata/val2017/000000015497.jpg +/userdata/val2017/000000409542.jpg +/userdata/val2017/000000507667.jpg +/userdata/val2017/000000407825.jpg +/userdata/val2017/000000290833.jpg +/userdata/val2017/000000364587.jpg +/userdata/val2017/000000235857.jpg +/userdata/val2017/000000422998.jpg +/userdata/val2017/000000152465.jpg +/userdata/val2017/000000310622.jpg +/userdata/val2017/000000420472.jpg +/userdata/val2017/000000565469.jpg +/userdata/val2017/000000548339.jpg +/userdata/val2017/000000325306.jpg +/userdata/val2017/000000440336.jpg +/userdata/val2017/000000097337.jpg +/userdata/val2017/000000318114.jpg +/userdata/val2017/000000243204.jpg +/userdata/val2017/000000219283.jpg +/userdata/val2017/000000400803.jpg +/userdata/val2017/000000418961.jpg +/userdata/val2017/000000162858.jpg +/userdata/val2017/000000409630.jpg +/userdata/val2017/000000181859.jpg +/userdata/val2017/000000173799.jpg +/userdata/val2017/000000187585.jpg +/userdata/val2017/000000459757.jpg +/userdata/val2017/000000125952.jpg +/userdata/val2017/000000567011.jpg +/userdata/val2017/000000398905.jpg +/userdata/val2017/000000095069.jpg +/userdata/val2017/000000479596.jpg +/userdata/val2017/000000488673.jpg +/userdata/val2017/000000162543.jpg +/userdata/val2017/000000064718.jpg +/userdata/val2017/000000031322.jpg +/userdata/val2017/000000522889.jpg +/userdata/val2017/000000448410.jpg +/userdata/val2017/000000345385.jpg +/userdata/val2017/000000412531.jpg +/userdata/val2017/000000479912.jpg +/userdata/val2017/000000382125.jpg +/userdata/val2017/000000179898.jpg +/userdata/val2017/000000253386.jpg +/userdata/val2017/000000248334.jpg +/userdata/val2017/000000286708.jpg +/userdata/val2017/000000480212.jpg +/userdata/val2017/000000177714.jpg +/userdata/val2017/000000494634.jpg +/userdata/val2017/000000458410.jpg +/userdata/val2017/000000263966.jpg +/userdata/val2017/000000494869.jpg +/userdata/val2017/000000019042.jpg +/userdata/val2017/000000135410.jpg +/userdata/val2017/000000426268.jpg +/userdata/val2017/000000100510.jpg +/userdata/val2017/000000218249.jpg +/userdata/val2017/000000470121.jpg +/userdata/val2017/000000266409.jpg +/userdata/val2017/000000551820.jpg +/userdata/val2017/000000208901.jpg +/userdata/val2017/000000020333.jpg +/userdata/val2017/000000549136.jpg +/userdata/val2017/000000310072.jpg +/userdata/val2017/000000156278.jpg +/userdata/val2017/000000134722.jpg +/userdata/val2017/000000237071.jpg +/userdata/val2017/000000209747.jpg +/userdata/val2017/000000085157.jpg +/userdata/val2017/000000308753.jpg +/userdata/val2017/000000555005.jpg +/userdata/val2017/000000360393.jpg +/userdata/val2017/000000291861.jpg +/userdata/val2017/000000098261.jpg +/userdata/val2017/000000348881.jpg +/userdata/val2017/000000322352.jpg +/userdata/val2017/000000447611.jpg +/userdata/val2017/000000123213.jpg +/userdata/val2017/000000027932.jpg +/userdata/val2017/000000562207.jpg +/userdata/val2017/000000037670.jpg +/userdata/val2017/000000353180.jpg +/userdata/val2017/000000529148.jpg +/userdata/val2017/000000191288.jpg +/userdata/val2017/000000534041.jpg +/userdata/val2017/000000486479.jpg +/userdata/val2017/000000140270.jpg +/userdata/val2017/000000383384.jpg +/userdata/val2017/000000542776.jpg +/userdata/val2017/000000413247.jpg +/userdata/val2017/000000044068.jpg +/userdata/val2017/000000534270.jpg +/userdata/val2017/000000378454.jpg +/userdata/val2017/000000210230.jpg +/userdata/val2017/000000325347.jpg +/userdata/val2017/000000560279.jpg +/userdata/val2017/000000058111.jpg +/userdata/val2017/000000437239.jpg +/userdata/val2017/000000171611.jpg +/userdata/val2017/000000395701.jpg +/userdata/val2017/000000080666.jpg +/userdata/val2017/000000578922.jpg +/userdata/val2017/000000434479.jpg +/userdata/val2017/000000296657.jpg +/userdata/val2017/000000010764.jpg +/userdata/val2017/000000452515.jpg +/userdata/val2017/000000303566.jpg +/userdata/val2017/000000505638.jpg +/userdata/val2017/000000032570.jpg +/userdata/val2017/000000007784.jpg +/userdata/val2017/000000121031.jpg +/userdata/val2017/000000512985.jpg +/userdata/val2017/000000189078.jpg +/userdata/val2017/000000374551.jpg +/userdata/val2017/000000560266.jpg +/userdata/val2017/000000297698.jpg +/userdata/val2017/000000160666.jpg +/userdata/val2017/000000222825.jpg +/userdata/val2017/000000045596.jpg +/userdata/val2017/000000482735.jpg +/userdata/val2017/000000426376.jpg +/userdata/val2017/000000550426.jpg +/userdata/val2017/000000224200.jpg +/userdata/val2017/000000201646.jpg +/userdata/val2017/000000298697.jpg +/userdata/val2017/000000332455.jpg +/userdata/val2017/000000453302.jpg +/userdata/val2017/000000447187.jpg +/userdata/val2017/000000222235.jpg +/userdata/val2017/000000476491.jpg +/userdata/val2017/000000551439.jpg +/userdata/val2017/000000227511.jpg +/userdata/val2017/000000384616.jpg +/userdata/val2017/000000474881.jpg +/userdata/val2017/000000275058.jpg +/userdata/val2017/000000292024.jpg +/userdata/val2017/000000038576.jpg +/userdata/val2017/000000551780.jpg +/userdata/val2017/000000409424.jpg +/userdata/val2017/000000078823.jpg +/userdata/val2017/000000114871.jpg +/userdata/val2017/000000348243.jpg +/userdata/val2017/000000237984.jpg +/userdata/val2017/000000085576.jpg +/userdata/val2017/000000377575.jpg +/userdata/val2017/000000199771.jpg +/userdata/val2017/000000516708.jpg +/userdata/val2017/000000315450.jpg +/userdata/val2017/000000060052.jpg +/userdata/val2017/000000116068.jpg +/userdata/val2017/000000287545.jpg +/userdata/val2017/000000464144.jpg +/userdata/val2017/000000368212.jpg +/userdata/val2017/000000494913.jpg +/userdata/val2017/000000550471.jpg +/userdata/val2017/000000335954.jpg +/userdata/val2017/000000005503.jpg +/userdata/val2017/000000193162.jpg +/userdata/val2017/000000418696.jpg +/userdata/val2017/000000180011.jpg +/userdata/val2017/000000309467.jpg +/userdata/val2017/000000018837.jpg +/userdata/val2017/000000395575.jpg +/userdata/val2017/000000054593.jpg +/userdata/val2017/000000394206.jpg +/userdata/val2017/000000205333.jpg +/userdata/val2017/000000194875.jpg +/userdata/val2017/000000521259.jpg +/userdata/val2017/000000532071.jpg +/userdata/val2017/000000234779.jpg +/userdata/val2017/000000082715.jpg +/userdata/val2017/000000322968.jpg +/userdata/val2017/000000256195.jpg +/userdata/val2017/000000500478.jpg +/userdata/val2017/000000377588.jpg +/userdata/val2017/000000553094.jpg +/userdata/val2017/000000302882.jpg +/userdata/val2017/000000015254.jpg +/userdata/val2017/000000417876.jpg +/userdata/val2017/000000424776.jpg +/userdata/val2017/000000396200.jpg +/userdata/val2017/000000446703.jpg +/userdata/val2017/000000159458.jpg +/userdata/val2017/000000187513.jpg +/userdata/val2017/000000500477.jpg +/userdata/val2017/000000414676.jpg +/userdata/val2017/000000376478.jpg +/userdata/val2017/000000053624.jpg +/userdata/val2017/000000572408.jpg +/userdata/val2017/000000302536.jpg +/userdata/val2017/000000014380.jpg +/userdata/val2017/000000329041.jpg +/userdata/val2017/000000483667.jpg +/userdata/val2017/000000047740.jpg +/userdata/val2017/000000227765.jpg +/userdata/val2017/000000475191.jpg +/userdata/val2017/000000153299.jpg +/userdata/val2017/000000412362.jpg +/userdata/val2017/000000531707.jpg +/userdata/val2017/000000465549.jpg +/userdata/val2017/000000473118.jpg +/userdata/val2017/000000263425.jpg +/userdata/val2017/000000223182.jpg +/userdata/val2017/000000269196.jpg +/userdata/val2017/000000506279.jpg +/userdata/val2017/000000580197.jpg +/userdata/val2017/000000183675.jpg +/userdata/val2017/000000300233.jpg +/userdata/val2017/000000271728.jpg +/userdata/val2017/000000262938.jpg +/userdata/val2017/000000535523.jpg +/userdata/val2017/000000294695.jpg +/userdata/val2017/000000174123.jpg +/userdata/val2017/000000227491.jpg +/userdata/val2017/000000447465.jpg +/userdata/val2017/000000578500.jpg +/userdata/val2017/000000180751.jpg +/userdata/val2017/000000530162.jpg +/userdata/val2017/000000180188.jpg +/userdata/val2017/000000326627.jpg +/userdata/val2017/000000534394.jpg +/userdata/val2017/000000158744.jpg +/userdata/val2017/000000143931.jpg +/userdata/val2017/000000167240.jpg +/userdata/val2017/000000371677.jpg +/userdata/val2017/000000439180.jpg +/userdata/val2017/000000482100.jpg +/userdata/val2017/000000374083.jpg +/userdata/val2017/000000090108.jpg +/userdata/val2017/000000140076.jpg +/userdata/val2017/000000136334.jpg +/userdata/val2017/000000410934.jpg +/userdata/val2017/000000151000.jpg +/userdata/val2017/000000273132.jpg +/userdata/val2017/000000263299.jpg +/userdata/val2017/000000130465.jpg +/userdata/val2017/000000129416.jpg +/userdata/val2017/000000500826.jpg +/userdata/val2017/000000334309.jpg +/userdata/val2017/000000434459.jpg +/userdata/val2017/000000463647.jpg +/userdata/val2017/000000173004.jpg +/userdata/val2017/000000224724.jpg +/userdata/val2017/000000151662.jpg +/userdata/val2017/000000465179.jpg +/userdata/val2017/000000383921.jpg +/userdata/val2017/000000543581.jpg +/userdata/val2017/000000404191.jpg +/userdata/val2017/000000211120.jpg +/userdata/val2017/000000051712.jpg +/userdata/val2017/000000401446.jpg +/userdata/val2017/000000079588.jpg +/userdata/val2017/000000397279.jpg +/userdata/val2017/000000049259.jpg +/userdata/val2017/000000178469.jpg +/userdata/val2017/000000474039.jpg +/userdata/val2017/000000486112.jpg +/userdata/val2017/000000462031.jpg +/userdata/val2017/000000533816.jpg +/userdata/val2017/000000459634.jpg +/userdata/val2017/000000461405.jpg +/userdata/val2017/000000320743.jpg +/userdata/val2017/000000356505.jpg +/userdata/val2017/000000141597.jpg +/userdata/val2017/000000493613.jpg +/userdata/val2017/000000376310.jpg +/userdata/val2017/000000049761.jpg +/userdata/val2017/000000416104.jpg +/userdata/val2017/000000144984.jpg +/userdata/val2017/000000228436.jpg +/userdata/val2017/000000161044.jpg +/userdata/val2017/000000484978.jpg +/userdata/val2017/000000268996.jpg +/userdata/val2017/000000060347.jpg +/userdata/val2017/000000482585.jpg +/userdata/val2017/000000478474.jpg +/userdata/val2017/000000051938.jpg +/userdata/val2017/000000022705.jpg +/userdata/val2017/000000476704.jpg +/userdata/val2017/000000478393.jpg +/userdata/val2017/000000085089.jpg +/userdata/val2017/000000438774.jpg +/userdata/val2017/000000512657.jpg +/userdata/val2017/000000315001.jpg +/userdata/val2017/000000134689.jpg +/userdata/val2017/000000281759.jpg +/userdata/val2017/000000496409.jpg +/userdata/val2017/000000203639.jpg +/userdata/val2017/000000143998.jpg +/userdata/val2017/000000318455.jpg +/userdata/val2017/000000376856.jpg +/userdata/val2017/000000508101.jpg +/userdata/val2017/000000087875.jpg +/userdata/val2017/000000211042.jpg +/userdata/val2017/000000139872.jpg +/userdata/val2017/000000151629.jpg +/userdata/val2017/000000207585.jpg +/userdata/val2017/000000291791.jpg +/userdata/val2017/000000033005.jpg +/userdata/val2017/000000294163.jpg +/userdata/val2017/000000119445.jpg +/userdata/val2017/000000055002.jpg +/userdata/val2017/000000057149.jpg +/userdata/val2017/000000502347.jpg +/userdata/val2017/000000074209.jpg +/userdata/val2017/000000579893.jpg +/userdata/val2017/000000085478.jpg +/userdata/val2017/000000257169.jpg +/userdata/val2017/000000135872.jpg +/userdata/val2017/000000372349.jpg +/userdata/val2017/000000165336.jpg +/userdata/val2017/000000469192.jpg +/userdata/val2017/000000447169.jpg +/userdata/val2017/000000090956.jpg +/userdata/val2017/000000578967.jpg +/userdata/val2017/000000473821.jpg +/userdata/val2017/000000274687.jpg +/userdata/val2017/000000562197.jpg +/userdata/val2017/000000074200.jpg +/userdata/val2017/000000314177.jpg +/userdata/val2017/000000007278.jpg +/userdata/val2017/000000064359.jpg +/userdata/val2017/000000144798.jpg +/userdata/val2017/000000284698.jpg +/userdata/val2017/000000439426.jpg +/userdata/val2017/000000147725.jpg +/userdata/val2017/000000425906.jpg +/userdata/val2017/000000064898.jpg +/userdata/val2017/000000104619.jpg +/userdata/val2017/000000303305.jpg +/userdata/val2017/000000424642.jpg +/userdata/val2017/000000098287.jpg +/userdata/val2017/000000524108.jpg +/userdata/val2017/000000537153.jpg +/userdata/val2017/000000475365.jpg +/userdata/val2017/000000256868.jpg +/userdata/val2017/000000259690.jpg +/userdata/val2017/000000142790.jpg +/userdata/val2017/000000110721.jpg +/userdata/val2017/000000086956.jpg +/userdata/val2017/000000155291.jpg +/userdata/val2017/000000172547.jpg +/userdata/val2017/000000280325.jpg +/userdata/val2017/000000296634.jpg +/userdata/val2017/000000001490.jpg +/userdata/val2017/000000320696.jpg +/userdata/val2017/000000298994.jpg +/userdata/val2017/000000278749.jpg +/userdata/val2017/000000357060.jpg +/userdata/val2017/000000424349.jpg +/userdata/val2017/000000027696.jpg +/userdata/val2017/000000472623.jpg +/userdata/val2017/000000163746.jpg +/userdata/val2017/000000370999.jpg +/userdata/val2017/000000369675.jpg +/userdata/val2017/000000518326.jpg +/userdata/val2017/000000515350.jpg +/userdata/val2017/000000546325.jpg +/userdata/val2017/000000382088.jpg +/userdata/val2017/000000176606.jpg +/userdata/val2017/000000280918.jpg +/userdata/val2017/000000297427.jpg +/userdata/val2017/000000267946.jpg +/userdata/val2017/000000442306.jpg +/userdata/val2017/000000334483.jpg +/userdata/val2017/000000407403.jpg +/userdata/val2017/000000442746.jpg +/userdata/val2017/000000548555.jpg +/userdata/val2017/000000542073.jpg +/userdata/val2017/000000293071.jpg +/userdata/val2017/000000292005.jpg +/userdata/val2017/000000084270.jpg +/userdata/val2017/000000415990.jpg +/userdata/val2017/000000175387.jpg +/userdata/val2017/000000251065.jpg +/userdata/val2017/000000213605.jpg +/userdata/val2017/000000421060.jpg +/userdata/val2017/000000521819.jpg +/userdata/val2017/000000459500.jpg +/userdata/val2017/000000532481.jpg +/userdata/val2017/000000031269.jpg +/userdata/val2017/000000375015.jpg +/userdata/val2017/000000340015.jpg +/userdata/val2017/000000069213.jpg +/userdata/val2017/000000180792.jpg +/userdata/val2017/000000415536.jpg +/userdata/val2017/000000061418.jpg +/userdata/val2017/000000154000.jpg +/userdata/val2017/000000036844.jpg +/userdata/val2017/000000279887.jpg +/userdata/val2017/000000384850.jpg +/userdata/val2017/000000233771.jpg +/userdata/val2017/000000491464.jpg +/userdata/val2017/000000388056.jpg +/userdata/val2017/000000438862.jpg +/userdata/val2017/000000444142.jpg +/userdata/val2017/000000050149.jpg +/userdata/val2017/000000394940.jpg +/userdata/val2017/000000505169.jpg +/userdata/val2017/000000531036.jpg +/userdata/val2017/000000528977.jpg +/userdata/val2017/000000377814.jpg +/userdata/val2017/000000567740.jpg +/userdata/val2017/000000557258.jpg +/userdata/val2017/000000294162.jpg +/userdata/val2017/000000467315.jpg +/userdata/val2017/000000388903.jpg +/userdata/val2017/000000327306.jpg +/userdata/val2017/000000170474.jpg +/userdata/val2017/000000361506.jpg +/userdata/val2017/000000109900.jpg +/userdata/val2017/000000328601.jpg +/userdata/val2017/000000334006.jpg +/userdata/val2017/000000036660.jpg +/userdata/val2017/000000396863.jpg +/userdata/val2017/000000561679.jpg +/userdata/val2017/000000043435.jpg +/userdata/val2017/000000118921.jpg +/userdata/val2017/000000512564.jpg +/userdata/val2017/000000297595.jpg +/userdata/val2017/000000020107.jpg +/userdata/val2017/000000559547.jpg +/userdata/val2017/000000374052.jpg +/userdata/val2017/000000250619.jpg +/userdata/val2017/000000261982.jpg +/userdata/val2017/000000491867.jpg +/userdata/val2017/000000234413.jpg +/userdata/val2017/000000318080.jpg +/userdata/val2017/000000540928.jpg +/userdata/val2017/000000317024.jpg +/userdata/val2017/000000215072.jpg +/userdata/val2017/000000428280.jpg +/userdata/val2017/000000574702.jpg +/userdata/val2017/000000094614.jpg +/userdata/val2017/000000526706.jpg +/userdata/val2017/000000463037.jpg +/userdata/val2017/000000450686.jpg +/userdata/val2017/000000555597.jpg +/userdata/val2017/000000105264.jpg +/userdata/val2017/000000502732.jpg +/userdata/val2017/000000545219.jpg +/userdata/val2017/000000292446.jpg +/userdata/val2017/000000233567.jpg +/userdata/val2017/000000317999.jpg +/userdata/val2017/000000148620.jpg +/userdata/val2017/000000014473.jpg +/userdata/val2017/000000021879.jpg +/userdata/val2017/000000336265.jpg +/userdata/val2017/000000019221.jpg +/userdata/val2017/000000361268.jpg +/userdata/val2017/000000293625.jpg +/userdata/val2017/000000497599.jpg +/userdata/val2017/000000424521.jpg +/userdata/val2017/000000008277.jpg +/userdata/val2017/000000163290.jpg +/userdata/val2017/000000454661.jpg +/userdata/val2017/000000068833.jpg +/userdata/val2017/000000286553.jpg +/userdata/val2017/000000261116.jpg +/userdata/val2017/000000013177.jpg +/userdata/val2017/000000174004.jpg +/userdata/val2017/000000311909.jpg +/userdata/val2017/000000009483.jpg +/userdata/val2017/000000565012.jpg +/userdata/val2017/000000166391.jpg +/userdata/val2017/000000368982.jpg +/userdata/val2017/000000248111.jpg +/userdata/val2017/000000148999.jpg +/userdata/val2017/000000007977.jpg +/userdata/val2017/000000391648.jpg +/userdata/val2017/000000108440.jpg +/userdata/val2017/000000425221.jpg +/userdata/val2017/000000370813.jpg +/userdata/val2017/000000565045.jpg +/userdata/val2017/000000253819.jpg +/userdata/val2017/000000384661.jpg +/userdata/val2017/000000110359.jpg +/userdata/val2017/000000437392.jpg +/userdata/val2017/000000098392.jpg +/userdata/val2017/000000156071.jpg +/userdata/val2017/000000023023.jpg +/userdata/val2017/000000419312.jpg +/userdata/val2017/000000307658.jpg +/userdata/val2017/000000218439.jpg +/userdata/val2017/000000108503.jpg +/userdata/val2017/000000148707.jpg +/userdata/val2017/000000385190.jpg +/userdata/val2017/000000049759.jpg +/userdata/val2017/000000095843.jpg +/userdata/val2017/000000564133.jpg +/userdata/val2017/000000269932.jpg +/userdata/val2017/000000477689.jpg +/userdata/val2017/000000389933.jpg +/userdata/val2017/000000160012.jpg +/userdata/val2017/000000104666.jpg +/userdata/val2017/000000367082.jpg +/userdata/val2017/000000122745.jpg +/userdata/val2017/000000146831.jpg +/userdata/val2017/000000163611.jpg +/userdata/val2017/000000124975.jpg +/userdata/val2017/000000127987.jpg +/userdata/val2017/000000455267.jpg +/userdata/val2017/000000463730.jpg +/userdata/val2017/000000400161.jpg +/userdata/val2017/000000313034.jpg +/userdata/val2017/000000190756.jpg +/userdata/val2017/000000488592.jpg +/userdata/val2017/000000188906.jpg +/userdata/val2017/000000392481.jpg +/userdata/val2017/000000054931.jpg +/userdata/val2017/000000357081.jpg +/userdata/val2017/000000542089.jpg +/userdata/val2017/000000402615.jpg +/userdata/val2017/000000190140.jpg +/userdata/val2017/000000064574.jpg +/userdata/val2017/000000520707.jpg +/userdata/val2017/000000402765.jpg +/userdata/val2017/000000433515.jpg +/userdata/val2017/000000475904.jpg +/userdata/val2017/000000321333.jpg +/userdata/val2017/000000209757.jpg +/userdata/val2017/000000232649.jpg +/userdata/val2017/000000042889.jpg +/userdata/val2017/000000128476.jpg +/userdata/val2017/000000416991.jpg +/userdata/val2017/000000530146.jpg +/userdata/val2017/000000037689.jpg +/userdata/val2017/000000058636.jpg +/userdata/val2017/000000126226.jpg +/userdata/val2017/000000378284.jpg +/userdata/val2017/000000344795.jpg +/userdata/val2017/000000484404.jpg +/userdata/val2017/000000146155.jpg +/userdata/val2017/000000415748.jpg +/userdata/val2017/000000574297.jpg +/userdata/val2017/000000002157.jpg +/userdata/val2017/000000409867.jpg +/userdata/val2017/000000355677.jpg +/userdata/val2017/000000289659.jpg +/userdata/val2017/000000366141.jpg +/userdata/val2017/000000058350.jpg +/userdata/val2017/000000471991.jpg +/userdata/val2017/000000479448.jpg +/userdata/val2017/000000085911.jpg +/userdata/val2017/000000516173.jpg +/userdata/val2017/000000145591.jpg +/userdata/val2017/000000140286.jpg +/userdata/val2017/000000467176.jpg +/userdata/val2017/000000361586.jpg +/userdata/val2017/000000190637.jpg +/userdata/val2017/000000474452.jpg +/userdata/val2017/000000578545.jpg +/userdata/val2017/000000080340.jpg +/userdata/val2017/000000060449.jpg +/userdata/val2017/000000343149.jpg +/userdata/val2017/000000158956.jpg +/userdata/val2017/000000170739.jpg +/userdata/val2017/000000544605.jpg +/userdata/val2017/000000505573.jpg +/userdata/val2017/000000230983.jpg +/userdata/val2017/000000037777.jpg +/userdata/val2017/000000127182.jpg +/userdata/val2017/000000536343.jpg +/userdata/val2017/000000172877.jpg +/userdata/val2017/000000485424.jpg +/userdata/val2017/000000086582.jpg +/userdata/val2017/000000034139.jpg +/userdata/val2017/000000072795.jpg +/userdata/val2017/000000501243.jpg +/userdata/val2017/000000575243.jpg +/userdata/val2017/000000568439.jpg +/userdata/val2017/000000382009.jpg +/userdata/val2017/000000524742.jpg +/userdata/val2017/000000360564.jpg +/userdata/val2017/000000266400.jpg +/userdata/val2017/000000117908.jpg +/userdata/val2017/000000558854.jpg +/userdata/val2017/000000111086.jpg +/userdata/val2017/000000325031.jpg +/userdata/val2017/000000480275.jpg +/userdata/val2017/000000461009.jpg +/userdata/val2017/000000556765.jpg +/userdata/val2017/000000320425.jpg +/userdata/val2017/000000109441.jpg +/userdata/val2017/000000397133.jpg +/userdata/val2017/000000339823.jpg +/userdata/val2017/000000289702.jpg +/userdata/val2017/000000507575.jpg +/userdata/val2017/000000502136.jpg +/userdata/val2017/000000011051.jpg +/userdata/val2017/000000262487.jpg +/userdata/val2017/000000325527.jpg +/userdata/val2017/000000080671.jpg +/userdata/val2017/000000018737.jpg +/userdata/val2017/000000520077.jpg +/userdata/val2017/000000460347.jpg +/userdata/val2017/000000168337.jpg +/userdata/val2017/000000451693.jpg +/userdata/val2017/000000273712.jpg +/userdata/val2017/000000384513.jpg +/userdata/val2017/000000001993.jpg +/userdata/val2017/000000377946.jpg +/userdata/val2017/000000290768.jpg +/userdata/val2017/000000203294.jpg +/userdata/val2017/000000134096.jpg +/userdata/val2017/000000309452.jpg +/userdata/val2017/000000078959.jpg +/userdata/val2017/000000503755.jpg +/userdata/val2017/000000274272.jpg +/userdata/val2017/000000078426.jpg +/userdata/val2017/000000045070.jpg +/userdata/val2017/000000110282.jpg +/userdata/val2017/000000125850.jpg +/userdata/val2017/000000561223.jpg +/userdata/val2017/000000521282.jpg +/userdata/val2017/000000278353.jpg +/userdata/val2017/000000079014.jpg +/userdata/val2017/000000324927.jpg +/userdata/val2017/000000134882.jpg +/userdata/val2017/000000136633.jpg +/userdata/val2017/000000395180.jpg +/userdata/val2017/000000560880.jpg +/userdata/val2017/000000500257.jpg +/userdata/val2017/000000481159.jpg +/userdata/val2017/000000187271.jpg +/userdata/val2017/000000253433.jpg +/userdata/val2017/000000456394.jpg +/userdata/val2017/000000416330.jpg +/userdata/val2017/000000566758.jpg +/userdata/val2017/000000416256.jpg +/userdata/val2017/000000530975.jpg +/userdata/val2017/000000133969.jpg +/userdata/val2017/000000543300.jpg +/userdata/val2017/000000080022.jpg +/userdata/val2017/000000191845.jpg +/userdata/val2017/000000334530.jpg +/userdata/val2017/000000265518.jpg +/userdata/val2017/000000186449.jpg +/userdata/val2017/000000262682.jpg +/userdata/val2017/000000364166.jpg +/userdata/val2017/000000057725.jpg +/userdata/val2017/000000484351.jpg +/userdata/val2017/000000579902.jpg +/userdata/val2017/000000396568.jpg +/userdata/val2017/000000262227.jpg +/userdata/val2017/000000441286.jpg +/userdata/val2017/000000003255.jpg +/userdata/val2017/000000248980.jpg +/userdata/val2017/000000498286.jpg +/userdata/val2017/000000474786.jpg +/userdata/val2017/000000153343.jpg +/userdata/val2017/000000355905.jpg +/userdata/val2017/000000463690.jpg +/userdata/val2017/000000420230.jpg +/userdata/val2017/000000274460.jpg +/userdata/val2017/000000167122.jpg +/userdata/val2017/000000113403.jpg +/userdata/val2017/000000566282.jpg +/userdata/val2017/000000340451.jpg +/userdata/val2017/000000117645.jpg +/userdata/val2017/000000509260.jpg +/userdata/val2017/000000324158.jpg +/userdata/val2017/000000176037.jpg +/userdata/val2017/000000093261.jpg +/userdata/val2017/000000186938.jpg +/userdata/val2017/000000133233.jpg +/userdata/val2017/000000441586.jpg +/userdata/val2017/000000450303.jpg +/userdata/val2017/000000507235.jpg +/userdata/val2017/000000066561.jpg +/userdata/val2017/000000391722.jpg +/userdata/val2017/000000514586.jpg +/userdata/val2017/000000003845.jpg +/userdata/val2017/000000417249.jpg +/userdata/val2017/000000431568.jpg +/userdata/val2017/000000052007.jpg +/userdata/val2017/000000231527.jpg +/userdata/val2017/000000513181.jpg +/userdata/val2017/000000129062.jpg +/userdata/val2017/000000161875.jpg +/userdata/val2017/000000433204.jpg +/userdata/val2017/000000285788.jpg +/userdata/val2017/000000414034.jpg +/userdata/val2017/000000506310.jpg +/userdata/val2017/000000575357.jpg +/userdata/val2017/000000166166.jpg +/userdata/val2017/000000352900.jpg +/userdata/val2017/000000172946.jpg +/userdata/val2017/000000105455.jpg +/userdata/val2017/000000210388.jpg +/userdata/val2017/000000272136.jpg +/userdata/val2017/000000207844.jpg +/userdata/val2017/000000139260.jpg +/userdata/val2017/000000073326.jpg +/userdata/val2017/000000408696.jpg +/userdata/val2017/000000561958.jpg +/userdata/val2017/000000372819.jpg +/userdata/val2017/000000239857.jpg +/userdata/val2017/000000261732.jpg +/userdata/val2017/000000363207.jpg +/userdata/val2017/000000134034.jpg +/userdata/val2017/000000458992.jpg +/userdata/val2017/000000088970.jpg +/userdata/val2017/000000245026.jpg +/userdata/val2017/000000430286.jpg +/userdata/val2017/000000069795.jpg +/userdata/val2017/000000526392.jpg +/userdata/val2017/000000091615.jpg +/userdata/val2017/000000255536.jpg +/userdata/val2017/000000546659.jpg +/userdata/val2017/000000108864.jpg +/userdata/val2017/000000399462.jpg +/userdata/val2017/000000134112.jpg +/userdata/val2017/000000549390.jpg +/userdata/val2017/000000161781.jpg +/userdata/val2017/000000445365.jpg +/userdata/val2017/000000129492.jpg +/userdata/val2017/000000474095.jpg +/userdata/val2017/000000038678.jpg +/userdata/val2017/000000085823.jpg +/userdata/val2017/000000233139.jpg +/userdata/val2017/000000444275.jpg +/userdata/val2017/000000153632.jpg +/userdata/val2017/000000088432.jpg +/userdata/val2017/000000451571.jpg +/userdata/val2017/000000436551.jpg +/userdata/val2017/000000243989.jpg +/userdata/val2017/000000288042.jpg +/userdata/val2017/000000166259.jpg +/userdata/val2017/000000260266.jpg +/userdata/val2017/000000428562.jpg +/userdata/val2017/000000347335.jpg +/userdata/val2017/000000002473.jpg +/userdata/val2017/000000572388.jpg +/userdata/val2017/000000044652.jpg +/userdata/val2017/000000535156.jpg +/userdata/val2017/000000210855.jpg +/userdata/val2017/000000471087.jpg +/userdata/val2017/000000170595.jpg +/userdata/val2017/000000282046.jpg +/userdata/val2017/000000248284.jpg +/userdata/val2017/000000097585.jpg +/userdata/val2017/000000515266.jpg +/userdata/val2017/000000530061.jpg +/userdata/val2017/000000367195.jpg +/userdata/val2017/000000220764.jpg +/userdata/val2017/000000102411.jpg +/userdata/val2017/000000276720.jpg +/userdata/val2017/000000293858.jpg +/userdata/val2017/000000218362.jpg +/userdata/val2017/000000507797.jpg +/userdata/val2017/000000410878.jpg +/userdata/val2017/000000373705.jpg +/userdata/val2017/000000078420.jpg +/userdata/val2017/000000324614.jpg +/userdata/val2017/000000512648.jpg +/userdata/val2017/000000135890.jpg +/userdata/val2017/000000064084.jpg +/userdata/val2017/000000577584.jpg +/userdata/val2017/000000288391.jpg +/userdata/val2017/000000527784.jpg +/userdata/val2017/000000300155.jpg +/userdata/val2017/000000370478.jpg +/userdata/val2017/000000090891.jpg +/userdata/val2017/000000096549.jpg +/userdata/val2017/000000342397.jpg +/userdata/val2017/000000030494.jpg +/userdata/val2017/000000403565.jpg +/userdata/val2017/000000513524.jpg +/userdata/val2017/000000070254.jpg +/userdata/val2017/000000425226.jpg +/userdata/val2017/000000014888.jpg +/userdata/val2017/000000046804.jpg +/userdata/val2017/000000100489.jpg +/userdata/val2017/000000577959.jpg +/userdata/val2017/000000227044.jpg +/userdata/val2017/000000091406.jpg +/userdata/val2017/000000189775.jpg +/userdata/val2017/000000399764.jpg +/userdata/val2017/000000544444.jpg +/userdata/val2017/000000437331.jpg +/userdata/val2017/000000272148.jpg +/userdata/val2017/000000008844.jpg +/userdata/val2017/000000531771.jpg +/userdata/val2017/000000358525.jpg +/userdata/val2017/000000375493.jpg +/userdata/val2017/000000417608.jpg +/userdata/val2017/000000065288.jpg +/userdata/val2017/000000021839.jpg +/userdata/val2017/000000000802.jpg +/userdata/val2017/000000072281.jpg +/userdata/val2017/000000326174.jpg +/userdata/val2017/000000343076.jpg +/userdata/val2017/000000548524.jpg +/userdata/val2017/000000323751.jpg +/userdata/val2017/000000078032.jpg +/userdata/val2017/000000127476.jpg +/userdata/val2017/000000356427.jpg +/userdata/val2017/000000431876.jpg +/userdata/val2017/000000316054.jpg +/userdata/val2017/000000407083.jpg +/userdata/val2017/000000427077.jpg +/userdata/val2017/000000384808.jpg +/userdata/val2017/000000039670.jpg +/userdata/val2017/000000415194.jpg +/userdata/val2017/000000024919.jpg +/userdata/val2017/000000394275.jpg +/userdata/val2017/000000458768.jpg +/userdata/val2017/000000139684.jpg +/userdata/val2017/000000054164.jpg +/userdata/val2017/000000453001.jpg +/userdata/val2017/000000405970.jpg +/userdata/val2017/000000377239.jpg +/userdata/val2017/000000418959.jpg +/userdata/val2017/000000512476.jpg +/userdata/val2017/000000279541.jpg +/userdata/val2017/000000236784.jpg +/userdata/val2017/000000475150.jpg +/userdata/val2017/000000113589.jpg +/userdata/val2017/000000246963.jpg +/userdata/val2017/000000146667.jpg +/userdata/val2017/000000513688.jpg +/userdata/val2017/000000570688.jpg +/userdata/val2017/000000360097.jpg +/userdata/val2017/000000172330.jpg +/userdata/val2017/000000241297.jpg +/userdata/val2017/000000163118.jpg +/userdata/val2017/000000450075.jpg +/userdata/val2017/000000440507.jpg +/userdata/val2017/000000351589.jpg +/userdata/val2017/000000279714.jpg +/userdata/val2017/000000122606.jpg +/userdata/val2017/000000282912.jpg +/userdata/val2017/000000189451.jpg +/userdata/val2017/000000220584.jpg +/userdata/val2017/000000292488.jpg +/userdata/val2017/000000349184.jpg +/userdata/val2017/000000327601.jpg +/userdata/val2017/000000194724.jpg +/userdata/val2017/000000522713.jpg +/userdata/val2017/000000474167.jpg +/userdata/val2017/000000558114.jpg +/userdata/val2017/000000424135.jpg +/userdata/val2017/000000482487.jpg +/userdata/val2017/000000055150.jpg +/userdata/val2017/000000520264.jpg +/userdata/val2017/000000296317.jpg +/userdata/val2017/000000221502.jpg +/userdata/val2017/000000468245.jpg +/userdata/val2017/000000068933.jpg +/userdata/val2017/000000390902.jpg +/userdata/val2017/000000132796.jpg +/userdata/val2017/000000210502.jpg +/userdata/val2017/000000109313.jpg +/userdata/val2017/000000051610.jpg +/userdata/val2017/000000046048.jpg +/userdata/val2017/000000414673.jpg +/userdata/val2017/000000048924.jpg +/userdata/val2017/000000025593.jpg +/userdata/val2017/000000394510.jpg +/userdata/val2017/000000127135.jpg +/userdata/val2017/000000259625.jpg +/userdata/val2017/000000177357.jpg +/userdata/val2017/000000496954.jpg +/userdata/val2017/000000571598.jpg +/userdata/val2017/000000129113.jpg +/userdata/val2017/000000189475.jpg +/userdata/val2017/000000031093.jpg +/userdata/val2017/000000188689.jpg +/userdata/val2017/000000553511.jpg +/userdata/val2017/000000517069.jpg +/userdata/val2017/000000499775.jpg +/userdata/val2017/000000527215.jpg +/userdata/val2017/000000460841.jpg +/userdata/val2017/000000184791.jpg +/userdata/val2017/000000062025.jpg +/userdata/val2017/000000036494.jpg +/userdata/val2017/000000539143.jpg +/userdata/val2017/000000345261.jpg +/userdata/val2017/000000213422.jpg +/userdata/val2017/000000159399.jpg +/userdata/val2017/000000375469.jpg +/userdata/val2017/000000131556.jpg +/userdata/val2017/000000226592.jpg +/userdata/val2017/000000514376.jpg +/userdata/val2017/000000581100.jpg +/userdata/val2017/000000084170.jpg +/userdata/val2017/000000255165.jpg +/userdata/val2017/000000062692.jpg +/userdata/val2017/000000471789.jpg +/userdata/val2017/000000205542.jpg +/userdata/val2017/000000239717.jpg +/userdata/val2017/000000512776.jpg +/userdata/val2017/000000059598.jpg +/userdata/val2017/000000305609.jpg +/userdata/val2017/000000481386.jpg +/userdata/val2017/000000435299.jpg +/userdata/val2017/000000204329.jpg +/userdata/val2017/000000011511.jpg +/userdata/val2017/000000159311.jpg +/userdata/val2017/000000229216.jpg +/userdata/val2017/000000546475.jpg +/userdata/val2017/000000052507.jpg +/userdata/val2017/000000451090.jpg +/userdata/val2017/000000206411.jpg +/userdata/val2017/000000352582.jpg +/userdata/val2017/000000473015.jpg +/userdata/val2017/000000117374.jpg +/userdata/val2017/000000060090.jpg +/userdata/val2017/000000336053.jpg +/userdata/val2017/000000011760.jpg +/userdata/val2017/000000138550.jpg +/userdata/val2017/000000061333.jpg +/userdata/val2017/000000292236.jpg +/userdata/val2017/000000015751.jpg +/userdata/val2017/000000102805.jpg +/userdata/val2017/000000465430.jpg +/userdata/val2017/000000289393.jpg +/userdata/val2017/000000351559.jpg +/userdata/val2017/000000520832.jpg +/userdata/val2017/000000151051.jpg +/userdata/val2017/000000465675.jpg +/userdata/val2017/000000468954.jpg +/userdata/val2017/000000524280.jpg +/userdata/val2017/000000174371.jpg +/userdata/val2017/000000512194.jpg +/userdata/val2017/000000032941.jpg +/userdata/val2017/000000147338.jpg +/userdata/val2017/000000088269.jpg +/userdata/val2017/000000001532.jpg +/userdata/val2017/000000250137.jpg +/userdata/val2017/000000504711.jpg +/userdata/val2017/000000549674.jpg +/userdata/val2017/000000129054.jpg +/userdata/val2017/000000359855.jpg +/userdata/val2017/000000267537.jpg +/userdata/val2017/000000292060.jpg +/userdata/val2017/000000041488.jpg +/userdata/val2017/000000239318.jpg +/userdata/val2017/000000002532.jpg +/userdata/val2017/000000519039.jpg +/userdata/val2017/000000376322.jpg +/userdata/val2017/000000165257.jpg +/userdata/val2017/000000513567.jpg +/userdata/val2017/000000150649.jpg +/userdata/val2017/000000084241.jpg +/userdata/val2017/000000309938.jpg +/userdata/val2017/000000572956.jpg +/userdata/val2017/000000558558.jpg +/userdata/val2017/000000309173.jpg +/userdata/val2017/000000209530.jpg +/userdata/val2017/000000522940.jpg +/userdata/val2017/000000312406.jpg +/userdata/val2017/000000473219.jpg +/userdata/val2017/000000140929.jpg +/userdata/val2017/000000115885.jpg +/userdata/val2017/000000416534.jpg +/userdata/val2017/000000438226.jpg +/userdata/val2017/000000460147.jpg +/userdata/val2017/000000286422.jpg +/userdata/val2017/000000220310.jpg +/userdata/val2017/000000051314.jpg +/userdata/val2017/000000196754.jpg +/userdata/val2017/000000119516.jpg +/userdata/val2017/000000368752.jpg +/userdata/val2017/000000523811.jpg +/userdata/val2017/000000180560.jpg +/userdata/val2017/000000481573.jpg +/userdata/val2017/000000544052.jpg +/userdata/val2017/000000250282.jpg +/userdata/val2017/000000365207.jpg +/userdata/val2017/000000286507.jpg +/userdata/val2017/000000087476.jpg +/userdata/val2017/000000034257.jpg +/userdata/val2017/000000365387.jpg +/userdata/val2017/000000050844.jpg +/userdata/val2017/000000273198.jpg +/userdata/val2017/000000263969.jpg +/userdata/val2017/000000153782.jpg +/userdata/val2017/000000307145.jpg +/userdata/val2017/000000466085.jpg +/userdata/val2017/000000376900.jpg +/userdata/val2017/000000331569.jpg +/userdata/val2017/000000042178.jpg +/userdata/val2017/000000272364.jpg +/userdata/val2017/000000555012.jpg +/userdata/val2017/000000407518.jpg +/userdata/val2017/000000230008.jpg +/userdata/val2017/000000509258.jpg +/userdata/val2017/000000561366.jpg +/userdata/val2017/000000346968.jpg +/userdata/val2017/000000100428.jpg +/userdata/val2017/000000462756.jpg +/userdata/val2017/000000157807.jpg +/userdata/val2017/000000351823.jpg +/userdata/val2017/000000481404.jpg +/userdata/val2017/000000332351.jpg +/userdata/val2017/000000369751.jpg +/userdata/val2017/000000343934.jpg +/userdata/val2017/000000491090.jpg +/userdata/val2017/000000013348.jpg +/userdata/val2017/000000350607.jpg +/userdata/val2017/000000268729.jpg +/userdata/val2017/000000060507.jpg +/userdata/val2017/000000449432.jpg +/userdata/val2017/000000028809.jpg +/userdata/val2017/000000146825.jpg +/userdata/val2017/000000385997.jpg +/userdata/val2017/000000228981.jpg +/userdata/val2017/000000201934.jpg +/userdata/val2017/000000345361.jpg +/userdata/val2017/000000338560.jpg +/userdata/val2017/000000088265.jpg +/userdata/val2017/000000283070.jpg +/userdata/val2017/000000094852.jpg +/userdata/val2017/000000341719.jpg +/userdata/val2017/000000370818.jpg +/userdata/val2017/000000054654.jpg +/userdata/val2017/000000295316.jpg +/userdata/val2017/000000361180.jpg +/userdata/val2017/000000039914.jpg +/userdata/val2017/000000034205.jpg +/userdata/val2017/000000405279.jpg +/userdata/val2017/000000289992.jpg +/userdata/val2017/000000363188.jpg +/userdata/val2017/000000110449.jpg +/userdata/val2017/000000234807.jpg +/userdata/val2017/000000152771.jpg +/userdata/val2017/000000170191.jpg +/userdata/val2017/000000554002.jpg +/userdata/val2017/000000306582.jpg +/userdata/val2017/000000131431.jpg +/userdata/val2017/000000239537.jpg +/userdata/val2017/000000167353.jpg +/userdata/val2017/000000369370.jpg +/userdata/val2017/000000093437.jpg +/userdata/val2017/000000217425.jpg +/userdata/val2017/000000050006.jpg +/userdata/val2017/000000232563.jpg +/userdata/val2017/000000214720.jpg +/userdata/val2017/000000470773.jpg +/userdata/val2017/000000297681.jpg +/userdata/val2017/000000577182.jpg +/userdata/val2017/000000261318.jpg +/userdata/val2017/000000565989.jpg +/userdata/val2017/000000521509.jpg +/userdata/val2017/000000322844.jpg +/userdata/val2017/000000475732.jpg +/userdata/val2017/000000042276.jpg +/userdata/val2017/000000489305.jpg +/userdata/val2017/000000149770.jpg +/userdata/val2017/000000094336.jpg +/userdata/val2017/000000495146.jpg +/userdata/val2017/000000311081.jpg +/userdata/val2017/000000377393.jpg +/userdata/val2017/000000038048.jpg +/userdata/val2017/000000210099.jpg +/userdata/val2017/000000521405.jpg +/userdata/val2017/000000320632.jpg +/userdata/val2017/000000358427.jpg +/userdata/val2017/000000378453.jpg +/userdata/val2017/000000581781.jpg +/userdata/val2017/000000370900.jpg +/userdata/val2017/000000009769.jpg +/userdata/val2017/000000019402.jpg +/userdata/val2017/000000344029.jpg +/userdata/val2017/000000106389.jpg +/userdata/val2017/000000581482.jpg +/userdata/val2017/000000017379.jpg +/userdata/val2017/000000498032.jpg +/userdata/val2017/000000200667.jpg +/userdata/val2017/000000449312.jpg +/userdata/val2017/000000402519.jpg +/userdata/val2017/000000522393.jpg +/userdata/val2017/000000448076.jpg +/userdata/val2017/000000283520.jpg +/userdata/val2017/000000369323.jpg +/userdata/val2017/000000273617.jpg +/userdata/val2017/000000048555.jpg +/userdata/val2017/000000577864.jpg +/userdata/val2017/000000104803.jpg +/userdata/val2017/000000419379.jpg +/userdata/val2017/000000131138.jpg +/userdata/val2017/000000270883.jpg +/userdata/val2017/000000308476.jpg +/userdata/val2017/000000318138.jpg +/userdata/val2017/000000446206.jpg +/userdata/val2017/000000489611.jpg +/userdata/val2017/000000514540.jpg +/userdata/val2017/000000243034.jpg +/userdata/val2017/000000245513.jpg +/userdata/val2017/000000394199.jpg +/userdata/val2017/000000233727.jpg +/userdata/val2017/000000480842.jpg +/userdata/val2017/000000345252.jpg +/userdata/val2017/000000560178.jpg +/userdata/val2017/000000002261.jpg +/userdata/val2017/000000341058.jpg +/userdata/val2017/000000210032.jpg +/userdata/val2017/000000227399.jpg +/userdata/val2017/000000553339.jpg +/userdata/val2017/000000319369.jpg +/userdata/val2017/000000310200.jpg +/userdata/val2017/000000255483.jpg +/userdata/val2017/000000058029.jpg +/userdata/val2017/000000334417.jpg +/userdata/val2017/000000261712.jpg +/userdata/val2017/000000273760.jpg +/userdata/val2017/000000168619.jpg +/userdata/val2017/000000404805.jpg +/userdata/val2017/000000507037.jpg +/userdata/val2017/000000497568.jpg +/userdata/val2017/000000308793.jpg +/userdata/val2017/000000066886.jpg +/userdata/val2017/000000559543.jpg +/userdata/val2017/000000026204.jpg +/userdata/val2017/000000395343.jpg +/userdata/val2017/000000275198.jpg +/userdata/val2017/000000347664.jpg +/userdata/val2017/000000335328.jpg +/userdata/val2017/000000255824.jpg +/userdata/val2017/000000227686.jpg +/userdata/val2017/000000042102.jpg +/userdata/val2017/000000190923.jpg +/userdata/val2017/000000517687.jpg +/userdata/val2017/000000226111.jpg +/userdata/val2017/000000369503.jpg +/userdata/val2017/000000301061.jpg +/userdata/val2017/000000031749.jpg +/userdata/val2017/000000371699.jpg +/userdata/val2017/000000067534.jpg +/userdata/val2017/000000430377.jpg +/userdata/val2017/000000012280.jpg +/userdata/val2017/000000332845.jpg +/userdata/val2017/000000407298.jpg +/userdata/val2017/000000213935.jpg +/userdata/val2017/000000086220.jpg +/userdata/val2017/000000065736.jpg +/userdata/val2017/000000230166.jpg +/userdata/val2017/000000257865.jpg +/userdata/val2017/000000286503.jpg +/userdata/val2017/000000349152.jpg +/userdata/val2017/000000351609.jpg +/userdata/val2017/000000008532.jpg +/userdata/val2017/000000390826.jpg +/userdata/val2017/000000450202.jpg +/userdata/val2017/000000049060.jpg +/userdata/val2017/000000502910.jpg +/userdata/val2017/000000500613.jpg +/userdata/val2017/000000527750.jpg +/userdata/val2017/000000426203.jpg +/userdata/val2017/000000563267.jpg +/userdata/val2017/000000102331.jpg +/userdata/val2017/000000187236.jpg +/userdata/val2017/000000488385.jpg +/userdata/val2017/000000390301.jpg +/userdata/val2017/000000226408.jpg +/userdata/val2017/000000435205.jpg +/userdata/val2017/000000518213.jpg +/userdata/val2017/000000284991.jpg +/userdata/val2017/000000562818.jpg +/userdata/val2017/000000303713.jpg +/userdata/val2017/000000304365.jpg +/userdata/val2017/000000350833.jpg +/userdata/val2017/000000010707.jpg +/userdata/val2017/000000302990.jpg +/userdata/val2017/000000312421.jpg +/userdata/val2017/000000548246.jpg +/userdata/val2017/000000271402.jpg +/userdata/val2017/000000211674.jpg +/userdata/val2017/000000244019.jpg +/userdata/val2017/000000218091.jpg +/userdata/val2017/000000314264.jpg +/userdata/val2017/000000138241.jpg +/userdata/val2017/000000169076.jpg +/userdata/val2017/000000350019.jpg +/userdata/val2017/000000084362.jpg +/userdata/val2017/000000329456.jpg +/userdata/val2017/000000023899.jpg +/userdata/val2017/000000416269.jpg +/userdata/val2017/000000515445.jpg +/userdata/val2017/000000416170.jpg +/userdata/val2017/000000061747.jpg +/userdata/val2017/000000350405.jpg +/userdata/val2017/000000389684.jpg +/userdata/val2017/000000144706.jpg +/userdata/val2017/000000412286.jpg +/userdata/val2017/000000139099.jpg +/userdata/val2017/000000121673.jpg +/userdata/val2017/000000523807.jpg +/userdata/val2017/000000261036.jpg +/userdata/val2017/000000478862.jpg +/userdata/val2017/000000540280.jpg +/userdata/val2017/000000120572.jpg +/userdata/val2017/000000367818.jpg +/userdata/val2017/000000278973.jpg +/userdata/val2017/000000289586.jpg +/userdata/val2017/000000013546.jpg +/userdata/val2017/000000153797.jpg +/userdata/val2017/000000177539.jpg +/userdata/val2017/000000506656.jpg +/userdata/val2017/000000367095.jpg +/userdata/val2017/000000363840.jpg +/userdata/val2017/000000270474.jpg +/userdata/val2017/000000493799.jpg +/userdata/val2017/000000568710.jpg +/userdata/val2017/000000529105.jpg +/userdata/val2017/000000166521.jpg +/userdata/val2017/000000461036.jpg +/userdata/val2017/000000302760.jpg +/userdata/val2017/000000411530.jpg +/userdata/val2017/000000318908.jpg +/userdata/val2017/000000439715.jpg +/userdata/val2017/000000508370.jpg +/userdata/val2017/000000245915.jpg +/userdata/val2017/000000319617.jpg +/userdata/val2017/000000249219.jpg +/userdata/val2017/000000192607.jpg +/userdata/val2017/000000424975.jpg +/userdata/val2017/000000554291.jpg +/userdata/val2017/000000194506.jpg +/userdata/val2017/000000352584.jpg +/userdata/val2017/000000235252.jpg +/userdata/val2017/000000569917.jpg +/userdata/val2017/000000528578.jpg +/userdata/val2017/000000204871.jpg +/userdata/val2017/000000550939.jpg +/userdata/val2017/000000063047.jpg +/userdata/val2017/000000414261.jpg +/userdata/val2017/000000106281.jpg +/userdata/val2017/000000181666.jpg +/userdata/val2017/000000299355.jpg +/userdata/val2017/000000290248.jpg +/userdata/val2017/000000082180.jpg +/userdata/val2017/000000280891.jpg +/userdata/val2017/000000199442.jpg +/userdata/val2017/000000527616.jpg +/userdata/val2017/000000127624.jpg +/userdata/val2017/000000131273.jpg +/userdata/val2017/000000558213.jpg +/userdata/val2017/000000336628.jpg +/userdata/val2017/000000398810.jpg +/userdata/val2017/000000403817.jpg +/userdata/val2017/000000225670.jpg +/userdata/val2017/000000313588.jpg +/userdata/val2017/000000346638.jpg +/userdata/val2017/000000494427.jpg +/userdata/val2017/000000459887.jpg +/userdata/val2017/000000343466.jpg +/userdata/val2017/000000089078.jpg +/userdata/val2017/000000084031.jpg +/userdata/val2017/000000143556.jpg +/userdata/val2017/000000476415.jpg +/userdata/val2017/000000199055.jpg +/userdata/val2017/000000172856.jpg +/userdata/val2017/000000321214.jpg +/userdata/val2017/000000308587.jpg +/userdata/val2017/000000250766.jpg +/userdata/val2017/000000117425.jpg +/userdata/val2017/000000570664.jpg +/userdata/val2017/000000356612.jpg +/userdata/val2017/000000361919.jpg +/userdata/val2017/000000018193.jpg +/userdata/val2017/000000377113.jpg +/userdata/val2017/000000022192.jpg +/userdata/val2017/000000359219.jpg +/userdata/val2017/000000486104.jpg +/userdata/val2017/000000084431.jpg +/userdata/val2017/000000396903.jpg +/userdata/val2017/000000511999.jpg +/userdata/val2017/000000144300.jpg +/userdata/val2017/000000398237.jpg +/userdata/val2017/000000314182.jpg +/userdata/val2017/000000378515.jpg +/userdata/val2017/000000408120.jpg +/userdata/val2017/000000556873.jpg +/userdata/val2017/000000442993.jpg +/userdata/val2017/000000490171.jpg +/userdata/val2017/000000006723.jpg +/userdata/val2017/000000217753.jpg +/userdata/val2017/000000437514.jpg +/userdata/val2017/000000155154.jpg +/userdata/val2017/000000132703.jpg +/userdata/val2017/000000147498.jpg +/userdata/val2017/000000339442.jpg +/userdata/val2017/000000248314.jpg +/userdata/val2017/000000311950.jpg +/userdata/val2017/000000144784.jpg +/userdata/val2017/000000229747.jpg +/userdata/val2017/000000173057.jpg +/userdata/val2017/000000113867.jpg +/userdata/val2017/000000334371.jpg +/userdata/val2017/000000010995.jpg +/userdata/val2017/000000016249.jpg +/userdata/val2017/000000328030.jpg +/userdata/val2017/000000227482.jpg +/userdata/val2017/000000554579.jpg +/userdata/val2017/000000170545.jpg +/userdata/val2017/000000323202.jpg +/userdata/val2017/000000393093.jpg +/userdata/val2017/000000108244.jpg +/userdata/val2017/000000151962.jpg +/userdata/val2017/000000255749.jpg +/userdata/val2017/000000362682.jpg +/userdata/val2017/000000197870.jpg +/userdata/val2017/000000189310.jpg +/userdata/val2017/000000010977.jpg +/userdata/val2017/000000555705.jpg +/userdata/val2017/000000551815.jpg +/userdata/val2017/000000160556.jpg +/userdata/val2017/000000516316.jpg +/userdata/val2017/000000427500.jpg +/userdata/val2017/000000547502.jpg +/userdata/val2017/000000129135.jpg +/userdata/val2017/000000198915.jpg +/userdata/val2017/000000149375.jpg +/userdata/val2017/000000108495.jpg +/userdata/val2017/000000089556.jpg +/userdata/val2017/000000222094.jpg +/userdata/val2017/000000185157.jpg +/userdata/val2017/000000318238.jpg +/userdata/val2017/000000278463.jpg +/userdata/val2017/000000526103.jpg +/userdata/val2017/000000468233.jpg +/userdata/val2017/000000354753.jpg +/userdata/val2017/000000010363.jpg +/userdata/val2017/000000504074.jpg +/userdata/val2017/000000122046.jpg +/userdata/val2017/000000085665.jpg +/userdata/val2017/000000140420.jpg +/userdata/val2017/000000510329.jpg +/userdata/val2017/000000455352.jpg +/userdata/val2017/000000447200.jpg +/userdata/val2017/000000397303.jpg +/userdata/val2017/000000324258.jpg +/userdata/val2017/000000192904.jpg +/userdata/val2017/000000206579.jpg +/userdata/val2017/000000034417.jpg +/userdata/val2017/000000058655.jpg +/userdata/val2017/000000106881.jpg +/userdata/val2017/000000468965.jpg +/userdata/val2017/000000464476.jpg +/userdata/val2017/000000265108.jpg +/userdata/val2017/000000460967.jpg +/userdata/val2017/000000087470.jpg +/userdata/val2017/000000565607.jpg +/userdata/val2017/000000041888.jpg +/userdata/val2017/000000110999.jpg +/userdata/val2017/000000442822.jpg +/userdata/val2017/000000481390.jpg +/userdata/val2017/000000156924.jpg +/userdata/val2017/000000108026.jpg +/userdata/val2017/000000360951.jpg +/userdata/val2017/000000145597.jpg +/userdata/val2017/000000181499.jpg +/userdata/val2017/000000467848.jpg +/userdata/val2017/000000445439.jpg +/userdata/val2017/000000207306.jpg +/userdata/val2017/000000475484.jpg +/userdata/val2017/000000192964.jpg +/userdata/val2017/000000227898.jpg +/userdata/val2017/000000446117.jpg +/userdata/val2017/000000149406.jpg +/userdata/val2017/000000377000.jpg +/userdata/val2017/000000511647.jpg +/userdata/val2017/000000500049.jpg +/userdata/val2017/000000239627.jpg +/userdata/val2017/000000038825.jpg +/userdata/val2017/000000328238.jpg +/userdata/val2017/000000113235.jpg +/userdata/val2017/000000394611.jpg +/userdata/val2017/000000490470.jpg +/userdata/val2017/000000407650.jpg +/userdata/val2017/000000016439.jpg +/userdata/val2017/000000105912.jpg +/userdata/val2017/000000170099.jpg +/userdata/val2017/000000182162.jpg +/userdata/val2017/000000079031.jpg +/userdata/val2017/000000515828.jpg +/userdata/val2017/000000055950.jpg +/userdata/val2017/000000436315.jpg +/userdata/val2017/000000379332.jpg +/userdata/val2017/000000465836.jpg +/userdata/val2017/000000210030.jpg +/userdata/val2017/000000475387.jpg +/userdata/val2017/000000141821.jpg +/userdata/val2017/000000459396.jpg +/userdata/val2017/000000144003.jpg +/userdata/val2017/000000402473.jpg +/userdata/val2017/000000181816.jpg +/userdata/val2017/000000161642.jpg +/userdata/val2017/000000081738.jpg +/userdata/val2017/000000257624.jpg +/userdata/val2017/000000573626.jpg +/userdata/val2017/000000535253.jpg +/userdata/val2017/000000267169.jpg +/userdata/val2017/000000571313.jpg +/userdata/val2017/000000479732.jpg +/userdata/val2017/000000433243.jpg +/userdata/val2017/000000565776.jpg +/userdata/val2017/000000548780.jpg +/userdata/val2017/000000340930.jpg +/userdata/val2017/000000056545.jpg +/userdata/val2017/000000276804.jpg +/userdata/val2017/000000447313.jpg +/userdata/val2017/000000206838.jpg +/userdata/val2017/000000565153.jpg +/userdata/val2017/000000060102.jpg +/userdata/val2017/000000239773.jpg +/userdata/val2017/000000300039.jpg +/userdata/val2017/000000370042.jpg +/userdata/val2017/000000515077.jpg +/userdata/val2017/000000446651.jpg +/userdata/val2017/000000545129.jpg +/userdata/val2017/000000466125.jpg +/userdata/val2017/000000173371.jpg +/userdata/val2017/000000243867.jpg +/userdata/val2017/000000166277.jpg +/userdata/val2017/000000008021.jpg +/userdata/val2017/000000216636.jpg +/userdata/val2017/000000577862.jpg +/userdata/val2017/000000154358.jpg +/userdata/val2017/000000270677.jpg +/userdata/val2017/000000457078.jpg +/userdata/val2017/000000206994.jpg +/userdata/val2017/000000179642.jpg +/userdata/val2017/000000365745.jpg +/userdata/val2017/000000080274.jpg +/userdata/val2017/000000237118.jpg +/userdata/val2017/000000572678.jpg +/userdata/val2017/000000525322.jpg +/userdata/val2017/000000450439.jpg +/userdata/val2017/000000189226.jpg +/userdata/val2017/000000522751.jpg +/userdata/val2017/000000067616.jpg +/userdata/val2017/000000118515.jpg +/userdata/val2017/000000187734.jpg +/userdata/val2017/000000502599.jpg +/userdata/val2017/000000445999.jpg +/userdata/val2017/000000008690.jpg +/userdata/val2017/000000085195.jpg +/userdata/val2017/000000567432.jpg +/userdata/val2017/000000071226.jpg +/userdata/val2017/000000237517.jpg +/userdata/val2017/000000216739.jpg +/userdata/val2017/000000447917.jpg +/userdata/val2017/000000212559.jpg +/userdata/val2017/000000302107.jpg +/userdata/val2017/000000158227.jpg +/userdata/val2017/000000226903.jpg +/userdata/val2017/000000295713.jpg +/userdata/val2017/000000577932.jpg +/userdata/val2017/000000263594.jpg +/userdata/val2017/000000539883.jpg +/userdata/val2017/000000296231.jpg +/userdata/val2017/000000553788.jpg +/userdata/val2017/000000563281.jpg +/userdata/val2017/000000236730.jpg +/userdata/val2017/000000350002.jpg +/userdata/val2017/000000276707.jpg +/userdata/val2017/000000372466.jpg +/userdata/val2017/000000217872.jpg +/userdata/val2017/000000550322.jpg +/userdata/val2017/000000443969.jpg +/userdata/val2017/000000177893.jpg +/userdata/val2017/000000523033.jpg +/userdata/val2017/000000485027.jpg +/userdata/val2017/000000053505.jpg +/userdata/val2017/000000086755.jpg +/userdata/val2017/000000171190.jpg +/userdata/val2017/000000387916.jpg +/userdata/val2017/000000140658.jpg +/userdata/val2017/000000167159.jpg +/userdata/val2017/000000220858.jpg +/userdata/val2017/000000040757.jpg +/userdata/val2017/000000544811.jpg +/userdata/val2017/000000024610.jpg +/userdata/val2017/000000235057.jpg +/userdata/val2017/000000527220.jpg +/userdata/val2017/000000452084.jpg +/userdata/val2017/000000267434.jpg +/userdata/val2017/000000560474.jpg +/userdata/val2017/000000322574.jpg +/userdata/val2017/000000350122.jpg +/userdata/val2017/000000090284.jpg +/userdata/val2017/000000110211.jpg +/userdata/val2017/000000559348.jpg +/userdata/val2017/000000047828.jpg +/userdata/val2017/000000290771.jpg +/userdata/val2017/000000303653.jpg +/userdata/val2017/000000023751.jpg +/userdata/val2017/000000195165.jpg +/userdata/val2017/000000273420.jpg +/userdata/val2017/000000233238.jpg +/userdata/val2017/000000031296.jpg +/userdata/val2017/000000017899.jpg +/userdata/val2017/000000317433.jpg +/userdata/val2017/000000340697.jpg +/userdata/val2017/000000229858.jpg +/userdata/val2017/000000356498.jpg +/userdata/val2017/000000441442.jpg +/userdata/val2017/000000492968.jpg +/userdata/val2017/000000213830.jpg +/userdata/val2017/000000213033.jpg +/userdata/val2017/000000520324.jpg +/userdata/val2017/000000466602.jpg +/userdata/val2017/000000042628.jpg +/userdata/val2017/000000033221.jpg +/userdata/val2017/000000285349.jpg +/userdata/val2017/000000015746.jpg +/userdata/val2017/000000323263.jpg +/userdata/val2017/000000300341.jpg +/userdata/val2017/000000474344.jpg +/userdata/val2017/000000312720.jpg +/userdata/val2017/000000164637.jpg +/userdata/val2017/000000569059.jpg +/userdata/val2017/000000007991.jpg +/userdata/val2017/000000195045.jpg +/userdata/val2017/000000267191.jpg +/userdata/val2017/000000006818.jpg +/userdata/val2017/000000292082.jpg +/userdata/val2017/000000054967.jpg +/userdata/val2017/000000377497.jpg +/userdata/val2017/000000161861.jpg +/userdata/val2017/000000389315.jpg +/userdata/val2017/000000028452.jpg +/userdata/val2017/000000128658.jpg +/userdata/val2017/000000236599.jpg +/userdata/val2017/000000182202.jpg +/userdata/val2017/000000466986.jpg +/userdata/val2017/000000559842.jpg +/userdata/val2017/000000189213.jpg +/userdata/val2017/000000006894.jpg +/userdata/val2017/000000164969.jpg +/userdata/val2017/000000327890.jpg +/userdata/val2017/000000180135.jpg +/userdata/val2017/000000101787.jpg +/userdata/val2017/000000027982.jpg +/userdata/val2017/000000079034.jpg +/userdata/val2017/000000098839.jpg +/userdata/val2017/000000012748.jpg +/userdata/val2017/000000403353.jpg +/userdata/val2017/000000157213.jpg +/userdata/val2017/000000194746.jpg +/userdata/val2017/000000517523.jpg +/userdata/val2017/000000001353.jpg +/userdata/val2017/000000263474.jpg +/userdata/val2017/000000122969.jpg +/userdata/val2017/000000229753.jpg +/userdata/val2017/000000377882.jpg +/userdata/val2017/000000130386.jpg +/userdata/val2017/000000148730.jpg +/userdata/val2017/000000045728.jpg +/userdata/val2017/000000288584.jpg +/userdata/val2017/000000166287.jpg +/userdata/val2017/000000521141.jpg +/userdata/val2017/000000173033.jpg +/userdata/val2017/000000256407.jpg +/userdata/val2017/000000393469.jpg +/userdata/val2017/000000079229.jpg +/userdata/val2017/000000155179.jpg +/userdata/val2017/000000019432.jpg +/userdata/val2017/000000443426.jpg +/userdata/val2017/000000071711.jpg +/userdata/val2017/000000199395.jpg +/userdata/val2017/000000565391.jpg +/userdata/val2017/000000181753.jpg +/userdata/val2017/000000416837.jpg +/userdata/val2017/000000245448.jpg +/userdata/val2017/000000502737.jpg +/userdata/val2017/000000078266.jpg +/userdata/val2017/000000384666.jpg +/userdata/val2017/000000114770.jpg +/userdata/val2017/000000327701.jpg +/userdata/val2017/000000268375.jpg +/userdata/val2017/000000224093.jpg +/userdata/val2017/000000449909.jpg +/userdata/val2017/000000322959.jpg +/userdata/val2017/000000473121.jpg +/userdata/val2017/000000116208.jpg +/userdata/val2017/000000460927.jpg +/userdata/val2017/000000525600.jpg +/userdata/val2017/000000290293.jpg +/userdata/val2017/000000256916.jpg +/userdata/val2017/000000531135.jpg +/userdata/val2017/000000303863.jpg +/userdata/val2017/000000393282.jpg +/userdata/val2017/000000427160.jpg +/userdata/val2017/000000000785.jpg +/userdata/val2017/000000480936.jpg +/userdata/val2017/000000236412.jpg +/userdata/val2017/000000394677.jpg +/userdata/val2017/000000395903.jpg +/userdata/val2017/000000363461.jpg +/userdata/val2017/000000577149.jpg +/userdata/val2017/000000109976.jpg +/userdata/val2017/000000354547.jpg +/userdata/val2017/000000219578.jpg +/userdata/val2017/000000024567.jpg +/userdata/val2017/000000081988.jpg +/userdata/val2017/000000244099.jpg +/userdata/val2017/000000297085.jpg +/userdata/val2017/000000258911.jpg +/userdata/val2017/000000542423.jpg +/userdata/val2017/000000383842.jpg +/userdata/val2017/000000219440.jpg +/userdata/val2017/000000128654.jpg +/userdata/val2017/000000355610.jpg +/userdata/val2017/000000498857.jpg +/userdata/val2017/000000104572.jpg +/userdata/val2017/000000537964.jpg +/userdata/val2017/000000546626.jpg +/userdata/val2017/000000562229.jpg +/userdata/val2017/000000094871.jpg +/userdata/val2017/000000361147.jpg +/userdata/val2017/000000431693.jpg +/userdata/val2017/000000568814.jpg +/userdata/val2017/000000558073.jpg +/userdata/val2017/000000005477.jpg +/userdata/val2017/000000144932.jpg +/userdata/val2017/000000241677.jpg +/userdata/val2017/000000532901.jpg +/userdata/val2017/000000243075.jpg +/userdata/val2017/000000365208.jpg +/userdata/val2017/000000194940.jpg +/userdata/val2017/000000356169.jpg +/userdata/val2017/000000427997.jpg +/userdata/val2017/000000212166.jpg +/userdata/val2017/000000283113.jpg +/userdata/val2017/000000252716.jpg +/userdata/val2017/000000033368.jpg +/userdata/val2017/000000440184.jpg +/userdata/val2017/000000438304.jpg +/userdata/val2017/000000334555.jpg +/userdata/val2017/000000367228.jpg +/userdata/val2017/000000521956.jpg +/userdata/val2017/000000071938.jpg +/userdata/val2017/000000281032.jpg +/userdata/val2017/000000002006.jpg +/userdata/val2017/000000287527.jpg +/userdata/val2017/000000157046.jpg +/userdata/val2017/000000424721.jpg +/userdata/val2017/000000527960.jpg +/userdata/val2017/000000041990.jpg +/userdata/val2017/000000299887.jpg +/userdata/val2017/000000481413.jpg +/userdata/val2017/000000492992.jpg +/userdata/val2017/000000528980.jpg +/userdata/val2017/000000563604.jpg +/userdata/val2017/000000044590.jpg +/userdata/val2017/000000031735.jpg +/userdata/val2017/000000022396.jpg +/userdata/val2017/000000059920.jpg +/userdata/val2017/000000270402.jpg +/userdata/val2017/000000521540.jpg +/userdata/val2017/000000285047.jpg +/userdata/val2017/000000421923.jpg +/userdata/val2017/000000048504.jpg +/userdata/val2017/000000471567.jpg +/userdata/val2017/000000224664.jpg +/userdata/val2017/000000502336.jpg +/userdata/val2017/000000474170.jpg +/userdata/val2017/000000427338.jpg +/userdata/val2017/000000084492.jpg +/userdata/val2017/000000301867.jpg +/userdata/val2017/000000199310.jpg +/userdata/val2017/000000074058.jpg +/userdata/val2017/000000409268.jpg +/userdata/val2017/000000364102.jpg +/userdata/val2017/000000517056.jpg +/userdata/val2017/000000291619.jpg +/userdata/val2017/000000277020.jpg +/userdata/val2017/000000554266.jpg +/userdata/val2017/000000174231.jpg +/userdata/val2017/000000145020.jpg +/userdata/val2017/000000068286.jpg +/userdata/val2017/000000082765.jpg +/userdata/val2017/000000035197.jpg +/userdata/val2017/000000410456.jpg +/userdata/val2017/000000305317.jpg +/userdata/val2017/000000023126.jpg +/userdata/val2017/000000402096.jpg +/userdata/val2017/000000233370.jpg +/userdata/val2017/000000061584.jpg +/userdata/val2017/000000478286.jpg +/userdata/val2017/000000248631.jpg +/userdata/val2017/000000508730.jpg +/userdata/val2017/000000116206.jpg +/userdata/val2017/000000402334.jpg +/userdata/val2017/000000425361.jpg +/userdata/val2017/000000293324.jpg +/userdata/val2017/000000248400.jpg +/userdata/val2017/000000152686.jpg +/userdata/val2017/000000007816.jpg +/userdata/val2017/000000556498.jpg +/userdata/val2017/000000420281.jpg +/userdata/val2017/000000391290.jpg +/userdata/val2017/000000167898.jpg +/userdata/val2017/000000122962.jpg +/userdata/val2017/000000025386.jpg +/userdata/val2017/000000023937.jpg +/userdata/val2017/000000492937.jpg +/userdata/val2017/000000293044.jpg +/userdata/val2017/000000165831.jpg +/userdata/val2017/000000501005.jpg +/userdata/val2017/000000432898.jpg +/userdata/val2017/000000172649.jpg +/userdata/val2017/000000516677.jpg +/userdata/val2017/000000205105.jpg +/userdata/val2017/000000532058.jpg +/userdata/val2017/000000015338.jpg +/userdata/val2017/000000177213.jpg +/userdata/val2017/000000517832.jpg +/userdata/val2017/000000033759.jpg +/userdata/val2017/000000279730.jpg +/userdata/val2017/000000126592.jpg +/userdata/val2017/000000463849.jpg +/userdata/val2017/000000065074.jpg +/userdata/val2017/000000491216.jpg +/userdata/val2017/000000273711.jpg +/userdata/val2017/000000196009.jpg +/userdata/val2017/000000521601.jpg +/userdata/val2017/000000516318.jpg +/userdata/val2017/000000388215.jpg +/userdata/val2017/000000472298.jpg +/userdata/val2017/000000150726.jpg +/userdata/val2017/000000221017.jpg +/userdata/val2017/000000182805.jpg +/userdata/val2017/000000400922.jpg +/userdata/val2017/000000203931.jpg +/userdata/val2017/000000106235.jpg +/userdata/val2017/000000070158.jpg +/userdata/val2017/000000412240.jpg +/userdata/val2017/000000025096.jpg +/userdata/val2017/000000004134.jpg +/userdata/val2017/000000233825.jpg +/userdata/val2017/000000425925.jpg +/userdata/val2017/000000130599.jpg +/userdata/val2017/000000408830.jpg +/userdata/val2017/000000006614.jpg +/userdata/val2017/000000416451.jpg +/userdata/val2017/000000370208.jpg +/userdata/val2017/000000311394.jpg +/userdata/val2017/000000347544.jpg +/userdata/val2017/000000327780.jpg +/userdata/val2017/000000488166.jpg +/userdata/val2017/000000333069.jpg +/userdata/val2017/000000013291.jpg +/userdata/val2017/000000393014.jpg +/userdata/val2017/000000492110.jpg +/userdata/val2017/000000430048.jpg +/userdata/val2017/000000549738.jpg +/userdata/val2017/000000203629.jpg +/userdata/val2017/000000119911.jpg +/userdata/val2017/000000504000.jpg +/userdata/val2017/000000337987.jpg +/userdata/val2017/000000564023.jpg +/userdata/val2017/000000205289.jpg +/userdata/val2017/000000312549.jpg +/userdata/val2017/000000249786.jpg +/userdata/val2017/000000553221.jpg +/userdata/val2017/000000210273.jpg +/userdata/val2017/000000493019.jpg +/userdata/val2017/000000289741.jpg +/userdata/val2017/000000117719.jpg +/userdata/val2017/000000484296.jpg +/userdata/val2017/000000162732.jpg +/userdata/val2017/000000541773.jpg +/userdata/val2017/000000401862.jpg +/userdata/val2017/000000333772.jpg +/userdata/val2017/000000162581.jpg +/userdata/val2017/000000434204.jpg +/userdata/val2017/000000179214.jpg +/userdata/val2017/000000426166.jpg +/userdata/val2017/000000516804.jpg +/userdata/val2017/000000529122.jpg +/userdata/val2017/000000442463.jpg +/userdata/val2017/000000376284.jpg +/userdata/val2017/000000301981.jpg +/userdata/val2017/000000411665.jpg +/userdata/val2017/000000493864.jpg +/userdata/val2017/000000530836.jpg +/userdata/val2017/000000342006.jpg +/userdata/val2017/000000314294.jpg +/userdata/val2017/000000125129.jpg +/userdata/val2017/000000124798.jpg +/userdata/val2017/000000246968.jpg +/userdata/val2017/000000435206.jpg +/userdata/val2017/000000382696.jpg +/userdata/val2017/000000046463.jpg +/userdata/val2017/000000267670.jpg +/userdata/val2017/000000126107.jpg +/userdata/val2017/000000550349.jpg +/userdata/val2017/000000067310.jpg +/userdata/val2017/000000477441.jpg +/userdata/val2017/000000378099.jpg +/userdata/val2017/000000479030.jpg +/userdata/val2017/000000379441.jpg +/userdata/val2017/000000142620.jpg +/userdata/val2017/000000007888.jpg +/userdata/val2017/000000179487.jpg +/userdata/val2017/000000292330.jpg +/userdata/val2017/000000338718.jpg +/userdata/val2017/000000006460.jpg +/userdata/val2017/000000328117.jpg +/userdata/val2017/000000449996.jpg +/userdata/val2017/000000297084.jpg +/userdata/val2017/000000080057.jpg +/userdata/val2017/000000543047.jpg +/userdata/val2017/000000072813.jpg +/userdata/val2017/000000081594.jpg +/userdata/val2017/000000471450.jpg +/userdata/val2017/000000106330.jpg +/userdata/val2017/000000109916.jpg +/userdata/val2017/000000286907.jpg +/userdata/val2017/000000270297.jpg +/userdata/val2017/000000388258.jpg +/userdata/val2017/000000566524.jpg +/userdata/val2017/000000098018.jpg +/userdata/val2017/000000438017.jpg +/userdata/val2017/000000564091.jpg +/userdata/val2017/000000146457.jpg +/userdata/val2017/000000384527.jpg +/userdata/val2017/000000241602.jpg +/userdata/val2017/000000525247.jpg +/userdata/val2017/000000376625.jpg +/userdata/val2017/000000394559.jpg +/userdata/val2017/000000348708.jpg +/userdata/val2017/000000449661.jpg +/userdata/val2017/000000295478.jpg +/userdata/val2017/000000308193.jpg +/userdata/val2017/000000313182.jpg +/userdata/val2017/000000366711.jpg +/userdata/val2017/000000083540.jpg +/userdata/val2017/000000027186.jpg +/userdata/val2017/000000308531.jpg +/userdata/val2017/000000191614.jpg +/userdata/val2017/000000101780.jpg +/userdata/val2017/000000052996.jpg +/userdata/val2017/000000482719.jpg +/userdata/val2017/000000533145.jpg +/userdata/val2017/000000289417.jpg +/userdata/val2017/000000312192.jpg +/userdata/val2017/000000381639.jpg +/userdata/val2017/000000283037.jpg +/userdata/val2017/000000474021.jpg +/userdata/val2017/000000288762.jpg +/userdata/val2017/000000506933.jpg +/userdata/val2017/000000445248.jpg +/userdata/val2017/000000084664.jpg +/userdata/val2017/000000138115.jpg +/userdata/val2017/000000463842.jpg +/userdata/val2017/000000551822.jpg +/userdata/val2017/000000215259.jpg +/userdata/val2017/000000214205.jpg +/userdata/val2017/000000080273.jpg +/userdata/val2017/000000001761.jpg +/userdata/val2017/000000147415.jpg +/userdata/val2017/000000489764.jpg +/userdata/val2017/000000552775.jpg +/userdata/val2017/000000523194.jpg +/userdata/val2017/000000026926.jpg +/userdata/val2017/000000290179.jpg +/userdata/val2017/000000369037.jpg +/userdata/val2017/000000296969.jpg +/userdata/val2017/000000013201.jpg +/userdata/val2017/000000144333.jpg +/userdata/val2017/000000472375.jpg +/userdata/val2017/000000491757.jpg +/userdata/val2017/000000198641.jpg +/userdata/val2017/000000049810.jpg +/userdata/val2017/000000277005.jpg +/userdata/val2017/000000471023.jpg +/userdata/val2017/000000091500.jpg +/userdata/val2017/000000159791.jpg +/userdata/val2017/000000565563.jpg +/userdata/val2017/000000023359.jpg +/userdata/val2017/000000452891.jpg +/userdata/val2017/000000506004.jpg +/userdata/val2017/000000192670.jpg +/userdata/val2017/000000364126.jpg +/userdata/val2017/000000278006.jpg +/userdata/val2017/000000322864.jpg +/userdata/val2017/000000404922.jpg +/userdata/val2017/000000245764.jpg +/userdata/val2017/000000506178.jpg +/userdata/val2017/000000082807.jpg +/userdata/val2017/000000116362.jpg +/userdata/val2017/000000249025.jpg +/userdata/val2017/000000030828.jpg +/userdata/val2017/000000135673.jpg +/userdata/val2017/000000529939.jpg +/userdata/val2017/000000223955.jpg +/userdata/val2017/000000121586.jpg +/userdata/val2017/000000006012.jpg +/userdata/val2017/000000419098.jpg +/userdata/val2017/000000343453.jpg +/userdata/val2017/000000181796.jpg +/userdata/val2017/000000261161.jpg +/userdata/val2017/000000177065.jpg +/userdata/val2017/000000192047.jpg +/userdata/val2017/000000033854.jpg +/userdata/val2017/000000399655.jpg +/userdata/val2017/000000239274.jpg +/userdata/val2017/000000013659.jpg +/userdata/val2017/000000037751.jpg +/userdata/val2017/000000566042.jpg +/userdata/val2017/000000575815.jpg +/userdata/val2017/000000017031.jpg +/userdata/val2017/000000407574.jpg +/userdata/val2017/000000222559.jpg +/userdata/val2017/000000250901.jpg +/userdata/val2017/000000297396.jpg +/userdata/val2017/000000052891.jpg +/userdata/val2017/000000169356.jpg +/userdata/val2017/000000383443.jpg +/userdata/val2017/000000425702.jpg +/userdata/val2017/000000206271.jpg +/userdata/val2017/000000039956.jpg +/userdata/val2017/000000581317.jpg +/userdata/val2017/000000574315.jpg +/userdata/val2017/000000389532.jpg +/userdata/val2017/000000065798.jpg +/userdata/val2017/000000494863.jpg +/userdata/val2017/000000391144.jpg +/userdata/val2017/000000338532.jpg +/userdata/val2017/000000372577.jpg +/userdata/val2017/000000259854.jpg +/userdata/val2017/000000032735.jpg +/userdata/val2017/000000341196.jpg +/userdata/val2017/000000228214.jpg +/userdata/val2017/000000475779.jpg +/userdata/val2017/000000549220.jpg +/userdata/val2017/000000502229.jpg +/userdata/val2017/000000369771.jpg +/userdata/val2017/000000539962.jpg +/userdata/val2017/000000493566.jpg +/userdata/val2017/000000428867.jpg +/userdata/val2017/000000066926.jpg +/userdata/val2017/000000043581.jpg +/userdata/val2017/000000551660.jpg +/userdata/val2017/000000029397.jpg +/userdata/val2017/000000160864.jpg +/userdata/val2017/000000374727.jpg +/userdata/val2017/000000138639.jpg +/userdata/val2017/000000197388.jpg +/userdata/val2017/000000120420.jpg +/userdata/val2017/000000128148.jpg +/userdata/val2017/000000302452.jpg +/userdata/val2017/000000161820.jpg +/userdata/val2017/000000579970.jpg +/userdata/val2017/000000360137.jpg +/userdata/val2017/000000170613.jpg +/userdata/val2017/000000426253.jpg +/userdata/val2017/000000046872.jpg +/userdata/val2017/000000267351.jpg +/userdata/val2017/000000562243.jpg +/userdata/val2017/000000020247.jpg +/userdata/val2017/000000561009.jpg +/userdata/val2017/000000297343.jpg +/userdata/val2017/000000264335.jpg +/userdata/val2017/000000569030.jpg +/userdata/val2017/000000309391.jpg +/userdata/val2017/000000540414.jpg +/userdata/val2017/000000068093.jpg +/userdata/val2017/000000357888.jpg +/userdata/val2017/000000217285.jpg +/userdata/val2017/000000246454.jpg +/userdata/val2017/000000527528.jpg +/userdata/val2017/000000364884.jpg +/userdata/val2017/000000329827.jpg +/userdata/val2017/000000541952.jpg +/userdata/val2017/000000293300.jpg +/userdata/val2017/000000350388.jpg +/userdata/val2017/000000315492.jpg +/userdata/val2017/000000402433.jpg +/userdata/val2017/000000131379.jpg +/userdata/val2017/000000376307.jpg +/userdata/val2017/000000563603.jpg +/userdata/val2017/000000348012.jpg +/userdata/val2017/000000406417.jpg +/userdata/val2017/000000247917.jpg +/userdata/val2017/000000487583.jpg +/userdata/val2017/000000324715.jpg +/userdata/val2017/000000404484.jpg +/userdata/val2017/000000260261.jpg +/userdata/val2017/000000045550.jpg +/userdata/val2017/000000329319.jpg +/userdata/val2017/000000080153.jpg +/userdata/val2017/000000368294.jpg +/userdata/val2017/000000125572.jpg +/userdata/val2017/000000106048.jpg +/userdata/val2017/000000370375.jpg +/userdata/val2017/000000245320.jpg +/userdata/val2017/000000261888.jpg +/userdata/val2017/000000031217.jpg +/userdata/val2017/000000344816.jpg +/userdata/val2017/000000245576.jpg +/userdata/val2017/000000221693.jpg +/userdata/val2017/000000491130.jpg +/userdata/val2017/000000223738.jpg +/userdata/val2017/000000260657.jpg +/userdata/val2017/000000181303.jpg +/userdata/val2017/000000491497.jpg +/userdata/val2017/000000148508.jpg +/userdata/val2017/000000106912.jpg +/userdata/val2017/000000512330.jpg +/userdata/val2017/000000197796.jpg +/userdata/val2017/000000514979.jpg +/userdata/val2017/000000449406.jpg +/userdata/val2017/000000538364.jpg +/userdata/val2017/000000052565.jpg +/userdata/val2017/000000533493.jpg +/userdata/val2017/000000352618.jpg +/userdata/val2017/000000039785.jpg +/userdata/val2017/000000139883.jpg +/userdata/val2017/000000030213.jpg +/userdata/val2017/000000064462.jpg +/userdata/val2017/000000429623.jpg +/userdata/val2017/000000115870.jpg +/userdata/val2017/000000338624.jpg +/userdata/val2017/000000265816.jpg +/userdata/val2017/000000465180.jpg +/userdata/val2017/000000540962.jpg +/userdata/val2017/000000032081.jpg +/userdata/val2017/000000455301.jpg +/userdata/val2017/000000182611.jpg +/userdata/val2017/000000232538.jpg +/userdata/val2017/000000304404.jpg +/userdata/val2017/000000226171.jpg +/userdata/val2017/000000153510.jpg +/userdata/val2017/000000184762.jpg +/userdata/val2017/000000223130.jpg +/userdata/val2017/000000455981.jpg +/userdata/val2017/000000579818.jpg +/userdata/val2017/000000541055.jpg +/userdata/val2017/000000422886.jpg +/userdata/val2017/000000199551.jpg +/userdata/val2017/000000023781.jpg +/userdata/val2017/000000015278.jpg +/userdata/val2017/000000173302.jpg +/userdata/val2017/000000349594.jpg +/userdata/val2017/000000344888.jpg +/userdata/val2017/000000166664.jpg +/userdata/val2017/000000187055.jpg +/userdata/val2017/000000484029.jpg +/userdata/val2017/000000575081.jpg +/userdata/val2017/000000372718.jpg +/userdata/val2017/000000363875.jpg +/userdata/val2017/000000140203.jpg +/userdata/val2017/000000366225.jpg +/userdata/val2017/000000569565.jpg +/userdata/val2017/000000434297.jpg +/userdata/val2017/000000214703.jpg +/userdata/val2017/000000378244.jpg +/userdata/val2017/000000183127.jpg +/userdata/val2017/000000571718.jpg +/userdata/val2017/000000571008.jpg +/userdata/val2017/000000174482.jpg +/userdata/val2017/000000080949.jpg +/userdata/val2017/000000552883.jpg +/userdata/val2017/000000135902.jpg +/userdata/val2017/000000545958.jpg +/userdata/val2017/000000423617.jpg +/userdata/val2017/000000453341.jpg +/userdata/val2017/000000335081.jpg +/userdata/val2017/000000284282.jpg +/userdata/val2017/000000082846.jpg +/userdata/val2017/000000400794.jpg +/userdata/val2017/000000132329.jpg +/userdata/val2017/000000532129.jpg +/userdata/val2017/000000405205.jpg +/userdata/val2017/000000021604.jpg +/userdata/val2017/000000458255.jpg +/userdata/val2017/000000128699.jpg +/userdata/val2017/000000366884.jpg +/userdata/val2017/000000433192.jpg +/userdata/val2017/000000269866.jpg +/userdata/val2017/000000340272.jpg +/userdata/val2017/000000416758.jpg +/userdata/val2017/000000203864.jpg +/userdata/val2017/000000203389.jpg +/userdata/val2017/000000455085.jpg +/userdata/val2017/000000351331.jpg +/userdata/val2017/000000373315.jpg +/userdata/val2017/000000536038.jpg +/userdata/val2017/000000460229.jpg +/userdata/val2017/000000088250.jpg +/userdata/val2017/000000209753.jpg +/userdata/val2017/000000270386.jpg +/userdata/val2017/000000083113.jpg +/userdata/val2017/000000025393.jpg +/userdata/val2017/000000378873.jpg +/userdata/val2017/000000149568.jpg +/userdata/val2017/000000304545.jpg +/userdata/val2017/000000123585.jpg +/userdata/val2017/000000483050.jpg +/userdata/val2017/000000124636.jpg +/userdata/val2017/000000025139.jpg +/userdata/val2017/000000376278.jpg +/userdata/val2017/000000438955.jpg +/userdata/val2017/000000463522.jpg +/userdata/val2017/000000505565.jpg +/userdata/val2017/000000010092.jpg +/userdata/val2017/000000421834.jpg +/userdata/val2017/000000422706.jpg +/userdata/val2017/000000360325.jpg +/userdata/val2017/000000402346.jpg +/userdata/val2017/000000184978.jpg +/userdata/val2017/000000460160.jpg +/userdata/val2017/000000245651.jpg +/userdata/val2017/000000042070.jpg +/userdata/val2017/000000020059.jpg +/userdata/val2017/000000488251.jpg +/userdata/val2017/000000275727.jpg +/userdata/val2017/000000546829.jpg +/userdata/val2017/000000224119.jpg +/userdata/val2017/000000458755.jpg +/userdata/val2017/000000076731.jpg +/userdata/val2017/000000387148.jpg +/userdata/val2017/000000389451.jpg +/userdata/val2017/000000279774.jpg +/userdata/val2017/000000568195.jpg +/userdata/val2017/000000165039.jpg +/userdata/val2017/000000533536.jpg +/userdata/val2017/000000184321.jpg +/userdata/val2017/000000050165.jpg +/userdata/val2017/000000212895.jpg +/userdata/val2017/000000216516.jpg +/userdata/val2017/000000125072.jpg +/userdata/val2017/000000277689.jpg +/userdata/val2017/000000229111.jpg +/userdata/val2017/000000264535.jpg +/userdata/val2017/000000050943.jpg +/userdata/val2017/000000104603.jpg +/userdata/val2017/000000256941.jpg +/userdata/val2017/000000137727.jpg +/userdata/val2017/000000119452.jpg +/userdata/val2017/000000289938.jpg +/userdata/val2017/000000016958.jpg +/userdata/val2017/000000557672.jpg +/userdata/val2017/000000255401.jpg +/userdata/val2017/000000384136.jpg +/userdata/val2017/000000419096.jpg +/userdata/val2017/000000091654.jpg +/userdata/val2017/000000391375.jpg +/userdata/val2017/000000365642.jpg +/userdata/val2017/000000399205.jpg +/userdata/val2017/000000154339.jpg +/userdata/val2017/000000079144.jpg +/userdata/val2017/000000029675.jpg +/userdata/val2017/000000323151.jpg +/userdata/val2017/000000406129.jpg +/userdata/val2017/000000244496.jpg +/userdata/val2017/000000227985.jpg +/userdata/val2017/000000553731.jpg +/userdata/val2017/000000442836.jpg +/userdata/val2017/000000186637.jpg +/userdata/val2017/000000061108.jpg +/userdata/val2017/000000293390.jpg +/userdata/val2017/000000101022.jpg +/userdata/val2017/000000025394.jpg +/userdata/val2017/000000171788.jpg +/userdata/val2017/000000380913.jpg +/userdata/val2017/000000567898.jpg +/userdata/val2017/000000485130.jpg +/userdata/val2017/000000493284.jpg +/userdata/val2017/000000042296.jpg +/userdata/val2017/000000175364.jpg +/userdata/val2017/000000410880.jpg +/userdata/val2017/000000092416.jpg +/userdata/val2017/000000080659.jpg +/userdata/val2017/000000035279.jpg +/userdata/val2017/000000002149.jpg +/userdata/val2017/000000357567.jpg +/userdata/val2017/000000183965.jpg +/userdata/val2017/000000253002.jpg +/userdata/val2017/000000047819.jpg +/userdata/val2017/000000185950.jpg +/userdata/val2017/000000365385.jpg +/userdata/val2017/000000429718.jpg +/userdata/val2017/000000159282.jpg +/userdata/val2017/000000388927.jpg +/userdata/val2017/000000001296.jpg +/userdata/val2017/000000281447.jpg +/userdata/val2017/000000345397.jpg +/userdata/val2017/000000404534.jpg +/userdata/val2017/000000018519.jpg +/userdata/val2017/000000406570.jpg +/userdata/val2017/000000042563.jpg +/userdata/val2017/000000376365.jpg +/userdata/val2017/000000081061.jpg +/userdata/val2017/000000210394.jpg +/userdata/val2017/000000196442.jpg +/userdata/val2017/000000361571.jpg +/userdata/val2017/000000146358.jpg +/userdata/val2017/000000405691.jpg +/userdata/val2017/000000453040.jpg +/userdata/val2017/000000151938.jpg +/userdata/val2017/000000367569.jpg +/userdata/val2017/000000231088.jpg +/userdata/val2017/000000213086.jpg +/userdata/val2017/000000319696.jpg +/userdata/val2017/000000578792.jpg +/userdata/val2017/000000347370.jpg +/userdata/val2017/000000165351.jpg +/userdata/val2017/000000491366.jpg +/userdata/val2017/000000270244.jpg +/userdata/val2017/000000454404.jpg +/userdata/val2017/000000144114.jpg +/userdata/val2017/000000343706.jpg +/userdata/val2017/000000396274.jpg +/userdata/val2017/000000259597.jpg +/userdata/val2017/000000546823.jpg +/userdata/val2017/000000329323.jpg +/userdata/val2017/000000237316.jpg +/userdata/val2017/000000392228.jpg +/userdata/val2017/000000269314.jpg +/userdata/val2017/000000043314.jpg +/userdata/val2017/000000545594.jpg +/userdata/val2017/000000248616.jpg +/userdata/val2017/000000089761.jpg +/userdata/val2017/000000348488.jpg +/userdata/val2017/000000530052.jpg +/userdata/val2017/000000007088.jpg +/userdata/val2017/000000280710.jpg +/userdata/val2017/000000248810.jpg +/userdata/val2017/000000252701.jpg +/userdata/val2017/000000328286.jpg +/userdata/val2017/000000390555.jpg +/userdata/val2017/000000569972.jpg +/userdata/val2017/000000157601.jpg +/userdata/val2017/000000538236.jpg +/userdata/val2017/000000412894.jpg +/userdata/val2017/000000089697.jpg +/userdata/val2017/000000222455.jpg +/userdata/val2017/000000122672.jpg +/userdata/val2017/000000551794.jpg +/userdata/val2017/000000562561.jpg +/userdata/val2017/000000051598.jpg +/userdata/val2017/000000078748.jpg +/userdata/val2017/000000278848.jpg +/userdata/val2017/000000001818.jpg +/userdata/val2017/000000183648.jpg +/userdata/val2017/000000288062.jpg +/userdata/val2017/000000230450.jpg +/userdata/val2017/000000301421.jpg +/userdata/val2017/000000031050.jpg +/userdata/val2017/000000374982.jpg +/userdata/val2017/000000216296.jpg +/userdata/val2017/000000193926.jpg +/userdata/val2017/000000011149.jpg +/userdata/val2017/000000099810.jpg +/userdata/val2017/000000093154.jpg +/userdata/val2017/000000518770.jpg +/userdata/val2017/000000066635.jpg +/userdata/val2017/000000131131.jpg +/userdata/val2017/000000067896.jpg +/userdata/val2017/000000142092.jpg +/userdata/val2017/000000210789.jpg +/userdata/val2017/000000201025.jpg +/userdata/val2017/000000543043.jpg +/userdata/val2017/000000009772.jpg +/userdata/val2017/000000097230.jpg +/userdata/val2017/000000050145.jpg +/userdata/val2017/000000112626.jpg +/userdata/val2017/000000370270.jpg +/userdata/val2017/000000507081.jpg +/userdata/val2017/000000057027.jpg +/userdata/val2017/000000172935.jpg +/userdata/val2017/000000482319.jpg +/userdata/val2017/000000522638.jpg +/userdata/val2017/000000208208.jpg +/userdata/val2017/000000319721.jpg +/userdata/val2017/000000328430.jpg +/userdata/val2017/000000499181.jpg +/userdata/val2017/000000528705.jpg +/userdata/val2017/000000079565.jpg +/userdata/val2017/000000312552.jpg +/userdata/val2017/000000221155.jpg +/userdata/val2017/000000468505.jpg +/userdata/val2017/000000172977.jpg +/userdata/val2017/000000537802.jpg +/userdata/val2017/000000425390.jpg +/userdata/val2017/000000369310.jpg +/userdata/val2017/000000356094.jpg +/userdata/val2017/000000441468.jpg +/userdata/val2017/000000236426.jpg +/userdata/val2017/000000045229.jpg +/userdata/val2017/000000504389.jpg +/userdata/val2017/000000153217.jpg +/userdata/val2017/000000259640.jpg +/userdata/val2017/000000151857.jpg +/userdata/val2017/000000038070.jpg +/userdata/val2017/000000223747.jpg +/userdata/val2017/000000308430.jpg +/userdata/val2017/000000037988.jpg +/userdata/val2017/000000519569.jpg +/userdata/val2017/000000385205.jpg +/userdata/val2017/000000515577.jpg +/userdata/val2017/000000562121.jpg +/userdata/val2017/000000456292.jpg +/userdata/val2017/000000489924.jpg +/userdata/val2017/000000400044.jpg +/userdata/val2017/000000555050.jpg +/userdata/val2017/000000357238.jpg +/userdata/val2017/000000407960.jpg +/userdata/val2017/000000049269.jpg +/userdata/val2017/000000371529.jpg +/userdata/val2017/000000365766.jpg +/userdata/val2017/000000044279.jpg +/userdata/val2017/000000254368.jpg +/userdata/val2017/000000345466.jpg +/userdata/val2017/000000338901.jpg +/userdata/val2017/000000109827.jpg +/userdata/val2017/000000261706.jpg +/userdata/val2017/000000118209.jpg +/userdata/val2017/000000229997.jpg +/userdata/val2017/000000055022.jpg +/userdata/val2017/000000320642.jpg +/userdata/val2017/000000095155.jpg +/userdata/val2017/000000085329.jpg +/userdata/val2017/000000202001.jpg +/userdata/val2017/000000460683.jpg +/userdata/val2017/000000440617.jpg +/userdata/val2017/000000044699.jpg +/userdata/val2017/000000535578.jpg +/userdata/val2017/000000537270.jpg +/userdata/val2017/000000579635.jpg +/userdata/val2017/000000258883.jpg +/userdata/val2017/000000276285.jpg +/userdata/val2017/000000140640.jpg +/userdata/val2017/000000066231.jpg +/userdata/val2017/000000105335.jpg +/userdata/val2017/000000267933.jpg +/userdata/val2017/000000111179.jpg +/userdata/val2017/000000110972.jpg +/userdata/val2017/000000274708.jpg +/userdata/val2017/000000092660.jpg +/userdata/val2017/000000025424.jpg +/userdata/val2017/000000463174.jpg +/userdata/val2017/000000453860.jpg +/userdata/val2017/000000273493.jpg +/userdata/val2017/000000181969.jpg +/userdata/val2017/000000218424.jpg +/userdata/val2017/000000047571.jpg +/userdata/val2017/000000458054.jpg +/userdata/val2017/000000520910.jpg +/userdata/val2017/000000460379.jpg +/userdata/val2017/000000176634.jpg +/userdata/val2017/000000565962.jpg +/userdata/val2017/000000513283.jpg +/userdata/val2017/000000368940.jpg +/userdata/val2017/000000145620.jpg +/userdata/val2017/000000183246.jpg +/userdata/val2017/000000346232.jpg +/userdata/val2017/000000001000.jpg +/userdata/val2017/000000382122.jpg +/userdata/val2017/000000213816.jpg +/userdata/val2017/000000127263.jpg +/userdata/val2017/000000316015.jpg +/userdata/val2017/000000132587.jpg +/userdata/val2017/000000171050.jpg +/userdata/val2017/000000313562.jpg +/userdata/val2017/000000078565.jpg +/userdata/val2017/000000489014.jpg +/userdata/val2017/000000436738.jpg +/userdata/val2017/000000097278.jpg +/userdata/val2017/000000060770.jpg +/userdata/val2017/000000364557.jpg +/userdata/val2017/000000295420.jpg +/userdata/val2017/000000275749.jpg +/userdata/val2017/000000408774.jpg +/userdata/val2017/000000541664.jpg +/userdata/val2017/000000022935.jpg +/userdata/val2017/000000454798.jpg +/userdata/val2017/000000455157.jpg +/userdata/val2017/000000294350.jpg +/userdata/val2017/000000415727.jpg +/userdata/val2017/000000039477.jpg +/userdata/val2017/000000029984.jpg +/userdata/val2017/000000157390.jpg +/userdata/val2017/000000331075.jpg +/userdata/val2017/000000091619.jpg +/userdata/val2017/000000134856.jpg +/userdata/val2017/000000373353.jpg +/userdata/val2017/000000470779.jpg +/userdata/val2017/000000236914.jpg +/userdata/val2017/000000192871.jpg +/userdata/val2017/000000017959.jpg +/userdata/val2017/000000449198.jpg +/userdata/val2017/000000347693.jpg +/userdata/val2017/000000011813.jpg +/userdata/val2017/000000281409.jpg +/userdata/val2017/000000231169.jpg +/userdata/val2017/000000264441.jpg +/userdata/val2017/000000100582.jpg +/userdata/val2017/000000283038.jpg +/userdata/val2017/000000242060.jpg +/userdata/val2017/000000369081.jpg +/userdata/val2017/000000391140.jpg +/userdata/val2017/000000407868.jpg +/userdata/val2017/000000168330.jpg +/userdata/val2017/000000087742.jpg +/userdata/val2017/000000466156.jpg +/userdata/val2017/000000442323.jpg +/userdata/val2017/000000269682.jpg +/userdata/val2017/000000404678.jpg +/userdata/val2017/000000476810.jpg +/userdata/val2017/000000070229.jpg +/userdata/val2017/000000006763.jpg +/userdata/val2017/000000547144.jpg +/userdata/val2017/000000066706.jpg +/userdata/val2017/000000516916.jpg +/userdata/val2017/000000325991.jpg +/userdata/val2017/000000187243.jpg +/userdata/val2017/000000283412.jpg +/userdata/val2017/000000322610.jpg +/userdata/val2017/000000505942.jpg +/userdata/val2017/000000466256.jpg +/userdata/val2017/000000074457.jpg +/userdata/val2017/000000378139.jpg +/userdata/val2017/000000198960.jpg +/userdata/val2017/000000561465.jpg +/userdata/val2017/000000118367.jpg +/userdata/val2017/000000532761.jpg +/userdata/val2017/000000414510.jpg +/userdata/val2017/000000306437.jpg +/userdata/val2017/000000569825.jpg +/userdata/val2017/000000167128.jpg +/userdata/val2017/000000288882.jpg +/userdata/val2017/000000537506.jpg +/userdata/val2017/000000359937.jpg +/userdata/val2017/000000499266.jpg +/userdata/val2017/000000313454.jpg +/userdata/val2017/000000253742.jpg +/userdata/val2017/000000268000.jpg +/userdata/val2017/000000461573.jpg +/userdata/val2017/000000369812.jpg +/userdata/val2017/000000479099.jpg +/userdata/val2017/000000154213.jpg +/userdata/val2017/000000131444.jpg +/userdata/val2017/000000222991.jpg +/userdata/val2017/000000578871.jpg +/userdata/val2017/000000164883.jpg +/userdata/val2017/000000127660.jpg +/userdata/val2017/000000166165.jpg +/userdata/val2017/000000297353.jpg +/userdata/val2017/000000571804.jpg +/userdata/val2017/000000509451.jpg +/userdata/val2017/000000084650.jpg +/userdata/val2017/000000234660.jpg +/userdata/val2017/000000344059.jpg +/userdata/val2017/000000117197.jpg +/userdata/val2017/000000150265.jpg +/userdata/val2017/000000519764.jpg +/userdata/val2017/000000003501.jpg +/userdata/val2017/000000214200.jpg +/userdata/val2017/000000351362.jpg +/userdata/val2017/000000102707.jpg +/userdata/val2017/000000167902.jpg +/userdata/val2017/000000283318.jpg +/userdata/val2017/000000159977.jpg +/userdata/val2017/000000379533.jpg +/userdata/val2017/000000104612.jpg +/userdata/val2017/000000342186.jpg +/userdata/val2017/000000202445.jpg +/userdata/val2017/000000006771.jpg +/userdata/val2017/000000050380.jpg +/userdata/val2017/000000397351.jpg +/userdata/val2017/000000419882.jpg +/userdata/val2017/000000533958.jpg +/userdata/val2017/000000105249.jpg +/userdata/val2017/000000307074.jpg +/userdata/val2017/000000259830.jpg +/userdata/val2017/000000356261.jpg +/userdata/val2017/000000284279.jpg +/userdata/val2017/000000464872.jpg +/userdata/val2017/000000386210.jpg +/userdata/val2017/000000403584.jpg +/userdata/val2017/000000148662.jpg +/userdata/val2017/000000447088.jpg +/userdata/val2017/000000137294.jpg +/userdata/val2017/000000426372.jpg +/userdata/val2017/000000379476.jpg +/userdata/val2017/000000019924.jpg +/userdata/val2017/000000439773.jpg +/userdata/val2017/000000214539.jpg +/userdata/val2017/000000024021.jpg +/userdata/val2017/000000379453.jpg +/userdata/val2017/000000277051.jpg +/userdata/val2017/000000363666.jpg +/userdata/val2017/000000154718.jpg +/userdata/val2017/000000273715.jpg +/userdata/val2017/000000521231.jpg +/userdata/val2017/000000504580.jpg +/userdata/val2017/000000091495.jpg +/userdata/val2017/000000342128.jpg +/userdata/val2017/000000153568.jpg +/userdata/val2017/000000153229.jpg +/userdata/val2017/000000238039.jpg +/userdata/val2017/000000000776.jpg +/userdata/val2017/000000371042.jpg +/userdata/val2017/000000157767.jpg +/userdata/val2017/000000438876.jpg +/userdata/val2017/000000443498.jpg +/userdata/val2017/000000488075.jpg +/userdata/val2017/000000481582.jpg +/userdata/val2017/000000138819.jpg +/userdata/val2017/000000297562.jpg +/userdata/val2017/000000331317.jpg +/userdata/val2017/000000138954.jpg +/userdata/val2017/000000516871.jpg +/userdata/val2017/000000244411.jpg +/userdata/val2017/000000014226.jpg +/userdata/val2017/000000101068.jpg +/userdata/val2017/000000133000.jpg +/userdata/val2017/000000279927.jpg +/userdata/val2017/000000205514.jpg +/userdata/val2017/000000381587.jpg +/userdata/val2017/000000226883.jpg +/userdata/val2017/000000442161.jpg +/userdata/val2017/000000353096.jpg +/userdata/val2017/000000478721.jpg +/userdata/val2017/000000451308.jpg +/userdata/val2017/000000335427.jpg +/userdata/val2017/000000221291.jpg +/userdata/val2017/000000320490.jpg +/userdata/val2017/000000172595.jpg +/userdata/val2017/000000346707.jpg +/userdata/val2017/000000474293.jpg +/userdata/val2017/000000277197.jpg +/userdata/val2017/000000024027.jpg +/userdata/val2017/000000549055.jpg +/userdata/val2017/000000330554.jpg +/userdata/val2017/000000396518.jpg +/userdata/val2017/000000092177.jpg +/userdata/val2017/000000156076.jpg +/userdata/val2017/000000305309.jpg +/userdata/val2017/000000202339.jpg +/userdata/val2017/000000006213.jpg +/userdata/val2017/000000532690.jpg +/userdata/val2017/000000185250.jpg +/userdata/val2017/000000060855.jpg +/userdata/val2017/000000509656.jpg +/userdata/val2017/000000260105.jpg +/userdata/val2017/000000532493.jpg +/userdata/val2017/000000397327.jpg +/userdata/val2017/000000414795.jpg +/userdata/val2017/000000065485.jpg +/userdata/val2017/000000054605.jpg +/userdata/val2017/000000475678.jpg +/userdata/val2017/000000017029.jpg +/userdata/val2017/000000290163.jpg +/userdata/val2017/000000397354.jpg +/userdata/val2017/000000004395.jpg +/userdata/val2017/000000453722.jpg +/userdata/val2017/000000255965.jpg +/userdata/val2017/000000232646.jpg +/userdata/val2017/000000141328.jpg +/userdata/val2017/000000333237.jpg +/userdata/val2017/000000085772.jpg +/userdata/val2017/000000099114.jpg +/userdata/val2017/000000068078.jpg +/userdata/val2017/000000084752.jpg +/userdata/val2017/000000011615.jpg +/userdata/val2017/000000015079.jpg +/userdata/val2017/000000504589.jpg +/userdata/val2017/000000562448.jpg +/userdata/val2017/000000510095.jpg +/userdata/val2017/000000027620.jpg +/userdata/val2017/000000023034.jpg +/userdata/val2017/000000184384.jpg +/userdata/val2017/000000358195.jpg +/userdata/val2017/000000446207.jpg +/userdata/val2017/000000363784.jpg +/userdata/val2017/000000560011.jpg +/userdata/val2017/000000419201.jpg +/userdata/val2017/000000566436.jpg +/userdata/val2017/000000532575.jpg +/userdata/val2017/000000557916.jpg +/userdata/val2017/000000101884.jpg +/userdata/val2017/000000150417.jpg +/userdata/val2017/000000097988.jpg +/userdata/val2017/000000217957.jpg +/userdata/val2017/000000321118.jpg +/userdata/val2017/000000476514.jpg +/userdata/val2017/000000441247.jpg +/userdata/val2017/000000410650.jpg +/userdata/val2017/000000125062.jpg +/userdata/val2017/000000307598.jpg +/userdata/val2017/000000532855.jpg +/userdata/val2017/000000537827.jpg +/userdata/val2017/000000556193.jpg +/userdata/val2017/000000128051.jpg +/userdata/val2017/000000193494.jpg +/userdata/val2017/000000021167.jpg +/userdata/val2017/000000252559.jpg +/userdata/val2017/000000099054.jpg +/userdata/val2017/000000386277.jpg +/userdata/val2017/000000506454.jpg +/userdata/val2017/000000060823.jpg +/userdata/val2017/000000495054.jpg +/userdata/val2017/000000216419.jpg +/userdata/val2017/000000322429.jpg +/userdata/val2017/000000314914.jpg +/userdata/val2017/000000007818.jpg +/userdata/val2017/000000507015.jpg +/userdata/val2017/000000047769.jpg +/userdata/val2017/000000211069.jpg +/userdata/val2017/000000168883.jpg +/userdata/val2017/000000400367.jpg +/userdata/val2017/000000142472.jpg +/userdata/val2017/000000377723.jpg +/userdata/val2017/000000456496.jpg +/userdata/val2017/000000534664.jpg +/userdata/val2017/000000446522.jpg +/userdata/val2017/000000187362.jpg +/userdata/val2017/000000241326.jpg +/userdata/val2017/000000115245.jpg +/userdata/val2017/000000576955.jpg +/userdata/val2017/000000421757.jpg +/userdata/val2017/000000080413.jpg +/userdata/val2017/000000100723.jpg +/userdata/val2017/000000500464.jpg +/userdata/val2017/000000400573.jpg +/userdata/val2017/000000110042.jpg +/userdata/val2017/000000111207.jpg +/userdata/val2017/000000466339.jpg +/userdata/val2017/000000048396.jpg +/userdata/val2017/000000469067.jpg +/userdata/val2017/000000507223.jpg +/userdata/val2017/000000089045.jpg +/userdata/val2017/000000560312.jpg +/userdata/val2017/000000242724.jpg +/userdata/val2017/000000326248.jpg +/userdata/val2017/000000293474.jpg +/userdata/val2017/000000164885.jpg +/userdata/val2017/000000171382.jpg +/userdata/val2017/000000396338.jpg +/userdata/val2017/000000349678.jpg +/userdata/val2017/000000051976.jpg +/userdata/val2017/000000152120.jpg +/userdata/val2017/000000466835.jpg +/userdata/val2017/000000475223.jpg +/userdata/val2017/000000190841.jpg +/userdata/val2017/000000060899.jpg +/userdata/val2017/000000140556.jpg +/userdata/val2017/000000171298.jpg +/userdata/val2017/000000006954.jpg +/userdata/val2017/000000281693.jpg +/userdata/val2017/000000169996.jpg +/userdata/val2017/000000031620.jpg +/userdata/val2017/000000547886.jpg +/userdata/val2017/000000500565.jpg +/userdata/val2017/000000511599.jpg +/userdata/val2017/000000311883.jpg +/userdata/val2017/000000538458.jpg +/userdata/val2017/000000465806.jpg +/userdata/val2017/000000465585.jpg +/userdata/val2017/000000089880.jpg +/userdata/val2017/000000445602.jpg +/userdata/val2017/000000464824.jpg +/userdata/val2017/000000200421.jpg +/userdata/val2017/000000056344.jpg +/userdata/val2017/000000356125.jpg +/userdata/val2017/000000161032.jpg +/userdata/val2017/000000133567.jpg +/userdata/val2017/000000366199.jpg +/userdata/val2017/000000568290.jpg +/userdata/val2017/000000071451.jpg +/userdata/val2017/000000538067.jpg +/userdata/val2017/000000304984.jpg +/userdata/val2017/000000210520.jpg +/userdata/val2017/000000076547.jpg +/userdata/val2017/000000458109.jpg +/userdata/val2017/000000257896.jpg +/userdata/val2017/000000435081.jpg +/userdata/val2017/000000184338.jpg +/userdata/val2017/000000341973.jpg +/userdata/val2017/000000413395.jpg +/userdata/val2017/000000198805.jpg +/userdata/val2017/000000178982.jpg +/userdata/val2017/000000328959.jpg +/userdata/val2017/000000453634.jpg +/userdata/val2017/000000113051.jpg +/userdata/val2017/000000180878.jpg +/userdata/val2017/000000464522.jpg +/userdata/val2017/000000005060.jpg +/userdata/val2017/000000450488.jpg +/userdata/val2017/000000365095.jpg +/userdata/val2017/000000197022.jpg +/userdata/val2017/000000509014.jpg +/userdata/val2017/000000331352.jpg +/userdata/val2017/000000160728.jpg +/userdata/val2017/000000375430.jpg +/userdata/val2017/000000286523.jpg +/userdata/val2017/000000013729.jpg +/userdata/val2017/000000547383.jpg +/userdata/val2017/000000419653.jpg +/userdata/val2017/000000026941.jpg +/userdata/val2017/000000488736.jpg +/userdata/val2017/000000006040.jpg +/userdata/val2017/000000232088.jpg +/userdata/val2017/000000450758.jpg +/userdata/val2017/000000372203.jpg +/userdata/val2017/000000238866.jpg +/userdata/val2017/000000526197.jpg +/userdata/val2017/000000276284.jpg +/userdata/val2017/000000007281.jpg +/userdata/val2017/000000226417.jpg +/userdata/val2017/000000468332.jpg +/userdata/val2017/000000496597.jpg +/userdata/val2017/000000520871.jpg +/userdata/val2017/000000226154.jpg +/userdata/val2017/000000150930.jpg +/userdata/val2017/000000524456.jpg +/userdata/val2017/000000477623.jpg +/userdata/val2017/000000075393.jpg +/userdata/val2017/000000298396.jpg +/userdata/val2017/000000130579.jpg +/userdata/val2017/000000009891.jpg +/userdata/val2017/000000350148.jpg +/userdata/val2017/000000255747.jpg +/userdata/val2017/000000089296.jpg +/userdata/val2017/000000352760.jpg +/userdata/val2017/000000014439.jpg +/userdata/val2017/000000142324.jpg +/userdata/val2017/000000193884.jpg +/userdata/val2017/000000379842.jpg +/userdata/val2017/000000236845.jpg +/userdata/val2017/000000123633.jpg +/userdata/val2017/000000581206.jpg +/userdata/val2017/000000135604.jpg +/userdata/val2017/000000173183.jpg +/userdata/val2017/000000196759.jpg +/userdata/val2017/000000554595.jpg +/userdata/val2017/000000118405.jpg +/userdata/val2017/000000402720.jpg +/userdata/val2017/000000143961.jpg +/userdata/val2017/000000286908.jpg +/userdata/val2017/000000245173.jpg +/userdata/val2017/000000191013.jpg +/userdata/val2017/000000320706.jpg +/userdata/val2017/000000546826.jpg +/userdata/val2017/000000191471.jpg +/userdata/val2017/000000274411.jpg +/userdata/val2017/000000119995.jpg +/userdata/val2017/000000505451.jpg +/userdata/val2017/000000338986.jpg +/userdata/val2017/000000183437.jpg +/userdata/val2017/000000410221.jpg +/userdata/val2017/000000229358.jpg +/userdata/val2017/000000288685.jpg +/userdata/val2017/000000529966.jpg +/userdata/val2017/000000437110.jpg +/userdata/val2017/000000093965.jpg +/userdata/val2017/000000420916.jpg +/userdata/val2017/000000463283.jpg +/userdata/val2017/000000492905.jpg +/userdata/val2017/000000016010.jpg +/userdata/val2017/000000240767.jpg +/userdata/val2017/000000529528.jpg +/userdata/val2017/000000320664.jpg +/userdata/val2017/000000099024.jpg +/userdata/val2017/000000323355.jpg +/userdata/val2017/000000112634.jpg +/userdata/val2017/000000428218.jpg +/userdata/val2017/000000409358.jpg +/userdata/val2017/000000287714.jpg +/userdata/val2017/000000090003.jpg +/userdata/val2017/000000246883.jpg +/userdata/val2017/000000481480.jpg +/userdata/val2017/000000213035.jpg +/userdata/val2017/000000343803.jpg +/userdata/val2017/000000553664.jpg +/userdata/val2017/000000530624.jpg +/userdata/val2017/000000060886.jpg +/userdata/val2017/000000034071.jpg +/userdata/val2017/000000455555.jpg +/userdata/val2017/000000364636.jpg +/userdata/val2017/000000007108.jpg +/userdata/val2017/000000512248.jpg +/userdata/val2017/000000575970.jpg +/userdata/val2017/000000260925.jpg +/userdata/val2017/000000096001.jpg +/userdata/val2017/000000387098.jpg +/userdata/val2017/000000159684.jpg +/userdata/val2017/000000340894.jpg +/userdata/val2017/000000453841.jpg +/userdata/val2017/000000252332.jpg +/userdata/val2017/000000341921.jpg +/userdata/val2017/000000477805.jpg +/userdata/val2017/000000404128.jpg +/userdata/val2017/000000246436.jpg +/userdata/val2017/000000507042.jpg +/userdata/val2017/000000501523.jpg +/userdata/val2017/000000446574.jpg +/userdata/val2017/000000497344.jpg +/userdata/val2017/000000450100.jpg +/userdata/val2017/000000100274.jpg +/userdata/val2017/000000580418.jpg +/userdata/val2017/000000125405.jpg +/userdata/val2017/000000279145.jpg +/userdata/val2017/000000099428.jpg +/userdata/val2017/000000330818.jpg +/userdata/val2017/000000572517.jpg +/userdata/val2017/000000015956.jpg +/userdata/val2017/000000456865.jpg +/userdata/val2017/000000547519.jpg +/userdata/val2017/000000032861.jpg +/userdata/val2017/000000571893.jpg +/userdata/val2017/000000345469.jpg +/userdata/val2017/000000035062.jpg +/userdata/val2017/000000136772.jpg +/userdata/val2017/000000361238.jpg +/userdata/val2017/000000469246.jpg +/userdata/val2017/000000369757.jpg +/userdata/val2017/000000064523.jpg +/userdata/val2017/000000123480.jpg +/userdata/val2017/000000438907.jpg +/userdata/val2017/000000163117.jpg +/userdata/val2017/000000377670.jpg +/userdata/val2017/000000020553.jpg +/userdata/val2017/000000579321.jpg +/userdata/val2017/000000182923.jpg +/userdata/val2017/000000403385.jpg +/userdata/val2017/000000169169.jpg +/userdata/val2017/000000229601.jpg +/userdata/val2017/000000353970.jpg +/userdata/val2017/000000094157.jpg +/userdata/val2017/000000244592.jpg +/userdata/val2017/000000031248.jpg +/userdata/val2017/000000347930.jpg +/userdata/val2017/000000136715.jpg +/userdata/val2017/000000322895.jpg +/userdata/val2017/000000117744.jpg +/userdata/val2017/000000220732.jpg +/userdata/val2017/000000136355.jpg +/userdata/val2017/000000146489.jpg +/userdata/val2017/000000389812.jpg +/userdata/val2017/000000125806.jpg +/userdata/val2017/000000563470.jpg +/userdata/val2017/000000039951.jpg +/userdata/val2017/000000186873.jpg +/userdata/val2017/000000423519.jpg +/userdata/val2017/000000039484.jpg +/userdata/val2017/000000050896.jpg +/userdata/val2017/000000346703.jpg +/userdata/val2017/000000462643.jpg +/userdata/val2017/000000455716.jpg +/userdata/val2017/000000030785.jpg +/userdata/val2017/000000520009.jpg +/userdata/val2017/000000553990.jpg +/userdata/val2017/000000503855.jpg +/userdata/val2017/000000555412.jpg +/userdata/val2017/000000272212.jpg +/userdata/val2017/000000429761.jpg +/userdata/val2017/000000545100.jpg +/userdata/val2017/000000050679.jpg +/userdata/val2017/000000116479.jpg +/userdata/val2017/000000079969.jpg +/userdata/val2017/000000280779.jpg +/userdata/val2017/000000234526.jpg +/userdata/val2017/000000521717.jpg +/userdata/val2017/000000386134.jpg +/userdata/val2017/000000154705.jpg +/userdata/val2017/000000299720.jpg +/userdata/val2017/000000143068.jpg +/userdata/val2017/000000025603.jpg +/userdata/val2017/000000128112.jpg +/userdata/val2017/000000166642.jpg +/userdata/val2017/000000249550.jpg +/userdata/val2017/000000293245.jpg +/userdata/val2017/000000043816.jpg +/userdata/val2017/000000532530.jpg +/userdata/val2017/000000431848.jpg +/userdata/val2017/000000557501.jpg +/userdata/val2017/000000132931.jpg +/userdata/val2017/000000323571.jpg +/userdata/val2017/000000432553.jpg +/userdata/val2017/000000468632.jpg +/userdata/val2017/000000301376.jpg +/userdata/val2017/000000239843.jpg +/userdata/val2017/000000415741.jpg +/userdata/val2017/000000289059.jpg +/userdata/val2017/000000561256.jpg +/userdata/val2017/000000229311.jpg +/userdata/val2017/000000200152.jpg +/userdata/val2017/000000165518.jpg +/userdata/val2017/000000429690.jpg +/userdata/val2017/000000229948.jpg +/userdata/val2017/000000053529.jpg +/userdata/val2017/000000252507.jpg +/userdata/val2017/000000476215.jpg +/userdata/val2017/000000176901.jpg +/userdata/val2017/000000003553.jpg +/userdata/val2017/000000115118.jpg +/userdata/val2017/000000112110.jpg +/userdata/val2017/000000241319.jpg +/userdata/val2017/000000430973.jpg +/userdata/val2017/000000540932.jpg +/userdata/val2017/000000140840.jpg +/userdata/val2017/000000303893.jpg +/userdata/val2017/000000003156.jpg +/userdata/val2017/000000535858.jpg +/userdata/val2017/000000319607.jpg +/userdata/val2017/000000057238.jpg +/userdata/val2017/000000345356.jpg +/userdata/val2017/000000192716.jpg +/userdata/val2017/000000183391.jpg +/userdata/val2017/000000043737.jpg +/userdata/val2017/000000262895.jpg +/userdata/val2017/000000157365.jpg +/userdata/val2017/000000348481.jpg +/userdata/val2017/000000079408.jpg +/userdata/val2017/000000411953.jpg +/userdata/val2017/000000322724.jpg +/userdata/val2017/000000567197.jpg +/userdata/val2017/000000411754.jpg +/userdata/val2017/000000224675.jpg +/userdata/val2017/000000335658.jpg +/userdata/val2017/000000397639.jpg +/userdata/val2017/000000479953.jpg +/userdata/val2017/000000235784.jpg +/userdata/val2017/000000244181.jpg +/userdata/val2017/000000451144.jpg +/userdata/val2017/000000184324.jpg +/userdata/val2017/000000544306.jpg +/userdata/val2017/000000122166.jpg +/userdata/val2017/000000417043.jpg +/userdata/val2017/000000165500.jpg +/userdata/val2017/000000308391.jpg +/userdata/val2017/000000533855.jpg +/userdata/val2017/000000190307.jpg +/userdata/val2017/000000493905.jpg +/userdata/val2017/000000207728.jpg +/userdata/val2017/000000034760.jpg +/userdata/val2017/000000554328.jpg +/userdata/val2017/000000302030.jpg +/userdata/val2017/000000190753.jpg +/userdata/val2017/000000329455.jpg +/userdata/val2017/000000092091.jpg +/userdata/val2017/000000570756.jpg +/userdata/val2017/000000175443.jpg +/userdata/val2017/000000581062.jpg +/userdata/val2017/000000172648.jpg +/userdata/val2017/000000113720.jpg +/userdata/val2017/000000125257.jpg +/userdata/val2017/000000188439.jpg +/userdata/val2017/000000337055.jpg +/userdata/val2017/000000173091.jpg +/userdata/val2017/000000142585.jpg +/userdata/val2017/000000067406.jpg +/userdata/val2017/000000269942.jpg +/userdata/val2017/000000217060.jpg +/userdata/val2017/000000179141.jpg +/userdata/val2017/000000074092.jpg +/userdata/val2017/000000122217.jpg +/userdata/val2017/000000429598.jpg +/userdata/val2017/000000157418.jpg +/userdata/val2017/000000254814.jpg +/userdata/val2017/000000000139.jpg +/userdata/val2017/000000067180.jpg +/userdata/val2017/000000193674.jpg +/userdata/val2017/000000074256.jpg +/userdata/val2017/000000416885.jpg +/userdata/val2017/000000564336.jpg +/userdata/val2017/000000068628.jpg +/userdata/val2017/000000216277.jpg +/userdata/val2017/000000365655.jpg +/userdata/val2017/000000270122.jpg +/userdata/val2017/000000088462.jpg +/userdata/val2017/000000398438.jpg +/userdata/val2017/000000455448.jpg +/userdata/val2017/000000036936.jpg +/userdata/val2017/000000212800.jpg +/userdata/val2017/000000178744.jpg +/userdata/val2017/000000078170.jpg +/userdata/val2017/000000015272.jpg +/userdata/val2017/000000101762.jpg +/userdata/val2017/000000013597.jpg +/userdata/val2017/000000109798.jpg +/userdata/val2017/000000461275.jpg +/userdata/val2017/000000231508.jpg +/userdata/val2017/000000459954.jpg +/userdata/val2017/000000276055.jpg +/userdata/val2017/000000465822.jpg +/userdata/val2017/000000005992.jpg +/userdata/val2017/000000156643.jpg +/userdata/val2017/000000069138.jpg +/userdata/val2017/000000116825.jpg +/userdata/val2017/000000255912.jpg +/userdata/val2017/000000187990.jpg +/userdata/val2017/000000355240.jpg +/userdata/val2017/000000370677.jpg +/userdata/val2017/000000252776.jpg +/userdata/val2017/000000064495.jpg +/userdata/val2017/000000224337.jpg +/userdata/val2017/000000507473.jpg +/userdata/val2017/000000256192.jpg +/userdata/val2017/000000105014.jpg +/userdata/val2017/000000173008.jpg +/userdata/val2017/000000015517.jpg +/userdata/val2017/000000177015.jpg +/userdata/val2017/000000017178.jpg +/userdata/val2017/000000492282.jpg +/userdata/val2017/000000353051.jpg +/userdata/val2017/000000459662.jpg +/userdata/val2017/000000166768.jpg +/userdata/val2017/000000485480.jpg +/userdata/val2017/000000410510.jpg +/userdata/val2017/000000308799.jpg +/userdata/val2017/000000321790.jpg +/userdata/val2017/000000379800.jpg +/userdata/val2017/000000062808.jpg +/userdata/val2017/000000195918.jpg +/userdata/val2017/000000562581.jpg +/userdata/val2017/000000459272.jpg +/userdata/val2017/000000128598.jpg +/userdata/val2017/000000055299.jpg +/userdata/val2017/000000106757.jpg +/userdata/val2017/000000484893.jpg +/userdata/val2017/000000183709.jpg +/userdata/val2017/000000500211.jpg +/userdata/val2017/000000120584.jpg +/userdata/val2017/000000276018.jpg +/userdata/val2017/000000320554.jpg +/userdata/val2017/000000073533.jpg +/userdata/val2017/000000177861.jpg +/userdata/val2017/000000314034.jpg +/userdata/val2017/000000512403.jpg +/userdata/val2017/000000464358.jpg +/userdata/val2017/000000243148.jpg +/userdata/val2017/000000188465.jpg +/userdata/val2017/000000234757.jpg +/userdata/val2017/000000209613.jpg +/userdata/val2017/000000189752.jpg +/userdata/val2017/000000361551.jpg +/userdata/val2017/000000365521.jpg +/userdata/val2017/000000147518.jpg +/userdata/val2017/000000142971.jpg +/userdata/val2017/000000180487.jpg +/userdata/val2017/000000023272.jpg +/userdata/val2017/000000549167.jpg +/userdata/val2017/000000329614.jpg +/userdata/val2017/000000573008.jpg +/userdata/val2017/000000344614.jpg +/userdata/val2017/000000475572.jpg +/userdata/val2017/000000371472.jpg +/userdata/val2017/000000477227.jpg +/userdata/val2017/000000476770.jpg +/userdata/val2017/000000136600.jpg +/userdata/val2017/000000255917.jpg +/userdata/val2017/000000301563.jpg +/userdata/val2017/000000195842.jpg +/userdata/val2017/000000257478.jpg +/userdata/val2017/000000430875.jpg +/userdata/val2017/000000401991.jpg +/userdata/val2017/000000182155.jpg +/userdata/val2017/000000417465.jpg +/userdata/val2017/000000442480.jpg +/userdata/val2017/000000542856.jpg +/userdata/val2017/000000458702.jpg +/userdata/val2017/000000526751.jpg +/userdata/val2017/000000245102.jpg +/userdata/val2017/000000322211.jpg +/userdata/val2017/000000376206.jpg +/userdata/val2017/000000357501.jpg +/userdata/val2017/000000066523.jpg +/userdata/val2017/000000326082.jpg +/userdata/val2017/000000099182.jpg +/userdata/val2017/000000205834.jpg +/userdata/val2017/000000232692.jpg +/userdata/val2017/000000246308.jpg +/userdata/val2017/000000121242.jpg +/userdata/val2017/000000466567.jpg +/userdata/val2017/000000454978.jpg +/userdata/val2017/000000380706.jpg +/userdata/val2017/000000515579.jpg +/userdata/val2017/000000063154.jpg +/userdata/val2017/000000386912.jpg +/userdata/val2017/000000126137.jpg +/userdata/val2017/000000485844.jpg +/userdata/val2017/000000483999.jpg +/userdata/val2017/000000184611.jpg +/userdata/val2017/000000161008.jpg +/userdata/val2017/000000102356.jpg +/userdata/val2017/000000535306.jpg +/userdata/val2017/000000104669.jpg +/userdata/val2017/000000482970.jpg +/userdata/val2017/000000193181.jpg +/userdata/val2017/000000313783.jpg +/userdata/val2017/000000269121.jpg +/userdata/val2017/000000534673.jpg +/userdata/val2017/000000535608.jpg +/userdata/val2017/000000050326.jpg +/userdata/val2017/000000036678.jpg +/userdata/val2017/000000226058.jpg +/userdata/val2017/000000189820.jpg +/userdata/val2017/000000201676.jpg +/userdata/val2017/000000170893.jpg +/userdata/val2017/000000111951.jpg +/userdata/val2017/000000012667.jpg +/userdata/val2017/000000530820.jpg +/userdata/val2017/000000336309.jpg +/userdata/val2017/000000088345.jpg +/userdata/val2017/000000323799.jpg +/userdata/val2017/000000133778.jpg +/userdata/val2017/000000270705.jpg +/userdata/val2017/000000362434.jpg +/userdata/val2017/000000294783.jpg +/userdata/val2017/000000186929.jpg +/userdata/val2017/000000455219.jpg +/userdata/val2017/000000114884.jpg +/userdata/val2017/000000127517.jpg +/userdata/val2017/000000189806.jpg +/userdata/val2017/000000389566.jpg +/userdata/val2017/000000037740.jpg +/userdata/val2017/000000556158.jpg +/userdata/val2017/000000025057.jpg +/userdata/val2017/000000500423.jpg +/userdata/val2017/000000376112.jpg +/userdata/val2017/000000496571.jpg +/userdata/val2017/000000563758.jpg +/userdata/val2017/000000569273.jpg +/userdata/val2017/000000500270.jpg +/userdata/val2017/000000480122.jpg +/userdata/val2017/000000326541.jpg +/userdata/val2017/000000468925.jpg +/userdata/val2017/000000085682.jpg +/userdata/val2017/000000283717.jpg +/userdata/val2017/000000047121.jpg +/userdata/val2017/000000472046.jpg +/userdata/val2017/000000018575.jpg +/userdata/val2017/000000218997.jpg +/userdata/val2017/000000536073.jpg +/userdata/val2017/000000229553.jpg +/userdata/val2017/000000095899.jpg +/userdata/val2017/000000017436.jpg +/userdata/val2017/000000260470.jpg +/userdata/val2017/000000121744.jpg +/userdata/val2017/000000292415.jpg +/userdata/val2017/000000316404.jpg +/userdata/val2017/000000497867.jpg +/userdata/val2017/000000333402.jpg +/userdata/val2017/000000492758.jpg +/userdata/val2017/000000470952.jpg +/userdata/val2017/000000133645.jpg +/userdata/val2017/000000232489.jpg +/userdata/val2017/000000137246.jpg +/userdata/val2017/000000179765.jpg +/userdata/val2017/000000082085.jpg +/userdata/val2017/000000342971.jpg +/userdata/val2017/000000297578.jpg +/userdata/val2017/000000580757.jpg +/userdata/val2017/000000306893.jpg +/userdata/val2017/000000017714.jpg +/userdata/val2017/000000260106.jpg +/userdata/val2017/000000577735.jpg +/userdata/val2017/000000039551.jpg +/userdata/val2017/000000528862.jpg +/userdata/val2017/000000221213.jpg +/userdata/val2017/000000048153.jpg +/userdata/val2017/000000153669.jpg +/userdata/val2017/000000452122.jpg +/userdata/val2017/000000071756.jpg +/userdata/val2017/000000546717.jpg +/userdata/val2017/000000071877.jpg +/userdata/val2017/000000552902.jpg +/userdata/val2017/000000458045.jpg +/userdata/val2017/000000046497.jpg +/userdata/val2017/000000249643.jpg +/userdata/val2017/000000178028.jpg +/userdata/val2017/000000297830.jpg +/userdata/val2017/000000258793.jpg +/userdata/val2017/000000057597.jpg +/userdata/val2017/000000236166.jpg +/userdata/val2017/000000061471.jpg +/userdata/val2017/000000007386.jpg +/userdata/val2017/000000034873.jpg +/userdata/val2017/000000098497.jpg +/userdata/val2017/000000331604.jpg +/userdata/val2017/000000137576.jpg +/userdata/val2017/000000254016.jpg +/userdata/val2017/000000287667.jpg +/userdata/val2017/000000185472.jpg +/userdata/val2017/000000193245.jpg +/userdata/val2017/000000473869.jpg +/userdata/val2017/000000125472.jpg +/userdata/val2017/000000284762.jpg +/userdata/val2017/000000309655.jpg +/userdata/val2017/000000190648.jpg +/userdata/val2017/000000442009.jpg +/userdata/val2017/000000241668.jpg +/userdata/val2017/000000033109.jpg +/userdata/val2017/000000451084.jpg +/userdata/val2017/000000215644.jpg +/userdata/val2017/000000272049.jpg +/userdata/val2017/000000491725.jpg +/userdata/val2017/000000065455.jpg +/userdata/val2017/000000226802.jpg +/userdata/val2017/000000472030.jpg +/userdata/val2017/000000172396.jpg +/userdata/val2017/000000477288.jpg +/userdata/val2017/000000176701.jpg +/userdata/val2017/000000213255.jpg +/userdata/val2017/000000140583.jpg +/userdata/val2017/000000445792.jpg +/userdata/val2017/000000073946.jpg +/userdata/val2017/000000297147.jpg +/userdata/val2017/000000002153.jpg +/userdata/val2017/000000199236.jpg +/userdata/val2017/000000523229.jpg +/userdata/val2017/000000154004.jpg +/userdata/val2017/000000442661.jpg +/userdata/val2017/000000440475.jpg +/userdata/val2017/000000357903.jpg +/userdata/val2017/000000200162.jpg +/userdata/val2017/000000426297.jpg +/userdata/val2017/000000561335.jpg +/userdata/val2017/000000563648.jpg +/userdata/val2017/000000106563.jpg +/userdata/val2017/000000458790.jpg +/userdata/val2017/000000528399.jpg +/userdata/val2017/000000546556.jpg +/userdata/val2017/000000127092.jpg +/userdata/val2017/000000392722.jpg +/userdata/val2017/000000084477.jpg +/userdata/val2017/000000291551.jpg +/userdata/val2017/000000053626.jpg +/userdata/val2017/000000354307.jpg +/userdata/val2017/000000210299.jpg +/userdata/val2017/000000314541.jpg +/userdata/val2017/000000030675.jpg +/userdata/val2017/000000389381.jpg +/userdata/val2017/000000015597.jpg +/userdata/val2017/000000491008.jpg +/userdata/val2017/000000511453.jpg +/userdata/val2017/000000261061.jpg +/userdata/val2017/000000150638.jpg +/userdata/val2017/000000185409.jpg +/userdata/val2017/000000026465.jpg +/userdata/val2017/000000007511.jpg +/userdata/val2017/000000076211.jpg +/userdata/val2017/000000155571.jpg +/userdata/val2017/000000212226.jpg +/userdata/val2017/000000445658.jpg +/userdata/val2017/000000549930.jpg +/userdata/val2017/000000083531.jpg +/userdata/val2017/000000170278.jpg +/userdata/val2017/000000107554.jpg +/userdata/val2017/000000225946.jpg +/userdata/val2017/000000572303.jpg +/userdata/val2017/000000133631.jpg +/userdata/val2017/000000437351.jpg +/userdata/val2017/000000162035.jpg +/userdata/val2017/000000112378.jpg +/userdata/val2017/000000178618.jpg +/userdata/val2017/000000455624.jpg +/userdata/val2017/000000182021.jpg +/userdata/val2017/000000554735.jpg +/userdata/val2017/000000231822.jpg +/userdata/val2017/000000569976.jpg +/userdata/val2017/000000413552.jpg +/userdata/val2017/000000035326.jpg +/userdata/val2017/000000060363.jpg +/userdata/val2017/000000544519.jpg +/userdata/val2017/000000224807.jpg +/userdata/val2017/000000199681.jpg +/userdata/val2017/000000378605.jpg +/userdata/val2017/000000346905.jpg +/userdata/val2017/000000321887.jpg +/userdata/val2017/000000126110.jpg +/userdata/val2017/000000308394.jpg +/userdata/val2017/000000234366.jpg +/userdata/val2017/000000563702.jpg +/userdata/val2017/000000135561.jpg +/userdata/val2017/000000035963.jpg +/userdata/val2017/000000236721.jpg +/userdata/val2017/000000300659.jpg +/userdata/val2017/000000439994.jpg +/userdata/val2017/000000381360.jpg +/userdata/val2017/000000073118.jpg +/userdata/val2017/000000132116.jpg +/userdata/val2017/000000053994.jpg +/userdata/val2017/000000032038.jpg +/userdata/val2017/000000203546.jpg +/userdata/val2017/000000400082.jpg +/userdata/val2017/000000359833.jpg +/userdata/val2017/000000427055.jpg +/userdata/val2017/000000429109.jpg +/userdata/val2017/000000022623.jpg +/userdata/val2017/000000562059.jpg +/userdata/val2017/000000300913.jpg +/userdata/val2017/000000320232.jpg +/userdata/val2017/000000186632.jpg +/userdata/val2017/000000448263.jpg +/userdata/val2017/000000489091.jpg +/userdata/val2017/000000360960.jpg +/userdata/val2017/000000244833.jpg +/userdata/val2017/000000383621.jpg +/userdata/val2017/000000294831.jpg +/userdata/val2017/000000026690.jpg +/userdata/val2017/000000323828.jpg +/userdata/val2017/000000338219.jpg +/userdata/val2017/000000231339.jpg +/userdata/val2017/000000166426.jpg +/userdata/val2017/000000443303.jpg +/userdata/val2017/000000488664.jpg +/userdata/val2017/000000051008.jpg +/userdata/val2017/000000149222.jpg +/userdata/val2017/000000480021.jpg +/userdata/val2017/000000322829.jpg +/userdata/val2017/000000085376.jpg +/userdata/val2017/000000293794.jpg +/userdata/val2017/000000550084.jpg +/userdata/val2017/000000011122.jpg +/userdata/val2017/000000076625.jpg +/userdata/val2017/000000225532.jpg +/userdata/val2017/000000193429.jpg +/userdata/val2017/000000565877.jpg +/userdata/val2017/000000263679.jpg +/userdata/val2017/000000082821.jpg +/userdata/val2017/000000356248.jpg +/userdata/val2017/000000016451.jpg +/userdata/val2017/000000343976.jpg +/userdata/val2017/000000433915.jpg +/userdata/val2017/000000321557.jpg +/userdata/val2017/000000436617.jpg +/userdata/val2017/000000225757.jpg +/userdata/val2017/000000079651.jpg +/userdata/val2017/000000451714.jpg +/userdata/val2017/000000041872.jpg +/userdata/val2017/000000386879.jpg +/userdata/val2017/000000423798.jpg +/userdata/val2017/000000493334.jpg +/userdata/val2017/000000284445.jpg +/userdata/val2017/000000198489.jpg +/userdata/val2017/000000383606.jpg +/userdata/val2017/000000209222.jpg +/userdata/val2017/000000463918.jpg +/userdata/val2017/000000570834.jpg +/userdata/val2017/000000104198.jpg +/userdata/val2017/000000537241.jpg +/userdata/val2017/000000482477.jpg +/userdata/val2017/000000003661.jpg +/userdata/val2017/000000325114.jpg +/userdata/val2017/000000418281.jpg +/userdata/val2017/000000152740.jpg +/userdata/val2017/000000480944.jpg +/userdata/val2017/000000312237.jpg +/userdata/val2017/000000389316.jpg +/userdata/val2017/000000490413.jpg +/userdata/val2017/000000248752.jpg +/userdata/val2017/000000014038.jpg +/userdata/val2017/000000270908.jpg +/userdata/val2017/000000201426.jpg +/userdata/val2017/000000259097.jpg +/userdata/val2017/000000219271.jpg +/userdata/val2017/000000180798.jpg +/userdata/val2017/000000356387.jpg +/userdata/val2017/000000022479.jpg +/userdata/val2017/000000429011.jpg +/userdata/val2017/000000407002.jpg +/userdata/val2017/000000467776.jpg +/userdata/val2017/000000157124.jpg +/userdata/val2017/000000203317.jpg +/userdata/val2017/000000366178.jpg +/userdata/val2017/000000150224.jpg +/userdata/val2017/000000145781.jpg +/userdata/val2017/000000514797.jpg +/userdata/val2017/000000050828.jpg +/userdata/val2017/000000111036.jpg +/userdata/val2017/000000132408.jpg +/userdata/val2017/000000103585.jpg +/userdata/val2017/000000365098.jpg +/userdata/val2017/000000349480.jpg +/userdata/val2017/000000230819.jpg +/userdata/val2017/000000244750.jpg +/userdata/val2017/000000559160.jpg +/userdata/val2017/000000343524.jpg +/userdata/val2017/000000092839.jpg +/userdata/val2017/000000197658.jpg +/userdata/val2017/000000417911.jpg +/userdata/val2017/000000009448.jpg +/userdata/val2017/000000002299.jpg +/userdata/val2017/000000359781.jpg +/userdata/val2017/000000542127.jpg +/userdata/val2017/000000570169.jpg +/userdata/val2017/000000482436.jpg +/userdata/val2017/000000204186.jpg +/userdata/val2017/000000216497.jpg +/userdata/val2017/000000482275.jpg +/userdata/val2017/000000027972.jpg +/userdata/val2017/000000261097.jpg +/userdata/val2017/000000161978.jpg +/userdata/val2017/000000417285.jpg +/userdata/val2017/000000409475.jpg +/userdata/val2017/000000152214.jpg +/userdata/val2017/000000203488.jpg +/userdata/val2017/000000477955.jpg +/userdata/val2017/000000019109.jpg +/userdata/val2017/000000228771.jpg +/userdata/val2017/000000361730.jpg +/userdata/val2017/000000334977.jpg +/userdata/val2017/000000280930.jpg +/userdata/val2017/000000505789.jpg +/userdata/val2017/000000123131.jpg +/userdata/val2017/000000527695.jpg +/userdata/val2017/000000422836.jpg +/userdata/val2017/000000173044.jpg +/userdata/val2017/000000561889.jpg +/userdata/val2017/000000559513.jpg +/userdata/val2017/000000168974.jpg +/userdata/val2017/000000055072.jpg +/userdata/val2017/000000198510.jpg +/userdata/val2017/000000109118.jpg +/userdata/val2017/000000052412.jpg +/userdata/val2017/000000452784.jpg +/userdata/val2017/000000562443.jpg +/userdata/val2017/000000034452.jpg +/userdata/val2017/000000242678.jpg +/userdata/val2017/000000222458.jpg +/userdata/val2017/000000458223.jpg +/userdata/val2017/000000508639.jpg +/userdata/val2017/000000329447.jpg +/userdata/val2017/000000430056.jpg +/userdata/val2017/000000414638.jpg +/userdata/val2017/000000426795.jpg +/userdata/val2017/000000499109.jpg +/userdata/val2017/000000205776.jpg +/userdata/val2017/000000000885.jpg +/userdata/val2017/000000382030.jpg +/userdata/val2017/000000082696.jpg +/userdata/val2017/000000578236.jpg +/userdata/val2017/000000508586.jpg +/userdata/val2017/000000534601.jpg +/userdata/val2017/000000566923.jpg +/userdata/val2017/000000269113.jpg +/userdata/val2017/000000480985.jpg +/userdata/val2017/000000267300.jpg +/userdata/val2017/000000296649.jpg +/userdata/val2017/000000439593.jpg +/userdata/val2017/000000495732.jpg +/userdata/val2017/000000214192.jpg +/userdata/val2017/000000410612.jpg +/userdata/val2017/000000576566.jpg +/userdata/val2017/000000025560.jpg +/userdata/val2017/000000297022.jpg +/userdata/val2017/000000547336.jpg +/userdata/val2017/000000057244.jpg +/userdata/val2017/000000385719.jpg +/userdata/val2017/000000551304.jpg +/userdata/val2017/000000062554.jpg +/userdata/val2017/000000417085.jpg +/userdata/val2017/000000229659.jpg +/userdata/val2017/000000060932.jpg +/userdata/val2017/000000431896.jpg +/userdata/val2017/000000457848.jpg +/userdata/val2017/000000513580.jpg +/userdata/val2017/000000266206.jpg +/userdata/val2017/000000512836.jpg +/userdata/val2017/000000176799.jpg +/userdata/val2017/000000351096.jpg +/userdata/val2017/000000133244.jpg +/userdata/val2017/000000104455.jpg +/userdata/val2017/000000130613.jpg +/userdata/val2017/000000047112.jpg +/userdata/val2017/000000489842.jpg +/userdata/val2017/000000049091.jpg +/userdata/val2017/000000158945.jpg +/userdata/val2017/000000503823.jpg +/userdata/val2017/000000323895.jpg +/userdata/val2017/000000139871.jpg +/userdata/val2017/000000223090.jpg +/userdata/val2017/000000462576.jpg +/userdata/val2017/000000542625.jpg +/userdata/val2017/000000301135.jpg +/userdata/val2017/000000095707.jpg +/userdata/val2017/000000423944.jpg +/userdata/val2017/000000354072.jpg +/userdata/val2017/000000095862.jpg +/userdata/val2017/000000222735.jpg +/userdata/val2017/000000483531.jpg +/userdata/val2017/000000334399.jpg +/userdata/val2017/000000450559.jpg +/userdata/val2017/000000095786.jpg +/userdata/val2017/000000374545.jpg +/userdata/val2017/000000127955.jpg +/userdata/val2017/000000579307.jpg +/userdata/val2017/000000336587.jpg +/userdata/val2017/000000525083.jpg +/userdata/val2017/000000344268.jpg +/userdata/val2017/000000022589.jpg +/userdata/val2017/000000038118.jpg +/userdata/val2017/000000267940.jpg +/userdata/val2017/000000492878.jpg +/userdata/val2017/000000088040.jpg +/userdata/val2017/000000555972.jpg +/userdata/val2017/000000007574.jpg +/userdata/val2017/000000398742.jpg +/userdata/val2017/000000292908.jpg +/userdata/val2017/000000327617.jpg +/userdata/val2017/000000187144.jpg +/userdata/val2017/000000019786.jpg +/userdata/val2017/000000573391.jpg +/userdata/val2017/000000000632.jpg +/userdata/val2017/000000329080.jpg +/userdata/val2017/000000251824.jpg +/userdata/val2017/000000344621.jpg +/userdata/val2017/000000529762.jpg +/userdata/val2017/000000118594.jpg +/userdata/val2017/000000384350.jpg +/userdata/val2017/000000456303.jpg +/userdata/val2017/000000238410.jpg +/userdata/val2017/000000002685.jpg +/userdata/val2017/000000551804.jpg +/userdata/val2017/000000573943.jpg +/userdata/val2017/000000498463.jpg +/userdata/val2017/000000343315.jpg +/userdata/val2017/000000258388.jpg +/userdata/val2017/000000451043.jpg +/userdata/val2017/000000119641.jpg +/userdata/val2017/000000315187.jpg +/userdata/val2017/000000309495.jpg +/userdata/val2017/000000499768.jpg +/userdata/val2017/000000124442.jpg +/userdata/val2017/000000180101.jpg +/userdata/val2017/000000076261.jpg +/userdata/val2017/000000463199.jpg +/userdata/val2017/000000002587.jpg +/userdata/val2017/000000012062.jpg +/userdata/val2017/000000074733.jpg +/userdata/val2017/000000491470.jpg +/userdata/val2017/000000151820.jpg +/userdata/val2017/000000171757.jpg +/userdata/val2017/000000550691.jpg +/userdata/val2017/000000441491.jpg +/userdata/val2017/000000052017.jpg +/userdata/val2017/000000256518.jpg +/userdata/val2017/000000365886.jpg +/userdata/val2017/000000332318.jpg +/userdata/val2017/000000340175.jpg +/userdata/val2017/000000400815.jpg +/userdata/val2017/000000290619.jpg +/userdata/val2017/000000434548.jpg +/userdata/val2017/000000491071.jpg +/userdata/val2017/000000402118.jpg +/userdata/val2017/000000240940.jpg +/userdata/val2017/000000059386.jpg +/userdata/val2017/000000029393.jpg +/userdata/val2017/000000221281.jpg +/userdata/val2017/000000078843.jpg +/userdata/val2017/000000231125.jpg +/userdata/val2017/000000453166.jpg +/userdata/val2017/000000463618.jpg +/userdata/val2017/000000206025.jpg +/userdata/val2017/000000336209.jpg +/userdata/val2017/000000306136.jpg +/userdata/val2017/000000399296.jpg +/userdata/val2017/000000473974.jpg +/userdata/val2017/000000148719.jpg +/userdata/val2017/000000154947.jpg +/userdata/val2017/000000287291.jpg +/userdata/val2017/000000032817.jpg +/userdata/val2017/000000336658.jpg +/userdata/val2017/000000023230.jpg +/userdata/val2017/000000191761.jpg +/userdata/val2017/000000211825.jpg +/userdata/val2017/000000423229.jpg +/userdata/val2017/000000484415.jpg +/userdata/val2017/000000411774.jpg +/userdata/val2017/000000375763.jpg +/userdata/val2017/000000069356.jpg +/userdata/val2017/000000360661.jpg +/userdata/val2017/000000306733.jpg +/userdata/val2017/000000107339.jpg +/userdata/val2017/000000194716.jpg +/userdata/val2017/000000016598.jpg +/userdata/val2017/000000209972.jpg +/userdata/val2017/000000387383.jpg +/userdata/val2017/000000521052.jpg +/userdata/val2017/000000433980.jpg +/userdata/val2017/000000528314.jpg +/userdata/val2017/000000096427.jpg +/userdata/val2017/000000249180.jpg +/userdata/val2017/000000242946.jpg +/userdata/val2017/000000090208.jpg +/userdata/val2017/000000193743.jpg +/userdata/val2017/000000141671.jpg +/userdata/val2017/000000116439.jpg +/userdata/val2017/000000304812.jpg +/userdata/val2017/000000035770.jpg +/userdata/val2017/000000189828.jpg +/userdata/val2017/000000405249.jpg +/userdata/val2017/000000341469.jpg +/userdata/val2017/000000522156.jpg +/userdata/val2017/000000276024.jpg +/userdata/val2017/000000579900.jpg +/userdata/val2017/000000133418.jpg +/userdata/val2017/000000304396.jpg +/userdata/val2017/000000509008.jpg +/userdata/val2017/000000154644.jpg +/userdata/val2017/000000208363.jpg +/userdata/val2017/000000432468.jpg +/userdata/val2017/000000058539.jpg +/userdata/val2017/000000064499.jpg +/userdata/val2017/000000519491.jpg +/userdata/val2017/000000371552.jpg +/userdata/val2017/000000383339.jpg +/userdata/val2017/000000352684.jpg +/userdata/val2017/000000384949.jpg +/userdata/val2017/000000063740.jpg +/userdata/val2017/000000341094.jpg +/userdata/val2017/000000026564.jpg +/userdata/val2017/000000334521.jpg +/userdata/val2017/000000453584.jpg +/userdata/val2017/000000078404.jpg +/userdata/val2017/000000546011.jpg +/userdata/val2017/000000032887.jpg +/userdata/val2017/000000430871.jpg +/userdata/val2017/000000544565.jpg +/userdata/val2017/000000284623.jpg +/userdata/val2017/000000362716.jpg +/userdata/val2017/000000540502.jpg +/userdata/val2017/000000282037.jpg +/userdata/val2017/000000367680.jpg +/userdata/val2017/000000311392.jpg +/userdata/val2017/000000097924.jpg +/userdata/val2017/000000375278.jpg +/userdata/val2017/000000120777.jpg +/userdata/val2017/000000509735.jpg +/userdata/val2017/000000239041.jpg +/userdata/val2017/000000289594.jpg +/userdata/val2017/000000565597.jpg +/userdata/val2017/000000098633.jpg +/userdata/val2017/000000552842.jpg +/userdata/val2017/000000242934.jpg +/userdata/val2017/000000436883.jpg +/userdata/val2017/000000337498.jpg +/userdata/val2017/000000174018.jpg +/userdata/val2017/000000119828.jpg +/userdata/val2017/000000451155.jpg +/userdata/val2017/000000333697.jpg +/userdata/val2017/000000190853.jpg +/userdata/val2017/000000128675.jpg +/userdata/val2017/000000235064.jpg +/userdata/val2017/000000050638.jpg +/userdata/val2017/000000030504.jpg +/userdata/val2017/000000155341.jpg +/userdata/val2017/000000125245.jpg +/userdata/val2017/000000336356.jpg +/userdata/val2017/000000123321.jpg +/userdata/val2017/000000199977.jpg +/userdata/val2017/000000050811.jpg +/userdata/val2017/000000514508.jpg +/userdata/val2017/000000091779.jpg +/userdata/val2017/000000147740.jpg +/userdata/val2017/000000133819.jpg +/userdata/val2017/000000093353.jpg +/userdata/val2017/000000441553.jpg +/userdata/val2017/000000127394.jpg +/userdata/val2017/000000213224.jpg +/userdata/val2017/000000235836.jpg +/userdata/val2017/000000117492.jpg +/userdata/val2017/000000225184.jpg +/userdata/val2017/000000508602.jpg +/userdata/val2017/000000434230.jpg +/userdata/val2017/000000223188.jpg +/userdata/val2017/000000572462.jpg +/userdata/val2017/000000114907.jpg +/userdata/val2017/000000140439.jpg +/userdata/val2017/000000578093.jpg +/userdata/val2017/000000251119.jpg +/userdata/val2017/000000261796.jpg +/userdata/val2017/000000066135.jpg +/userdata/val2017/000000304817.jpg +/userdata/val2017/000000015335.jpg +/userdata/val2017/000000131386.jpg +/userdata/val2017/000000568690.jpg +/userdata/val2017/000000553776.jpg +/userdata/val2017/000000408112.jpg +/userdata/val2017/000000363072.jpg +/userdata/val2017/000000284725.jpg +/userdata/val2017/000000481567.jpg +/userdata/val2017/000000567886.jpg +/userdata/val2017/000000213171.jpg +/userdata/val2017/000000562843.jpg +/userdata/val2017/000000445846.jpg +/userdata/val2017/000000112798.jpg +/userdata/val2017/000000092939.jpg +/userdata/val2017/000000292997.jpg +/userdata/val2017/000000295797.jpg +/userdata/val2017/000000461751.jpg +/userdata/val2017/000000449603.jpg +/userdata/val2017/000000357742.jpg +/userdata/val2017/000000474164.jpg +/userdata/val2017/000000173383.jpg +/userdata/val2017/000000283785.jpg +/userdata/val2017/000000054123.jpg +/userdata/val2017/000000109055.jpg +/userdata/val2017/000000348045.jpg +/userdata/val2017/000000361621.jpg +/userdata/val2017/000000190007.jpg +/userdata/val2017/000000029640.jpg +/userdata/val2017/000000332570.jpg +/userdata/val2017/000000344100.jpg +/userdata/val2017/000000185890.jpg +/userdata/val2017/000000060835.jpg +/userdata/val2017/000000148739.jpg +/userdata/val2017/000000522007.jpg +/userdata/val2017/000000497628.jpg +/userdata/val2017/000000552371.jpg +/userdata/val2017/000000177934.jpg +/userdata/val2017/000000070774.jpg +/userdata/val2017/000000012639.jpg +/userdata/val2017/000000163682.jpg +/userdata/val2017/000000055528.jpg +/userdata/val2017/000000161799.jpg +/userdata/val2017/000000311180.jpg +/userdata/val2017/000000148957.jpg +/userdata/val2017/000000435880.jpg +/userdata/val2017/000000383386.jpg +/userdata/val2017/000000120853.jpg +/userdata/val2017/000000179265.jpg +/userdata/val2017/000000299553.jpg +/userdata/val2017/000000460929.jpg +/userdata/val2017/000000155443.jpg +/userdata/val2017/000000135670.jpg +/userdata/val2017/000000565853.jpg +/userdata/val2017/000000197528.jpg +/userdata/val2017/000000022969.jpg +/userdata/val2017/000000134886.jpg +/userdata/val2017/000000502168.jpg +/userdata/val2017/000000343561.jpg +/userdata/val2017/000000295138.jpg +/userdata/val2017/000000254516.jpg +/userdata/val2017/000000186422.jpg +/userdata/val2017/000000213445.jpg +/userdata/val2017/000000519611.jpg +/userdata/val2017/000000427655.jpg +/userdata/val2017/000000205324.jpg +/userdata/val2017/000000485895.jpg +/userdata/val2017/000000215245.jpg +/userdata/val2017/000000148783.jpg +/userdata/val2017/000000464689.jpg +/userdata/val2017/000000081394.jpg +/userdata/val2017/000000032334.jpg +/userdata/val2017/000000167540.jpg +/userdata/val2017/000000401250.jpg +/userdata/val2017/000000469174.jpg +/userdata/val2017/000000380711.jpg +/userdata/val2017/000000045472.jpg +/userdata/val2017/000000158548.jpg +/userdata/val2017/000000177935.jpg +/userdata/val2017/000000208423.jpg +/userdata/val2017/000000138856.jpg +/userdata/val2017/000000231237.jpg +/userdata/val2017/000000491213.jpg +/userdata/val2017/000000230993.jpg +/userdata/val2017/000000147745.jpg +/userdata/val2017/000000325483.jpg +/userdata/val2017/000000252294.jpg +/userdata/val2017/000000467511.jpg +/userdata/val2017/000000206218.jpg +/userdata/val2017/000000511398.jpg +/userdata/val2017/000000404601.jpg +/userdata/val2017/000000088848.jpg +/userdata/val2017/000000345027.jpg +/userdata/val2017/000000338905.jpg +/userdata/val2017/000000546964.jpg +/userdata/val2017/000000271457.jpg +/userdata/val2017/000000017207.jpg +/userdata/val2017/000000240754.jpg +/userdata/val2017/000000580410.jpg +/userdata/val2017/000000217948.jpg +/userdata/val2017/000000372260.jpg +/userdata/val2017/000000551215.jpg +/userdata/val2017/000000427649.jpg +/userdata/val2017/000000445834.jpg +/userdata/val2017/000000537672.jpg +/userdata/val2017/000000457559.jpg +/userdata/val2017/000000444879.jpg +/userdata/val2017/000000384670.jpg +/userdata/val2017/000000350023.jpg +/userdata/val2017/000000028993.jpg +/userdata/val2017/000000015440.jpg +/userdata/val2017/000000162415.jpg +/userdata/val2017/000000001425.jpg +/userdata/val2017/000000509131.jpg +/userdata/val2017/000000314709.jpg +/userdata/val2017/000000274219.jpg +/userdata/val2017/000000524850.jpg +/userdata/val2017/000000094185.jpg +/userdata/val2017/000000447342.jpg +/userdata/val2017/000000201148.jpg +/userdata/val2017/000000206487.jpg +/userdata/val2017/000000170116.jpg +/userdata/val2017/000000523782.jpg +/userdata/val2017/000000482917.jpg +/userdata/val2017/000000353518.jpg +/userdata/val2017/000000447789.jpg +/userdata/val2017/000000001584.jpg +/userdata/val2017/000000308165.jpg +/userdata/val2017/000000203580.jpg +/userdata/val2017/000000330396.jpg +/userdata/val2017/000000308328.jpg +/userdata/val2017/000000189698.jpg +/userdata/val2017/000000083172.jpg +/userdata/val2017/000000203095.jpg +/userdata/val2017/000000185802.jpg +/userdata/val2017/000000343218.jpg +/userdata/val2017/000000177489.jpg +/userdata/val2017/000000287874.jpg +/userdata/val2017/000000509403.jpg +/userdata/val2017/000000300276.jpg +/userdata/val2017/000000392933.jpg +/userdata/val2017/000000175535.jpg +/userdata/val2017/000000196141.jpg +/userdata/val2017/000000004765.jpg +/userdata/val2017/000000495448.jpg +/userdata/val2017/000000164363.jpg +/userdata/val2017/000000333745.jpg +/userdata/val2017/000000356424.jpg +/userdata/val2017/000000308466.jpg +/userdata/val2017/000000259382.jpg +/userdata/val2017/000000154087.jpg +/userdata/val2017/000000512929.jpg +/userdata/val2017/000000094326.jpg +/userdata/val2017/000000404839.jpg +/userdata/val2017/000000164115.jpg +/userdata/val2017/000000423971.jpg +/userdata/val2017/000000119038.jpg +/userdata/val2017/000000464786.jpg +/userdata/val2017/000000331280.jpg +/userdata/val2017/000000557172.jpg +/userdata/val2017/000000368961.jpg +/userdata/val2017/000000355169.jpg +/userdata/val2017/000000329219.jpg +/userdata/val2017/000000032901.jpg +/userdata/val2017/000000057672.jpg +/userdata/val2017/000000235778.jpg +/userdata/val2017/000000066771.jpg +/userdata/val2017/000000357816.jpg +/userdata/val2017/000000129322.jpg +/userdata/val2017/000000439623.jpg +/userdata/val2017/000000490125.jpg +/userdata/val2017/000000164602.jpg +/userdata/val2017/000000008211.jpg +/userdata/val2017/000000081766.jpg +/userdata/val2017/000000570456.jpg +/userdata/val2017/000000166563.jpg +/userdata/val2017/000000369442.jpg +/userdata/val2017/000000231879.jpg +/userdata/val2017/000000089670.jpg +/userdata/val2017/000000101420.jpg +/userdata/val2017/000000530854.jpg +/userdata/val2017/000000564127.jpg +/userdata/val2017/000000053909.jpg +/userdata/val2017/000000008899.jpg +/userdata/val2017/000000319100.jpg +/userdata/val2017/000000559707.jpg +/userdata/val2017/000000197004.jpg +/userdata/val2017/000000161128.jpg +/userdata/val2017/000000130699.jpg +/userdata/val2017/000000530466.jpg +/userdata/val2017/000000102820.jpg +/userdata/val2017/000000361142.jpg +/userdata/val2017/000000290081.jpg +/userdata/val2017/000000276434.jpg +/userdata/val2017/000000395388.jpg +/userdata/val2017/000000426836.jpg +/userdata/val2017/000000405972.jpg +/userdata/val2017/000000257084.jpg +/userdata/val2017/000000401244.jpg +/userdata/val2017/000000028449.jpg +/userdata/val2017/000000243495.jpg +/userdata/val2017/000000161925.jpg +/userdata/val2017/000000154425.jpg +/userdata/val2017/000000179653.jpg +/userdata/val2017/000000033638.jpg +/userdata/val2017/000000084674.jpg +/userdata/val2017/000000359540.jpg +/userdata/val2017/000000275791.jpg +/userdata/val2017/000000382734.jpg +/userdata/val2017/000000069224.jpg +/userdata/val2017/000000182441.jpg +/userdata/val2017/000000077396.jpg +/userdata/val2017/000000351810.jpg +/userdata/val2017/000000179285.jpg +/userdata/val2017/000000419408.jpg +/userdata/val2017/000000375078.jpg +/userdata/val2017/000000415882.jpg +/userdata/val2017/000000253452.jpg +/userdata/val2017/000000409211.jpg +/userdata/val2017/000000050331.jpg +/userdata/val2017/000000428454.jpg +/userdata/val2017/000000417632.jpg +/userdata/val2017/000000516143.jpg +/userdata/val2017/000000350679.jpg +/userdata/val2017/000000389109.jpg +/userdata/val2017/000000024144.jpg +/userdata/val2017/000000571857.jpg +/userdata/val2017/000000046252.jpg +/userdata/val2017/000000032610.jpg +/userdata/val2017/000000315219.jpg +/userdata/val2017/000000545730.jpg +/userdata/val2017/000000404479.jpg +/userdata/val2017/000000322944.jpg +/userdata/val2017/000000189436.jpg +/userdata/val2017/000000067213.jpg +/userdata/val2017/000000419601.jpg +/userdata/val2017/000000482800.jpg +/userdata/val2017/000000179392.jpg +/userdata/val2017/000000486040.jpg +/userdata/val2017/000000147729.jpg +/userdata/val2017/000000106266.jpg +/userdata/val2017/000000180383.jpg +/userdata/val2017/000000485071.jpg +/userdata/val2017/000000240023.jpg +/userdata/val2017/000000570782.jpg +/userdata/val2017/000000153529.jpg +/userdata/val2017/000000581615.jpg +/userdata/val2017/000000044260.jpg +/userdata/val2017/000000334719.jpg +/userdata/val2017/000000255664.jpg +/userdata/val2017/000000228942.jpg +/userdata/val2017/000000090062.jpg +/userdata/val2017/000000284106.jpg +/userdata/val2017/000000109992.jpg +/userdata/val2017/000000058705.jpg +/userdata/val2017/000000437205.jpg +/userdata/val2017/000000305695.jpg +/userdata/val2017/000000476787.jpg +/userdata/val2017/000000459437.jpg +/userdata/val2017/000000010583.jpg +/userdata/val2017/000000088951.jpg +/userdata/val2017/000000402992.jpg +/userdata/val2017/000000200839.jpg +/userdata/val2017/000000097679.jpg +/userdata/val2017/000000001675.jpg +/userdata/val2017/000000358923.jpg +/userdata/val2017/000000075456.jpg +/userdata/val2017/000000005586.jpg +/userdata/val2017/000000462904.jpg +/userdata/val2017/000000301718.jpg +/userdata/val2017/000000417779.jpg +/userdata/val2017/000000452321.jpg +/userdata/val2017/000000310980.jpg +/userdata/val2017/000000349302.jpg +/userdata/val2017/000000226147.jpg +/userdata/val2017/000000330369.jpg +/userdata/val2017/000000171740.jpg +/userdata/val2017/000000078915.jpg +/userdata/val2017/000000536947.jpg +/userdata/val2017/000000445722.jpg +/userdata/val2017/000000383289.jpg +/userdata/val2017/000000398652.jpg +/userdata/val2017/000000108253.jpg +/userdata/val2017/000000163057.jpg +/userdata/val2017/000000121497.jpg +/userdata/val2017/000000058393.jpg +/userdata/val2017/000000448365.jpg +/userdata/val2017/000000266981.jpg +/userdata/val2017/000000115898.jpg +/userdata/val2017/000000104782.jpg +/userdata/val2017/000000215114.jpg +/userdata/val2017/000000138492.jpg +/userdata/val2017/000000096825.jpg +/userdata/val2017/000000119088.jpg +/userdata/val2017/000000431727.jpg +/userdata/val2017/000000403122.jpg +/userdata/val2017/000000017182.jpg +/userdata/val2017/000000441543.jpg +/userdata/val2017/000000100624.jpg +/userdata/val2017/000000474854.jpg +/userdata/val2017/000000163314.jpg +/userdata/val2017/000000294855.jpg +/userdata/val2017/000000163258.jpg +/userdata/val2017/000000545826.jpg +/userdata/val2017/000000252216.jpg +/userdata/val2017/000000534827.jpg +/userdata/val2017/000000460494.jpg +/userdata/val2017/000000368900.jpg +/userdata/val2017/000000360943.jpg +/userdata/val2017/000000564280.jpg +/userdata/val2017/000000074646.jpg +/userdata/val2017/000000271116.jpg +/userdata/val2017/000000559099.jpg +/userdata/val2017/000000193717.jpg +/userdata/val2017/000000570539.jpg +/userdata/val2017/000000520659.jpg +/userdata/val2017/000000205282.jpg +/userdata/val2017/000000455597.jpg +/userdata/val2017/000000396729.jpg +/userdata/val2017/000000530457.jpg +/userdata/val2017/000000414170.jpg +/userdata/val2017/000000062355.jpg +/userdata/val2017/000000167067.jpg +/userdata/val2017/000000451150.jpg +/userdata/val2017/000000284296.jpg +/userdata/val2017/000000261535.jpg +/userdata/val2017/000000573258.jpg +/userdata/val2017/000000039405.jpg +/userdata/val2017/000000009400.jpg +/userdata/val2017/000000306139.jpg +/userdata/val2017/000000545007.jpg +/userdata/val2017/000000235399.jpg +/userdata/val2017/000000398203.jpg +/userdata/val2017/000000423104.jpg +/userdata/val2017/000000111609.jpg +/userdata/val2017/000000554838.jpg +/userdata/val2017/000000147223.jpg +/userdata/val2017/000000070739.jpg +/userdata/val2017/000000194471.jpg +/userdata/val2017/000000434247.jpg +/userdata/val2017/000000056350.jpg +/userdata/val2017/000000368038.jpg +/userdata/val2017/000000187249.jpg +/userdata/val2017/000000244379.jpg +/userdata/val2017/000000445675.jpg +/userdata/val2017/000000298251.jpg +/userdata/val2017/000000265777.jpg +/userdata/val2017/000000011197.jpg +/userdata/val2017/000000251537.jpg +/userdata/val2017/000000304291.jpg +/userdata/val2017/000000579070.jpg +/userdata/val2017/000000181421.jpg +/userdata/val2017/000000219485.jpg +/userdata/val2017/000000312278.jpg +/userdata/val2017/000000344611.jpg +/userdata/val2017/000000323709.jpg +/userdata/val2017/000000022892.jpg +/userdata/val2017/000000112997.jpg +/userdata/val2017/000000262048.jpg +/userdata/val2017/000000047010.jpg +/userdata/val2017/000000449190.jpg +/userdata/val2017/000000018833.jpg +/userdata/val2017/000000157138.jpg +/userdata/val2017/000000186980.jpg +/userdata/val2017/000000349837.jpg +/userdata/val2017/000000563349.jpg +/userdata/val2017/000000291634.jpg +/userdata/val2017/000000161609.jpg +/userdata/val2017/000000117914.jpg +/userdata/val2017/000000227187.jpg +/userdata/val2017/000000180296.jpg +/userdata/val2017/000000272566.jpg +/userdata/val2017/000000157098.jpg +/userdata/val2017/000000163640.jpg +/userdata/val2017/000000575205.jpg +/userdata/val2017/000000479248.jpg +/userdata/val2017/000000105923.jpg +/userdata/val2017/000000231831.jpg +/userdata/val2017/000000139077.jpg +/userdata/val2017/000000574425.jpg +/userdata/val2017/000000176857.jpg +/userdata/val2017/000000377486.jpg +/userdata/val2017/000000462371.jpg +/userdata/val2017/000000575500.jpg +/userdata/val2017/000000404923.jpg +/userdata/val2017/000000005529.jpg +/userdata/val2017/000000012120.jpg +/userdata/val2017/000000263644.jpg +/userdata/val2017/000000424545.jpg +/userdata/val2017/000000195754.jpg +/userdata/val2017/000000115946.jpg +/userdata/val2017/000000190236.jpg +/userdata/val2017/000000082986.jpg +/userdata/val2017/000000263860.jpg +/userdata/val2017/000000281687.jpg +/userdata/val2017/000000496722.jpg +/userdata/val2017/000000381971.jpg +/userdata/val2017/000000079188.jpg +/userdata/val2017/000000398028.jpg +/userdata/val2017/000000406997.jpg +/userdata/val2017/000000511321.jpg +/userdata/val2017/000000386457.jpg +/userdata/val2017/000000151657.jpg +/userdata/val2017/000000352491.jpg +/userdata/val2017/000000113354.jpg +/userdata/val2017/000000473237.jpg +/userdata/val2017/000000355817.jpg +/userdata/val2017/000000187745.jpg +/userdata/val2017/000000411938.jpg +/userdata/val2017/000000215778.jpg +/userdata/val2017/000000410428.jpg +/userdata/val2017/000000478136.jpg +/userdata/val2017/000000465718.jpg +/userdata/val2017/000000170670.jpg +/userdata/val2017/000000042528.jpg +/userdata/val2017/000000269632.jpg +/userdata/val2017/000000284764.jpg +/userdata/val2017/000000370711.jpg +/userdata/val2017/000000343496.jpg +/userdata/val2017/000000183104.jpg +/userdata/val2017/000000258541.jpg +/userdata/val2017/000000279769.jpg +/userdata/val2017/000000560371.jpg +/userdata/val2017/000000044195.jpg +/userdata/val2017/000000272416.jpg +/userdata/val2017/000000312263.jpg +/userdata/val2017/000000515982.jpg +/userdata/val2017/000000023666.jpg +/userdata/val2017/000000137106.jpg +/userdata/val2017/000000504415.jpg +/userdata/val2017/000000460682.jpg +/userdata/val2017/000000262587.jpg +/userdata/val2017/000000488710.jpg +/userdata/val2017/000000018491.jpg +/userdata/val2017/000000188296.jpg +/userdata/val2017/000000291664.jpg +/userdata/val2017/000000572620.jpg +/userdata/val2017/000000036539.jpg +/userdata/val2017/000000576654.jpg +/userdata/val2017/000000292456.jpg +/userdata/val2017/000000464251.jpg +/userdata/val2017/000000405432.jpg +/userdata/val2017/000000369541.jpg +/userdata/val2017/000000410496.jpg +/userdata/val2017/000000329542.jpg +/userdata/val2017/000000387387.jpg +/userdata/val2017/000000411817.jpg +/userdata/val2017/000000227478.jpg +/userdata/val2017/000000107851.jpg +/userdata/val2017/000000018770.jpg +/userdata/val2017/000000565624.jpg +/userdata/val2017/000000201418.jpg +/userdata/val2017/000000214753.jpg +/userdata/val2017/000000342367.jpg +/userdata/val2017/000000130586.jpg +/userdata/val2017/000000047801.jpg +/userdata/val2017/000000534639.jpg +/userdata/val2017/000000433103.jpg +/userdata/val2017/000000132544.jpg +/userdata/val2017/000000323496.jpg +/userdata/val2017/000000167486.jpg +/userdata/val2017/000000063602.jpg +/userdata/val2017/000000326970.jpg +/userdata/val2017/000000451879.jpg +/userdata/val2017/000000464089.jpg +/userdata/val2017/000000565778.jpg +/userdata/val2017/000000311002.jpg +/userdata/val2017/000000072852.jpg +/userdata/val2017/000000096493.jpg +/userdata/val2017/000000368684.jpg +/userdata/val2017/000000289960.jpg +/userdata/val2017/000000286660.jpg +/userdata/val2017/000000402774.jpg +/userdata/val2017/000000305343.jpg +/userdata/val2017/000000222863.jpg +/userdata/val2017/000000089271.jpg +/userdata/val2017/000000550797.jpg +/userdata/val2017/000000579158.jpg +/userdata/val2017/000000541291.jpg +/userdata/val2017/000000137950.jpg +/userdata/val2017/000000295231.jpg +/userdata/val2017/000000063965.jpg +/userdata/val2017/000000528524.jpg +/userdata/val2017/000000414133.jpg +/userdata/val2017/000000295809.jpg +/userdata/val2017/000000217400.jpg +/userdata/val2017/000000319534.jpg +/userdata/val2017/000000212573.jpg +/userdata/val2017/000000100238.jpg +/userdata/val2017/000000066038.jpg +/userdata/val2017/000000020992.jpg +/userdata/val2017/000000005037.jpg +/userdata/val2017/000000509719.jpg +/userdata/val2017/000000107094.jpg +/userdata/val2017/000000427034.jpg +/userdata/val2017/000000476258.jpg +/userdata/val2017/000000289415.jpg +/userdata/val2017/000000450399.jpg +/userdata/val2017/000000488270.jpg +/userdata/val2017/000000069106.jpg +/userdata/val2017/000000471756.jpg +/userdata/val2017/000000275392.jpg +/userdata/val2017/000000492362.jpg +/userdata/val2017/000000016228.jpg +/userdata/val2017/000000185599.jpg +/userdata/val2017/000000025228.jpg +/userdata/val2017/000000304180.jpg +/userdata/val2017/000000470924.jpg +/userdata/val2017/000000350054.jpg +/userdata/val2017/000000228144.jpg +/userdata/val2017/000000552612.jpg +/userdata/val2017/000000024243.jpg +/userdata/val2017/000000491613.jpg +/userdata/val2017/000000431140.jpg +/userdata/val2017/000000013923.jpg +/userdata/val2017/000000413689.jpg +/userdata/val2017/000000094944.jpg +/userdata/val2017/000000410735.jpg +/userdata/val2017/000000217219.jpg +/userdata/val2017/000000175438.jpg +/userdata/val2017/000000574810.jpg +/userdata/val2017/000000238013.jpg +/userdata/val2017/000000312340.jpg +/userdata/val2017/000000040036.jpg +/userdata/val2017/000000509824.jpg +/userdata/val2017/000000311518.jpg +/userdata/val2017/000000022755.jpg +/userdata/val2017/000000224051.jpg +/userdata/val2017/000000036861.jpg +/userdata/val2017/000000056288.jpg +/userdata/val2017/000000331799.jpg +/userdata/val2017/000000121153.jpg +/userdata/val2017/000000395633.jpg +/userdata/val2017/000000459809.jpg +/userdata/val2017/000000054592.jpg +/userdata/val2017/000000394328.jpg +/userdata/val2017/000000338325.jpg +/userdata/val2017/000000014007.jpg +/userdata/val2017/000000051738.jpg +/userdata/val2017/000000223789.jpg +/userdata/val2017/000000073702.jpg +/userdata/val2017/000000556000.jpg +/userdata/val2017/000000347254.jpg +/userdata/val2017/000000157847.jpg +/userdata/val2017/000000437898.jpg +/userdata/val2017/000000008629.jpg +/userdata/val2017/000000020571.jpg +/userdata/val2017/000000143572.jpg +/userdata/val2017/000000168593.jpg +/userdata/val2017/000000470173.jpg +/userdata/val2017/000000568981.jpg +/userdata/val2017/000000300842.jpg +/userdata/val2017/000000374369.jpg +/userdata/val2017/000000273642.jpg +/userdata/val2017/000000368456.jpg +/userdata/val2017/000000357430.jpg +/userdata/val2017/000000232348.jpg +/userdata/val2017/000000277584.jpg +/userdata/val2017/000000213593.jpg +/userdata/val2017/000000087038.jpg +/userdata/val2017/000000494188.jpg +/userdata/val2017/000000393115.jpg +/userdata/val2017/000000414340.jpg +/userdata/val2017/000000286182.jpg +/userdata/val2017/000000540466.jpg +/userdata/val2017/000000209142.jpg +/userdata/val2017/000000281929.jpg +/userdata/val2017/000000064868.jpg +/userdata/val2017/000000176778.jpg +/userdata/val2017/000000161879.jpg +/userdata/val2017/000000057760.jpg +/userdata/val2017/000000179174.jpg +/userdata/val2017/000000130566.jpg +/userdata/val2017/000000032811.jpg +/userdata/val2017/000000523100.jpg +/userdata/val2017/000000002592.jpg +/userdata/val2017/000000224222.jpg +/userdata/val2017/000000463527.jpg +/userdata/val2017/000000046031.jpg +/userdata/val2017/000000498709.jpg +/userdata/val2017/000000531495.jpg +/userdata/val2017/000000179112.jpg +/userdata/val2017/000000051961.jpg +/userdata/val2017/000000281414.jpg +/userdata/val2017/000000558421.jpg +/userdata/val2017/000000299609.jpg +/userdata/val2017/000000546219.jpg +/userdata/val2017/000000327769.jpg +/userdata/val2017/000000017627.jpg +/userdata/val2017/000000432085.jpg +/userdata/val2017/000000303818.jpg +/userdata/val2017/000000172571.jpg +/userdata/val2017/000000419974.jpg +/userdata/val2017/000000555009.jpg +/userdata/val2017/000000040471.jpg +/userdata/val2017/000000257370.jpg +/userdata/val2017/000000165713.jpg +/userdata/val2017/000000099242.jpg +/userdata/val2017/000000099053.jpg +/userdata/val2017/000000349860.jpg +/userdata/val2017/000000003934.jpg +/userdata/val2017/000000025986.jpg +/userdata/val2017/000000448810.jpg +/userdata/val2017/000000364297.jpg +/userdata/val2017/000000361103.jpg +/userdata/val2017/000000371749.jpg +/userdata/val2017/000000397681.jpg +/userdata/val2017/000000519338.jpg +/userdata/val2017/000000136466.jpg +/userdata/val2017/000000046378.jpg +/userdata/val2017/000000121417.jpg +/userdata/val2017/000000312586.jpg +/userdata/val2017/000000281179.jpg +/userdata/val2017/000000287347.jpg +/userdata/val2017/000000110784.jpg +/userdata/val2017/000000257566.jpg +/userdata/val2017/000000296224.jpg +/userdata/val2017/000000013004.jpg +/userdata/val2017/000000469652.jpg +/userdata/val2017/000000175251.jpg +/userdata/val2017/000000232244.jpg +/userdata/val2017/000000456143.jpg +/userdata/val2017/000000128748.jpg +/userdata/val2017/000000098853.jpg +/userdata/val2017/000000535094.jpg +/userdata/val2017/000000288430.jpg +/userdata/val2017/000000370486.jpg +/userdata/val2017/000000256775.jpg +/userdata/val2017/000000212072.jpg +/userdata/val2017/000000449579.jpg +/userdata/val2017/000000507975.jpg +/userdata/val2017/000000089648.jpg +/userdata/val2017/000000500663.jpg +/userdata/val2017/000000396205.jpg +/userdata/val2017/000000498747.jpg +/userdata/val2017/000000530470.jpg +/userdata/val2017/000000183500.jpg +/userdata/val2017/000000061268.jpg +/userdata/val2017/000000073153.jpg +/userdata/val2017/000000389804.jpg +/userdata/val2017/000000100283.jpg +/userdata/val2017/000000190676.jpg +/userdata/val2017/000000357737.jpg +/userdata/val2017/000000041635.jpg +/userdata/val2017/000000110638.jpg +/userdata/val2017/000000067315.jpg +/userdata/val2017/000000155145.jpg +/userdata/val2017/000000404568.jpg +/userdata/val2017/000000129945.jpg +/userdata/val2017/000000152870.jpg +/userdata/val2017/000000435003.jpg +/userdata/val2017/000000222118.jpg +/userdata/val2017/000000498807.jpg +/userdata/val2017/000000201775.jpg +/userdata/val2017/000000103723.jpg +/userdata/val2017/000000001503.jpg +/userdata/val2017/000000124277.jpg +/userdata/val2017/000000303908.jpg +/userdata/val2017/000000231747.jpg +/userdata/val2017/000000546976.jpg +/userdata/val2017/000000091921.jpg +/userdata/val2017/000000173830.jpg +/userdata/val2017/000000511760.jpg +/userdata/val2017/000000182417.jpg +/userdata/val2017/000000398377.jpg +/userdata/val2017/000000009378.jpg +/userdata/val2017/000000475064.jpg +/userdata/val2017/000000079837.jpg +/userdata/val2017/000000061171.jpg +/userdata/val2017/000000420840.jpg +/userdata/val2017/000000548267.jpg +/userdata/val2017/000000457262.jpg +/userdata/val2017/000000466416.jpg +/userdata/val2017/000000447522.jpg +/userdata/val2017/000000429530.jpg +/userdata/val2017/000000007795.jpg +/userdata/val2017/000000347174.jpg +/userdata/val2017/000000029187.jpg +/userdata/val2017/000000482978.jpg +/userdata/val2017/000000185292.jpg +/userdata/val2017/000000098716.jpg +/userdata/val2017/000000063552.jpg +/userdata/val2017/000000452793.jpg +/userdata/val2017/000000426241.jpg +/userdata/val2017/000000382111.jpg +/userdata/val2017/000000435208.jpg +/userdata/val2017/000000451435.jpg +/userdata/val2017/000000065350.jpg +/userdata/val2017/000000221754.jpg +/userdata/val2017/000000343937.jpg +/userdata/val2017/000000286994.jpg +/userdata/val2017/000000336232.jpg +/userdata/val2017/000000127270.jpg +/userdata/val2017/000000087244.jpg +/userdata/val2017/000000455872.jpg +/userdata/val2017/000000016502.jpg +/userdata/val2017/000000355325.jpg +/userdata/val2017/000000022371.jpg +/userdata/val2017/000000570448.jpg +/userdata/val2017/000000159112.jpg +/userdata/val2017/000000042888.jpg +/userdata/val2017/000000080932.jpg +/userdata/val2017/000000140987.jpg +/userdata/val2017/000000002923.jpg +/userdata/val2017/000000040083.jpg +/userdata/val2017/000000356531.jpg +/userdata/val2017/000000498919.jpg +/userdata/val2017/000000266892.jpg +/userdata/val2017/000000521719.jpg +/userdata/val2017/000000439290.jpg +/userdata/val2017/000000410487.jpg +/userdata/val2017/000000333956.jpg +/userdata/val2017/000000568213.jpg +/userdata/val2017/000000568147.jpg +/userdata/val2017/000000263403.jpg +/userdata/val2017/000000315257.jpg +/userdata/val2017/000000439854.jpg +/userdata/val2017/000000226984.jpg +/userdata/val2017/000000271997.jpg +/userdata/val2017/000000165681.jpg +/userdata/val2017/000000232684.jpg +/userdata/val2017/000000330790.jpg +/userdata/val2017/000000196185.jpg +/userdata/val2017/000000570736.jpg +/userdata/val2017/000000235241.jpg +/userdata/val2017/000000032285.jpg +/userdata/val2017/000000292225.jpg +/userdata/val2017/000000142238.jpg +/userdata/val2017/000000076417.jpg +/userdata/val2017/000000128372.jpg +/userdata/val2017/000000029596.jpg +/userdata/val2017/000000239347.jpg +/userdata/val2017/000000236592.jpg +/userdata/val2017/000000033707.jpg +/userdata/val2017/000000407943.jpg +/userdata/val2017/000000039480.jpg +/userdata/val2017/000000421455.jpg +/userdata/val2017/000000526728.jpg +/userdata/val2017/000000191672.jpg +/userdata/val2017/000000287959.jpg +/userdata/val2017/000000194216.jpg +/userdata/val2017/000000145665.jpg +/userdata/val2017/000000052591.jpg +/userdata/val2017/000000186282.jpg +/userdata/val2017/000000579655.jpg +/userdata/val2017/000000270066.jpg +/userdata/val2017/000000018380.jpg +/userdata/val2017/000000563882.jpg +/userdata/val2017/000000477118.jpg +/userdata/val2017/000000035682.jpg +/userdata/val2017/000000326542.jpg +/userdata/val2017/000000571943.jpg +/userdata/val2017/000000163951.jpg +/userdata/val2017/000000454067.jpg +/userdata/val2017/000000312489.jpg +/userdata/val2017/000000396580.jpg +/userdata/val2017/000000325838.jpg +/userdata/val2017/000000151480.jpg +/userdata/val2017/000000442456.jpg +/userdata/val2017/000000160772.jpg +/userdata/val2017/000000541634.jpg +/userdata/val2017/000000166918.jpg +/userdata/val2017/000000231097.jpg +/userdata/val2017/000000531134.jpg +/userdata/val2017/000000427256.jpg +/userdata/val2017/000000262631.jpg +/userdata/val2017/000000430961.jpg +/userdata/val2017/000000356428.jpg +/userdata/val2017/000000162130.jpg +/userdata/val2017/000000057232.jpg +/userdata/val2017/000000309678.jpg +/userdata/val2017/000000127530.jpg +/userdata/val2017/000000172617.jpg +/userdata/val2017/000000293200.jpg +/userdata/val2017/000000338625.jpg +/userdata/val2017/000000334767.jpg +/userdata/val2017/000000296222.jpg +/userdata/val2017/000000070048.jpg +/userdata/val2017/000000347456.jpg +/userdata/val2017/000000327605.jpg +/userdata/val2017/000000462614.jpg +/userdata/val2017/000000338428.jpg +/userdata/val2017/000000125936.jpg +/userdata/val2017/000000156292.jpg +/userdata/val2017/000000033104.jpg +/userdata/val2017/000000440171.jpg +/userdata/val2017/000000501368.jpg +/userdata/val2017/000000255718.jpg +/userdata/val2017/000000222317.jpg +/userdata/val2017/000000378673.jpg +/userdata/val2017/000000537991.jpg +/userdata/val2017/000000326128.jpg +/userdata/val2017/000000177383.jpg +/userdata/val2017/000000213547.jpg +/userdata/val2017/000000458663.jpg +/userdata/val2017/000000393569.jpg +/userdata/val2017/000000176232.jpg +/userdata/val2017/000000529568.jpg +/userdata/val2017/000000396526.jpg +/userdata/val2017/000000247806.jpg +/userdata/val2017/000000130826.jpg +/userdata/val2017/000000424162.jpg +/userdata/val2017/000000383676.jpg +/userdata/val2017/000000424551.jpg +/userdata/val2017/000000389197.jpg +/userdata/val2017/000000463542.jpg +/userdata/val2017/000000200252.jpg +/userdata/val2017/000000088218.jpg +/userdata/val2017/000000021465.jpg +/userdata/val2017/000000338191.jpg +/userdata/val2017/000000456015.jpg +/userdata/val2017/000000426329.jpg +/userdata/val2017/000000513041.jpg +/userdata/val2017/000000350488.jpg +/userdata/val2017/000000473406.jpg +/userdata/val2017/000000129756.jpg +/userdata/val2017/000000184400.jpg +/userdata/val2017/000000410712.jpg +/userdata/val2017/000000456559.jpg +/userdata/val2017/000000185473.jpg +/userdata/val2017/000000509699.jpg +/userdata/val2017/000000493286.jpg +/userdata/val2017/000000420069.jpg +/userdata/val2017/000000335529.jpg +/userdata/val2017/000000316666.jpg +/userdata/val2017/000000191580.jpg +/userdata/val2017/000000527427.jpg +/userdata/val2017/000000102644.jpg +/userdata/val2017/000000476119.jpg +/userdata/val2017/000000262440.jpg +/userdata/val2017/000000082812.jpg +/userdata/val2017/000000242411.jpg +/userdata/val2017/000000000872.jpg +/userdata/val2017/000000388846.jpg +/userdata/val2017/000000422670.jpg +/userdata/val2017/000000332901.jpg +/userdata/val2017/000000491683.jpg +/userdata/val2017/000000021503.jpg +/userdata/val2017/000000474078.jpg +/userdata/val2017/000000138979.jpg +/userdata/val2017/000000176446.jpg +/userdata/val2017/000000233033.jpg +/userdata/val2017/000000012576.jpg +/userdata/val2017/000000271471.jpg +/userdata/val2017/000000440508.jpg +/userdata/val2017/000000119365.jpg +/userdata/val2017/000000215723.jpg +/userdata/val2017/000000415238.jpg +/userdata/val2017/000000471893.jpg +/userdata/val2017/000000289229.jpg +/userdata/val2017/000000335800.jpg +/userdata/val2017/000000252219.jpg +/userdata/val2017/000000376093.jpg +/userdata/val2017/000000428111.jpg +/userdata/val2017/000000153011.jpg +/userdata/val2017/000000274066.jpg +/userdata/val2017/000000298738.jpg +/userdata/val2017/000000006471.jpg +/userdata/val2017/000000405195.jpg +/userdata/val2017/000000574823.jpg +/userdata/val2017/000000554156.jpg +/userdata/val2017/000000000724.jpg +/userdata/val2017/000000492284.jpg +/userdata/val2017/000000094751.jpg +/userdata/val2017/000000523957.jpg +/userdata/val2017/000000082688.jpg +/userdata/val2017/000000090155.jpg +/userdata/val2017/000000559956.jpg +/userdata/val2017/000000132375.jpg +/userdata/val2017/000000455937.jpg +/userdata/val2017/000000328683.jpg +/userdata/val2017/000000298904.jpg +/userdata/val2017/000000319935.jpg +/userdata/val2017/000000511076.jpg +/userdata/val2017/000000433374.jpg +/userdata/val2017/000000147205.jpg +/userdata/val2017/000000359135.jpg +/userdata/val2017/000000553669.jpg +/userdata/val2017/000000539445.jpg +/userdata/val2017/000000001268.jpg +/userdata/val2017/000000430073.jpg +/userdata/val2017/000000133343.jpg +/userdata/val2017/000000485802.jpg +/userdata/val2017/000000523241.jpg +/userdata/val2017/000000005001.jpg +/userdata/val2017/000000433774.jpg +/userdata/val2017/000000581357.jpg +/userdata/val2017/000000041633.jpg +/userdata/val2017/000000250205.jpg +/userdata/val2017/000000125778.jpg +/userdata/val2017/000000269316.jpg +/userdata/val2017/000000551350.jpg +/userdata/val2017/000000530099.jpg +/userdata/val2017/000000005600.jpg +/userdata/val2017/000000508917.jpg +/userdata/val2017/000000247838.jpg +/userdata/val2017/000000119677.jpg +/userdata/val2017/000000267903.jpg +/userdata/val2017/000000051309.jpg +/userdata/val2017/000000459153.jpg +/userdata/val2017/000000236308.jpg +/userdata/val2017/000000416745.jpg +/userdata/val2017/000000373382.jpg +/userdata/val2017/000000157928.jpg +/userdata/val2017/000000092124.jpg +/userdata/val2017/000000230362.jpg +/userdata/val2017/000000331817.jpg +/userdata/val2017/000000468124.jpg +/userdata/val2017/000000351530.jpg +/userdata/val2017/000000027768.jpg +/userdata/val2017/000000278705.jpg +/userdata/val2017/000000210915.jpg +/userdata/val2017/000000236690.jpg +/userdata/val2017/000000207538.jpg +/userdata/val2017/000000276921.jpg +/userdata/val2017/000000453981.jpg +/userdata/val2017/000000290843.jpg +/userdata/val2017/000000507893.jpg +/userdata/val2017/000000223959.jpg +/userdata/val2017/000000474028.jpg +/userdata/val2017/000000376264.jpg +/userdata/val2017/000000268378.jpg +/userdata/val2017/000000202228.jpg +/userdata/val2017/000000416343.jpg +/userdata/val2017/000000104119.jpg +/userdata/val2017/000000151516.jpg +/userdata/val2017/000000311303.jpg +/userdata/val2017/000000563653.jpg +/userdata/val2017/000000499031.jpg +/userdata/val2017/000000413404.jpg +/userdata/val2017/000000226662.jpg +/userdata/val2017/000000153527.jpg +/userdata/val2017/000000576052.jpg +/userdata/val2017/000000307172.jpg +/userdata/val2017/000000338304.jpg +/userdata/val2017/000000068409.jpg +/userdata/val2017/000000431545.jpg +/userdata/val2017/000000125211.jpg +/userdata/val2017/000000155051.jpg +/userdata/val2017/000000306700.jpg +/userdata/val2017/000000534605.jpg +/userdata/val2017/000000447314.jpg +/userdata/val2017/000000283268.jpg +/userdata/val2017/000000486573.jpg +/userdata/val2017/000000129812.jpg +/userdata/val2017/000000214869.jpg +/userdata/val2017/000000051326.jpg +/userdata/val2017/000000161397.jpg +/userdata/val2017/000000548506.jpg +/userdata/val2017/000000242287.jpg +/userdata/val2017/000000090631.jpg +/userdata/val2017/000000423123.jpg +/userdata/val2017/000000550714.jpg +/userdata/val2017/000000326462.jpg +/userdata/val2017/000000469828.jpg +/userdata/val2017/000000012670.jpg +/userdata/val2017/000000494759.jpg +/userdata/val2017/000000039769.jpg +/userdata/val2017/000000406611.jpg +/userdata/val2017/000000341681.jpg +/userdata/val2017/000000376442.jpg +/userdata/val2017/000000335450.jpg +/userdata/val2017/000000496854.jpg +/userdata/val2017/000000308631.jpg +/userdata/val2017/000000453708.jpg +/userdata/val2017/000000423506.jpg +/userdata/val2017/000000356347.jpg +/userdata/val2017/000000186624.jpg +/userdata/val2017/000000273551.jpg +/userdata/val2017/000000485237.jpg +/userdata/val2017/000000116589.jpg +/userdata/val2017/000000383838.jpg +/userdata/val2017/000000117525.jpg +/userdata/val2017/000000405306.jpg +/userdata/val2017/000000577976.jpg +/userdata/val2017/000000537812.jpg +/userdata/val2017/000000205401.jpg +/userdata/val2017/000000541123.jpg +/userdata/val2017/000000044877.jpg +/userdata/val2017/000000357748.jpg +/userdata/val2017/000000492077.jpg +/userdata/val2017/000000364322.jpg +/userdata/val2017/000000028285.jpg +/userdata/val2017/000000576031.jpg +/userdata/val2017/000000047585.jpg diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/model/dog.jpg b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/dog.jpg new file mode 100644 index 0000000..77b0381 Binary files /dev/null and b/rknn_yolo_demo/install/rknn_yolo_demo_test/model/dog.jpg differ diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/rknn_yolo_demo b/rknn_yolo_demo/install/rknn_yolo_demo_test/rknn_yolo_demo new file mode 100644 index 0000000..361cca7 Binary files /dev/null and b/rknn_yolo_demo/install/rknn_yolo_demo_test/rknn_yolo_demo differ diff --git a/rknn_yolo_demo/install/rknn_yolo_demo_test/rknn_yolo_demo_test b/rknn_yolo_demo/install/rknn_yolo_demo_test/rknn_yolo_demo_test new file mode 100644 index 0000000..5e96a04 Binary files /dev/null and b/rknn_yolo_demo/install/rknn_yolo_demo_test/rknn_yolo_demo_test differ diff --git a/rknn_yolo_demo/lib/libeasymedia.so b/rknn_yolo_demo/lib/libeasymedia.so new file mode 100644 index 0000000..3978490 Binary files /dev/null and b/rknn_yolo_demo/lib/libeasymedia.so differ diff --git a/rknn_yolo_demo/lib/libeasymedia.so.1 b/rknn_yolo_demo/lib/libeasymedia.so.1 new file mode 100644 index 0000000..3978490 Binary files /dev/null and b/rknn_yolo_demo/lib/libeasymedia.so.1 differ diff --git a/rknn_yolo_demo/lib/libeasymedia.so.1.0.1 b/rknn_yolo_demo/lib/libeasymedia.so.1.0.1 new file mode 100644 index 0000000..3978490 Binary files /dev/null and b/rknn_yolo_demo/lib/libeasymedia.so.1.0.1 differ diff --git a/rknn_yolo_demo/libs/README.md b/rknn_yolo_demo/libs/README.md new file mode 100644 index 0000000..f8b0898 --- /dev/null +++ b/rknn_yolo_demo/libs/README.md @@ -0,0 +1,38 @@ +# Libs 说明 + +libs 文件夹存放 C demo 编译时依赖的库,目前分为以下子文件夹 + + + +## common + +存放无需区分使用平台的依赖库 + + + +## platform + +存放需区分使用平台的依赖库 + + + +## rklibs + +存放 Rockchip 维护的依赖库,编译任意 C demo 前需执行以下指令进行初始化 + +``` +cd rklibs + +# RK1808/RV1126/RV1109 NPU 依赖库 +git clone https://github.com/rockchip-linux/rknpu + +# RK3399pro NPU 依赖库 +git clone https://github.com/airockchip/RK3399Pro_npu + +# RK3566/RK3568/RK3588/RV1106/RV1103 NPU 依赖库 +git clone https://github.com/rockchip-linux/rknpu2 + +# RGA调用依赖库,不区分硬件平台 +git clone https://github.com/airockchip/librga +``` + diff --git a/rknn_yolo_demo/libs/README_EN.md b/rknn_yolo_demo/libs/README_EN.md new file mode 100644 index 0000000..cf1a328 --- /dev/null +++ b/rknn_yolo_demo/libs/README_EN.md @@ -0,0 +1,8 @@ +## Libs + +Collection of the libs used for RKNN_C_demo + + + + + diff --git a/rknn_yolo_demo/libs/common/CImg/CImg.h b/rknn_yolo_demo/libs/common/CImg/CImg.h new file mode 100644 index 0000000..2bfe567 --- /dev/null +++ b/rknn_yolo_demo/libs/common/CImg/CImg.h @@ -0,0 +1,65138 @@ +/* + # + # File : CImg.h + # ( C++ header file ) + # + # Description : C++ Template Image Processing Toolkit. + # This file is the main component of the CImg Library project. + # ( http://cimg.eu ) + # + # Project manager : David Tschumperlé + # ( http://tschumperle.users.greyc.fr/ ) + # + # A complete list of contributors is available in file 'README.txt' + # distributed within the CImg package. + # + # Licenses : This file is 'dual-licensed', you have to choose one + # of the two licenses below to apply. + # + # CeCILL-C + # The CeCILL-C license is close to the GNU LGPL. + # ( http://cecill.info/licences/Licence_CeCILL-C_V1-en.html ) + # + # or CeCILL v2.1 + # The CeCILL license is compatible with the GNU GPL. + # ( http://cecill.info/licences/Licence_CeCILL_V2.1-en.html ) + # + # This software is governed either by the CeCILL or the CeCILL-C license + # under French law and abiding by the rules of distribution of free software. + # You can use, modify and or redistribute the software under the terms of + # the CeCILL or CeCILL-C licenses as circulated by CEA, CNRS and INRIA + # at the following URL: "http://cecill.info". + # + # As a counterpart to the access to the source code and rights to copy, + # modify and redistribute granted by the license, users are provided only + # with a limited warranty and the software's author, the holder of the + # economic rights, and the successive licensors have only limited + # liability. + # + # In this respect, the user's attention is drawn to the risks associated + # with loading, using, modifying and/or developing or reproducing the + # software by the user in light of its specific status of free software, + # that may mean that it is complicated to manipulate, and that also + # therefore means that it is reserved for developers and experienced + # professionals having in-depth computer knowledge. Users are therefore + # encouraged to load and test the software's suitability as regards their + # requirements in conditions enabling the security of their systems and/or + # data to be ensured and, more generally, to use and operate it in the + # same conditions as regards security. + # + # The fact that you are presently reading this means that you have had + # knowledge of the CeCILL and CeCILL-C licenses and that you accept its terms. + # +*/ + +// Set version number of the library. +#ifndef cimg_version +#define cimg_version 298 + +/*----------------------------------------------------------- + # + # Test and possibly auto-set CImg configuration variables + # and include required headers. + # + # If you find that the default configuration variables are + # not adapted to your system, you can override their values + # before including the header file "CImg.h" + # (use the #define directive). + # + ------------------------------------------------------------*/ + +// Include standard C++ headers. +// This is the minimal set of required headers to make CImg-based codes compile. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define cimg_str(x) #x +#define cimg_str2(x) cimg_str(x) + +// Detect/configure OS variables. +// +// Define 'cimg_OS' to: '0' for an unknown OS (will try to minize library dependencies). +// '1' for a Unix-like OS (Linux, Solaris, BSD, MacOSX, Irix, ...). +// '2' for Microsoft Windows. +// (auto-detection is performed if 'cimg_OS' is not set by the user). +#ifndef cimg_OS +#if defined(unix) || defined(__unix) || defined(__unix__) \ + || defined(linux) || defined(__linux) || defined(__linux__) \ + || defined(sun) || defined(__sun) \ + || defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined (__DragonFly__) \ + || defined(sgi) || defined(__sgi) \ + || defined(__OSX__) || defined(__MACOSX__) || defined(__APPLE__) \ + || defined(__CYGWIN__) +#define cimg_OS 1 +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +#define cimg_OS 2 +#else +#define cimg_OS 0 +#endif +#elif !(cimg_OS==0 || cimg_OS==1 || cimg_OS==2) +#error CImg Library: Invalid configuration variable 'cimg_OS'. +#error (correct values are '0 = unknown OS', '1 = Unix-like OS', '2 = Microsoft Windows'). +#endif +#ifndef cimg_date +#define cimg_date __DATE__ +#endif +#ifndef cimg_time +#define cimg_time __TIME__ +#endif + +// Disable silly warnings on some Microsoft VC++ compilers. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#pragma warning(disable:4244) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#pragma warning(disable:4319) +#pragma warning(disable:4512) +#pragma warning(disable:4571) +#pragma warning(disable:4640) +#pragma warning(disable:4706) +#pragma warning(disable:4710) +#pragma warning(disable:4800) +#pragma warning(disable:4804) +#pragma warning(disable:4820) +#pragma warning(disable:4996) + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#endif + +// Define correct string functions for each compiler and OS. +#if cimg_OS==2 && defined(_MSC_VER) +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#include +#if defined(__MACOSX__) || defined(__APPLE__) +#define cimg_sscanf cimg::_sscanf +#define cimg_sprintf cimg::_sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf snprintf +#define cimg_vsnprintf vsnprintf +#endif +#endif + +// Include OS-specific headers. +#if cimg_OS==1 +#include +#include +#include +#include +#include +#include +#elif cimg_OS==2 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#ifndef _WIN32_IE +#define _WIN32_IE 0x0400 +#endif +#include +#include +#include +enum {FALSE_WIN = 0}; +#endif + +// Look for C++11 features. +#ifndef cimg_use_cpp11 +#if __cplusplus>201100 +#define cimg_use_cpp11 1 +#else +#define cimg_use_cpp11 0 +#endif +#endif +#if cimg_use_cpp11==1 +#include +#include +#endif + +// Convenient macro to define pragma +#ifdef _MSC_VER +#define cimg_pragma(x) __pragma(x) +#else +#define cimg_pragma(x) _Pragma(#x) +#endif + +// Define own types 'cimg_long/ulong' and 'cimg_int64/uint64' to ensure portability. +// ( constrained to 'sizeof(cimg_ulong/cimg_long) = sizeof(void*)' and 'sizeof(cimg_int64/cimg_uint64)=8' ). +#if cimg_OS==2 + +#define cimg_uint64 unsigned __int64 +#define cimg_int64 __int64 +#define cimg_ulong UINT_PTR +#define cimg_long INT_PTR +#ifdef _MSC_VER +#define cimg_fuint64 "%I64u" +#define cimg_fint64 "%I64d" +#else +#define cimg_fuint64 "%llu" +#define cimg_fint64 "%lld" +#endif + +#else + +#if UINTPTR_MAX==0xffffffff || defined(__arm__) || defined(_M_ARM) || ((ULONG_MAX)==(UINT_MAX)) +#define cimg_uint64 unsigned long long +#define cimg_int64 long long +#define cimg_fuint64 "%llu" +#define cimg_fint64 "%lld" +#else +#define cimg_uint64 unsigned long +#define cimg_int64 long +#define cimg_fuint64 "%lu" +#define cimg_fint64 "%ld" +#endif + +#if defined(__arm__) || defined(_M_ARM) +#define cimg_ulong unsigned long long +#define cimg_long long long +#else +#define cimg_ulong unsigned long +#define cimg_long long +#endif + +#endif + +// Configure filename separator. +// +// Filename separator is set by default to '/', except for Windows where it is '\'. +#ifndef cimg_file_separator +#if cimg_OS==2 +#define cimg_file_separator '\\' +#else +#define cimg_file_separator '/' +#endif +#endif + +// Configure verbosity of output messages. +// +// Define 'cimg_verbosity' to: '0' to hide library messages (quiet mode). +// '1' to output library messages on the console. +// '2' to output library messages on a basic dialog window (default behavior). +// '3' to do as '1' + add extra warnings (may slow down the code!). +// '4' to do as '2' + add extra warnings (may slow down the code!). +// +// Define 'cimg_strict_warnings' to replace warning messages by exception throwns. +// +// Define 'cimg_use_vt100' to allow output of color messages on VT100-compatible terminals. +#ifndef cimg_verbosity +#if cimg_OS==2 +#define cimg_verbosity 2 +#else +#define cimg_verbosity 1 +#endif +#elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4) +#error CImg Library: Configuration variable 'cimg_verbosity' is badly defined. +#error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }). +#endif + +// Configure OpenMP support. +// (http://www.openmp.org) +// +// Define 'cimg_use_openmp' to enable OpenMP support (requires OpenMP 3.0+). +// +// OpenMP directives are used in many CImg functions to get +// advantages of multi-core CPUs. +#if !defined(cimg_use_openmp) +#ifdef _OPENMP +#define cimg_use_openmp 1 +#else +#define cimg_use_openmp 0 +#endif +#endif +#if cimg_use_openmp!=0 +#include +#define cimg_pragma_openmp(p) cimg_pragma(omp p) +#else +#define cimg_pragma_openmp(p) +#endif + +// Configure the 'abort' signal handler (does nothing by default). +// A typical signal handler can be defined in your own source like this: +// #define cimg_abort_test if (is_abort) throw CImgAbortException("") +// +// where 'is_abort' is a boolean variable defined somewhere in your code and reachable in the method. +// 'cimg_abort_test2' does the same but is called more often (in inner loops). +#if defined(cimg_abort_test) && cimg_use_openmp!=0 + +// Define abort macros to be used with OpenMP. +#ifndef _cimg_abort_init_openmp +#define _cimg_abort_init_openmp bool _cimg_abort_go_openmp = true; cimg::unused(_cimg_abort_go_openmp) +#endif +#ifndef _cimg_abort_try_openmp +#define _cimg_abort_try_openmp if (_cimg_abort_go_openmp) try +#endif +#ifndef _cimg_abort_catch_openmp +#define _cimg_abort_catch_openmp catch (CImgAbortException&) { cimg_pragma(omp atomic) _cimg_abort_go_openmp&=false; } +#endif +#ifndef _cimg_abort_catch_fill_openmp +#define _cimg_abort_catch_fill_openmp \ + catch (CImgException& e) { cimg_pragma(omp critical(abort)) CImg::string(e._message).move_to(is_error); \ + cimg_pragma(omp atomic) _cimg_abort_go_openmp&=false; } +#endif +#ifdef cimg_abort_test2 +#ifndef _cimg_abort_try_openmp2 +#define _cimg_abort_try_openmp2 _cimg_abort_try_openmp +#endif +#ifndef _cimg_abort_catch_openmp2 +#define _cimg_abort_catch_openmp2 _cimg_abort_catch_openmp +#endif +#endif +#endif + +#ifndef _cimg_abort_init_openmp +#define _cimg_abort_init_openmp +#endif +#ifndef _cimg_abort_try_openmp +#define _cimg_abort_try_openmp +#endif +#ifndef _cimg_abort_catch_openmp +#define _cimg_abort_catch_openmp +#endif +#ifndef _cimg_abort_try_openmp2 +#define _cimg_abort_try_openmp2 +#endif +#ifndef _cimg_abort_catch_openmp2 +#define _cimg_abort_catch_openmp2 +#endif +#ifndef _cimg_abort_catch_fill_openmp +#define _cimg_abort_catch_fill_openmp +#endif +#ifndef cimg_abort_init +#define cimg_abort_init +#endif +#ifndef cimg_abort_test +#define cimg_abort_test +#endif +#ifndef cimg_abort_test2 +#define cimg_abort_test2 +#endif + +// Configure display framework. +// +// Define 'cimg_display' to: '0' to disable display capabilities. +// '1' to use the X-Window framework (X11). +// '2' to use the Microsoft GDI32 framework. +#ifndef cimg_display +#if cimg_OS==0 +#define cimg_display 0 +#elif cimg_OS==1 +#define cimg_display 1 +#elif cimg_OS==2 +#define cimg_display 2 +#endif +#elif !(cimg_display==0 || cimg_display==1 || cimg_display==2) +#error CImg Library: Configuration variable 'cimg_display' is badly defined. +#error (should be { 0=none | 1=X-Window (X11) | 2=Microsoft GDI32 }). +#endif + +// Include display-specific headers. +#if cimg_display==1 +#include +#include +#include +#include +#ifdef cimg_use_xshm +#include +#include +#include +#endif +#ifdef cimg_use_xrandr +#include +#endif +#endif +#ifndef cimg_appname +#define cimg_appname "CImg" +#endif + +// Configure OpenCV support. +// (http://opencv.willowgarage.com/wiki/) +// +// Define 'cimg_use_opencv' to enable OpenCV support. +// +// OpenCV library may be used to access images from cameras +// (see method 'CImg::load_camera()'). +#ifdef cimg_use_opencv +#ifdef True +#undef True +#define _cimg_redefine_True +#endif +#ifdef False +#undef False +#define _cimg_redefine_False +#endif +#ifdef Status +#undef Status +#define _cimg_redefine_Status +#endif +#include +#include +#if CV_MAJOR_VERSION>=3 +#define _cimg_fourcc cv::VideoWriter::fourcc +#define _cimg_cap_prop_frame_width cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH +#define _cimg_cap_prop_frame_height cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT +#define _cimg_cap_prop_frame_count cv::VideoCaptureProperties::CAP_PROP_FRAME_COUNT +#else +#define _cimg_fourcc CV_FOURCC +#define _cimg_cap_prop_frame_width CV_CAP_PROP_FRAME_WIDTH +#define _cimg_cap_prop_frame_height CV_CAP_PROP_FRAME_HEIGHT +#define _cimg_cap_prop_frame_count CV_CAP_PROP_FRAME_COUNT +#endif +#endif + +// Configure LibPNG support. +// (http://www.libpng.org) +// +// Define 'cimg_use_png' to enable LibPNG support. +// +// PNG library may be used to get a native support of '.png' files. +// (see methods 'CImg::{load,save}_png()'. +#ifdef cimg_use_png +extern "C" { +#include "png.h" +} +#endif + +// Configure LibJPEG support. +// (http://en.wikipedia.org/wiki/Libjpeg) +// +// Define 'cimg_use_jpeg' to enable LibJPEG support. +// +// JPEG library may be used to get a native support of '.jpg' files. +// (see methods 'CImg::{load,save}_jpeg()'). +#ifdef cimg_use_jpeg +extern "C" { +#include "jpeglib.h" +#include "setjmp.h" +} +#endif + +// Configure LibTIFF support. +// (http://www.libtiff.org) +// +// Define 'cimg_use_tiff' to enable LibTIFF support. +// +// TIFF library may be used to get a native support of '.tif' files. +// (see methods 'CImg[List]::{load,save}_tiff()'). +#ifdef cimg_use_tiff +extern "C" { +#define uint64 uint64_hack_ +#define int64 int64_hack_ +#include "tiffio.h" +#undef uint64 +#undef int64 +} +#endif + +// Configure HEIF support +// (https://github.com/strukturag/libheif) +// +// Define 'cimg_use_heif' to enable HEIF support. +// +// HEIF library may be used to get a native support of '.heic' and '.avif' files. +// (see method 'CImg::load_heif()'). +#ifdef cimg_use_heif +#include +#endif + +// Configure LibMINC2 support. +// (http://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_File_Format_Reference) +// +// Define 'cimg_use_minc2' to enable LibMINC2 support. +// +// MINC2 library may be used to get a native support of '.mnc' files. +// (see methods 'CImg::{load,save}_minc2()'). +#ifdef cimg_use_minc2 +#include "minc_io_simple_volume.h" +#include "minc_1_simple.h" +#include "minc_1_simple_rw.h" +#endif + +// Configure Zlib support. +// (http://www.zlib.net) +// +// Define 'cimg_use_zlib' to enable Zlib support. +// +// Zlib library may be used to allow compressed data in '.cimgz' files +// (see methods 'CImg[List]::{load,save}_cimg()'). +#ifdef cimg_use_zlib +extern "C" { +#include "zlib.h" +} +#endif + +// Configure libcurl support. +// (http://curl.haxx.se/libcurl/) +// +// Define 'cimg_use_curl' to enable libcurl support. +// +// Libcurl may be used to get a native support of file downloading from the network. +// (see method 'cimg::load_network()'.) +#ifdef cimg_use_curl +#include "curl/curl.h" +#endif + +// Configure Magick++ support. +// (http://www.imagemagick.org/Magick++) +// +// Define 'cimg_use_magick' to enable Magick++ support. +// +// Magick++ library may be used to get a native support of various image file formats. +// (see methods 'CImg::{load,save}()'). +#ifdef cimg_use_magick +#include "Magick++.h" +#endif + +// Configure FFTW3 support. +// (http://www.fftw.org) +// +// Define 'cimg_use_fftw3' to enable libFFTW3 support. +// +// FFTW3 library may be used to efficiently compute the Fast Fourier Transform +// of image data, without restriction on the image size. +// (see method 'CImg[List]::FFT()'). +#ifdef cimg_use_fftw3 +extern "C" { +#include "fftw3.h" +} +#endif + +// Configure LibBoard support. +// (http://libboard.sourceforge.net/) +// +// Define 'cimg_use_board' to enable Board support. +// +// Board library may be used to draw 3D objects in vector-graphics canvas +// that can be saved as '.ps' or '.svg' files afterwards. +// (see method 'CImg::draw_object3d()'). +#ifdef cimg_use_board +#include "Board.h" +#endif + +// Configure OpenEXR support. +// (http://www.openexr.com/) +// +// Define 'cimg_use_openexr' to enable OpenEXR support. +// +// OpenEXR library may be used to get a native support of '.exr' files. +// (see methods 'CImg::{load,save}_exr()'). +#ifdef cimg_use_openexr +#if __GNUC__>=5 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wshadow" +#endif +#include "ImfRgbaFile.h" +#include "ImfInputFile.h" +#include "ImfChannelList.h" +#include "ImfMatrixAttribute.h" +#include "ImfArray.h" +#if __GNUC__>=5 +#pragma GCC diagnostic pop +#endif +#endif + +// Configure TinyEXR support. +// (https://github.com/syoyo/tinyexr) +// +// Define 'cimg_use_tinyexr' to enable TinyEXR support. +// +// TinyEXR is a small, single header-only library to load and save OpenEXR(.exr) images. +#ifdef cimg_use_tinyexr +#ifndef TINYEXR_IMPLEMENTATION +#define TINYEXR_IMPLEMENTATION +#endif +#include "tinyexr.h" +#endif + +// Lapack configuration. +// (http://www.netlib.org/lapack) +// +// Define 'cimg_use_lapack' to enable LAPACK support. +// +// Lapack library may be used in several CImg methods to speed up +// matrix computations (eigenvalues, inverse, ...). +#ifdef cimg_use_lapack +extern "C" { + extern void sgetrf_(int*, int*, float*, int*, int*, int*); + extern void sgetri_(int*, float*, int*, int*, float*, int*, int*); + extern void sgetrs_(char*, int*, int*, float*, int*, int*, float*, int*, int*); + extern void sgesvd_(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*); + extern void ssyev_(char*, char*, int*, float*, int*, float*, float*, int*, int*); + extern void dgetrf_(int*, int*, double*, int*, int*, int*); + extern void dgetri_(int*, double*, int*, int*, double*, int*, int*); + extern void dgetrs_(char*, int*, int*, double*, int*, int*, double*, int*, int*); + extern void dgesvd_(char*, char*, int*, int*, double*, int*, double*, double*, + int*, double*, int*, double*, int*, int*); + extern void dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*); + extern void dgels_(char*, int*,int*,int*,double*,int*,double*,int*,double*,int*,int*); + extern void sgels_(char*, int*,int*,int*,float*,int*,float*,int*,float*,int*,int*); +} +#endif + +// Check if min/max/PI macros are defined. +// +// CImg does not compile if macros 'min', 'max' or 'PI' are defined, +// because it redefines functions min(), max() and const variable PI in the cimg:: namespace. +// so it '#undef' these macros if necessary, and restore them to reasonable +// values at the end of this file. +#ifdef min +#undef min +#define _cimg_redefine_min +#endif +#ifdef max +#undef max +#define _cimg_redefine_max +#endif +#ifdef PI +#undef PI +#define _cimg_redefine_PI +#endif + +// Define 'cimg_library' namespace suffix. +// +// You may want to add a suffix to the 'cimg_library' namespace, for instance if you need to work +// with several versions of the library at the same time. +#ifdef cimg_namespace_suffix +#define __cimg_library_suffixed(s) cimg_library_##s +#define _cimg_library_suffixed(s) __cimg_library_suffixed(s) +#define cimg_library_suffixed _cimg_library_suffixed(cimg_namespace_suffix) +#else +#define cimg_library_suffixed cimg_library +#endif + +/*------------------------------------------------------------------------------ + # + # Define user-friendly macros. + # + # These CImg macros are prefixed by 'cimg_' and can be used safely in your own + # code. They are useful to parse command line options, or to write image loops. + # + ------------------------------------------------------------------------------*/ + +// Macros to define program usage, and retrieve command line arguments. +#define cimg_usage(usage) cimg_library_suffixed::cimg::option((char*)0,argc,argv,(char*)0,usage,false) +#define cimg_help(str) cimg_library_suffixed::cimg::option((char*)0,argc,argv,str,(char*)0) +#define cimg_option(name,_default,usage) cimg_library_suffixed::cimg::option(name,argc,argv,_default,usage) + +// Macros to define and manipulate local neighborhoods. +#define CImg_2x2(I,T) T I[4]; \ + T& I##cc = I[0]; T& I##nc = I[1]; \ + T& I##cn = I[2]; T& I##nn = I[3]; \ + I##cc = I##nc = \ + I##cn = I##nn = 0 + +#define CImg_3x3(I,T) T I[9]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; \ + T& I##pc = I[3]; T& I##cc = I[4]; T& I##nc = I[5]; \ + T& I##pn = I[6]; T& I##cn = I[7]; T& I##nn = I[8]; \ + I##pp = I##cp = I##np = \ + I##pc = I##cc = I##nc = \ + I##pn = I##cn = I##nn = 0 + +#define CImg_4x4(I,T) T I[16]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; T& I##ap = I[3]; \ + T& I##pc = I[4]; T& I##cc = I[5]; T& I##nc = I[6]; T& I##ac = I[7]; \ + T& I##pn = I[8]; T& I##cn = I[9]; T& I##nn = I[10]; T& I##an = I[11]; \ + T& I##pa = I[12]; T& I##ca = I[13]; T& I##na = I[14]; T& I##aa = I[15]; \ + I##pp = I##cp = I##np = I##ap = \ + I##pc = I##cc = I##nc = I##ac = \ + I##pn = I##cn = I##nn = I##an = \ + I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_5x5(I,T) T I[25]; \ + T& I##bb = I[0]; T& I##pb = I[1]; T& I##cb = I[2]; T& I##nb = I[3]; T& I##ab = I[4]; \ + T& I##bp = I[5]; T& I##pp = I[6]; T& I##cp = I[7]; T& I##np = I[8]; T& I##ap = I[9]; \ + T& I##bc = I[10]; T& I##pc = I[11]; T& I##cc = I[12]; T& I##nc = I[13]; T& I##ac = I[14]; \ + T& I##bn = I[15]; T& I##pn = I[16]; T& I##cn = I[17]; T& I##nn = I[18]; T& I##an = I[19]; \ + T& I##ba = I[20]; T& I##pa = I[21]; T& I##ca = I[22]; T& I##na = I[23]; T& I##aa = I[24]; \ + I##bb = I##pb = I##cb = I##nb = I##ab = \ + I##bp = I##pp = I##cp = I##np = I##ap = \ + I##bc = I##pc = I##cc = I##nc = I##ac = \ + I##bn = I##pn = I##cn = I##nn = I##an = \ + I##ba = I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_2x2x2(I,T) T I[8]; \ + T& I##ccc = I[0]; T& I##ncc = I[1]; \ + T& I##cnc = I[2]; T& I##nnc = I[3]; \ + T& I##ccn = I[4]; T& I##ncn = I[5]; \ + T& I##cnn = I[6]; T& I##nnn = I[7]; \ + I##ccc = I##ncc = \ + I##cnc = I##nnc = \ + I##ccn = I##ncn = \ + I##cnn = I##nnn = 0 + +#define CImg_3x3x3(I,T) T I[27]; \ + T& I##ppp = I[0]; T& I##cpp = I[1]; T& I##npp = I[2]; \ + T& I##pcp = I[3]; T& I##ccp = I[4]; T& I##ncp = I[5]; \ + T& I##pnp = I[6]; T& I##cnp = I[7]; T& I##nnp = I[8]; \ + T& I##ppc = I[9]; T& I##cpc = I[10]; T& I##npc = I[11]; \ + T& I##pcc = I[12]; T& I##ccc = I[13]; T& I##ncc = I[14]; \ + T& I##pnc = I[15]; T& I##cnc = I[16]; T& I##nnc = I[17]; \ + T& I##ppn = I[18]; T& I##cpn = I[19]; T& I##npn = I[20]; \ + T& I##pcn = I[21]; T& I##ccn = I[22]; T& I##ncn = I[23]; \ + T& I##pnn = I[24]; T& I##cnn = I[25]; T& I##nnn = I[26]; \ + I##ppp = I##cpp = I##npp = \ + I##pcp = I##ccp = I##ncp = \ + I##pnp = I##cnp = I##nnp = \ + I##ppc = I##cpc = I##npc = \ + I##pcc = I##ccc = I##ncc = \ + I##pnc = I##cnc = I##nnc = \ + I##ppn = I##cpn = I##npn = \ + I##pcn = I##ccn = I##ncn = \ + I##pnn = I##cnn = I##nnn = 0 + +#define cimg_def2x2(img,x,y) \ + int _n1##x = x<(img).width() - 1?x + 1:(img).width() - 1, \ + _n1##y = y<(img).height() - 1?y + 1:(img).height() - 1 + +#define cimg_def3x3(img,x,y) \ + cimg_def2x2(img,x,y); \ + int _p1##x = x>1?x - 1:0, \ + _p1##y = y>1?y - 1:0 + +#define cimg_def4x4(img,x,y) \ + cimg_def3x3(img,x,y); \ + int _n2##x = x<(img).width() - 2?x + 2:(img).width() - 1, \ + _n2##y = y<(img).height() - 2?y + 2:(img).height() - 1 + +#define cimg_def5x5(img,x,y) \ + cimg_def4x4(img,x,y); \ + int _p2##x = x>2?x - 2:0, \ + _p2##y = y>2?y - 2:0 + +#define cimg_def6x6(img,x,y) \ + cimg_def5x5(img,x,y); \ + int _n3##x = x<(img).width() - 3?x + 3:(img).width() - 1, \ + _n3##y = y<(img).height() - 3?y + 3:(img).height() - 1 + +#define cimg_def7x7(img,x,y) \ + cimg_def6x6(img,x,y); \ + int _p3##x = x>3?x - 3:0, \ + _p3##y = y>3?y - 3:0 + +#define cimg_def8x8(img,x,y) \ + cimg_def7x7(img,x,y); \ + int _n4##x = x<(img).width() - 4?x + 4:(img).width() - 1, \ + _n4##y = y<(img).height() - 4?y + 4:(img).height() - 1 + +#define cimg_def9x9(img,x,y) \ + cimg_def8x8(img,x,y); \ + int _p4##x = x>4?x - 4:0, \ + _p4##y = y>4?y - 4:0 + +#define cimg_def2x2x2(img,x,y,z) \ + cimg_def2x2(img,x,y); \ + int _n1##z = z<(img).depth() - 1?z + 1:(img).depth() - 1 + +#define cimg_def3x3x3(img,x,y,z) \ + cimg_def2x2x2(img,x,y,z); \ + int _p1##x = x>1?x - 1:0, \ + _p1##y = y>1?y - 1:0, \ + _p1##z = z>1?z - 1:0 + +#define cimg_get2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_p1##x,y,z,c), I[4] = (T)(img)(x,y,z,c), I[5] = (T)(img)(_n1##x,y,z,c), \ + I[6] = (T)(img)(_p1##x,_n1##y,z,c), I[7] = (T)(img)(x,_n1##y,z,c), I[8] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get4x4(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_n2##x,_p1##y,z,c), I[4] = (T)(img)(_p1##x,y,z,c), I[5] = (T)(img)(x,y,z,c), \ + I[6] = (T)(img)(_n1##x,y,z,c), I[7] = (T)(img)(_n2##x,y,z,c), I[8] = (T)(img)(_p1##x,_n1##y,z,c), \ + I[9] = (T)(img)(x,_n1##y,z,c), I[10] = (T)(img)(_n1##x,_n1##y,z,c), I[11] = (T)(img)(_n2##x,_n1##y,z,c), \ + I[12] = (T)(img)(_p1##x,_n2##y,z,c), I[13] = (T)(img)(x,_n2##y,z,c), I[14] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[15] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get5x5(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[6] = (T)(img)(_p1##x,_p1##y,z,c), I[7] = (T)(img)(x,_p1##y,z,c), I[8] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[9] = (T)(img)(_n2##x,_p1##y,z,c), I[10] = (T)(img)(_p2##x,y,z,c), I[11] = (T)(img)(_p1##x,y,z,c), \ + I[12] = (T)(img)(x,y,z,c), I[13] = (T)(img)(_n1##x,y,z,c), I[14] = (T)(img)(_n2##x,y,z,c), \ + I[15] = (T)(img)(_p2##x,_n1##y,z,c), I[16] = (T)(img)(_p1##x,_n1##y,z,c), I[17] = (T)(img)(x,_n1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_n1##y,z,c), I[19] = (T)(img)(_n2##x,_n1##y,z,c), I[20] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_n2##y,z,c), I[22] = (T)(img)(x,_n2##y,z,c), I[23] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get6x6(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[6] = (T)(img)(_p2##x,_p1##y,z,c), I[7] = (T)(img)(_p1##x,_p1##y,z,c), I[8] = (T)(img)(x,_p1##y,z,c), \ + I[9] = (T)(img)(_n1##x,_p1##y,z,c), I[10] = (T)(img)(_n2##x,_p1##y,z,c), I[11] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[12] = (T)(img)(_p2##x,y,z,c), I[13] = (T)(img)(_p1##x,y,z,c), I[14] = (T)(img)(x,y,z,c), \ + I[15] = (T)(img)(_n1##x,y,z,c), I[16] = (T)(img)(_n2##x,y,z,c), I[17] = (T)(img)(_n3##x,y,z,c), \ + I[18] = (T)(img)(_p2##x,_n1##y,z,c), I[19] = (T)(img)(_p1##x,_n1##y,z,c), I[20] = (T)(img)(x,_n1##y,z,c), \ + I[21] = (T)(img)(_n1##x,_n1##y,z,c), I[22] = (T)(img)(_n2##x,_n1##y,z,c), I[23] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[24] = (T)(img)(_p2##x,_n2##y,z,c), I[25] = (T)(img)(_p1##x,_n2##y,z,c), I[26] = (T)(img)(x,_n2##y,z,c), \ + I[27] = (T)(img)(_n1##x,_n2##y,z,c), I[28] = (T)(img)(_n2##x,_n2##y,z,c), I[29] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[30] = (T)(img)(_p2##x,_n3##y,z,c), I[31] = (T)(img)(_p1##x,_n3##y,z,c), I[32] = (T)(img)(x,_n3##y,z,c), \ + I[33] = (T)(img)(_n1##x,_n3##y,z,c), I[34] = (T)(img)(_n2##x,_n3##y,z,c), I[35] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get7x7(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_p3##x,_p2##y,z,c), I[8] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p1##x,_p2##y,z,c), I[10] = (T)(img)(x,_p2##y,z,c), I[11] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[12] = (T)(img)(_n2##x,_p2##y,z,c), I[13] = (T)(img)(_n3##x,_p2##y,z,c), I[14] = (T)(img)(_p3##x,_p1##y,z,c), \ + I[15] = (T)(img)(_p2##x,_p1##y,z,c), I[16] = (T)(img)(_p1##x,_p1##y,z,c), I[17] = (T)(img)(x,_p1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_p1##y,z,c), I[19] = (T)(img)(_n2##x,_p1##y,z,c), I[20] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[21] = (T)(img)(_p3##x,y,z,c), I[22] = (T)(img)(_p2##x,y,z,c), I[23] = (T)(img)(_p1##x,y,z,c), \ + I[24] = (T)(img)(x,y,z,c), I[25] = (T)(img)(_n1##x,y,z,c), I[26] = (T)(img)(_n2##x,y,z,c), \ + I[27] = (T)(img)(_n3##x,y,z,c), I[28] = (T)(img)(_p3##x,_n1##y,z,c), I[29] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_n1##y,z,c), I[31] = (T)(img)(x,_n1##y,z,c), I[32] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_n1##y,z,c), I[34] = (T)(img)(_n3##x,_n1##y,z,c), I[35] = (T)(img)(_p3##x,_n2##y,z,c), \ + I[36] = (T)(img)(_p2##x,_n2##y,z,c), I[37] = (T)(img)(_p1##x,_n2##y,z,c), I[38] = (T)(img)(x,_n2##y,z,c), \ + I[39] = (T)(img)(_n1##x,_n2##y,z,c), I[40] = (T)(img)(_n2##x,_n2##y,z,c), I[41] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p3##x,_n3##y,z,c), I[43] = (T)(img)(_p2##x,_n3##y,z,c), I[44] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[45] = (T)(img)(x,_n3##y,z,c), I[46] = (T)(img)(_n1##x,_n3##y,z,c), I[47] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[48] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get8x8(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_n4##x,_p3##y,z,c), I[8] = (T)(img)(_p3##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p2##x,_p2##y,z,c), I[10] = (T)(img)(_p1##x,_p2##y,z,c), I[11] = (T)(img)(x,_p2##y,z,c), \ + I[12] = (T)(img)(_n1##x,_p2##y,z,c), I[13] = (T)(img)(_n2##x,_p2##y,z,c), I[14] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[15] = (T)(img)(_n4##x,_p2##y,z,c), I[16] = (T)(img)(_p3##x,_p1##y,z,c), I[17] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[18] = (T)(img)(_p1##x,_p1##y,z,c), I[19] = (T)(img)(x,_p1##y,z,c), I[20] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[21] = (T)(img)(_n2##x,_p1##y,z,c), I[22] = (T)(img)(_n3##x,_p1##y,z,c), I[23] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[24] = (T)(img)(_p3##x,y,z,c), I[25] = (T)(img)(_p2##x,y,z,c), I[26] = (T)(img)(_p1##x,y,z,c), \ + I[27] = (T)(img)(x,y,z,c), I[28] = (T)(img)(_n1##x,y,z,c), I[29] = (T)(img)(_n2##x,y,z,c), \ + I[30] = (T)(img)(_n3##x,y,z,c), I[31] = (T)(img)(_n4##x,y,z,c), I[32] = (T)(img)(_p3##x,_n1##y,z,c), \ + I[33] = (T)(img)(_p2##x,_n1##y,z,c), I[34] = (T)(img)(_p1##x,_n1##y,z,c), I[35] = (T)(img)(x,_n1##y,z,c), \ + I[36] = (T)(img)(_n1##x,_n1##y,z,c), I[37] = (T)(img)(_n2##x,_n1##y,z,c), I[38] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[39] = (T)(img)(_n4##x,_n1##y,z,c), I[40] = (T)(img)(_p3##x,_n2##y,z,c), I[41] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p1##x,_n2##y,z,c), I[43] = (T)(img)(x,_n2##y,z,c), I[44] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[45] = (T)(img)(_n2##x,_n2##y,z,c), I[46] = (T)(img)(_n3##x,_n2##y,z,c), I[47] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[48] = (T)(img)(_p3##x,_n3##y,z,c), I[49] = (T)(img)(_p2##x,_n3##y,z,c), I[50] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[51] = (T)(img)(x,_n3##y,z,c), I[52] = (T)(img)(_n1##x,_n3##y,z,c), I[53] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[54] = (T)(img)(_n3##x,_n3##y,z,c), I[55] = (T)(img)(_n4##x,_n3##y,z,c), I[56] = (T)(img)(_p3##x,_n4##y,z,c), \ + I[57] = (T)(img)(_p2##x,_n4##y,z,c), I[58] = (T)(img)(_p1##x,_n4##y,z,c), I[59] = (T)(img)(x,_n4##y,z,c), \ + I[60] = (T)(img)(_n1##x,_n4##y,z,c), I[61] = (T)(img)(_n2##x,_n4##y,z,c), I[62] = (T)(img)(_n3##x,_n4##y,z,c), \ + I[63] = (T)(img)(_n4##x,_n4##y,z,c); + +#define cimg_get9x9(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p4##x,_p4##y,z,c), I[1] = (T)(img)(_p3##x,_p4##y,z,c), I[2] = (T)(img)(_p2##x,_p4##y,z,c), \ + I[3] = (T)(img)(_p1##x,_p4##y,z,c), I[4] = (T)(img)(x,_p4##y,z,c), I[5] = (T)(img)(_n1##x,_p4##y,z,c), \ + I[6] = (T)(img)(_n2##x,_p4##y,z,c), I[7] = (T)(img)(_n3##x,_p4##y,z,c), I[8] = (T)(img)(_n4##x,_p4##y,z,c), \ + I[9] = (T)(img)(_p4##x,_p3##y,z,c), I[10] = (T)(img)(_p3##x,_p3##y,z,c), I[11] = (T)(img)(_p2##x,_p3##y,z,c), \ + I[12] = (T)(img)(_p1##x,_p3##y,z,c), I[13] = (T)(img)(x,_p3##y,z,c), I[14] = (T)(img)(_n1##x,_p3##y,z,c), \ + I[15] = (T)(img)(_n2##x,_p3##y,z,c), I[16] = (T)(img)(_n3##x,_p3##y,z,c), I[17] = (T)(img)(_n4##x,_p3##y,z,c), \ + I[18] = (T)(img)(_p4##x,_p2##y,z,c), I[19] = (T)(img)(_p3##x,_p2##y,z,c), I[20] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_p2##y,z,c), I[22] = (T)(img)(x,_p2##y,z,c), I[23] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_p2##y,z,c), I[25] = (T)(img)(_n3##x,_p2##y,z,c), I[26] = (T)(img)(_n4##x,_p2##y,z,c), \ + I[27] = (T)(img)(_p4##x,_p1##y,z,c), I[28] = (T)(img)(_p3##x,_p1##y,z,c), I[29] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_p1##y,z,c), I[31] = (T)(img)(x,_p1##y,z,c), I[32] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_p1##y,z,c), I[34] = (T)(img)(_n3##x,_p1##y,z,c), I[35] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[36] = (T)(img)(_p4##x,y,z,c), I[37] = (T)(img)(_p3##x,y,z,c), I[38] = (T)(img)(_p2##x,y,z,c), \ + I[39] = (T)(img)(_p1##x,y,z,c), I[40] = (T)(img)(x,y,z,c), I[41] = (T)(img)(_n1##x,y,z,c), \ + I[42] = (T)(img)(_n2##x,y,z,c), I[43] = (T)(img)(_n3##x,y,z,c), I[44] = (T)(img)(_n4##x,y,z,c), \ + I[45] = (T)(img)(_p4##x,_n1##y,z,c), I[46] = (T)(img)(_p3##x,_n1##y,z,c), I[47] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[48] = (T)(img)(_p1##x,_n1##y,z,c), I[49] = (T)(img)(x,_n1##y,z,c), I[50] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[51] = (T)(img)(_n2##x,_n1##y,z,c), I[52] = (T)(img)(_n3##x,_n1##y,z,c), I[53] = (T)(img)(_n4##x,_n1##y,z,c), \ + I[54] = (T)(img)(_p4##x,_n2##y,z,c), I[55] = (T)(img)(_p3##x,_n2##y,z,c), I[56] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[57] = (T)(img)(_p1##x,_n2##y,z,c), I[58] = (T)(img)(x,_n2##y,z,c), I[59] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[60] = (T)(img)(_n2##x,_n2##y,z,c), I[61] = (T)(img)(_n3##x,_n2##y,z,c), I[62] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[63] = (T)(img)(_p4##x,_n3##y,z,c), I[64] = (T)(img)(_p3##x,_n3##y,z,c), I[65] = (T)(img)(_p2##x,_n3##y,z,c), \ + I[66] = (T)(img)(_p1##x,_n3##y,z,c), I[67] = (T)(img)(x,_n3##y,z,c), I[68] = (T)(img)(_n1##x,_n3##y,z,c), \ + I[69] = (T)(img)(_n2##x,_n3##y,z,c), I[70] = (T)(img)(_n3##x,_n3##y,z,c), I[71] = (T)(img)(_n4##x,_n3##y,z,c), \ + I[72] = (T)(img)(_p4##x,_n4##y,z,c), I[73] = (T)(img)(_p3##x,_n4##y,z,c), I[74] = (T)(img)(_p2##x,_n4##y,z,c), \ + I[75] = (T)(img)(_p1##x,_n4##y,z,c), I[76] = (T)(img)(x,_n4##y,z,c), I[77] = (T)(img)(_n1##x,_n4##y,z,c), \ + I[78] = (T)(img)(_n2##x,_n4##y,z,c), I[79] = (T)(img)(_n3##x,_n4##y,z,c), I[80] = (T)(img)(_n4##x,_n4##y,z,c) + +#define cimg_get2x2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c), I[4] = (T)(img)(x,y,_n1##z,c), I[5] = (T)(img)(_n1##x,y,_n1##z,c), \ + I[6] = (T)(img)(x,_n1##y,_n1##z,c), I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +#define cimg_get3x3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c), I[1] = (T)(img)(x,_p1##y,_p1##z,c), \ + I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c), I[3] = (T)(img)(_p1##x,y,_p1##z,c), I[4] = (T)(img)(x,y,_p1##z,c), \ + I[5] = (T)(img)(_n1##x,y,_p1##z,c), I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c), I[7] = (T)(img)(x,_n1##y,_p1##z,c), \ + I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c), I[9] = (T)(img)(_p1##x,_p1##y,z,c), I[10] = (T)(img)(x,_p1##y,z,c), \ + I[11] = (T)(img)(_n1##x,_p1##y,z,c), I[12] = (T)(img)(_p1##x,y,z,c), I[13] = (T)(img)(x,y,z,c), \ + I[14] = (T)(img)(_n1##x,y,z,c), I[15] = (T)(img)(_p1##x,_n1##y,z,c), I[16] = (T)(img)(x,_n1##y,z,c), \ + I[17] = (T)(img)(_n1##x,_n1##y,z,c), I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c), I[19] = (T)(img)(x,_p1##y,_n1##z,c), \ + I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c), I[21] = (T)(img)(_p1##x,y,_n1##z,c), I[22] = (T)(img)(x,y,_n1##z,c), \ + I[23] = (T)(img)(_n1##x,y,_n1##z,c), I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c), I[25] = (T)(img)(x,_n1##y,_n1##z,c), \ + I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +// Macros to perform various image loops. +// +// These macros are simpler to use than loops with C++ iterators. +#define cimg_for(img,ptrs,T_ptrs) \ + for (T_ptrs *ptrs = (img)._data, *_max##ptrs = (img)._data + (img).size(); ptrs<_max##ptrs; ++ptrs) +#define cimg_rof(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size() - 1; ptrs>=(img)._data; --ptrs) +#define cimg_foroff(img,off) for (cimg_ulong off = 0, _max##off = (img).size(); off<_max##off; ++off) +#define cimg_rofoff(img,off) for (cimg_long off = (cimg_long)((img).size() - 1); off>=0; --off) + +#define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i) +#define cimg_forX(img,x) cimg_for1((img)._width,x) +#define cimg_forY(img,y) cimg_for1((img)._height,y) +#define cimg_forZ(img,z) cimg_for1((img)._depth,z) +#define cimg_forC(img,c) cimg_for1((img)._spectrum,c) +#define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x) +#define cimg_forXZ(img,x,z) cimg_forZ(img,z) cimg_forX(img,x) +#define cimg_forYZ(img,y,z) cimg_forZ(img,z) cimg_forY(img,y) +#define cimg_forXC(img,x,c) cimg_forC(img,c) cimg_forX(img,x) +#define cimg_forYC(img,y,c) cimg_forC(img,c) cimg_forY(img,y) +#define cimg_forZC(img,z,c) cimg_forC(img,c) cimg_forZ(img,z) +#define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y) +#define cimg_forXYC(img,x,y,c) cimg_forC(img,c) cimg_forXY(img,x,y) +#define cimg_forXZC(img,x,z,c) cimg_forC(img,c) cimg_forXZ(img,x,z) +#define cimg_forYZC(img,y,z,c) cimg_forC(img,c) cimg_forYZ(img,y,z) +#define cimg_forXYZC(img,x,y,z,c) cimg_forC(img,c) cimg_forXYZ(img,x,y,z) + +#define cimg_rof1(bound,i) for (int i = (int)(bound) - 1; i>=0; --i) +#define cimg_rofX(img,x) cimg_rof1((img)._width,x) +#define cimg_rofY(img,y) cimg_rof1((img)._height,y) +#define cimg_rofZ(img,z) cimg_rof1((img)._depth,z) +#define cimg_rofC(img,c) cimg_rof1((img)._spectrum,c) +#define cimg_rofXY(img,x,y) cimg_rofY(img,y) cimg_rofX(img,x) +#define cimg_rofXZ(img,x,z) cimg_rofZ(img,z) cimg_rofX(img,x) +#define cimg_rofYZ(img,y,z) cimg_rofZ(img,z) cimg_rofY(img,y) +#define cimg_rofXC(img,x,c) cimg_rofC(img,c) cimg_rofX(img,x) +#define cimg_rofYC(img,y,c) cimg_rofC(img,c) cimg_rofY(img,y) +#define cimg_rofZC(img,z,c) cimg_rofC(img,c) cimg_rofZ(img,z) +#define cimg_rofXYZ(img,x,y,z) cimg_rofZ(img,z) cimg_rofXY(img,x,y) +#define cimg_rofXYC(img,x,y,c) cimg_rofC(img,c) cimg_rofXY(img,x,y) +#define cimg_rofXZC(img,x,z,c) cimg_rofC(img,c) cimg_rofXZ(img,x,z) +#define cimg_rofYZC(img,y,z,c) cimg_rofC(img,c) cimg_rofYZ(img,y,z) +#define cimg_rofXYZC(img,x,y,z,c) cimg_rofC(img,c) cimg_rofXYZ(img,x,y,z) + +#define cimg_for_in1(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), _max##i = (int)(i1)<(int)(bound)?(int)(i1):(int)(bound) - 1; i<=_max##i; ++i) +#define cimg_for_inX(img,x0,x1,x) cimg_for_in1((img)._width,x0,x1,x) +#define cimg_for_inY(img,y0,y1,y) cimg_for_in1((img)._height,y0,y1,y) +#define cimg_for_inZ(img,z0,z1,z) cimg_for_in1((img)._depth,z0,z1,z) +#define cimg_for_inC(img,c0,c1,c) cimg_for_in1((img)._spectrum,c0,c1,c) +#define cimg_for_inXY(img,x0,y0,x1,y1,x,y) cimg_for_inY(img,y0,y1,y) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXZ(img,x0,z0,x1,z1,x,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXC(img,x0,c0,x1,c1,x,c) cimg_for_inC(img,c0,c1,c) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inYZ(img,y0,z0,y1,z1,y,z) cimg_for_inZ(img,x0,z1,z) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inYC(img,y0,c0,y1,c1,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inZC(img,z0,c0,z1,c1,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inZ(img,z0,z1,z) +#define cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXZ(img,x0,z0,x1,z1,x,z) +#define cimg_for_inYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inYZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_inXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_inC(img,c0,c1,c) cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_insideX(img,x,n) cimg_for_inX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_insideY(img,y,n) cimg_for_inY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_insideZ(img,z,n) cimg_for_inZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_insideC(img,c,n) cimg_for_inC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_insideXY(img,x,y,n) cimg_for_inXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_insideXYZ(img,x,y,z,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_insideXYZC(img,x,y,z,c,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) + +#define cimg_for_out1(boundi,i0,i1,i) \ + for (int i = (int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); ++i, i = i==(int)(i0)?(int)(i1) + 1:i) +#define cimg_for_out2(boundi,boundj,i0,j0,i1,j1,i,j) \ + for (int j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out3(boundi,boundj,boundk,i0,j0,k0,i1,j1,k1,i,j,k) \ + for (int k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j || _n1k?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out4(boundi,boundj,boundk,boundl,i0,j0,k0,l0,i1,j1,k1,l1,i,j,k,l) \ + for (int l = 0; l<(int)(boundl); ++l) \ + for (int _n1l = (int)(l<(int)(l0) || l>(int)(l1)), k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k || _n1l?0:(int)(i0)>0?0:(int)(i1) + 1; \ + i<(int)(boundi); ++i, i = _n1j || _n1k || _n1l?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_outX(img,x0,x1,x) cimg_for_out1((img)._width,x0,x1,x) +#define cimg_for_outY(img,y0,y1,y) cimg_for_out1((img)._height,y0,y1,y) +#define cimg_for_outZ(img,z0,z1,z) cimg_for_out1((img)._depth,z0,z1,z) +#define cimg_for_outC(img,c0,c1,c) cimg_for_out1((img)._spectrum,c0,c1,c) +#define cimg_for_outXY(img,x0,y0,x1,y1,x,y) cimg_for_out2((img)._width,(img)._height,x0,y0,x1,y1,x,y) +#define cimg_for_outXZ(img,x0,z0,x1,z1,x,z) cimg_for_out2((img)._width,(img)._depth,x0,z0,x1,z1,x,z) +#define cimg_for_outXC(img,x0,c0,x1,c1,x,c) cimg_for_out2((img)._width,(img)._spectrum,x0,c0,x1,c1,x,c) +#define cimg_for_outYZ(img,y0,z0,y1,z1,y,z) cimg_for_out2((img)._height,(img)._depth,y0,z0,y1,z1,y,z) +#define cimg_for_outYC(img,y0,c0,y1,c1,y,c) cimg_for_out2((img)._height,(img)._spectrum,y0,c0,y1,c1,y,c) +#define cimg_for_outZC(img,z0,c0,z1,c1,z,c) cimg_for_out2((img)._depth,(img)._spectrum,z0,c0,z1,c1,z,c) +#define cimg_for_outXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) \ + cimg_for_out3((img)._width,(img)._height,(img)._depth,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_outXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) \ + cimg_for_out3((img)._width,(img)._height,(img)._spectrum,x0,y0,c0,x1,y1,c1,x,y,c) +#define cimg_for_outXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) \ + cimg_for_out3((img)._width,(img)._depth,(img)._spectrum,x0,z0,c0,x1,z1,c1,x,z,c) +#define cimg_for_outYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) \ + cimg_for_out3((img)._height,(img)._depth,(img)._spectrum,y0,z0,c0,y1,z1,c1,y,z,c) +#define cimg_for_outXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_out4((img)._width,(img)._height,(img)._depth,(img)._spectrum,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) +#define cimg_for_borderX(img,x,n) cimg_for_outX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_borderY(img,y,n) cimg_for_outY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_borderZ(img,z,n) cimg_for_outZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_borderC(img,c,n) cimg_for_outC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_borderXY(img,x,y,n) cimg_for_outXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_borderXYZ(img,x,y,z,n) \ + cimg_for_outXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_borderXYZC(img,x,y,z,c,n) \ + cimg_for_outXYZC(img,n,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n), \ + (img)._depth - 1 - (n),(img)._spectrum - 1 - (n),x,y,z,c) + +#define cimg_for_spiralXY(img,x,y) \ + for (int x = 0, y = 0, _n1##x = 1, _n1##y = (img).width()*(img).height(); _n1##y; \ + --_n1##y, _n1##x+=(_n1##x>>2) - ((!(_n1##x&3)?--y:((_n1##x&3)==1?(img)._width - 1 - ++x:\ + ((_n1##x&3)==2?(img)._height - 1 - ++y:--x))))?0:1) + +#define cimg_for_lineXY(x,y,x0,y0,x1,y1) \ + for (int x = (int)(x0), y = (int)(y0), _sx = 1, _sy = 1, _steep = 0, \ + _dx=(x1)>(x0)?(int)(x1) - (int)(x0):(_sx=-1,(int)(x0) - (int)(x1)), \ + _dy=(y1)>(y0)?(int)(y1) - (int)(y0):(_sy=-1,(int)(y0) - (int)(y1)), \ + _counter = _dx, \ + _err = _dx>_dy?(_dy>>1):((_steep=1),(_counter=_dy),(_dx>>1)); \ + _counter>=0; \ + --_counter, x+=_steep? \ + (y+=_sy,(_err-=_dx)<0?_err+=_dy,_sx:0): \ + (y+=(_err-=_dy)<0?_err+=_dx,_sy:0,_sx)) + +#define cimg_for2(bound,i) \ + for (int i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + ++i, ++_n1##i) +#define cimg_for2X(img,x) cimg_for2((img)._width,x) +#define cimg_for2Y(img,y) cimg_for2((img)._height,y) +#define cimg_for2Z(img,z) cimg_for2((img)._depth,z) +#define cimg_for2C(img,c) cimg_for2((img)._spectrum,c) +#define cimg_for2XY(img,x,y) cimg_for2Y(img,y) cimg_for2X(img,x) +#define cimg_for2XZ(img,x,z) cimg_for2Z(img,z) cimg_for2X(img,x) +#define cimg_for2XC(img,x,c) cimg_for2C(img,c) cimg_for2X(img,x) +#define cimg_for2YZ(img,y,z) cimg_for2Z(img,z) cimg_for2Y(img,y) +#define cimg_for2YC(img,y,c) cimg_for2C(img,c) cimg_for2Y(img,y) +#define cimg_for2ZC(img,z,c) cimg_for2C(img,c) cimg_for2Z(img,z) +#define cimg_for2XYZ(img,x,y,z) cimg_for2Z(img,z) cimg_for2XY(img,x,y) +#define cimg_for2XZC(img,x,z,c) cimg_for2C(img,c) cimg_for2XZ(img,x,z) +#define cimg_for2YZC(img,y,z,c) cimg_for2C(img,c) cimg_for2YZ(img,y,z) +#define cimg_for2XYZC(img,x,y,z,c) cimg_for2C(img,c) cimg_for2XYZ(img,x,y,z) + +#define cimg_for_in2(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + ++i, ++_n1##i) +#define cimg_for_in2X(img,x0,x1,x) cimg_for_in2((img)._width,x0,x1,x) +#define cimg_for_in2Y(img,y0,y1,y) cimg_for_in2((img)._height,y0,y1,y) +#define cimg_for_in2Z(img,z0,z1,z) cimg_for_in2((img)._depth,z0,z1,z) +#define cimg_for_in2C(img,c0,c1,c) cimg_for_in2((img)._spectrum,c0,c1,c) +#define cimg_for_in2XY(img,x0,y0,x1,y1,x,y) cimg_for_in2Y(img,y0,y1,y) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XZ(img,x0,z0,x1,z1,x,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XC(img,x0,c0,x1,c1,x,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2YC(img,y0,c0,y1,c1,y,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2ZC(img,z0,c0,z1,c1,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Z(img,z0,z1,z) +#define cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in2XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in2YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in2XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in2C(img,c0,c1,c) cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i) +#define cimg_for3X(img,x) cimg_for3((img)._width,x) +#define cimg_for3Y(img,y) cimg_for3((img)._height,y) +#define cimg_for3Z(img,z) cimg_for3((img)._depth,z) +#define cimg_for3C(img,c) cimg_for3((img)._spectrum,c) +#define cimg_for3XY(img,x,y) cimg_for3Y(img,y) cimg_for3X(img,x) +#define cimg_for3XZ(img,x,z) cimg_for3Z(img,z) cimg_for3X(img,x) +#define cimg_for3XC(img,x,c) cimg_for3C(img,c) cimg_for3X(img,x) +#define cimg_for3YZ(img,y,z) cimg_for3Z(img,z) cimg_for3Y(img,y) +#define cimg_for3YC(img,y,c) cimg_for3C(img,c) cimg_for3Y(img,y) +#define cimg_for3ZC(img,z,c) cimg_for3C(img,c) cimg_for3Z(img,z) +#define cimg_for3XYZ(img,x,y,z) cimg_for3Z(img,z) cimg_for3XY(img,x,y) +#define cimg_for3XZC(img,x,z,c) cimg_for3C(img,c) cimg_for3XZ(img,x,z) +#define cimg_for3YZC(img,y,z,c) cimg_for3C(img,c) cimg_for3YZ(img,y,z) +#define cimg_for3XYZC(img,x,y,z,c) cimg_for3C(img,c) cimg_for3XYZ(img,x,y,z) + +#define cimg_for_in3(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + _p1##i = i++, ++_n1##i) +#define cimg_for_in3X(img,x0,x1,x) cimg_for_in3((img)._width,x0,x1,x) +#define cimg_for_in3Y(img,y0,y1,y) cimg_for_in3((img)._height,y0,y1,y) +#define cimg_for_in3Z(img,z0,z1,z) cimg_for_in3((img)._depth,z0,z1,z) +#define cimg_for_in3C(img,c0,c1,c) cimg_for_in3((img)._spectrum,c0,c1,c) +#define cimg_for_in3XY(img,x0,y0,x1,y1,x,y) cimg_for_in3Y(img,y0,y1,y) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XZ(img,x0,z0,x1,z1,x,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XC(img,x0,c0,x1,c1,x,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3YC(img,y0,c0,y1,c1,y,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3ZC(img,z0,c0,z1,c1,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Z(img,z0,z1,z) +#define cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in3XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in3YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in3XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in3C(img,c0,c1,c) cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for4(bound,i) \ + for (int i = 0, _p1##i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for4X(img,x) cimg_for4((img)._width,x) +#define cimg_for4Y(img,y) cimg_for4((img)._height,y) +#define cimg_for4Z(img,z) cimg_for4((img)._depth,z) +#define cimg_for4C(img,c) cimg_for4((img)._spectrum,c) +#define cimg_for4XY(img,x,y) cimg_for4Y(img,y) cimg_for4X(img,x) +#define cimg_for4XZ(img,x,z) cimg_for4Z(img,z) cimg_for4X(img,x) +#define cimg_for4XC(img,x,c) cimg_for4C(img,c) cimg_for4X(img,x) +#define cimg_for4YZ(img,y,z) cimg_for4Z(img,z) cimg_for4Y(img,y) +#define cimg_for4YC(img,y,c) cimg_for4C(img,c) cimg_for4Y(img,y) +#define cimg_for4ZC(img,z,c) cimg_for4C(img,c) cimg_for4Z(img,z) +#define cimg_for4XYZ(img,x,y,z) cimg_for4Z(img,z) cimg_for4XY(img,x,y) +#define cimg_for4XZC(img,x,z,c) cimg_for4C(img,c) cimg_for4XZ(img,x,z) +#define cimg_for4YZC(img,y,z,c) cimg_for4C(img,c) cimg_for4YZ(img,y,z) +#define cimg_for4XYZC(img,x,y,z,c) cimg_for4C(img,c) cimg_for4XYZ(img,x,y,z) + +#define cimg_for_in4(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in4X(img,x0,x1,x) cimg_for_in4((img)._width,x0,x1,x) +#define cimg_for_in4Y(img,y0,y1,y) cimg_for_in4((img)._height,y0,y1,y) +#define cimg_for_in4Z(img,z0,z1,z) cimg_for_in4((img)._depth,z0,z1,z) +#define cimg_for_in4C(img,c0,c1,c) cimg_for_in4((img)._spectrum,c0,c1,c) +#define cimg_for_in4XY(img,x0,y0,x1,y1,x,y) cimg_for_in4Y(img,y0,y1,y) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XZ(img,x0,z0,x1,z1,x,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XC(img,x0,c0,x1,c1,x,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4YC(img,y0,c0,y1,c1,y,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4ZC(img,z0,c0,z1,c1,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Z(img,z0,z1,z) +#define cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in4XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in4YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in4XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in4C(img,c0,c1,c) cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for5(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for5X(img,x) cimg_for5((img)._width,x) +#define cimg_for5Y(img,y) cimg_for5((img)._height,y) +#define cimg_for5Z(img,z) cimg_for5((img)._depth,z) +#define cimg_for5C(img,c) cimg_for5((img)._spectrum,c) +#define cimg_for5XY(img,x,y) cimg_for5Y(img,y) cimg_for5X(img,x) +#define cimg_for5XZ(img,x,z) cimg_for5Z(img,z) cimg_for5X(img,x) +#define cimg_for5XC(img,x,c) cimg_for5C(img,c) cimg_for5X(img,x) +#define cimg_for5YZ(img,y,z) cimg_for5Z(img,z) cimg_for5Y(img,y) +#define cimg_for5YC(img,y,c) cimg_for5C(img,c) cimg_for5Y(img,y) +#define cimg_for5ZC(img,z,c) cimg_for5C(img,c) cimg_for5Z(img,z) +#define cimg_for5XYZ(img,x,y,z) cimg_for5Z(img,z) cimg_for5XY(img,x,y) +#define cimg_for5XZC(img,x,z,c) cimg_for5C(img,c) cimg_for5XZ(img,x,z) +#define cimg_for5YZC(img,y,z,c) cimg_for5C(img,c) cimg_for5YZ(img,y,z) +#define cimg_for5XYZC(img,x,y,z,c) cimg_for5C(img,c) cimg_for5XYZ(img,x,y,z) + +#define cimg_for_in5(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in5X(img,x0,x1,x) cimg_for_in5((img)._width,x0,x1,x) +#define cimg_for_in5Y(img,y0,y1,y) cimg_for_in5((img)._height,y0,y1,y) +#define cimg_for_in5Z(img,z0,z1,z) cimg_for_in5((img)._depth,z0,z1,z) +#define cimg_for_in5C(img,c0,c1,c) cimg_for_in5((img)._spectrum,c0,c1,c) +#define cimg_for_in5XY(img,x0,y0,x1,y1,x,y) cimg_for_in5Y(img,y0,y1,y) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XZ(img,x0,z0,x1,z1,x,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XC(img,x0,c0,x1,c1,x,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5YC(img,y0,c0,y1,c1,y,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5ZC(img,z0,c0,z1,c1,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Z(img,z0,z1,z) +#define cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in5XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in5YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in5XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in5C(img,c0,c1,c) cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for6(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for6X(img,x) cimg_for6((img)._width,x) +#define cimg_for6Y(img,y) cimg_for6((img)._height,y) +#define cimg_for6Z(img,z) cimg_for6((img)._depth,z) +#define cimg_for6C(img,c) cimg_for6((img)._spectrum,c) +#define cimg_for6XY(img,x,y) cimg_for6Y(img,y) cimg_for6X(img,x) +#define cimg_for6XZ(img,x,z) cimg_for6Z(img,z) cimg_for6X(img,x) +#define cimg_for6XC(img,x,c) cimg_for6C(img,c) cimg_for6X(img,x) +#define cimg_for6YZ(img,y,z) cimg_for6Z(img,z) cimg_for6Y(img,y) +#define cimg_for6YC(img,y,c) cimg_for6C(img,c) cimg_for6Y(img,y) +#define cimg_for6ZC(img,z,c) cimg_for6C(img,c) cimg_for6Z(img,z) +#define cimg_for6XYZ(img,x,y,z) cimg_for6Z(img,z) cimg_for6XY(img,x,y) +#define cimg_for6XZC(img,x,z,c) cimg_for6C(img,c) cimg_for6XZ(img,x,z) +#define cimg_for6YZC(img,y,z,c) cimg_for6C(img,c) cimg_for6YZ(img,y,z) +#define cimg_for6XYZC(img,x,y,z,c) cimg_for6C(img,c) cimg_for6XYZ(img,x,y,z) + +#define cimg_for_in6(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in6X(img,x0,x1,x) cimg_for_in6((img)._width,x0,x1,x) +#define cimg_for_in6Y(img,y0,y1,y) cimg_for_in6((img)._height,y0,y1,y) +#define cimg_for_in6Z(img,z0,z1,z) cimg_for_in6((img)._depth,z0,z1,z) +#define cimg_for_in6C(img,c0,c1,c) cimg_for_in6((img)._spectrum,c0,c1,c) +#define cimg_for_in6XY(img,x0,y0,x1,y1,x,y) cimg_for_in6Y(img,y0,y1,y) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XZ(img,x0,z0,x1,z1,x,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XC(img,x0,c0,x1,c1,x,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6YC(img,y0,c0,y1,c1,y,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6ZC(img,z0,c0,z1,c1,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Z(img,z0,z1,z) +#define cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in6XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in6YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in6XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in6C(img,c0,c1,c) cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for7(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for7X(img,x) cimg_for7((img)._width,x) +#define cimg_for7Y(img,y) cimg_for7((img)._height,y) +#define cimg_for7Z(img,z) cimg_for7((img)._depth,z) +#define cimg_for7C(img,c) cimg_for7((img)._spectrum,c) +#define cimg_for7XY(img,x,y) cimg_for7Y(img,y) cimg_for7X(img,x) +#define cimg_for7XZ(img,x,z) cimg_for7Z(img,z) cimg_for7X(img,x) +#define cimg_for7XC(img,x,c) cimg_for7C(img,c) cimg_for7X(img,x) +#define cimg_for7YZ(img,y,z) cimg_for7Z(img,z) cimg_for7Y(img,y) +#define cimg_for7YC(img,y,c) cimg_for7C(img,c) cimg_for7Y(img,y) +#define cimg_for7ZC(img,z,c) cimg_for7C(img,c) cimg_for7Z(img,z) +#define cimg_for7XYZ(img,x,y,z) cimg_for7Z(img,z) cimg_for7XY(img,x,y) +#define cimg_for7XZC(img,x,z,c) cimg_for7C(img,c) cimg_for7XZ(img,x,z) +#define cimg_for7YZC(img,y,z,c) cimg_for7C(img,c) cimg_for7YZ(img,y,z) +#define cimg_for7XYZC(img,x,y,z,c) cimg_for7C(img,c) cimg_for7XYZ(img,x,y,z) + +#define cimg_for_in7(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in7X(img,x0,x1,x) cimg_for_in7((img)._width,x0,x1,x) +#define cimg_for_in7Y(img,y0,y1,y) cimg_for_in7((img)._height,y0,y1,y) +#define cimg_for_in7Z(img,z0,z1,z) cimg_for_in7((img)._depth,z0,z1,z) +#define cimg_for_in7C(img,c0,c1,c) cimg_for_in7((img)._spectrum,c0,c1,c) +#define cimg_for_in7XY(img,x0,y0,x1,y1,x,y) cimg_for_in7Y(img,y0,y1,y) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XZ(img,x0,z0,x1,z1,x,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XC(img,x0,c0,x1,c1,x,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7YC(img,y0,c0,y1,c1,y,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7ZC(img,z0,c0,z1,c1,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Z(img,z0,z1,z) +#define cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in7XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in7YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in7XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in7C(img,c0,c1,c) cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for8(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for8X(img,x) cimg_for8((img)._width,x) +#define cimg_for8Y(img,y) cimg_for8((img)._height,y) +#define cimg_for8Z(img,z) cimg_for8((img)._depth,z) +#define cimg_for8C(img,c) cimg_for8((img)._spectrum,c) +#define cimg_for8XY(img,x,y) cimg_for8Y(img,y) cimg_for8X(img,x) +#define cimg_for8XZ(img,x,z) cimg_for8Z(img,z) cimg_for8X(img,x) +#define cimg_for8XC(img,x,c) cimg_for8C(img,c) cimg_for8X(img,x) +#define cimg_for8YZ(img,y,z) cimg_for8Z(img,z) cimg_for8Y(img,y) +#define cimg_for8YC(img,y,c) cimg_for8C(img,c) cimg_for8Y(img,y) +#define cimg_for8ZC(img,z,c) cimg_for8C(img,c) cimg_for8Z(img,z) +#define cimg_for8XYZ(img,x,y,z) cimg_for8Z(img,z) cimg_for8XY(img,x,y) +#define cimg_for8XZC(img,x,z,c) cimg_for8C(img,c) cimg_for8XZ(img,x,z) +#define cimg_for8YZC(img,y,z,c) cimg_for8C(img,c) cimg_for8YZ(img,y,z) +#define cimg_for8XYZC(img,x,y,z,c) cimg_for8C(img,c) cimg_for8XYZ(img,x,y,z) + +#define cimg_for_in8(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in8X(img,x0,x1,x) cimg_for_in8((img)._width,x0,x1,x) +#define cimg_for_in8Y(img,y0,y1,y) cimg_for_in8((img)._height,y0,y1,y) +#define cimg_for_in8Z(img,z0,z1,z) cimg_for_in8((img)._depth,z0,z1,z) +#define cimg_for_in8C(img,c0,c1,c) cimg_for_in8((img)._spectrum,c0,c1,c) +#define cimg_for_in8XY(img,x0,y0,x1,y1,x,y) cimg_for_in8Y(img,y0,y1,y) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XZ(img,x0,z0,x1,z1,x,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XC(img,x0,c0,x1,c1,x,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8YC(img,y0,c0,y1,c1,y,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8ZC(img,z0,c0,z1,c1,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Z(img,z0,z1,z) +#define cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in8XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in8YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in8XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in8C(img,c0,c1,c) cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for9(bound,i) \ + for (int i = 0, _p4##i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(int)(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(int)(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(int)(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(int)(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for9X(img,x) cimg_for9((img)._width,x) +#define cimg_for9Y(img,y) cimg_for9((img)._height,y) +#define cimg_for9Z(img,z) cimg_for9((img)._depth,z) +#define cimg_for9C(img,c) cimg_for9((img)._spectrum,c) +#define cimg_for9XY(img,x,y) cimg_for9Y(img,y) cimg_for9X(img,x) +#define cimg_for9XZ(img,x,z) cimg_for9Z(img,z) cimg_for9X(img,x) +#define cimg_for9XC(img,x,c) cimg_for9C(img,c) cimg_for9X(img,x) +#define cimg_for9YZ(img,y,z) cimg_for9Z(img,z) cimg_for9Y(img,y) +#define cimg_for9YC(img,y,c) cimg_for9C(img,c) cimg_for9Y(img,y) +#define cimg_for9ZC(img,z,c) cimg_for9C(img,c) cimg_for9Z(img,z) +#define cimg_for9XYZ(img,x,y,z) cimg_for9Z(img,z) cimg_for9XY(img,x,y) +#define cimg_for9XZC(img,x,z,c) cimg_for9C(img,c) cimg_for9XZ(img,x,z) +#define cimg_for9YZC(img,y,z,c) cimg_for9C(img,c) cimg_for9YZ(img,y,z) +#define cimg_for9XYZC(img,x,y,z,c) cimg_for9C(img,c) cimg_for9XYZ(img,x,y,z) + +#define cimg_for_in9(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p4##i = i - 4<0?0:i - 4, \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in9X(img,x0,x1,x) cimg_for_in9((img)._width,x0,x1,x) +#define cimg_for_in9Y(img,y0,y1,y) cimg_for_in9((img)._height,y0,y1,y) +#define cimg_for_in9Z(img,z0,z1,z) cimg_for_in9((img)._depth,z0,z1,z) +#define cimg_for_in9C(img,c0,c1,c) cimg_for_in9((img)._spectrum,c0,c1,c) +#define cimg_for_in9XY(img,x0,y0,x1,y1,x,y) cimg_for_in9Y(img,y0,y1,y) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XZ(img,x0,z0,x1,z1,x,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XC(img,x0,c0,x1,c1,x,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9YC(img,y0,c0,y1,c1,y,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9ZC(img,z0,c0,z1,c1,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Z(img,z0,z1,z) +#define cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in9XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in9YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in9XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in9C(img,c0,c1,c) cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[4] = (T)(img)(x,y,z,c)), \ + (I[7] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for4x4(img,x,y,z,c,I,T) \ + cimg_for4((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = I[5] = (T)(img)(0,y,z,c)), \ + (I[8] = I[9] = (T)(img)(0,_n1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in4x4(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in4((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = (T)(img)(_p1##x,y,z,c)), \ + (I[8] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[5] = (T)(img)(x,y,z,c)), \ + (I[9] = (T)(img)(x,_n1##y,z,c)), \ + (I[13] = (T)(img)(x,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for5x5(img,x,y,z,c,I,T) \ + cimg_for5((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = I[6] = I[7] = (T)(img)(0,_p1##y,z,c)), \ + (I[10] = I[11] = I[12] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = I[17] = (T)(img)(0,_n1##y,z,c)), \ + (I[20] = I[21] = I[22] = (T)(img)(0,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in5x5(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in5((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[10] = (T)(img)(_p2##x,y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[11] = (T)(img)(_p1##x,y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[7] = (T)(img)(x,_p1##y,z,c)), \ + (I[12] = (T)(img)(x,y,z,c)), \ + (I[17] = (T)(img)(x,_n1##y,z,c)), \ + (I[22] = (T)(img)(x,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for6x6(img,x,y,z,c,I,T) \ + cimg_for6((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = I[7] = I[8] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = I[14] = (T)(img)(0,y,z,c)), \ + (I[18] = I[19] = I[20] = (T)(img)(0,_n1##y,z,c)), \ + (I[24] = I[25] = I[26] = (T)(img)(0,_n2##y,z,c)), \ + (I[30] = I[31] = I[32] = (T)(img)(0,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in6x6(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in6((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)x0, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p2##x,y,z,c)), \ + (I[18] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[30] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[7] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_p1##x,y,z,c)), \ + (I[19] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[25] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[31] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[8] = (T)(img)(x,_p1##y,z,c)), \ + (I[14] = (T)(img)(x,y,z,c)), \ + (I[20] = (T)(img)(x,_n1##y,z,c)), \ + (I[26] = (T)(img)(x,_n2##y,z,c)), \ + (I[32] = (T)(img)(x,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for7x7(img,x,y,z,c,I,T) \ + cimg_for7((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = I[8] = I[9] = I[10] = (T)(img)(0,_p2##y,z,c)), \ + (I[14] = I[15] = I[16] = I[17] = (T)(img)(0,_p1##y,z,c)), \ + (I[21] = I[22] = I[23] = I[24] = (T)(img)(0,y,z,c)), \ + (I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_n1##y,z,c)), \ + (I[35] = I[36] = I[37] = I[38] = (T)(img)(0,_n2##y,z,c)), \ + (I[42] = I[43] = I[44] = I[45] = (T)(img)(0,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in7x7(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in7((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[14] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[21] = (T)(img)(_p3##x,y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[35] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[42] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[22] = (T)(img)(_p2##x,y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[36] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[43] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[23] = (T)(img)(_p1##x,y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[37] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[44] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[10] = (T)(img)(x,_p2##y,z,c)), \ + (I[17] = (T)(img)(x,_p1##y,z,c)), \ + (I[24] = (T)(img)(x,y,z,c)), \ + (I[31] = (T)(img)(x,_n1##y,z,c)), \ + (I[38] = (T)(img)(x,_n2##y,z,c)), \ + (I[45] = (T)(img)(x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for8x8(img,x,y,z,c,I,T) \ + cimg_for8((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = I[9] = I[10] = I[11] = (T)(img)(0,_p2##y,z,c)), \ + (I[16] = I[17] = I[18] = I[19] = (T)(img)(0,_p1##y,z,c)), \ + (I[24] = I[25] = I[26] = I[27] = (T)(img)(0,y,z,c)), \ + (I[32] = I[33] = I[34] = I[35] = (T)(img)(0,_n1##y,z,c)), \ + (I[40] = I[41] = I[42] = I[43] = (T)(img)(0,_n2##y,z,c)), \ + (I[48] = I[49] = I[50] = I[51] = (T)(img)(0,_n3##y,z,c)), \ + (I[56] = I[57] = I[58] = I[59] = (T)(img)(0,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in8x8(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in8((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[24] = (T)(img)(_p3##x,y,z,c)), \ + (I[32] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[56] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[17] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_p2##x,y,z,c)), \ + (I[33] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[49] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[57] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[10] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_p1##x,y,z,c)), \ + (I[34] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[42] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[50] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[58] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[11] = (T)(img)(x,_p2##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,z,c)), \ + (I[27] = (T)(img)(x,y,z,c)), \ + (I[35] = (T)(img)(x,_n1##y,z,c)), \ + (I[43] = (T)(img)(x,_n2##y,z,c)), \ + (I[51] = (T)(img)(x,_n3##y,z,c)), \ + (I[59] = (T)(img)(x,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for9x9(img,x,y,z,c,I,T) \ + cimg_for9((img)._height,y) for (int x = 0, \ + _p4##x = 0, _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = I[4] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = I[10] = I[11] = I[12] = I[13] = (T)(img)(0,_p3##y,z,c)), \ + (I[18] = I[19] = I[20] = I[21] = I[22] = (T)(img)(0,_p2##y,z,c)), \ + (I[27] = I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_p1##y,z,c)), \ + (I[36] = I[37] = I[38] = I[39] = I[40] = (T)(img)(0,y,z,c)), \ + (I[45] = I[46] = I[47] = I[48] = I[49] = (T)(img)(0,_n1##y,z,c)), \ + (I[54] = I[55] = I[56] = I[57] = I[58] = (T)(img)(0,_n2##y,z,c)), \ + (I[63] = I[64] = I[65] = I[66] = I[67] = (T)(img)(0,_n3##y,z,c)), \ + (I[72] = I[73] = I[74] = I[75] = I[76] = (T)(img)(0,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in9x9(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in9((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p4##x = x - 4<0?0:x - 4, \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = (T)(img)(_p4##x,_p3##y,z,c)), \ + (I[18] = (T)(img)(_p4##x,_p2##y,z,c)), \ + (I[27] = (T)(img)(_p4##x,_p1##y,z,c)), \ + (I[36] = (T)(img)(_p4##x,y,z,c)), \ + (I[45] = (T)(img)(_p4##x,_n1##y,z,c)), \ + (I[54] = (T)(img)(_p4##x,_n2##y,z,c)), \ + (I[63] = (T)(img)(_p4##x,_n3##y,z,c)), \ + (I[72] = (T)(img)(_p4##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p3##x,_p4##y,z,c)), \ + (I[10] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[19] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[37] = (T)(img)(_p3##x,y,z,c)), \ + (I[46] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[55] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[64] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[73] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p2##x,_p4##y,z,c)), \ + (I[11] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[38] = (T)(img)(_p2##x,y,z,c)), \ + (I[47] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[56] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[65] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[74] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,_p4##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[39] = (T)(img)(_p1##x,y,z,c)), \ + (I[48] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[57] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[66] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[75] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[4] = (T)(img)(x,_p4##y,z,c)), \ + (I[13] = (T)(img)(x,_p3##y,z,c)), \ + (I[22] = (T)(img)(x,_p2##y,z,c)), \ + (I[31] = (T)(img)(x,_p1##y,z,c)), \ + (I[40] = (T)(img)(x,y,z,c)), \ + (I[49] = (T)(img)(x,_n1##y,z,c)), \ + (I[58] = (T)(img)(x,_n2##y,z,c)), \ + (I[67] = (T)(img)(x,_n3##y,z,c)), \ + (I[76] = (T)(img)(x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for2x2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._depth,z) cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + (I[4] = (T)(img)(0,y,_n1##z,c)), \ + (I[6] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in2((img)._depth,z0,z1,z) cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + (I[4] = (T)(img)(x,y,_n1##z,c)), \ + (I[6] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for3x3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._depth,z) cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,_p1##z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,_p1##z,c)), \ + (I[9] = I[10] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = (T)(img)(0,_n1##y,z,c)), \ + (I[18] = I[19] = (T)(img)(0,_p1##y,_n1##z,c)), \ + (I[21] = I[22] = (T)(img)(0,y,_n1##z,c)), \ + (I[24] = I[25] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in3((img)._depth,z0,z1,z) cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = (T)(img)(_p1##x,y,_p1##z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c)), \ + (I[9] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,y,z,c)), \ + (I[15] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c)), \ + (I[21] = (T)(img)(_p1##x,y,_n1##z,c)), \ + (I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c)), \ + (I[1] = (T)(img)(x,_p1##y,_p1##z,c)), \ + (I[4] = (T)(img)(x,y,_p1##z,c)), \ + (I[7] = (T)(img)(x,_n1##y,_p1##z,c)), \ + (I[10] = (T)(img)(x,_p1##y,z,c)), \ + (I[13] = (T)(img)(x,y,z,c)), \ + (I[16] = (T)(img)(x,_n1##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,_n1##z,c)), \ + (I[22] = (T)(img)(x,y,_n1##z,c)), \ + (I[25] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimglist_for(list,l) for (int l = 0; l<(int)(list)._width; ++l) +#define cimglist_rof(list,l) for (int l = (int)(list)._width - 1; l>=0; --l) +#define cimglist_for_in(list,l0,l1,l) \ + for (int l = (int)(l0)<0?0:(int)(l0), _max##l = (unsigned int)l1<(list)._width?(int)(l1):(int)(list)._width - 1; \ + l<=_max##l; ++l) + +#define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn + +// Macros used to display error messages when exceptions are thrown. +// You should not use these macros is your own code. +#define _cimgdisplay_instance "[instance(%u,%u,%u,%c%s%c)] CImgDisplay::" +#define cimgdisplay_instance _width,_height,_normalization,_title?'\"':'[',_title?_title:"untitled",_title?'\"':']' +#define _cimg_instance "[instance(%u,%u,%u,%u,%p,%sshared)] CImg<%s>::" +#define cimg_instance _width,_height,_depth,_spectrum,_data,_is_shared?"":"non-",pixel_type() +#define _cimglist_instance "[instance(%u,%u,%p)] CImgList<%s>::" +#define cimglist_instance _width,_allocated_width,_data,pixel_type() + +/*------------------------------------------------ + # + # + # Define cimg_library:: namespace + # + # + -------------------------------------------------*/ +//! Contains all classes and functions of the \CImg library. +/** + This namespace is defined to avoid functions and class names collisions + that could happen with the inclusion of other C++ header files. + Anyway, it should not happen often and you should reasonably start most of your + \CImg-based programs with + \code + #include "CImg.h" + using namespace cimg_library; + \endcode + to simplify the declaration of \CImg Library objects afterwards. +**/ +namespace cimg_library_suffixed { + + // Declare the four classes of the CImg Library. + template struct CImg; + template struct CImgList; + struct CImgDisplay; + struct CImgException; + + // Declare cimg:: namespace. + // This is an incomplete namespace definition here. It only contains some + // necessary stuff to ensure a correct declaration order of the classes and functions + // defined afterwards. + namespace cimg { + + // Define character sequences for colored terminal output. +#ifdef cimg_use_vt100 + static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 }; + static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 }; + static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 }; + static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 }; + static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 }; + static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 }; + static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 }; + static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 }; + static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 }; + static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 }; + static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 }; +#else + static const char t_normal[] = { 0 }; + static const char *const t_black = cimg::t_normal, + *const t_red = cimg::t_normal, + *const t_green = cimg::t_normal, + *const t_yellow = cimg::t_normal, + *const t_blue = cimg::t_normal, + *const t_magenta = cimg::t_normal, + *const t_cyan = cimg::t_normal, + *const t_white = cimg::t_normal, + *const t_bold = cimg::t_normal, + *const t_underscore = cimg::t_normal; +#endif + + inline std::FILE* output(std::FILE *file=0); + inline void info(); + + //! Avoid warning messages due to unused parameters. Do nothing actually. + template + inline void unused(const T&, ...) {} + + // [internal] Lock/unlock a mutex for managing concurrent threads. + // 'lock_mode' can be { 0=unlock | 1=lock | 2=trylock }. + // 'n' can be in [0,31] but mutex range [0,15] is reserved by CImg. + inline int mutex(const unsigned int n, const int lock_mode=1); + + inline unsigned int& exception_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = cimg_verbosity; + if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); } + return mode; + } + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + inline FILE* _stdin(const bool throw_exception=true); + inline FILE* _stdout(const bool throw_exception=true); + inline FILE* _stderr(const bool throw_exception=true); + + // Mandatory because Microsoft's _snprintf() and _vsnprintf() do not add the '\0' character + // at the end of the string. +#if cimg_OS==2 && defined(_MSC_VER) + inline int _snprintf(char *const s, const size_t size, const char *const format, ...) { + va_list ap; + va_start(ap,format); + const int result = _vsnprintf(s,size,format,ap); + va_end(ap); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) { + int result = -1; + cimg::mutex(6); + if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap); + if (result==-1) result = _vscprintf(format,ap); + cimg::mutex(6,0); + return result; + } + + // Mutex-protected version of sscanf, sprintf and snprintf. + // Used only MacOSX, as it seems those functions are not re-entrant on MacOSX. +#elif defined(__MACOSX__) || defined(__APPLE__) + inline int _sscanf(const char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsscanf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _sprintf(char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsprintf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _snprintf(char *const s, const size_t n, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsnprintf(s,n,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) { + cimg::mutex(6); + const int result = std::vsnprintf(s,size,format,ap); + cimg::mutex(6,0); + return result; + } +#endif + + //! Set current \CImg exception mode. + /** + The way error messages are handled by \CImg can be changed dynamically, using this function. + \param mode Desired exception mode. Possible values are: + - \c 0: Hide library messages (quiet mode). + - \c 1: Print library messages on the console. + - \c 2: Display library messages on a dialog window. + - \c 3: Do as \c 1 + add extra debug warnings (slow down the code!). + - \c 4: Do as \c 2 + add extra debug warnings (slow down the code!). + **/ + inline unsigned int& exception_mode(const unsigned int mode) { + return exception_mode(mode,true); + } + + //! Return current \CImg exception mode. + /** + \note By default, return the value of configuration macro \c cimg_verbosity + **/ + inline unsigned int& exception_mode() { + return exception_mode(0,false); + } + + inline unsigned int openmp_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = 2; + if (is_set) { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); } + return mode; + } + + //! Set current \CImg openmp mode. + /** + The way openmp-based methods are handled by \CImg can be changed dynamically, using this function. + \param mode Desired openmp mode. Possible values are: + - \c 0: Never parallelize. + - \c 1: Always parallelize. + - \c 2: Adaptive parallelization mode (default behavior). + **/ + inline unsigned int openmp_mode(const unsigned int mode) { + return openmp_mode(mode,true); + } + + //! Return current \CImg openmp mode. + inline unsigned int openmp_mode() { + return openmp_mode(0,false); + } + +#ifndef cimg_openmp_sizefactor +#define cimg_openmp_sizefactor 1 +#endif +#define cimg_openmp_if(cond) if ((cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond)))) +#define cimg_openmp_if_size(size,min_size) cimg_openmp_if((size)>=(cimg_openmp_sizefactor)*(min_size)) +#ifdef _MSC_VER +// Disable 'collapse()' directive for MSVC (supports only OpenMP 2.0). +#define cimg_openmp_collapse(k) +#else +#define cimg_openmp_collapse(k) collapse(k) +#endif + +#if cimg_OS==2 +// Disable parallelization of simple loops on Windows, due to noticed performance drop. +#define cimg_openmp_for(instance,expr,min_size) cimg_rof((instance),ptr,T) *ptr = (T)(expr); +#else +#define cimg_openmp_for(instance,expr,min_size) \ + cimg_pragma_openmp(parallel for cimg_openmp_if_size((instance).size(),min_size)) \ + cimg_rof((instance),ptr,T) *ptr = (T)(expr); +#endif + + // Display a simple dialog box, and wait for the user's response. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label="OK", const char *const button2_label=0, + const char *const button3_label=0, const char *const button4_label=0, + const char *const button5_label=0, const char *const button6_label=0, + const bool centering=false); + + // Evaluate math expression. + inline double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0); + + } // namespace cimg { ... + + /*--------------------------------------- + # + # Define the CImgException structures + # + --------------------------------------*/ + //! Instances of \c CImgException are thrown when errors are encountered in a \CImg function call. + /** + \par Overview + + CImgException is the base class of all exceptions thrown by \CImg (except \b CImgAbortException). + CImgException is never thrown itself. Derived classes that specify the type of errord are thrown instead. + These classes can be: + + - \b CImgAbortException: Thrown when a computationally-intensive function is aborted by an external signal. + This is the only \c non-derived exception class. + + - \b CImgArgumentException: Thrown when one argument of a called \CImg function is invalid. + This is probably one of the most thrown exception by \CImg. + For instance, the following example throws a \c CImgArgumentException: + \code + CImg img(100,100,1,3); // Define a 100x100 color image with float-valued pixels + img.mirror('e'); // Try to mirror image along the (non-existing) 'e'-axis + \endcode + + - \b CImgDisplayException: Thrown when something went wrong during the display of images in CImgDisplay instances. + + - \b CImgInstanceException: Thrown when an instance associated to a called \CImg method does not fit + the function requirements. For instance, the following example throws a \c CImgInstanceException: + \code + const CImg img; // Define an empty image + const float value = img.at(0); // Try to read first pixel value (does not exist) + \endcode + + - \b CImgIOException: Thrown when an error occurred when trying to load or save image files. + This happens when trying to read files that do not exist or with invalid formats. + For instance, the following example throws a \c CImgIOException: + \code + const CImg img("missing_file.jpg"); // Try to load a file that does not exist + \endcode + + - \b CImgWarningException: Thrown only if configuration macro \c cimg_strict_warnings is set, and + when a \CImg function has to display a warning message (see cimg::warn()). + + It is not recommended to throw CImgException instances by yourself, + since they are expected to be thrown only by \CImg. + When an error occurs in a library function call, \CImg may display error messages on the screen or on the + standard output, depending on the current \CImg exception mode. + The \CImg exception mode can be get and set by functions cimg::exception_mode() and + cimg::exception_mode(unsigned int). + + \par Exceptions handling + + In all cases, when an error occurs in \CImg, an instance of the corresponding exception class is thrown. + This may lead the program to break (this is the default behavior), but you can bypass this behavior by + handling the exceptions by yourself, + using a usual try { ... } catch () { ... } bloc, as in the following example: + \code + #define "CImg.h" + using namespace cimg_library; + int main() { + cimg::exception_mode(0); // Enable quiet exception mode + try { + ... // Here, do what you want to stress CImg + } catch (CImgException& e) { // You succeeded: something went wrong! + std::fprintf(stderr,"CImg Library Error: %s",e.what()); // Display your custom error message + ... // Do what you want now to save the ship! + } + } + \endcode + **/ + struct CImgException : public std::exception { +#define _cimg_exception_err(etype,disp_flag) \ + std::va_list ap, ap2; \ + va_start(ap,format); va_start(ap2,format); \ + int size = cimg_vsnprintf(0,0,format,ap2); \ + if (size++>=0) { \ + delete[] _message; \ + _message = new char[(size_t)size]; \ + cimg_vsnprintf(_message,(size_t)size,format,ap); \ + if (cimg::exception_mode()) { \ + std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \ + if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \ + catch (CImgException&) {} \ + if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \ + } \ + } \ + va_end(ap); va_end(ap2); + + char *_message; + CImgException() { _message = new char[1]; *_message = 0; } + CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); } + CImgException(const CImgException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgException() throw() { delete[] _message; } + CImgException& operator=(const CImgException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; // struct CImgException { ... + + // The CImgAbortException class is used to throw an exception when + // a computationally-intensive function has been aborted by an external signal. + struct CImgAbortException : public std::exception { + char *_message; + CImgAbortException() { _message = new char[1]; *_message = 0; } + CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); } + CImgAbortException(const CImgAbortException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgAbortException() throw() { delete[] _message; } + CImgAbortException& operator=(const CImgAbortException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; // struct CImgAbortException { ... + + // The CImgArgumentException class is used to throw an exception related + // to invalid arguments encountered in a library function call. + struct CImgArgumentException : public CImgException { + CImgArgumentException(const char *const format, ...) { _cimg_exception_err("CImgArgumentException",true); } + }; // struct CImgArgumentException { ... + + // The CImgDisplayException class is used to throw an exception related + // to display problems encountered in a library function call. + struct CImgDisplayException : public CImgException { + CImgDisplayException(const char *const format, ...) { _cimg_exception_err("CImgDisplayException",false); } + }; // struct CImgDisplayException { ... + + // The CImgInstanceException class is used to throw an exception related + // to an invalid instance encountered in a library function call. + struct CImgInstanceException : public CImgException { + CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); } + }; // struct CImgInstanceException { ... + + // The CImgIOException class is used to throw an exception related + // to input/output file problems encountered in a library function call. + struct CImgIOException : public CImgException { + CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); } + }; // struct CImgIOException { ... + + // The CImgWarningException class is used to throw an exception for warnings + // encountered in a library function call. + struct CImgWarningException : public CImgException { + CImgWarningException(const char *const format, ...) { _cimg_exception_err("CImgWarningException",false); } + }; // struct CImgWarningException { ... + + /*------------------------------------- + # + # Define cimg:: namespace + # + -----------------------------------*/ + //! Contains \a low-level functions and variables of the \CImg Library. + /** + Most of the functions and variables within this namespace are used by the \CImg library for low-level operations. + You may use them to access specific const values or environment variables internally used by \CImg. + \warning Never write using namespace cimg_library::cimg; in your source code. Lot of functions in the + cimg:: namespace have the same names as standard C functions that may be defined in the global + namespace ::. + **/ + namespace cimg { + + // Define traits that will be used to determine the best data type to work in CImg functions. + // + template struct type { + static const char* string() { + static const char* s[] = { "unknown", "unknown8", "unknown16", "unknown24", + "unknown32", "unknown40", "unknown48", "unknown56", + "unknown64", "unknown72", "unknown80", "unknown88", + "unknown96", "unknown104", "unknown112", "unknown120", + "unknown128" }; + return s[(sizeof(T)<17)?sizeof(T):0]; + } + static bool is_float() { return false; } + static bool is_inf(const T) { return false; } + static bool is_nan(const T) { return false; } + static bool is_finite(const T) { return true; } + static T min() { return ~max(); } + static T max() { return (T)1<<(8*sizeof(T) - 1); } + static T inf() { return max(); } + static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; } + static const char* format() { return "%s"; } + static const char* format_s() { return "%s"; } + static const char* format(const T& val) { static const char *const s = "unknown"; cimg::unused(val); return s; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "bool"; return s; } + static bool is_float() { return false; } + static bool is_inf(const bool) { return false; } + static bool is_nan(const bool) { return false; } + static bool is_finite(const bool) { return true; } + static bool min() { return false; } + static bool max() { return true; } + static bool inf() { return max(); } + static bool is_inf() { return false; } + static bool cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(bool)val; } + static const char* format() { return "%s"; } + static const char* format_s() { return "%s"; } + static const char* format(const bool val) { static const char* s[] = { "false", "true" }; return s[val?1:0]; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned char) { return false; } + static bool is_nan(const unsigned char) { return false; } + static bool is_finite(const unsigned char) { return true; } + static unsigned char min() { return 0; } + static unsigned char max() { return (unsigned char)-1; } + static unsigned char inf() { return max(); } + static unsigned char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned char val) { return (unsigned int)val; } + }; + +#if defined(CHAR_MAX) && CHAR_MAX==255 + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static bool is_finite(const char) { return true; } + static char min() { return 0; } + static char max() { return (char)-1; } + static char inf() { return max(); } + static char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const char val) { return (unsigned int)val; } + }; +#else + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static bool is_finite(const char) { return true; } + static char min() { return ~max(); } + static char max() { return (char)((unsigned char)-1>>1); } + static char inf() { return max(); } + static char cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(char)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const char val) { return (int)val; } + }; +#endif + + template<> struct type { + static const char* string() { static const char *const s = "signed char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const signed char) { return false; } + static bool is_nan(const signed char) { return false; } + static bool is_finite(const signed char) { return true; } + static signed char min() { return ~max(); } + static signed char max() { return (signed char)((unsigned char)-1>>1); } + static signed char inf() { return max(); } + static signed char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(signed char)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const signed char val) { return (int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned short) { return false; } + static bool is_nan(const unsigned short) { return false; } + static bool is_finite(const unsigned short) { return true; } + static unsigned short min() { return 0; } + static unsigned short max() { return (unsigned short)-1; } + static unsigned short inf() { return max(); } + static unsigned short cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned short)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned short val) { return (unsigned int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const short) { return false; } + static bool is_nan(const short) { return false; } + static bool is_finite(const short) { return true; } + static short min() { return ~max(); } + static short max() { return (short)((unsigned short)-1>>1); } + static short inf() { return max(); } + static short cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(short)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const short val) { return (int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned int) { return false; } + static bool is_nan(const unsigned int) { return false; } + static bool is_finite(const unsigned int) { return true; } + static unsigned int min() { return 0; } + static unsigned int max() { return (unsigned int)-1; } + static unsigned int inf() { return max(); } + static unsigned int cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned int)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned int val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const int) { return false; } + static bool is_nan(const int) { return false; } + static bool is_finite(const int) { return true; } + static int min() { return ~max(); } + static int max() { return (int)((unsigned int)-1>>1); } + static int inf() { return max(); } + static int cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(int)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const int val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_uint64) { return false; } + static bool is_nan(const cimg_uint64) { return false; } + static bool is_finite(const cimg_uint64) { return true; } + static cimg_uint64 min() { return 0; } + static cimg_uint64 max() { return (cimg_uint64)-1; } + static cimg_uint64 inf() { return max(); } + static cimg_uint64 cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(cimg_uint64)val; } + static const char* format() { return cimg_fuint64; } + static const char* format_s() { return cimg_fuint64; } + static cimg_uint64 format(const cimg_uint64 val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_int64) { return false; } + static bool is_nan(const cimg_int64) { return false; } + static bool is_finite(const cimg_int64) { return true; } + static cimg_int64 min() { return ~max(); } + static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); } + static cimg_int64 inf() { return max(); } + static cimg_int64 cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(cimg_int64)val; + } + static const char* format() { return cimg_fint64; } + static const char* format_s() { return cimg_fint64; } + static long format(const long val) { return (long)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const double val) { // Custom version that works with '-ffast-math' + if (sizeof(double)==8) { + cimg_uint64 u; + std::memcpy(&u,&val,sizeof(double)); + return ((unsigned int)(u>>32)&0x7fffffff) + ((unsigned int)u!=0)>0x7ff00000; + } +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const double val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static double min() { return -DBL_MAX; } + static double max() { return DBL_MAX; } + static double inf() { +#ifdef INFINITY + return (double)INFINITY; +#else + return max()*max(); +#endif + } + static double nan() { +#ifdef NAN + return (double)NAN; +#else + const double val_nan = -std::sqrt(-1.); return val_nan; +#endif + } + static double cut(const double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const double val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "float"; return s; } + static bool is_float() { return true; } + static bool is_inf(const float val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const float val) { // Custom version that works with '-ffast-math' + if (sizeof(float)==4) { + unsigned int u; + std::memcpy(&u,&val,sizeof(float)); + return (u&0x7fffffff)>0x7f800000; + } +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const float val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static float min() { return -FLT_MAX; } + static float max() { return FLT_MAX; } + static float inf() { return (float)cimg::type::inf(); } + static float nan() { return (float)cimg::type::nan(); } + static float cut(const double val) { return (float)val; } + static float cut(const float val) { return (float)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const float val) { return (double)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "long double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const long double val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const long double val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static long double min() { return -LDBL_MAX; } + static long double max() { return LDBL_MAX; } + static long double inf() { return max()*max(); } + static long double nan() { const long double val_nan = -std::sqrt(-1.L); return val_nan; } + static long double cut(const long double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const long double val) { return (double)val; } + }; + +#ifdef cimg_use_half + template<> struct type { + static const char* string() { static const char *const s = "half"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const half val) { // Custom version that works with '-ffast-math' + if (sizeof(half)==2) { + short u; + std::memcpy(&u,&val,sizeof(short)); + return (bool)((u&0x7fff)>0x7c00); + } + return cimg::type::is_nan((float)val); + } + static bool is_finite(const half val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static half min() { return (half)-65504; } + static half max() { return (half)65504; } + static half inf() { return max()*max(); } + static half nan() { const half val_nan = (half)-std::sqrt(-1.); return val_nan; } + static half cut(const double val) { return (half)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const half val) { return (double)val; } + }; +#endif + + template struct superset { typedef T type; }; + template<> struct superset { typedef unsigned char type; }; + template<> struct superset { typedef char type; }; + template<> struct superset { typedef signed char type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + +#ifdef cimg_use_half + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; +#endif + + template struct superset2 { + typedef typename superset::type>::type type; + }; + + template struct superset3 { + typedef typename superset::type>::type type; + }; + + template struct last { typedef t2 type; }; + +#define _cimg_Tt typename cimg::superset::type +#define _cimg_Tfloat typename cimg::superset::type +#define _cimg_tfloat typename cimg::superset::type +#define _cimg_Ttfloat typename cimg::superset2::type +#define _cimg_Ttdouble typename cimg::superset2::type + + // Define variables used internally by CImg. +#if cimg_display==1 + struct X11_static { + unsigned int nb_wins; + pthread_t *events_thread; + pthread_cond_t wait_event; + pthread_mutex_t wait_event_mutex; + CImgDisplay **wins; + Display *display; + unsigned int nb_bits; + bool is_blue_first; + bool is_shm_enabled; + bool byte_order; + +#ifdef cimg_use_xrandr + XRRScreenSize *resolutions; + Rotation curr_rotation; + unsigned int curr_resolution; + unsigned int nb_resolutions; +#endif + X11_static():nb_wins(0),events_thread(0),display(0), + nb_bits(0),is_blue_first(false),is_shm_enabled(false),byte_order(false) { +#ifdef __FreeBSD__ + XInitThreads(); +#endif + wins = new CImgDisplay*[1024]; + pthread_mutex_init(&wait_event_mutex,0); + pthread_cond_init(&wait_event,0); + +#ifdef cimg_use_xrandr + resolutions = 0; + curr_rotation = 0; + curr_resolution = nb_resolutions = 0; +#endif + } + + ~X11_static() { + delete[] wins; + /* + if (events_thread) { + pthread_cancel(*events_thread); + delete events_thread; + } + if (display) { } // XCloseDisplay(display); } + pthread_cond_destroy(&wait_event); + pthread_mutex_unlock(&wait_event_mutex); + pthread_mutex_destroy(&wait_event_mutex); + */ + } + }; // struct X11_static { ... +#if defined(cimg_module) + X11_static& X11_attr(); +#elif defined(cimg_main) + X11_static& X11_attr() { static X11_static val; return val; } +#else + inline X11_static& X11_attr() { static X11_static val; return val; } +#endif + +#elif cimg_display==2 + struct Win32_static { + HANDLE wait_event; + Win32_static() { wait_event = CreateEvent(0,FALSE_WIN,FALSE_WIN,0); } + }; // struct Win32_static { ... +#if defined(cimg_module) + Win32_static& Win32_attr(); +#elif defined(cimg_main) + Win32_static& Win32_attr() { static Win32_static val; return val; } +#else + inline Win32_static& Win32_attr() { static Win32_static val; return val; } +#endif +#endif +#define cimg_lock_display() cimg::mutex(15) +#define cimg_unlock_display() cimg::mutex(15,0) + + struct Mutex_static { +#if cimg_OS==1 && (defined(cimg_use_pthread) || cimg_display==1) + pthread_mutex_t mutex[32]; + Mutex_static() { for (unsigned int i = 0; i<32; ++i) pthread_mutex_init(&mutex[i],0); } + void lock(const unsigned int n) { pthread_mutex_lock(&mutex[n]); } + void unlock(const unsigned int n) { pthread_mutex_unlock(&mutex[n]); } + int trylock(const unsigned int n) { return pthread_mutex_trylock(&mutex[n]); } +#elif cimg_OS==2 + HANDLE mutex[32]; + Mutex_static() { for (unsigned int i = 0; i<32; ++i) mutex[i] = CreateMutex(0,FALSE_WIN,0); } + void lock(const unsigned int n) { WaitForSingleObject(mutex[n],INFINITE); } + void unlock(const unsigned int n) { ReleaseMutex(mutex[n]); } + int trylock(const unsigned int) { return 0; } +#else + Mutex_static() {} + void lock(const unsigned int) {} + void unlock(const unsigned int) {} + int trylock(const unsigned int) { return 0; } +#endif + }; // struct Mutex_static { ... +#if defined(cimg_module) + Mutex_static& Mutex_attr(); +#elif defined(cimg_main) + Mutex_static& Mutex_attr() { static Mutex_static val; return val; } +#else + inline Mutex_static& Mutex_attr() { static Mutex_static val; return val; } +#endif + +#if defined(cimg_use_magick) + struct Magick_static { + Magick_static() { + Magick::InitializeMagick(""); + } + }; // struct Magick_static { ... + static Magick_static _Magick_static; +#endif + +#if defined(cimg_use_fftw3) && !defined(cimg_use_fftw3_singlethread) + struct FFTW3_static { + FFTW3_static() { + fftw_init_threads(); + } + }; // struct FFTW3_static { ... + static FFTW3_static _FFTW3_static; +#endif + +#if cimg_display==1 + // Define keycodes for X11-based graphical systems. + const unsigned int keyESC = XK_Escape; + const unsigned int keyF1 = XK_F1; + const unsigned int keyF2 = XK_F2; + const unsigned int keyF3 = XK_F3; + const unsigned int keyF4 = XK_F4; + const unsigned int keyF5 = XK_F5; + const unsigned int keyF6 = XK_F6; + const unsigned int keyF7 = XK_F7; + const unsigned int keyF8 = XK_F8; + const unsigned int keyF9 = XK_F9; + const unsigned int keyF10 = XK_F10; + const unsigned int keyF11 = XK_F11; + const unsigned int keyF12 = XK_F12; + const unsigned int keyPAUSE = XK_Pause; + const unsigned int key1 = XK_1; + const unsigned int key2 = XK_2; + const unsigned int key3 = XK_3; + const unsigned int key4 = XK_4; + const unsigned int key5 = XK_5; + const unsigned int key6 = XK_6; + const unsigned int key7 = XK_7; + const unsigned int key8 = XK_8; + const unsigned int key9 = XK_9; + const unsigned int key0 = XK_0; + const unsigned int keyBACKSPACE = XK_BackSpace; + const unsigned int keyINSERT = XK_Insert; + const unsigned int keyHOME = XK_Home; + const unsigned int keyPAGEUP = XK_Page_Up; + const unsigned int keyTAB = XK_Tab; + const unsigned int keyQ = XK_q; + const unsigned int keyW = XK_w; + const unsigned int keyE = XK_e; + const unsigned int keyR = XK_r; + const unsigned int keyT = XK_t; + const unsigned int keyY = XK_y; + const unsigned int keyU = XK_u; + const unsigned int keyI = XK_i; + const unsigned int keyO = XK_o; + const unsigned int keyP = XK_p; + const unsigned int keyDELETE = XK_Delete; + const unsigned int keyEND = XK_End; + const unsigned int keyPAGEDOWN = XK_Page_Down; + const unsigned int keyCAPSLOCK = XK_Caps_Lock; + const unsigned int keyA = XK_a; + const unsigned int keyS = XK_s; + const unsigned int keyD = XK_d; + const unsigned int keyF = XK_f; + const unsigned int keyG = XK_g; + const unsigned int keyH = XK_h; + const unsigned int keyJ = XK_j; + const unsigned int keyK = XK_k; + const unsigned int keyL = XK_l; + const unsigned int keyENTER = XK_Return; + const unsigned int keySHIFTLEFT = XK_Shift_L; + const unsigned int keyZ = XK_z; + const unsigned int keyX = XK_x; + const unsigned int keyC = XK_c; + const unsigned int keyV = XK_v; + const unsigned int keyB = XK_b; + const unsigned int keyN = XK_n; + const unsigned int keyM = XK_m; + const unsigned int keySHIFTRIGHT = XK_Shift_R; + const unsigned int keyARROWUP = XK_Up; + const unsigned int keyCTRLLEFT = XK_Control_L; + const unsigned int keyAPPLEFT = XK_Super_L; + const unsigned int keyALT = XK_Alt_L; + const unsigned int keySPACE = XK_space; + const unsigned int keyALTGR = XK_Alt_R; + const unsigned int keyAPPRIGHT = XK_Super_R; + const unsigned int keyMENU = XK_Menu; + const unsigned int keyCTRLRIGHT = XK_Control_R; + const unsigned int keyARROWLEFT = XK_Left; + const unsigned int keyARROWDOWN = XK_Down; + const unsigned int keyARROWRIGHT = XK_Right; + const unsigned int keyPAD0 = XK_KP_0; + const unsigned int keyPAD1 = XK_KP_1; + const unsigned int keyPAD2 = XK_KP_2; + const unsigned int keyPAD3 = XK_KP_3; + const unsigned int keyPAD4 = XK_KP_4; + const unsigned int keyPAD5 = XK_KP_5; + const unsigned int keyPAD6 = XK_KP_6; + const unsigned int keyPAD7 = XK_KP_7; + const unsigned int keyPAD8 = XK_KP_8; + const unsigned int keyPAD9 = XK_KP_9; + const unsigned int keyPADADD = XK_KP_Add; + const unsigned int keyPADSUB = XK_KP_Subtract; + const unsigned int keyPADMUL = XK_KP_Multiply; + const unsigned int keyPADDIV = XK_KP_Divide; + +#elif cimg_display==2 + // Define keycodes for Windows. + const unsigned int keyESC = VK_ESCAPE; + const unsigned int keyF1 = VK_F1; + const unsigned int keyF2 = VK_F2; + const unsigned int keyF3 = VK_F3; + const unsigned int keyF4 = VK_F4; + const unsigned int keyF5 = VK_F5; + const unsigned int keyF6 = VK_F6; + const unsigned int keyF7 = VK_F7; + const unsigned int keyF8 = VK_F8; + const unsigned int keyF9 = VK_F9; + const unsigned int keyF10 = VK_F10; + const unsigned int keyF11 = VK_F11; + const unsigned int keyF12 = VK_F12; + const unsigned int keyPAUSE = VK_PAUSE; + const unsigned int key1 = '1'; + const unsigned int key2 = '2'; + const unsigned int key3 = '3'; + const unsigned int key4 = '4'; + const unsigned int key5 = '5'; + const unsigned int key6 = '6'; + const unsigned int key7 = '7'; + const unsigned int key8 = '8'; + const unsigned int key9 = '9'; + const unsigned int key0 = '0'; + const unsigned int keyBACKSPACE = VK_BACK; + const unsigned int keyINSERT = VK_INSERT; + const unsigned int keyHOME = VK_HOME; + const unsigned int keyPAGEUP = VK_PRIOR; + const unsigned int keyTAB = VK_TAB; + const unsigned int keyQ = 'Q'; + const unsigned int keyW = 'W'; + const unsigned int keyE = 'E'; + const unsigned int keyR = 'R'; + const unsigned int keyT = 'T'; + const unsigned int keyY = 'Y'; + const unsigned int keyU = 'U'; + const unsigned int keyI = 'I'; + const unsigned int keyO = 'O'; + const unsigned int keyP = 'P'; + const unsigned int keyDELETE = VK_DELETE; + const unsigned int keyEND = VK_END; + const unsigned int keyPAGEDOWN = VK_NEXT; + const unsigned int keyCAPSLOCK = VK_CAPITAL; + const unsigned int keyA = 'A'; + const unsigned int keyS = 'S'; + const unsigned int keyD = 'D'; + const unsigned int keyF = 'F'; + const unsigned int keyG = 'G'; + const unsigned int keyH = 'H'; + const unsigned int keyJ = 'J'; + const unsigned int keyK = 'K'; + const unsigned int keyL = 'L'; + const unsigned int keyENTER = VK_RETURN; + const unsigned int keySHIFTLEFT = VK_SHIFT; + const unsigned int keyZ = 'Z'; + const unsigned int keyX = 'X'; + const unsigned int keyC = 'C'; + const unsigned int keyV = 'V'; + const unsigned int keyB = 'B'; + const unsigned int keyN = 'N'; + const unsigned int keyM = 'M'; + const unsigned int keySHIFTRIGHT = VK_SHIFT; + const unsigned int keyARROWUP = VK_UP; + const unsigned int keyCTRLLEFT = VK_CONTROL; + const unsigned int keyAPPLEFT = VK_LWIN; + const unsigned int keyALT = VK_LMENU; + const unsigned int keySPACE = VK_SPACE; + const unsigned int keyALTGR = VK_CONTROL; + const unsigned int keyAPPRIGHT = VK_RWIN; + const unsigned int keyMENU = VK_APPS; + const unsigned int keyCTRLRIGHT = VK_CONTROL; + const unsigned int keyARROWLEFT = VK_LEFT; + const unsigned int keyARROWDOWN = VK_DOWN; + const unsigned int keyARROWRIGHT = VK_RIGHT; + const unsigned int keyPAD0 = 0x60; + const unsigned int keyPAD1 = 0x61; + const unsigned int keyPAD2 = 0x62; + const unsigned int keyPAD3 = 0x63; + const unsigned int keyPAD4 = 0x64; + const unsigned int keyPAD5 = 0x65; + const unsigned int keyPAD6 = 0x66; + const unsigned int keyPAD7 = 0x67; + const unsigned int keyPAD8 = 0x68; + const unsigned int keyPAD9 = 0x69; + const unsigned int keyPADADD = VK_ADD; + const unsigned int keyPADSUB = VK_SUBTRACT; + const unsigned int keyPADMUL = VK_MULTIPLY; + const unsigned int keyPADDIV = VK_DIVIDE; + +#else + // Define random keycodes when no display is available. + // (should rarely be used then!). + const unsigned int keyESC = 1U; //!< Keycode for the \c ESC key (architecture-dependent) + const unsigned int keyF1 = 2U; //!< Keycode for the \c F1 key (architecture-dependent) + const unsigned int keyF2 = 3U; //!< Keycode for the \c F2 key (architecture-dependent) + const unsigned int keyF3 = 4U; //!< Keycode for the \c F3 key (architecture-dependent) + const unsigned int keyF4 = 5U; //!< Keycode for the \c F4 key (architecture-dependent) + const unsigned int keyF5 = 6U; //!< Keycode for the \c F5 key (architecture-dependent) + const unsigned int keyF6 = 7U; //!< Keycode for the \c F6 key (architecture-dependent) + const unsigned int keyF7 = 8U; //!< Keycode for the \c F7 key (architecture-dependent) + const unsigned int keyF8 = 9U; //!< Keycode for the \c F8 key (architecture-dependent) + const unsigned int keyF9 = 10U; //!< Keycode for the \c F9 key (architecture-dependent) + const unsigned int keyF10 = 11U; //!< Keycode for the \c F10 key (architecture-dependent) + const unsigned int keyF11 = 12U; //!< Keycode for the \c F11 key (architecture-dependent) + const unsigned int keyF12 = 13U; //!< Keycode for the \c F12 key (architecture-dependent) + const unsigned int keyPAUSE = 14U; //!< Keycode for the \c PAUSE key (architecture-dependent) + const unsigned int key1 = 15U; //!< Keycode for the \c 1 key (architecture-dependent) + const unsigned int key2 = 16U; //!< Keycode for the \c 2 key (architecture-dependent) + const unsigned int key3 = 17U; //!< Keycode for the \c 3 key (architecture-dependent) + const unsigned int key4 = 18U; //!< Keycode for the \c 4 key (architecture-dependent) + const unsigned int key5 = 19U; //!< Keycode for the \c 5 key (architecture-dependent) + const unsigned int key6 = 20U; //!< Keycode for the \c 6 key (architecture-dependent) + const unsigned int key7 = 21U; //!< Keycode for the \c 7 key (architecture-dependent) + const unsigned int key8 = 22U; //!< Keycode for the \c 8 key (architecture-dependent) + const unsigned int key9 = 23U; //!< Keycode for the \c 9 key (architecture-dependent) + const unsigned int key0 = 24U; //!< Keycode for the \c 0 key (architecture-dependent) + const unsigned int keyBACKSPACE = 25U; //!< Keycode for the \c BACKSPACE key (architecture-dependent) + const unsigned int keyINSERT = 26U; //!< Keycode for the \c INSERT key (architecture-dependent) + const unsigned int keyHOME = 27U; //!< Keycode for the \c HOME key (architecture-dependent) + const unsigned int keyPAGEUP = 28U; //!< Keycode for the \c PAGEUP key (architecture-dependent) + const unsigned int keyTAB = 29U; //!< Keycode for the \c TAB key (architecture-dependent) + const unsigned int keyQ = 30U; //!< Keycode for the \c Q key (architecture-dependent) + const unsigned int keyW = 31U; //!< Keycode for the \c W key (architecture-dependent) + const unsigned int keyE = 32U; //!< Keycode for the \c E key (architecture-dependent) + const unsigned int keyR = 33U; //!< Keycode for the \c R key (architecture-dependent) + const unsigned int keyT = 34U; //!< Keycode for the \c T key (architecture-dependent) + const unsigned int keyY = 35U; //!< Keycode for the \c Y key (architecture-dependent) + const unsigned int keyU = 36U; //!< Keycode for the \c U key (architecture-dependent) + const unsigned int keyI = 37U; //!< Keycode for the \c I key (architecture-dependent) + const unsigned int keyO = 38U; //!< Keycode for the \c O key (architecture-dependent) + const unsigned int keyP = 39U; //!< Keycode for the \c P key (architecture-dependent) + const unsigned int keyDELETE = 40U; //!< Keycode for the \c DELETE key (architecture-dependent) + const unsigned int keyEND = 41U; //!< Keycode for the \c END key (architecture-dependent) + const unsigned int keyPAGEDOWN = 42U; //!< Keycode for the \c PAGEDOWN key (architecture-dependent) + const unsigned int keyCAPSLOCK = 43U; //!< Keycode for the \c CAPSLOCK key (architecture-dependent) + const unsigned int keyA = 44U; //!< Keycode for the \c A key (architecture-dependent) + const unsigned int keyS = 45U; //!< Keycode for the \c S key (architecture-dependent) + const unsigned int keyD = 46U; //!< Keycode for the \c D key (architecture-dependent) + const unsigned int keyF = 47U; //!< Keycode for the \c F key (architecture-dependent) + const unsigned int keyG = 48U; //!< Keycode for the \c G key (architecture-dependent) + const unsigned int keyH = 49U; //!< Keycode for the \c H key (architecture-dependent) + const unsigned int keyJ = 50U; //!< Keycode for the \c J key (architecture-dependent) + const unsigned int keyK = 51U; //!< Keycode for the \c K key (architecture-dependent) + const unsigned int keyL = 52U; //!< Keycode for the \c L key (architecture-dependent) + const unsigned int keyENTER = 53U; //!< Keycode for the \c ENTER key (architecture-dependent) + const unsigned int keySHIFTLEFT = 54U; //!< Keycode for the \c SHIFTLEFT key (architecture-dependent) + const unsigned int keyZ = 55U; //!< Keycode for the \c Z key (architecture-dependent) + const unsigned int keyX = 56U; //!< Keycode for the \c X key (architecture-dependent) + const unsigned int keyC = 57U; //!< Keycode for the \c C key (architecture-dependent) + const unsigned int keyV = 58U; //!< Keycode for the \c V key (architecture-dependent) + const unsigned int keyB = 59U; //!< Keycode for the \c B key (architecture-dependent) + const unsigned int keyN = 60U; //!< Keycode for the \c N key (architecture-dependent) + const unsigned int keyM = 61U; //!< Keycode for the \c M key (architecture-dependent) + const unsigned int keySHIFTRIGHT = 62U; //!< Keycode for the \c SHIFTRIGHT key (architecture-dependent) + const unsigned int keyARROWUP = 63U; //!< Keycode for the \c ARROWUP key (architecture-dependent) + const unsigned int keyCTRLLEFT = 64U; //!< Keycode for the \c CTRLLEFT key (architecture-dependent) + const unsigned int keyAPPLEFT = 65U; //!< Keycode for the \c APPLEFT key (architecture-dependent) + const unsigned int keyALT = 66U; //!< Keycode for the \c ALT key (architecture-dependent) + const unsigned int keySPACE = 67U; //!< Keycode for the \c SPACE key (architecture-dependent) + const unsigned int keyALTGR = 68U; //!< Keycode for the \c ALTGR key (architecture-dependent) + const unsigned int keyAPPRIGHT = 69U; //!< Keycode for the \c APPRIGHT key (architecture-dependent) + const unsigned int keyMENU = 70U; //!< Keycode for the \c MENU key (architecture-dependent) + const unsigned int keyCTRLRIGHT = 71U; //!< Keycode for the \c CTRLRIGHT key (architecture-dependent) + const unsigned int keyARROWLEFT = 72U; //!< Keycode for the \c ARROWLEFT key (architecture-dependent) + const unsigned int keyARROWDOWN = 73U; //!< Keycode for the \c ARROWDOWN key (architecture-dependent) + const unsigned int keyARROWRIGHT = 74U; //!< Keycode for the \c ARROWRIGHT key (architecture-dependent) + const unsigned int keyPAD0 = 75U; //!< Keycode for the \c PAD0 key (architecture-dependent) + const unsigned int keyPAD1 = 76U; //!< Keycode for the \c PAD1 key (architecture-dependent) + const unsigned int keyPAD2 = 77U; //!< Keycode for the \c PAD2 key (architecture-dependent) + const unsigned int keyPAD3 = 78U; //!< Keycode for the \c PAD3 key (architecture-dependent) + const unsigned int keyPAD4 = 79U; //!< Keycode for the \c PAD4 key (architecture-dependent) + const unsigned int keyPAD5 = 80U; //!< Keycode for the \c PAD5 key (architecture-dependent) + const unsigned int keyPAD6 = 81U; //!< Keycode for the \c PAD6 key (architecture-dependent) + const unsigned int keyPAD7 = 82U; //!< Keycode for the \c PAD7 key (architecture-dependent) + const unsigned int keyPAD8 = 83U; //!< Keycode for the \c PAD8 key (architecture-dependent) + const unsigned int keyPAD9 = 84U; //!< Keycode for the \c PAD9 key (architecture-dependent) + const unsigned int keyPADADD = 85U; //!< Keycode for the \c PADADD key (architecture-dependent) + const unsigned int keyPADSUB = 86U; //!< Keycode for the \c PADSUB key (architecture-dependent) + const unsigned int keyPADMUL = 87U; //!< Keycode for the \c PADMUL key (architecture-dependent) + const unsigned int keyPADDIV = 88U; //!< Keycode for the \c PADDDIV key (architecture-dependent) +#endif + + const double PI = 3.14159265358979323846; //!< Value of the mathematical constant PI + + // Define a 10x13 binary font (small sans). + static const char *const data_font_small[] = { + " UwlwnwoyuwHwlwmwcwlwnw[xuwowlwmwoyuwRwlwnxcw Mw (wnwnwuwpwuypwuwoy" + "ZwnwmwuwowuwmwnwnwuwowuwfwuxnwnwmwuwpwuypwuwZwnwnwtwpwtwow'y Hw cwnw >{ jw %xdxZwdw_wexfwYwkw 7yowoyFx=w " + "ry qw %wuw !xnwkwnwoyuwfwuw[wkwnwcwowrwpwdwuwoxuwpwkwnwoyuwRwkwnwbwpwNyoyoyoyoy;wdwnxpxtxowG|!ydwnwuwowtwow" + "pxswqxlwnxnxmwDwoyoxnyoymwp{oyq{pyoy>ypwqwpwp{oyqzo{q{pzrwrwowlwqwswpwnwqwsxswpypzoyqzozq}swrwrwqwtwswswtxsxswq" + "ws}qwnwkwnydwew_wfwdwkwmwowkw(w0wmwmwGwtwdxQw swuwnwo{q{pynwp|rwtwtwqydwcwcwcwmwmxgwqwpwnzpwuwpzoyRzoyoyexnynwd" + "z\\xnxgxrwsxrwsyswowmwmwmwmwmwmwo}ryp{q{q{q{nwmwnwmwozqxswpyoyoyoyoyeyuwswrwrwrwrwrwrwrwrwqwrwmwtwnwmwnwuwpwuyp" + "wuwoyZwmwnwuwowuwmwqwkwuwowuwoxnwuxowmwnwuwpwuypwuwZwmwnwuwowuwnwowmwtw\\wuwuwqwswqwswqwswqwswEwqwtweypzr~qyIw " + "rwswewnwuwowuwozswtwuwqwtwmwnwlwowuwuwowOxpxuxqwuwowswqwswoxpwlwjwqwswqwswy~}P{|k~-{|w~}k{|w~}Ww~|S{|k~X{|v~vv~|Y{|}k~}|Z{|y~" + "}y|xy|}w~| s{|}k~}|Z{|l~|V{}p~}\"{|y~}|w{|}w~|V{|}|u{|v~P{}x~} {{}h~} N{|~y}y|}x~|S{|v~}|y{|}w~}2{|w~y}x~|g{}x" + "~|k{|w~y}x~|g{}x~|kx}|w{|}w~}k{}x~}%{}t~|P{}t~|P{}t~|P{}t~|P{}t~|P{}t~}W{|[~}e{}f~}b{}c~|a{}c~|a{}c~|a{}c~|X{}w" + "~}M{}w~}M{}w~}M{}w~}Z{|d~}|`{}t~}kv~b{|g~}]{|g~}]{|g~}]{|g~}]{|g~}){|g~|{|w~|h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f" + "{|v~h{}w~}f{|v~|j{|v~|b{}w~}L{|u~}|w{|}v~|W{|w~|Iw~}Qw~x{}x~|V{}y~}x{}s~|X{|v~|wv~}Vx~}v{|x~| D{}x~}I{}w~Q{}x~|" + "xw~U{}w~}w{|v~T{|w~|J{|w~Q{|x~}x{|x~|V{|v~vv~|T{}q~}|Wx~|x{}s~T{|w~I{|w~|R{|x~}x{}x~|Vx~}x{}s~|X{|v~vv~| Fw~}J{" + "|w~|R{|x~}x{|x~}Uv~|w{}w~}Q{|w~|Ww~}Hv~}w{}w~} Pw~}y{|x~}cY~ i{}y~|#{|w~}Qm~|`m~}w{|m~|\\{}v~| ;{}`~} -" + "{|r~x}t~}$v~}R{}x~}vw~}S{|w~t{|x~}U{|y~|_{|w~}w{}w~|n{}x~}_{|t~w}u~|Q{}x~}K{}w~N{}x~}Jx~ +{|w~Xs~y}s~|\\m~}X{}" + "f~\\{}g~}R{|s~}\\{|g~}Y{|i~|`{}c~|_{|s~w}s~}]{|s~x}s~ hr~}r~|[{|f~}Xs~}Y{}d~|\\{|c~}g{}b~|^{}c~|`{}e~_{|a~|g{" + "}w~}hv~|Y{}w~}M{}w~}W{}w~}n{|u~|_{}w~}V{}s~}jr~|h{}s~|lv~c{|p~}q~}^{}f~}_{|p~}q~}`{}e~[{}q~}p~dZ~g{|v~h{}w~}h{|" + "v~|f{|v~p{|v~m{|t~}m{}w~}m{|v~|m{}v~c{}v~jv~}e\\~]{|w~}Nw~}D{|w~|Sp~| ww~|!w~} `{|w~|${}w~}!w~}Cv~Lv~Tw~}Dv~ " + " Ov~ !{}w~}Mw~|N{|v~ :{}v~|s{|v~V{|t}|V{|t~s}w~| p{|v~ {{|v~|t{|v~|Vs~}W{}c~|_{}d~}c{|d~|W{|v~Y{}^~|iv~" + "}r{|v~qv~}f{|p~}q~}${}r~} v{}w~ v{}q~| ?y~}Ps~x}u~,v~k{}w~|Ww~|Su~}v|}w~X{|v~vv~|Z{}v~}y|wy|}v~}[{|}q{}x~} t{}" + "v~}y|wy|}v~}&{}w~|x{|w~}#y|r{}x~}Kw~|R{|w~ {{}p~}v|x~} H{}x~|S{}w~t{}w~|3x|x{}x~|h{|x~}j{|}|x{}x~|h{|x~}`{|w~l{" + "|w~$s~}Ps~}Ps~}Ps~}Ps~}Pr~W{}[~}g{|c~}c{}c~|a{}c~|a{}c~|a{}c~|X{}w~}M{}w~}M{}w~}M{}w~}Z{|b~}a{}s~|lv~c{|p~}q~}_" + "{|p~}q~}_{|p~}q~}_{|p~}q~}_{|p~}q~}+{|p~}q~}w~|g{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}e{}v~jv~}a{}w~}Lu~r{" + "|v~V{|w~J{}x~}Q{}x~|w{}x~Vx~|w{}u~}Vv|vv|U{}x~}x|}w~ Bw~|K{|w~|R{|x~}w{|x~}Vu|vv|S{|w~K{|w~|Qx~}v{}x~Uv|vv|T{|}" + "t~}|Tx~|w{|u~|S{}x~}Jw~}Qw~vw~Vx~|w{}u~}Vv|vv| Dw~|Kw~|Qw~v{}x~|Vv|vv|Pw~|Vw~}Hv|uv| G{|t}|P{|t}|P{|t}|P{|t}|P{" + "|t}|Lw~|xw~c{|[~} iy~}\"u~|S{|l~a{}l~|x{}l~]{}t~ ={|^~} .{|u~}|u{|}w~}$v~}R{}x~}vw~}S{}x~}t{}x~}Xy|y}y~y}x" + "|cw~}u{}w~o{|w~^u~}t{|}y~|Q{}x~}Kw~|N{|w~|T{}sx~s{} 4{}x~}Y{}v~}|v{}u~\\m~}X{}v~y}|wy|s~]{}x~}x|v{|}t~}Sr~}\\{" + "|v~k|Z{|t~}|v{|y}y~|`h|u~^t~|u{|}u~|^u~}|v{|}v~} iv~y|v{|t~]{|o~y}p~|[{|r~|Z{}w~}q|}s~]{|s~}|t{|}u~}g{}w~}r|y" + "}q~}_{}w~}h|_{}w~}j|`{|s~}|s{|}t~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}o{}u~|^{}w~}V{}r~k{|r~|h{}r~lv~d{|t~}|uy|s~_{}w~}" + "s|y}t~}a{|t~}|uy|s~a{}w~}s|y}s~]{}u~}|ty|}v~dn|}v~}n|g{|v~h{}w~}gv~}f{}w~}ov~|n{|t~}mv~|l{}v~|o{|v~|bv~}l{}v~dc" + "|u~}]{|w~}N{}w~D{|w~|T{}o~| x{|w~!w~} `{|w~|${}w~ w~} >w~}Dv~ Ov~ !{}w~|Mw~|M{}w~ :v~|q{}w~|Xp~}X{}v~|p{|" + "}| o{}w~| v~|r{|v~W{|r~|X{}v~}i|^{}w~}h|d{|s~}y|xy|}s~}[{|y}u~y}y|]{}w~}h|v~|iv~}r{|v~qv~}g{|t~}|uy|s~&{}p" + "~} w{}w~ w{}o~| @y~}Q{}v~}|u{|}y~,{|w~}m{|w~}Vw~|T{|v~|s{|}~({|w~}|o{|}w~|P{}x~| w{|w~}|o{|}w~|(x~}tw~ rw~K{}x" + "~|Rw~ {{}o~}w{|x~} H{}x~|T{|w~r{}x~}-{}x~|hw~|d{}x~|hw~|_{}x~|mw~|%{|r~|R{|r~|R{|r~|R{|r~|R{|r~|R{}r~|Y{|v~|y{|" + "v~}h|h{|s~}|t{|}u~}c{}w~}h|`{}w~}h|`{}w~}h|`{}w~}h|W{}w~}M{}w~}M{}w~}M{}w~}Z{|v~r|x}q~b{}r~lv~d{|t~}|uy|s~a{|t~" + "}|uy|s~a{|t~}|uy|s~a{|t~}|uy|s~a{|t~}|uy|s~-{|t~}|u{|}q~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}dv~}l{}v~`" + "{}w~}M{|v~p{}w~|V{}x~}L{}x~}Q{|x~|ux~}Wx~|v{|w~} {{}q~| Aw~|Lw~|Qw~u{}x~| y{|x~}Lw~|Q{}x~tx~}#{|}r~}Rx~u{|}y~}|" + "Q{}x~}L{}x~}Q{}x~|v{|x~}Wx~|v{}w~} j{|w~L{}x~}Q{}x~|u{}x~ x{}x~}Uw~} b{|}p~}|V{|}p~}|V{|}p~}|V{|}p~}|V{|}p~}|" + "P{|w~|xx|av~|fv~| j{|y~|#{}t~Sk~|c{|k~}y{|k~}_{|s~} ?{}t~}y| u{|u~|p{}y~}$v~}R{}x~}vw~}Sw~|tw~|[{|}m~}|h{" + "|w~sw~|p{}x~|_{}v~|q{|}|Q{}x~}L{}w~Lw~}U{}y~|ux~u{|y~}U{|x}| `w~|Z{|v~}s{|v~}]w~y}y|{}w~}X{}x~|p{|u~|^y}|n{|u~" + "|U{}x~y}w~}\\{|w~}K{|u~}o{}|Mv~|_{}v~}q{|u~_{}v~}r{|v~| jy~}|qu~|_{}t~}y|s{|}t~}\\{}w~}w~}Z{}w~}o{|u~}_{|t~|n" + "{|}x~}g{}w~}n{|}t~}`{}w~}L{}w~}P{|t~}m{|}w~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}p{}u~|]{}w~}V{}w~}w~|l{}r~|h{}r~|mv~e{|" + "u~}|p{|t~`{}w~}q{|}u~|c{|u~}|p{|t~b{}w~}p{}u~|_{|u~|n{|}y~W{|v~|Z{|v~h{}w~}g{|v~fv~|o{}w~}n{}x~}w~mv~|kv~}ov~}a" + "{|v~|n{|v~|M{}v~}\\{|w~}N{|w~|E{|w~|U{}v~}{|u~| x{|x~}\"w~} `{|w~|$v~ w~} >w~}Dv~ Ov~ !v~Lw~|M{}w~| <{|w~" + "}p{|w~}Xn~|Zv~ _{|v~ !{|w~}p{}w~}X{}w~}w~}W{}v~|M{}w~}R{|t~|p{|t~|_{|}l~}|`{}w~}hv~|iv~}r{|v~qv~}h{|u~}|p{|" + "t~({}n~} x{}w~ x{}m~| Ay~}R{|v~}p{}+{}w~|nv~Uw~|T{}w~| x{|w~|k{|w~|Q{|x~| x{|w~|k{|w~|*{|x~rx~|R{|w}Fw~Kw~|S{}" + "x~| {|n~}w{|x~} H{}x~|T{}x~}qw~|.{}x~|i{}x~}c{}x~|i{}x~}^{}x~|n{}x~}${}w~}w~}R{}w~}w~}R{}w~}w~}R{}w~}w~}R{}w~}w" + "~}Rv~|w~}Y{}w~}x{|v~U{|t~|n{|}x~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~n{|}s~c{}r~|mv~e{|u~}|p{|" + "t~c{|u~}|p{|t~c{|u~}|p{|t~c{|u~}|p{|t~c{|u~}|p{|t~/{|u~}|p{}t~}e{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}d{|v" + "~|n{|v~|`{}w~}M{}w~}ow~}U{}x~|N{|w~Px~}t{|x~|Xx|sy| w{}s~| @{|w~M{}x~|Q{}x~|tw~ x{}x~}N{}x~|Q{|x~|t{|x~|&{}t~}v" + "~} t{}x~|N{|x~}Q{|x~}t{}x~|Xx|sy| g{|x~}N{|x~}Q{|x~}sx~} {{|x~}Tw~} d{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|j~|R{|w~Z{}w~}" + "g{}w~} Ay|J{}y~#{|s~}Tk~}c{}j~|{}j~_q~| A{}u~} q{}v~|n{}~}$v~}R{}x~}vw~}Sw~t{|w~\\{|h~|i{}x~}s{}x~}q{|x~}^" + "v~|C{}x~}Lw~}L{}w~V{|v~|wx~w{|v~|V{}w~ a{|w~Yv~}q{|v~|^{}y|u{}w~}Xy}|m{|u~M{|v~}V{|w~|}w~}\\{|w~}Ku~|?{|v~^u~o" + "{}v~|a{|v~}p{}v~ j{~|nv~}`u~}|l{|}u~]v~{v~Z{}w~}mu~_u~}j{|y~}g{}w~}l{|}u~}a{}w~}L{}w~}Q{|u~}i{|}y~|g{}w~}hv~|" + "Y{}w~}M{}w~}W{}w~}q{}u~|\\{}w~}V{}w~|w~}lw~|v~|h{}q~mv~f{|u~}m{|u~}a{}w~}o{}v~}d{|u~}m{|u~}c{}w~}o{|u~_{}v~|j{|" + "W{|v~|Z{|v~h{}w~}fv~|h{}v~n{}w~}nw~|w~|o{|v~j{|v~}q{}v~_{}v~nv~}M{|u~[{|w~}Mw~}E{|w~|V{}v~}x{|u~| vw~} `{|w~|$" + "w~} w~} >w~}Dv~ Ov~ !v~Lw~|M{}w~| <{}w~|ow~}Xm~|[v~ ^v~| \"v~|p{|v~Xv~{v~V{}v~|N{}w~}Ru~}l{}u~|b{|g~}" + "|b{}w~}hv~|iv~}r{|v~qv~}i{|u~}m{|u~}*{}l~} y{}w~ y{}k~| By~}R{}v~ y{|w~}o{|w~}Uw~|T{}w~ x{|x~}g{}x~|R{|x~} y{|" + "x~}g{}x~|+{}y~}r{}y~}R{}w~Fx~}M{|}w~ Mm~}w{|x~} H{}x~|Tw~p{}x~|.{}x~|j{|w~b{}x~|j{|w~]w~n{|w~#v~{v~Rv~{v~Rv~{v~" + "Rv~{v~Rv~{v~S{|w~}{}w~|Zv~|x{|v~Uu~}j{|y~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~k{}t~d{}q~mv~f{|" + "u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}1{|u~}m{|u~}e{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w" + "~}c{}v~nv~}_{}w~}Mv~n{}w~Tw}N{|x}P{|x}r{|x} F{|}x~}| ={|x}|O{|x}|Px}|s{|x}| xw|Nw|Pw|rw|'{|v~}|y{|v~} tw}Nw}P{|" + "x}rx}| 6w|Nw|Ox|rw| Nw~} e{}h~}\\{}h~}\\{}h~}\\{}h~}\\{}h~}S{|w~Z{|v~gv~| Ay~}L{|y~}${|q~}V{|j~ci~}|i~|a{}p~|" + "Oy|Uw|jw|Vu|Wv|kw|b{}v~} p{|v~|l{|}$v~}R{}x~}vw~}T{|x~}t{|x~}]{|g~|i{}x~|s{|w~qw~|^v~B{}x~}M{|w~|L{|w~}V{|}" + "w~}xx~x{}w~}|U{}w~ a{}w~Z{|v~o{}w~}U{}w~}X{|j{}v~|M{}v~Vw~}{}w~}\\{|w~}L{|v~|>v~}_{|v~|nv~}a{}v~nv~| \\{}w~}" + "b{|u~|h{|}v~|`{|w~}{}w~|[{}w~}m{|v~|a{}v~}gy}g{}w~}j{}u~|b{}w~}L{}w~}Q{}v~}f{|~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}r{}" + "u~|[{}w~}V{}w~y|w~m{|w~{v~|h{}w~}v~|nv~f{}v~}ju~|b{}w~}nu~d{}v~}ju~|d{}w~}n{}v~|`v~}D{|v~|Z{|v~h{}w~}f{}w~}hv~}" + "n{|v~o{|w~{}x~}o{}w~}i{}v~|s{|v~|^v~}p{}v~M{|u~|[{|w~}M{}x~}E{|w~|W{}v~|v{|u~| ww~} `{|w~|$w~} w~} >w~}Dv~ " + "Ov~ !v~Lw~|M{|w~| <{}w~|ow~}Xy~}w|}t~[v~| _{}w~} #{|w~}n{}w~|Z{|w~}{}w~|Vu~|O{}w~}S{}v~}j{}u~c{}d~|c{}w~" + "}hv~|iv~}r{|v~qv~}i{}v~}ju~|,{}v~y}w~|v~} {{}w~ {{}v~y}w~|u~| Cy~}R{}w~}R{|ey|_{}w~|pv~Tw~|T{}w~ y{|x~}e{}x~|\\" + "{|}p~} {{|x~}e{}x~|,{}y~}r{}y~}R{}w~G{}x~|Rq~| N{|m~}w{|x~} H{}x~|U{|w~p{|x~}.{}x~|j{}x~|b{}x~|j{}x~|_{|w~|n{}" + "x~|${|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{}w~|{|w~}[{|v~w{|v~V{}v~}gy}c{}w~}M{}w~}M{}w~}M{}w~" + "}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~j{|u~}e{}w~}v~|nv~f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|c{}d{}|d{}v~}" + "k{}u~|f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}bv~}p{}v~^{}m~y}|Yv~o{|}w~ Py~}|u{|v~} 2w~} f{" + "}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~T{|w~Yv~|i{|v~ A{}x~}M{}y~|$o~|W{|j~ch~}i~}" + "b{}n~T{|}t~y}|Zw~}kw~}X{}u~|X{}w~|m{}w~|d{|v~| ov~}j{|$v~}R{}x~}vw~}T{}x~}t{}x~}]u~}|{|y~|y{|y}x~|iw~|rw~r{" + "}x~}]v~B{}x~}Mv~Jv~T{|}w~|{x~{|w~}|S{}w~ aw~}Z{}w~}o{|v~U{}w~}Ev~}M{|v~W{}w~y{}w~}\\{|w~}Lv~}>{|v~|_{|v~m{}w~}" + "av~|n{|v~ 8{|y}6{|~|4{}v~c{|v~}d{|v~`{}w~|{|w~}[{}w~}lv~|b{|v~}e{|g{}w~}i{}u~b{}w~}L{}w~}R{|v~}dy|g{}w~}hv~|Y{}" + "w~}M{}w~}W{}w~}s{}u~Y{}w~}V{}w~|{w~|nw~}{v~|h{}w~y|v~nv~g{|v~}i{|u~b{}w~}n{|v~|f{|v~}i{|u~d{}w~}n{|v~|a{|v~C{|v" + "~|Z{|v~h{}w~}f{|v~|j{|v~|mv~|p{|w~{|x~}ov~|hv~}sv~}]{|v~|r{|v~|Mu~|Z{|w~}M{|w~E{|w~|X{}v~|t{|u~| xw~} `{|w~|$w" + "~} w~} >w~}Dv~ Ov~ !w~}Lw~|M{|w~| {|v~]{|v~m{}w~}b{|w~}l{}w~}W{|v}M{}v~D{}r~}6{|r~}|>{|v~|e{}w~|^{|w~|dv~w{|v~\\{}w~}lv~|c{}v~N{}w~}g{}v~|d{" + "}w~}L{}w~}S{}v~L{}w~}hv~|Y{}w~}M{}w~}W{}w~}vu~}V{}w~}V{}w~|yw~}pw~}yv~|h{}w~|y{}w~}pv~h{}v~e{}v~|d{}w~}mv~}g{}v" + "~e{}v~|f{}w~}mv~}a{|v~C{|v~|Z{|v~h{}w~}dv~|l{|v~k{|v~q{|w~x{}x~}q{}w~}e{}v~wv~}Y{|v~|v{|v~|N{|v~}W{|w~}L{|w~F{|" + "w~|[{}v~l{}v~ S{|}k~|Zw~}y{|o~}V{|k~|\\{|o~}y{|w~|\\{|m~}X{}k~}Y{|o~}y{|w~|`w~}y{|o~}Sv~Lv~Tw~}o{|v~}Wv~_w~}y{|" + "o~|v{|o~|ew~}y{|o~}Y{|}n~}|[w~}y{|o~}Y{|o~}y{|w~|Zw~}y{|r~|[{}j~[{}i~]{|w~|m{}w~|b{}w~|k{|w~}i{|w~}q{|u~|q{|w~|" + "h{|v~|o{|v~}b{}w~|k{|w~}`d~Uw~}Lw~|M{|w~| n{|o~}vw~|av~o{}w~|M{|v~[{|o~}|U{}k~}]w~}y{|o~}_u~|k{|w~}Wu~X{|w~|m{" + "}w~|dv~|h{|v~_{}x~}x{}s~}__~|dv~t{}w~t{|w~}\\{}n~}Y{|}e~}f{|`~b{|w~}l{}w~|\\v~w{|v~T{|u~R{}w~}U{}v~dv~}i{}u~u{|" + "v~u{|u~|g{}w~}hv~|iv~}r{|v~qv~|k{}v~e{}v~|c{~}I{|y~}w{}w~w{|y~}I{}~|U{}w~T{}~|k{}~|\\y~}w{}w~w{|y~| v~}P{}k~Z{|" + "v~S{|v~}x{|}v~}|y{|v~}^{|w~}u{|w~}Rw~|S{|u~}${}y~|v{}v~}|wy|}y~u{|y~}c{|x~}r{|x~}Q{|q{| W{}y~|uw~vy|v~u{|y~}-w~" + "|v{|w~Q{}w~K{|w~|I{|w~'{|w~|m{}w~|a{}m~}w{|x~} H{}x~|U{|x~}p{|x~}]{|q{|X{}x~|m{|w~_{}x~|m{|w~]{|}w~}q{|w~Pv~|Sv" + "~w{|v~Vv~w{|v~Vv~w{|v~Vv~w{|v~Vv~w{|v~W{|v~vv~^{|v~|v{|v~X{}v~J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z" + "{|v~g{|v~}g{}w~|y{}w~}pv~h{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|g{|u~l{}v~}g{}v~kw~}{}v~g{|v~h{" + "}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}`{|v~|v{|v~|\\{}w~}s|y}t~}_w~}u{|v~|Y{|}k~|Z{|}k~|Z{|}k~|Z{|}k~|Z{|}k~|Z{|" + "}k~|d{|}k~|v{|m~}_{|k~|[{|m~}W{|m~}W{|m~}W{|m~}Rv~Lv~Lv~Lv~Q{|}l~\\w~}y{|o~}Y{|}n~}|X{|}n~}|X{|}n~}|X{|}n~}|X{|" + "}n~}|S{}u~S{|}n~}{|x~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|b{}w~|k{|w~}aw~}y{|o~}^{}w~|k{|w~} X{|w~}" + "t{}w~t{|w~}f{|w~}h{|w~}f{|w~}yy|p{|}y{|w~}f{|w~}ly|y{|w~}f{|w~}h{|w~}X{}x~}X{|v~kv~| Cv~|Lx~&{|i~|Y{|m~}bU~|e{}" + "h~\\{|u~}|xy|}u~^w~}kw~}Yr~}X{}w~}ov~d{}w~ lv~| lv~}R{}x~}vw~}^{}Z~f{|w~|v{|y~|`w~|s{|w~tw~|[{|v~|D{}x~}Nw~" + "}H{}w~|Q{|t~|N{}w~ c{|w~|Zv~|lv~|W{}w~}E{}w~}M{}w~}Z{|w~|w{}w~}\\{|w~}N{|v~={}w~}\\v~|nv~|b{}w~}l{}v~W{}v~M{}v" + "~G{|}p~|6{|o~}@u~e{|w~|\\{}w~e{|w~}v{}w~|]{}w~}m{|v~|cv~}N{}w~}g{|v~}d{}w~}L{}w~}Sv~}L{}w~}hv~|Y{}w~}M{}w~}W{}w" + "~}x{|u~}U{}w~}V{}w~|y{}w~q{|w~|yv~|h{}w~|y{|v~pv~hv~}e{|v~}d{}w~}mv~}gv~}e{|v~}f{}w~}mv~}a{|v~|D{|v~|Z{|v~h{}w~" + "}d{}w~}l{}w~}jv~|r{|w~x{|x~}qv~|e{|v~}y{}v~W{}v~vv~}N{|u~V{|w~}Kw~|G{|w~|\\{}w~}j{}v~ T{}i~}[w~}{}m~}X{}j~|]{}m" + "~}{|w~|]{}j~Y{}k~}Z{}m~}{|w~|`w~}{|l~Tv~Lv~Tw~}p{}v~}Vv~_w~}{|m~|x{|m~|fw~}{|m~}[{|j~|\\w~}{}m~}[{}m~}{|w~|Zw~}" + "{|q~|\\{}i~[{}i~]{|w~|m{}w~|b{|w~}k{}w~|hw~}q{|u~}q{}w~|g{}v~ov~}a{|w~}k{}w~|`d~Uw~}Lw~|M{|w~| Gy|l{|Z{}m~}x{|w" + "~`v~p{|v~Kv~Z{|m~|X{}j~}]w~}{|l~`t~|l{}w~|X{|u~}Y{|w~|m{}w~|e{}v~f{}w~}b{|v~}y{|q~}`_~|dv~t{}w~t{|w~}^{|k~}[{|c" + "~}f{|`~b{}w~}l{}w~}]{|w~}vv~|T{|v~}S{}w~}Uv~}d{}v~j{|u~t{|v~t{|u~g{}w~}hv~|iv~}r{|v~r{|v~|kv~}e{|v~}dx~}I{|}v{}" + "w~v{|}I{}x~|V{}w~U{}x~|m{}x~|\\{|v{}w~vy| {{v~}R{|i~Z{|v~R{|v~}|q~}|v~}\\v~u{}w~Qw~|R{|t~|'{|y~}v{}w~}p{|t{}y~|" + "d{}x~|r{|x~}Ry}r{|~ X{|y~}tw~sw~|u{}y~|.{|w~}x|}w~|Q{}w~L{|w~|G{|x~}({|w~|m{}w~|a{}m~}w{|x~} H{}x~|U{|w~p{|x~}]" + "{~|r{|}Y{}x~|mw~|_{}x~|m{}x~|[{|w~|r{}x~|Pv~|T{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{}w~}" + "v{}w~}_{}w~}u{|v~Xv~}J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~fu~g{}w~|y{|v~pv~hv~}e{|v~}jv~}e{|v~}" + "jv~}e{|v~}jv~}e{|v~}jv~}e{|v~}f{|u~n{}v~}fv~}l{}x~}y{|v~|h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}_{}v~vv~}[" + "{}w~}q{|}u~|`w~}uv~W{}i~}[{}i~}[{}i~}[{}i~}[{}i~}[{}i~}e{}i~}x{}k~}a{}j~|\\{}j~Y{}j~Y{}j~Y{}j~Sv~Lv~Lv~Lv~R{}j~" + "}]w~}{|m~}[{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|j~|T{}u~T{|f~`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|b{|w~}k{}w~|a" + "w~}{}m~}_{|w~}k{}w~| Xw~}s{}w~s{}w~fw~}f{}w~fw~}y{|y~|r{|y~}y{}w~fw~}l{|y~}y{}w~fw~}f{}w~X{}x~}Wv~|m{|v~ C{}w~}" + "[{|}|o{|y~|&g~|Y{}n~|b{}V~e{|g~}]v~}r{|v~}_w~}kw~}Z{|r~}X{|v~p{|w~}dw~} pw|v~l| {{v~}R{}x~}vw~}^{}Z~f{|w~|v" + "{|y~|`{}x~}s{|x~}u{}x~}Y{}v~|E{}x~}O{|w~}H{}w~|S{|}r~}|P{}w~ c{|w~Yv~|lv~|W{}w~}Ev~|N{|v~|Zw~}v{}w~}\\{|w~}|}v" + "~y}|X{}w~}>{|v~|\\{}w~}o{|v~a{}w~}l{}v~W{}v~M{}v~J{|}p~}|2{|}p~}|D{}v~|e{}x~}p{|}w~}|vx|uw~|f{}w~|v{|w~}]{}w~}m" + "{}v~c{|v~|N{}w~}fv~}d{}w~}L{}w~}T{|v~|L{}w~}hv~|Y{}w~}M{}w~}W{}w~}y{|u~}T{}w~}V{}w~|y{|w~|r{}x~}xv~|h{}w~|x{}w~" + "}qv~i{|v~|dv~}d{}w~}mv~}h{|v~|dv~}f{}w~}n{|v~|`u~D{|v~|Z{|v~h{}w~}d{|v~m{|v~|j{}w~}r{}x~}x{|w~qv~|d{}v~y|v~|Vv~" + "}x{}v~Mu~|V{|w~}K{}x~}G{|w~|]{}w~}h{|v~ U{}u~v}s~}\\w~}|v~w}t~}Zr~v}v~|^{}t~w}v~}|w~|^{}t~v}t~Zv}v~s}[{}t~w}v~}" + "|w~|`w~}|u~x}t~}Uv~Lv~Tw~}q{}v~|Uv~_w~}|v~x}s~y{|v~x}s~fw~}|u~x}t~}]{|s~x}s~|]w~}|v~w}t~}]{|t~w}v~}|w~|Zw~}|t~}" + "x~|]{}t~u}u~[{|x}v~q}]{|w~|m{}w~|av~kv~g{}w~q{}t~qv~e{}v~q{}v~_v~|m{|v~_d~Uw~}Lw~|M{|w~| J{|}v~}r{}v~}|_{}u~w}u" + "~|y{}x~}`v~q{|v~}K{}w~|\\{}w~}p~}Z{}s~w}u~}]w~}|u~x}t~}as~m{|v~W{}t~Y{|w~|m{}w~|ev~|f{|v~c{|u~}yn~a_~|dv~t{}w~t" + "{|w~}_{|t~w}t~}]{|b~}f{|`~b{}w~|l{}w~}]{}w~|v{|w~}S{|v~}T{}w~}Uv~|d{|v~|k{}v~|t{|v~s{}v~|h{}w~}hv~|i{}w~}r{|v~r" + "{|v~|l{|v~|dv~}ev~}C{}w~C{}v~|W{}w~V{}v~n{|v~|W{}w~ sv~}S{|s~}y~x}v~Z{|v~Q{|e~}[{|w~}w{|w~}Qw~|R{}r~|){}y~|w{|w" + "~}g{|y~}dw~q{}x~}S{}~}s{}y~ X{}y~|tw~s{}x~}u{|y~}-{}p~}P{}w~M{|w~|F{|x~}({|w~|m{}w~|a{}m~}w{|x~} H{}x~|Tw~p{}x~" + "|]y~}s{|y~Z{}x~|n{|x~}^{}x~|n{|w~Y{|x~}s{|x~}Ov~|T{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}Xv" + "~u{|v~_v~|u{|v~Y{|v~|J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{}v~g{}w~|x{}w~}qv~i{|v~|dv~}k{|v~|d" + "v~}k{|v~|dv~}k{|v~|dv~}k{|v~|dv~}e{|u~p{}v~}f{|v~|m{}w~wv~}h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}^v~}x{}v" + "~Z{}w~}o{}v~}`w~}v{|w~|W{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}f{}u~v}s~}{s~w}t~}cr~v}" + "v~|]{}t~v}t~[{}t~v}t~[{}t~v}t~[{}t~v}t~Tv~Lv~Lv~Lv~S{}h~|^w~}|u~x}t~}]{|s~x}s~|\\{|s~x}s~|\\{|s~x}s~|\\{|s~x}s~" + "|\\{|s~x}s~|U{}u~U{|s~x}q~|`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|av~|m{|v~`w~}|v~w}t~}_v~|m{|v~ X{|w~" + "r{}w~rw~}h{|w~dw~}h{|w~y{|w~|t{|w~}yw~}h{|w~l{|w~}yw~}h{|w~dw~}Y{}x~}W{}w~}m{}w~} Xg|}v~s|e{|}x~}o{}y~&{}f~Y{|o" + "~}a{|V~f{|e~}_{|w~}p{|v~_w~}kw~}Z{}w~}v~Wv~|q{}w~}e{|w~ pc~} {{v~}R{|x}|v{|x}|^{}Z~f{|w~|v{|y~|`{|w~s{}x~}v" + "{|w~Wu~|F{|x}|O{}w~|H{|w~}U{|}w~|x~|w~}|R{}w~ c{}x~}Yv~|lv~|W{}w~}F{|v~N{|v~}Z{}w~u{}w~}\\{|k~}Z{}w~}x{|}u~y}|" + "L{}v~Zv~|pv~}a{|v~l{}v~|X{}v~M{}v~M{|}p~}|,{|}p~}|H{}v~|e{|w~q{|q~}y{}x~|v{|x~}fv~tv~]{}w~}n{}v~|c{|v~|N{}w~}f{" + "}v~d{}w~}L{}w~}T{}v~|L{}w~}hv~|Y{}w~}M{}w~}W{}w~}{|u~}S{}w~}V{}w~|xw~}rw~|xv~|h{}w~|x{|v~|rv~i{|v~|d{}v~d{}w~}n" + "{|v~|h{|v~|d{}v~f{}w~}n{}v~|`{}v~}|F{|v~|Z{|v~h{}w~}cv~|n{}v~i{}w~}rw~|ww~|s{|v~b{}q~}U{|v~|{|v~|N{}v~|U{|w~}K{" + "|w~G{|w~|^{}w~}f{|v~ V{}y~}|r{|u~|]r~|u{|u~}\\{}u~}s{|}y~|_{|u~|u{|}s~|_{}v~}|t{}v~}Vw~}T{|u~|u{|}s~|`r~|u{|u~|" + "Vv~Lv~Tw~}ru~|Tv~_r~|v{|}v~}{w~|u{}v~}gr~|u{|u~|^u~}|v{|}u~]r~|u{|u~|_{|u~|u{|}s~|Zr~}|v{|\\v~}|r{|}y~Wv~S{|w~|" + "m{}w~|a{}w~|m{|w~}g{}w~|rs~qw~}dv~}s{|v~|_{}w~}m{}w~|Nu~Uw~}Lw~|M{|w~| K{}r~u{|r~}a{|v~}|v{}v~yw~|`v~r{|u~|K{|w" + "~|]{}w~|xy|}t~}[u~}|s{|}~}]r~|u{|u~|ay|v~|n{}w~|X{|s~|Z{|w~|m{}w~|f{|v~dv~|e{|u~}|{|v~y|}v~}bx}u~q}u~x}|dv~t{}w" + "~t{|w~}_u~|u{|u~|_{|u~}|v{|}t~v}f{|q}u~p}b{}w~|l{|v~]v~tv~R{}v~}U{}w~}V{|v~|cv~}l{|v~}s{|v~s{|v~}h{}w~}hv~|i{}v" + "~r{|v~r{|v~|l{|v~|d{}v~fu~|C{}w~C{|u~|X{}w~W{}v~}m{}v~|X{}w~ sv~}T{|u~}|yy~}x{|}y~Z{|v~P{|g~}Y{}w~|xv~Pw~|T{|v~" + "}u~}*x~v{}w~ex~dw~qw~}U{|x~}t{}x~ Xx~sw~s{}x~}tx~,{|r~|O{}w~N{|w~|Dw~({|w~|m{}w~|a{|m~}w{|x~} H{}x~|T{}x~}qw~|]" + "x~}t{|x~|\\{}x~|nw~]{}x~|nw~|Xw~sw~|Ov~|Tv~tv~Xv~tv~Xv~tv~Xv~tv~Xv~tv~Y{|w~}tv~|a{|v~t{|v~Y{|v~|J{}w~}M{}w~}M{}" + "w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|x{|v~|rv~i{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{" + "}v~d{|u~r{}v~}e{|v~|n{}w~v{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}^{|v~|{|v~|Z{}w~}nu~`w~}v{}w~V{}y~}|r" + "{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|g{}y~}|r{|o~}|u{|}v~}e{}u~}s{|}y~|^{}v~}|" + "t{}v~}]{}v~}|t{}v~}]{}v~}|t{}v~}]{}v~}|t{}v~}Uv~Lv~Lv~Lv~T{}u~}|v{|}v~}^r~|u{|u~|^u~}|v{|}u~\\u~}|v{|}u~\\u~}|v" + "{|}u~\\u~}|v{|}u~\\u~}|v{|}u~U{}u~Uu~}|u{}u~|_{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{}w~}m{}w~|`r~|u{" + "|u~|`{}w~}m{}w~| Xw~|r{}w~r{|w~hw~|d{|w~hw~|yu~|v{|u~y{|w~hw~|m{|u~y{|w~hw~|d{|w~Y{}x~}Vv~mv~| XZ~}g{}t~oy~}'{}" + "e~}Y{}p~_W~|fc~|`v~n{}w~|`w~}kw~}Zv~|}w~|X{}w~}qv~|e{}x~} q{|c~| {{v~} y{|x~}t{}x~}]{|w~}v{|y~|_w~|u{|w~|vw" + "~|Wt~ p{}w~|H{|v~V{}w~}yx~y{}w~}S{}w~ cw~|Z{|v~k{}w~}W{}w~}Fv~}Qy|u~}Z{|w~|u{}w~}\\{|i~|\\v~|y{}p~}|Nv~}Z{|v~|" + "s{|v~}`{|v~lu~|X{}v~M{}v~P{|}p~}|b{|Z~}b{|}p~}|L{}v~}d{}x~|r{|n~{}x~|uw~|h{}w~}t{}w~|^{}w~}q{|}u~}b{}v~M{}w~}f{" + "}v~d{}w~}L{}w~}T{}v~K{}w~}hv~|Y{}w~}M{}w~}W{}w~}|u~}R{}w~}V{}w~|x{|w~s{}w~wv~|h{}w~|w{}w~}rv~i{}v~c{}v~d{}w~}n{" + "}v~|h{}v~c{}v~f{}w~}o{|u~_{|t~}|H{|v~|Z{|v~h{}w~}c{}v~nv~}i{|v~s{|w~|w{}x~}s{}w~}b{|q~S{}v~|v~}N{}v~}T{|w~}K{|w" + "~|H{|w~| s{}|m{}w~}]t~}q{}v~|^{}v~}ny|_u~q{}t~|`{|v~|q{|v~|Ww~}Tu~q{|t~|`t~}r{|v~}Vv~Lv~Tw~}t{|u~Rv~_t~}r{}v~}" + "y~}r{}v~gt~}r{|v~}_{}v~|r{|v~}^s~q{}v~_{}v~|r{}t~|Zs~T{|w~}m{|Wv~S{|w~|m{}w~|a{|w~}mv~|g{|w~}s{|s~|s{|w~|d{|v~|" + "u{|v~}]v~mv~N{}v~Tw~}Lw~|M{|w~| L{}p~w{|p~}bv~}s{}w~y|w~_v~wx|}t~}J{|w~}^{}w~r{}u~|]{|v~|Ot~}r{|v~}_{|v~nv~W{}s" + "~}Z{|w~|m{}w~|f{}w~}d{}w~}eu~}x{|w~|x{}v~|`{|w~}q{|w~}`v~t{}w~t{|w~}`{}v~q{}v~_u~}r{|v~}V{|w~}Wv~|l{|v~^{}w~}t{" + "}w~|R{}v~}V{}w~}V{|v~bv~}l{|v~|s{|v~r{}v~h{}w~}hv~|i{}v~r{|v~r{}v~k{}v~c{}v~gu~|B{}w~B{|u~|Y{}w~X{}v~}k{}v~|Y{}" + "w~ sv~}Tu~|wy~}u{|Z{|v~O{|u~}|x{|}v~}_{|p~}y{|p~}Ww~|Tw~}y{|t~|,y~}vw~|e{}y~dw~|s{}w~}V{|w~}u{}w~ Xy~}sw~s{}x~}" + "t{}y~*y}x~}|[m|}w~l|^{}w~C{|x~}({|w~|m{}w~|`m~}w{|x~} H{}x~|T{|w~|s{}x~}\\w~}u{|w~|]{}x~|o{}x~}]{}x~|o{}x~}Ww~t" + "{}x~}Nv~|U{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~|t{|w~}av~}t{|v~Y{}v~I{}w~}M{}w~}M{}w" + "~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|w{}w~}rv~i{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~c{|" + "u~t{}v~}d{}v~n{|w~|v{|v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}]{}v~|v~}Y{}w~}n{|v~|aw~}vv~V{}|m{}w~}]{}|m" + "{}w~}]{}|m{}w~}]{}|m{}w~}]{}|m{}w~}]{}|m{}w~}g{}|m{}r~|q{|v~|g{}v~}ny|_{|v~|q{|v~|_{|v~|q{|v~|_{|v~|q{|v~|_{|v~" + "|q{|v~|Vv~Lv~Lv~Lv~U{|v~}q{|v~|_t~}r{|v~}_{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}V{}u~V{}v~" + "|r{|v~}_{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|`v~mv~_s~q{}v~_v~mv~ X{|w~q{}w~q{}x~|j{|w~b{}x~|j{|w~wu~" + "|x{|u~|x{}x~|j{|w~m{|u~|x{}x~|j{|w~b{}x~|Z{}x~}V{}w~|o{|v~ WZ~}gx~}w~|q{}y~|({|c~}_v|{}r~u|d{}X~f{}b~|b{|w~}mw~" + "}`w~}kw~}[{|v~{}w~}X{|w~}r{|v~d{}x~| q{}c~ yv~} y{}x~}t{}x~}\\v~}w{|y~|_{}w~|vw~}v{|x~}X{|r~ qv~Fv~X{}w~}|x" + "x~x{|}w~}U{}w~ d{|w~Y{|v~k{}w~}W{}w~}G{}v~|Xm~}Y{}x~}t{}w~}\\{|h~}]v~y|l~}P{|v~|Y{|u~u|}v~}_{|v~|n{|u~|X{}v~M{" + "}v~R{|o~}|`{|Z~}_{|}p~}|P{}v~}cw~r{|l~}x~|u{|x~|hv~|t{|v~^{}e~}a{}v~M{}w~}f{|v~|e{}d~|_{}g~|d{}v~K{}^~|Y{}w~}M{" + "}w~}W{}p~|Q{}w~}V{}w~|ww~|tw~}wv~|h{}w~|vv~|sv~i{}v~c{|v~|e{}w~}o{|u~g{}v~c{|v~|g{}w~}p{|u~|^{}q~y}|M{|v~|Z{|v~" + "h{}w~}c{|v~|p{|v~gv~|t{|w~v{|x~}sv~|a{|s~|Rq~}N{}v~}S{|w~}Jw~}H{|w~| bv~|^t~ov~}^v~}P{|v~|p{}u~|`v~|o{|v~Ww~}U" + "{|v~o{}u~|`u~}p{|v~Vv~Lv~Tw~}u{|v~}Qv~_u~}pt~}pv~|hu~}p{|v~`{|v~|p{|v~|_t~ov~}a{|v~|p{}u~|Zt~S{}w~Gv~S{|w~|m{}w" + "~|`v~|o{|v~ev~s{|x~y}x~}s{}w~|c{}v~uv~}\\{}w~|o{|w~}O{}v~|U{|w~}Lw~|M{|w~} M{|x~}x|}w~}xv~}x|}x~|d{}v~qw~y}x~}_" + "v~x{}q~}I{|w~}_{|w~|q{|u~]{}w~|Nu~}p{|v~^{}w~|p{|w~}X{|q~Z{|w~|m{}w~|fv~|d{|v~f{|v~}w{}w~|wu~`{|w~}q{|w~}`v~t{}" + "w~t{|w~}a{|v~ov~}a{|v~}p{}v~|W{|w~}Wv~}l|}v~^v~|t{|v~Q{}v~}W{}w~}V{|v~b{}w~}l{}v~r{|v~r{}v~|i{}w~}hv~|i{|v~|s{|" + "v~r{}v~k{}v~xi~}y{|v~|iu~|A{}w~A{|u~|Z{}w~Y{}v~}i{}v~|Z{}w~ sv}|U{}v~|vy~}S{|v~O{|w~}s{|v~_{|o~|{o~}Ww~|U{}x~}v" + "{}u~}.{|y~|w{|w~d{|y~|e{}w~t{}v~}W{|v~|v{}w~}cY|8{|y~|sw~sw~|t{|y~| `{|Z~}_{}x~}C{|w~}({|w~|m{}w~|`{|n~}w{|x~} " + "H{}x~|Sv~|u{}w~|\\{}v~v{|v~|^{}x~|p{|w~\\{}x~|p{|w~W{|x~}u{|w~Mv}|Uv~|t{|v~Zv~|t{|v~Zv~|t{|v~Zv~|t{|v~Zv~|t{|v~" + "Zv~rv~b{|v~s{|c~l{}v~I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}Z{|v~ev~}h{}w~|vv~|sv~i{}v~c{|v~|l{}v~c{|v" + "~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|c{|u~v{}v~}c{}v~o{|w~|u{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}\\q~" + "}X{}w~}mv~}aw~}vv~Ev~|Mv~|Mv~|Mv~|Mv~|Mv~|Ws~|o{}w~}gv~}Ov~|o{|v~_v~|o{|v~_v~|o{|v~_v~|o{|v~Vv~Lv~Lv~Lv~Uv~}o{}" + "w~}_u~}p{|v~`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|Wt|W{|v~|q{}u~|`{|w~|m{}w~|a{|w~|m{}w~|" + "a{|w~|m{}w~|a{|w~|m{}w~|`{}w~|o{|w~}_t~ov~}`{}w~|o{|w~} X{}x~}q{}w~q{|x~}j{}x~}b{|x~}j{}x~}vu~|yu~|w{|x~}j{}x~}" + "mu~|w{|x~}j{}x~}b{|x~}Z{}x~}V{|v~o{}w~} WZ~}g{}|yw~}qx~'a~|c{|}t~}k~}|fY~}g{}`~b{|w~|m{}w~`w~}kw~}[{|w~}{|v~Wv~" + "r{}w~}dw~| lv~| kv~| yw~|tw~|\\{}v~}|y{|y~|^v~}y|}v~uw~X{|p~ rv~Fv~Xw~|vx~v{|w~U{}w~ d{}x~}Y{|v~k{}w~}W{}w" + "~}H{|v~}Wo~}|Y{|w~|t{}w~}\\{|v~x}|x}s~}^v~|j~}Q{}w~}V{}l~}]v~}n{}u~}X{}v~M{|v}U{|}p~}|]{|Z~}\\{}o~|S{}v~}c{|x~}" + "rv~}|w{|}t~|tx~}i{|v~rv~|_{}h~}|_v~}M{}w~}f{|v~|e{}d~|_{}g~|dv~}K{}^~|Y{}w~}M{}w~}W{}q~|P{}w~}V{}w~|w{}w~u{|w~|" + "wv~|h{}w~|v{}w~}sv~iv~}c{|v~|e{}w~}p{|u~|gv~}c{|v~|g{}w~}sy|}u~}\\{}m~}|Q{|v~|Z{|v~h{}w~}bv~}p{}w~}g{}w~}t{}x~}" + "v{|w~sv~|`{}u~}Q{|r~|O{|u~R{|w~}J{}w~H{|w~| b{|w~}^u~|o{|v~_{}v~Ov~}nu~|a{}w~}m{}w~|Xw~}Uv~|nu~|`u~nv~|Wv~Lv~T" + "w~}v{}v~}Pv~_u~o{}u~|p{}w~}hu~nv~|a{}w~}n{}w~}_u~|o{|v~a{}w~}nu~|Zu~|S{}w~Gv~S{|w~|m{}w~|`{}w~}o{}w~}e{}w~s{}x~" + "}|w~sv~a{}v~w{}v~[{|w~}ov~|P{}v~|T{|w~}Lw~|M{|w~}:{|4x~|v{|w~}{}x~}u{}x~dv~}q{}s~|_v~x{}r~}S{|y}~y}|w{|w~}_w~}o" + "{|v~}^{}w~Mu~nv~|_{|w~}pv~|X{}w~}v~|[{|w~|m{}w~|g{|v~bv~|g{}v~v{}w~v{|v~|a{|w~}q{|w~}`v~t{}w~t{|w~}a{}w~|o{|v~a" + "{}v~nv~}W{|w~}W`~_{|v~rv~|Q{}v~|X{}w~}V{|v~b{}w~}lu~r{|v~r{|v~|i{}w~}hv~|hv~}s{|v~rv~}kv~}xi~}y{|v~|ju~|@{}w~@{" + "|u~|[{}w~Z{}v~}g{}v~|[{}w~ Gv~}uy~}S{|v~Ow~}q{|w~|`{|n~}o~}Ww~|Uw~|t{}u~|0{|y~|w{|x~}d{|y~|e{|v~}w|t~}X{|v~|vv~" + "}c{|Z~}8{|y~|sw~t{}w~s{|y~| `{|Z~}`{}x~}M{|~}|v{|}v~'{|w~|m{}w~|_{}o~}w{|x~}Vv}| s{}x~|S{|v~}|{y|}w~}Z{}v~|w{|v" + "~}_{}x~|pw~|o{}w~m{}x~|p{}x~|vy|}w~y}|g{|w~|u{}x~|o{}w~3{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{}w~}" + "r{}w~|c{}w~}s{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w~|v{}w~}sv~iv~}c{|v~|lv~}c{|" + "v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|b{|u~x{}v~}bv~}p{|w~}t{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}\\{|r~|" + "X{}w~}mv~}aw~}v{}w~}F{|w~}M{|w~}M{|w~}M{|w~}M{|w~}M{|w~}W{|u~}m{}w~h{}v~O{}w~}m{}w~|a{}w~}m{}w~|a{}w~}m{}w~|a{}" + "w~}m{}w~|Wv~Lv~Lv~Lv~V{}v~n{|v~_u~nv~|a{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~},{}w~}q{}t~}`" + "{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|`{|w~}ov~|_u~|o{|v~`{|w~}ov~| X{}x~|q{}w~q{|w~j{}x~|b{|w~j{}x~|u" + "u~|u~|v{|w~j{}x~|nu~|v{|w~j{}x~|b{|w~Zw~}Uv~|q{|v~ VZ~}c{}w~r{|y~}({}`~d{}^~|h{|Z~g{|_~}c{}w~l{|w~`w~}kw~}[{}w~" + "|yv~|X{}w~|sv~|dV~} 2v~| k{}w~| {{|w~t{|w~Zs~y}y~|^{|o~|v{}x~}rx|e{|v~y}u~n{|w~},{|v~Fv~|Y{|~}tx~t{}~|U{}w~ " + " dw~|Y{|v~k{}w~}W{}w~}Hu~Vp~}|Y{|w~}s{}w~}\\{|~}|q{}t~|`{|q~}|xy|t~|Rv~|U{|}p~|[{}v~|ot~} V{|}p~}|Z{|Z~}Z{|}p~}" + "|W{}v~|b{}x~|s{}w~|s{|u~|tw~i{}w~}r{}w~}_{}g~}|`v~}M{}w~}f{|v~|e{}d~|_{}g~|dv~}K{}^~|Y{}w~}M{}w~}W{}q~O{}w~}V{}" + "w~|w{|w~|v{}w~vv~|h{}w~|uv~|tv~iv~}c{|v~|e{}w~}sy|s~fv~}c{|v~|g{}f~}Z{}k~}S{|v~|Z{|v~h{}w~}b{|v~pv~|g{}w~}tw~|u" + "w~|u{|v~_{}u~O{}t~|O{|u~|R{|w~}J{|w~|I{|w~| aw~}^v~}m{}w~}`v~|P{|v~m{}v~|av~l{|w~}Xw~}V{|v~m{|v~|`v~}n{}w~|Wv~" + "Lv~Tw~}w{}v~}Ov~_v~}o{|v~}o{|w~}hv~}n{}w~|av~|n{|v~|`u~mv~|bv~m{}v~|Zv~}R{}w~Gv~S{|w~|m{}w~|`{|v~ov~d{}w~|tw~|{" + "w~|u{|w~}`v~}y{|v~|Z{}w~|q{|v~P{}v~|Sv~|Lw~|Lv~|W{|y}w~}|iy}5{|y~}sw~|x~}s{}y~|f{|v~|ps~^v~x{}q~}|W{|r~|y{|w~}`" + "{}w~m{}v~^{}w~Mv~}n{}w~|^{}w~q{|v~Wv~y|w~}[{|w~|m{}w~|g{}v~b{}w~}h{|v~|v{}w~u{}w~}a{|w~}q{|w~}`v~t{}w~t{|w~}av~" + "mv~|c{|v~|n{|v~W{|w~}W`~_{}w~}r{}w~}Q{|v~}X{}w~}V{|v~b{}w~}lv~}r{|v~r{|v~|i{}w~}hv~|h{}v~s{|v~s{|v~|kv~}xi~}y{|" + "v~|ku~|?{}w~?{|u~|\\{}w~[{}v~}e{}v~|\\{}w~ H{}v~ty~}S{|v~P{|w~o{}w~_s|}r~s|Vw~|V{|w~r{|u~0{|y~v{}x~}d{|y~|d{}o~" + "|x~}Y{}v~v{|v~|b{|Z~}8{|y~rw~u}v~|s{|y~| `{|Z~}a{}l~|X{|m~|'{|w~|m{}w~|^o~}w{|x~}W{|v~| xm~}W{|n~}X{|v~|vv~}e{}" + "n~}v{}x~}o{|v~m{}x~|q{|w~w{|o~|t{|~}y|w{|}v~u{|x~}o{|v~3{}w~}r{}w~}\\{}w~}r{}w~}\\{}w~}r{}w~}\\{}w~}r{}w~}\\{}w" + "~}r{}w~}\\v~|r{|w~}cv~|s{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w~|uv~|tv~iv~}c{|v" + "~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|a{|u~|}v~}av~}pw~}s{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}[" + "{}t~|W{}w~}mv~}aw~}v{}v~|Fw~}Lw~}Lw~}Lw~}Lw~}Lw~}Vu~l{|w~|iv~|Ov~l{|w~}av~l{|w~}av~l{|w~}av~l{|w~}Wv~Lv~Lv~Lv~V" + "v~|mv~|`v~}n{}w~|av~|n{|v~|av~|n{|v~|av~|n{|v~|av~|n{|v~|av~|n{|v~|-v~|r{|x~}v~`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{" + "}w~|a{|w~|m{}w~|_{}w~|q{|v~^u~mv~|`{}w~|q{|v~ Ww~p{}w~pw~jw~yd|yw~jw~t{|p~|tw~jw~nu~|tw~jw~pv~}qw~Zw~|U{}w~}q{}" + "w~} F{}w~}W{|w~|s{}y~|){|_~}f{}\\~|h{}\\~|g{}^~c{}w~l{|w~|aw~}kw~}[v~x{}w~}X{|w~}t{|v~cV~} 2v~| k{}w~| {{|x~" + "}t{|x~}Z{|o~}y|`{|}r~|v{|w~t{}u~}|hv~}y{}u~o{|w~|,{|v~F{}w~|X{|sx~s{|T{}w~ e{|w~X{|v~k{}w~}W{}w~}Iu~|Vm~|[{}w~" + "r{}w~}L{}u~`{|r~|s{|u~S{}v~V{|}m~}|\\u~p{}t~} Y{|}p~}|VY|W{|}p~}|[{|v~|aw~rw~}q{|v~|t{}x~iv~q{|v~_{}e~}av~}M{}w" + "~}f{|v~|e{}d~|_{}g~|dv~}m{}n~|h{}^~|Y{}w~}M{}w~}W{}q~}P{}w~}V{}w~|vw~}vw~}vv~|h{}w~|u{}v~tv~iv~}bv~|e{}e~|fv~}b" + "v~|g{}g~}X{|}k~}U{|v~|Z{|v~h{}w~}av~|r{|v~f{|v~u{|w~|u{}x~}u{}w~}`{|t~|O{}v~}Nu~|Q{|w~}Iw~}I{|w~| a{}w~^v~|m{|" + "w~}a{|v~O{|w~}lv~|b{|w~}kv~Xw~}V{|w~}lv~|`v~|n{|w~}Wv~Lv~Tw~}x{}v~|Nv~_v~|nv~|nv~hv~|n{|w~}b{|v~lv~|`v~}m{|w~}c" + "{|w~}m{|v~|Zv~|R{}w~|Hv~S{|w~|m{}w~|_{}w~|q{|w~}d{|w~}u{|w~y{}x~|u{|w~|`{|v~y|v~}Y{|w~}q{}w~|Q{|v~}S{}v~Kw~|L{}" + "w~}Y{|p~}|n{|y~}5{}y~r{|t~qy~}f{}v~ot~}^v~x{}o~}Y{}p~|{|w~|`w~}lv~|_{|w~}Nv~|n{|w~}^{|w~|r{}w~|X{}w~}yv~[{|w~|m" + "{}w~|gv~}b{}v~h{|v~u{}w~u{|v~a{|w~}q{|w~}`v~t{}w~t{|w~}b{|w~}m{|w~}c{|v~lv~|X{|w~}W`~_v~|r{|v~Qu~W{}w~}V{|v~b{}" + "w~}lv~}r{|v~qv~|i{}w~}hv~|h{|v~|t{|v~s{}v~jv~}xi~}xv~|lu~[|]{}w~\\\\|u~|]{}w~\\{}v~}c|u~|]{}w~ H{}w~}ty~}X{}g~|" + "[{}x~}nw~Vs~|Nw~|V{}x~}pv~}1{}y~v{}x~}d{|y~}c{}r~}{|x~}Z{}w~}v{|v~|a{|Z~}8{}y~rn~}q{|y~} `{|Z~}a{}l~|X{|o~}|&{|" + "w~|m{}w~|]{}q~}w{|x~}W{|v~| xm~}V{|}q~|V{|v~|v{}w~}fm~}vw~o{|u~rm~}vw~|w{}n~|u{|m~|uw~|p{|u~3v~q{|v~\\v~q{|v~\\" + "v~q{|v~\\v~q{|v~\\v~q{|v~]{|v~pv~|e{}w~}r{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w" + "~|u{}v~tv~iv~}bv~|lv~}bv~|lv~}bv~|lv~}bv~|lv~}bv~|`{|p~}`v~}q{}x~}qv~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}" + "w~}Z{}v~}V{}w~}mv~}aw~}uu~}G{}w~L{}w~L{}w~L{}w~L{}w~L{}w~V{}w~}kw~}j{|v~O{|w~}kv~b{|w~}kv~b{|w~}kv~b{|w~}kv~Wv~" + "Lv~Lv~Lv~W{|v~l{}w~}`v~|n{|w~}b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|.{|v~r{|w~{}w~|a{|w~|m{}w~|a{|w~|m{}" + "w~|a{|w~|m{}w~|a{|w~|m{}w~|_{|w~}q{}w~|^v~}m{|w~}`{|w~}q{}w~| Ww~yd~|{w~jw~yd~|{w~jw~s{|r~|sw~jw~ou~|sw~jw~pv~}" + "qw~Zw~|U{|v~qv~| G{}w~}Uw~}sx~({}^~g{}Z~g]~}f{|_~|cw~}l{|w~|aw~}kw~}\\{|v~x{|v~Wv~t{}w~}cV~} 2v~| k{}w~| {{}" + "x~}t{}x~}Y{|}m~}`{|}w~}|tw~|v{|q~}j{}v~w{}u~p{}w~|,{|w~}F{}w~|Ox~Z{|Z~} t{}x~}X{|v~k{}w~}W{}w~}J{}v~|Ut|}t~}]{" + "|w~|r{}w~}K{}v~|a{|s~p{|v~}Tv~}W{}i~}]{}u~|t{|}s~} Z{|q~}| e{|}q~}\\v~}`x~}s{}w~ov~|t{}x~|k{|w~}p{}w~|`{}w~}p|}" + "t~|cv~}M{}w~}f{|v~|e{}w~}i|^{}w~}l|cv~}m{}n~|h{}w~}h|v~|Y{}w~}M{}w~}W{}w~}u~}Q{}w~}V{}w~|v{}w~w{|w~uv~|h{}w~|tv" + "~|uv~iv~}c{|v~|e{}f~|ev~}c{|v~|g{}i~}S{|}m~}V{|v~|Z{|v~h{}w~}a{}w~}rv~}ev~|v{|w~t{|w~uv~|`r~O{|v~|O{}v~}P{|w~}I" + "{}w~I{|w~| a{}w~^v~|lv~a{}w~}O{}w~|lv~|b{|w~|k{}w~Xw~}V{}w~|lv~|`v~m{|w~}Wv~Lv~Tw~}yu~|Mv~_v~mv~mv~hv~m{|w~}b{" + "}w~}l{}w~}`v~|m{|v~c{}w~|lv~|Zv~Q{}v~|Iv~S{|w~|m{}w~|_{|w~}q{}w~|cv~u{}x~}y{}x~}u{}w~^{}q~}Wv~qv~Q{|v~}Uy|}v~|K" + "w~|L{|u~}|^{|k~}|s{|}x~}5y~}q{}v~|q{}y~f{}w~}o{}u~|^v~ty|}s~[{|u~y}v~y|w~|a{|w~}l{}w~}^{}w~|Ov~m{|w~}]w~}rv~Wv~" + "|y{}w~}\\{|w~|m{}w~|gv~|b{|v~h{}w~}u{}w~tv~a{|w~}q{|w~}`v~t{}w~t{|w~}b{}w~|m{|v~c{}w~}l{}w~}X{|w~}W`~`{|w~}pv~|" + "S{}v~|W{}w~}V{|v~bv~}lv~}r{|v~r{|v~|i{}w~}hv~|gu~t{|v~t{|v~}jv~}xh|y{|v~|mT~]{}w~]T~|^{}w~]{}U~|^{}w~ Hv~|ty~}X" + "{}g~|[w~|nw~|W{}u~}Mw~|V{}w~ov~1{|y~v{}x~}d{|y~|ay}x~y}ww|[{}w~}v{|v~|`{|Z~}8{|y~ro~o{|y~| Q{}w~R{}l~|V{|y}v~y}" + "|${|w~|m{}w~|\\{|}s~}w{|x~}W{|v~| xm~}T{|y}w~}|S{|v~|v{}w~}gm~}w{}x~}oy~y}x~rm~}w{}x~}v{}~}y|w{|v~u{|o~}t{}x~}o", + "t~^v|V{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{}w~}p{}w~}ev~|r{|v~h|lv~}I{}w~}i|_{}w~}i|_{}" + "w~}i|_{}w~}i|V{}w~}M{}w~}M{}w~}M{}w~}_v}u~r}nv~}h{}w~|tv~|uv~iv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|" + "_{|r~}_v~}r{}w~q{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}mv~}aw~}u{|t~|I{}w~L{}w~L{}w~L{}w~" + "L{}w~L{}w~V{}w~|kv~j{}w~}O{|w~|k{}w~b{|w~|k{}w~b{|w~|k{}w~b{|w~|k{}w~Wv~Lv~Lv~Lv~W{}w~}l{|w~}`v~m{|w~}b{}w~}l{}" + "w~}b{}w~}l{}w~}b{}w~}l{}w~}b{}w~}l{}w~}b{}w~}l{}w~}eY|f{}w~}rw~y{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|" + "m{}w~|^v~qv~]v~|m{|v~_v~qv~ Vw~yd~|{}x~|kw~yd~|{}x~|kw~r{|t~|r{}x~|kw~pu~|r{}x~|kw~pv~}q{}x~|[w~|T{}w~|s{|v~ G{" + "}v~T{}w~t{|y~}(]~|i{|Y~}h{|_~}d{|a~}bw~}kw~|aw~}kw~}\\{}w~}wv~|Xv~|u{}w~|cV~} 2v~| k{}w~| {{w~|tw~|W{|}m~}T{" + "}x~}v{|o~}l{|v~|v{}u~q{}w~+{|w~}F{}w~|Ox~Z{|Z~}+m| ww~|X{|v~k{}w~}W{}w~}K{}v~}K{|}v~}^w~}q{}w~}Ju~a{|t~|o{}v~U{" + "|v~|X{}u~}|wy|u~}]t~}y|{y|}q~} Z{|t~}| _{|}t~}\\v~`{|x~}s{}x~}o{|w~|t{}x~|kv~|p{|w~}`{}w~}n{|u~cv~}M{}w~}f{|v~|" + "e{}w~}L{}w~}Tv~}m{}n~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}|u~}R{}w~}V{}w~|v{|w~|x{}x~}uv~|h{}w~|t{|v~uv~iv~}c{|v~|e{}h~" + "}cv~}c{|v~|g{}h~}Qy|y}p~W{|v~|Z{|v~h{}w~}a{|v~s{|v~|e{}w~}v{}x~}t{|w~uv~|a{}r~}P{|v~|P{}v~}O{|w~}I{|w~|J{|w~| " + "n{|y}l~^v~kv~a{}w~|Ov~|l{}w~|b{}w~|k{}w~|Yw~}Vv~|l{}w~|`v~m{|w~}Wv~Lv~Tw~}|u~Kv~_v~mv~mv~hv~m{|w~}b{}w~|l{|v~`v" + "~kv~c{}w~|l{}w~|Zv~Pu~}|Kv~S{|w~|m{}w~|^v~qv~b{}w~u{}x~|y{|w~uv~]{}r~V{}w~|s{|w~}R{|v~}X{|q~}Jw~|K{|q~}c{}g~}w|" + "}u~}5y~}pw~}p{}y~fv~|o{}u~]v~p{|t~\\v~}w{|w~}w~|a{}w~|l{|w~}]{}w~}y|Rv~m{|w~}]{}w~s{}w~}X{}w~}x{|v~\\{|w~|m{}w~" + "|h{|v~|b{|v~|i{}w~|u{}w~tv~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~kv~c{}w~|l{|w~}X{|w~}Wv~jv~`v~|p{}w~}T{}v~|V{}w~}V{|v~" + "|cv~|lv~}r{|v~r{|v~|i{}w~}hv~|g{}v~}u{|v~tu~|jv~}c{|v~|n{|T~]{}w~]T~}^{}w~]T~}^{}w~ I{|v~sy~}X{}g~|[w~m{}x~|Vu~" + "|#{|w~|p{|w~|2{|y~|w{|x~}d{|y~|3v~}v{}v~|Aw~}8{|y~|sw~x{|w~}p{|y~| Q{}w~ p{|w~|m{}w~|Y{|}v~}w{|x~}W{|v~| jv~}" + "v{}v~|W{|w~o{}y~{}x~r{}n~}x{|w~uy|rw~|ty|t}|s{|w~o{}y~|}x~^{}w~|Wv~|p{|w~}^v~|p{|w~}^v~|p{|w~}^v~|p{|w~}^v~|p{|" + "w~}^v~|p{|v~f{|v~q{|v~Yv~}I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~ev~}h{}w~|t{|v~uv~iv~}c{|v~|lv~}" + "c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|^{|t~}^v~}s{}w~p{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w" + "~}n{|v~|aw~}t{}t~}W{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~c{|y}l~j{}w~j{}w~|O{}w~|k{}w~|c{}w~|k{}w~|c{}w~|k{}" + "w~|c{}w~|k{}w~|Xv~Lv~Lv~Lv~W{}w~|l{|v~`v~m{|w~}b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~f{|Z~}f{}" + "w~|s{}x~|y{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|^{}w~|s{|w~}]v~kv~_{}w~|s{|w~} Vw~yd~|{}x~|kw~yd" + "~|{}x~|kw~qt~|r{}x~|kw~qu~|q{}x~|kw~pv~}q{}x~|[w~|T{|w~}s{}w~} H{|v~|T{|w~|u{}y~({|]~}i{}X~g{|`~b{}b~aw~}kw~}aw" + "~}kw~}\\v~|w{}w~}X{}w~}uv~bw~}Z| 5x|v~}p| v{}w~| {|w~t{|w~S{|}n~|Vw~uv~|y{|}w~}m{}w~}t{}u~rw~}+{|w~}F{}w~|Ox" + "~Z{|Z~},{|m~ x{|w~|X{|v~k{}w~}W{}w~}L{}v~}H{}v~}`{}w~p{}w~}J{}v~`t~n{|v~|V{}v~X{}v~}q{}v~}^{|j~|v~| Z{|t~| ]{|}" + "u~}]{|w~}`{|x~|sw~|o{|w~|t{}x~|l{|v~nv~`{}w~}lv~}dv~}M{}w~}f{|v~|e{}w~}L{}w~}Tv~}m{}n~|h{}w~}hv~|Y{}w~}M{}w~}W{" + "}w~}{|t~S{}w~}V{}w~|u{}x~}y{|w~|uv~|h{}w~|sv~|vv~iv~}c{|v~|e{}k~}|av~}c{|v~|g{}w~}t|y}u~}M{|}s~}X{|v~|Z{|v~h{}w" + "~}`v~}t{}v~d{}w~}vw~|sw~|w{|v~a{|v~}v~|Q{|v~|Q{|u~N{|w~}Hw~|J{|w~| p{}h~|_v~k{}w~|bv~|Ov~k{}w~|bv~j}v~|Yw~}Vv~" + "k{}w~|`w~}m{|w~}Wv~Lv~Tq~}Jv~_w~}mv~mv~hw~}m{|w~}bv~|l{|v~`v~kv~|dv~k{}w~|Zv~P{}r~}y|Pv~S{|w~|m{}w~|^{}w~|s{|w~" + "}b{|w~|vw~|xw~|w{|w~}\\s~|Uv~sv~|Ru~W{|s~}|Iw~|I{|}t~}d{|u~}w|}g~}5{|y~|p{|x~|p{}y~fv~|o{|v~}]v~n{}v~|^{}w~|ts~" + "`v~|l{|v~\\{}p~}Xw~}m{|w~}]{|w~|tv~|Xv~|wv~|]{|w~|m{}w~|h{|v~|q{}x~}q{|v~|iv~|u{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{" + "|w~}bv~kv~|dv~|l{|v~X{|w~}Wv~|l{|v~a{|v~nv~U{|v~}U{}w~}Uv~}d{|v~|l{}v~r{|v~r{|v~|i{}w~}hv~|fu~|v{|v~u{}v~}iv~}c" + "{|v~|n{|T~]{}w~]T~}^{}w~]T~}^{}w~ rw|V{|w~}sy~}X{|w}u~q}Zw~m{}x~|V{}v~\"{|v~ow~|2{|y~|w{|w~d{|y~|4{}w~}v{|v~?w~" + "}8{|y~|sw~vw~}q{|y~| Q{}w~ p{|w~|m{}w~|Ux~}w{|x~}W{|v~| i{}w~|v{|v~Ww~|p{|y~|{}x~`{}x~|j{|x~}bw~|p{|y~}{}x~^{" + "}w~|X{|v~nv~_{|v~nv~_{|v~nv~_{|v~nv~_{|v~nv~_{|w~}nv~|g{}w~}q{|v~Yv~}I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}" + "M{}w~}Z{|v~ev~}h{}w~|sv~|vv~iv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|]{}u~|^v~}t{|w~|p{|v~|i{|v~h{}w~}" + "f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}n{}v~|aw~}s{|s~|[{}h~|\\{}h~|\\{}h~|\\{}h~|\\{}h~|\\{}h~|f{}h~j}v~" + "jv~|Ov~j}v~|cv~j}v~|cv~j}v~|cv~j}v~|Xv~Lv~Lv~Lv~Wv~|l{|v~`w~}m{|w~}bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v" + "~f{|Z~}fv~|t{}x~|wv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|]v~sv~|]v~kv~|_v~sv~| Vw~yd~|{w~jw~yd~|{w~j" + "w~rr~|sw~jw~ru~|pw~jw~pv~}qw~Zw~|Sv~sv~ H{|v~|Rw~}uy~}({|]~}i{}X~|g{}b~|a{}d~|aw~}kw~}aw~}kw~}]{|v~v{|v~X{|v~v{" + "|w~}b{}x~} pf~ v{|w~ {{|w~t{|x~}P{|y~}r~W{}x~|v{}w~u{}w~mv~r{}u~t{|w~|+{|v~F{}w~|Ox~Z{|Z~},{|m~ x{}w~W{|v~k" + "{}w~}W{}w~}M{}v~}F{}v~a{|w~|p{}w~}Iv~|au~}mv~}Vv~|Y{|v~}o{|v~|]{}m~|{v~| Z{|r~}| c{|}r~}]{|w~}`{|x~|sw~|nw~|t{}" + "x~k{}w~}n{}w~}a{}w~}l{|v~|e{}v~M{}w~}f{}v~d{}w~}L{}w~}T{}v~mr|v~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}y{|t~T{}w~}V{}w~|u" + "{|w~y{}w~tv~|h{}w~|s{|v~vv~i{}v~c{|v~|e{}w~}r|]{}v~c{|v~|g{}w~}q{}v~}K{|t~|Y{|v~|Z{|v~h{}w~}`{}v~tv~|d{|v~w{|w~" + "|s{}x~}w{}w~}av~}{}v~Q{|v~|R{|u~M{|w~}H{}x~}J{|w~| r{|f~|_w~}k{}w~|bv~|Ov~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~" + "Lv~Tq~Iv~_w~}mv~mv~hw~}m{|w~}bv~jv~`v~k{}w~|dv~k{}w~|Zw~}O{}o~}|Sv~S{|w~|m{}w~|^{|w~}s{}w~|b{|w~}w{|w~w{}x~}w{|" + "w~|\\{|u~}T{}w~|u{|w~}Ru~V{|s~}|Iw~|J{|}s~}d{|w~|s{|}k~|3y~}p{|x~}p{}y~fv~mv~|]v~m{}v~_{|w~}rt~`v~jv~Z{}r~}Xw~}" + "m{|w~}\\w~}u{|w~}X{|w~}v{}w~}]{|w~|m{}w~|h{|v~|q{}x~}pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~k{}w~|dv~jv" + "~X{|w~}W{}w~|l{|v~a{}w~}n{}w~}W{|u~T{}w~}U{}w~}d{}v~k{}v~|s{|v~r{}v~h{}w~}hv~|f{|u~|w{|v~v{}u~h{}v~c{|v~|n{|T~]" + "{}w~]T~|^{}w~]{}U~}^{}w~ s{|w~V{|w~}sy~}S{|v~Pw~|nw~|V{|w~}!{}v~|q{}x~|1y~}vw~|e{}y~ci|]{}w~u{|w~|?w~}7y~}sw~v{" + "|w~|r{}y~ P{}w~ p{|w~|m{}w~|Ux~}w{|x~}W{|v~| Fi|U{|w~|u{}w~X{}x~}p{|y~}y{}x~a{|w~i{|x~}c{}x~}p{|y~}y{}x~^{}w~|" + "X{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~|n{}w~}h{|v~p{|v~Y{}v~I{}w~}M{}w~}M{}w~}M{}w~}" + "D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|s{|v~vv~i{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|^{}s~|_" + "{}v~u{|w~|o{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}o{|u~`w~}q{}t~|^{|f~|^{|f~|^{|f~|^{|f~|" + "^{|f~|^{|f~|h{|P~jv~|O`~|c`~|c`~|c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~f{|Z~}fv~|u{}x~}" + "vv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|]{}w~|u{|w~}\\v~k{}w~|_{}w~|u{|w~} Uw~yq}w~r}yw~jw~yd|yw~jw~" + "sp~|tw~jw~su~|ow~jw~pv~}qw~Zw~|S{}w~}u{|w~} Hv~|Q{}w~|w{|y~|({|\\~iW~|f{}d~|_e~|`w~}kw~}aw~}kw~|]{}w~}uv~Wv~|w{" + "}w~|b{}x~} q{|g~| v{|w~({}Z~X{|y~|{|}u~}Y{|w~uw~|tw~}o{|w~}q{}u~u{}w~*{|v~F{}w~|*m|}w~l|,{|m~ xw~}W{|v~k{}w" + "~}W{}w~}N{}v~}Dv~|bw~}o{}w~}Iv~|au~|m{}w~}W{|v~X{}v~m{}v~\\{|p~}xv~| Y{}p~}| i{|}p~}|]{}w~}`{|x~|sw~mw~|t{}x~kv" + "~}n|}v~a{}w~}kv~}e{}v~M{}w~}f{}v~d{}w~}L{}w~}T{}v~dv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}x{|t~U{}w~}V{}w~|tw~|{w~}tv~|" + "h{}w~|rv~}wv~i{}v~c{}v~d{}w~}T{}v~c{}v~f{}w~}p{}v~|Ju~}Y{|v~|Z{|v~h{}w~}_v~|v{|v~bv~|x{|w~r{}w~wv~|b{}v~xv~}R{|" + "v~|Ru~|M{|w~}H{|w~J{|w~| s{|q~t}v~|_w~}k{}w~|bv~Nv~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tp~Jv~_w~}mv~mv~hw~}" + "m{|w~}bv~jv~`w~}k{}w~|dv~k{}w~|Zw~}N{|m~|Uv~S{|w~|m{}w~|]v~t{|v~`v~w{}x~}w{|x~}w{}w~[{|u~|T{|w~}u{}w~|S{}v~|V{|" + "x}t~}Jw~|K{|s~y}|d{|y~}n{|}p~}1y~}p{}w~p{}y~fv~mv~\\v~lv~|`{}w~|r{|v~}`v~jv~\\{|p~}Xw~}m{|w~}\\{}w~u{}w~|Xv~|v{" + "|v~]{|w~|m{}w~|h{|v~p{}w~pv~}iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bw~}k{}w~|dv~jv~X{|w~}W{}w~|l{|w~}av~|n{|v" + "~Wu~|T{}w~}U{}v~dv~}k{|v~}s{|v~s{|v~}h{}w~}hv~|e{}u~|x{|v~w{}u~|h{}v~c{}v~l{|u~}\\|]{}w~][|u~|]{}w~\\{}v~}c|u~}" + "]{}w~ s{|w~V{|w~}sy~}S{|v~P{}x~}o{|w~`{|a~}+u~|rw~|1y~}v{}w~ex~d{|j~}]{}w~}v{|v~|@w~}7y~}sw~u{}w~rx~ P{}w~ p{|" + "w~|m{}w~|Ux~}w{|x~} w{|j~}V{|v~|v{}w~}Xw~oy~}x{}x~aw~|i{|x~|cw~ox~x{}x~^{}w~|Xv~}n|}v~`v~}n|}v~`v~}n|}v~`v~}n|" + "}v~`v~}n|}v~a{|b~h{}v~p|}v~Y{}v~I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|rv~}wv~i{}v~c{" + "}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~^{}q~|`{}v~v{|w~}n{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{" + "|v~|V{}w~}p{|u~|`w~}p{|t~}`{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|i{|q~t}`~|kv~N`~|c`~|c`~|" + "c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~f{|Z~}fv~u{|x~}uv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m" + "{}w~|a{|w~|m{}w~|]{|w~}u{}w~|\\w~}k{}w~|_{|w~}u{}w~| U{}x~|q{}w~q{|w~j{}x~|b{|w~j{}x~|uu~|u~|v{|w~j{}x~|uu~|o{|" + "w~j{}x~|qv}|r{|w~[{|w~|S{|v~uv~| TZ~}a{|w~}wx~'{|\\~iW~|ee~|^{|g~}_w~}kw~}aw~}kw~|]v~|u{}w~|X{}w~}wv~|b{|w~| " + " r{}g~ u{|w~({}Z~X{|y~|w{}v~|Zw~|v{|w~s{|w~o{|w~}p{}u~vw~})v~Fv~| w{}w~ x{|m~ y{|w~|Vv~|lv~|W{}w~}O{}v~}C{}w~}" + "c{|w~n|}w~}v|N{}w~}au~l{|v~Wv~}Xv~}m{|v~|[{|y}w~y}|x{|v~ V{|}p~}|XY|X{|}q~}|Z{}w~}`{|x~|sw~mw~|tw~l{|b~|b{}w~}k" + "{}v~e{|v~|N{}w~}fv~}d{}w~}L{}w~}T{|v~|ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}w{|t~V{}w~}V{}w~|t{}w~|w~|tv~|h{}w~|r{|v~" + "wv~i{|v~|d{}v~d{}w~}T{|v~|d{}v~f{}w~}o{}v~J{|u~Y{|v~|Z{|v~h{}w~}_{}w~}v{}w~}b{}w~}x{}x~}r{|w~wv~b{|v~|x{|v~|S{|" + "v~|S{}v~|L{|w~}Gw~|K{|w~| t{|u~}|q{}w~|_v~k{}w~|bv~Nv~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tw~}|u~Kv~_w~}mv~" + "mv~hw~}m{|w~}bv~jv~`w~}k{}w~|dv~k{}w~|Zw~}L{|}o~}Vv~S{|w~|m{}w~|]{}w~}u{}w~}`{}w~|xw~|w{|w~wv~\\{|s~Sv~uv~S{}v~" + "|O{}v~}Kw~|L{|v~}|_{|~|j{|y}x~y}|/x~q{|v~}qx~fv~m{}x~}\\v~l{}w~|`v~pv~}`v~jv~]n~}Xw~}m{|w~}\\{|w~|vv~X{|v~t{}w~" + "|^{|w~|m{}w~|h{|v~p{}w~pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bw~}k{}w~|dv~jv~X{|w~}W{}w~}l{}w~}b{|v~lv~|Y" + "{}v~|S{}w~}U{|v~}f{|v~|ju~|t{|v~s{}v~|h{}w~}hv~|dt~}y{|v~y{|t~|g{|v~|d{}v~k{|u~|?{}w~>u~|b{|v{}w~[{}v~|e{}v~}\\" + "{}w~ s{|w~V{|w~}sy~}S{|v~P{|w~o{}x~}`{|a~}+{|u~}|u{|w~0{}y~v{|w~}g{|y~}d{|j~}\\{}v~|w{|v~}Aw~}7{}y~sw~tw~}t{|y~" + "} P{}w~ p{|w~|m{}w~|Ux~}w{|x~} w{|j~}W{|v~|vv~}X{}x~|p{}y~|x{}x~b{}x~}hw~c{}x~}p{}y~|x{}x~^v~X{|b~|b{|b~|b{|b" + "~|b{|b~|b{|b~|b{}b~}id~Y{|v~|J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{}v~g{}w~|r{|v~wv~i{|v~|d{}v" + "~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~_{}v~}u~|a{|v~|ww~}m{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w" + "~}Z{|v~|V{}w~}sy|s~_w~}n{}u~|b{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|j{|u" + "~}|q{}a~|kv~N`~|c`~|c`~|c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~.v~v{|w~tv~a{|w~|m{}w~|a{" + "|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|\\v~uv~[w~}k{}w~|^v~uv~ T{}x~}q{}w~q{|x~}j{}x~}b{|x~}j{}x~}vu~|{|u~|w{|x~}j{}" + "x~}vu~|n{|x~}j{}x~}b{|x~}[{|w~Qv~|w{|v~ SZ~}`v~x{|y~}'{|]~}iW~|e{|g~}\\{}i~}^w~}kw~}aw~}l{|w~|^{|v~t{|w~}X{|v~x" + "{|v~`w~} m{|v~ jw|({}Z~X{|y~|v{}w~}[{}x~}u{}x~}s{|w~o{}w~}o{}u~x{|w~|)v~Fv~ v{}w~ g{}w~Uv~|lv~|W{}w~}P{}v~" + "}B{|v~c{|_~|O{}w~}a{}v~l{|v~X{|v~|Y{|v~|lv~|N{|v~ S{|}p~|[{|Z~}[{|}p~}|X{}w~}`{|x~|sw~|nw~|u{|x~}l{}b~}b{}w~}k{" + "|v~e{|v~}N{}w~}g{|v~}d{}w~}L{}w~}T{|v~}ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}v{|t~W{}w~}V{}w~|t{|r~sv~|h{}w~|q{}w~}xv" + "~i{|v~}dv~}d{}w~}T{|v~}dv~}f{}w~}nv~}J{}v~Y{|v~|Z{|v~|i{}w~}_{|v~vv~|b{}w~}xw~|qw~|y{|v~bv~}v{}v~S{|v~|T{}v~}K{" + "|w~}G{}x~}K{|w~| tv~}n{}w~|_v~kv~|bv~|Ov~k{}w~|bv~Bw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tw~}{|u~|Mv~_w~}mv~mv~hw~}m{|w~" + "}bv~|kv~`v~k{}w~|dv~k{}w~|Zw~}Iy|}q~Wv~S{|w~|m{}w~|]{|v~uv~_{|w~|xw~uw~|y{|w~}\\r~}T{|w~|w{}w~}T{}v~|M{|v~Kw~|L" + "{}w~} O{}y~|rt~|s{|y~}fv~|nw~}\\v~l{|w~}`w~}p{}w~|`v~|kv~^u~}|Qw~}m{|w~}[w~}w{}w~}X{}w~|t{|w~}^{|w~|m{}w~|h{|v~" + "pv~pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~k{}w~|dv~|l{|v~X{|w~}W{|w~}l{}w~|b{}w~}l{}w~}Z{|v~}R{}w~}T{}v" + "~f{}v~i{|u~t{|v~t{|u~g{}w~}hv~|cr~}v~}s~}f{|v~}dv~}j{|u~|@{}w~?u~|b{}~|w{}w~vy~a{}v~|g{}v~}b{}~|w{}w~vy} {{}w~|" + "W{|w~}sy~}S{|v~Ow~}q{|w~|`{|a~}){}u~}vw~}0{|y~}v{}w~}p{|t{}y~|d{|j~}[{|v~|vv~}Bw~}7{|y~}tw~t{|w~|u{}y~| P{}w~ " + "p{|w~|m{}w~|Ux~}w{|x~} w{|j~}X{}v~v{|v~}X{|w~p{|y~|w{}x~bw~h{}x~|d{|w~p{|y~}w{}x~^v~X{}b~}b{}b~}b{}b~}b{}b~}b{" + "}b~}b`~j{}d~Y{|v~}J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~fv~}g{}w~|q{}w~}xv~i{|v~}dv~}k{|v~}dv~}k" + "{|v~}dv~}k{|v~}dv~}k{|v~}dv~}`{}v~|{|u~|b{|v~}x{}x~}lv~}h{|v~|i{}w~}f{|v~|i{}w~}f{|v~|i{}w~}f{|v~|i{}w~}Z{|v~|V" + "{}e~|_w~}m{|u~bv~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|jv~}n{}w~Tv~|Ov~Lv~Lv~Lv~Av~Lv~Lv~Lv~" + "Wv~|l{|v~`w~}m{|w~}bv~|kv~bv~|kv~bv~|kv~bv~|kv~bv~|kv~.v~vw~|u{|v~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}" + "w~|\\{|w~|w{}w~}[v~k{}w~|^{|w~|w{}w~} T{|w~q{}w~q{}x~|j{|w~b{}x~|j{|w~wu~|x{|u~|x{}x~|j{|w~wu~|m{}x~|j{|w~b{}x~" + "|[{|w~Q{|w~}w{}w~} SZ~}`{}w~|y{}y~|'{|n~y}~|n~}i{}k~x}k~c{|i~}Z{}j~]w~}kw~}a{}w~l{|w~|^{}w~}sv~Wv~|y{}w~}`{}w~|" + " mv~| o{}Z~X{|y~|v{|w~}\\{|w~t{}x~|rw~|p{}w~}n{}u~yw~}(v~|Gv~ v{}w~ gw~}U{}w~}m{|v~V{}w~}Q{}v~}A{|v~c{|_~" + "|O{}w~}a{}v~l{|v~X{}v~X{|v~k{}w~}N{}w~} Q{|}p~}|^{|Z~}^{|}p~}|U{}w~}`{|x~}sw~|o{|w~|u{}x~|l`~b{}w~}k{|v~|eu~N{}" + "w~}g{}v~|d{}w~}L{}w~}Su~ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}u{|t~X{}w~}V{}w~|ss~}sv~|h{}w~|q{|v~|yv~hu~e{|v~|d{}w~}" + "Su~e{|v~|f{}w~}n{}v~|K{|v~|Z{|v~|Yv~|i{}w~}^v~|x{}v~a{|v~y{|w~|q{}x~}y{}w~}c{}v~tv~}T{|v~|U{|v~}J{|w~}G{|w~K{|w" + "~| u{|v~m{}w~|_v~kv~a{}w~|O{}w~|l{}w~|bv~|Cw~}V{}w~|l{}w~|`w~}m{|w~}Wv~Lv~Tw~}y{|u~|Nv~_w~}mv~mv~hw~}m{|w~}bv~" + "|l{|v~`v~kv~cv~|l{}w~|Zw~}D{|}u~}Xv~S{|w~|m{}w~|\\{}w~|w{|w~}^w~}y{|w~u{}x~}y{}w~|]{}q~|Tv~wv~|U{|v~}K{}w~|Lw~|" + "Lv~ N{|x~s{}x~{w~|tx~|fv~|o{|v~\\v~l{|w~}a{|w~|p{}w~_{}w~|l{|v~_{}v~|Ow~}m{|w~}[{}w~|xv~X{|v~rv~|_{|w~|m{}w~|h{" + "|v~|qv~pv~|iv~|u{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~|bv~kv~c{}w~|l{|v~X{|w~}Vv~l{}w~|bv~|l{|v~[{|v~}Q{}w~}T{|v~}" + "h{|v~|hu~}u{|v~u{|u~|g{}w~}hv~|b{}f~|du~e{|v~|i{|u~|A{}w~@u~|b{}x~|x{}w~ww~a{}v~|i{}v~}b{}x~|x{}w~w{}y~} {}w~|W" + "{|v~sy~}S{|v~O{|w~}s{}w~}^q|}v~q|'{}t~|{|w~}.x~u{}v~}|wy|}y~tx~/{|v~|v{}w~}Cw~}6x~tw~s{}w~ux~ O{}w~ p{|w~|m{}w" + "~|Ux~}w{|x~} B{}w~}v{|v~|Ww~|q{|y~}v{}x~c{}x~|i{}x~}cw~|q{|y~}v{}x~_{|v~X`~b`~b`~b`~b`~c{|`~|kc~Xu~J{}w~}M{}w~" + "}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~g{|v~}g{}w~|q{|v~|yv~hu~e{|v~|ju~e{|v~|ju~e{|v~|ju~e{|v~|ju~e{|v~|a{}" + "v~|x{|u~|bu~y{}w~l{|v~|gv~|i{}w~}ev~|i{}w~}ev~|i{}w~}ev~|i{}w~}Z{|v~|V{}f~|^w~}l{|v~|d{|v~m{}w~|a{|v~m{}w~|a{|v" + "~m{}w~|a{|v~m{}w~|a{|v~m{}w~|a{|v~m{}w~|k{|v~m{}w~T{}w~|Ov~|Mv~|Mv~|Mv~|Bv~Lv~Lv~Lv~W{}w~|l{|v~`w~}m{|w~}bv~|l{" + "|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~.v~|x{}x~|t{|v~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|[v~wv~|[v" + "~kv~\\v~wv~| Sw~|r{}w~r{|w~hw~|d{|w~hw~|yu~|v{|u~y{|w~hw~|yu~|m{|w~hw~|d{|w~Z{|w~Pv~wv~| SZ~}_w~}yx~%n~{|~{|o~|" + "i{|l~}|}|l~}b{}j~Xk~|]w~}kw~}a{}w~l{}w~]v~|s{}w~|X{}w~}yv~|_w~} mv~} g{}x~}t{}x~}O{|y~|uw~}\\{}x~|t{}x~|rw" + "~|p{|w~}m{}u~}w~|({}w~|H{|w~} v{}w~ h{|w~|U{}w~}m{|v~V{}w~}R{}v~}@{|v~c{|_~|Ov~|a{|v~l{}w~}Xv~}X{|v~k{}w~}Nv~|" + " N{|}p~}|a{|Z~}a{|}p~}|R{|w}|_x~}s{}x~}o{}w~|v{|w~l{}`~|c{}w~}k{|v~|e{}v~|O{}w~}gu~c{}w~}L{}w~}S{}v~|fv~|h{}w~}" + "hv~|Y{}w~}M{}w~}W{}w~}t{|t~Y{}w~}V{}w~|s{}t~rv~|h{}w~|p{}w~}yv~h{}v~|f{}v~c{}w~}S{}v~|f{}v~e{}w~}mv~}K{|v~|Z{|v" + "~|Yv~|iv~|^{}w~}xv~}`v~|{|w~p{}w~yv~|d{|v~|t{|v~|U{|v~|V{|u~I{|w~}Fw~|L{|w~| u{}w~|mv~|_v~|m{|v~a{}w~}O{}w~|lv" + "~|b{}w~|Cw~}V{}w~|lv~|`w~}m{|w~}Wv~Lv~Tw~}x{|u~|Ov~_w~}mv~mv~hw~}m{|w~}b{}w~|l{|w~}`v~kv~c{}w~|lv~|Zw~}B{|u~Xv~" + "S{|w~|m{}w~|\\{|w~}w{}w~|^v~y{}x~}u{|x~}y{}w~]{|v~|}v~T{}w~|y{|w~}U{|v~}J{|w~}Lw~|M{|w~} Mx~}v{|w~|{|w~|v{}x~e{" + "}w~|o{}v~\\v~l{|w~}a{|w~|pw~}_{}w~|l{|w~}_v~Mw~}m{|w~}[{|w~}y{|w~}X{}w~|r{}w~}_{|w~|m{}w~|h{|v~|qv~|r{|v~|i{}w~" + "|u{}w~tv~|b{|w~}q{|w~}`v~t{}w~t{}w~|bv~kv~c{}w~|l{|w~}X{|w~}Vv~lv~b{}v~jv~|\\u~P{}w~}S{}v~|iu~g{|t~|w{|v~v{}u~}" + "f{}w~}hv~|a{}h~|c{}v~|f{}v~g{|u~|B{}w~Au~|b{}v~|y{}w~xu~a{}v~|k{}v~}b{}v~|y{}w~x{}w~}!{}w~|Vv~sy~}S{|v~O{|u~}y|" + "{y|u~}T{|w~}Lw}|P{|}p~}-{|y~}u{}l~u{}y~|.{|v~|v{}w~}Dw~}6{|y~}uw~rw~}w{}y~| O{}w~ p{|w~|m{}w~|Ux~}w{|x~} C{}w" + "~}v{|v~|W{}x~}px~u{}x~d{|w~i{}x~}c{}x~}px~u{}x~_{}w~}Y{}`~|d{}`~|d{}`~|d{}`~|d{}`~|d{}w~}j|}w~}l{|c~X{}v~|K{}w~" + "}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~gu~|g{}w~|p{}w~}yv~h{}v~|f{}v~i{}v~|f{}v~i{}v~|f{}v~i{}v~|f{}v~" + "i{}v~|f{}v~a{}v~|v{|u~|c{}v~|}w~|l{}v~fv~|iv~|ev~|iv~|ev~|iv~|ev~|iv~|Z{|v~|V{}h~}\\w~}k{}w~|d{}w~|mv~|a{}w~|mv" + "~|a{}w~|mv~|a{}w~|mv~|a{}w~|mv~|a{}w~|mv~|k{}w~|mv~|U{}w~}O{}w~|M{}w~|M{}w~|M{}w~|Bv~Lv~Lv~Lv~W{}w~}l{}w~}`w~}m" + "{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}.{}w~|y{}x~|s{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w" + "~|m{}w~|a{|w~|m{}w~|[{}w~|y{|w~}Zv~kv~\\{}w~|y{|w~} R{|w~r{}w~rw~}h{|w~dw~}h{|w~y{|w~|t{|w~}yw~}h{|w~y{|w~|lw~}" + "h{|w~dw~}Z{|w~P{}w~|y{|w~} Rs}v~g}|_{}w~{|y~}%{|p~|{|~yp~}g{}m~{}~{}m~|a{}l~|X{|m~}\\w~}kw~}a{|w~|mv~]v~r{}w~}X" + "{|v~{|v~^{}w~} n{}v~ gw~|tw~|O{|y~|uw~}]{|x~}sw~|rw~|p{|v~l{}r~}'{|w~}H{|w~} v{}w~ h{|w~T{|v~m{}w~}V{}w~}" + "S{}v~}?{|v~c{|_~|Ov~|`v~|m{}w~}Y{|v~W{|v~k{}w~}O{|v~ J{|}p~}|d{|Z~}d{|}p~}|-w~s{|w~ov~|v{}x~|lv~|j{|v~c{}w~}k{}" + "v~cv~}O{}w~}h{}v~|c{}w~}L{}w~}Rv~}fv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}rt~Z{}w~}V{}w~|ru~}rv~|h{}w~|p{|v~|{v~h{|v~}g" + "{|v~}c{}w~}Rv~}g{|v~}e{}w~}m{|v~|L{|v~|Z{|v~|Y{}w~}j{|v~|^{|v~|{|v~_{}w~}{}x~}p{|w~yv~cv~}r{}v~U{|v~|W{|u~|I{|w" + "~}F{}x~}L{|w~| u{}w~|n{|v~|_v~}m{}w~}a{|w~}O{|w~}m{|v~|b{}w~}Cw~}V{|w~}m{|v~|`w~}m{|w~}Wv~Lv~Tw~}vu~|Pv~_w~}mv" + "~mv~hw~}m{|w~}b{|w~}l{}w~}`v~|m{|w~}c{|w~}lv~|Zw~}@v~|Yv~S{|w~}mv~|[v~wv~]{}w~|{w~|u{|w~yw~}]v~}y{}v~U{|w~}y{}w" + "~|V{|v~}I{|w~}Lw~|M{|w~} M{|w~x}v~}x{}v~x}w~|e{}w~}ou~|]v~l{|w~|a{|w~p{}w~|_{|w~}l{}w~}`{|w~}Mw~}m{|w~}Zv~y{}w~" + "|Y{|v~q{|v~_{|w~}m{}w~|gv~|r{|v~|r{|v~h{}w~}u{}w~tv~a{|w~}q{|w~}`v~t{}w~t{}w~|bv~|m{|w~}c{|w~}l{}w~}X{|w~}V{}w~" + "|n{|w~}bv~}j{}v~]{}v~|P{}w~}Ru~j{}v~|f{|t~}|y{|v~x{|t~}e{}w~}hv~|`{|}l~}`v~}g{|v~}f{|u~|C{}w~Bu~|`u~|{}w~yu~|`{" + "}v~|m{}v~}a{|u~|{}w~y{}v~}!{}w~|Vv~|ty~}S{|v~P{|g~}U{|w~}Lw~|N{|r~}+{}y~|u{|}o~}v{|y~}+v~}v{}v~Ew~}5{}y~|vw~r{|" + "w~|y{|y~} N{}w~ p{|w~}m{}w~|Ux~}w{|x~} Dv~}v{}v~|W{|w~p{}y~|u{}x~dw~|j{}w~c{|w~p{}y~|u{}x~`{}v~|Yv~|j{|v~dv~|" + "j{|v~dv~|j{|v~dv~|j{|v~dv~|j{|v~dv~|j{|v~l{}w~}n{|v~Wv~}K{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~h{" + "|v~}f{}w~|p{|v~|{v~h{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}b{}v~|t{|u~|cq~|l{|v~}f{}w~}j{|v" + "~|e{}w~}j{|v~|e{}w~}j{|v~|e{}w~}j{|v~|Z{|v~|V{}k~}|Zw~}k{}w~}d{}w~|n{|v~|a{}w~|n{|v~|a{}w~|n{|v~|a{}w~|n{|v~|a{" + "}w~|n{|v~|a{}w~|n{|v~|k{}w~|n{|v~}U{|w~}O{}w~}M{}w~}M{}w~}M{}w~}Bv~Lv~Lv~Lv~W{|v~lv~|`w~}m{|w~}b{|w~}l{}w~}b{|w" + "~}l{}w~}b{|w~}l{}w~}b{|w~}l{}w~}b{|w~}l{}w~}Xt|X{}w~}{}x~}r{}w~}a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|[{|w~}y" + "{}w~|Zv~|m{|w~}\\{|w~}y{}w~| Qw~}s{}w~s{}w~fw~}f{}w~fw~}y{|y~|r{|y~}y{}w~fw~}y{|y~|l{}w~fw~}f{}w~Y{|w~P{|v~y{}w" + "~| Kv~}J{|w~|}y~|${}r~}y{}~y{|q~f{|n~|{}~yn~}_m~|V{|o~}[w~}kw~}`w~}n{|w~}^{|w~}r{|v~Wv~{}w~}]v~| o{|v~| hw" + "~t{|w~N{|y~|uw~}]w~|s{}x~|rw~|ov~|l{}s~&{|w~}H{}w~| v{}w~ h{}x~}Sv~|nv~|V{}w~}T{}v~}>{}w~}Q{}w~}J{}v~_{}w~}mv~" + "}Y{}w~}Vv~|lv~|Ov~} G{|}p~}|0{|}o~}*{}x~rw~}q{}v~|w{}w~l{|v~hv~|d{}w~}ku~c{}v~}P{}w~}i{}u~b{}w~}L{}w~}R{}v~|gv~" + "|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}qt~[{}w~}V{}w~|r{}v~|rv~|h{}w~|o{}w~}{v~g{}v~|hu~|c{}w~}R{}v~|hu~|e{}w~}lv~}L{}v~Y" + "{|v~|Y{}v~j{}v~\\{}w~}{}w~}_{|v~{w~|ow~y|v~d{}v~pv~}V{|v~|Wu~|H{|w~}F{|w~L{|w~| u{}w~m{}v~|_u~mv~|a{|v~Nv~|n{}" + "v~|b{|v~Cw~}Uv~|n{}v~|`w~}m{|w~}Wv~Lv~Tw~}uu~|Qv~_w~}mv~mv~hw~}m{|w~}b{|v~lv~|`v~}m{}w~}c{|v~m{|v~|Zw~}@{}w~|Yv" + "~S{|w~}mv~|[{}w~|y{|w~}]{|w~}{w~sw~y|w~}^{}w~}wv~}U{}w~yv~Uv~}Gw~}Lw~|M{|w~| L{|q~}v{}q~|d{|w~}p{|u~|]v~l{}w~|a" + "{|w~pv~^{|v~lv~|`{|w~|Mw~}m{|w~}Z{}w~y|v~X{}w~}pv~|`{|w~}mv~|gv~}r{|v~}r{}v~h{|v~u{}w~u{|w~}a{|w~}q{|w~}`{}w~|u" + "{}w~tv~av~}m{}w~}c{|v~lv~|X{|w~}V{|w~}n{}w~|c{|v~i{|v~|_{}v~}O{}w~}R{|v~}l{}v~|d{|r~y}v~y}s~}d{}w~}hv~|]{|}s~y}" + "|^{}v~|hu~|e{|v~}C{}w~C{}v~|^u~|}w~{}v~|^{}v~n{|v~}_{|u~|}w~{}v~} {}w~|V{}w~}ty~}S{|v~Q{}e~}V{|w~}Lw~|L{|t~*{|x" + "~|t{|y}u~}|u{|x~|*{}w~|v{|v~Fw~}5{|x~|ww|qw|y{|x~| >{|w~}mv~|Ux~}w{|x~} Ev~}v{|v~U{}x~|q{|y~}t{}x~e{}x~}j{}w" + "~b{}x~|q{|y~}t{}x~a{}v~}Y{|v~hv~|f{|v~hv~|f{|v~hv~|f{|v~hv~|f{|v~hv~|f{}v~hv~|n{|v~|n{|v~W{}v~}L{}w~}M{}w~}M{}w" + "~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~i{|u~|f{}w~|o{}w~}{v~g{}v~|hu~|h{}v~|hu~|h{}v~|hu~|h{}v~|hu~|h{}v~|hu~|c{}" + "v~|r{|u~|d{}s~|ku~|f{}v~j{}v~d{}v~j{}v~d{}v~j{}v~d{}v~j{}v~Y{|v~|V{}w~}r|Vw~}k{|w~|d{}w~m{}v~|a{}w~m{}v~|a{}w~m" + "{}v~|a{}w~m{}v~|a{}w~m{}v~|a{}w~m{}v~|k{}w~m{}u~U{|v~O{|v~M{|v~M{|v~M{|v~Bv~Lv~Lv~Lv~Vv~|n{|v~_w~}m{|w~}b{|v~lv" + "~|b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|X{}u~X{|v~|x~}qv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|Z{}w~yv~Yv~}m{}" + "w~}[{}w~yv~ P{|w~}t{}w~t{|w~}f{|w~}h{|w~}f{|w~}yy|p{|}y{|w~}f{|w~}yy|l{|w~}f{|w~}h{|w~}Y{|w~Ov~y|v~ K{}w~}Hw~}y" + "~}\"{}t~}x{}~x{|s~d{|p~}y{}~y{|p~}]o~|T{}p~Zw~}kw~}`{}w~|o{}w~|^{}w~|qv~|X{}w~|v~|]{|v~| o{}v~j{} {|x~}t{|" + "x~}N{|y~|v{}w~}^{}x~}r{}x~}rw~|o{}v~k{}u~|%v~Hv~ u{}w~ hw~|S{}v~o{}v~U{}w~}U{}v~}>{|v~}Q{}w~}Ju~_{|v~n{|v~|Z{|" + "v~|Vv~}m{|v~|P{}v~ C{}o~}4{|o~}|({|x~}s{}w~}s{}u~|x{}w~|l{}w~}h{}w~}d{}w~}l{|v~}bu~|g{|}g{}w~}j{}u~|b{}w~}L{}w~" + "}R{|u~|hv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}pt~\\{}w~}V{}w~|r{|v}qv~|h{}w~|nv~|v~g{|u~|j{}v~}b{}w~}R{|u~i{}v~}d{}w~}" + "l{|v~|M{}v~Y{|v~|Y{|v~|kv~}\\{|v~{v~|_{|v~|w~|o{}x~y}w~}e{|v~|p{|v~|W{|v~|X{}v~}G{|w~}F{|w~|M{|w~| u{}w~|nu~|_" + "u~}o{}v~_v~}O{}w~}o{|u~|av~}Dw~}U{}w~}o{|u~|`w~}m{|w~}Wv~Lv~Tw~}t{}v~|Rv~_w~}mv~mv~hw~}m{|w~}av~|n{|v~_u~mv~|bv" + "~|n{}v~|Zw~}@{}w~|Yv~Rv~n{}v~|[{|w~}y{}w~|\\w~}|x~}s{}x~y}w~|_{}v~v{|v~|V{|w~y}w~}Vu~Fw~}Lw~|M{|w~| K{|s~}t{}s~" + "|bv~p{}u~}]v~|mv~`{|w~q{}w~}]v~}n{}v~_{|w~|Mw~}m{|w~}Yw~y}w~|Xv~o{|w~}`{|v~n{|v~|g{}v~r{}u~rv~}gv~|v{}w~uv~|a{|" + "w~}q{|w~}`{|w~}u{}w~u{|v~au~mv~|bv~}n{}v~Vv~Uv~nv~b{}w~}hv~}`{|v~}N{}w~}Q{|v~}n{}v~}b{|c~}c{}w~}hv~|Z{|v~Z{|u~|" + "j{}v~}c{|w~B{}w~B{}x~|\\u~}w~}v~|\\{}x~|m{}x~}]{|u~}w~}v~} {{v~|V{|v~|uy~}S{|v~R{}v~y|q~}|u~W{|w~}Lw~|J{}u~*{|x" + "~|e{|x~|({}x~}u{|w~F{|x}|4{|x~|e{|x~| ={|v~n{|v~|Ux~}w{|x~} Ew~|u{|x~}U{|x~}p{}j~}iw~j{}w~b{|x~}p{}j~}f{}v~}" + "X{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}fv~}h{}w~}n{}w~}m{|v~Vu~|g{|}c{}w~}M{}w~}M{}w~}M{}w" + "~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~j{|u~}e{}w~|nv~|v~g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}c{" + "}v~|p{|u~|e{|t~}k{}v~}e{|v~|kv~}d{|v~|kv~}d{|v~|kv~}d{|v~|kv~}Y{|v~|V{}w~}Mw~}k{}w~|d{}w~|nu~|a{}w~|nu~|a{}w~|n" + "u~|a{}w~|nu~|a{}w~|nu~|a{}w~|nu~|k{}w~|nt~|Uv~}Ov~}Mv~}Mv~}Mv~}Cv~Lv~Lv~Lv~V{}v~nv~}_w~}m{|w~}av~|n{|v~`v~|n{|v" + "~`v~|n{|v~`v~|n{|v~`v~|n{|v~W{}u~Wr~q{|v~_v~n{}v~|`v~n{}v~|`v~n{}v~|`v~n{}v~|Z{|w~y}w~}Yu~mv~|[{|w~y}w~} O{}w~}" + "u{}w~u{}w~}d{}w~}j{}w~}d{}w~}j{}w~}d{}w~}j{}w~}d{}w~}j{}w~}X{}w~O{|w~y}w~} L{}w~}G{}u~|!{|}x~}|w{}~v{}w~}b{|r~|" + "x{}~w{}s~|\\{|q~}Rq~|Zw~}kw~}`{|v~p{|v~]v~p{}w~}X{|q~[{}v~} p{|v~}ly}$v}|\"{}x~}t{}x~}Yy}|s{|y~|w{|v~|_{|w~" + "q{}x~}s{|w~n{|v~}l{|u~}%{}w~|Iw~} u{}w~L{}w~} tv}|P{|w~R{|v~|pv~}U{}w~}V{}v~}={}v~|Q{}w~}K{}v~|^v~|o{}v~Y{}v~U{" + "}v~m{}v~P{|v~}U{|v}M{}w~}F{|}q~}6{|q~}|G{|w}|^w~ru~y|x{|}t~y|}v~|kv~|h{|v~d{}w~}m{|u~|b{|u~|i{|~}g{}w~}l{|}u~}a" + "{}w~}L{}w~}Q{}u~|iv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}ot~]{}w~}V{}w~|bv~|h{}w~|n{}q~f{}u~k{}u~a{}w~}Q{}u~k{|u~c{}w~}" + "kv~}c{|}h{|v~}Y{|v~|X{}v~l{}v~|[v~}v~]v~}w~n{}r~|ev~}n{}v~W{|v~|Y{}v~}F{|w~}Ew~}M{|w~| u{}w~|o{}u~|_t~|q{|v~}_" + "{|v~|P{|v~}pt~|a{|v~|Ew~}U{|v~|pt~|`w~}m{|w~}Wv~Lv~Tw~}s{}v~|Sv~_w~}mv~mv~hw~}m{|w~}a{}v~nv~}_u~}o{}v~a{}v~o{|u" + "~|Zw~}@{}w~|Y{}w~|Sv~|p{|u~|Zv~{|v~[v~}x~}s{|r~_{|v~|u{}v~Uq~V{}v~|Fw~}Lw~|M{|w~| I{|y}~y}|r{|}x~}|`{}w~}qs~]u~" + "n{|v~`{|w~r{|v~\\{|v~nv~}_{|w~}Mw~}m{|w~}Y{}r~X{}w~}nv~`{|v~|o{}v~|g{|v~|st~|t{|v~|g{}v~v{}w~v{|v~`{|w~}q{|w~}_" + "v~|v{}w~uv~}au~}o{}v~a{|v~nv~}Vv~U{|w~}p{}w~}bv~|h{|v~`u~M{}w~}P{|u~|q{}v~}_{}g~}|b{}w~}hv~|Z{|v~Y{}u~k{}u~a{|y" + "~A{}w~A{}~|Zl~|Z{}~|k{}~}[{|l~} yv~}Uv~}uy~}S{|v~S{}v~|x{|y}x~}|wu~X{|w~}Lw~|I{|v~}*{}x~|g{|x~}&{}y~}t{|x~ T{}x" + "~|g{|x~} <{|v~|o{}v~|Ux~}w{|x~} Ex~|t{|y~}Tw~|p{}j~}j{}x~|k{}x~}aw~|p{}j~}g{}v~}Wv~|h{|v~fv~|h{|v~fv~|h{|v~f" + "v~|h{|v~fv~|h{|v~g{|v~g{|v~|ov~|m{|v~V{|u~|i{|~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~k{}t~d{}w~" + "|n{}q~f{}u~k{}u~e{}u~k{}u~e{}u~k{}u~e{}u~k{}u~e{}u~k{}u~c{}v~|n{|u~|e{}u~|l{}u~c{}v~l{}v~|c{}v~l{}v~|c{}v~l{}v~" + "|c{}v~l{}v~|Y{|v~|V{}w~}Mw~}kv~c{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|k{}w~|o{" + "}s~U{|v~|P{|v~|N{|v~|N{|v~|N{|v~|Dv~Lv~Lv~Lv~Uv~}p{}v~^w~}m{|w~}a{}v~nv~}`{}v~nv~}`{}v~nv~}`{}v~nv~}`{}v~nv~}W{" + "}u~W{}t~|qv~}_v~|p{|u~|`v~|p{|u~|`v~|p{|u~|`v~|p{|u~|Yq~Xu~}o{}v~Yq~ M{}w~}|w{}x~}v{}v~b{}w~}|m{}v~b{}w~}|m{}v~" + "b{}w~}|m{}v~b{}w~}|m{}v~W{}x~}Nq~| M{|v~F{|u~ py~|V{|}y~y}|vy~|w{|y}y~y}Y{|s~}Q{|s~|Yw~}kw~}_{}v~|s{}v~|^{|w~}p" + "{|v~X{|r~}Z{}u~} q{}v~}o{|y~}$v~}\"w~|tw~|Y{}y~}|u{|y~|x{|u~^{}x~|q{|w~s{}x~}mu~}n{|s~}&{|w~|J{|w~| u{}w~L{" + "}v~ u{|v~|P{}x~}Q{}v~|r{}v~T{}w~}W{}v~}O{}|k{}v~}P{}w~}]{}|l{}u~]{|v~|q{}v~|Yv~}U{|v~}o{}v~}Q{|v~}T{}v~M{}v~C{|" + "}t~}6{|t~}|D{}w~}^{}x~|s{|m~y}q~|k{|v~fv~|e{}w~}n{|u~}`{}u~|l{|}y~}g{}w~}n{|}t~}`{}w~}L{}w~}P{}u~}jv~|h{}w~}hv~" + "|Y{}w~}M{}w~}W{}w~}nt~^{}w~}V{}w~|bv~|h{}w~|mq~e{}u~|n{}u~|a{}w~}P{}u~|n{}u~|c{}w~}k{|v~|d{|y~}k{|u~|Y{|v~|X{|u" + "~n{|u~Z{}r~}]{}s~}n{|r~e{}v~lv~}X{|v~|Z{|u~E{|w~}E{}w~M{|w~| u{|v~p{|t~|_s~|s{|u~]u~|P{}v~}s{|s~|`u~|k{|Ww~}T{" + "}v~}s{|s~|`w~}m{|w~}Wv~Lv~Tw~}r{}v~}Tv~_w~}mv~mv~hw~}m{|w~}`v~}p{}v~|_t~|q{|v~|`v~}q{|t~|Zw~}Q{|kv~|Y{}w~}S{}v~" + "pt~|Z{}w~y}w~}[{}s~|rs~}_v~}s{}w~}V{}s~}W{}v~|Ew~}Lw~|M{|w~| r{|v~|s{}s~}^u~}ov~|_w~|s{}w~|[v~}pu~]v~|Nw~}m{|w" + "~}Y{|s~}Xv~m{}w~|a{|u~p{|u~|fv~}t{}x~}x~}t{}v~ev~}w{}w~w{|v~}`{|w~}q{|w~}_{}v~|w{}w~v{}v~`t~|q{|v~|`v~}p{}v~U{}" + "w~|Uv~|r{|v~b{|v~fv~|bu~|M{}w~}O{|u~}t{|u~}\\{|k~}|`{}w~}hv~|Z{|v~X{}u~|n{}u~|`{|@{}w~@{|Xn~|X{|i{|Y{|n~} xv~}U" + "{|v~}vy~}S{|v~T{|v~|jv~}Y{|w~}Lw~|H{|v~|*{}x~}i{}x~}${}~}s{|y~ S{}x~}i{}x~} ;{|u~p{|u~|Ux~}w{|x~} Ey~|s{|~}T" + "{}x~}o{}j~}k{|w~k{}x~}a{}x~}o{}j~}h{}v~}W{|v~fv~|h{|v~fv~|h{|v~fv~|h{|v~fv~|h{|v~fv~|h{}w~}f{}w~}p{|v~l{|v~U{}u" + "~|l{|}y~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~n{|}s~c{}w~|mq~e{}u~|n{}u~|d{}u~|n{}u~|d{}u~|n{}u" + "~|d{}u~|n{}u~|d{}u~|n{}u~|d{}v~|l{|u~|et~|n{}u~|c{|u~n{|u~b{|u~n{|u~b{|u~n{|u~b{|u~n{|u~X{|v~|V{}w~}Mw~}x{|p{}v" + "~c{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|k{|v~p{|q~j{|gu~|Pu~|k{|_u~|k{|_u~|k{|_u~|k{" + "|Vv~Lv~Lv~Lv~U{|v~}r{}v~}^w~}m{|w~}`v~}p{}v~|_v~}p{}v~|_v~}p{}v~|_v~}p{}v~|_v~}p{}v~|W{}u~Vu~|q{}v~|_{}v~pt~|`{" + "}v~pt~|`{}v~pt~|`{}v~pt~|Y{}s~}Xt~|q{|v~|Y{}s~} Lu~}p{}u~|au~}p{}u~|au~}p{}u~|au~}p{}u~|au~}p{}u~|W{}x~}N{}s~} " + "M{|v~|Ev~} py~|Jy~|M{}t~O{|u~}Xw~}kw~}_{|t~}w|}u~}]{}w~}ov~|Xr~|Y{}t~}y| tt~|r{}x~}$v~}\"w~t{|w~X{}v~}y|y{|" + "y~y|}t~|_{|x~}ow~}tw~|m{|t~|r{|}q~}&w~}J{}w~ t{}w~L{}v~ u{|v~|Pw~|Pu~|t{}v~|\\s|}w~}r|a{}v~}Nx~}|p{}t~O{}w~}]{}" + "y~}|q{}t~|\\{}v~|s{}u~Y{|v~|T{}u~|r{}u~|_{~}|r{|}u~|T{}v~M{}v~@{|}w~}6{|w~}|A{}w~}^{|w~r{|o~}{}s~}iv~}f{}w~}e{}" + "w~}q|y}s~|_{}t~|p{|}w~}g{}w~}r|y}q~}_{}w~}g|`{}w~}O{}t~}o{|}u~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}mt~_{}w~}h|i{}w~|bv~" + "|h{}w~|m{}r~dt~}|r{|t~|`{}w~}Ot~}q{|t~}b{}w~}jv~}d{|w~}|p{|}u~}X{|v~|W{}u~|q{}u~|Z{|r~|]{|s~|mr~f{|v~|l{|v~|Y{|" + "v~|[{|u~}b|^{|w~}E{|w~|N{|w~| tv~}r{}s~|_w~y}x~}|w{|}u~|]{|u~|p{|}|^t~y|x{|}w~}w~|`{|u~|n{|y~|Xw~}St~y|x{|}w~}" + "w~|`w~}m{|w~}Wv~Lv~Tw~}q{}v~}Uv~_w~}mv~mv~hw~}m{|w~}`{}v~}r{}v~}^s~}s{|v~}_{}v~}s{|s~|Zw~}Qy~}|o{}w~}X{|v~}|U{|" + "v~}s{|s~|Z{|q~Z{|s~qs~|`{}w~}qv~}Vs~|X{}v~|Dw~}Lw~|M{|w~| qu~|u{}w~|v~}_s~|s{|u~^{}w~t{}w~}Z{|v~}|t{|}v~|]{}v~" + "|ny|^w~}m{|w~}Xs~|Y{}w~}m{|w~}a{|t~|s{}t~}f{}v~}v{|w~{w~|v{}v~}e{}v~}x{}w~x{}u~_{|w~}q{|w~}^u~}|y{}w~x{}u~}`s~}" + "s{|v~}_{|v~}|t{|}v~|U{|v~}|W{|v~|t{|v~|bu~f|v~}c{}v~}h|_{}w~}Vs}t~}v{}t~s}`{|y}t~y}|]{}w~}hv~|Z{|v~Wt~}|r{|t~|#" + "{}w~ vp~| {|p~} wv~}T{}v~}wy~}v{}~Z{|v~S{}x~|hx~}X{|w~}Lw~|G{}w~}){|w~|m{|w~|\"{|}q{} R{|w~|m{|w~| XY| ${|u~}r{" + "|t~}Ux~}w{|x~} E{}qy|T{|w~c{}x~gw~|lw~}a{|w~c{}x~e{}v~}Vv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~|f" + "{|v~pv~}l{|v~}h|h{}t~|p{|}w~}c{}w~}g|a{}w~}g|a{}w~}g|a{}w~}g|X{}w~}M{}w~}M{}w~}M{}w~}Z{|v~r|x}q~b{}w~|m{}r~dt~}" + "|r{|t~|bt~}|r{|t~|bt~}|r{|t~|bt~}|r{|t~|bt~}|r{|t~|d{|v~|j{|v~}f{}s~}|r{|t~|a{}u~|q{}u~|a{}u~|q{}u~|a{}u~|q{}u~" + "|a{}u~|q{}u~|X{|v~|V{}w~}Mw~}xy~}y|wy|u~|bv~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|jv~}r{}w~}" + "|u~|o{|}y~g{|u~|p{|}|_{|u~|n{|y~|`{|u~|n{|y~|`{|u~|n{|y~|`{|u~|n{|y~|Wv~Lv~Lv~Lv~T{}u~}|x{|}u~}]w~}m{|w~}`{}v~}" + "r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}V{}u~V{|v~}r{}v~}^{|v~}s{|s~|`{|v~}s{|s~|`{|v~}s{|s~|`{|v" + "~}s{|s~|Xs~|Xs~}s{|v~}Ws~| K{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~U{}x~}N{|s~| M" + "{|w~|D{}w~| q{|y~}K{|y~}L{}v~|N{}v~Ww~}kw~}^{|j~}\\v~|o{}w~}X{}s~W{|^~} -s~}v|}v~}$v~}#{|w~t{|x~}X{}e~|^w~|o" + "{|w~|v{}w~k{|s~}v|}t~y}v~}'{}w~Jw~} t{}w~L{}v~ u{|v~|Q{|w~O{|u~}w|}u~}\\{|e~|ab~`u~w}|x}r~|O{}w~}]{}v~w}|x}s~}Z" + "t~}w|}t~X{}w~}S{|t~y}v|}t~}^v~y}y|y}s~|S{}v~M{}v~={|}~}6{|y~}|?{}w~}]w~}q{}r~|y{}u~}h{|v~|f{|v~e{}c~|]{}s~y}v|y" + "}t~}g{}b~|^{}c~}`{}w~}N{}r~y}v|y}r~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}lt~`{}d~}i{}w~|bv~|h{}w~|lr~cr~}v|}s~}_{}w~}Ns~" + "y}v|}s~}a{}w~}j{|v~|e{|s~}u|}r~W{|v~|Vs~}v|y}t~|Xs~}\\{|s~|m{}t~}fv~}j{}v~Y{|v~|[{}\\~}^{|w~}Dw~}N{|w~| t{}u~y" + "|x{|}w~y}w~|_w~}{k~|[{|t~}|wy|}x~|^{|k~y|w~|_{|t~}|vy|y}w~|Xw~}S{|k~y|w~|`w~}m{|w~}Wv~Lv~Tw~}p{}v~}Vv~_w~}mv~mv" + "~hw~}m{|w~}_{}u~}|x{|}u~}]w~y}w~y|yy|}u~|^{}u~}|x{|}w~}w~|Zw~}Qv~}y|v{|}u~|Wm~[{}u~}w|}v~}w~|Y{}s~}Yt~}q{}t~|a{" + "}v~p{|v~|W{}t~W{}d~Uw~}Lw~|M{|w~| q{|u~}|y{|}v~{|s~br~}y|yy|}u~|^{|w~}v{}v~X{}u~}y|{y|}u~}\\{|t~}|vy|y}y~}^w~}" + "m{|w~}X{}t~Xv~|lv~|b{|s~}v|}q~x}hu~}|{y|w~}{}w~}|{|}u~c{}u~}|}w~|}t~|_{|w~}q{|v~}_{|s~}v~}s~}_w~y}w~y|yy|}u~|^{" + "}u~}y|{y|}u~}S{}r~}Z{}v~}|x{|}v~}b{|Z~c{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~Vr~}v|}s~|\"{}w~ ur~| y{|r~} vv~" + "}St~}y|y~}{y|}x~`{}b~}a{}~|f{~}W{|w~}Lw~|G{|w~}({|v~}|s{|}v~| E{|v~}|s{|}v~| X{|Z~} ${|s~}y|{y|}q~}|}Xx~}w{|x~" + "} l{}x~|c{}x~h{}x~}m{|w~|`{}x~|c{}x~f{|v~}V{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~dv~|r{|" + "v~k{|b~g{}s~y}v|y}t~}c{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|b~}a{}w~|lr~cr~}v|}s~}`r~}v|}s~}`r~}v|}" + "s~}`r~}v|}s~}`r~}v|}s~}b{|x~|h{|x~}f{}o~}v|}s~}_s~}v|y}t~|_s~}v|y}t~|_s~}v|y}t~|_s~}v|y}t~|W{|v~|V{}w~}Mw~}xk~}" + "a{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|j{}" + "u~y|x{|}u~y{|t~}|vy|}v~f{|t~}|wy|}x~|^{|t~}|vy|y}w~|_{|t~}|vy|y}w~|_{|t~}|vy|y}w~|_{|t~}|vy|y}w~|Wv~Lv~Lv~Lv~S{" + "}j~}\\w~}m{|w~}_{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}U{}u~V{}t~}|x{|}u~}\\{" + "}u~}w|}v~}w~|_{}u~}w|}v~}w~|_{}u~}w|}v~}w~|_{}u~}w|}v~}w~|X{}t~Ww~y}w~y|yy|}u~|W{}t~ I{}h~}\\{}h~}\\{}h~}\\{}h~" + "}\\{}h~}T{}x~}Ms~ K{|y~}C{|w~ p{}x~K{}x~Kw~|L{}x~|Ww~}kw~}]{|l~}\\{|v~n{|w~}X{|s~U{}`~} -{|h~|$v~}#{}x~}t{}x" + "~}X{|}g~|^{}x~}m{}w~}y|}v~|j{|g~}y{}v~}({|w~|L{|w~| t{}w~L{}v~ u{|v~|Q{}x~}N{}k~}[{|e~|ab~`e~|N{}w~}]{}g~}Y{|i~" + "|Xv~|R{|g~}]i~|R{}v~M{}v~;y|5{|<{}w~}]{|w~|p{|v}|w{|x}|e{}v~dv~}f{}e~}|[{}d~|g{}d~}\\{}c~}`{}w~}M{}c~}|g{}w~}hv" + "~|Y{}w~}M{}w~}W{}w~}kt~a{}d~}i{}w~|bv~|h{}w~|l{|s~b{}f~|^{}w~}M{}f~|`{}w~}iv~}e{|c~V{|v~|Uf~}W{}t~|[s~l{}t~|g{}" + "v~hv~}Z{|v~|[{}\\~}^{|w~}D{}w~N{|w~| sj~{}w~|_w~}{|m~|Y{}i~|]{|m~|{|w~|^{|f~|Xw~}R{|m~|{}w~|`w~}m{|w~}Wv~Lv~Tw" + "~}o{}v~}Wv~_w~}mv~mv~hw~}m{|w~}^h~\\w~}{k~|\\k~y|w~|Zw~}Qg~}V{|n~Zk~{}w~|Y{|s~|Y{}u~}q{|t~a{|v~|o{}v~W{|u~|W{}d" + "~Uw~}Lw~|M{|w~| p{|l~|ys~be~}\\{}v~x}u~V{}j~}Z{|h~}^w~}m{|w~}X{|u~|Y{|w~}k{}w~}b{|w~}m~|s~h{|m~xm~|b{}g~|^{|w~" + "}pr~a{|f~}^w~}{k~|\\{}j~}R{|r~}Y{}l~}a{}Z~}d{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~U{}f~|!{}w~ tt~| w{|t~} uv~" + "}R{}i~`{}b~}`{|?{|w~}Lw~|Fw~}&{}t~w}t~} A{}t~w}t~} V{|Z~} ${|w~}m~|s~Xx~}w{|x~} m{|x~}b{}x~hw~lk~k{|x~}b{}x~" + "fv~}U{}v~dv~}j{}v~dv~}j{}v~dv~}j{}v~dv~}j{}v~dv~}j{}w~}d{}w~}r{}w~}k{|b~f{}d~|c{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}" + "w~}M{}w~}M{}w~}Z{|d~}|`{}w~|l{|s~b{}f~|^{}f~|^{}f~|^{}f~|^{}f~|`{|~|f{|~}f{|w~|}f~|]f~}]f~}]f~}]f~}V{|v~|V{}w~}" + "Mw~}xl~}_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|ii~w{|f~e{}i~|]{|f~|^{|f~|^{|f~|^{|f~|Wv~Lv~Lv~Lv~R{}l~" + "}[w~}m{|w~}^h~Zh~Zh~Zh~Zh~){|f~Zk~{}w~|^k~{}w~|^k~{}w~|^k~{}w~|X{|u~|Ww~}{k~|V{|u~| H{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|" + "j~|S{}x~}M{}u~} I{}Ax~} pw~|Lw~|L{|y~|Jy~|Vw~}kw~}[{}o~|[{}w~}mv~Wt~}T{|}b~} +{}l~}\"v~}#w~|tw~|U{|}l~}]{|w~" + "ko~|h{|j~}|w{}u~({}w~L{}w~ s{}w~Lv~| u{|v~|Qw~}M{|m~}Z{|e~|ab~`g~}|M{}w~}]{}h~|W{|k~W{}v~P{|i~|\\k~}P{}v~Mv~| " + "i{}w~}\\{}w~Jv~}d{}v~f{}g~}|X{|}h~}e{}g~}|Z{}c~}`{}w~}L{|}g~}|e{}w~}hv~|Y{}w~}M{}w~}W{}w~}jt~b{}d~}i{}w~|bv~|h{" + "}w~|ks~a{|i~}\\{}w~}L{|i~}^{}w~}i{|v~|e{}f~}U{|v~|T{}i~|Ut~Z{}u~}l{|t~g{|v~|h{|v~|[{|v~|[{}\\~}^{|w~}D{|w~N{|w~" + "| s{|l~|{}w~|_w~}x{}q~}|W{|j~|[{}p~|y{|w~|]{|g~|Xw~}P{}q~}|y{}w~|`w~}m{|w~}Wv~Lv~Tw~}n{|v~}Xv~_w~}mv~mv~hw~}m{" + "|w~}]{}l~}[w~}{|m~|Zm~|{|w~|Zw~}Qh~|T{|o~Z{|m~|{}w~|Xs~X{}u~|pu~}av~}m{}w~}Wu~V{}d~Uw~}Lw~|M{|w~| o{|n~|w{}u~b" + "f~}Z{}p~}T{}l~}X{|i~}^w~}m{|w~}Wu~Xv~|k{|v~b{|w~y|o~|{}t~g{|o~|x{|o~}`{}i~|]{|w~}p{}s~_{}j~}|]w~}{|m~|Z{}l~}P{|" + "s~}X{}n~}`X~d{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~T{|i~} {{}w~ sv~| u{|v~} tv~}Q{}j~`{}b~}#{|w~}Lw~|G{|w~}${" + "}m~} ={}m~} T{|Z~} ${|w~y|o~|{}t~Xx~}w{|x~} mw~|b{}x~i{}x~|lk~kw~|b{}x~g{|v~Tv~}d{}v~jv~}d{}v~jv~}d{}v~jv~}d" + "{}v~jv~}d{}v~k{|v~|d{|v~rv~|k{|b~e{|}h~}a{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|g~}|]{}w~|ks~a{|i~}[" + "{|i~}[{|i~}[{|i~}[{|i~}/{|w~|y{|i~}Z{}i~|[{}i~|[{}i~|[{}i~|U{|v~|V{}w~}Mw~}xm~|^{|l~|{}w~|_{|l~|{}w~|_{|l~|{}w~" + "|_{|l~|{}w~|_{|l~|{}w~|_{|l~|{}w~|i{|l~}u{|g~d{|j~|\\{|g~|]{|g~|]{|g~|]{|g~|Wv~Lv~Lv~Lv~Q{|}p~}|Zw~}m{|w~}]{}l~" + "}X{}l~}X{}l~}X{}l~}X{}l~}){|w~}l~}Y{|m~|{}w~|^{|m~|{}w~|^{|m~|{}w~|^{|m~|{}w~|Wu~Vw~}{|m~|Tu~ E{|}p~}|V{|}p~}|V" + "{|}p~}|V{|}p~}|V{|}p~}|Qw~}Lu~| i{}y~| q{|w~}M{|w~}K{|}I{|}Uw~}kw~}Y{|y}w~y}|Yv~|m{}w~|X{}u~|Q{|}e~} *{|}p~" + "}|!v~}#w~t{|w~Py|x}y~x}y|[w~|j{}r~|e{|n~}|t{}u~){|w~|N{|w~| s{}w~Lv~ t{|v~|R{|w~|L{|}p~|Y{|e~|ab~`y|}l~}|K{}w~}" + "]{|}k~|S{}o~|Vv~}N{|m~}Z{}n~}|O{}v~Mv~ h{}w~}[v~L{|v~|d{|v~|g{}k~y}y|T{|}m~}|c{}m~x}y|W{}c~}`{}w~}J{|}k~}|c{}w" + "~}hv~|Y{}w~}M{}w~}W{}w~}it~c{}d~}i{}w~|bv~|h{}w~|k{|t~_{|m~}|[{}w~}J{|l~|]{}w~}h{}w~}c{|}k~}|T{|v~R{|}m~|S{}v~}" + "Z{|u~|kt~gv~}f{}v~[{|v~|[{}\\~}^{|w~}Cw~|O{|w~| q{}p~}x{}w~|_v}vy}w~y}|S{}m~}Xy}w~y}|w{|w}|[{|l~}|Vw~}N{|}w~y}" + "|w{}w~|`v}lw}|Wv~Lv~Tv}m{|u}Yv}_w~}mv~mv~hw~}m{|w~}\\{|n~|Zw~}x{}q~}W{}q~}|y{|w~|Zw~}Q{|}l~}P{|y}s~X{}q~}x{}w~|" + "X{}u~}X{|u~o{}v~|b{}w~}kv~}X{}w~}V{}d~Uv~Lw~|M{|w~| n{|}q~}u{|}w~bv~{}o~}|X{|r~|R{|}p~}|U{}l~}|^w~}m{|w~}W{}w~" + "}Xw}|i{|w}b{|w~|{|q~|y{|t~f{|q~|v{|q~|^{|l~}[{|w~}os~]{|}o~}|[w~}x{}q~}W{|}p~}|M{|}v~}W{|p~|`{|X~|e{}c~}_{}w~}V" + "k~v{}l~|^{|v~Y{}w~}hv~|Z{|v~R{|m~}| y{}w~ rx~| s{|x~} sv~}P{|}n~}|`{}b~}#{|w~}Lw~|Ty|pv~|\"y|}u~}y| 9y|}u~}y| " + "R{|Z~} ${|w~|{|q~|y{|t~Xx~}w{|x~} y}| q{}x~}aw}j{|w~kk~l{}x~}aw}gv~}U{|v~|d{|v~|l{|v~|d{|v~|l{|v~|d{|v~|l{|v~|" + "d{|v~|l{|v~|d{|v~|l{|v}bv}|t{}w~}j{|b~c{|}m~}|_{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|m~x}y|Z{}w~|k{" + "|t~_{|m~}|X{|m~}|X{|m~}|X{|m~}|X{|m~}|.w~}v{|}n~}|X{|}m~|X{|}m~|X{|}m~|X{|}m~|S{|v~|V{}w~}Mv|wy|}u~y}|Z{}p~}x{}" + "w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|g{}o~|r{|l~}|a{}m~}Y{|l~}|Y{|l~}|Y{|l~}|Y{|l~}|U" + "v~Lv~Lv~Lv~O{|y}v~y}|Xw~}m{|w~}\\{|n~|V{|n~|V{|n~|V{|n~|V{|n~|(w~|{|n~|V{}q~}x{}w~|\\{}q~}x{}w~|\\{}q~}x{}w~|\\" + "{}q~}x{}w~|W{}w~}Vw~}x{}q~}R{}w~} B{|t}|P{|t}|P{|t}|P{|t}|P{|t}|Nw~} 3{|~} ;f| '{|y}w~}y| 8{|y~|X{|x~}" + "h{|}w~}|ay|y}w~y}| rw~}N{}w~ ?{|w~| D{}w~I{|y}w~y}|%b|\\{|x}u~y}|!y|y}u~y}y|O{|y}w~y}| {{y|}u~y}|Vy|y}v~}y| u{|" + "w~| B{|v~| 1{|y}u~y}| o{|x}u~y}y| Fv~| 7y|y}v~y}| {{y|y}q~|#y|y}u~y}y| {{|y}v~y}y| a{|w~}C{}x~}O{|w~| oy}" + "v~}|vv|!{|}t~y}|!{|y}t~y}|Sv|Av~\"v|Lv~ Rv|mv|mv|hv|lv|Z{|y}u~}|Xw~}v{|}w~y}|T{|}w~y}|w{|w~|Zv|Ny|y}u~y}| {{|y}" + "w~}|uw|W{|u}|Wv}|o{|v}av|ju|Xv~| sv~Lw~|M{}w~| ly|}v~}|Uv~yy|}v~y}|S{|y}~y}|N{|y}v~y}|Qy|y}v~x}|[v|m{|w~}W{|w~" + "|#{|w~|x{|}w~}|v{|}y~y}c{|y}x~y}ry}x~y}|Z{|y}s~}y|G{}w~}|Zy|v~}|Ww~}v{|}w~y}|T{|y}v~y}| x{|y}w~}| Ry|y}v~y}|" + " Zy| rv~}M{|y}u~}|]`| Iw~|T{|y~}|u{|u~ 5{|w~|x{|}w~}|v{|}x~}Wx~}w{|x~} {}y~} r{|y}|Kw~|L{|y}|Hv~| E" + "{|y}u~y}| qy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|+{|y~}r{|y}v~y}|R{|y}v~y}y|S{|y}v~y}y|S{|y}v~y" + "}y|S{|y}v~y}y| oy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|d{|}v~y}|n{|y}u~y}y|\\{|}t~y}|U{|y}" + "t~y}|T{|y}t~y}|T{|y}t~y}|T{|y}t~y}|Rv|Lv|Lv|Lv|!v|lv|Z{|y}u~}|R{|y}u~}|R{|y}u~}|R{|y}u~}|R{|y}u~}|'{}x~|w{|y}u~" + "}|S{|y}w~}|uw|Z{|y}w~}|uw|Z{|y}w~}|uw|Z{|y}w~}|uw|Vv~|Vw~}v{|}w~y}|Qv~| Mw~| K{|y~| e{|w~Nw~" + "| ?{}w~ Cw~} .{}w~ @{|v~|d{}| Kv~| !u~| J{|w~}C{|w~O{|w~| 9w~} Iv~ bw~}9{|w~| X{|v~ rv" + "~Lw~|M{}w~| w~| D{|w~| .w~| ?{|v~}g{|x~| M{|v~ {|u~| K{|w~}Bw~|P{|w~| :{}w~} Iw~} bw~}9{" + "|w~| X{}w~| r{}w~|Mw~|Mv~ ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~|T{|l~| 4{|w~" + "|Ax~}w{|x~} {{}y~} /v~| ?x~| f{|x~ M{} %{}w~|Uw~}D{}w~| Lw~| K" + "{|y~| d{|w~Pw~| ?{|w~ C{}w~ .{|w~ ={|u~}|l{|u~| N{}v~ {{|u~| L{|q~}H{}x~}V{}q~| :v~| Iw~}" + " bw~}9{|w~| Xv~ q{}w~}Mw~|N{|v~ ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~|T{|}o~}| " + " 3{|w~|Ax~}w{|x~} {{|x~| 0v~}m{} N{|x~ e{}y~} Rv~Tw~}Dv~ S{}x~x{|w~| " + " K{|y~| c{}x~}R{}x~} >{|x~| Cw~} .{|x~| ;{}t~}|sy|}t~| N{|v~} y{|u~| M{|q~}H{|w~V" + "{}q~| ;{}v~ I{|w~} bw~}9{|w~| Y{}w~} q{|v~}|Ow~|P{|}v~} ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} " + " )v~}Iy~} gw~|Q{|y}v~y}| 1{|w~|Ax~}w{|x~} yx~| 0{}v~|p{|~} N{|x~| f{|x~ " + " S{}w~}Tw~}E{}w~} S{}x~|y{|w~ J{|y~| bw~|Sw~| >{}y~} K{}y~} 9{|p~x}q~}| N{|u~" + "| x{|u~ M{|q~} y{}q~| K{|}|p{|u~| I{}w~| bw~}9{|w~| Z{|v~ o{}q~}Tw~|U{|p~ :v~ S{|w~}W{|w~|#{|" + "w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~| W{|w~|Aw|vx| y{|x~} 0{|u~|s{}x~} N{|x~| " + " f{|x~| U{|v~Sw~}F{|v~ R{|x~}y{}w~ J{|y~| b{|x}|T{|x}| w{}g~}| Q" + "x|y}u~} v{|u~ N{|p} yp}| K{|x~}y|wy|}u~} J{|}v~ aw~}9{|w~| \\{|}v~} nq~}Tw~|U{|q~| :v~ S{|w~}" + "W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~| W{|w~| :{|}w|}w~| /t~y}x|y}v~} U{|}|x{|w~| " + " f{}x~| W{|}v~}Sw~}H{|}v~} Qq~| J{|y} *{|}l~}| O{}q" + "~ tt| `{|i~} Lr~| aw~}9{|w~| `{}q~ l{}s~}Tw~|U{|s~}| 9v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~" + "} )v~}Iy~} gw~| W{|w~| :{|q~ .{|i~} U{|q~ ly}w|}w~| [{}q~Rw~}" + "L{}q~ P{}r~ M{|y}u~y}y| L{}r~| R{|j~} Ks~} `w~}9{|w~| " + " `{}r~| jy|v}|Tw~|U{|u}| 6v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy}| gw~| W{|w~| :{|r~| " + " -{|k~}| U{|r~} l{}r~} Z{}r~|Rw~}L{}r~| O{}t~ " + " k{}t~} -{|`}| `{|}m~}| Jt~} _w~}9{|w~| `{}s~| :w~| cv~ S{|w~}W{|w~|#{|w~| j{}w~ s{}" + "w~Uw~} )v~} d{|w~| 9y}w~y} ){}o~}| S{|}u~}| k{}r~ Y{}s~|Qw~" + "}L{}s~| M{}w~} j{}w~}| +{}`~} ]{|x}v~y}| Gw~y} ]w~}9{|w~" + "| `{}v~}| 8w~| cv~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} g{|w~| 8{|}v~y}| Ly| " + " g{|y}w~}| X{}v~}|Ow~}L{}v~}| Iy| " + "l{}`~} Ww~| " + " L{}`~} Ww}| " + " r{" }; + + // Define a 104x128 binary font (huge sans). + static const char *const data_font_huge[] = { + " " + " " + " " + " " + " " + " " + " " + " " + " FY AY " + "'Z ;W @Y @Y 'Z Y @Y (Z :Y ?Y (Z 0Y ?Y (Z >X " + " " + " " + " " + " " + " )X AX '\\ )XAV 7YDY -] BY BY '[ +YEY 2X AY (\\ -YDY 'XAU 3Y AY (\\ )XAV 8YD" + "Y LY AY (\\ ,YEY #Y " + " " + " " + " " + " (X CX '^ +[CU 6ZEY .` C" + "X CY '] -ZEZ 2X CY (^ .ZEZ )[CU 2Y CY (] *[CU 7ZEZ LY CY (] -ZEZ %Y " + " " + " " + " " + " " + " 'Y EY '^ ,^FV 6ZEY /b CX DX '_ .ZEZ 2Y DX '_ /ZEZ +_FV 1X CX (_ ,^FV 7ZEZ " + " KX CX (_ .ZEZ &Y " + " " + " " + " " + " %Y GY '` .aHV 6ZEY 1e DY FX" + " 'a /ZEZ 1Y FX '` /ZEZ +aHV 0X EX '` .aHV 7ZEZ JX EX (a /ZEZ &X " + " " + " " + " " + " " + " #X GX 'XNX 0dKW 6ZEY 1f DY HX &WMX 0ZEZ 0X GX 'XMW 0ZEZ ,dLX /X GX 'WMX 0dLX 7ZEZ" + " IX GX 'WMX 0ZEZ 'X :T " + " " + " " + " " + " ;X IX 'XLX 1o 5ZEY 2ZLY " + " CX IX &WKW 0ZEZ /X HX (XLX 1ZEZ ,o .Y HX (WKX 1o 6ZEZ IY IY (WKW 0ZEZ (X X MX &WH" + "W 3VHa 4ZEY 3WDW CX LX 'WGW 2ZEZ -X LX 'WHW 2ZEZ -VHa +X KX (XHW 3VHa 5ZEZ GX KX (WGW 2ZEZ )X " + " ?b " + " " + " " + " " + " ?W MW &WFW 4VF^ 3ZEY 4WBV BW MX 'WEW 3ZEZ ,W M" + "X 'WFW 3ZEZ -VF^ )X MX 'WFW 4VF^ 4ZEZ FX MX 'WFW 3ZEZ *X ?d " + " " + " " + " " + " " + " ?W X 'WDW 5UC[ 2ZEY 4VAV AW X &WDW 4ZEZ +W NW 'WDW 4ZEZ -UC[ 'W MW 'WDW 5UC[ 3ZEZ " + "EW MW 'WDW 4ZEZ +X ?f " + " " + " " + " " + " @X \"X 'WBW 6UAW 0ZEY 4V@V B" + "X !W &WBV 4ZEZ +X !W 'WBW 5ZEZ .VAW $W W 'WBW 6UAW 1ZEZ DW W 'WBV 4ZEZ +W >f " + " " + " " + " " + " " + " ?X #W 'W@W U?V AX #W &W@V NX #W &V@W 9W \"W 'W@V .W " + "\"W 'W@V !W >XHX " + " 3Y " + " " + " " + " 6W $W &V>V U?V @W $W &W>V " + " NW $X 'V>V 8W $X (W>V /X $W 'W>V #W >XFX " + " 5Z " + " " + " ,Z " + " GZ " + " #U?V NY 7Z ,X CVCW MY " + " 7Z ,X $Z 7Z ,X >Z 6Y ,X 4Z 7Y +W 7Y @Z " + " " + " +Z " + " " + " HY \"U?V " + " MY 8Y ,Y CVBV LY 9Z ,Y #Z 9Z ,Z >Z 8Y ,Y 3Y 8Z ,Y 9Y " + " ?Z " + " *Y " + " " + " IY !U?V " + " LY :Y ,[ $R>U ,V@V MZ :Y +Z #Y 9Y +Z ?R" + ">U 8Y 9Y +Z %S?U HY :Z ,[ ;Y ?[ " + " " + " )Y " + " 8U " + " 9Y V@U JY Y @Y /X 0Y K` .X " + " ^ =ZEY @Y " + " NVAV

Y E^ /X 0_ %f 1] 'c " + " @ZEZ AY MV" + "CW X *^ +]DU 7ZEZ 5U>U JY ?Y *^ -YEZ 4Y " + " ?Y *^ .ZEZ 5[ ]DU 5Y >Y +^ ,]DU 6ZEZ Y ?Y +_ .ZEZ \"Y Z G[ G\\ @e !f JX !Y " + "LY %d :Y Y Ha /X 0b *j L] D_ " + " +g A[ LY 8Z -ZEZ \"Y 1o )V FX NZ FY " + "%Y ,X NX*Z NW 3WEW H\\ #[ !Z \"[ \"[ \"[ G[7T 8g 0Y " + "@Y +_ ,_FV 7ZEZ 5U>U IY @Y +` .YEZ 3X ?X *` /ZEZ 4[:P 8_FV 4X ?Y +` ._EU 6ZEZ NX @Y *_ .ZEZ #Y ;Y" + " FYEZ ;] GU W ,X " + " FV a \"d -g >d (d +b %b 4f Bg Ie \"e \"h " + " Ge !f IX \"Y LY &e :Y Y Jc /X 0c " + " -n $g I` .j >a ;e HU .U +b Ac 2ZEZ 'b " + " 5o -] Na (c KY .Y #_ 8Y!W'Y\"X.c$X 3XGX Mf -e +d " + ",e ,e ,e \"e=V ;k 1Y BY +XNW .aGV 7ZEZ 5V@V HX AY +XNW .YEZ 3Y AY *WNW /ZEZ 4\\>T 9`GV 3" + "X AY +XNW .`GV 6ZEZ NY AX *XNW /ZEZ $Y :Y FYEZ <_ IU (Q LZ 4Z2Z 1Q " + " &g %Z +XCX MT Y Kd /X 0e 0p " + " (m Lb 1m ,\\ 5~S E~R Ah 'Z :~]+[;Z;Z Ik LW DX DW /i ?Y(Y 4h 5ZEZ" + " ,\\ ,h 7\\ -o .` $f -h NY No %_ %c @_\"X-_\"W0h&W .\\ $\\ \"\\ #\\ #\\ )g 5~a Lm D~S I~S " + "H~R H~R 6Z !Z !Z \"Z :r 8^,Y Bk 2k 2k 2k 2k (kAX+Z(Z#Z(Z$Z(Z$Y'Y&[%[ MZ Im 1X CY *WMX /bHV 7ZEZ 5V@V G" + "X CY *WLW /YEZ 2Y CY *WLW 0ZEZ 3[AW :bHV 3Y BX *WLW 0bHV 6ZEZ MY CX *XMX 0ZEZ $X 9Y FYEZ " + " =a M~i 7U (Q N_ 9_8_ 3R )k 'Z +XCX +X@X 4T >e,X Cl &X IX *X GV " + " GX 5i 0d 2p ;u !^ ?y 2o F~S @n 4j /l N\\ 8x .r Nx 7~R E} >t KZ(Z :Z \"Z 4Z-] KZ 2_'_(^-Z" + " Ep =t 5o Au 1u N~d'Z(Z)Z MZY " + " Le /X 0e 1r +r c 3o -\\ 5~S E~R Dn *Z :~]+[;Z;Z Ko " + " Y EX EY 2m @Y)Y 6l 7ZEZ 0e 2k >e 1o 0c 'j /i X !r (b 'g Eb\"W0c#X0i(W -" + "\\ $] #\\ $] #\\ (f 6~b r F~S I~S H~R H~R 6Z !Z !Z \"Z :w =^,Y Ep 6p 7p 7o 7p ,oDY+Z(Z#Z(Z$Z(Z$Y'Y%Z%Z LZ Kp" + " 1X DX *WKW /WMYJV 6ZEZ 5V@V GY EY *WKX 0YEZ 1Y EY *XKW 1ZEZ 2[EZ :WMZKV 1Y DX *WKX 1WLYKW 6ZEZ L" + "Y EY *WKW 0ZEZ %X 8Y FYEZ >c M~h 7T (S !a Y >X 8f /X 0f 3t -s c " + " 4q /^ 6~S E~R Fr ,Z :~]+[;Z;Z Ms #[ FX F[ 4n @Y*Y 6m 7ZEZ 3k 5l Bk 4o 1f )k 0k #" + "X #u (b (i Fb#X0c#W/k+X .^ %] $^ %] $^ (d 5~b\"v H~S I~S H~R H~R 6Z !Z !Z \"Z :{ A_-Y Gt :t ;t ;s ;t " + " 0sGY*Z(Z#Z(Z$Z(Z$Y'Y$Z'[ LZ Ls 2X FX *WIW 1WJc 6ZEZ 4VBV EY FX *XJW 0YEZ 0X EX )WJW 1ZEZ 1[I^ x %_ ?y 5r F~S Ct :p" + " 6s /e *^ 9| 6z#~ =~R E} B}!Z(Z :Z \"Z 4Z/\\ HZ 2`)`(_.Z Iw @y >w Ez 9z!~d'Z(Z)[ Z;Z0]/Z4Z,Z$[(Z%~^ " + "@e 2X Gf +a MX %Y LY *i :Y Y >Y 9f /X 0g 5v " + " 0u d 6_K_ 0^ 6~S E~R Gu .Z :~]+[;Z;Z w &] GX G] 6U &o ?Y+Y 7X )n 7ZEZ " + "6p 7m Eo 6o 2h *l 1l %X #v (b )k Gb$X/c$X/l,W -^ &_ %^ &_ %^ 'b 4~b$z J~S I~S H~R H~R 6Z !Z " + "!Z \"Z :~ D_-Y Hw =v >w >w >w 4wIX)Z(Z#Z(Z$Z(Z$Y'Y$[)[ KZ Mt 1X HX )WHW 2VHb 6ZEZ 4WDW DX GX )WHW 1YE" + "Z /X GX )WHW 2ZEZ 0[M` ;VHb /X GY *WHW 3VHb 5ZEZ JX GX )WHW 2ZEZ 'Y 7Y FYEZ ?e M~f " + " 7U )U %g Bh@g :W .~T 't +Z +XCX ,X@X 3T Ak1X Er (X JX 'X IV HX 8q" + " =m 7y ?y '` ?y 6s F~S Dv Y >Y " + " :] %X &] 5]C\\ 1v Nc 7\\D\\ 1_ 6~S E~R Iy 0Z :~]+[;Z;Z!y (_ H" + "X H_ 7U 'p ?Y,Y 6X *o 7ZEZ 8t 9YH] Ht 9o 3i *XG[ 1VE[ &Y %x (b *[I[ Hb$W.c%X.VE[-X " + " ._ &_ %_ '_ %_ '` 4~c%} L~S I~S H~R H~R 6Z !Z !Z \"Z :~Q F`.Y Jz @z Az Ay Az 7zKX(Z(Z#Z(Z$Z(Z$Y'Y#[*Z JZ Na" + "J_ 2X IX )WGW 2VG` 5ZEZ 4XFX CX IX )WFW 2YEZ .X IX )WFW 3ZEZ /j 8VG` -X HX *WFW 4VG` 4ZEZ IX IX " + ")WGW 2ZEZ 'X 6Y FYEZ ?XKX M~f 7T )W 'i DiAi ;X 1~V (w -Z " + "+XCX ,X@X 3T AZI[2W Es (X KX &X IV HX 9s >m 7z @z )a ?y 7t F~R Dx >t 9v 8s 2` :~P <~Q&~S" + " A~R E} E~T$Z(Z :Z \"Z 4Z2] FZ 2a+a(`/Z K| C{ C} H| =|!~d'Z(Z(Z!Z9Z1^1Z2[0[!Z+[$~^ @X $X ;Y -e MX 'Y " + "LY +[ +Y Y >Y :[ #X #Z 6\\?[ 2v F\\ " + " 8Z@[ 2` 7~S E~R J{ 1Z :~]+[;Z;Z#} +` HX Ia 8U (q >Y-Y 6X +p 7ZEZ 9bMb ;U@Y JbMb :" + "n 3ZIZ +T@Y 2R>Y 'X %y (XLV +ZEZ IXMW%X.YMW%W-R>Y.W -` '_ &` '_ &` '` 4~c'~R N~S I~S H~R H~R 6Z !Z " + "!Z \"Z :~S Ha/Y K| B| C| D} D| 9|MX'Z(Z#Z(Z$Z(Z$Y'Y\"Z+[ JZ N]B\\ 2X JX *WEW 3UE_ 5ZEZ 3YJY AX JW )WE" + "W 2YEZ -X KX (WFW 3ZEZ .f 5UE_ ,X JX )WFW 4VF_ 4ZEZ HX KX )WEW 3ZEZ (X 5Y FYEZ @YJW M~" + "e 7U *X (j EkCk =Y 3~X )x -Z +XCX ,W?X 3T BYEY3X Ft (X KX %X JV " + " IX 9u ?m 7{ A{ *a ?y 8u F~R Ez @v :v :w 4` :~Q >~S'~U C~R E} G~V$Z(Z :Z \"Z 4Z3] EZ 2a+a(a0Z M~P D" + "| E~P I} ?}!~d'Z(Z'Z\"Z9Z1^1Z1Z0Z [,Z#~^ @X $X ;Y .g MW 'Y LY +Y )Y Y " + " >Y :Z \"X \"Z 7[=Z 3aE[ E[ 9Z>[ 3` 7~S E~R L~ 2Z :~]+[;Z;Z$" + "~P -b IX Jc 9U )r >Y.Y 5X ,]DX 7ZEZ ;\\>\\ \\ 0XDX ,R=Y MX (X %hEW (SG" + "V ,YAY JSHW%W-SGW&X GX/W ,` (a '` (a '` (a 5~d(~S N~S I~S H~R H~R 6Z !Z !Z \"Z :~T Ia/Y L~P F~P F~P F~P F~P" + " <~X&Z(Z#Z(Z$Z(Z$Y'Y\"[-[ IZ \\>Z 1X LX )VCW 4UD] 4ZEZ 2f ?X LX )WDW 3YEZ ,W KX )WDW 4ZEZ -b 2UD] *W" + " KX )WDW 5UD] 3ZEZ GW LX (VCW 4ZEZ )X 4Y FYEZ @XIX M~d 7U *Y *l GmDl ?[ " + " 6~Z *`C\\ -Z +XCX ,W?W 2T CYCY5X E]CZ (X LX $X JV IX 9]E^ @m 7aGb B^Ec ,b ?y " + "9aF[ F~R E_C_ B_E^ ;]E_ ={ 7b ;~R @cBb'~V D~R E} HeBc$Z(Z :Z \"Z 4Z4] DZ 2b-b(a0Z NbCb E} GbCb J~ Aa" + "B_!~d'Z(Z'Z#[9Z2_1Z0Z2[ N[.Z\"~^ @X $X ;Y /i MW (Y LY ,Y (Y Y >Y " + " :Y !X !Y 8[;Z 1\\ 0\\:U D[ ;ZbCh%Z(Z" + "#Z(Z$Z(Z$Y'Y![.Z HZ Z;Z 1X NX )WBV 5VBZ $e >W MX )WBW !X MX )WBW #` /UBZ (W MX )WBW 6UBZ " + " 9X MW (WCW MX 3Y GXHW M~d 8U *[ +m HnFn A] 9~\\ +^=Y" + " -Z +XCX -X@X 2U DXAX5W E\\=V (X LX #X .R@V?Q ,X :\\A\\ @m 7\\>_ CY<_ -c ?y :^=V F~Q E]>^ D]@] " + " j E~R E| Ha8^$Z(Z :Z \"Z 4Z5] CZ 2b-b(b1Z `<_ FZ@d I`=` K[@d C_:Z ~b&Z(Z'Z#Z8Z2`" + "2Z0[4[ LZ/[\"~^ @X #X Y >Y ;Z " + "!X !Y 8Z9Y 6d 4[5R CZ ;Y:Z 5b 8~R D~Q MbAb 8` =~]+[;Z;Z&`=` 1f KX Lg " + " ;U *\\=T =Y0Y 4X ,Z;R 5Z3Y &W !Y3Y 3W@W EW LX *W %jEW KV -X=X @W'X W'X EX1W ,b " + "*b (b )b )b )b 7ZH~R)a:] N~R H~R G~R H~R 6Z !Z !Z \"Z :Z>j Lb0Y N_<` J`<_ J`=` J`=` J`=` @`=e%Z(Z#Z(Z$Z(Z$Y'Y" + " Z/[ HZ !Z9Y 0W X )WAW 6VAW \"d Y >Y ;Y X !Y " + " 8Y8Y 6f 6Z2P BY j BZ(Z+[;Z;Z'_9_ 3h LX Mi <" + "U *[:R V EW KW +W %kEW KV .X;W @W'W NW(X CW2X -c *c )b " + "*c )c +c 7ZHZ 2_5[ NZ !Z Z !Z >Z !Z !Z \"Z :Z7d Mc1Y ^8_ K^8^ L_8^ L_9_ L^8_ B_9b$Z(Z#Z(Z$Z(Z$Y'Y [1[ GZ !Z" + "8Y 0W !W (V?W I` :X !W (V?W X \"X (W@W *d EX !W (W@W 0X \"X (V?W !W 1Y #d ," + "e +d +d ,e #XHW LZ#Z 7U +] -o KqHp C_ X #X " + " Y >Y ;Y X X 9Z7X 6g 7Y" + " #Z =Y8Z 7d 7[ Z )_7_ Bp EZ(Z+[;Z;Z(^5^ 5j MX Nk =U +[7P Z !Z !Z \"Z :Z3a Nc1Y!^5] L]4] N^5^ N^5^ N^5] C^5_#Z(Z#Z(Z$Z(Z$Y'Y N[2Z FZ \"Z7Y /W #W (W>V H^" + " 8X #W (W>V NW \"W (W>W .h EW \"X )W>W 0W #X (V=V \"W 0Y &j 1i 0j 1j 1i &X ` .\\5U -Z +XCX -W?W =r'X>W8X EZ ;X NY !X 1XDVDX 2X " + " &X ;[;[ BWDZ 7T2\\ \"\\ 1XMZ ?Y L\\ 2Z E[7[ G\\9[ >S5[ F`7` ?YNY Y >Y ;Y X Y :Y6Y 7i 9Y \"Y " + " >Y6Y 7YNY 6[ !Z *^3] Dt GZ(Z+[;Z;Z)]2] 6l NX m >U +Z !Y4Z 3X -Y NW(W (W " + " &X)X 8VZ !Z !Z \"Z :Z1` d2Y\"]2] N]2] ]2]!^2]!]2] E]2]\"Z(Z#Z(Z$Z(Z$Y'Y MZ3[ FZ \"Z6X .V $W 'VR4[ G^1^ AZNY Y >Y ;Y X Y :Y6Y 7j :Y \"Y " + " >Y6Z 9YMY 5[ \"Z *]1] Hy IZ(Z+[;Z;Z)\\/\\ 8n X !o ?U ,[ Y5Y 2X -Y W&W )W 'W%W 9V" + "Z " + "!Z !Z \"Z :Z/_!d2Y#]0]!]0]\"]0\\!\\/\\\"]0] F\\0]#Z(Z#Z(Z$Z(Z$Y'Y M[5[ EZ \"Y5X +P " + " %_K[ CY *r 9q 8r 9r 9q *X ;Z%Z >Q JT ,b 0q MsKs Ge " + "C^ *[0R -Z +XCX .X@X @v)X=X:W CY :X Y NX 1[HVH[ 1X 'X ;Z7Z 0Z 7P,[ ![ 3XLZ ?Y M[" + " 1Z EZ4[ I[5Z ?P1Z I^-] BYLY =Z1[ H\\(T'Z-^ JZ MZ *\\$S$Z(Z :Z \"Z 4Z:] >Z 2YMX1XMY(YNZ4Z$].\\ JZ5" + "\\!\\-\\ Z4[ GZ ;Y 9Z(Z%Z'Z4Z5XNX5Z*Z:[ F[6Z [ ;X \"X =Y 5\\C[ #Y LY -Y 'Y 8X >Y " + " >Y ;Y X Y :Y6Y 7k ;Y \"Z @Z5Y 9YLY 5[ #Z +\\.] J| KZ" + "(Z+[;Z;Z*\\-\\ :p !X \"q @U ,Z NY6Y 1X -X W#V *W (W#W :U;V +X DW LW )mEW KV" + " /X9X BW*X LW*X BW3W +YLY -YMY ,YLY -YMY ,YLY -YMZ ;ZFZ 5\\'S NZ !Z Z !Z >Z !Z !Z \"Z :Z-^\"e3Y#\\.]#].\\" + "#\\-\\#\\-\\#\\-\\ H\\.]$Z(Z#Z(Z$Z(Z$Y'Y L[6Z DZ \"Y5Y /[G[ " + " DY +u =u S LU ,c 1q MtLt Hf E] )[.Q " + " -Z +XCX .W?X Bx)X=X;X DZ :X X MY 0ZIVIZ /X 'X ;Z7[ 1Z AZ ![ 4XKZ ?Y MZ 0Z EZ3Z I[5Z " + "Z J])\\ CYLY =Z1[ I\\%R'Z+] KZ MZ +\\\"R$Z(Z :Z \"Z 4Z;] =Z 2YMX1XMY(YNZ4Z$\\,\\ KZ4[\"\\+[ Z4\\ I[ ;Y 9Z(Z$Z" + "(Z4Z5WLW5Z*[<[ DZ7[ !\\ ;X \"X =Y 6\\A[ $Y LY -Y 'Y 8X >Y >Y " + " ;Y X Y :Y6Y 7l Z !Z !Z \"Z :Z,^#YNZ3Y$\\,\\#\\,\\$\\,\\%\\+\\%\\,\\ MP" + " NP N\\-]$Z(Z#Z(Z$Z(Z$Y'Y KZ7[ Dq :Z4X /XC[ EY " + " -x @x >x ?x @x -X :Z'Z ?U MU -e 2q MtLt Ig E[ 'Z,P -Z +XCX .W?W By)" + "XZ0Z" + " J\\#Q'Z*\\ KZ MZ +[ Q$Z(Z :Z \"Z 4Z<] Y 7[>[ %Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y" + "5Y 7UH_ Z !Z !Z \"Z :Z+]#YMZ4Y%\\*\\%\\*\\&\\*[%[)[%[*\\ R!R [-_%Z(Z#Z" + "(Z$Z(Z$Y'Y K[9[ Ct =Y3X /U@[ \"Q EY .z B{ " + "B{ Az B{ /X :Z'Y >V U -g 4r NvNu Ji *\\ 5X.X 6\\ 7Z1Z M[ '[ 8Z +XCX /X@X C`MTL_)W;" + "WZ0Z " + "J[ 'Z)\\ LZ MZ ,\\ \"Z(Z :Z \"Z 4Z=] ;Z 2YLX3XLY(YMZ5Z%[([ LZ3[$\\)\\\"Z3[ IZ :Y 9Z(Z$Z)Z3Z6XLX6Z(Z>[ B[:Z !" + "\\ 9X !X >Y 8[<[ &Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y5Y " + "7RB] =\\ $Z BY2Y ;YJY 3[ &Z -[(\\!~U Z(Z+[;Z;Z,\\)\\ ?\\MXL[ $X %\\LXM\\ CU" + " ,Y *Q\"R DY9Y 0X -Y #V=_?V Cm *V LV Z !Z !Z \"Z :Z*]$YMZ4Y%[([%[(['\\)\\'\\)\\'\\)[!T#T\"\\-`&Z(Z#Z(" + "Z$Z(Z$Y'Y J[:Z Bw @Y6[ .Q<[ #S GY /`Da E`C" + "` DaD` C`Da E`C` 0X 9Y(Z ?X !U .h 4r NvNu Kk .c 9X.X 7^ 7Y1Y M[ &Z 7Z +XCX /X@X C\\" + "ITFY)W;W=X BY 9X !X KY +YNVNZ *X (X ;Z4Z 2Z @Z !Z 6YJZ ?Y Z /Z DY2Z JZ1Y ,T T MZ N[ NZ HZJ" + "Y >Z0Z K[ &Z(\\ MZ MZ ,[ !Z(Z :Z \"Z 4Z>] :Z 2YLX3XLY(YLZ6Z&['\\ MZ3[$['[\"Z2Z IZ :Y 9Z(Z#Z*Z2Z7XLX7Z'[@[ @Z;" + "[ ![ 8X !X >Y 9[:[ 'Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y" + "5Y %\\ =] %Y BY2Z =ZJY 3\\ 'Z .\\'[#cLZLb!Z(Z+[;Z;Z,['[ @\\LXK[ %X &\\KXL\\ " + " DU -Z +S$T EY:Y /X -Z %V?fBU Eo +VEg=V =VZ !Z !Z \"Z :Z)\\$YLZ5Y&\\'['['\\(['['['['['[#V%V#[-a&Z(Z#Z(Z$" + "Z(Z$Y'Y IZ;Z Ay BY9^ G[ %U HY 0]<^ G^=^ F" + "^<] E]<^ G^=^ 1X 9Z)Z @Z \"U .i 5r NvNu Lm 2h ;X.X 7^ 7Y1Y N[ &[ 7Z +XCX /W?X D[GTC" + "V)W;W=W AZ :X \"Y KY *j (X (X ZY .Y3Y 3Z '\\ MZ )Z ;Z 2^ +Y ;Y " + "X Y 6Y /Y5Y $[ =` G^ !Z IZ M\\ #Y2Z =YIZ 3\\ (Z .[%[%aIZI`\"Z(Z+[;Z;Z-[%[ B\\KXJ[" + " &X '\\JXK\\ H\\ 1Z ,U&V EY;Y /X ,Z 'V@jDV Gp +UDj?V >VZ !Z !Z \"Z :Z(\\%YLZ5Y&[&['[&[)\\&[)[%[)" + "[&[$X'X%[-b&Z(Z#Z(Z$Z(Z$Y'Y I[=[ Az CY;` 5\\ $] $\\ \"\\ #\\ $] 8\\/[ 3\\ '\\ #\\ \"[ \"[ \"[ &Z &[ ![" + " #\\ #[ ![ G[@W IYBZ J]8] I\\7\\ H]8] I]8] I\\7\\ 2X 8Y*Z @Z \"U .k 5q N~o Mm 4l =X" + ".X 7^ 7Z3Z NZ %Z 6Z +XCX /W?W D[FT@S)W;W>X AZ :X \"Y JX (f &X )X ;Z3Z 2Z @Z !Z 7" + "XHZ ?Y !Z /Z CY1Y JZ1Z 2Y Y $Z Z HY JYHY ?Z/Y L[ %Z'\\ NZ MZ -[ Z(Z :Z \"Z 4Z@\\ 7Z 2YKX5XKY(YKZ7Z'[" + "$[ NZ2Z%[%[#Z2[ JZ :Y 9Z(Z#[,Z1Z8XJW7Z%ZB[ >[>Z !\\ 7X X ?Y ;[6[ (e 7YE` (e 3aEY 8c 2r 5`DX GYEa (X NX " + "0X1Z 8Y FXD`9` YD` -c 9XD` /aEX :XD] 6g 7t BX0Y LY)Y+X6Z6X)Z/Z NX)Y I} 2Y X Y 9_>W KY5Y #[ =c h >XD` " + "AT#X 5Y 6X0X LY'Y ?RCW ?~Y!X?X?X ;d 'r!~W KZ1Y =YHY 2\\ )Z /[$[%_GZG_#Z(Z+[;Z;Z-[%[ C\\JXI[ 'X (\\IXJ\\ " + " (Y d 5Z -W(X FYV=W +X HX )^ ,Y1Y HnEW KV 0X7W BW-W HW.X M^/X )" + "Y +YHY 2YHZ 1YHY 2ZHY 1YHY 2ZHY ?ZDZ 9[ LZ !Z Z !Z >Z !Z !Z \"Z :Z'[%YKZ6Y'\\%[)[$[*[%[)[%[)[%[%Y)Z&[.d'Z(Z#" + "Z(Z$Z(Z$Y'Y H[>Z @{ DY=b ;f -f -f ,e -f -f Ae7c ;e /b )c *c *c 'Y NX NX X E[ >XD` -c )c *b *c )c '\\ &bDX L" + "X0X GX0X GX0X GX0X KY)X KYE` ?Y*Y 8[4\\ K[3[ J\\4[ I[4\\ K[3[ 3X 8Z+Z AZ !U /m 6q N~o No 6o ?X.X 8_ " + "6Y3Z Z $Z 6Z +XCX 0X@X DZET>Q)W;W>W ?Y :X \"X IY 'b $X )X ;Z2Y 2Z @Z !Z 8YHZ ?Y " + "!Z 0[ CY1Y JZ1Z 5\\ \\ 'Z!Z FY LZHZ @Z/Y L[ %Z&[ NZ MZ .[ NZ(Z :Z \"Z 4ZA\\ 6Z 2YKX6YKY(YKZ7Z'[$[ NZ" + "2Z&[#Z#Z2[ JZ :Y 9Z(Z\"Z,Z1Z8XJX8Z%[D[ ZHY 1\\ *Z /[#['^EZE^$Z(Z+[;Z;Z.[#Z C[IXH[ (X ([HXI[ (" + "Z $k 9Z .Y*Z FY=Y .X ,\\ *UAnCU J^CW -VCmAV ?W>V *X IX (a /Y1Y HnEW KV 0X7W BW.X HW.W La3X " + "(Y ,ZHY 2YGY 2ZHZ 3YGY 1YHZ 3YGY @ZCZ 9[ LZ !Z Z !Z >Z !Z !Z \"Z :Z'\\&YJY6Y'[$[)[$[*[$[+[#[+[$[&[+\\([.e'Z(" + "Z#Z(Z$Z(Z$Y'Y GZ?Z ?| EY>c >l 4l 3l 2l 3l 4l Gl=h @k 5h /h /h /h )Y Y NX Y E[ ?XFd 1g .h /h /h /h )\\ )hHX " + "LY0X HY0X GX0X GX0Y LZ+Y KYGd AY*Y 9[EXD[ M[1[ L[1[ K[1[ M[1[ 4X 8Z+Y A[ !T /n 6q N~o q 8q @X.X 8` 7" + "Y3Y Z $Z 5Z +XCX 0X@X DYDT EW;W?X ?Y :X #Y IY %^ \"X )X k 5}\"~W KY0Z ?YGZ 1[ *Z /Z\"[(]CZD^%Z(Z+[;Z;Z.[#[ CYHXGY 'X 'YGXHY 'Z &o" + " ;Z /[,[ FZ?Y -X +\\ +UBoBU LZ>W -UBnAU >W@W *X JX 'c 1Y1Y HnEW KV /W7W BW.W GW/X Lc5W 'Y ," + "YFY 4ZGY 2YFY 3YGZ 3YFY 3YGZ AZCZ 9Z KZ !Z Z !Z >Z !Z !Z \"Z :Z&[&YJZ7Y'[#[*Z\"Z+[#[+[#[+[#[&[-\\'[/YM[(Z(Z#" + "Z(Z$Z(Z$Y'Y G[A[ ?} FY?] :p 8q 8q 7q 8q 8p LqAl Do 9l 3l 3l 3l +Y Y NX Y #i @XHh 5k 2l 3l 3k 2l +\\ +lKX KY0" + "X HY0X GX0X GX0Y KY,Z KYIh CZ,Z :ZCXC[ [/[ N[.Z MZ.[ [/[ 5X 7Y,Z AZ !U /o 7p M~n s :s AX.X 8` 7Z4Y Y" + " #Z 5Z +XCX 0W?X EYCT EW;W@X >Z ;X #Y HX #Z X *X ;Z1Z 3Z @Z !Z 9XFZ ?Y \"Z /Z " + "BY2Z KZ0[ [/Z 4t =YJj 3q >kJY >o 8r ;kJY GYJk .Y NX 0X5\\ 6Y FY" + "JiBi$YJk 8o ?YJj 9kJX ;YJc Z !Z !Z \"Z :Z&[&YIZ8Y([\"[+[\"[,[\"Z+Z!Z,[\"[%[/\\" + "&Z/YL[(Z(Z#Z(Z$Z(Z$Y'Y F[BZ >Z@d GY@\\ :t ;t t TAU NX;W )P9P =UAWAYAU >XDX )X LX HY 3Y1Y HnEW KV /W7W " + "AP9P 9W0X FW0X ?Y8W &Y -YEZ 5YEY 4ZFZ 5YEY 4ZEY 5YEY BZBZ :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z%['YIZ8Y([!Z+Z![,Z![-" + "[![-[!Z$[1\\&[/XJZ(Z(Z#Z(Z$Z(Z$Y'Y EZCZ =Z;` HYA[ 8u oLX ;YLe ?u VAW?XAU ?ZHY (X MX EX 4Y1Y HnE" + "W KV /W7W AQ:Q :W0W EW1X Z !Z !Z \"Z :Z%['YHZ" + "9Y(Z Z+Z Z-[![-[![-Z [$[3\\%[0XI[)Z(Z#Z(Z$Z(Z$Y'Y E[E[ =Z9^ HYBZ 6v =v >w =w >v =v\"vIt Lt >t ;t ;t ;t /Y Y N" + "X Y *r BXKn qMY GYMp 0Y NX 0X8[ 2Y FYMoIp'YMq ?v BYMp ?qMX ;YMf ?u U@W?XAU >j (X " + " NX CX 5Y1Y HnEW KV /W7W AR;R ;W1X EW1W :XZ " + "!Z !Z \"Z :Z$Z'YHZ9Y)[ [-[ [.[ Z-Z NZ-Z [#[5\\$Z0XH[)Z(Z#Z(Z$Z(Z$Y'Y D[FZ w ?x >x ?w >w#wKv Nu ?v" + " =v =v =v 0Y Y NX Y +s BXLp >u \\ DX.X :c 7Z7Z!Y \"Z 4Z +XCX C~d&XBT DW=XB" + "X :[ >X $Y FY +f &X +X ;Z/Z 4Z AZ !Z ;YDZ ?YFP -Z?Q BZ ?Z5Z JZ/Z 5Z \"[ Gj Ii ;[\"X1Q,W\"YCZ BZ1" + "Z MZ \"Z$[!Z MZ /Z LZ(Z :Z \"Z 4ZH] 0Z 2YHX;XHY(YHZ:Z)Z N[!Z2Z([ NZ%Z2Z I[ ;Y 9Z(Z Z1Z,Z;XGW;Z N[L[ 4[H[ #\\" + " 1X MX AY BZ&Z 8^Ga AYN[H_ " + "YDY *X )b 6UDY%U V9W ,SU@W>W@T =h 'X X AW 5Y1Y HnEW KV /X9X ASZ !Z !Z \"Z :Z$Z'YGZ:Y)[ NZ-[ [.Z N[.Z NZ.[ NZ\"[7\\$[1XFZ)Z(Z#Z(" + "Z$Z(Z$Y'Y CZGZ ;Z6\\ IYCY 4^Ga ?^Ga @_Hb ?^Ga ?^Ga ?^Ga$^GaMaI`!bH\\ @aI` ?aI` ?aI` ?aI` 1Y Y NX Y ,u CXM^Nb" + " @aKa >aJa ?aJa ?aKa =`Ja 1\\ 0`Ic GY0X HY0X GX0X GX0Y IY0Z IYN[H_ FZ0Z X>Y&X#X%YJT9TIY&Y.TJY&X#X 8X 5Y0" + "Z CZ ;P4U 1w 9l J~m#z B[;[ EX.X :d 7Y7Y X )~Q #Z +XCX C~d&XBT DW=XCX 9\\ ?X $Y FY " + "-j (X +X ;Z/Z 4Z AZ \"Z :XCZ ?YM_ 5ZE^ IZ >Y6Z IZ0[ 5Z \"[ Jj Ci ?\\\"X6\\2X#YBY BZ1Z MZ \"Z$[!Z " + "MZ 0[ LZ(Z :Z \"Z 4ZI] /Z 2YHX;XHY(YGZ;Z)Z N[!Z3[([ NZ%Z2Z H[ ^ BcB] >_?W C^CYNY C]A] 4Y /]Bc GYNYD^ 2Y NX 0X;\\ 0Y FYNXC\\KYD](YNYC] A]B^ DcB] C^CYNX ;YNZDQ A\\" + ";V 5Y .Y1Y IY/Y&Y;_;Y\"Z;Z FZ0Y $[ 2Y X Y M];\\ F]E[JX IY9[ LY >ZKf =]=V CYNYC] K`2Z 5^ 9Y1Y!Z\"Z!^JZM^" + " K~Y!Y@X@Y E]C^ CaHl\"~W LY.Z BYBY .\\ 0Z 1Z M[-[>Z>[(Z(Z*Z;Z<[0[ N[$[ W@U =f &X !X @W 5Y1Y HnEW KV /X9X AT=T =W2X DW2W 8W=X $Y .YBY 8ZC" + "Z 7YBY 8ZCZ 7YBY 8ZBY FZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(YGZ:Y)[ NZ-Z MZ.Z N[/[ N[/[ NZ![9\\#[2YFZ)Z(Z#Z(Z" + "$Z(Z$Y'Y C[I[ ;Z5\\ JYCY 4X=^ @X=] @Y=] ?Y>^ @X=^ @X=^%X=l@\\\"_?W A]@\\ @]@\\ @^A\\ @^A\\ 1Y Y NX Y -w DXNY" + "C] A^C^ ?^C^ A^B] @^C^ ?^C^ 2\\ 1^C_ FY0X HY0X GX0X GX0Y IY0Y HcB] FY0Y ;X=X=Y(Y#Y'YJV;VIX&X.VJY(Y#Y 9W 4Z1" + "Z DZ =S4U 2y 9j I~l#{ BZ9Z EX.X :d 7Z8Y!Y *~R #Z +XCX C~d'YBT DX?XBW 7\\ @X $Y FY " + "/ZNVNZ *X ,X :Z/Z 4Z AZ #Z :XBZ ?o 9ZGc MZ =Z8[ HY0\\ 6Z \"[ Li >j C\\\"X8aGVBW$ZBZ CZ2Z LZ \"Z#Z!" + "Z MZ 0[ LZ(Z :Z \"Z 4ZJ] .Z 2YHXY 9Z(Z NZ2Z,Z\\ @^:T C\\?b D\\=\\ 5Y 0\\>a Ga?\\ 2Y NX 0X<\\ /Y Fa@\\MX@[(b@\\ B]?\\ Da?] D\\?a ;b 1Z6" + "S 5Y .Y1Y IZ1Z&Y;_;X![=Z DY1Y #[ 2Y X Y `>` I\\B[KX IY:\\ LY ?ZDa ?\\7R Cb?\\ F[3Y 5_ 9Y1Y\"Z Y!]IYJ] L" + "~Y!Y@X@Y F\\?\\ D^Ai\"~W LY.Z CZBZ .\\ 1Z 1Z LZ.[=Z>[(Z(Z*Z;Z<[0[ N[%\\ XAU V ?W3X CW3X 8X>W #Y /Z" + "BZ 9YAY 8ZBZ 9YAY 8ZBZ 9YAY FZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(YFZ;Y)Z MZ-Z MZ/[ MZ/[ N[/Z M[![;\\\"[3YE[*" + "Z(Z#Z(Z$Z(Z$Y'Y B[JZ :Z4[ JYCX 3U8\\ @U8\\ AV8\\ @U7\\ AU7[ @U8\\%U8h=\\$]9T B\\=\\ B\\=\\ B\\=\\ B\\<[ 2Y Y " + "NX Y .x Da?\\ C]?] A]?] B\\?] B]?] A]?] 3\\ 2]?] FY0X HY0X GX0X GX0Y IZ1Y Ha?] GY1Z ~d W5T 2{ 9i H~k$} DZ7Z FX.X :d 7Z9Z!X )~R #Z 0~d&XBT DX?XCX 6\\ " + " =Y EY 0ZMVMZ +X ,X :Z/Z 4Z B[ %\\ :XBZ ?q ;YHg Z \\ 0Z 6Y.Z CYAZ -\\ 2Z 1Z LZ.[=Z=[)Z(Z*Z;ZW>X@T ;a #X #X =W 6Y1Y GmEW KV .X;X @W@W @W3W BW4X 6W?X #Y /Y@Y :" + "ZAY 8Y@Y 9YAZ 9Y@Y 9YAZ GZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(YFZ;Y)Z M[/[ MZ/[ MZ/Z LZ/Z M[ [=\\!Z3YD[*Z(Z#Z" + "(Z$Z(Z$Y'Y AZKZ 9Z4[ JYDY 3R3[ AR3[ BS3Z @S4[ AS4[ AR3[&R3e:[&]6R C\\:[ D\\:[ D\\:[ D\\:[ 3Y Y NX Y /_B] E_<" + "[ C[;[ B\\<\\ C\\<\\ C[;\\ C\\<\\ 3\\ 3\\<\\ FY0X HY0X GX0X GX0Y HY2Z H`<[ FY2Y ;X~d#Z6U 3} :h G~k%~P EY5Y FX.X ;ZNY 6Y9Z!X *~R \"Z 0~d&YCT CXAXBW 5] " + " >Y EY 2ZKVKZ -X ,X :Z/Z 4Z BZ &] :XAZ ?s =YJk #[ ;[=[ FZ1\\ 6Z \"[ #j L~d Ki J\\!X:hKVAW%Y@Y CZ5\\ L" + "[ \"Z#Z!Z MZ 0Z KZ(Z :Z \"Z 4ZL] ,Z 2YGX=XGY(YEZ=Z*[ M[\"Z4['Z LZ&Z4[ F` BY 9Z(Z MZ4Z*Z=XEW=Z Jd .ZLZ #\\ .X" + " LX BY JQ1[ D_:[ B\\ ([9_ F[7Z 6Y 1[:_ G^9Z 3Y NX 0X>\\ -Y F^;b;Z)_:Z D[:\\ F_:[ G[9^ ;_ /Y EY .Y1Y " + "HY2Z$Y=a=Y NZ@[ BY3Z %[ 0Y X Y \"eCd L[>YLX HY>^ IY AY=] @Z &_:Z DY4Y 5a :Y1Y\"Z Z$\\GYG\\ EY9Y IY@X@Y G" + "Z9[ G\\;[ 0Y 5Y.Z DZ@Y ,\\ 3Z 1Z LZ.ZUDX!T\"XW>X@U :] !X $X Z !Z !Z \"Z :Z#Z(YEZ~d&^7U 4~ 9f E~i%~R GY4Y FX.X ;ZNZ 7Y9Y!X )~R \"Z NW?W BYCT CYBXCX 6_ ?Y EZ 5ZI" + "VIZ /X ,X :Z.Y 4Z C[ )_ :YAZ ?t >YKn %Z 9\\A\\ EZ1\\ 6Z \"[ &j I~d Hi N\\ W:jLVAW&Z@Z DZ8^ KZ !Z#[\"Z " + " MZ 0Z KZ(Z :Z \"Z 4ZM] +Z 2YGY?XFY(YEZ=Z*Z L[\"Z4['Z LZ&Z4[ Fc EY 9Z(Z MZ5Z)Z>XDW=Z Ic .[NZ #\\ -X KX CY " + " )Z D^8[ D\\ '[8^ FZ5Z 7Y 2[8^ G]8Z 3Y NX 0X?[ +Y F]9`9Y)^9Z E[8[ F^8Z GZ8^ ;^ .Y EY .Y1Y GY3Y#Y=WNX=Y M" + "ZAZ AY3Y %[ /Y X Y #gEf N[W>W?U 7W <~d BX ;W 6Y1Y GmEW KV -X=X ?YBY BW4W AW5X 5W@W !Y 0Y?Z ;Y?Y :Z@Z ;Y?Y :Z?Y ;Y" + "?Y HZ?Z <[ IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(YEZY D~P JZ !Z#[\"~Q Dy Z K~] :Z \"Z 4ZN] *Z 2YFX?XF" + "Y(YDZ>Z*Z L[\"Z5\\([ LZ&Z5\\ Eg JY 9Z(Z MZ5Z)Z>XDX>Z Ib ,f $\\ ,X KX CY (Y D]6Z D[ '[7^ GZ4Z 7Y 2Z6] " + "G]7Z 4Y NX 0X@[ *Y F]8^8Z*]7Z FZ6[ G]6Z I[7] ;] -X DY .Y1Y GY3Y#Y=WNX=X L[CZ ?Y4Y &[ .X NX Y $iGh Z:XNX" + " GYHg HY CY8\\ CY $]7Z DY6Y 4b ;Y1Y#Z MZ&[EYE[ FY9Y IY@X@Y HZ7[ I[7[ 2Y 5~V DY>Y +\\ 5Z 2Z KZ/[W>W?U K~d CX ;X " + " 6Y1Y FlEW KV -Y?Y ?ZCZ CW5X AW5W 5XAX !Y 0Y>Y Y Y ;Y?Z JZ>~Q3[ I~Q G~Q F~Q G~Q 5Z !Z !Z " + "\"Z :Z#Z(YDZ=Y*[ LZ/Z L[0Z L[0Z LZ0[ LZ L[C\\ N[5X@Z*Z(Z#Z(Z$Z(Z$Y'Y ?e 7Z3[ KYDY @Y Y !Z Y Y Y 4_4Y)[ %Z3" + "Y GZ3Y FZ4Y FZ4Y 4Y Y NX Y 1[8Z F\\7Z F[7[ EZ6[ G[6[ G[6Z EZ6[ Y D~ IZ !Z#[\"~Q Dy![ K~] :Z \"Z 4h )Z 2YFX@YFY(YDZ>Z*Z KZ\"Z5\\([ LZ&Z6\\ Ck Y 9Z(Z LZ6Z(" + "Z?XDX?Z G` *d #[ +X KX CY 'Y E]6[ F[ &Z5] GY2Y 7Y 3Z4\\ G\\6Z 4Y NX 0XA[ )Y F\\7]6Y*\\5Y G[5Z G\\5Z I" + "Z5\\ ;] -X DY .Y1Y GZ5Z#Y>XMW>Y K[E[ ?Y5Y &[ .Y NX Y $XIZHZIY!Z:XNX GYHf GY DY6[ CY $\\5Y CX6Y 5c ;Y1Y#" + "Z MZ&[EYDZ FY9Y IY@X@Y IZ5Z IZ5Z 2Y 5~V EZ>Y *[ 5Z 2Z KZ/[Z EiKh 6X /XC^ BTDX U\"YA\\ 4ZCZ N~d &U>W?X>T K~d EY :W 5Y1Y EkEW KV ,YAY =ZCZ DW6X @W6" + "X 5W@W 'Z>Y Z =Y=Y ;Y>Z =Z>Y JZ>~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z :Z#[)YDZ=Y*[ LZ/Z KZ0Z L[1[ LZ0[ L" + "Z K[E\\ M[6Y@Z*Z(Z#Z(Z$Z(Z$Y'Y >d 7Z2Z KYDY @Y Y Y NY Y !Y 4^3Z*Z $Z3Z HZ3Z HZ3Z HZ2Y 5Y Y NX Y 2[6Z G" + "\\6Y FZ5[ G[5Z GZ5[ GZ5[ G[5Z =[:_ HY0X HY0X GX0X GX0Y GZ5Y F\\5Z GY5Z Z6Y &[ .Y NX Y %WEYJYEX#Z8a GYHe FY DX4[ DY $\\5Y CY8Z 5d Y*Z KZ/Z KZ0Z L[1[ L[1[ LZ J[G\\ L[7Y?Z*Z(Z#Z(Z$Z(Z$" + "Y'Y >c 6Z2Z KYDY ?Y X NX NY Y Y 4\\1Y+[ %Z1Y HY1Y HY1Y HY1Y 5Y Y NX Y 3[5Z G[5Z HZ3Z GZ4[ HZ4Z HZ3Z GZ" + "4[ >Z9` IY0X HY0X GX0X GX0Y FY6Z F\\4Z GY6Y ;W9X9W-X JX,WD[I\\DW,W1[DW-X JX =X 1Y6Z <~d'RKY:U 5~U J" + "~T$~g'~X KY1X GX.X Z ?y DgF` *Z 2k >Z4^ 6Z \"[ 1j >~d =i -[ LW=\\C_?W)YZ=Z =YZ=Z =YZ=Z LZ=~Q3Z H~Q G~Q F~Q G~Q" + " 5Z !Z !Z \"Z Ew5[)YCZ>Y*Z KZ/Z KZ0Z KZ1[ L[1Z KZ I[I\\ K[8Y>[+Z(Z#Z(Z$Z(Z$Y'Y =a 5Z2Z KYDY ?Y Y X MX Y Y" + " 4\\1Y+Z $Y0Y IZ1Y IZ1Y IZ0X 5Y Y NX Y 3Z3Y GZ3Y HZ3Z HZ2Z IZ2Z IZ3Z GZ3Z >Z:a IY0X HY0X GX0X GX0Y FZ7Y E[" + "3Z GY6Y ;W9X9W-W HW,WC[K\\CW,W2[CW-W HW =X 1Z7Z <~d NX:U 5~V M~X%~e&~Y LX0Y HX.X =ZJY 6Y=Z W " + " NZ 3Y X@X ?]IT ?hCW 7h2X ;Y CY 7TAVAT 1X .X 8Z.Y 4Z G\\ 6g 5X=Z ?X?a EeB^ +Z /f ;[5" + "^ 4i ;~d :i 1[ LWr *Y " + "9Z(Z KZ8Z'Z@XBX@Y D\\ &` $\\ )X JX DY &X E[2Z HZ %Z3\\ IZ/X 8Y 4Z2[ GZ3Y 4Y NX 0XE\\ &Y FZ4[5Y*[4Z IZ" + "2Z H[2Y KY2[ ;[ +X DY .Y1Y FZ7Z!Y?WLX?X H[IZ ;Y7Y '[ ,Y NX NY *Q NV@WLW?U#Z8` FYHd .^FY EX2[ DX $[3Y CX8Y" + " 5YMY [/[IuI[.\\ 4X 4\\ =X =\\$\\" + " =X MZAU -Z &X8Y G~W 6X 0W<\\ FUEX MT iNW 8[D[ K~d &T=WE\\QZZeBX] ,Z 1j <[7_ 7i 8~d 7i 5[ KW=Z=" + "\\?W*Y:Y F{ FZ !Z\"Z\"~Q Dy![1j&~] :Z \"Z 4e &Z 2YDXCXDY(YBZ@Z*Z KZ\"Z[/[IuI[/\\ 3X 3\\ >X >\\\"\\ >X MZAU -Z 'X6X 5c " + "%X 1X;\\ GUEX MT NgMW 9[D[ J~d &T=m;T K~d In 4TA[ 4Y1Y BhEW 3Z DX )i 5[D[ IX9W5Z3W8WFj?TA[BX5Z KY" + ";Z @Z;Z ?Y:Y @Z;Z ?Z;Y ?Y;Z NZ<~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)YAY?Y*Z KZ/Z KZ1[ KZ1[ L[1Z KZ G[M\\ IZ8" + "X<[+Z(Z#Z(Z$Z(Z$Y'Y <_ 4Z2Z KYD[ @X NX Y NY X NX 3Z/Y-Z $Z/Y KZ/Y KZ/Y KZ/Y 6Y Y NX Y 4Z2Z HZ3Y IZ1Z I" + "Z1Z JY1Z JZ1Z IZ1Z @Z;XNZ JY0X HY0X GX0X GX0Y EY8Y D[2Z GY8Y ;X9X8W.W HW-W@hAW-X4[@W.W:[:W =X 0Z9Z I" + "[ 7YY ~m 4Z 3Y W?X >g =cAW?]'[K\\5Y ;Y CZ %V M" + "X /X 7Y-Z 5Z H[ 4l ;XZ>Z.[IuI[0\\ 2X 2\\ ?X ?\\ \\ ?X MY@U 8y ;X6X 4a $X 1X9[ HUEX MT MeLW :[D[ I~d &T=l:T " + "K~d Io 5m 3Y1Y AgEW 3Z Nl 2g 3[D[%lDX5Z>mDXFk@mAW5[ LZ:Y @Y:Z ?Y:Y @Z:Y ?Y:Z AZ:Y NZ<~Q3Z H~Q G~Q F~Q G" + "~Q 5Z !Z !Z \"Z Ew5[)YAZ@Y*Z KZ/Z KZ1[ KZ1[ L[1Z K[ Gh HZ9X;[+Z(Z#Z(Z$Z(Z$Y'Y ;] 3Z2Z KYC[ AX NX Y NY Y X" + " 3Y.Y-Z $Y.Y KY.Y KY.Y KY.Y 6Y Y NX Y 4Z1Y HY2Y IZ1Z IY0Z KZ0Z KZ1Z IY0Z @Y;XMZ JY0X HY0X GX0X GX0Y DY9Y D" + "Z0Y GY9Z ;W8X8W.W HW-W?f?W.W4[?W.W:[:W =X 0Z9Y HZ 5X_@XAa*[I\\6Y ;Y CZ %V MX /X 7Y-Z 5Z I[ 3n >X;Z ] G`9\\ .Z 4s @[9` " + " =i /i ;Z IV=Y9Z>V+Z:Z G~P JZ !Z\"Z\"~Q Dy!Z1l'~] :Z \"Z 4g (Z 2YDYEXCY(YAZAZ*Z KZ\"}$Z K['z 5r /Y 9Z(Z JZ;Z" + "$ZAW@WAZ F_ %\\ $[ &X IX EY &Y FZ0Y IZ %Y/Z IY.Y 9Y 4Y0Z GY1Y 5Y NX 0XH[ \"Y FY3Z3Y+Z2Y JZ0Z IZ0Y MY0" + "Z ;Z *Z FY .Y1Y DY9Y MYAWJXAY F[MZ 8Z:Y )[ +Z MX N[ 7g1U U<^;U&Z6^ EYHj 9gJY FX/Y CY &Z2Y BYY1Y%Z" + " J[*ZBYBZ HY9Y IY@X@Y KY0Z MY/Y 4Y 6~W GZ:Z ,[ 6Z 2Z KZ/Z;Z;Z*Z(Z([>Z?[.ZHuI[1\\ 1X 1\\ @X @\\ M\\ @X NZ" + "@U 8y ;W4X 5` #X 1X8Z HUEX MT LbJW ;ZC[ H~d &T=j8U L~d Io 5l 2Y1Y @fEW 3Z Nl 0c 0[CZ&lDW5[>mEXE\\N^" + "AlAX6\\ LZ:Z AY9Y @Z:Z AY9Y @Z:Z AY9Z!Z;~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)Y@ZAY*Z KZ/Z KZ1[ KZ1[ L[1Z K" + "[ Ff GZ:X:[+Z(Z#Z(Z$Z(Z$Y'Y :\\ 3Z2Z KYC\\ BY X NX NY Y X 3Y-X-Y #Y-X KY-X KY-X KY-X 6Y Y NX Y 5Z0Y HY" + "2Y IY/Y JZ0Z KZ0Z KY/Z KZ/Y AZ;WKY JY0X HY0X GX0X GX0Y DY:Z DZ0Y FY:Y :WK~KW.WK}KW-W>d>W.W5[>W.W:[:W =X /" + "Y:Z IZ 4Y=T 6~[%~b'~_%~\\ NY/X HX.X >ZHY 6Y?Y N~m 4Z 3Y !X@X ;l @[>WBe,ZG\\7Y ;Y" + " CZ %V ;~c LX 7Y-Z 5Z J\\ 2n @Y;Z N\\ G`8\\ /Z 5u A\\V+Y8Y G~R LZ !Z\"Z\"~Q" + " Dy![2l'~] :Z \"Z 4h )Z 2YCXEXCY(Y@ZBZ*Z KZ\"|#Z K['x 0q 1Y 9Z(Z IZY1Y%Z IZ*YAYBZ HY9Y IY@X@Y KY/Y MY/Y 4Y 6~W GY9Z " + "-[ 5Z 2[ LZ/Z;Z;Z*Z(Z'[?Z?[.[IuI[2~n BX B~n AX A~m AX NZ@U 8y dEW 3Z Nl ._ ,ZCZ'lEX6\\>mEWDVCZBkAX6] LY8Y BZ9Z AY8Y BZ9Z AY8Y BZ9Z!Z;~Q3Z H~Q " + "G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)Y@ZAY*Z KZ/Z KZ1[ KZ1[ L[1Z KZ Ee FZ;Y:[+Z(Z#Z(Z$Z(Z$Y'Y :[ 2Z2Z KYB\\ CY X NX" + " NY Y Y 4Y-Y.Y #Y-X KY-X KY-Y LY-Y 7Y Y NX Y 5Z0Z IY2Y JZ/Z KZ/Y KY/Z KY/Z KZ/Y#~d$ZX /Z;Z JZ 2X>U 6~\\'~c&~^$~Z MY/X HX.X >YGZ 7Z@Y " + "N~m 4Z 3Y !X@X :n 'WBg.ZE\\8X :Y CZ %V <~e NX 6Y-Y 4Z K\\ #a AX:Z M\\ H_6[ 0Z" + " 6aI` A]?c ?f $f ?Z IW>Y7Y>V,Z8Z HZ8` MZ !Z\"Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZN] *Z 2YCXFYCY(Y@ZBZ*Z KZ\"{\"Z " + "K['v +o 2Y 9Z(Z IZq:X !U:[9U&Y5] DY?d =jLX FY/Z C[ " + ")Y1Y AX=Z 6ZIY >Y1Y%Z IZ*YAYAY HY9Y IY@X@Y KY/Y NZ/Z 5Y 5Y-Y HZ8Y .[ 4Z 1Z LZ/Z;Z;Z*Z(Z'[?Z@[-[ L[3~o BX B~o BX" + " B~o BX NZ@U 8y mFXDS?YBi?W5] CY 4Z8Y BY7Y BZ8Z CY7Y AY8Z CZ8Y!Y:Z Z !Z !Z \"Z Ew5[)Y?ZBY*Z KZ/Z KZ1[ KZ" + "1[ L[1Z KZ Dc E[=Y9[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z2Z KYB^ &i 0i 1i /i 0i 0i Ej-Y/Z $Z-Y MZ-Y MZ-Y LY-Y 7Y Y NX Y 5Y/" + "Z IY1X JZ/Z KZ/Z LY.Y LZ/Z KZ/Z$~d$Z=WIZ KY0X HY0X GX0X GX0Y CYX .Y;Y JZ 1Y?U 6~\\(~e'~]\"~X LX.X HX.X >YFY 7ZAZ N~m 4Z 3Y !W?X 9p +XCi0ZC\\9X " + " :Y CZ %V <~e NX 6Z.Y 4Z L\\ M^ CY:Z L[ H^4Z 0Z 7^A^ C_Ce ?c Mc @Z HW>X6Y>V,Y7Z HZ5^ NZ !Z\"" + "Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZM] +Z 2YBXGXBY(Y?ZCZ*Z KZ\"z![ LZ&w 'k 3Y 9Z(Z IZ=Z\"ZCX@XCZ Gc &Z &\\ $X HX FY " + " >q FY.Y JY $Y/Z JY,X 9Y 5Y.Y GY1Y 5Y NX 0XL\\ NY FY3Z3Y+Y1Y JY.Z JY/Z NY/Y ;Y (^ KY .Y1Y CY;Y KYCXIXCY " + "Bc 4Y\\IYMX FY/Z B\\ +Y1Y AY>Y 5ZIZ ?Y1Y%Z IZ*YAYAY HY9Y IY@X@Y KY/Y NZ" + "/Z 5Y 5Y-Y HZ8Z 0\\ 4Z 1Z LZ/Z;Z;Z*Z(Z&[@Z@[-[ L[4~p BX B~o BX B~p CX NY?U 8y mFWCQ;XAe>X6UNW CY 4Y7Z DZ7Y BZ8Z CY7Z CZ7" + "Y CY7Z#Z:Z Z !Z !Z \"Z :Z#[)Y?ZBY*Z KZ/Z KZ0Z KZ1[ L[1Z KZ Ca D[>Y8[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ " + "KYA^ /q 9r 9q 7q 8q 9r Mq,Y/Z $Y,Y MY,Y MY,Y MZ-Y 7Y Y NX Y 5Y.Y IY1X JZ/Z KY.Z LY.Y LZ/Z KY.Z$~d$Y=XIZ KY0X" + " HY0X GX0X GX0Y CYX .YW-Y6Y HZ2\\ Z !Z\"Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZL] ,Z 2YBXGXBY(Y?Z" + "CZ*Z KZ\"x N[ LZ&x #f 3Y 9Z(Z HZ>Z\"ZCW>WCZ Hd &Z &[ #X HX FY At FY.Y JY $Y/Z JY,Y :Y 5Y.Y GY1Y 5Y NX" + " 0XM\\ MY FY3Y2Y+Y1Y JY.Z JY.Y Z/Y ;Y (b Y .Y1Y CY;Y KYCWHXCY Bb 3Y=Y *[ 6e JX Ke KzF^ !U9Y7T'Z4[ CY7] @[E" + "XNX GZ.Y Ai 9Y1Y AY>Y 5YHZ ?Y1Y&[ IZ+ZAYAY HY9Y IY@X@Y KY/Y NZ.Y 5Y 5Y-Y IZ6Y 0[ 3Z 1Z LZ/Z;Z;Z*Z(Z&\\AZA[,[ L[" + "4~p BX B~o BX C~q CX NY?U 8y Z !Z !Z \"Z :Z#[)Y>ZCY*Z K" + "Z/Z KZ0Z L[1[ L[1Z KZ B_ C[>X7[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ KY@_ 5u XHZ KY0X HY0X GX0X GX0Y BY=Y BY.Y FY=Z 9WK~KW/WJ}JW.W:\\:W.W" + "9[:W/W9[9W >X .Z=Y JZ /X@U 6~^*~g&~Y N~V KX.Y IX.X ?ZFZ 7ZBY L~l 4Z 3Y \"X@X 3n /X" + "CZIZ2Z@\\W.Z6" + "Z IZ1[ Z !Z#[\"Z MZ 1[2l'Z(Z :Z \"Z 4ZK] -Z 2YBXHYBY(Y>ZDZ*Z KZ\"v L[ LZ&z !c 4Y 9Z(Z HZ>Z\"ZDX>XDY Ge 'Z '[ " + "\"X GX GY Dw FY.Y JY %Z/Z J~W :Y 5Y.Y GY1Y 5Y NX 0XN\\ LY FY3Y2Y+Y1Y JY.Z JY.Y Z/Y ;Y 'e $Y .Y1Y CZ=Z" + " KYDXGWDY @a 3Z>Y +[ 5d IX Ic L~d !U8X7T'Z4[ CY5\\ AZCa GY-Y @h 9Y1Y @X?Z 6ZGY ?Y1Y&[9X9Z+ZAYAZ IY9Y IY@X@Y " + "KY/Z Y-Y 5Y 5Y.Z IZ6Z 2[ 2Z 1Z M[/Z;Z<[*Z(Z%[AZB\\,[ LZ3~p BX B~o BX C~q CX NY?U 8y Z !Z !Z \"Z :Z#[)Y>ZCY*Z KZ/Z KZ0Z L[1[ L[1[ LZ A] B[?X6Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ KY?" + "_ 8w ?x ?w =w >w >w$~u/Y #~W M~W M~W M~W 7Y Y NX Y 6Z.Y IX0X JY-Y KY.Z MZ.Z MY-Y KY-Y$~d$Y?XFY KY0X HY0X GX0" + "X GX0Y BY>Z BY.Y EY>Y 8WK~KW/WJ}JW.W;]:W.W:[9W/W9[9W >X -Y>Z KZ .YAU 6~^*~g%~W L~T JX.Y IX.X ?YEZ 7Z" + "CZ L~k :y KY \"X@X 0m 1WCYEY3Y>\\=X 9Y BY %V <~e =l X 5Z.Y 4Z \\ E[ GY8Z JZ I]" + "2Z 2Z 8[7[ BqMZ ?^ C^ @Y GV=W4X>V-Y5Z IZ0[!Z !Z#[\"Z MZ 1[2l'Z(Z :Z \"Z 4ZJ] .Z 2YAXIXAY(Y=YDZ*Z L[\"s" + " I[ LZ&[Cc Na 5Y 9Z(Z HZ?Z YDX>XEZ Hg (Z (\\ \"X GX GY Fy FY.Y KZ %Z/Z J~W :Y 5Y.Y GY1Y 5Y NX 0e KY" + " FY3Y2Y+Y1Y KZ.Z JY.Y Y.Y ;Y &h (Y .Y1Y BY=Y IXDXGWDY ?_ 1Y?Z ,[ 4b GX Ga L~c T6V6T'Z4[ CY4\\ CZ@_ GY-Y >f " + "9Y1Y @Y@Y 5YFZ @Y1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y KX.Z Y-Y 5Y 5Y.Z IY5Z 3[ 1Z 1Z M[/[WEY9T -X EY1Y 1WEW 3Z 6ZCZ 7X7" + "UKV HW*W KX6ULW CY 5Y5Z FZ5Z EY4Y FZ5Z EZ5Y EY5Z%Z9Z Z !Z !Z \"Z :Z#Z(Y=ZDY*[ LZ/Z KZ0Z L[0Z " + "LZ0[ LZ A] B[@X5Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z4[ JY>` Y 8WK~KW/WJ}JW.W<_;W.W;[8W/W9[9W >X -Z?Z " + " LZ -YBU 5~^*~h%~U J~R IX.Y IX.X @ZDY 6YCZ LW 'y JY \"W?X ,j 3WCYCY4Y=\\>X 9Y CZ" + " %V <~e =l X 5Z.Y 4Z !\\ C[ IY7Z JZ I]2Z 3[ 9[5[ BoLZ ?a Ia @Y HW>X3W>V.Z4Y IZ/Z!Z !Z#[\"Z MZ 0" + "Z Z'Z(Z :Z \"Z 4ZI] /Z 2YAXIXAY(Y=ZEZ*Z L[\"o DZ LZ&Z<^ M_ 5Y 9Z(Z GZ@Z ZEX>XEZ I[MZ (Z )\\ !X GX GY " + "Gz FY.Y KZ %Y-Y J~W :Y 5Y.Y GY1Y 5Y NX 0c IY FY3Y2Y+Y1Y KZ.Z JY.Y Y.Y ;Y %j +Y .Y1Y BY=Y IYEXGXEY >] 0Y?Y ,[ " + "3` EX E_ L\\Cx NT6V6T'Z4Z BY2Z CY>^ GY-Y ;c 9Y1Y @YAZ 6ZEY @Y1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y KX.Z Y-Y 5Y 5Y.Z JZ" + "4Y 4\\ 1Z 1[ NZ.[" + "WDX:U -X EY1Y 1WEW 3Z 5YBY 7W6UKV IX*W KW6UKW CY 6Z4Y FZ5Z FZ4Z GZ4Y EY4Z GZ4Y%Y8Z <[ IZ !Z " + " Z !Z >Z !Z !Z \"Z :Z#Z(Y=ZDY*[ LZ/Z L[0Z L[0Z LZ0[ LZ B_ BZAY5Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z5\\ JY=` ?{ B{ Bz @z B{ " + "B{'~x/Y #~W M~W M~W M~W 7Y Y NX Y 6Z.Y IX0X JY-Y LZ-Y MZ.Z MY-Y KY-Y$~d$Y@WDY KY0X HY0X GX0X GX0Y AY@Z AY.Y " + "DY@Z 8WK~KW/WJ}JW.W=aX ,Y?Y LZ +XBU 6~_+~i%~U I~P HX.Y IX.X @ZDZ 7YCY KX " + " (y JY \"W?W (h 5XCXAX5Z<\\@Y 9Y CZ $T ;~e =l X 5Z/Z 4Z \"\\ AZ IX6Z JZ I\\1[ 4Z 8Z3Z AmKZ" + " ?d d AZ HW>X3W>V.Z4Z JZ.Z\"[ \"Z#[\"Z MZ 0Z Z'Z(Z :Z \"Z 4ZH] 0Z 2YAYKX@Y(YWCX;U -X EY1Y 1WEW 3Z Is 0YAX 8W6UJV IW)W" + " LX7UJW CY 6Z4Z GY3Y FZ4Z GY3Y FZ4Z GY3Z'Z8Z <[ IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(Yc=W.W=[6W/X:[:X >X ,Y@Z M[ " + "+YCT 5~`,~i$~S H~P HX.Y IX.X @YCZ 7ZDY KX )y HX #X@X (TNc 6WCX@X5Y:\\AX 8Y CZ :~e" + " =l !X 4Z/Z 4Z #\\ @[ KY6Z IZ I[0Z 4Z 9Z2[ @jJZ ?f %g AZ HW>X3W>V.Y2Y JZ.Z\"[ \"Z#Z!Z MZ 0Z Z'Z(Z" + " :Z \"Z 4ZG] 1Z 2Y@XKX@Y(YWBXZ !Z !Z \"Z :Z#Z(YW.W>[5W.W:[:W =W +ZAY LZ *YDU 5~`,~i#~Q F} GX.Y IX.X AZBY 7ZEZ KX " + ")y HX 6~e 9TJ_ 7XCX?X6Y9\\BX 8Y CZ KX Nl !X 4Z/Z 4Z $\\ >Z LY5Z IZ I[0Z 5Z 8Z1Z >fHY =h " + " +i @Z HW>X3W?W/Z2Z KZ.[#[ \"Z#Z!Z MZ 0Z Z'Z(Z :Z \"Z 4ZF] 2Z 2Y@XLY@Y(Y;ZGZ*[ MZ!Z /Z M[&Z7[ K\\ 6Y 9Z(Z FZ" + "BZ MYFXY FY.Y KZ %Y-Y K~X :Y 5Y.Y GY1Y 5Y NX 0e KY FY3Y2Y+Y1Y KZ-Y JY.Y" + " Y-X ;Y !m 2Y .Y1Y AZAZ GYGXEXGY >] .ZBY -[ 1e JX Ke LU4k IU8Y8T'Y2X AY0Y EX:[ FY-Z Ah 9Y1Y >XCZ 6YBY AY1Y&" + "Z8X8Z,Y@YAZ IY9Y IY@X@Y LY-Y Y-Y 5Y 5Z/Y JZ2Z 8[ .Z 0[!Z,[=Z=[)Z(Z\"]FZG]'Z M[1] 1X 1\\ @X @\\ L\\ AX DX 4" + "Z?U -Z (X4X H~W ;\\;W GTDX\"U s A[D[ 6X %T>WBXZ !Z !Z \"Z :Z$[(Y;ZFY)Z M[/[ MZ/[ MZ/Z M[/Z M[ Ee EZC" + "X3[*Z(Z#Z(Z$Z(Z$Y(Z 9Z 2Z8^ IY9` Fb=Y Eb=Y Eb=X Cb>Y Eb=Y Eb=Y*b=~V/Y #~W M~W M~W M~W 7Y Y NX Y 6Y-Z JX0X JY" + "-Y LZ-Y MY-Z MY-Y LZ-Y CZCXBY KY0X HY0X GX0X GX0Y @YBZ @Y.Y CYBY 6W8X8W.W HW-W@g@X.W?[4W.W:[:W =W *YBZ " + " MZ (XDU 5~`,~i\"~ D{ FX.Y IX.X AZBZ 7YEY IX +y GX 6~e 9TG] 8WBW>X6Y8\\DY 8Y CZ " + " KX Nl !X 4Z/Z 4Z %\\ =Z LX4Z IZ I[0Z 5Z 9Z0Z X3W?W/~S KZ-Z\"Z \"Z#Z!Z MZ 0[!Z" + "'Z(Z :Z \"Z 4ZE] 3Z 2Y?XMX?Y(Y;ZGZ)Z MZ!Z /[ N[&Z6[ K\\ 7Y 9Z(Z FZCZ LZGX^ .YCZ ." + "[ )_ KX L_ ES/e FU8Z9T'Z3X AY0Y FY:[ FY-Z Cj 9Y1Y >XCY 6ZBZ BY1Y&Z8X9[,Y@YAZ IY9Y IY@X@Y LY-Y Y-Y 5Y 5Z/Y J" + "Z2Z 9\\ .Z /Z!Z,\\>Z>[(Z(Z!]GZH^'[ N[0\\ 1X 2\\ ?X ?[ M\\ @X DX 4Z?U -Z 'W4W G~W :]>X GTDY#U s @[D[ 7" + "X %U?WAX>U ,X EY1Y 1WEW \"s 3ZC[ 9X7UHV KW(W MX7UHW CY 7~S J~S H~S I~S I~S I~S)} ;Z IZ !Z Z" + " !Z >Z !Z !Z \"Z :Z$[(Y;ZFY)Z MZ-Z MZ/[ N[/[ N[/Z MZ Eg F[EX2[*Z(Z#Z(Z$Z(Z$Y(Z 9Z 2Z9^ HY7_ G]8Y F^8Y F^8X D]8" + "Y E]8Y F^8Y+^8~V/Y #~W M~W M~W M~W 7Y Y NX Y 6Y-Z JX0X JY-Y LZ-Y MY-Z MY-Y LZ-Y BYDXAY KY0X HY0X GX0X GX0Y" + " @ZCY ?Y.Y CYBY 5W9X8W.W HW-WAiAW,WA[3W.W9Y9W >X *ZCZ 6~d IYET 4~`,~i!| By EX.Y IX.X AYAZ 7ZFY IX " + " Z 3X 6~e 9TF\\ 9WBX=W7Z7\\EX 7Y CZ KX Nl \"X 3Z/Z 4Z &\\ ;Z M~Z %Z I[0Z 6[ 9Z/" + "Y 8ZCZ 8i 6~d 5i ;Z HW>X3W?W0~T KZ-Z\"Z \"Z$[!Z MZ 0[!Z'Z(Z :Z \"Z 4ZD] 4Z 2Y?XMX?Y(Y:ZHZ)Z N[!Z /[ NZ%Z6[" + " J[ 7Y 9Z(Y DZDZ LZGW:WGZ K[GZ +Z -\\ LX EX IY L\\6Y FY.Y KZ %Y-Y K~W 9Y 5Y.Y GY1Y 5Y NX 0XM\\ MY " + "FY3Y2Y+Y1Y KZ.Z JY.Y Y-X ;Y Ji 4Y .Y1Y @YAY FYGWDXGX >` /YCY .[ $\\ LX M\\ AR+` CT9[:U'Z3X AY0Y FY9Z FY-Z " + "D` .Y1Y >YEZ 6YAZ BY1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y LY.Z Y-Y 5Y 5Z/Y KZ1Z 9[ -Z /Z\"[+[>Z>[(Z(Z ^IZJ_&[ NZ.\\ 2X 3" + "\\ >X >[ \\ ?X DX 4Z?U -Z 'X6X G~W 9^@X GUDY$T Ns ?[CZ 8X %U?WAY?U ,X EY1Y 1WEW \"s 4" + "ZCZ 7W7UGV LX)X MW7UGW CY 8~T J~T I~S J~T I~T K~T*~ ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(Y:ZGY)[ NZ-Z N[.Z N[/[ N" + "[/[ NZ Fi G[FX1Z)Z(Z#Z(Z$Z(Z$Z)Z 9Z 2ZX )YCY 5~d IYFU 4~`,~i!{ @x EX.Y IX.X AY@Y 7ZGZ IX Z 3X 6~e 9TD[ ;XBX=X8" + "Z6\\GY 7Y CY JX Nl \"X 2Y/Z 4Z '\\ :Z M~Z %Z I[0Z 6Z 8Z/Z \"Z 5i 9~d 8i 8Z HW>X3W?W0~U LZ-Z\"[ " + "#Z$[!Z MZ /Z!Z'Z(Z :Z \"Z 4ZC] 5Z 2Y?XNY?Y(Y:ZHZ)[ [!Z .Z NZ%Z5[ K[ 7Y 9Z(Y DZDY KZHX:XHY K[EZ ,Z .\\ KX EX" + " IY LZ4Y FY.Y KZ %Z.Y KZ X DX 4Z?U -Z 'X6X G~W " + "8^BX FUDY%U Ns =ZCZ 9X $U@W@X?T +X EY1Y 1WEW \"s 5ZCZ 7W7UFV LW(W MX8UFW CY 8~U K~T J~U K~" + "T J~U K~T*~ ;[ JZ !Z Z !Z >Z !Z !Z \"Z :Z$Z'Y9YGY)[ [-[ [.Z N[.Z NZ.[ NZ G\\L[ GZGX0Z)Z(Z#Z(Z$Z(Y#Z)Z 9Z 2~ " + "GY4] J[4Y G[4Y G[4X EZ4Y FZ4Y G[4Y,[4X 1Y #Y Y Y Y 9Y Y NX Y 6Y-Z JX0X JY-Y LZ-Y MZ.Z MY-Y KY-Y BYEW?Y" + " KY0X HY0X GX0X GX0Y ?YDY >Y.Y BYDY 4W9X9W-X JX,WD\\J[CW,WC[2W-X JX >X )YDZ 5~d HXFU 4~_+~i z @w DX.Y" + " IX.X BZ@Y 6YGZ IY Y @~e 9TCZ ;WAX=X8Y4\\HX 6Y CY JX Mj !X 2Y/Y 3Z (\\ 9Z" + " M~Z %Z I[0Z 6Z 8Z/Z \"Z 2i <~d ;i 5Z HW>X3W@W/~U LZ-[#[ #Z$Z Z MZ /Z!Z'Z(Z :Z \"Z 4ZB] 6Z 2Y>a>Y(Y9ZIZ)[ " + "Z Z .Z [%Z4Z JZ 7Y 9Z)Z DZEZ JYHX:XIZ KZD[ -Z /\\ JX EX IY MZ3Y FY.Y JY %Z/Z JY Z !Z !Z \"Z :Z%['Y9ZHY(Z [-[ Z" + "-[ Z-Z [-Z [ H\\J[ HZHY1[)Z(Z#Z(Z$Z(Y#Z)Z 9Z 2} FY2\\ KZ3Y GZ3Y GY3Y FZ3Y GZ3Y GZ3Y,Z3X 1Y #Y Y Y Y 9Y Y " + "NX Y 6Y-Z JX0X JY-Y KY.Z MZ.Z MY-Y KY-Y BYFX?Y KY0X HY0X GX0X GX0Y >YEY >Y.Y BYEZ 4X:X9W,W JW+WE\\H[EX,X" + "E[1W,W JW =X )ZEY 4~d HYHU 2~^+~i Nx >u CX.Y IX.X BY?Z 7ZHY GX Z A~e 9TCZ ~d >i 2Z GV>X3W@W0~V LZ-[\"Z " + "#Z%[ Z MZ /[\"Z'Z(Z :Z \"Z 4ZA] 7Z 2Y>a>Y(Y9ZIZ(Z Z Z .[![%Z4[ KZ 7Y 9Z)Z CZFZ JZIX:XIZ L[CZ -Z /[ IX DX J" + "Y MY2Y FY.Y JY %Z/Z JY Y CY1Y&Z9Y9Z+ZAYAY HY9Y IY@X@Y LZ/Y N" + "Y-Y 5Y 4Y0Z LZ.Y =[ *Z .[%Z(]AZA]'Z(Z L~\"[![+\\ 5X 6\\ JTEXET J[&\\ KSDXES $Y 3Y?U -Z &Y:Y F~W 5_GX DU" + "CZ9QAU DZCZ ;X $VAW?YBU +X EY1Y 1WEW DZCZ 6W7UEV NX)X MX8UEW DY 8~V L~V L~W M~V K~V M~V" + ",~P :Z JZ !Z Z !Z >Z !Z !Z \"Z :Z%['Y8ZIY(Z Z+Z Z-[![-[![-[![ I\\H[ I[JY0[(Y(Z#Z(Z$Z)Z#Z)Z 9Z 2| EY1\\ LY2Y " + "HZ2Y HZ3Y FY2Y GY2Y GY2Y-Z2X 1Y #Y Y Y Y 9Y Y NX Y 6Z.Y IX0X JY-Y KY.Z MZ.Z MY-Y KY.Z BYGX?Z KY1Y HY0X" + " GX0X GX0Y >YFZ >Y.Y AYFY 2W:X:X,W JW+XG\\F[FW+XF[1X,W JW =X (YEY 4~d GXHU 2kNRMk*tNq Mv Y 7ZIZ GY !Z A~e 9TBY `=Y(Y8ZJZ([\"[ Z " + ".[!Z$Z3Z KZ 7Y 9Z)Z CZGZ IZIW8WIZ M[AZ .Z 0\\ IX DX JY MY2Y FY.Y JY $Y/Z JY YEY CYIWBXIX @f 0YGZ 0[ LZ NX NY 'U>WMW?V&Z4Y AY/Y HY8Y" + " EZ.Y FZ %Y1Y Y CY1Y&[:Z:Z+ZAYAY HY9Y IY@X@Y LZ/Y NZ.Y 5Y 4Y0Y KZ.Z ?\\ *Z -['['\\AZB]&Z(Z K|![!Z)\\ 6" + "X 7\\ JVFXFV J[(\\ KUEXFU %Y 3Y?U -Z %YXCU *X EY1Y 1WEW" + " F[CZ 6X8UDV NW)X MX8UDW DY 8~W N~W L~W M~V L~W M~W-~P :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z%['Y8ZIY([\"[+[" + "\"[,Z![-[!Z,[!Z I\\F[ J[KY/Z'Z)Z#Z)Z#Z)Z#Z)Z 9Z 2{ DY0[ MY1Y HY1Y HY2Y FY2Y HZ2Y HY1Y-Y2Y 1Z $Y Y Y Z :Y Y" + " NX Y 6Z.Y IX0X JZ.Y KY.Z MZ.Y LZ.Y KY.Z BYHX>Z KY1Y HY1Y GX0X GX0Y =YGY =Y.Y AYFY 2X;X:W+X LX*WH\\D[HX" + "*WG[0W+X LX =X (YFZ 4~d GYIU 2jLQLj*pNRNq Lt :q AX.Y IY0Y CZ>Y 6YIZ FX !Z A~e 9T" + "BZ >W?W;W8Z2\\MY 4Y DY JX 4X 1Z1Z 3Z +\\ 6Z M~Z %Z HZ0Z 8[ 7Y.Z #Z )i D~d Ci -Z GV=W4XAW/~W M" + "Z-[\"[ $Z&[ NZ MZ .Z\"Z'Z(Z :Z \"Z 4Z?] 9Z 2Y=_=Y(Y8ZJZ([\"[ Z -Z\"[$Z3[ L[ 8Y 9Z)Z BZHZ IZJX8XJY LZ@[ /Z 1\\" + " HX DX JY NY1Y FZ0Z JY $Y/Z JY YEY BXJXAWJY A[N[ 1YGY 0[ JY NX NY 'V@WLX@U$Y5[ BY/Y HX7X DZ.Y FY $Y1Y Z " + "/Z K_MZ BUC]BVBU A[D[ >X #VBW=XDU *X EY1Y 1WEW G[D[ 5W8UCV X*X LW8UCW EZ 8~W N~X M" + "~W N~X M~W N~X.~Q :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z&[&Y7ZJY([\"[+[\"[,[\"Z+[#[+Z\"[ J\\D[ JZKX/['Z*[#[*Z#Z)Z#Z)Z" + " 9Z 2z CY/Z MY1Y HY2Z HY2Y GY1Y HY1Y HY1Y-Y2Z 2Z $Z !Z !Z !Z :Y Y NX Y 6Z.Y IX0X JZ/Z KY.Z LY.Y LZ/Z KY.Z " + " BYHW=Z KY1Y GX1Y GX1Y GX0Y =YHZ =Y/Z @YHY 1X;X;X*W LW)XJ\\B[IX*XI[0X*W LW Z 7ZJY EY !Z 1X@X &TAY ?X?W;W8Z1\\NX 3Y DY JX 5Y 0" + "Y1Z 3Z ,\\ 5Z M~Z %Z HZ0Z 8Z 6Y.Z #Z &i G~d Fi )X FV=X5XAW0~Y NZ-[!Z $Z&[ NZ MZ .[#Z'Z(Z :Z \"Z 4Z>] :Z 2" + "Y=_=Y(Y7ZKZ'Z#[ NZ -[#[$Z2[ M[ 8Y 9Z)Z BZHZ HYJX8XKZ M[?Z /Z 2\\ GX CX KY NY1Y FZ0Z JZ %Y/Z JZ =Y 4" + "Y0Z GY1Y 5Y NX 0XG\\ $Y FY3Y2Y+Y1Y JZ/Y IZ0Y MY/Y ;Y 8[ 8Y .Y1Y >ZGZ BYKXAXKY B[LZ 0YHY 1[ IY NX Z &VB" + "XKXBV$Y5[ BY/Y HX8Y CY/Z GY #Y1Y Z !Z !Z \"Z :Z&[&" + "Y7ZJY'[#Z)Z#[+[#[+[#[+[#[ K\\B[ K[MX.['Z*Z!Z*Z#Z)Z#Z)Z 9Z 2x AY.Z NY2Z HY2Z IY1Y GY1Y HY1Y HY2Z-X1Z 2Z $Z !Z !Z" + " !Z :Y Y NX Y 5Y/Z IX0X JZ/Z KZ/Y KY.Y LZ/Z KZ/Y AYIWW;W8Z0e 3Y EZ JX 5X /Z2Y 2Z -\\ 4Z M~Z %Z HZ0Z 8Z 6Z/Z $Z #j J~d Ii CW>X6Y" + "BX0~Y NZ-[![ %Z'\\ NZ MZ -Z#Z'Z(Z :Z \"Z 4Z=] ;Z 2Y<][ 0" + "Z 3\\ FX CX KY NY2Z FZ0Y IZ %Y/Z JZ =Y 4Y0Z GY1Y 5Y NX 0XF\\ %Y FY3Y2Y+Y1Y JZ/Y IZ0Y MY/Y ;Y 7Z 8Y" + " .Y2Z =YGY AYKW@XKY BZJZ 1YIY 1[ HY NX Y %WEYIYFW#Y5[ BY/Y HX8Y CY/Z GY #Y1Y ;XIY 6Y;Z EY1Y%Z:Z:Z*ZBYBZ " + "HY9Y IY@X@Y LZ/Y MY/Z 4Y 4Y2Y KZ,Z B[ 'Z +[+[#_FZF_$Z(Z Gt JZ$[%\\ 9X :\\ J\\IXI[ I\\/\\ K[HXI[ (Y 3Z@U -Z " + "%^F^ /Z X \"f >VBnCU >[D[ @X \"VCWZ !Z !Z \"Z :Z'[%Y6ZKY'[$[)[$[*[$[*[%[*[$[ K\\@[ Le.[&Z*Z!Z*Z\"Z*Z#Z*[ 9Z 2v " + "?Y.Z NY2Z HX1Z IY1Y GY1Y HY2Z HX1Z.Y1Z 1Y #Y Y Y Y :Y Y NX Y 5Y/Z IX0X IY/Z KZ/Y KY/Z KY/Z KZ/Y 7\\ 7ZKW" + ";Y IX1Y GX1Y GY2Y GY2Z YJX(XJY/X)X Y W;W7Y/c 2Y EY IX 5X /Z3Z 2Z .\\" + " 3Z M~Z &Z FY1Z 8[ 6Z/Z $Z i L~d Li @W>Y7YBW0Z*Y NZ-[![ %Z'[ MZ MZ -[$Z'Z(Z :Z \"Z 4Z<] Z !Z !Z \"Z :Z(\\%" + "Y6ZKY&[%[)\\&[)[%[)[%[)[%[ L\\>[ Ld.[&Z*Z!Z*Z\"Z+[\"Z+Z 8Z 2s YJY .X=X=Y(" + "X!X'YJWX.Y HY2Y CZW=X8ZC" + "W/Z*Z Z-Z N[ &Z(\\ MZ MZ -\\%Z'Z(Z :Z \"Z 4Z;] =Z 2Y<]Y 4Z2[ GY1Y 5Y NX 0XD\\ 'Y FY3Y2Y+Y1Y IY0Z IZ1Z MZ1Z ;Y 6Y" + " 8Y .Y2Z =ZIZ @XLX?WLY C[H[ 2YKZ 3[ EX NX Y $hFh\"Z7\\ BY0Y GX9Y BZ1Z FX \"Y1Y ;YKY 6Y9Y EY2Z%Z;[:Z*ZBYB" + "Y GY9Y IY@XAZ L[1Y LZ1Z 3Y 3Y3Y LZ*Z D[ &Z *[-[ aJZJa\"Z(Z Cl F\\'[\"\\ ;X <\\ F\\KXK\\ F\\3\\ H\\JXK\\ 'Y " + "2ZAU -Z 'z 1Z X Na ;V@jDV :ZCZ BX UDW;XIU 'X EY2Z 1WEW KZCZ 3X9U@V\"W*X LX9VAW H[ " + "8Z*Z\"Y)Y!Z*Z\"Z*Y!Z*Z\"Z*Z1Z3Z 8[ MZ !Z Z !Z >Z !Z !Z \"Z :Z(\\%Y5ZLY&[&['[&[([&[)\\'\\)[&[ L\\<[ Mc.[$Z,[!" + "[,[\"Z+Z!Z+Z 8Z 2n 7Y-Y NX1Z IY2[ IY2Z GY2Z HY2Z IY2[.Y2\\ 2Z $Z !Z !Z !Z ;Y Y NX Y 5Z0Y HX0X IZ1Z IY0Z KZ0" + "Y JZ1Z IZ1Z 7\\ 6YMX;Z IY3Z GY2Y GY2Y GY2Z ;YKY ;Z1Z >YJY .Y>X=X'Y#Y&XIU:UJY&YJU.X'Y#Y ;X &YJZ #Z JXLU" + " -dIQId%kKRKk El 2j >X.Y HY2Y CY;Z 7ZMZ BZ #Z 3X@X %TAX @WZ 2Y;[;Y(Y5ZMZ&\\([ LZ +['[\"Z0[ Z 7Y 8[,Z ?YKZ EYLX6XLY [:[ 2Z 5\\ DX BX LY NY3[ F[2Z HZ %Y1" + "[ IZ >Y 3Y2[ GY1Y 5Y NX 0XC\\ (Y FY3Y2Y+Y1Y IZ2Z H[2Z LY1Z ;Y 6Z 9Y .Y2Z Z !Z" + " !Z \"Z :Z)\\$Y5ZLY%[(\\'\\(['\\(['['['[(\\ M\\:[ Ma-[$Z,Z NZ,Z![,Z!Z,[ 8Z 2Z #Y-Y NX2[ IY2[ IY2Z GY3[ HX2[ IY2" + "[.Y2\\ 2Z $Z !Z !Z Y ;Y Y NX Y 5Z1Z HX0X IZ1Z IZ1Z JZ2Z JZ1Z IZ1Z 7\\ 6c:Z IY3Z GY3Z GY3Z GY3[ ;YKY ;[2Z =" + "YLY ,Y?X>Y&Y%Y%YIS8SJY$YJS.Y&Y%Y :X &ZKY #Z IYNU ,cISIb#jKRJi Cj 1i =X.Y GY4Y BY:Y 7ZMZ AZ " + " $[,P )W?X %TBY AXXMY DZDZ 2YLY 3[ DY X Y \"eCd NY8^ CY0Y GX:Y @Z2Z FX \"Y1Y :YMY 6Y7Y " + "FY2Z%[<\\a@V 7YBY CX NV LV BZ3Z 1WEW LYBY 2W8U?V#W+X KX9U" + "?W J[ 7Z(Y#Z)Z#Z(Z$Z)Z\"Y(Z$Z(Y2Z2Z 7\\\"P NZ !Z Z !Z >Z !Z !Z \"Z :Z*\\#Y4ZMY%\\)[%[)\\&[)\\'\\)\\'\\)[ M\\8" + "[ N`-[#Z,Z NZ,Z Z-[![-[ 8Z 2Z #Y-Y NX2[ IY2[ IY3[ GY3[ HY3[ HX2[.Y3^ 2Z $Z !Z !Z !Z ZMZ DZMW4WMZ![7Z 3Z 7\\ BX AX MY NY3" + "[ F\\4Z FZ &Z3\\ HZ ?Y 3Z4\\ GY1Y 5Y NX 0X@[ *Y FY3Y2Y+Y1Y HZ3Z H\\4Z KZ3[ ;Y 5Y 9Y -Y4[ ;YKY >YNX=WNY D[D[ " + "3YMY 3[ CY X Y !cAb MZ9^ CZ2Z GX:Y @Z3Z EX \"Y1Y :YMY 7Z7Y FZ4[$Z<\\Z !Z !Z \"Z :Z+]#Y4ZMY$[*\\%\\*[%\\+\\%\\+\\%\\+\\ N\\6[ N^-\\#[.[ N[.[ [.Z NZ-Z 7Z 2Z #Y-Y NY4\\ IY3" + "\\ IY3[ GY3[ HY4\\ HX3\\.Y3^ 2Z $Z !Z !Z !Z i i 2WZ4" + "Z EY #Y1Y 9XNZ 7Y6Z GZ4[$Z=]=['ZDYDZ FY9Y HZBXBZ K]5Z J[5[ 2Y 2Z7Y L[(Z H[ #Z '\\5[ F~ LZ(Z :Z :\\-\\ KW :X :" + "V >r >V/V @s #Z 2[CU -Z +[MeL[ 5Z X G\\ :W!V 3W@W 7V!W AZ4[ 1WEW LW@W 1W7s,X-" + "Y JX8t$\\ 7Z'Z%Z'Z$Z'Y%Z'Z$Z'Y%Z'Z4Z1Z 6\\&S NZ !Z Z !Z >Z !Z !Z \"Z :Z,]\"Y3ZNY$\\,\\#\\,\\$\\,\\$\\-\\$\\," + "\\ N\\4[ ]-\\![/Z LZ/[ N[/[ N[/[ 7Z 2Z #Y-Y NY4\\ HY5] IY4\\ GY4\\ HY4\\ HY4\\.Z5` 2Z $Z !Z !Z !Z =Y Y NX Y " + "3Z4Z GX0X H[5[ GZ4Z GZ4Z H[5[ GZ4[ 6\\ 5_9[ HZ5[ GZ5[ FY5[ FY5\\ :YNZ :\\4Z ;YNY )YAXAZ\"Z+Z!Z*Y Y*Z\"Z+Z 8" + "X $YMY %[ F^ '\\FSF\\ LcGRGc >f ,c :X.Y FZ7Y BY8Y 7e >[ %[1S -Y 'X@X ;Q:TCZ CX:X=X" + "5[.] /Y HY HX NZ GZ 'X +[8Z 0Z 4\\ 0[ 'Z M\\ CZ6[ 9Z 2[3[ '[ 0Y Y ?f f BX DW=\\C_J[.Z&Z\"Z0\\ " + "J\\(T'Z._ JZ MZ *])Z'Z(Z :Z \"Z 4Z6] BZ 2Y JY(Y3e#\\.\\ JZ )]/\\ NZ.[ NQ'[ 6Y 6[0[ =ZNZ CYNX4XNY!Z4[ 5Z 8[ @X" + " AX MY NY5] F]6Z DZ &Z5] G[ AY 2[8^ GY1Y 5Y NX 0X>[ ,Y FY3Y2Y+Y1Y H[6[ G]6Z IZ5\\ ;Y 6Y 8Y -Z6\\ ;Z" + "MZ =b=b EZ@Z 3d 5[ AY X Y L[:\\ IZ;` D[4Z FXZ5[ EY #Y1Y 9c 7Z5Y GZ5\\$[>^>['[EYE[ FY9Y HZBXCZ J]5Z " + "IZ5Z 1Y 1Y8Z LZ&Z J[ \"Z &\\8] E| KZ(Z :Z :]/] JU 9X 9T

q \"Z 1ZCU -Z ,[JaI[ 6Z X F\\ :W#V 1" + "V?V 7W#W @[5[ 1WEW LV?V 1X7s,W-Y JX7t%\\ 6Z&Z&Z'Z%Z&Z&Z'Z%Z&Z&Z&Y4Y0Z 5\\(T NZ !Z Z " + "!Z >Z !Z !Z \"Z :Z.^!Y3e#\\.\\!\\.\\#].\\#]/]#\\.\\ N\\2[ ]/]![0[ L[0[ M[0[ N\\1[ 6Z 2Z #Y-Y NY5] HY5] IZ6] GY" + "5] HY5] HY5]-Y5a 3[ %[ \"[ \"[ \"[ >Y Y NX Y 3Z5[ GX0X GZ5Z F[6[ G[6[ GZ5Z F[5Z 5\\ 4^9Z FY6\\ FY6\\ FY6\\ " + "FY6] 9c 9]6Z :d )[CXBZ Z-Z NZ-[ [-Z Z-Z 7X $YNZ %Z D] $VCSDW G`FSG` ;d +c :X.Y F[9Z CZ8Y 6d =\\ " + " '\\3T -Z (W?X ;Sd c @Z EW<_Ks-Z&Z\"Z1] J^,V'Z/_ IZ MZ )]*Z'Z(Z :Z \"Z 4Z5] CZ 2Y JY(Y2d#]0\\ IZ (]1] NZ-" + "Z NS*\\ 6Y 6[1[ Z 4c 5[ @Y X Y HS3V FZZ%ZEYF[ EY9Y GZCXD[ J^7Z H[7[ 1Y 1Z:Z KZ&Z K[ !Z %];] Bx IZ(Z :Z 9]1] HS 8X 8R :n :R+R U 6W%W ?[6\\ 1WEW LU>U 0W6s-X.X HW6t&\\ 5Z&Z'Z" + "%Z&Z&Z'Z%Z&Z&Z&Z&Z6Z0Z 4],V NZ !Z Z !Z >Z !Z !Z \"Z :Z0`!Y2d\"\\0]!]0\\!]0\\!]1]!]1] \\0[ ]1] N[2\\ L\\2[ L\\" + "2[ L[1[ 6Z 2Z #Y.Y MZ7^ HY6^ HY6] GZ6] HZ7^ HZ7^-Y6c 3[ %[ \"[ \"[ \"[ ?Y Y NX Y 3[7[ FX0X G[7[ E[7[ FZ7[ F" + "[7[ E[7[ 5\\ 4]9[ FZ8] FZ8] FZ8] FZ7] 9c 9]7[ 9b '[DXD[ N[/Z LZ/[ M[0[ N[/Z 6X $d %Z C\\ ?S 2\\ETD" + "\\ 9b )a 9X.Y E[<[ BY7Z 7c ;\\ '\\5U -Z (W?W :U>TE[ CX8X?X3\\3b 1Y IY GX NZ GZ (" + "X )[;[ /Z 5[ %Q-\\ &Z BQ/] AZ9\\ 9Z 0[6\\ (\\ /Z \"[ ;a ` =Z EX[ 4b 6[ ?Y X Y " + "FZ=b E]7Z EX=Z <[9\\ D[ %Y1Y 8a 6Y3Y H\\8]#[@WNW@[%[FYG\\ EY9Y G[DXD[ J_9[ G[9[ /Y 1Z;Z LZ%Z L\\ !Z $]=\\ >t GZ" + "(Z :Z 8]3] FQ 7X 7P 8l 8P)P :m Z 0[EU -Z .[?P?[ 8Z X D[ 9W(W -T\\8] 1WEW " + " LSZ !Z !Z \"Z :Z2a Y2d\"^3] N]3^ ]3" + "] N]3] N]3] \\.[!^3] M\\4\\ J\\4\\ K\\4\\ L\\4\\ 5Z 2Z #Y.Y MZ8_ HZ8_ HZ8^ FZ8^ HZ8_ HZ8_-Z8e-Q)\\ &\\-Q G\\-Q " + "G\\-Q G\\-Q 5Y Y NX Y 2[9\\ FX0X F[9[ D\\9[ E[8[ E[9[ D\\9[ 4\\ 3[9[ EZ9^ FZ9^ FZ9^ F[9^ 9b 8^9[ 8b &[2[" + " L\\3\\ K[2[ K[2[ L\\3\\ 6X #c &Z B\\ ?S /UATAT 4a '_ 8X.Y E\\>\\ BY6Y 7c :] (\\7V " + "-Z )X@X :W@TF[ BW7X?X3]6e 1X IY GX NZ GZ (X ([=[ .Z 6[ $S1^ &Z BS3^ @\\<\\ 8Z 0]9] FR6] .Z \"[ 8^ " + " ^ ;Z DW;lMc+Z$Z#Z4_ G_2Y'Z5c GZ MZ '^/\\'Z(Z :Z \"Z 4Z3] EZ 2Y JY(Y1c!^6^ HZ '^6^ LZ,Z X1] 5Y 5]6\\ :c Ab2a" + "\"Z0[ 7Z ;\\ >X @X NY MZ:` F_:[ B\\3P D[;` E\\1S 7Y 0\\>a GY1Y 5Y NX 0X;\\ 0Y FY3Y2Y+Y1Y F[:[ E_;\\ " + "F[;_ ;Y *S1Y 6Z .[;_ :e ;`;` G[<[ 5a 6[ >Y X Y F[?YNY F_:[ DX?Z :[;\\ B[ &Y1Y 8a 7Z3Y H]:^#\\BXNWA[#[" + "GYH\\ DY9Y F\\FXF\\ I`;[ F\\;\\ /Z 2[=Z KZ$Z N\\ Z #^A] :n DZ(Z :Z 7]5] +X Mj (k NZ 0\\FUBP ;Z /[,[ " + "9Z X CZ 8X+W *R;R 4X+X =]:^ 1WEW LR;R /X5s.W.X GW5t(\\ 4Z$Z(Z%Z'Z$Z(Z$Y'Z$Z(Z$Z" + "8Z/Z 3_2Y NZ !Z Z !Z >Z !Z !Z \"Z :Z5c NY1c!^6^ L^6^ M^6^ M]5] M^6^ \\,[#a7^ K\\6] I\\6\\ J]6\\ J\\6] 5Z 2Z #" + "Y/Z LZ:` H[:` H[:_ FZ:` GZ:` GZ:`-[:YN\\0S(\\4Q C\\0S F\\0S F\\0S F\\0S 5Y Y NX Y 1[:[ EX0X F\\;\\ C\\;[ C[:" + "[ D\\;\\ C\\;\\ 4\\ 3[:\\ DZ;_ EZ;_ EZ;_ EZ;` 8a 8_;\\ 7a %\\6\\ J\\5\\ I\\6\\ I\\6\\ J\\5\\ 5X #c 'Z " + "@[ @T JT _ %] 7X.Y D^D^ BZ6Y 6b 9_ *];X -Z )X@X :ZCTH] CX7YAX1^:h 2Y JY GX NZ" + " GZ (X (\\?\\ .Z 7\\ $W7_ %Z BV8` ?\\>] 9[ /];] ET9] -Z \"[ 5[ [ 8Z DX;jLb*Z$Z#Z7a E`7\\'Z9f FZ MZ &`4^" + "'Z(Z :Z \"Z 4Z2] FZ 2Y JY(Y1c _:_ GZ &_9^ KZ,[![6^ 4Y 4]9] 8b @a2a#[/Z 7Z ;[ =X @X NY M[\\ @]7R" + " D\\=a E]4U 7Y /]Bc GY1Y 5Y NX 0X:\\ 1Y FY3Y2Y+Y1Y E\\>] E`=\\ E\\=` ;Y *U5[ 6[ /\\>a 9c :_:` GZ:Z 4` 6[ >Y " + "X Y E[AYMZ G`<[ CX@Z 9\\=\\ A\\3Q EY1Y 7` 7Y2Z I^<_\"[BWMXC\\#]IYI\\ CY9Y F]GXG] Ia=\\ E\\=\\ .[ 2[?Z J" + "Z$Z N[ NZ \"^C^ 7g @Z(Z :Z 7_9_ +X Lh &i MZ /]HUDR ;Z .Y*Y 8Z X BZ 8Y/X (Q:Q 2X/Y " + " <^<` 2WEW LQ:Q .W MV(X/X GX NW\"\\ 3Z$Z)Z#Z(Z$Z)Z#Z(Z$Z)Z#Z8Z/Z 2`7\\ NZ !Z Z !Z >Z !Z !Z \"Z :" + "Z9f MY0b _:_ J_:_ K_:_ L_9_ L_9^ N[*[$c:^ J^:^ H^:^ I^:] H]9] 4Z 2Z #YIP7[ L[] C\\=\\ A\\=\\ 3\\ 2\\=\\ C[=` E[=` E[=" + "` E[=a 8a 8`=\\ 6` #]:] H]9] G]:] G]:] H]9] 4W !a 'Z ?Z ?U KT N] $] 7X.Y Cv AZ6Z 7a 7a " + " -_?Z -Z )W?X :^GTK_ CX5XAX0_>k 3Y JX FX NZ GZ )Y ']C] ?} I~S IZ=b %Z BZ>a =]B^ 8Z ._?^ DX" + "@_ ,Z \"[ 3Y X 5Z CW:gJ`)Z\"Z$~T Cb=_'~W E~S FZ %b:a'Z(Z :Z \"Z 4Z1] G~Q)Y JY(Y0b N`>` FZ %a?` JZ+Z!^_ 8b @a2a$[.[ 8Z <~` AX ?X Y L\\@c Fb@] ?^` H`>` I`>` Ja?a Ja?` LY(Y$f?` H_>_ F_>_ G_>_ H_>" + "_ 3Z 2Z #YIS;[ K\\?c G\\?c G\\?b E\\@c F\\@c G\\?c,\\?[L^9Y'^} I~S I~ $Z B| ;^F_ 7Z -aEa Dv +Z \"[ 0V U 2Z CX9dI^'Z\"Z$~S AfGd'~U C~S FZ $gGg&Z(Z :Z \"Z 4Z0] H" + "~Q)Y JY(Y0b McGd EZ $dGc IZ+[\"cEd 3Y 3cGc 7a ?`1a$Z,[ 9Z =~a AX ?X Y L^DZNY FYNZF_ =`CY B^EZNY CaB] 7" + "Y .qMY GY1Y 5Y NX 0X8\\ 3Y FY3Y2Y+Y1Y D_F_ CYNYE_ B^EZNX ;Y *]A^ 4k >^G[NY 8a 9_9^ H[8[ 5^ 6~P 2Y X Y " + " D^H[La NfH` AYD[ 6^E_ ?`?X EY1Y 7_ 7Y0Y IcFk(]HZLZI^ `Nk BY9Z E~Q GYNZE^ B_E_ ,e ;]G] J~c!~T FZ 3oDo @Z :Z(Z :" + "Z 5dGd )X Jd \"e KZ -`MUKY H~U IU&U 6Z X AY 5Z7Z LZ7Z ;~d 3cFk 8WEW " + " BW LV)X0X FW LW$\\ 2Z\"Z+[#Z)Z\"Z*Z\"Z*Z\"Z*Z\"Z:Z.~T*fGd N~T J~T I~S I~S 7Z !Z !Z \"Z :~U JY/a MdGc FcGd GcGd" + " HdGd HdGc JW&W$kGc FbFb DbFb FcFb FcGc 3Z 2Z #YIWB] I^DZNY F]D[NY F]D[NX E^DZNY F^DZNY F^E[NY+]D]J`@]&`BY AaA]" + " DaA] DaA] DaA] 5Y Y NX Y /_F_ CX0X D_E_ ?_F_ ?_F_ @_E_ ?_F_ 7aF_ @^FZMX D^FZMX D_GZMX D_G[NY 7_ 7YNYE_ 4^" + " dLd CdMd BdLd CdLd DeMd 2X !` %X =Y ?U LV MZ !Y 5X.Y As AZ4Y 6` 5~] )x -Z " + "*X@X 9} BX3YFZ-{L] 4Y LY FX NZ GZ )X $t >} I~S I} #Z B{ :v 7[ ,{ Cu *Z \"[ -S S 0Z BW8aG[%[\"Z$~R" + " ?~S'~T B~S FZ #~V%Z(Z :Z \"Z 4Z/] I~Q)Y JY(Y/a L~ DZ #~ HZ*Z\"~R 2Y 2} 5` ?`0_$[+Z 9Z =~a AX ?X Y KsN" + "Y FYNr ;u AqMY B{ 7Y -oLY GY1Y 5Y NX 0X7\\ 4Y FY3Y2Y+Y1Y Cv BYNr ArMX ;Y *y 2j >qMY 8a 8^9^ I[6Z 5^ 6~P 2Y X " + " Y CpK` N} ?YF[ 5w =x EY1Y 6] 7Z0Z J~Y(nJm M{ AY9\\ F~ FYMq @w *d ;r J~d!~T FZ 3oDo @Z :Z(Z :Z 4~ 'X " + " Ib c JZ ,u H~U HS$S 5Z X AY 4\\>\\ I]>\\ :~d 3~Y 8WEW CW KV)W0X FX LW" + "$[ 2[\"Z+Z!Z*Z\"Z+Z!Z*Z!Z,Z!Z:Z.~T)~S N~T J~T I~S I~S 7Z !Z !Z \"Z :~T IY/a L~ D~ E~ F~ E~ HU$U$~X D| B| D} D} " + "2Z 2Z #YIr HrMY FsMY FsMX DsNY ErMY FsMY+uH|%v @| C| C| C| 5Y Y NX Y .v BX0X Cw =w >v >w =w 8{ ?qMX CqMX C" + "qMX CqMY 6] 6YNr 3^ My Ay @y @z Ay 1X _ $V X !" + "Y JqMY FYMp 9t ApLY Az 7Y ,mKY GY1Y 5Y NX 0X6\\ 5Y FY3Y2Y+Y1Y Bt AYMp ?pLX ;Y *x 1j =oLY 8a 8]8^ IZ4Z 6" + "] 5~P 2Y X Y CoI_ N} ?[K] 3u ;w EY1Y 6] 7Y.Y JvM_'mJm Ly @Y9b K| EYLp ?u (c :p I~e\"~T FZ 3oDo @Z :Z(Z" + " :Z 2{ &X H` Ma IZ +t H~U GQ\"Q 4Z X AY 2aLb FaKa 8~d 3YNlN_ 8WEW " + "DX KV*W0o-W KW%[ 1Z Z,Z!Z+Z Z,Z!Z+Z Z,Z!Z;Z-~T'~P M~T J~T I~S I~S 7Z !Z !Z \"Z :~R GY.` K| B| C{ B{ B{ FS\"S$YM" + "{ Bz @z B{ B{ 1Z 2Z #YIq GqLY EqLY EqLX CqMY ErMY EqLY*sF{$u ?{ B{ B{ B{ 5Y Y NX Y -t AX0X Bu ;u pLX CpLX CpLX BoLY 6] 6YMp 1] Lv >w =v =v >w 0X _ #T ;X ?W MV LW LV 4X.Y ?n >Y3Z 7_ 1~Z " + " 't +Z *W?X 8y @X1j)vG] 5X MY EX NZ GZ *X !p <} I~S Iz Z By 6r 5Z )w As (Z \"[ " + " 5Z AX HZ Z%~ 9|$~P >~S FZ ~P\"Z(Z :Z \"Z 4Z-] K~Q)Y JY(Y.` Jy AZ x EZ)Z#~P 0Y /x 3_ =_0_%Z([ ;Z =~a AX " + ">X !Y JpLY FYLn 7s @nKY @y 7Y +kJY GY1Y 5Y NX 0X5\\ 6Y FY3Y2Y+Y1Y Ar @YLn =nKX ;Y *w /i x ?x @y 0Z 2Z #YIp EoKY DoKY DoKX BoLY DpLY DoKY)qCy#t =y @y @y @y 5Y Y NX Y ,r @X0X As 9s :r :s 9s 7z <" + "nKX BnKX BnKX BnKY 6] 6YLn 0\\ Jt ;s :t ;t ;s .X N] !R 9V >W NX LU KU 3X.Y >l =Y2Y 7_ /~X " + " %p )Z *W?W 4u @X/i(tE] 6Y NX DX NZ GZ *X m :} I~S Iy NZ Bw 2o 5Z 'u @r 'Z \"Z " + " 4Z AY J[ Z%} 6x\"} <~S FZ N| Z(Z :Z \"Z 4Z,] L~Q)Y JY(Y.` Hv @Z Mu DZ)[$~ /Y .u 0^ =^/_&['Z ;Z =~a AX >X" + " !Y InKY FYKl 5r ?lJY >w 7Y )hIY GY1Y 5Y NX 0X4\\ 7Y FY3Y2Y+Y1Y @p ?YKl ;lJX ;Y *v -h ;kJY 7_ 7]7\\ J[2" + "[ 7\\ 5~P 2Y X Y AkE] Nz :i .p 7u EY1Y 5[ 7Y,Y KYMiL_%iGj Hu >Y8a Hv BYJl :p $a 7k H~f\"~T FZ 3oDo @Z " + ":Z(Z :Z /u #X F\\ I] GZ )r H~U *Z X AY /p >o 4~d 3YMiK^ 8WEW EX " + "JV+W/o/X JW&Z 0[ Z-Z NZ-[ [.Z NZ,Z NZ.Z NZ=Z,~T$x I~T J~T I~S I~S 7Z !Z !Z \"Z :| BY-_ Hv p %Z \"Z " + " 4Z @X JZ MZ&{ 3u z 9~S FZ Lx MZ(Z :Z \"Z 4Z+] M~Q)Y JY(Y-_ Fr >Z Lr BZ(Z!y -Y -s /] <^.]&[&[ m >YJj 8iIX ;Y *u *f :iIY 7_ 6\\7" + "\\ K[0Z 6Z 4~P 2Y X Y ?hC\\ NYMm 8f +m 3s EY1Y 5[ 8Z,Y KYLgJ^$gEh Fs =Y8a Fr @YIi 7m !` 6i G~g#~T FZ 3o" + "Do @Z :Z(Z :Z .s \"X EZ G[ FZ 'p H~U *Z X AY ,k :k 2~d 3YLgJ^ 8WEW " + " EW IV,X/o/W IW&Z 0Z MZ/[ NZ-Z MZ.Z N[.Z MZ.Z MZ>Z,~T\"t G~T J~T I~S I~S 7Z !Z !Z \"Z :y ?Y-_ Fr 8r 9r :s :r " + " AXEr :r 8r :s :s -Z 2Z #YIn AkIY BkIY BkIX @jIY BkIY BkIY'l=t Mq :t ;t ;t ;t 3Y Y NX Y *m =X0X >m 3m 5n 5m" + " 3m 6XLm 7iHX @iHX @jIX @jIY 5[ 5YJj -Z El 3k 2l 3l 4l *X N\\ 5U ?Y Y KR HQ 1X.Y 9b 9Y1Z 7" + "] )~S \"j &Z +X@X -h ;X+c!l?\\ 6X Y DX Z FZ +X Kh 8} I~S Fr JZ As ,i 3[ $n ;m " + "#Z \"Y 3Z ?X KZ MZ&x -p Mu 4~S FZ Js JZ(Z :Z \"Z 4Z*] N~Q)Y JY(Y-_ Dn gB[ NYLj 5d (j 0q EY1Y 5Z 7Y+Z LYKdG]\"dBd Bo ;Y7` Dn >YHg 4i L^ 4e " + "E~g#~T FZ 3oDo @Z :Z(Z :Z ,n NX DX EY EZ %m G~U *Z X BZ )e 4e /~d 3YKeH] 8" + "WEW FW HV,W.o0X IW'Z /Z MZ/Z LZ.Z MZ/[ MZ.Z MZ/[ MZ>Y+~T p E~T J~T I~S I~S 7Z !Z !Z \"Z :u ;Y,^ Dn 4" + "n 5n 6o 6n @XBm 5n 4n 6o 6o +Z 2Z #YIl =gGY AhGY AhGX ?hHY @hHY @gGY%i:o Hm 7p 6o 6p 7p 1Y Y NX Y (i ;X0X " + "fGX >fGX >fGY 4Y 4YHf +Z Bg /g .g -g /g (X M[ 5T ?Z !Z JP 'X.Y 5" + "[ 6Y0Y 7] &~P Ne $Z +W?X '] 6W)a Mh<\\ 7Y !X CX Y EZ +X Id 6} I~S Cm HZ =l 'e " + "1Z i 6h !Z #Z 3Z ?Y M[ M['s &k Jo .~S FZ Gm GZ(Z :Z \"Z 4Z)] ~Q)Y JY(Y,^ Bi 9Z Gl AZ'Z Jm (Y (i )\\ " + ";].]'[#Z =Z =~a AX =X \"Y DdFY FYFb *h 6cFY 8j 0Y \"YAY GY1Y 5Y NX 0X1\\ :Y FY3Y2Y+Y1Y ;f :YFb 1cFX ;Y" + " $k ` 7cFY 6] 5[5Z KZ-[ 8Y 3~P 2Y X Y ;b=X NYJe 0` $e +l BY1Y 4Y 7Y*Y LYIaE[ b@a >k 9Y6_ Ah ;YFc 0e " + "FZ 2a D~i$~T FZ 3oDo @Z :Z(Z :Z )i LX CV CW DZ #h D~U *Z X -R9Z #[ *[ *~d 3" + "YIaE\\ 8WEW GX HV-W-o0W HW'Z 0Z L[0Z LZ/[ LZ0Z LZ/[ LZ0Z LZ?Z+~T Lj B~T J~T I~S I~S 7Z !Z !Z \"Z :o " + "5Y,^ Ai /h 0i 0i 0i >W?i 1j 0j 1j 1i (Z 2Z #YGh 9cEY ?dEY ?dEX =dFY >dFY >cEY#d5j Ch 1j 1j 1j 1j -Y Y NX Y" + " &e 9X0X :e ,f -f -e ,f 4XFe 0cEX a NU CZ N` 9X -T<[ " + " LYG]BX 5WEW %U HW NX MX GZ (d +b (b )b )a )b 9V;a " + ")c *c *c *c =a 4_ &^ %^ $^ &_ &_ :_/c RM] !R Z 5\\ " + " 9X ;X $Y HY NY 0Y 'X NY BY X !Y " + ":Y 8Y 4Y *Y 1Y EX 3Y CZ IU 3X -p " + " IY 8WEW #V &Z MV " + " 0U 'P ;Y 2Y >Z 8X " + " MT *X &X 9X DX " + " 5X ?\\%W ?Z 4\\ :X ;X $Y " + " IZ NY 0Y 'X NY BZ !X !Y :Y 8Y 4Y *Y 1Y EX 3Y " + " CZ IU 3X -o HY 8WEW \"V " + " 'Z LU 0V " + " CZ 2Y >Y 7X " + " MT )X 'X 9X DX 5W <\\(X ?" + "Z 3\\ ;Y e GX 2f KZ LY 0Y 'X !Y >" + "\\ %X &] 9Y 8Y 4Y *Y 1Y EX 3Y CZ IU 3" + "X $^ @Y 8WEW !V '\\:V ;V " + " 1W GZ 0Y @Z " + " FWHX LT 'X +W 7W " + " V 5b?c A[ -\\ ?e !f " + " f /X 0g 9Y 8Y 4Y *Y " + " 1Y EX 3Y CZ IU 3X 5Y " + " NV &\\=X ;V " + "1W GY /Y AZ EWHX " + " LT &W ,X 7V V 3~T " + " A] ,\\ @e !f d " + " %e -Y Nd @c " + " (m @c " + " +u $b -Y 'X 0d 2^ /X 0_ 1Y 8Y 4Y *Y " + " 1Y EX 3Y CZ IT 2X 5Y " + "-c !q Hd >c " + " $d ,Y Nd ?b " + " %g =" + "b *t #a ,Y 'X 0d " + " ,X /X 0Y +Y 8Y 4Y *Y 1Y EX 3Y CZ '" + "X 5Y -c Nm Fc " + " =c $c +Y Nc " + " >a " + " M\\ 8a \"~Y 1" + "r !` +Y 'X 0c 1X 1Y 8Y 4Y *Y 1Y EX 3Y " + " CZ &W 5Y -b Lj " + " Db std::printf(). + \note If configuration macro \c cimg_strict_warnings is set, this function throws a + \c CImgWarningException instead. + \warning As the first argument is a format string, it is highly recommended to write + \code + cimg::warn("%s",warning_message); + \endcode + instead of + \code + cimg::warn(warning_message); + \endcode + if \c warning_message can be arbitrary, to prevent nasty memory access. + **/ + inline void warn(const char *const format, ...) { + if (cimg::exception_mode()>=1) { + char *const message = new char[16384]; + std::va_list ap; + va_start(ap,format); + cimg_vsnprintf(message,16384,format,ap); + va_end(ap); +#ifdef cimg_strict_warnings + throw CImgWarningException(message); +#else + std::fprintf(cimg::output(),"\n%s[CImg] *** Warning ***%s%s\n",cimg::t_red,cimg::t_normal,message); +#endif + delete[] message; + } + } + + // Execute an external system command. + /** + \param command C-string containing the command line to execute. + \param module_name Module name. + \return Status value of the executed command, whose meaning is OS-dependent. + \note This function is similar to std::system() + but it does not open an extra console windows + on Windows-based systems. + **/ + inline int system(const char *const command, const char *const module_name=0, const bool is_verbose=false) { + cimg::unused(module_name); +#ifdef cimg_no_system_calls + return -1; +#else + if (is_verbose) return std::system(command); +#if cimg_OS==1 + const unsigned int l = (unsigned int)std::strlen(command); + if (l) { + char *const ncommand = new char[l + 24]; + std::memcpy(ncommand,command,l); + std::strcpy(ncommand + l," >/dev/null 2>&1"); // Make command silent + const int out_val = std::system(ncommand); + delete[] ncommand; + return out_val; + } else return -1; +#elif cimg_OS==2 + PROCESS_INFORMATION pi; + STARTUPINFOA si; + std::memset(&pi,0,sizeof(PROCESS_INFORMATION)); + std::memset(&si,0,sizeof(STARTUPINFO)); + GetStartupInfoA(&si); + si.cb = sizeof(si); + si.wShowWindow = SW_HIDE; + si.dwFlags |= SW_HIDE | STARTF_USESHOWWINDOW; + const BOOL res = CreateProcessA((LPCSTR)module_name,(LPSTR)command,0,0,FALSE,0,0,0,&si,&pi); + if (res) { + WaitForSingleObject(pi.hProcess,INFINITE); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return 0; + } else { + char* lpMsgBuf; + + // Get the error message. + DWORD errorCode = GetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0,errorCode,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPSTR)&lpMsgBuf,0,0); + cimg::warn("cimg::system() : Command '%s' (module name '%s) failed with error %lu: %s", + module_name==0?"(null)":module_name, + command==0?"(null)":command, + errorCode,lpMsgBuf); + return -1; + } +#else + return std::system(command); +#endif +#endif + } + + //! Return a reference to a temporary variable of type T. + template + inline T& temporary(const T&) { + static T temp; + return temp; + } + + //! Exchange values of variables \c a and \c b. + template + inline void swap(T& a, T& b) { T t = a; a = b; b = t; } + + //! Exchange values of variables (\c a1,\c a2) and (\c b1,\c b2). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) { + cimg::swap(a1,b1); cimg::swap(a2,b2); + } + + //! Exchange values of variables (\c a1,\c a2,\c a3) and (\c b1,\c b2,\c b3). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3) { + cimg::swap(a1,b1,a2,b2); cimg::swap(a3,b3); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a4) and (\c b1,\c b2,...,\c b4). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4) { + cimg::swap(a1,b1,a2,b2,a3,b3); cimg::swap(a4,b4); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a5) and (\c b1,\c b2,...,\c b5). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4); cimg::swap(a5,b5); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a6) and (\c b1,\c b2,...,\c b6). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5); cimg::swap(a6,b6); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a7) and (\c b1,\c b2,...,\c b7). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6); cimg::swap(a7,b7); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a8) and (\c b1,\c b2,...,\c b8). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7, T8& a8, T8& b8) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7); cimg::swap(a8,b8); + } + + //! Return the endianness of the current architecture. + /** + \return \c false for Little Endian or \c true for Big Endian. + **/ + inline bool endianness() { + const int x = 1; + return ((unsigned char*)&x)[0]?false:true; + } + + //! Reverse endianness of all elements in a memory buffer. + /** + \param[in,out] buffer Memory buffer whose endianness must be reversed. + \param size Number of buffer elements to reverse. + **/ + template + inline void invert_endianness(T* const buffer, const cimg_ulong size) { + if (size) switch (sizeof(T)) { + case 1 : break; + case 2 : { + for (unsigned short *ptr = (unsigned short*)buffer + size; ptr>(unsigned short*)buffer; ) { + const unsigned short val = *(--ptr); + *ptr = (unsigned short)((val>>8) | ((val<<8))); + } + } break; + case 4 : { + for (unsigned int *ptr = (unsigned int*)buffer + size; ptr>(unsigned int*)buffer; ) { + const unsigned int val = *(--ptr); + *ptr = (val>>24) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | (val<<24); + } + } break; + case 8 : { + const cimg_uint64 + m0 = (cimg_uint64)0xff, m1 = m0<<8, m2 = m0<<16, m3 = m0<<24, + m4 = m0<<32, m5 = m0<<40, m6 = m0<<48, m7 = m0<<56; + for (cimg_uint64 *ptr = (cimg_uint64*)buffer + size; ptr>(cimg_uint64*)buffer; ) { + const cimg_uint64 val = *(--ptr); + *ptr = (((val&m7)>>56) | ((val&m6)>>40) | ((val&m5)>>24) | ((val&m4)>>8) | + ((val&m3)<<8) |((val&m2)<<24) | ((val&m1)<<40) | ((val&m0)<<56)); + } + } break; + default : { + for (T* ptr = buffer + size; ptr>buffer; ) { + unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T); + for (int i = 0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe)); + } + } + } + } + inline void invert_endianness(bool* const, const cimg_ulong) {} + inline void invert_endianness(unsigned char* const, const cimg_ulong) {} + inline void invert_endianness(char* const, const cimg_ulong) {} + + //! Reverse endianness of a single variable. + /** + \param[in,out] a Variable to reverse. + \return Reference to reversed variable. + **/ + template + inline T& invert_endianness(T& a) { + invert_endianness(&a,1); + return a; + } + + // Conversion functions to get more precision when trying to store unsigned ints values as floats. + inline unsigned int float2uint(const float f) { + int tmp = 0; + std::memcpy(&tmp,&f,sizeof(float)); + if (tmp>=0) return (unsigned int)f; + unsigned int u; + // use memcpy instead of assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&u,&f,sizeof(float)); + return ((u)<<2)>>2; // set sign & exponent bit to 0 + } + + inline float uint2float(const unsigned int u) { + if (u<(1U<<19)) return (float)u; // Consider safe storage of unsigned int as floats until 19bits (i.e 524287) + float f; + const unsigned int v = u|(3U<<(8*sizeof(unsigned int)-2)); // set sign & exponent bit to 1 + // use memcpy instead of simple assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&f,&v,sizeof(float)); + return f; + } + + //! Return the value of a system timer, with a millisecond precision. + /** + \note The timer does not necessarily starts from \c 0. + **/ + inline cimg_uint64 time() { +#if cimg_OS==1 + struct timeval st_time; + gettimeofday(&st_time,0); + return (cimg_uint64)st_time.tv_sec*1000 + (cimg_uint64)st_time.tv_usec/1000; +#elif cimg_OS==2 + ULARGE_INTEGER ul; + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + ul.LowPart = ft.dwLowDateTime; + ul.HighPart = ft.dwHighDateTime; + return (cimg_uint64)ul.QuadPart/10000; +#else + return 0; +#endif + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_uint64 tictoc(const bool is_tic); + + //! Start tic/toc timer for time measurement between code instructions. + /** + \return Current value of the timer (same value as time()). + **/ + inline cimg_uint64 tic() { + return cimg::tictoc(true); + } + + //! End tic/toc timer and displays elapsed time from last call to tic(). + /** + \return Time elapsed (in ms) since last call to tic(). + **/ + inline cimg_uint64 toc() { + return cimg::tictoc(false); + } + + //! Sleep for a given numbers of milliseconds. + /** + \param milliseconds Number of milliseconds to wait for. + \note This function frees the CPU resources during the sleeping time. + It can be used to temporize your program properly, without wasting CPU time. + **/ + inline void sleep(const unsigned int milliseconds) { +#if cimg_OS==1 + struct timespec tv; + tv.tv_sec = milliseconds/1000; + tv.tv_nsec = (milliseconds%1000)*1000000; + nanosleep(&tv,0); +#elif cimg_OS==2 + Sleep(milliseconds); +#else + cimg::unused(milliseconds); +#endif + } + + inline unsigned int wait(const unsigned int milliseconds, cimg_uint64 *const p_timer) { + if (!*p_timer) *p_timer = cimg::time(); + const cimg_uint64 current_time = cimg::time(); + if (current_time<*p_timer || current_time>=*p_timer + milliseconds) { *p_timer = current_time; return 0; } + const unsigned int time_diff = (unsigned int)(*p_timer + milliseconds - current_time); + *p_timer = current_time + time_diff; + cimg::sleep(time_diff); + return time_diff; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \return Number of milliseconds elapsed since the last call to wait(). + \note Same as sleep() with a waiting time computed with regard to the last call + of wait(). It may be used to temporize your program properly, without wasting CPU time. + **/ + inline unsigned int wait(const unsigned int milliseconds) { + cimg::mutex(3); + static cimg_uint64 timer = cimg::time(); + cimg::mutex(3,0); + return cimg::wait(milliseconds,&timer); + } + + // Custom random number generator (allow re-entrance). + inline cimg_uint64& rng() { // Used as a shared global number for rng + static cimg_uint64 rng = 0xB16B00B5U; + return rng; + } + + inline unsigned int _rand(cimg_uint64 *const p_rng) { + *p_rng = *p_rng*1103515245 + 12345U; + return (unsigned int)*p_rng; + } + + inline unsigned int _rand() { + cimg::mutex(4); + const unsigned int res = cimg::_rand(&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline void srand(cimg_uint64 *const p_rng) { +#if cimg_OS==1 + *p_rng = cimg::time() + (cimg_uint64)getpid(); +#elif cimg_OS==2 + *p_rng = cimg::time() + (cimg_uint64)_getpid(); +#endif + } + + inline void srand() { + cimg::mutex(4); + cimg::srand(&cimg::rng()); + cimg::mutex(4,0); + } + + inline void srand(const cimg_uint64 seed) { + cimg::mutex(4); + cimg::rng() = seed; + cimg::mutex(4,0); + } + + inline double rand(const double val_min, const double val_max, cimg_uint64 *const p_rng) { + const double val = cimg::_rand(p_rng)/(double)~0U; + return val_min + (val_max - val_min)*val; + } + + inline double rand(const double val_min, const double val_max) { + cimg::mutex(4); + const double res = cimg::rand(val_min,val_max,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline double rand(const double val_max, cimg_uint64 *const p_rng) { + const double val = cimg::_rand(p_rng)/(double)~0U; + return val_max*val; + } + + inline double rand(const double val_max=1) { + cimg::mutex(4); + const double res = cimg::rand(val_max,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline double grand(cimg_uint64 *const p_rng) { + double x1, w; + do { + const double x2 = cimg::rand(-1,1,p_rng); + x1 = cimg::rand(-1,1,p_rng); + w = x1*x1 + x2*x2; + } while (w<=0 || w>=1.); + return x1*std::sqrt((-2*std::log(w))/w); + } + + inline double grand() { + cimg::mutex(4); + const double res = cimg::grand(&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline unsigned int prand(const double z, cimg_uint64 *const p_rng) { + if (z<=1.e-10) return 0; + if (z>100) return (unsigned int)((std::sqrt(z) * cimg::grand(p_rng)) + z); + unsigned int k = 0; + const double y = std::exp(-z); + for (double s = 1.; s>=y; ++k) s*=cimg::rand(1,p_rng); + return k - 1; + } + + inline unsigned int prand(const double z) { + cimg::mutex(4); + const unsigned int res = cimg::prand(z,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + //! Cut (i.e. clamp) value in specified interval. + template + inline T cut(const T& val, const t& val_min, const t& val_max) { + return val<=val_min?(T)val_min:val>=val_max?(T)val_max:val; + } + + //! Bitwise-rotate value on the left. + template + inline T rol(const T& a, const unsigned int n=1) { + return n?(T)((a<>((sizeof(T)<<3) - n))):a; + } + + inline float rol(const float a, const unsigned int n=1) { + return (float)rol((int)a,n); + } + + inline double rol(const double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + + inline double rol(const long double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half rol(const half a, const unsigned int n=1) { + return (half)rol((int)a,n); + } +#endif + + //! Bitwise-rotate value on the right. + template + inline T ror(const T& a, const unsigned int n=1) { + return n?(T)((a>>n)|(a<<((sizeof(T)<<3) - n))):a; + } + + inline float ror(const float a, const unsigned int n=1) { + return (float)ror((int)a,n); + } + + inline double ror(const double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + + inline double ror(const long double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half ror(const half a, const unsigned int n=1) { + return (half)ror((int)a,n); + } +#endif + + //! Return absolute value of a value. + template + inline T abs(const T& a) { + return a>=0?a:-a; + } + inline bool abs(const bool a) { + return a; + } + inline int abs(const unsigned char a) { + return (int)a; + } + inline int abs(const unsigned short a) { + return (int)a; + } + inline int abs(const unsigned int a) { + return (int)a; + } + inline int abs(const int a) { + return std::abs(a); + } + inline cimg_int64 abs(const cimg_uint64 a) { + return (cimg_int64)a; + } + inline double abs(const double a) { + return std::fabs(a); + } + inline float abs(const float a) { + return (float)std::fabs((double)a); + } + + //! Return hyperbolic arcosine of a value. + inline double acosh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::acosh(x); +#else + return std::log(x + std::sqrt(x*x - 1)); +#endif + } + + //! Return hyperbolic arcsine of a value. + inline double asinh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::asinh(x); +#else + return std::log(x + std::sqrt(x*x + 1)); +#endif + } + + //! Return hyperbolic arctangent of a value. + inline double atanh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::atanh(x); +#else + return 0.5*std::log((1. + x)/(1. - x)); +#endif + } + + //! Return the sinc of a given value. + inline double sinc(const double x) { + return x?std::sin(x)/x:1; + } + + //! Return base-2 logarithm of a value. + inline double log2(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::log2(x); +#else + const double base2 = std::log(2.); + return std::log(x)/base2; +#endif + } + + //! Return square of a value. + template + inline T sqr(const T& val) { + return val*val; + } + + // Return inverse of error function. + template + inline T erfinv(const T& val) { + const T + sgn = val<0?-1:1, + x = (1 - val)*(1 + val), + lnx = std::log(x), + tt1 = (T)(2/(cimg::PI*0.147) + 0.5*lnx), + tt2 = lnx/(T)0.147; + return sgn*std::sqrt(-tt1 + std::sqrt(tt1*tt1 - tt2)); + } + + //! Return cubic root of a value. + template + inline double cbrt(const T& x) { +#if cimg_use_cpp11==1 + return std::cbrt(x); +#else + return x>=0?std::pow((double)x,1./3):-std::pow(-(double)x,1./3); +#endif + } + + template + inline T pow3(const T& val) { + return val*val*val; + } + template + inline T pow4(const T& val) { + return val*val*val*val; + } + + //! Return the minimum between three values. + template + inline t min(const t& a, const t& b, const t& c) { + return std::min(std::min(a,b),c); + } + + //! Return the minimum between four values. + template + inline t min(const t& a, const t& b, const t& c, const t& d) { + return std::min(std::min(a,b),std::min(c,d)); + } + + //! Return the minabs between two values. + template + inline t minabs(const t& a, const t& b) { + return cimg::abs(b) + inline t minabs(const t& a, const t& b, const t& abs_b) { + return abs_b + inline t max(const t& a, const t& b, const t& c) { + return std::max(std::max(a,b),c); + } + + //! Return the maximum between four values. + template + inline t max(const t& a, const t& b, const t& c, const t& d) { + return std::max(std::max(a,b),std::max(c,d)); + } + + //! Return the maxabs between two values. + template + inline t maxabs(const t& a, const t& b) { + return cimg::abs(b)>cimg::abs(a)?b:a; + } + + template + inline t maxabs(const t& a, const t& b, const t& abs_b) { + return abs_b>cimg::abs(a)?b:a; + } + + //! Return the sign of a value. + template + inline T sign(const T& x) { + return (T)(cimg::type::is_nan(x)?0:x<0?-1:x>0); + } + + //! Return the nearest power of 2 higher than given value. + template + inline cimg_uint64 nearest_pow2(const T& x) { + cimg_uint64 i = 1; + while (x>i) i<<=1; + return i; + } + + //! Return the modulo of a value. + /** + \param x Input value. + \param m Modulo value. + \note This modulo function accepts negative and floating-points modulo numbers, as well as variables of any type. + **/ + template + inline T mod(const T& x, const T& m) { + const double dx = (double)x, dm = (double)m; + if (!cimg::type::is_finite(dm)) return x; + if (cimg::type::is_finite(dx)) return (T)(dx - dm * std::floor(dx / dm)); + return (T)0; + } + inline int mod(const bool x, const bool m) { + return m?(x?1:0):0; + } + inline int mod(const unsigned char x, const unsigned char m) { + return x%m; + } + inline int mod(const char x, const char m) { +#if defined(CHAR_MAX) && CHAR_MAX==255 + return x%m; +#else + return x>=0?x%m:(x%m?m + x%m:0); +#endif + } + inline int mod(const unsigned short x, const unsigned short m) { + return (int)(x%m); + } + inline int mod(const short x, const short m) { + return (int)(x>=0?x%m:(x%m?m + x%m:0)); + } + inline int mod(const unsigned int x, const unsigned int m) { + return (int)(x%m); + } + inline int mod(const int x, const int m) { + return (int)(x>=0?x%m:(x%m?m + x%m:0)); + } + inline cimg_int64 mod(const cimg_uint64 x, const cimg_uint64 m) { + return (cimg_int64)(x%m); + } + inline cimg_int64 mod(const cimg_int64 x, const cimg_int64 m) { + return (cimg_int64)(x>=0?x%m:(x%m?m + x%m:0)); + } + + //! Return the min-mod of two values. + /** + \note minmod(\p a,\p b) is defined to be: + - minmod(\p a,\p b) = min(\p a,\p b), if \p a and \p b have the same sign. + - minmod(\p a,\p b) = 0, if \p a and \p b have different signs. + **/ + template + inline T minmod(const T& a, const T& b) { + return a*b<=0?0:(a>0?(a + inline T round(const T& x) { + return (T)std::floor((_cimg_Tfloat)x + 0.5f); + } + + template + inline int uiround(const T x) { + return cimg::type::is_float()?(int)(x + 0.5f):(int)x; + } + + //! Return rounded value. + /** + \param x Value to be rounded. + \param y Rounding precision. + \param rounding_type Type of rounding operation (\c 0 = nearest, \c -1 = backward, \c 1 = forward). + \return Rounded value, having the same type as input value \c x. + **/ + template + inline T round(const T& x, const double y, const int rounding_type=0) { + if (y<=0) return x; + if (y==1) switch (rounding_type) { + case 0 : return cimg::round(x); + case 1 : return (T)std::ceil((_cimg_Tfloat)x); + default : return (T)std::floor((_cimg_Tfloat)x); + } + const double sx = (double)x/y, floor = std::floor(sx), delta = sx - floor; + return (T)(y*(rounding_type<0?floor:rounding_type>0?std::ceil(sx):delta<0.5?floor:std::ceil(sx))); + } + + // Code to compute fast median from 2,3,5,7,9,13,25 and 49 values. + // (contribution by RawTherapee: http://rawtherapee.com/). + template + inline T median(T val0, T val1) { + return (val0 + val1)/2; + } + + template + inline T median(T val0, T val1, T val2) { + return std::max(std::min(val0,val1),std::min(val2,std::max(val0,val1))); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = std::max(val0,tmp); val1 = std::min(val1,val4); tmp = std::min(val1,val2); val2 = std::max(val1,val2); + val1 = tmp; tmp = std::min(val2,val3); + return std::max(val1,tmp); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6) { + T tmp = std::min(val0,val5); + val5 = std::max(val0,val5); val0 = tmp; tmp = std::min(val0,val3); val3 = std::max(val0,val3); val0 = tmp; + tmp = std::min(val1,val6); val6 = std::max(val1,val6); val1 = tmp; tmp = std::min(val2,val4); + val4 = std::max(val2,val4); val2 = tmp; val1 = std::max(val0,val1); tmp = std::min(val3,val5); + val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); + val3 = std::max(tmp,val3); val3 = std::min(val3,val6); tmp = std::min(val4,val5); val4 = std::max(val1,tmp); + tmp = std::min(val1,tmp); val3 = std::max(tmp,val3); + return std::min(val3,val4); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8) { + T tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val7 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); + val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val6,val7); + val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val3 = std::max(val0,val3); val5 = std::min(val5,val8); + val7 = std::max(val4,tmp); tmp = std::min(val4,tmp); val6 = std::max(val3,val6); + val4 = std::max(val1,tmp); val2 = std::min(val2,val5); val4 = std::min(val4,val7); + tmp = std::min(val4,val2); val2 = std::max(val4,val2); val4 = std::max(val6,tmp); + return std::min(val4,val2); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8, T val9, T val10, T val11, + T val12) { + T tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = tmp; tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; + tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val5,val8); + val8 = std::max(val5,val8); val5 = tmp; tmp = std::min(val0,val12); val12 = std::max(val0,val12); + val0 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val2,val3); val3 = std::max(val2,val3); val2 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val8,val11); + val11 = std::max(val8,val11); val8 = tmp; tmp = std::min(val7,val12); val12 = std::max(val7,val12); val7 = tmp; + tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val10,val11); val11 = std::max(val10,val11); val10 = tmp; tmp = std::min(val1,val4); + val4 = std::max(val1,val4); val1 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val8); val8 = std::max(val7,val8); val7 = tmp; val11 = std::min(val11,val12); + tmp = std::min(val4,val9); val9 = std::max(val4,val9); val4 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; + tmp = std::min(val5,val6); val6 = std::max(val5,val6); val5 = tmp; val8 = std::min(val8,val9); + val10 = std::min(val10,val11); tmp = std::min(val1,val7); val7 = std::max(val1,val7); val1 = tmp; + tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; val3 = std::max(val1,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; val8 = std::min(val8,val10); + val5 = std::max(val0,val5); val5 = std::max(val2,val5); tmp = std::min(val6,val8); val8 = std::max(val6,val8); + val5 = std::max(val3,val5); val7 = std::min(val7,val8); val6 = std::max(val4,tmp); tmp = std::min(val4,tmp); + val5 = std::max(tmp,val5); val6 = std::min(val6,val7); + return std::max(val5,val6); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, + T val5, T val6, T val7, T val8, T val9, + T val10, T val11, T val12, T val13, T val14, + T val15, T val16, T val17, T val18, T val19, + T val20, T val21, T val22, T val23, T val24) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); val2 = std::min(tmp,val3); + val3 = std::max(tmp,val3); tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; + tmp = std::min(val5,val7); val7 = std::max(val5,val7); val5 = std::min(tmp,val6); val6 = std::max(tmp,val6); + tmp = std::min(val9,val10); val10 = std::max(val9,val10); val9 = tmp; tmp = std::min(val8,val10); + val10 = std::max(val8,val10); val8 = std::min(tmp,val9); val9 = std::max(tmp,val9); + tmp = std::min(val12,val13); val13 = std::max(val12,val13); val12 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val15,val16); val16 = std::max(val15,val16); val15 = tmp; tmp = std::min(val14,val16); + val16 = std::max(val14,val16); val14 = std::min(tmp,val15); val15 = std::max(tmp,val15); + tmp = std::min(val18,val19); val19 = std::max(val18,val19); val18 = tmp; tmp = std::min(val17,val19); + val19 = std::max(val17,val19); val17 = std::min(tmp,val18); val18 = std::max(tmp,val18); + tmp = std::min(val21,val22); val22 = std::max(val21,val22); val21 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = std::min(tmp,val21); val21 = std::max(tmp,val21); + tmp = std::min(val23,val24); val24 = std::max(val23,val24); val23 = tmp; tmp = std::min(val2,val5); + val5 = std::max(val2,val5); val2 = tmp; tmp = std::min(val3,val6); val6 = std::max(val3,val6); val3 = tmp; + tmp = std::min(val0,val6); val6 = std::max(val0,val6); val0 = std::min(tmp,val3); val3 = std::max(tmp,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = std::min(tmp,val4); val4 = std::max(tmp,val4); tmp = std::min(val11,val14); + val14 = std::max(val11,val14); val11 = tmp; tmp = std::min(val8,val14); val14 = std::max(val8,val14); + val8 = std::min(tmp,val11); val11 = std::max(tmp,val11); tmp = std::min(val12,val15); + val15 = std::max(val12,val15); val12 = tmp; tmp = std::min(val9,val15); val15 = std::max(val9,val15); + val9 = std::min(tmp,val12); val12 = std::max(tmp,val12); tmp = std::min(val13,val16); + val16 = std::max(val13,val16); val13 = tmp; tmp = std::min(val10,val16); val16 = std::max(val10,val16); + val10 = std::min(tmp,val13); val13 = std::max(tmp,val13); tmp = std::min(val20,val23); + val23 = std::max(val20,val23); val20 = tmp; tmp = std::min(val17,val23); val23 = std::max(val17,val23); + val17 = std::min(tmp,val20); val20 = std::max(tmp,val20); tmp = std::min(val21,val24); + val24 = std::max(val21,val24); val21 = tmp; tmp = std::min(val18,val24); val24 = std::max(val18,val24); + val18 = std::min(tmp,val21); val21 = std::max(tmp,val21); tmp = std::min(val19,val22); + val22 = std::max(val19,val22); val19 = tmp; val17 = std::max(val8,val17); tmp = std::min(val9,val18); + val18 = std::max(val9,val18); val9 = tmp; tmp = std::min(val0,val18); val18 = std::max(val0,val18); + val9 = std::max(tmp,val9); tmp = std::min(val10,val19); val19 = std::max(val10,val19); val10 = tmp; + tmp = std::min(val1,val19); val19 = std::max(val1,val19); val1 = std::min(tmp,val10); + val10 = std::max(tmp,val10); tmp = std::min(val11,val20); val20 = std::max(val11,val20); val11 = tmp; + tmp = std::min(val2,val20); val20 = std::max(val2,val20); val11 = std::max(tmp,val11); + tmp = std::min(val12,val21); val21 = std::max(val12,val21); val12 = tmp; tmp = std::min(val3,val21); + val21 = std::max(val3,val21); val3 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val13,val22); val22 = std::max(val13,val22); val4 = std::min(val4,val22); + val13 = std::max(val4,tmp); tmp = std::min(val4,tmp); val4 = tmp; tmp = std::min(val14,val23); + val23 = std::max(val14,val23); val14 = tmp; tmp = std::min(val5,val23); val23 = std::max(val5,val23); + val5 = std::min(tmp,val14); val14 = std::max(tmp,val14); tmp = std::min(val15,val24); + val24 = std::max(val15,val24); val15 = tmp; val6 = std::min(val6,val24); tmp = std::min(val6,val15); + val15 = std::max(val6,val15); val6 = tmp; tmp = std::min(val7,val16); val7 = std::min(tmp,val19); + tmp = std::min(val13,val21); val15 = std::min(val15,val23); tmp = std::min(val7,tmp); + val7 = std::min(tmp,val15); val9 = std::max(val1,val9); val11 = std::max(val3,val11); + val17 = std::max(val5,val17); val17 = std::max(val11,val17); val17 = std::max(val9,val17); + tmp = std::min(val4,val10); val10 = std::max(val4,val10); val4 = tmp; tmp = std::min(val6,val12); + val12 = std::max(val6,val12); val6 = tmp; tmp = std::min(val7,val14); val14 = std::max(val7,val14); + val7 = tmp; tmp = std::min(val4,val6); val6 = std::max(val4,val6); val7 = std::max(tmp,val7); + tmp = std::min(val12,val14); val14 = std::max(val12,val14); val12 = tmp; val10 = std::min(val10,val14); + tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val10,val12); + val12 = std::max(val10,val12); val10 = std::max(val6,tmp); tmp = std::min(val6,tmp); + val17 = std::max(tmp,val17); tmp = std::min(val12,val17); val17 = std::max(val12,val17); val12 = tmp; + val7 = std::min(val7,val17); tmp = std::min(val7,val10); val10 = std::max(val7,val10); val7 = tmp; + tmp = std::min(val12,val18); val18 = std::max(val12,val18); val12 = std::max(val7,tmp); + val10 = std::min(val10,val18); tmp = std::min(val12,val20); val20 = std::max(val12,val20); val12 = tmp; + tmp = std::min(val10,val20); + return std::max(tmp,val12); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, + T val7, T val8, T val9, T val10, T val11, T val12, T val13, + T val14, T val15, T val16, T val17, T val18, T val19, T val20, + T val21, T val22, T val23, T val24, T val25, T val26, T val27, + T val28, T val29, T val30, T val31, T val32, T val33, T val34, + T val35, T val36, T val37, T val38, T val39, T val40, T val41, + T val42, T val43, T val44, T val45, T val46, T val47, T val48) { + T tmp = std::min(val0,val32); + val32 = std::max(val0,val32); val0 = tmp; tmp = std::min(val1,val33); val33 = std::max(val1,val33); val1 = tmp; + tmp = std::min(val2,val34); val34 = std::max(val2,val34); val2 = tmp; tmp = std::min(val3,val35); + val35 = std::max(val3,val35); val3 = tmp; tmp = std::min(val4,val36); val36 = std::max(val4,val36); val4 = tmp; + tmp = std::min(val5,val37); val37 = std::max(val5,val37); val5 = tmp; tmp = std::min(val6,val38); + val38 = std::max(val6,val38); val6 = tmp; tmp = std::min(val7,val39); val39 = std::max(val7,val39); val7 = tmp; + tmp = std::min(val8,val40); val40 = std::max(val8,val40); val8 = tmp; tmp = std::min(val9,val41); + val41 = std::max(val9,val41); val9 = tmp; tmp = std::min(val10,val42); val42 = std::max(val10,val42); + val10 = tmp; tmp = std::min(val11,val43); val43 = std::max(val11,val43); val11 = tmp; + tmp = std::min(val12,val44); val44 = std::max(val12,val44); val12 = tmp; tmp = std::min(val13,val45); + val45 = std::max(val13,val45); val13 = tmp; tmp = std::min(val14,val46); val46 = std::max(val14,val46); + val14 = tmp; tmp = std::min(val15,val47); val47 = std::max(val15,val47); val15 = tmp; + tmp = std::min(val16,val48); val48 = std::max(val16,val48); val16 = tmp; tmp = std::min(val0,val16); + val16 = std::max(val0,val16); val0 = tmp; tmp = std::min(val1,val17); val17 = std::max(val1,val17); + val1 = tmp; tmp = std::min(val2,val18); val18 = std::max(val2,val18); val2 = tmp; tmp = std::min(val3,val19); + val19 = std::max(val3,val19); val3 = tmp; tmp = std::min(val4,val20); val20 = std::max(val4,val20); val4 = tmp; + tmp = std::min(val5,val21); val21 = std::max(val5,val21); val5 = tmp; tmp = std::min(val6,val22); + val22 = std::max(val6,val22); val6 = tmp; tmp = std::min(val7,val23); val23 = std::max(val7,val23); val7 = tmp; + tmp = std::min(val8,val24); val24 = std::max(val8,val24); val8 = tmp; tmp = std::min(val9,val25); + val25 = std::max(val9,val25); val9 = tmp; tmp = std::min(val10,val26); val26 = std::max(val10,val26); + val10 = tmp; tmp = std::min(val11,val27); val27 = std::max(val11,val27); val11 = tmp; + tmp = std::min(val12,val28); val28 = std::max(val12,val28); val12 = tmp; tmp = std::min(val13,val29); + val29 = std::max(val13,val29); val13 = tmp; tmp = std::min(val14,val30); val30 = std::max(val14,val30); + val14 = tmp; tmp = std::min(val15,val31); val31 = std::max(val15,val31); val15 = tmp; + tmp = std::min(val32,val48); val48 = std::max(val32,val48); val32 = tmp; tmp = std::min(val16,val32); + val32 = std::max(val16,val32); val16 = tmp; tmp = std::min(val17,val33); val33 = std::max(val17,val33); + val17 = tmp; tmp = std::min(val18,val34); val34 = std::max(val18,val34); val18 = tmp; + tmp = std::min(val19,val35); val35 = std::max(val19,val35); val19 = tmp; tmp = std::min(val20,val36); + val36 = std::max(val20,val36); val20 = tmp; tmp = std::min(val21,val37); val37 = std::max(val21,val37); + val21 = tmp; tmp = std::min(val22,val38); val38 = std::max(val22,val38); val22 = tmp; + tmp = std::min(val23,val39); val39 = std::max(val23,val39); val23 = tmp; tmp = std::min(val24,val40); + val40 = std::max(val24,val40); val24 = tmp; tmp = std::min(val25,val41); val41 = std::max(val25,val41); + val25 = tmp; tmp = std::min(val26,val42); val42 = std::max(val26,val42); val26 = tmp; + tmp = std::min(val27,val43); val43 = std::max(val27,val43); val27 = tmp; tmp = std::min(val28,val44); + val44 = std::max(val28,val44); val28 = tmp; tmp = std::min(val29,val45); val45 = std::max(val29,val45); + val29 = tmp; tmp = std::min(val30,val46); val46 = std::max(val30,val46); val30 = tmp; + tmp = std::min(val31,val47); val47 = std::max(val31,val47); val31 = tmp; tmp = std::min(val0,val8); + val8 = std::max(val0,val8); val0 = tmp; tmp = std::min(val1,val9); val9 = std::max(val1,val9); val1 = tmp; + tmp = std::min(val2,val10); val10 = std::max(val2,val10); val2 = tmp; tmp = std::min(val3,val11); + val11 = std::max(val3,val11); val3 = tmp; tmp = std::min(val4,val12); val12 = std::max(val4,val12); val4 = tmp; + tmp = std::min(val5,val13); val13 = std::max(val5,val13); val5 = tmp; tmp = std::min(val6,val14); + val14 = std::max(val6,val14); val6 = tmp; tmp = std::min(val7,val15); val15 = std::max(val7,val15); val7 = tmp; + tmp = std::min(val16,val24); val24 = std::max(val16,val24); val16 = tmp; tmp = std::min(val17,val25); + val25 = std::max(val17,val25); val17 = tmp; tmp = std::min(val18,val26); val26 = std::max(val18,val26); + val18 = tmp; tmp = std::min(val19,val27); val27 = std::max(val19,val27); val19 = tmp; + tmp = std::min(val20,val28); val28 = std::max(val20,val28); val20 = tmp; tmp = std::min(val21,val29); + val29 = std::max(val21,val29); val21 = tmp; tmp = std::min(val22,val30); val30 = std::max(val22,val30); + val22 = tmp; tmp = std::min(val23,val31); val31 = std::max(val23,val31); val23 = tmp; + tmp = std::min(val32,val40); val40 = std::max(val32,val40); val32 = tmp; tmp = std::min(val33,val41); + val41 = std::max(val33,val41); val33 = tmp; tmp = std::min(val34,val42); val42 = std::max(val34,val42); + val34 = tmp; tmp = std::min(val35,val43); val43 = std::max(val35,val43); val35 = tmp; + tmp = std::min(val36,val44); val44 = std::max(val36,val44); val36 = tmp; tmp = std::min(val37,val45); + val45 = std::max(val37,val45); val37 = tmp; tmp = std::min(val38,val46); val46 = std::max(val38,val46); + val38 = tmp; tmp = std::min(val39,val47); val47 = std::max(val39,val47); val39 = tmp; + tmp = std::min(val8,val32); val32 = std::max(val8,val32); val8 = tmp; tmp = std::min(val9,val33); + val33 = std::max(val9,val33); val9 = tmp; tmp = std::min(val10,val34); val34 = std::max(val10,val34); + val10 = tmp; tmp = std::min(val11,val35); val35 = std::max(val11,val35); val11 = tmp; + tmp = std::min(val12,val36); val36 = std::max(val12,val36); val12 = tmp; tmp = std::min(val13,val37); + val37 = std::max(val13,val37); val13 = tmp; tmp = std::min(val14,val38); val38 = std::max(val14,val38); + val14 = tmp; tmp = std::min(val15,val39); val39 = std::max(val15,val39); val15 = tmp; + tmp = std::min(val24,val48); val48 = std::max(val24,val48); val24 = tmp; tmp = std::min(val8,val16); + val16 = std::max(val8,val16); val8 = tmp; tmp = std::min(val9,val17); val17 = std::max(val9,val17); + val9 = tmp; tmp = std::min(val10,val18); val18 = std::max(val10,val18); val10 = tmp; + tmp = std::min(val11,val19); val19 = std::max(val11,val19); val11 = tmp; tmp = std::min(val12,val20); + val20 = std::max(val12,val20); val12 = tmp; tmp = std::min(val13,val21); val21 = std::max(val13,val21); + val13 = tmp; tmp = std::min(val14,val22); val22 = std::max(val14,val22); val14 = tmp; + tmp = std::min(val15,val23); val23 = std::max(val15,val23); val15 = tmp; tmp = std::min(val24,val32); + val32 = std::max(val24,val32); val24 = tmp; tmp = std::min(val25,val33); val33 = std::max(val25,val33); + val25 = tmp; tmp = std::min(val26,val34); val34 = std::max(val26,val34); val26 = tmp; + tmp = std::min(val27,val35); val35 = std::max(val27,val35); val27 = tmp; tmp = std::min(val28,val36); + val36 = std::max(val28,val36); val28 = tmp; tmp = std::min(val29,val37); val37 = std::max(val29,val37); + val29 = tmp; tmp = std::min(val30,val38); val38 = std::max(val30,val38); val30 = tmp; + tmp = std::min(val31,val39); val39 = std::max(val31,val39); val31 = tmp; tmp = std::min(val40,val48); + val48 = std::max(val40,val48); val40 = tmp; tmp = std::min(val0,val4); val4 = std::max(val0,val4); + val0 = tmp; tmp = std::min(val1,val5); val5 = std::max(val1,val5); val1 = tmp; tmp = std::min(val2,val6); + val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val8,val12); val12 = std::max(val8,val12); val8 = tmp; tmp = std::min(val9,val13); + val13 = std::max(val9,val13); val9 = tmp; tmp = std::min(val10,val14); val14 = std::max(val10,val14); + val10 = tmp; tmp = std::min(val11,val15); val15 = std::max(val11,val15); val11 = tmp; + tmp = std::min(val16,val20); val20 = std::max(val16,val20); val16 = tmp; tmp = std::min(val17,val21); + val21 = std::max(val17,val21); val17 = tmp; tmp = std::min(val18,val22); val22 = std::max(val18,val22); + val18 = tmp; tmp = std::min(val19,val23); val23 = std::max(val19,val23); val19 = tmp; + tmp = std::min(val24,val28); val28 = std::max(val24,val28); val24 = tmp; tmp = std::min(val25,val29); + val29 = std::max(val25,val29); val25 = tmp; tmp = std::min(val26,val30); val30 = std::max(val26,val30); + val26 = tmp; tmp = std::min(val27,val31); val31 = std::max(val27,val31); val27 = tmp; + tmp = std::min(val32,val36); val36 = std::max(val32,val36); val32 = tmp; tmp = std::min(val33,val37); + val37 = std::max(val33,val37); val33 = tmp; tmp = std::min(val34,val38); val38 = std::max(val34,val38); + val34 = tmp; tmp = std::min(val35,val39); val39 = std::max(val35,val39); val35 = tmp; + tmp = std::min(val40,val44); val44 = std::max(val40,val44); val40 = tmp; tmp = std::min(val41,val45); + val45 = std::max(val41,val45); val41 = tmp; tmp = std::min(val42,val46); val46 = std::max(val42,val46); + val42 = tmp; tmp = std::min(val43,val47); val47 = std::max(val43,val47); val43 = tmp; + tmp = std::min(val4,val32); val32 = std::max(val4,val32); val4 = tmp; tmp = std::min(val5,val33); + val33 = std::max(val5,val33); val5 = tmp; tmp = std::min(val6,val34); val34 = std::max(val6,val34); + val6 = tmp; tmp = std::min(val7,val35); val35 = std::max(val7,val35); val7 = tmp; + tmp = std::min(val12,val40); val40 = std::max(val12,val40); val12 = tmp; tmp = std::min(val13,val41); + val41 = std::max(val13,val41); val13 = tmp; tmp = std::min(val14,val42); val42 = std::max(val14,val42); + val14 = tmp; tmp = std::min(val15,val43); val43 = std::max(val15,val43); val15 = tmp; + tmp = std::min(val20,val48); val48 = std::max(val20,val48); val20 = tmp; tmp = std::min(val4,val16); + val16 = std::max(val4,val16); val4 = tmp; tmp = std::min(val5,val17); val17 = std::max(val5,val17); + val5 = tmp; tmp = std::min(val6,val18); val18 = std::max(val6,val18); val6 = tmp; + tmp = std::min(val7,val19); val19 = std::max(val7,val19); val7 = tmp; tmp = std::min(val12,val24); + val24 = std::max(val12,val24); val12 = tmp; tmp = std::min(val13,val25); val25 = std::max(val13,val25); + val13 = tmp; tmp = std::min(val14,val26); val26 = std::max(val14,val26); val14 = tmp; + tmp = std::min(val15,val27); val27 = std::max(val15,val27); val15 = tmp; tmp = std::min(val20,val32); + val32 = std::max(val20,val32); val20 = tmp; tmp = std::min(val21,val33); val33 = std::max(val21,val33); + val21 = tmp; tmp = std::min(val22,val34); val34 = std::max(val22,val34); val22 = tmp; + tmp = std::min(val23,val35); val35 = std::max(val23,val35); val23 = tmp; tmp = std::min(val28,val40); + val40 = std::max(val28,val40); val28 = tmp; tmp = std::min(val29,val41); val41 = std::max(val29,val41); + val29 = tmp; tmp = std::min(val30,val42); val42 = std::max(val30,val42); val30 = tmp; + tmp = std::min(val31,val43); val43 = std::max(val31,val43); val31 = tmp; tmp = std::min(val36,val48); + val48 = std::max(val36,val48); val36 = tmp; tmp = std::min(val4,val8); val8 = std::max(val4,val8); + val4 = tmp; tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val7,val11); val11 = std::max(val7,val11); val7 = tmp; + tmp = std::min(val12,val16); val16 = std::max(val12,val16); val12 = tmp; tmp = std::min(val13,val17); + val17 = std::max(val13,val17); val13 = tmp; tmp = std::min(val14,val18); val18 = std::max(val14,val18); + val14 = tmp; tmp = std::min(val15,val19); val19 = std::max(val15,val19); val15 = tmp; + tmp = std::min(val20,val24); val24 = std::max(val20,val24); val20 = tmp; tmp = std::min(val21,val25); + val25 = std::max(val21,val25); val21 = tmp; tmp = std::min(val22,val26); val26 = std::max(val22,val26); + val22 = tmp; tmp = std::min(val23,val27); val27 = std::max(val23,val27); val23 = tmp; + tmp = std::min(val28,val32); val32 = std::max(val28,val32); val28 = tmp; tmp = std::min(val29,val33); + val33 = std::max(val29,val33); val29 = tmp; tmp = std::min(val30,val34); val34 = std::max(val30,val34); + val30 = tmp; tmp = std::min(val31,val35); val35 = std::max(val31,val35); val31 = tmp; + tmp = std::min(val36,val40); val40 = std::max(val36,val40); val36 = tmp; tmp = std::min(val37,val41); + val41 = std::max(val37,val41); val37 = tmp; tmp = std::min(val38,val42); val42 = std::max(val38,val42); + val38 = tmp; tmp = std::min(val39,val43); val43 = std::max(val39,val43); val39 = tmp; + tmp = std::min(val44,val48); val48 = std::max(val44,val48); val44 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val1,val3); val3 = std::max(val1,val3); val1 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val5,val7); + val7 = std::max(val5,val7); val5 = tmp; tmp = std::min(val8,val10); val10 = std::max(val8,val10); val8 = tmp; + tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; tmp = std::min(val12,val14); + val14 = std::max(val12,val14); val12 = tmp; tmp = std::min(val13,val15); val15 = std::max(val13,val15); + val13 = tmp; tmp = std::min(val16,val18); val18 = std::max(val16,val18); val16 = tmp; + tmp = std::min(val17,val19); val19 = std::max(val17,val19); val17 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = tmp; tmp = std::min(val21,val23); val23 = std::max(val21,val23); + val21 = tmp; tmp = std::min(val24,val26); val26 = std::max(val24,val26); val24 = tmp; + tmp = std::min(val25,val27); val27 = std::max(val25,val27); val25 = tmp; tmp = std::min(val28,val30); + val30 = std::max(val28,val30); val28 = tmp; tmp = std::min(val29,val31); val31 = std::max(val29,val31); + val29 = tmp; tmp = std::min(val32,val34); val34 = std::max(val32,val34); val32 = tmp; + tmp = std::min(val33,val35); val35 = std::max(val33,val35); val33 = tmp; tmp = std::min(val36,val38); + val38 = std::max(val36,val38); val36 = tmp; tmp = std::min(val37,val39); val39 = std::max(val37,val39); + val37 = tmp; tmp = std::min(val40,val42); val42 = std::max(val40,val42); val40 = tmp; + tmp = std::min(val41,val43); val43 = std::max(val41,val43); val41 = tmp; tmp = std::min(val44,val46); + val46 = std::max(val44,val46); val44 = tmp; tmp = std::min(val45,val47); val47 = std::max(val45,val47); + val45 = tmp; tmp = std::min(val2,val32); val32 = std::max(val2,val32); val2 = tmp; tmp = std::min(val3,val33); + val33 = std::max(val3,val33); val3 = tmp; tmp = std::min(val6,val36); val36 = std::max(val6,val36); val6 = tmp; + tmp = std::min(val7,val37); val37 = std::max(val7,val37); val7 = tmp; tmp = std::min(val10,val40); + val40 = std::max(val10,val40); val10 = tmp; tmp = std::min(val11,val41); val41 = std::max(val11,val41); + val11 = tmp; tmp = std::min(val14,val44); val44 = std::max(val14,val44); val14 = tmp; + tmp = std::min(val15,val45); val45 = std::max(val15,val45); val15 = tmp; tmp = std::min(val18,val48); + val48 = std::max(val18,val48); val18 = tmp; tmp = std::min(val2,val16); val16 = std::max(val2,val16); + val2 = tmp; tmp = std::min(val3,val17); val17 = std::max(val3,val17); val3 = tmp; + tmp = std::min(val6,val20); val20 = std::max(val6,val20); val6 = tmp; tmp = std::min(val7,val21); + val21 = std::max(val7,val21); val7 = tmp; tmp = std::min(val10,val24); val24 = std::max(val10,val24); + val10 = tmp; tmp = std::min(val11,val25); val25 = std::max(val11,val25); val11 = tmp; + tmp = std::min(val14,val28); val28 = std::max(val14,val28); val14 = tmp; tmp = std::min(val15,val29); + val29 = std::max(val15,val29); val15 = tmp; tmp = std::min(val18,val32); val32 = std::max(val18,val32); + val18 = tmp; tmp = std::min(val19,val33); val33 = std::max(val19,val33); val19 = tmp; + tmp = std::min(val22,val36); val36 = std::max(val22,val36); val22 = tmp; tmp = std::min(val23,val37); + val37 = std::max(val23,val37); val23 = tmp; tmp = std::min(val26,val40); val40 = std::max(val26,val40); + val26 = tmp; tmp = std::min(val27,val41); val41 = std::max(val27,val41); val27 = tmp; + tmp = std::min(val30,val44); val44 = std::max(val30,val44); val30 = tmp; tmp = std::min(val31,val45); + val45 = std::max(val31,val45); val31 = tmp; tmp = std::min(val34,val48); val48 = std::max(val34,val48); + val34 = tmp; tmp = std::min(val2,val8); val8 = std::max(val2,val8); val2 = tmp; tmp = std::min(val3,val9); + val9 = std::max(val3,val9); val3 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val13); val13 = std::max(val7,val13); val7 = tmp; tmp = std::min(val10,val16); + val16 = std::max(val10,val16); val10 = tmp; tmp = std::min(val11,val17); val17 = std::max(val11,val17); + val11 = tmp; tmp = std::min(val14,val20); val20 = std::max(val14,val20); val14 = tmp; + tmp = std::min(val15,val21); val21 = std::max(val15,val21); val15 = tmp; tmp = std::min(val18,val24); + val24 = std::max(val18,val24); val18 = tmp; tmp = std::min(val19,val25); val25 = std::max(val19,val25); + val19 = tmp; tmp = std::min(val22,val28); val28 = std::max(val22,val28); val22 = tmp; + tmp = std::min(val23,val29); val29 = std::max(val23,val29); val23 = tmp; tmp = std::min(val26,val32); + val32 = std::max(val26,val32); val26 = tmp; tmp = std::min(val27,val33); val33 = std::max(val27,val33); + val27 = tmp; tmp = std::min(val30,val36); val36 = std::max(val30,val36); val30 = tmp; + tmp = std::min(val31,val37); val37 = std::max(val31,val37); val31 = tmp; tmp = std::min(val34,val40); + val40 = std::max(val34,val40); val34 = tmp; tmp = std::min(val35,val41); val41 = std::max(val35,val41); + val35 = tmp; tmp = std::min(val38,val44); val44 = std::max(val38,val44); val38 = tmp; + tmp = std::min(val39,val45); val45 = std::max(val39,val45); val39 = tmp; tmp = std::min(val42,val48); + val48 = std::max(val42,val48); val42 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); + val2 = tmp; tmp = std::min(val3,val5); val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val6,val8); + val8 = std::max(val6,val8); val6 = tmp; tmp = std::min(val7,val9); val9 = std::max(val7,val9); val7 = tmp; + tmp = std::min(val10,val12); val12 = std::max(val10,val12); val10 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = tmp; tmp = std::min(val14,val16); val16 = std::max(val14,val16); + val14 = tmp; tmp = std::min(val15,val17); val17 = std::max(val15,val17); val15 = tmp; + tmp = std::min(val18,val20); val20 = std::max(val18,val20); val18 = tmp; tmp = std::min(val19,val21); + val21 = std::max(val19,val21); val19 = tmp; tmp = std::min(val22,val24); val24 = std::max(val22,val24); + val22 = tmp; tmp = std::min(val23,val25); val25 = std::max(val23,val25); val23 = tmp; + tmp = std::min(val26,val28); val28 = std::max(val26,val28); val26 = tmp; tmp = std::min(val27,val29); + val29 = std::max(val27,val29); val27 = tmp; tmp = std::min(val30,val32); val32 = std::max(val30,val32); + val30 = tmp; tmp = std::min(val31,val33); val33 = std::max(val31,val33); val31 = tmp; + tmp = std::min(val34,val36); val36 = std::max(val34,val36); val34 = tmp; tmp = std::min(val35,val37); + val37 = std::max(val35,val37); val35 = tmp; tmp = std::min(val38,val40); val40 = std::max(val38,val40); + val38 = tmp; tmp = std::min(val39,val41); val41 = std::max(val39,val41); val39 = tmp; + tmp = std::min(val42,val44); val44 = std::max(val42,val44); val42 = tmp; tmp = std::min(val43,val45); + val45 = std::max(val43,val45); val43 = tmp; tmp = std::min(val46,val48); val48 = std::max(val46,val48); + val46 = tmp; val1 = std::max(val0,val1); val3 = std::max(val2,val3); val5 = std::max(val4,val5); + val7 = std::max(val6,val7); val9 = std::max(val8,val9); val11 = std::max(val10,val11); + val13 = std::max(val12,val13); val15 = std::max(val14,val15); val17 = std::max(val16,val17); + val19 = std::max(val18,val19); val21 = std::max(val20,val21); val23 = std::max(val22,val23); + val24 = std::min(val24,val25); val26 = std::min(val26,val27); val28 = std::min(val28,val29); + val30 = std::min(val30,val31); val32 = std::min(val32,val33); val34 = std::min(val34,val35); + val36 = std::min(val36,val37); val38 = std::min(val38,val39); val40 = std::min(val40,val41); + val42 = std::min(val42,val43); val44 = std::min(val44,val45); val46 = std::min(val46,val47); + val32 = std::max(val1,val32); val34 = std::max(val3,val34); val36 = std::max(val5,val36); + val38 = std::max(val7,val38); val9 = std::min(val9,val40); val11 = std::min(val11,val42); + val13 = std::min(val13,val44); val15 = std::min(val15,val46); val17 = std::min(val17,val48); + val24 = std::max(val9,val24); val26 = std::max(val11,val26); val28 = std::max(val13,val28); + val30 = std::max(val15,val30); val17 = std::min(val17,val32); val19 = std::min(val19,val34); + val21 = std::min(val21,val36); val23 = std::min(val23,val38); val24 = std::max(val17,val24); + val26 = std::max(val19,val26); val21 = std::min(val21,val28); val23 = std::min(val23,val30); + val24 = std::max(val21,val24); val23 = std::min(val23,val26); + return std::max(val23,val24); + } + + //! Return sqrt(x^2 + y^2). + template + inline T hypot(const T x, const T y) { + return std::sqrt(x*x + y*y); + } + + template + inline T hypot(const T x, const T y, const T z) { + return std::sqrt(x*x + y*y + z*z); + } + + template + inline T _hypot(const T x, const T y) { // Slower but more precise version + T nx = cimg::abs(x), ny = cimg::abs(y), t; + if (nx0) { t/=nx; return nx*std::sqrt(1 + t*t); } + return 0; + } + + //! Return the factorial of n + inline double factorial(const int n) { + if (n<0) return cimg::type::nan(); + if (n<2) return 1; + double res = 2; + for (int i = 3; i<=n; ++i) res*=i; + return res; + } + + //! Return the number of permutations of k objects in a set of n objects. + inline double permutations(const int k, const int n, const bool with_order) { + if (n<0 || k<0) return cimg::type::nan(); + if (k>n) return 0; + double res = 1; + for (int i = n; i>=n - k + 1; --i) res*=i; + return with_order?res:res/cimg::factorial(k); + } + + inline double _fibonacci(int exp) { + double + base = (1 + std::sqrt(5.))/2, + result = 1/std::sqrt(5.); + while (exp) { + if (exp&1) result*=base; + exp>>=1; + base*=base; + } + return result; + } + + //! Calculate fibonacci number. + // (Precise up to n = 78, less precise for n>78). + inline double fibonacci(const int n) { + if (n<0) return cimg::type::nan(); + if (n<3) return 1; + if (n<11) { + cimg_uint64 fn1 = 1, fn2 = 1, fn = 0; + for (int i = 3; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + if (n<75) // precise up to n = 74, faster than the integer calculation above for n>10 + return (double)((cimg_uint64)(_fibonacci(n) + 0.5)); + + if (n<94) { // precise up to n = 78, less precise for n>78 up to n = 93, overflows for n>93 + cimg_uint64 + fn1 = ((cimg_uint64)303836)<<32 | 3861581201UL, // 1304969544928657ULL (avoid C++98 warning with ULL) + fn2 = ((cimg_uint64)187781)<<32 | 2279239217UL, // 806515533049393ULL + fn = 0; + for (int i = 75; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + return _fibonacci(n); // Not precise, but better than the wrong overflowing calculation + } + + //! Calculate greatest common divisor. + inline long gcd(long a, long b) { + while (a) { const long c = a; a = b%a; b = c; } + return b; + } + + //! Convert character to lower case. + inline char lowercase(const char x) { + return (char)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + inline double lowercase(const double x) { + return (double)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + + //! Convert C-string to lower case. + inline void lowercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = lowercase(*ptr); + } + + //! Convert character to upper case. + inline char uppercase(const char x) { + return (char)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + inline double uppercase(const double x) { + return (double)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + //! Convert C-string to upper case. + inline void uppercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = uppercase(*ptr); + } + + //! Return \c true if input character is blank (space, tab, or non-printable character). + inline bool is_blank(const char c) { + return c>=0 && (unsigned char)c<=' '; + } + + //! Read value in a C-string. + /** + \param str C-string containing the float value to read. + \return Read value. + \note Same as std::atof() extended to manage the retrieval of fractions from C-strings, + as in "1/2". + **/ + inline double atof(const char *const str) { + double x = 0, y = 1; + return str && cimg_sscanf(str,"%lf/%lf",&x,&y)>0?x/y:0; + } + + //! Compare the first \p l characters of two C-strings, ignoring the case. + /** + \param str1 C-string. + \param str2 C-string. + \param l Number of characters to compare. + \return \c 0 if the two strings are equal, something else otherwise. + \note This function has to be defined since it is not provided by all C++-compilers (not ANSI). + **/ + inline int strncasecmp(const char *const str1, const char *const str2, const int l) { + if (!l) return 0; + if (!str1) return str2?-1:0; + const char *nstr1 = str1, *nstr2 = str2; + int k, diff = 0; for (k = 0; kp && str[q]==delimiter; ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Remove white spaces on the start and/or end of a C-string. + inline bool strpare(char *const str, const bool is_symmetric, const bool is_iterative) { + if (!str) return false; + const int l = (int)std::strlen(str); + int p, q; + if (is_symmetric) for (p = 0, q = l - 1; pp && is_blank(str[q]); ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Replace reserved characters (for Windows filename) by another character. + /** + \param[in,out] str C-string to work with (modified at output). + \param[in] c Replacement character. + **/ + inline void strwindows_reserved(char *const str, const char c='_') { + for (char *s = str; *s; ++s) { + const char i = *s; + if (i=='<' || i=='>' || i==':' || i=='\"' || i=='/' || i=='\\' || i=='|' || i=='?' || i=='*') *s = c; + } + } + + //! Replace escape sequences in C-strings by character values. + /** + \param[in,out] str C-string to work with (modified at output). + **/ + inline void strunescape(char *const str) { +#define cimg_strunescape(ci,co) case ci : *nd = co; ++ns; break; + + unsigned char val = 0; + for (char *ns = str, *nd = str; *ns || (bool)(*nd = 0); ++nd) if (*ns=='\\') switch (*(++ns)) { + cimg_strunescape('a','\a'); + cimg_strunescape('b','\b'); + cimg_strunescape('e',0x1B); + cimg_strunescape('f','\f'); + cimg_strunescape('n','\n'); + cimg_strunescape('r','\r'); + cimg_strunescape('t','\t'); + cimg_strunescape('v','\v'); + cimg_strunescape('\\','\\'); + cimg_strunescape('\'','\''); + cimg_strunescape('\"','\"'); + cimg_strunescape('\?','\?'); + case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : + val = (unsigned char)(*(ns++) - '0'); + if (*ns>='0' && *ns<='7') (val<<=3)|=*(ns++) - '0'; + if (*ns>='0' && *ns<='7') (val<<=3)|=*(ns++) - '0'; + *nd = (char)val; + break; + case 'x' : { + char c = lowercase(*(++ns)); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + val = (unsigned char)(c<='9'?c - '0':c - 'a' + 10); + c = lowercase(*(++ns)); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + (val<<=4)|=(c<='9'?c - '0':c - 'a' + 10); + ++ns; + } + *nd = (char)val; + } else *nd = c; + } break; + case 'u' : { // UTF-8 BMP + char c1, c2, c3, c4; + if ((((c1 = lowercase(ns[1]))>='0' && c1<='9') || (c1>='a' && c1<='f')) && + (((c2 = lowercase(ns[2]))>='0' && c2<='9') || (c2>='a' && c2<='f')) && + (((c3 = lowercase(ns[3]))>='0' && c3<='9') || (c3>='a' && c3<='f')) && + (((c4 = lowercase(ns[4]))>='0' && c4<='9') || (c4>='a' && c4<='f'))) { + c1 = (c1<='9'?c1 - '0':c1 - 'a' + 10); + c2 = (c2<='9'?c2 - '0':c2 - 'a' + 10); + c3 = (c3<='9'?c3 - '0':c3 - 'a' + 10); + c4 = (c4<='9'?c4 - '0':c4 - 'a' + 10); + const unsigned int ival = + ((unsigned int)c1<<12) | ((unsigned int)c2<<8) | ((unsigned int)c3<<4) | c4; + if (ival<=0x007f) *nd = (char)ival; + else if (ival<=0x07ff) { + *(nd++) = (char)((ival>>6)|0xc0); + *nd = (char)((ival&0x3f)|0x80); + } else { + *(nd++) = (char)((ival>>12)|0xe0); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } + ns+=5; + } else *nd = *(ns++); + } break; + case 'U' : { // UTF-8 astral planes + char c1, c2, c3, c4, c5, c6, c7, c8; + if ((((c1 = lowercase(ns[1]))>='0' && c1<='9') || (c1>='a' && c1<='f')) && + (((c2 = lowercase(ns[2]))>='0' && c2<='9') || (c2>='a' && c2<='f')) && + (((c3 = lowercase(ns[3]))>='0' && c3<='9') || (c3>='a' && c3<='f')) && + (((c4 = lowercase(ns[4]))>='0' && c4<='9') || (c4>='a' && c4<='f')) && + (((c5 = lowercase(ns[5]))>='0' && c5<='9') || (c5>='a' && c5<='f')) && + (((c6 = lowercase(ns[6]))>='0' && c6<='9') || (c6>='a' && c6<='f')) && + (((c7 = lowercase(ns[7]))>='0' && c7<='9') || (c7>='a' && c7<='f')) && + (((c8 = lowercase(ns[8]))>='0' && c8<='9') || (c8>='a' && c8<='f'))) { + c1 = (c1<='9'?c1 - '0':c1 - 'a' + 10); + c2 = (c2<='9'?c2 - '0':c2 - 'a' + 10); + c3 = (c3<='9'?c3 - '0':c3 - 'a' + 10); + c4 = (c4<='9'?c4 - '0':c4 - 'a' + 10); + c5 = (c5<='9'?c5 - '0':c5 - 'a' + 10); + c6 = (c6<='9'?c6 - '0':c6 - 'a' + 10); + c7 = (c7<='9'?c7 - '0':c7 - 'a' + 10); + c8 = (c8<='9'?c8 - '0':c8 - 'a' + 10); + const unsigned int ival = + ((unsigned int)c1<<28) | ((unsigned int)c2<<24) | ((unsigned int)c3<<20) | ((unsigned int)c4<<16) | + ((unsigned int)c5<<12) | ((unsigned int)c6<<8) | ((unsigned int)c7<<4) | (unsigned int)c8; + if (ival<=0x007f) *nd = (char)ival; + else if (ival<=0x07ff) { + *(nd++) = (char)((ival>>6)|0xc0); + *nd = (char)((ival&0x3f)|0x80); + } else if (ival<=0xffff) { + *(nd++) = (char)((ival>>12)|0xe0); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } else { + *(nd++) = (char)((ival>>18)|0xf0); + *(nd++) = (char)(((ival>>12)&0x3f)|0x80); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } + ns+=9; + } else *nd = *(ns++); + } break; + default : if (*ns) *nd = *(ns++); + } + else *nd = *(ns++); + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size); + + // Return string that identifies the running OS. + inline const char *stros() { +#if defined(linux) || defined(__linux) || defined(__linux__) + static const char *const str = "Linux"; +#elif defined(sun) || defined(__sun) + static const char *const str = "Sun OS"; +#elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__) + static const char *const str = "BSD"; +#elif defined(sgi) || defined(__sgi) + static const char *const str = "Irix"; +#elif defined(__MACOSX__) || defined(__APPLE__) + static const char *const str = "Mac OS"; +#elif defined(unix) || defined(__unix) || defined(__unix__) + static const char *const str = "Generic Unix"; +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ + defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + static const char *const str = "Windows"; +#else + const char + *const _str1 = std::getenv("OSTYPE"), + *const _str2 = _str1?_str1:std::getenv("OS"), + *const str = _str2?_str2:"Unknown OS"; +#endif + return str; + } + + //! Return the basename of a filename. + inline const char* basename(const char *const s, const char separator=cimg_file_separator) { + const char *p = 0, *np = s; + while (np>=s && (p=np)) np = std::strchr(np,separator) + 1; + return p; + } + + // Return a random filename. + inline const char* filenamerand() { + cimg::mutex(6); + static char randomid[9]; + for (unsigned int k = 0; k<8; ++k) { + const int v = (int)cimg::rand(65535)%3; + randomid[k] = (char)(v==0?('0' + ((int)cimg::rand(65535)%10)): + (v==1?('a' + ((int)cimg::rand(65535)%26)): + ('A' + ((int)cimg::rand(65535)%26)))); + } + cimg::mutex(6,0); + return randomid; + } + + // Convert filename as a Windows-style filename (short path name). + inline void winformat_string(char *const str) { + if (str && *str) { +#if cimg_OS==2 + char *const nstr = new char[MAX_PATH]; + if (GetShortPathNameA(str,nstr,MAX_PATH)) std::strcpy(str,nstr); + delete[] nstr; +#endif + } + } + + // Open a file (similar to std:: fopen(), but with wide character support on Windows). + inline std::FILE *std_fopen(const char *const path, const char *const mode); + + + //! Open a file. + /** + \param path Path of the filename to open. + \param mode C-string describing the opening mode. + \return Opened file. + \note Same as std::fopen() but throw a \c CImgIOException when + the specified file cannot be opened, instead of returning \c 0. + **/ + inline std::FILE *fopen(const char *const path, const char *const mode) { + if (!path) + throw CImgArgumentException("cimg::fopen(): Specified file path is (null)."); + if (!mode) + throw CImgArgumentException("cimg::fopen(): File '%s', specified mode is (null).", + path); + std::FILE *res = 0; + if (*path=='-' && (!path[1] || path[1]=='.')) { + res = (*mode=='r')?cimg::_stdin():cimg::_stdout(); +#if cimg_OS==2 + if (*mode && mode[1]=='b') { // Force stdin/stdout to be in binary mode +#ifdef __BORLANDC__ + if (setmode(_fileno(res),0x8000)==-1) res = 0; +#else + if (_setmode(_fileno(res),0x8000)==-1) res = 0; +#endif + } +#endif + } else res = cimg::std_fopen(path,mode); + if (!res) throw CImgIOException("cimg::fopen(): Failed to open file '%s' with mode '%s'.", + path,mode); + return res; + } + + //! Close a file. + /** + \param file File to close. + \return \c 0 if file has been closed properly, something else otherwise. + \note Same as std::fclose() but display a warning message if + the file has not been closed properly. + **/ + inline int fclose(std::FILE *file) { + if (!file) { warn("cimg::fclose(): Specified file is (null)."); return 0; } + if (file==cimg::_stdin(false) || file==cimg::_stdout(false)) return 0; + const int errn = std::fclose(file); + if (errn!=0) warn("cimg::fclose(): Error code %d returned during file closing.", + errn); + return errn; + } + + //! Version of 'fseek()' that supports >=64bits offsets everywhere (for Windows). + inline int fseek(FILE *stream, cimg_long offset, int origin) { +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + return _fseeki64(stream,(__int64)offset,origin); +#else + return std::fseek(stream,offset,origin); +#endif + } + + //! Version of 'ftell()' that supports >=64bits offsets everywhere (for Windows). + inline cimg_long ftell(FILE *stream) { +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + return (cimg_long)_ftelli64(stream); +#else + return (cimg_long)std::ftell(stream); +#endif + } + + // Get the file or directory attributes with support for UTF-8 paths (Windows only). +#if cimg_OS==2 + inline DWORD win_getfileattributes(const char *const path); +#endif + + //! Check if a path is a directory. + /** + \param path Specified path to test. + **/ + inline bool is_directory(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==1 + struct stat st_buf; + return (!stat(path,&st_buf) && S_ISDIR(st_buf.st_mode)); +#elif cimg_OS==2 + const DWORD res = win_getfileattributes(path); + return res!=INVALID_FILE_ATTRIBUTES && (res&FILE_ATTRIBUTE_DIRECTORY); +#else + return false; +#endif + } + + //! Check if a path is a file. + /** + \param path Specified path to test. + **/ + inline bool is_file(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==2 + const DWORD res = cimg::win_getfileattributes(path); + return res!=INVALID_FILE_ATTRIBUTES && !(res&FILE_ATTRIBUTE_DIRECTORY); +#else + std::FILE *const file = cimg::std_fopen(path,"rb"); + if (!file) return false; + cimg::fclose(file); + return !is_directory(path); +#endif + } + + //! Get file size. + /** + \param filename Specified filename to get size from. + \return File size or '-1' if file does not exist. + **/ + inline cimg_int64 fsize(const char *const filename) { + std::FILE *const file = cimg::std_fopen(filename,"rb"); + if (!file) return (cimg_int64)-1; + std::fseek(file,0,SEEK_END); + const cimg_int64 siz = (cimg_int64)std::ftell(file); + cimg::fclose(file); + return siz; + } + + //! Get last write time of a given file or directory (multiple-attributes version). + /** + \param path Specified path to get attributes from. + \param[in,out] attr Type of requested time attributes. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second } + Replaced by read attributes after return (or -1 if an error occurred). + \param nb_attr Number of attributes to read/write. + \return Latest read attribute. + **/ + template + inline int fdate(const char *const path, T *attr, const unsigned int nb_attr) { +#define _cimg_fdate_err() for (unsigned int i = 0; i + inline int date(T *attr, const unsigned int nb_attr) { + int res = -1; + cimg::mutex(6); +#if cimg_OS==2 + SYSTEMTIME st; + GetLocalTime(&st); + for (unsigned int i = 0; itm_year + 1900: + attr[i]==1?st->tm_mon + 1: + attr[i]==2?st->tm_mday: + attr[i]==3?st->tm_wday: + attr[i]==4?st->tm_hour: + attr[i]==5?st->tm_min: + attr[i]==6?st->tm_sec: + attr[i]==7?_st.tv_usec/1000:-1); + attr[i] = (T)res; + } +#endif + cimg::mutex(6,0); + return res; + } + + //! Get current local time (single-attribute version). + /** + \param attr Type of requested time attribute. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second | + 7=millisecond } + \return Specified attribute or -1 if an error occurred. + **/ + inline int date(unsigned int attr) { + int out = (int)attr; + return date(&out,1); + } + + // Get/set path to the \c curl binary. + inline const char *curl_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c dcraw binary. + inline const char *dcraw_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the custom's \c custom binary. + inline const char *custom_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the GraphicsMagick's \c gm binary. + inline const char* graphicsmagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gunzip binary. + inline const char *gunzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gzip binary. + inline const char *gzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the ImageMagick's \c convert binary. + inline const char* imagemagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the Medcon's \c medcon binary. + inline const char* medcon_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to store temporary files. + inline const char* temporary_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c wget binary. + inline const char *wget_path(const char *const user_path=0, const bool reinit_path=false); + + //! Split filename into two C-strings \c body and \c extension. + /** + filename and body must not overlap! + **/ + inline const char *split_filename(const char *const filename, char *const body=0) { + if (!filename) { if (body) *body = 0; return ""; } + const char * p = std::strrchr(filename,'.'); + if (!p || std::strchr(p,'/') || std::strchr(p,'\\')) { // No extension. + if (body) std::strcpy(body,filename); + return filename + std::strlen(filename); + } + const unsigned int l = (unsigned int)(p - filename); + if (body) { if (l) std::memcpy(body,filename,l); body[l] = 0; } + return p + 1; + } + + // Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str); + + //! Read data from file. + /** + \param[out] ptr Pointer to memory buffer that will contain the binary data read from file. + \param nmemb Number of elements to read. + \param stream File to read data from. + \return Number of read elements. + \note Same as std::fread() but may display warning message if all elements could not be read. + **/ + template + inline size_t fread(T *const ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fread(): Invalid reading request of %u %s%s from file %p to buffer %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",stream,ptr); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0; + do { + l_to_read = (to_read*sizeof(T))0); + if (to_read>0) + warn("cimg::fread(): Only %lu/%lu elements could be read from file.", + (unsigned long)al_read,(unsigned long)nmemb); + return al_read; + } + + //! Write data to file. + /** + \param ptr Pointer to memory buffer containing the binary data to write on file. + \param nmemb Number of elements to write. + \param[out] stream File to write data on. + \return Number of written elements. + \note Similar to std::fwrite but may display warning messages if all elements could not be written. + **/ + template + inline size_t fwrite(const T *ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",ptr,stream); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0; + do { + l_to_write = (to_write*sizeof(T))0); + if (to_write>0) + warn("cimg::fwrite(): Only %lu/%lu elements could be written in file.", + (unsigned long)al_write,(unsigned long)nmemb); + return al_write; + } + + //! Create an empty file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + **/ + inline void fempty(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::fempty(): Specified filename is (null)."); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (!file) cimg::fclose(nfile); + } + + // Try to guess format from an image file. + inline const char *ftype(std::FILE *const file, const char *const filename); + + // Get or set load from network mode (can be { 0=disabled | 1=enabled }). + inline bool& network_mode(const bool value, const bool is_set) { + static bool mode = true; + if (is_set) { cimg::mutex(0); mode = value; cimg::mutex(0,0); } + return mode; + } + + inline bool& network_mode() { + return network_mode(false,false); + } + + // Load file from network as a local temporary file. + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout=0, const bool try_fallback=false, + const char *const referer=0); + + //! Return options specified on the command line. + inline const char* option(const char *const name, const int argc, const char *const *const argv, + const char *const _default, const char *const usage, const bool reset_static) { + static bool first = true, visu = false; + if (reset_static) { first = true; return 0; } + const char *res = 0; + if (first) { + first = false; + visu = cimg::option("-h",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("-help",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("--help",argc,argv,(char*)0,(char*)0,false)!=0; + } + if (!name && visu) { + if (usage) { + std::fprintf(cimg::output(),"\n %s%s%s",cimg::t_red,cimg::basename(argv[0]),cimg::t_normal); + std::fprintf(cimg::output(),": %s",usage); + std::fprintf(cimg::output()," (%s, %s)\n\n",cimg_date,cimg_time); + } + if (_default) std::fprintf(cimg::output(),"%s\n",_default); + } + if (name) { + if (argc>0) { + int k = 0; + while (k Operating System: %s%-13s%s %s('cimg_OS'=%d)%s\n", + cimg::t_bold, + cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknown"), + cimg::t_normal,cimg::t_green, + cimg_OS, + cimg::t_normal); + + std::fprintf(cimg::output()," > CPU endianness: %s%s Endian%s\n", + cimg::t_bold, + cimg::endianness()?"Big":"Little", + cimg::t_normal); + + std::fprintf(cimg::output()," > Verbosity mode: %s%-13s%s %s('cimg_verbosity'=%d)%s\n", + cimg::t_bold, + cimg_verbosity==0?"Quiet": + cimg_verbosity==1?"Console": + cimg_verbosity==2?"Dialog": + cimg_verbosity==3?"Console+Warnings":"Dialog+Warnings", + cimg::t_normal,cimg::t_green, + cimg_verbosity, + cimg::t_normal); + + std::fprintf(cimg::output()," > Stricts warnings: %s%-13s%s %s('cimg_strict_warnings' %s)%s\n", + cimg::t_bold, +#ifdef cimg_strict_warnings + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Support for C++11: %s%-13s%s %s('cimg_use_cpp11'=%d)%s\n", + cimg::t_bold, + cimg_use_cpp11?"Yes":"No", + cimg::t_normal,cimg::t_green, + (int)cimg_use_cpp11, + cimg::t_normal); + + std::fprintf(cimg::output()," > Using VT100 messages: %s%-13s%s %s('cimg_use_vt100' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_vt100 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Display type: %s%-13s%s %s('cimg_display'=%d)%s\n", + cimg::t_bold, + cimg_display==0?"No display":cimg_display==1?"X11":cimg_display==2?"Windows GDI":"Unknown", + cimg::t_normal,cimg::t_green, + (int)cimg_display, + cimg::t_normal); + +#if cimg_display==1 + std::fprintf(cimg::output()," > Using XShm for X11: %s%-13s%s %s('cimg_use_xshm' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xshm + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using XRand for X11: %s%-13s%s %s('cimg_use_xrandr' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xrandr + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); +#endif + std::fprintf(cimg::output()," > Using OpenMP: %s%-13s%s %s('cimg_use_openmp' %s)%s\n", + cimg::t_bold, +#if cimg_use_openmp!=0 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using PNG library: %s%-13s%s %s('cimg_use_png' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_png + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using JPEG library: %s%-13s%s %s('cimg_use_jpeg' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_jpeg + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using TIFF library: %s%-13s%s %s('cimg_use_tiff' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_tiff + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using Magick++ library: %s%-13s%s %s('cimg_use_magick' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_magick + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using FFTW3 library: %s%-13s%s %s('cimg_use_fftw3' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_fftw3 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using LAPACK library: %s%-13s%s %s('cimg_use_lapack' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_lapack + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + char *const tmp = new char[1024]; + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::curl_path()); + std::fprintf(cimg::output()," > Path of 'curl': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::dcraw_path()); + std::fprintf(cimg::output()," > Path of 'dcraw': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::custom_path()); + std::fprintf(cimg::output()," > Path of 'custom': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::graphicsmagick_path()); + std::fprintf(cimg::output()," > Path of 'graphicsmagick': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::gunzip_path()); + std::fprintf(cimg::output()," > Path of 'gunzip': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::gzip_path()); + std::fprintf(cimg::output()," > Path of 'gzip': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::imagemagick_path()); + std::fprintf(cimg::output()," > Path of 'imagemagick': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::medcon_path()); + std::fprintf(cimg::output()," > Path of 'medcon': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::temporary_path()); + std::fprintf(cimg::output()," > Temporary path: %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::wget_path()); + std::fprintf(cimg::output()," > Path of 'wget': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + std::fprintf(cimg::output(),"\n"); + delete[] tmp; + } + + // Declare LAPACK function signatures if LAPACK support is enabled. +#ifdef cimg_use_lapack + template + inline void getrf(int &N, T *lapA, int *IPIV, int &INFO) { + dgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + inline void getrf(int &N, float *lapA, int *IPIV, int &INFO) { + sgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + template + inline void getri(int &N, T *lapA, int *IPIV, T* WORK, int &LWORK, int &INFO) { + dgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + inline void getri(int &N, float *lapA, int *IPIV, float* WORK, int &LWORK, int &INFO) { + sgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + template + inline void gesvd(char &JOB, int &M, int &N, T *lapA, int &MN, + T *lapS, T *lapU, T *lapV, T *WORK, int &LWORK, int &INFO) { + dgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + inline void gesvd(char &JOB, int &M, int &N, float *lapA, int &MN, + float *lapS, float *lapU, float *lapV, float *WORK, int &LWORK, int &INFO) { + sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + template + inline void getrs(char &TRANS, int &N, T *lapA, int *IPIV, T *lapB, int &INFO) { + int one = 1; + dgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + inline void getrs(char &TRANS, int &N, float *lapA, int *IPIV, float *lapB, int &INFO) { + int one = 1; + sgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + template + inline void syev(char &JOB, char &UPLO, int &N, T *lapA, T *lapW, T *WORK, int &LWORK, int &INFO) { + dsyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + inline void syev(char &JOB, char &UPLO, int &N, float *lapA, float *lapW, float *WORK, int &LWORK, int &INFO) { + ssyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + template + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, T* lapA, int &LDA, + T* lapB, int &LDB, T* WORK, int &LWORK, int &INFO) { + dgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, float* lapA, int &LDA, + float* lapB, int &LDB, float* WORK, int &LWORK, int &INFO) { + sgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + +#endif + + } // namespace cimg { ... + + /*------------------------------------------------ + # + # + # Definition of mathematical operators and + # external functions. + # + # + -------------------------------------------------*/ + +#define _cimg_create_operator(typ) \ + template \ + inline CImg::type> operator+(const typ val, const CImg& img) { \ + return img + val; \ + } \ + template \ + inline CImg::type> operator-(const typ val, const CImg& img) { \ + typedef typename cimg::superset::type Tt; \ + return CImg(img._width,img._height,img._depth,img._spectrum,val)-=img; \ + } \ + template \ + inline CImg::type> operator*(const typ val, const CImg& img) { \ + return img*val; \ + } \ + template \ + inline CImg::type> operator/(const typ val, const CImg& img) { \ + return val*img.get_invert(); \ + } \ + template \ + inline CImg::type> operator&(const typ val, const CImg& img) { \ + return img & val; \ + } \ + template \ + inline CImg::type> operator|(const typ val, const CImg& img) { \ + return img | val; \ + } \ + template \ + inline CImg::type> operator^(const typ val, const CImg& img) { \ + return img ^ val; \ + } \ + template \ + inline bool operator==(const typ val, const CImg& img) { \ + return img == val; \ + } \ + template \ + inline bool operator!=(const typ val, const CImg& img) { \ + return img != val; \ + } + + _cimg_create_operator(bool) + _cimg_create_operator(unsigned char) + _cimg_create_operator(char) + _cimg_create_operator(signed char) + _cimg_create_operator(unsigned short) + _cimg_create_operator(short) + _cimg_create_operator(unsigned int) + _cimg_create_operator(int) + _cimg_create_operator(cimg_uint64) + _cimg_create_operator(cimg_int64) + _cimg_create_operator(float) + _cimg_create_operator(double) + _cimg_create_operator(long double) + + template + inline CImg<_cimg_Tfloat> operator+(const char *const expression, const CImg& img) { + return img + expression; + } + + template + inline CImg<_cimg_Tfloat> operator-(const char *const expression, const CImg& img) { + return CImg<_cimg_Tfloat>(img,false).fill(expression,true)-=img; + } + + template + inline CImg<_cimg_Tfloat> operator*(const char *const expression, const CImg& img) { + return img*expression; + } + + template + inline CImg<_cimg_Tfloat> operator/(const char *const expression, const CImg& img) { + return expression*img.get_invert(); + } + + template + inline CImg operator&(const char *const expression, const CImg& img) { + return img & expression; + } + + template + inline CImg operator|(const char *const expression, const CImg& img) { + return img | expression; + } + + template + inline CImg operator^(const char *const expression, const CImg& img) { + return img ^ expression; + } + + template + inline bool operator==(const char *const expression, const CImg& img) { + return img==expression; + } + + template + inline bool operator!=(const char *const expression, const CImg& img) { + return img!=expression; + } + + template + inline CImg transpose(const CImg& instance) { + return instance.get_transpose(); + } + + template + inline CImg<_cimg_Tfloat> invert(const CImg& instance, const bool use_LU=true) { + return instance.get_invert(use_LU); + } + + template + inline CImg<_cimg_Tfloat> pseudoinvert(const CImg& instance, const bool use_LU=false) { + return instance.get_pseudoinvert(use_LU); + } + +#define _cimg_create_pointwise_function(name) \ + template \ + inline CImg<_cimg_Tfloat> name(const CImg& instance) { \ + return instance.get_##name(); \ + } + + _cimg_create_pointwise_function(sqr) + _cimg_create_pointwise_function(sqrt) + _cimg_create_pointwise_function(exp) + _cimg_create_pointwise_function(log) + _cimg_create_pointwise_function(log2) + _cimg_create_pointwise_function(log10) + _cimg_create_pointwise_function(abs) + _cimg_create_pointwise_function(sign) + _cimg_create_pointwise_function(cos) + _cimg_create_pointwise_function(sin) + _cimg_create_pointwise_function(sinc) + _cimg_create_pointwise_function(tan) + _cimg_create_pointwise_function(acos) + _cimg_create_pointwise_function(asin) + _cimg_create_pointwise_function(atan) + _cimg_create_pointwise_function(cosh) + _cimg_create_pointwise_function(sinh) + _cimg_create_pointwise_function(tanh) + _cimg_create_pointwise_function(acosh) + _cimg_create_pointwise_function(asinh) + _cimg_create_pointwise_function(atanh) + + /*----------------------------------- + # + # Define the CImgDisplay structure + # + ----------------------------------*/ + //! Allow the creation of windows, display images on them and manage user events (keyboard, mouse and windows events). + /** + CImgDisplay methods rely on a low-level graphic library to perform: it can be either \b X-Window + (X11, for Unix-based systems) or \b GDI32 (for Windows-based systems). + If both libraries are missing, CImgDisplay will not be able to display images on screen, and will enter + a minimal mode where warning messages will be outputted each time the program is trying to call one of the + CImgDisplay method. + + The configuration variable \c cimg_display tells about the graphic library used. + It is set automatically by \CImg when one of these graphic libraries has been detected. + But, you can override its value if necessary. Valid choices are: + - 0: Disable display capabilities. + - 1: Use \b X-Window (X11) library. + - 2: Use \b GDI32 library. + + Remember to link your program against \b X11 or \b GDI32 libraries if you use CImgDisplay. + **/ + struct CImgDisplay { + cimg_uint64 _timer, _fps_frames, _fps_timer; + unsigned int _width, _height, _normalization; + float _fps_fps, _min, _max; + bool _is_fullscreen; + char *_title; + unsigned int _window_width, _window_height, _button, *_keys, *_released_keys; + int _window_x, _window_y, _mouse_x, _mouse_y, _wheel; + bool _is_closed, _is_resized, _is_moved, _is_event, + _is_keyESC, _is_keyF1, _is_keyF2, _is_keyF3, _is_keyF4, _is_keyF5, _is_keyF6, _is_keyF7, + _is_keyF8, _is_keyF9, _is_keyF10, _is_keyF11, _is_keyF12, _is_keyPAUSE, _is_key1, _is_key2, + _is_key3, _is_key4, _is_key5, _is_key6, _is_key7, _is_key8, _is_key9, _is_key0, + _is_keyBACKSPACE, _is_keyINSERT, _is_keyHOME, _is_keyPAGEUP, _is_keyTAB, _is_keyQ, _is_keyW, _is_keyE, + _is_keyR, _is_keyT, _is_keyY, _is_keyU, _is_keyI, _is_keyO, _is_keyP, _is_keyDELETE, + _is_keyEND, _is_keyPAGEDOWN, _is_keyCAPSLOCK, _is_keyA, _is_keyS, _is_keyD, _is_keyF, _is_keyG, + _is_keyH, _is_keyJ, _is_keyK, _is_keyL, _is_keyENTER, _is_keySHIFTLEFT, _is_keyZ, _is_keyX, + _is_keyC, _is_keyV, _is_keyB, _is_keyN, _is_keyM, _is_keySHIFTRIGHT, _is_keyARROWUP, _is_keyCTRLLEFT, + _is_keyAPPLEFT, _is_keyALT, _is_keySPACE, _is_keyALTGR, _is_keyAPPRIGHT, _is_keyMENU, _is_keyCTRLRIGHT, + _is_keyARROWLEFT, _is_keyARROWDOWN, _is_keyARROWRIGHT, _is_keyPAD0, _is_keyPAD1, _is_keyPAD2, _is_keyPAD3, + _is_keyPAD4, _is_keyPAD5, _is_keyPAD6, _is_keyPAD7, _is_keyPAD8, _is_keyPAD9, _is_keyPADADD, _is_keyPADSUB, + _is_keyPADMUL, _is_keyPADDIV; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- + +#ifdef cimgdisplay_plugin +#include cimgdisplay_plugin +#endif +#ifdef cimgdisplay_plugin1 +#include cimgdisplay_plugin1 +#endif +#ifdef cimgdisplay_plugin2 +#include cimgdisplay_plugin2 +#endif +#ifdef cimgdisplay_plugin3 +#include cimgdisplay_plugin3 +#endif +#ifdef cimgdisplay_plugin4 +#include cimgdisplay_plugin4 +#endif +#ifdef cimgdisplay_plugin5 +#include cimgdisplay_plugin5 +#endif +#ifdef cimgdisplay_plugin6 +#include cimgdisplay_plugin6 +#endif +#ifdef cimgdisplay_plugin7 +#include cimgdisplay_plugin7 +#endif +#ifdef cimgdisplay_plugin8 +#include cimgdisplay_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + \note If the associated window is visible on the screen, it is closed by the call to the destructor. + **/ + ~CImgDisplay() { + assign(); + delete[] _keys; + delete[] _released_keys; + } + + //! Construct an empty display. + /** + \note Constructing an empty CImgDisplay instance does not make a window appearing on the screen, until + display of valid data is performed. + \par Example + \code + CImgDisplay disp; // Does actually nothing + ... + disp.display(img); // Construct new window and display image in it + \endcode + **/ + CImgDisplay(): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(); + } + + //! Construct a display with specified dimensions. + /** \param width Window width. + \param height Window height. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note A black background is initially displayed on the associated window. + **/ + CImgDisplay(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(width,height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image. + /** \param img Image used as a model to create the window. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note The pixels of the input image are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(img,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list. + /** \param list The images list to display. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note All images of the list, appended along the X-axis, are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(list,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of an existing one. + /** + \param disp Display instance to copy. + \note The pixel buffer of the input window is initially displayed on the associated window. + **/ + CImgDisplay(const CImgDisplay& disp): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(disp); + } + + //! Take a screenshot. + /** + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(CImg& img) { + return screenshot(0,0,cimg::type::max(),cimg::type::max(),img); + } + +#if cimg_display==0 + + static void _no_display_exception() { + throw CImgDisplayException("CImgDisplay(): No display available."); + } + + //! Destructor - Empty constructor \inplace. + /** + \note Replace the current instance by an empty display. + **/ + CImgDisplay& assign() { + return flush(); + } + + //! Construct a display with specified dimensions \inplace. + /** + **/ + CImgDisplay& assign(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + cimg::unused(width,height,title,normalization,is_fullscreen,is_closed); + _no_display_exception(); + return assign(); + } + + //! Construct a display from an image \inplace. + /** + **/ + template + CImgDisplay& assign(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(img._width,img._height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list \inplace. + /** + **/ + template + CImgDisplay& assign(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(list._width,list._width,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of another one \inplace. + /** + **/ + CImgDisplay& assign(const CImgDisplay &disp) { + _no_display_exception(); + return assign(disp._width,disp._height); + } + +#endif + + //! Return a reference to an empty display. + /** + \note Can be useful for writing function prototypes where one of the argument (of type CImgDisplay&) + must have a default value. + \par Example + \code + void foo(CImgDisplay& disp=CImgDisplay::empty()); + \endcode + **/ + static CImgDisplay& empty() { + static CImgDisplay _empty; + return _empty.assign(); + } + + //! Return a reference to an empty display \const. + static const CImgDisplay& const_empty() { + static const CImgDisplay _empty; + return _empty; + } + +#define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,-25,-85,false), \ + CImgDisplay::_fitscreen(dx,dy,dz,-25,-85,true) + static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy, const unsigned int dz, + const int dmin, const int dmax, const bool return_y) { + const int + u = CImgDisplay::screen_width(), + v = CImgDisplay::screen_height(); + const float + mw = dmin<0?cimg::round(u*-dmin/100.f):(float)dmin, + mh = dmin<0?cimg::round(v*-dmin/100.f):(float)dmin, + Mw = dmax<0?cimg::round(u*-dmax/100.f):(float)dmax, + Mh = dmax<0?cimg::round(v*-dmax/100.f):(float)dmax; + float + w = (float)std::max(1U,dx), + h = (float)std::max(1U,dy); + if (dz>1) { w+=dz; h+=dz; } + if (wMw) { h = h*Mw/w; w = Mw; } + if (h>Mh) { w = w*Mh/h; h = Mh; } + if (wdisp = img is equivalent to disp.display(img). + **/ + template + CImgDisplay& operator=(const CImg& img) { + return display(img); + } + + //! Display list of images on associated window. + /** + \note disp = list is equivalent to disp.display(list). + **/ + template + CImgDisplay& operator=(const CImgList& list) { + return display(list); + } + + //! Construct a display as a copy of another one \inplace. + /** + \note Equivalent to assign(const CImgDisplay&). + **/ + CImgDisplay& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return \c false if display is empty, \c true otherwise. + /** + \note if (disp) { ... } is equivalent to if (!disp.is_empty()) { ... }. + **/ + operator bool() const { + return !is_empty(); + } + + //@} + //------------------------------------------ + // + //! \name Instance Checking + //@{ + //------------------------------------------ + + //! Return \c true if display is empty, \c false otherwise. + /** + **/ + bool is_empty() const { + return !(_width && _height); + } + + //! Return \c true if display is closed (i.e. not visible on the screen), \c false otherwise. + /** + \note + - When a user physically closes the associated window, the display is set to closed. + - A closed display is not destroyed. Its associated window can be show again on the screen using show(). + **/ + bool is_closed() const { + return _is_closed; + } + + //! Return \c true if associated window has been resized on the screen, \c false otherwise. + /** + **/ + bool is_resized() const { + return _is_resized; + } + + //! Return \c true if associated window has been moved on the screen, \c false otherwise. + /** + **/ + bool is_moved() const { + return _is_moved; + } + + //! Return \c true if any event has occurred on the associated window, \c false otherwise. + /** + **/ + bool is_event() const { + return _is_event; + } + + //! Return \c true if current display is in fullscreen mode, \c false otherwise. + /** + **/ + bool is_fullscreen() const { + return _is_fullscreen; + } + + //! Return \c true if any key is being pressed on the associated window, \c false otherwise. + /** + \note The methods below do the same only for specific keys. + **/ + bool is_key() const { + return _is_keyESC || _is_keyF1 || _is_keyF2 || _is_keyF3 || + _is_keyF4 || _is_keyF5 || _is_keyF6 || _is_keyF7 || + _is_keyF8 || _is_keyF9 || _is_keyF10 || _is_keyF11 || + _is_keyF12 || _is_keyPAUSE || _is_key1 || _is_key2 || + _is_key3 || _is_key4 || _is_key5 || _is_key6 || + _is_key7 || _is_key8 || _is_key9 || _is_key0 || + _is_keyBACKSPACE || _is_keyINSERT || _is_keyHOME || + _is_keyPAGEUP || _is_keyTAB || _is_keyQ || _is_keyW || + _is_keyE || _is_keyR || _is_keyT || _is_keyY || + _is_keyU || _is_keyI || _is_keyO || _is_keyP || + _is_keyDELETE || _is_keyEND || _is_keyPAGEDOWN || + _is_keyCAPSLOCK || _is_keyA || _is_keyS || _is_keyD || + _is_keyF || _is_keyG || _is_keyH || _is_keyJ || + _is_keyK || _is_keyL || _is_keyENTER || + _is_keySHIFTLEFT || _is_keyZ || _is_keyX || _is_keyC || + _is_keyV || _is_keyB || _is_keyN || _is_keyM || + _is_keySHIFTRIGHT || _is_keyARROWUP || _is_keyCTRLLEFT || + _is_keyAPPLEFT || _is_keyALT || _is_keySPACE || _is_keyALTGR || + _is_keyAPPRIGHT || _is_keyMENU || _is_keyCTRLRIGHT || + _is_keyARROWLEFT || _is_keyARROWDOWN || _is_keyARROWRIGHT || + _is_keyPAD0 || _is_keyPAD1 || _is_keyPAD2 || + _is_keyPAD3 || _is_keyPAD4 || _is_keyPAD5 || + _is_keyPAD6 || _is_keyPAD7 || _is_keyPAD8 || + _is_keyPAD9 || _is_keyPADADD || _is_keyPADSUB || + _is_keyPADMUL || _is_keyPADDIV; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode Keycode to test. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.key(cimg::keyTAB)) { ... } // Equivalent to 'if (disp.is_keyTAB())' + disp.wait(); + } + \endcode + **/ + bool is_key(const unsigned int keycode) const { +#define _cimg_iskey_test(k) if (keycode==cimg::key##k) return _is_key##k; + _cimg_iskey_test(ESC); _cimg_iskey_test(F1); _cimg_iskey_test(F2); _cimg_iskey_test(F3); + _cimg_iskey_test(F4); _cimg_iskey_test(F5); _cimg_iskey_test(F6); _cimg_iskey_test(F7); + _cimg_iskey_test(F8); _cimg_iskey_test(F9); _cimg_iskey_test(F10); _cimg_iskey_test(F11); + _cimg_iskey_test(F12); _cimg_iskey_test(PAUSE); _cimg_iskey_test(1); _cimg_iskey_test(2); + _cimg_iskey_test(3); _cimg_iskey_test(4); _cimg_iskey_test(5); _cimg_iskey_test(6); + _cimg_iskey_test(7); _cimg_iskey_test(8); _cimg_iskey_test(9); _cimg_iskey_test(0); + _cimg_iskey_test(BACKSPACE); _cimg_iskey_test(INSERT); _cimg_iskey_test(HOME); + _cimg_iskey_test(PAGEUP); _cimg_iskey_test(TAB); _cimg_iskey_test(Q); _cimg_iskey_test(W); + _cimg_iskey_test(E); _cimg_iskey_test(R); _cimg_iskey_test(T); _cimg_iskey_test(Y); + _cimg_iskey_test(U); _cimg_iskey_test(I); _cimg_iskey_test(O); _cimg_iskey_test(P); + _cimg_iskey_test(DELETE); _cimg_iskey_test(END); _cimg_iskey_test(PAGEDOWN); + _cimg_iskey_test(CAPSLOCK); _cimg_iskey_test(A); _cimg_iskey_test(S); _cimg_iskey_test(D); + _cimg_iskey_test(F); _cimg_iskey_test(G); _cimg_iskey_test(H); _cimg_iskey_test(J); + _cimg_iskey_test(K); _cimg_iskey_test(L); _cimg_iskey_test(ENTER); + _cimg_iskey_test(SHIFTLEFT); _cimg_iskey_test(Z); _cimg_iskey_test(X); _cimg_iskey_test(C); + _cimg_iskey_test(V); _cimg_iskey_test(B); _cimg_iskey_test(N); _cimg_iskey_test(M); + _cimg_iskey_test(SHIFTRIGHT); _cimg_iskey_test(ARROWUP); _cimg_iskey_test(CTRLLEFT); + _cimg_iskey_test(APPLEFT); _cimg_iskey_test(ALT); _cimg_iskey_test(SPACE); _cimg_iskey_test(ALTGR); + _cimg_iskey_test(APPRIGHT); _cimg_iskey_test(MENU); _cimg_iskey_test(CTRLRIGHT); + _cimg_iskey_test(ARROWLEFT); _cimg_iskey_test(ARROWDOWN); _cimg_iskey_test(ARROWRIGHT); + _cimg_iskey_test(PAD0); _cimg_iskey_test(PAD1); _cimg_iskey_test(PAD2); + _cimg_iskey_test(PAD3); _cimg_iskey_test(PAD4); _cimg_iskey_test(PAD5); + _cimg_iskey_test(PAD6); _cimg_iskey_test(PAD7); _cimg_iskey_test(PAD8); + _cimg_iskey_test(PAD9); _cimg_iskey_test(PADADD); _cimg_iskey_test(PADSUB); + _cimg_iskey_test(PADMUL); _cimg_iskey_test(PADDIV); + return false; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode C-string containing the keycode label of the key to test. + \note Use it when the key you want to test can be dynamically set by the user. + \par Example + \code + CImgDisplay disp(400,400); + const char *const keycode = "TAB"; + while (!disp.is_closed()) { + if (disp.is_key(keycode)) { ... } // Equivalent to 'if (disp.is_keyTAB())' + disp.wait(); + } + \endcode + **/ + bool& is_key(const char *const keycode) { + static bool f = false; + f = false; +#define _cimg_iskey_test2(k) if (!cimg::strcasecmp(keycode,#k)) return _is_key##k; + _cimg_iskey_test2(ESC); _cimg_iskey_test2(F1); _cimg_iskey_test2(F2); _cimg_iskey_test2(F3); + _cimg_iskey_test2(F4); _cimg_iskey_test2(F5); _cimg_iskey_test2(F6); _cimg_iskey_test2(F7); + _cimg_iskey_test2(F8); _cimg_iskey_test2(F9); _cimg_iskey_test2(F10); _cimg_iskey_test2(F11); + _cimg_iskey_test2(F12); _cimg_iskey_test2(PAUSE); _cimg_iskey_test2(1); _cimg_iskey_test2(2); + _cimg_iskey_test2(3); _cimg_iskey_test2(4); _cimg_iskey_test2(5); _cimg_iskey_test2(6); + _cimg_iskey_test2(7); _cimg_iskey_test2(8); _cimg_iskey_test2(9); _cimg_iskey_test2(0); + _cimg_iskey_test2(BACKSPACE); _cimg_iskey_test2(INSERT); _cimg_iskey_test2(HOME); + _cimg_iskey_test2(PAGEUP); _cimg_iskey_test2(TAB); _cimg_iskey_test2(Q); _cimg_iskey_test2(W); + _cimg_iskey_test2(E); _cimg_iskey_test2(R); _cimg_iskey_test2(T); _cimg_iskey_test2(Y); + _cimg_iskey_test2(U); _cimg_iskey_test2(I); _cimg_iskey_test2(O); _cimg_iskey_test2(P); + _cimg_iskey_test2(DELETE); _cimg_iskey_test2(END); _cimg_iskey_test2(PAGEDOWN); + _cimg_iskey_test2(CAPSLOCK); _cimg_iskey_test2(A); _cimg_iskey_test2(S); _cimg_iskey_test2(D); + _cimg_iskey_test2(F); _cimg_iskey_test2(G); _cimg_iskey_test2(H); _cimg_iskey_test2(J); + _cimg_iskey_test2(K); _cimg_iskey_test2(L); _cimg_iskey_test2(ENTER); + _cimg_iskey_test2(SHIFTLEFT); _cimg_iskey_test2(Z); _cimg_iskey_test2(X); _cimg_iskey_test2(C); + _cimg_iskey_test2(V); _cimg_iskey_test2(B); _cimg_iskey_test2(N); _cimg_iskey_test2(M); + _cimg_iskey_test2(SHIFTRIGHT); _cimg_iskey_test2(ARROWUP); _cimg_iskey_test2(CTRLLEFT); + _cimg_iskey_test2(APPLEFT); _cimg_iskey_test2(ALT); _cimg_iskey_test2(SPACE); _cimg_iskey_test2(ALTGR); + _cimg_iskey_test2(APPRIGHT); _cimg_iskey_test2(MENU); _cimg_iskey_test2(CTRLRIGHT); + _cimg_iskey_test2(ARROWLEFT); _cimg_iskey_test2(ARROWDOWN); _cimg_iskey_test2(ARROWRIGHT); + _cimg_iskey_test2(PAD0); _cimg_iskey_test2(PAD1); _cimg_iskey_test2(PAD2); + _cimg_iskey_test2(PAD3); _cimg_iskey_test2(PAD4); _cimg_iskey_test2(PAD5); + _cimg_iskey_test2(PAD6); _cimg_iskey_test2(PAD7); _cimg_iskey_test2(PAD8); + _cimg_iskey_test2(PAD9); _cimg_iskey_test2(PADADD); _cimg_iskey_test2(PADSUB); + _cimg_iskey_test2(PADMUL); _cimg_iskey_test2(PADDIV); + return f; + } + + //! Return \c true if specified key sequence has been typed on the associated window, \c false otherwise. + /** + \param keycodes_sequence Buffer of keycodes to test. + \param length Number of keys in the \c keycodes_sequence buffer. + \param remove_sequence Tells if the key sequence must be removed from the key history, if found. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + const unsigned int key_seq[] = { cimg::keyCTRLLEFT, cimg::keyD }; + while (!disp.is_closed()) { + if (disp.is_key_sequence(key_seq,2)) { ... } // Test for the 'CTRL+D' keyboard event + disp.wait(); + } + \endcode + **/ + bool is_key_sequence(const unsigned int *const keycodes_sequence, const unsigned int length, + const bool remove_sequence=false) { + if (keycodes_sequence && length) { + const unsigned int + *const ps_end = keycodes_sequence + length - 1, + *const pk_end = (unsigned int*)_keys + 1 + 128 - length, + k = *ps_end; + for (unsigned int *pk = (unsigned int*)_keys; pk[0,255]. + If the range of values of the data to display is different, a normalization may be required for displaying + the data in a correct way. The normalization type can be one of: + - \c 0: Value normalization is disabled. It is then assumed that all input data to be displayed by the + CImgDisplay instance have values in range [0,255]. + - \c 1: Value normalization is always performed (this is the default behavior). + Before displaying an input image, its values will be (virtually) stretched + in range [0,255], so that the contrast of the displayed pixels will be maximum. + Use this mode for images whose minimum and maximum values are not prescribed to known values + (e.g. float-valued images). + Note that when normalized versions of images are computed for display purposes, the actual values of these + images are not modified. + - \c 2: Value normalization is performed once (on the first image display), then the same normalization + coefficients are kept for next displayed frames. + - \c 3: Value normalization depends on the pixel type of the data to display. For integer pixel types, + the normalization is done regarding the minimum/maximum values of the type (no normalization occurs then + for unsigned char). + For float-valued pixel types, the normalization is done regarding the minimum/maximum value of the image + data instead. + **/ + unsigned int normalization() const { + return _normalization; + } + + //! Return title of the associated window as a C-string. + /** + \note Window title may be not visible, depending on the used window manager or if the current display is + in fullscreen mode. + **/ + const char *title() const { + return _title?_title:""; + } + + //! Return width of the associated window. + /** + \note The width of the display (i.e. the width of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual width of the associated window. + **/ + int window_width() const { + return (int)_window_width; + } + + //! Return height of the associated window. + /** + \note The height of the display (i.e. the height of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual height of the associated window. + **/ + int window_height() const { + return (int)_window_height; + } + + //! Return X-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_x() const { + return _window_x; + } + + //! Return Y-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_y() const { + return _window_y; + } + + //! Return X-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,width()-1]. + **/ + int mouse_x() const { + return _mouse_x; + } + + //! Return Y-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,height()-1]. + **/ + int mouse_y() const { + return _mouse_y; + } + + //! Return current state of the mouse buttons. + /** + \note Three mouse buttons can be managed. If one button is pressed, its corresponding bit in the returned + value is set: + - bit \c 0 (value \c 0x1): State of the left mouse button. + - bit \c 1 (value \c 0x2): State of the right mouse button. + - bit \c 2 (value \c 0x4): State of the middle mouse button. + + Several bits can be activated if more than one button are pressed at the same time. + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.button()&1) { // Left button clicked + ... + } + if (disp.button()&2) { // Right button clicked + ... + } + if (disp.button()&4) { // Middle button clicked + ... + } + disp.wait(); + } + \endcode + **/ + unsigned int button() const { + return _button; + } + + //! Return current state of the mouse wheel. + /** + \note + - The returned value can be positive or negative depending on whether the mouse wheel has been scrolled + forward or backward. + - Scrolling the wheel forward add \c 1 to the wheel value. + - Scrolling the wheel backward subtract \c 1 to the wheel value. + - The returned value cumulates the number of forward of backward scrolls since the creation of the display, + or since the last reset of the wheel value (using set_wheel()). It is strongly recommended to quickly reset + the wheel counter when an action has been performed regarding the current wheel value. + Otherwise, the returned wheel value may be for instance \c 0 despite the fact that many scrolls have been done + (as many in forward as in backward directions). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.wheel()) { + int counter = disp.wheel(); // Read the state of the mouse wheel + ... // Do what you want with 'counter' + disp.set_wheel(); // Reset the wheel value to 0 + } + disp.wait(); + } + \endcode + **/ + int wheel() const { + return _wheel; + } + + //! Return one entry from the pressed keys history. + /** + \param pos Index to read from the pressed keys history (index \c 0 corresponds to latest entry). + \return Keycode of a pressed key or \c 0 for a released key. + \note + - Each CImgDisplay stores a history of the pressed keys in a buffer of size \c 128. When a new key is pressed, + its keycode is stored in the pressed keys history. When a key is released, \c 0 is put instead. + This means that up to the 64 last pressed keys may be read from the pressed keys history. + When a new value is stored, the pressed keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int& key(const unsigned int pos=0) const { + static unsigned int key0; + return pos<128?_keys[pos]:(key0 = 0); + + } + + //! Return one entry from the released keys history. + /** + \param pos Index to read from the released keys history (index \c 0 corresponds to latest entry). + \return Keycode of a released key or \c 0 for a pressed key. + \note + - Each CImgDisplay stores a history of the released keys in a buffer of size \c 128. When a new key is released, + its keycode is stored in the pressed keys history. When a key is pressed, \c 0 is put instead. + This means that up to the 64 last released keys may be read from the released keys history. + When a new value is stored, the released keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int& released_key(const unsigned int pos=0) const { + static unsigned int key0; + return pos<128?_released_keys[pos]:(key0 = 0); + } + + //! Return keycode corresponding to the specified string. + /** + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + const unsigned int keyTAB = CImgDisplay::keycode("TAB"); // Return cimg::keyTAB + \endcode + **/ + static unsigned int keycode(const char *const keycode) { +#define _cimg_keycode(k) if (!cimg::strcasecmp(keycode,#k)) return cimg::key##k; + _cimg_keycode(ESC); _cimg_keycode(F1); _cimg_keycode(F2); _cimg_keycode(F3); + _cimg_keycode(F4); _cimg_keycode(F5); _cimg_keycode(F6); _cimg_keycode(F7); + _cimg_keycode(F8); _cimg_keycode(F9); _cimg_keycode(F10); _cimg_keycode(F11); + _cimg_keycode(F12); _cimg_keycode(PAUSE); _cimg_keycode(1); _cimg_keycode(2); + _cimg_keycode(3); _cimg_keycode(4); _cimg_keycode(5); _cimg_keycode(6); + _cimg_keycode(7); _cimg_keycode(8); _cimg_keycode(9); _cimg_keycode(0); + _cimg_keycode(BACKSPACE); _cimg_keycode(INSERT); _cimg_keycode(HOME); + _cimg_keycode(PAGEUP); _cimg_keycode(TAB); _cimg_keycode(Q); _cimg_keycode(W); + _cimg_keycode(E); _cimg_keycode(R); _cimg_keycode(T); _cimg_keycode(Y); + _cimg_keycode(U); _cimg_keycode(I); _cimg_keycode(O); _cimg_keycode(P); + _cimg_keycode(DELETE); _cimg_keycode(END); _cimg_keycode(PAGEDOWN); + _cimg_keycode(CAPSLOCK); _cimg_keycode(A); _cimg_keycode(S); _cimg_keycode(D); + _cimg_keycode(F); _cimg_keycode(G); _cimg_keycode(H); _cimg_keycode(J); + _cimg_keycode(K); _cimg_keycode(L); _cimg_keycode(ENTER); + _cimg_keycode(SHIFTLEFT); _cimg_keycode(Z); _cimg_keycode(X); _cimg_keycode(C); + _cimg_keycode(V); _cimg_keycode(B); _cimg_keycode(N); _cimg_keycode(M); + _cimg_keycode(SHIFTRIGHT); _cimg_keycode(ARROWUP); _cimg_keycode(CTRLLEFT); + _cimg_keycode(APPLEFT); _cimg_keycode(ALT); _cimg_keycode(SPACE); _cimg_keycode(ALTGR); + _cimg_keycode(APPRIGHT); _cimg_keycode(MENU); _cimg_keycode(CTRLRIGHT); + _cimg_keycode(ARROWLEFT); _cimg_keycode(ARROWDOWN); _cimg_keycode(ARROWRIGHT); + _cimg_keycode(PAD0); _cimg_keycode(PAD1); _cimg_keycode(PAD2); + _cimg_keycode(PAD3); _cimg_keycode(PAD4); _cimg_keycode(PAD5); + _cimg_keycode(PAD6); _cimg_keycode(PAD7); _cimg_keycode(PAD8); + _cimg_keycode(PAD9); _cimg_keycode(PADADD); _cimg_keycode(PADSUB); + _cimg_keycode(PADMUL); _cimg_keycode(PADDIV); + return 0; + } + + //! Return the current refresh rate, in frames per second. + /** + \note Returns a significant value when the current instance is used to display successive frames. + It measures the delay between successive calls to frames_per_second(). + **/ + float frames_per_second() { + if (!_fps_timer) _fps_timer = cimg::time(); + const float delta = (float)((cimg::time() - _fps_timer)/1000.f); + ++_fps_frames; + if (delta>=1) { + _fps_fps = _fps_frames/delta; + _fps_frames = 0; + _fps_timer = cimg::time(); + } + return _fps_fps; + } + + // Move current display window so that its content stays inside the current screen. + CImgDisplay& move_inside_screen() { + if (is_empty()) return *this; + const int + x0 = window_x(), + y0 = window_y(), + x1 = x0 + window_width() - 1, + y1 = y0 + window_height() - 1, + sw = CImgDisplay::screen_width(), + sh = CImgDisplay::screen_height(); + if (x0<0 || y0<0 || x1>=sw || y1>=sh) + move(std::max(0,std::min(x0,sw - x1 + x0)), + std::max(0,std::min(y0,sh - y1 + y0))); + return *this; + } + + //@} + //--------------------------------------- + // + //! \name Window Manipulation + //@{ + //--------------------------------------- + +#if cimg_display==0 + + //! Display image on associated window. + /** + \param img Input image to display. + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImg& img) { + return assign(img); + } + +#endif + + //! Display list of images on associated window. + /** + \param list List of images to display. + \param axis Axis used to append the images along, for the visualization (can be \c x, \c y, \c z or \c c). + \param align Relative position of aligned images when displaying lists with images of different sizes + (\c 0 for upper-left, \c 0.5 for centering and \c 1 for lower-right). + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImgList& list, const char axis='x', const float align=0) { + if (list._width==1) { + const CImg& img = list[0]; + if (img._depth==1 && (img._spectrum==1 || img._spectrum>=3) && _normalization!=1) return display(img); + } + CImgList::ucharT> visu(list._width); + unsigned int dims = 0; + cimglist_for(list,l) { + const CImg& img = list._data[l]; + img._get_select(*this,_normalization,(img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2).move_to(visu[l]); + dims = std::max(dims,visu[l]._spectrum); + } + cimglist_for(list,l) if (visu[l]._spectrumimg.width() become equal, as well as height() and + img.height(). + - The associated window is also resized to specified dimensions. + **/ + template + CImgDisplay& resize(const CImg& img, const bool force_redraw=true) { + return resize(img._width,img._height,force_redraw); + } + + //! Resize display to the size of another CImgDisplay instance. + /** + \param disp Input display to take size from. + \param force_redraw Tells if the previous window content must be resized and updated as well. + \note + - Calling this method ensures that width() and disp.width() become equal, as well as height() and + disp.height(). + - The associated window is also resized to specified dimensions. + **/ + CImgDisplay& resize(const CImgDisplay& disp, const bool force_redraw=true) { + return resize(disp.width(),disp.height(),force_redraw); + } + + // [internal] Render pixel buffer with size (wd,hd) from source buffer of size (ws,hs). + template + static void _render_resize(const T *ptrs, const unsigned int ws, const unsigned int hs, + t *ptrd, const unsigned int wd, const unsigned int hd) { + typedef typename cimg::last::type ulongT; + const ulongT one = (ulongT)1; + CImg off_x(wd), off_y(hd + 1); + if (wd==ws) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + for (unsigned int x = 0; xstd::printf(). + \warning As the first argument is a format string, it is highly recommended to write + \code + disp.set_title("%s",window_title); + \endcode + instead of + \code + disp.set_title(window_title); + \endcode + if \c window_title can be arbitrary, to prevent nasty memory access. + **/ + CImgDisplay& set_title(const char *const format, ...) { + return assign(0,0,format); + } + +#endif + + //! Enable or disable fullscreen mode. + /** + \param is_fullscreen Tells is the fullscreen mode must be activated or not. + \param force_redraw Tells if the previous window content must be displayed as well. + \note + - When the fullscreen mode is enabled, the associated window fills the entire screen but the size of the + current display is not modified. + - The screen resolution may be switched to fit the associated window size and ensure it appears the largest + as possible. + For X-Window (X11) users, the configuration flag \c cimg_use_xrandr has to be set to allow the screen + resolution change (requires the X11 extensions to be enabled). + **/ + CImgDisplay& set_fullscreen(const bool is_fullscreen, const bool force_redraw=true) { + if (is_empty() || _is_fullscreen==is_fullscreen) return *this; + return toggle_fullscreen(force_redraw); + } + +#if cimg_display==0 + + //! Toggle fullscreen mode. + /** + \param force_redraw Tells if the previous window content must be displayed as well. + \note Enable fullscreen mode if it was not enabled, and disable it otherwise. + **/ + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + return assign(_width,_height,0,3,force_redraw); + } + + //! Show mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& show_mouse() { + return assign(); + } + + //! Hide mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& hide_mouse() { + return assign(); + } + + //! Move mouse pointer to a specified location. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& set_mouse(const int pos_x, const int pos_y) { + return assign(pos_x,pos_y); + } + +#endif + + //! Simulate a mouse button release event. + /** + \note All mouse buttons are considered released at the same time. + **/ + CImgDisplay& set_button() { + _button = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a mouse button press or release event. + /** + \param button Buttons event code, where each button is associated to a single bit. + \param is_pressed Tells if the mouse button is considered as pressed or released. + **/ + CImgDisplay& set_button(const unsigned int button, const bool is_pressed=true) { + const unsigned int buttoncode = button==1U?1U:button==2U?2U:button==3U?4U:0U; + if (is_pressed) _button |= buttoncode; else _button &= ~buttoncode; + _is_event = buttoncode?true:false; + if (buttoncode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all mouse wheel events. + /** + \note Make wheel() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_wheel() { + _wheel = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a wheel event. + /** + \param amplitude Amplitude of the wheel scrolling to simulate. + \note Make wheel() to return \c amplitude, if called afterwards. + **/ + CImgDisplay& set_wheel(const int amplitude) { + _wheel+=amplitude; + _is_event = amplitude?true:false; + if (amplitude) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all key events. + /** + \note Make key() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_key() { + std::memset((void*)_keys,0,128*sizeof(unsigned int)); + std::memset((void*)_released_keys,0,128*sizeof(unsigned int)); + _is_keyESC = _is_keyF1 = _is_keyF2 = _is_keyF3 = _is_keyF4 = _is_keyF5 = _is_keyF6 = _is_keyF7 = _is_keyF8 = + _is_keyF9 = _is_keyF10 = _is_keyF11 = _is_keyF12 = _is_keyPAUSE = _is_key1 = _is_key2 = _is_key3 = _is_key4 = + _is_key5 = _is_key6 = _is_key7 = _is_key8 = _is_key9 = _is_key0 = _is_keyBACKSPACE = _is_keyINSERT = + _is_keyHOME = _is_keyPAGEUP = _is_keyTAB = _is_keyQ = _is_keyW = _is_keyE = _is_keyR = _is_keyT = _is_keyY = + _is_keyU = _is_keyI = _is_keyO = _is_keyP = _is_keyDELETE = _is_keyEND = _is_keyPAGEDOWN = _is_keyCAPSLOCK = + _is_keyA = _is_keyS = _is_keyD = _is_keyF = _is_keyG = _is_keyH = _is_keyJ = _is_keyK = _is_keyL = + _is_keyENTER = _is_keySHIFTLEFT = _is_keyZ = _is_keyX = _is_keyC = _is_keyV = _is_keyB = _is_keyN = + _is_keyM = _is_keySHIFTRIGHT = _is_keyARROWUP = _is_keyCTRLLEFT = _is_keyAPPLEFT = _is_keyALT = _is_keySPACE = + _is_keyALTGR = _is_keyAPPRIGHT = _is_keyMENU = _is_keyCTRLRIGHT = _is_keyARROWLEFT = _is_keyARROWDOWN = + _is_keyARROWRIGHT = _is_keyPAD0 = _is_keyPAD1 = _is_keyPAD2 = _is_keyPAD3 = _is_keyPAD4 = _is_keyPAD5 = + _is_keyPAD6 = _is_keyPAD7 = _is_keyPAD8 = _is_keyPAD9 = _is_keyPADADD = _is_keyPADSUB = _is_keyPADMUL = + _is_keyPADDIV = false; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a keyboard press/release event. + /** + \param keycode Keycode of the associated key. + \param is_pressed Tells if the key is considered as pressed or released. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + CImgDisplay& set_key(const unsigned int keycode, const bool is_pressed=true) { +#define _cimg_set_key(k) if (keycode==cimg::key##k) _is_key##k = is_pressed; + _cimg_set_key(ESC); _cimg_set_key(F1); _cimg_set_key(F2); _cimg_set_key(F3); + _cimg_set_key(F4); _cimg_set_key(F5); _cimg_set_key(F6); _cimg_set_key(F7); + _cimg_set_key(F8); _cimg_set_key(F9); _cimg_set_key(F10); _cimg_set_key(F11); + _cimg_set_key(F12); _cimg_set_key(PAUSE); _cimg_set_key(1); _cimg_set_key(2); + _cimg_set_key(3); _cimg_set_key(4); _cimg_set_key(5); _cimg_set_key(6); + _cimg_set_key(7); _cimg_set_key(8); _cimg_set_key(9); _cimg_set_key(0); + _cimg_set_key(BACKSPACE); _cimg_set_key(INSERT); _cimg_set_key(HOME); + _cimg_set_key(PAGEUP); _cimg_set_key(TAB); _cimg_set_key(Q); _cimg_set_key(W); + _cimg_set_key(E); _cimg_set_key(R); _cimg_set_key(T); _cimg_set_key(Y); + _cimg_set_key(U); _cimg_set_key(I); _cimg_set_key(O); _cimg_set_key(P); + _cimg_set_key(DELETE); _cimg_set_key(END); _cimg_set_key(PAGEDOWN); + _cimg_set_key(CAPSLOCK); _cimg_set_key(A); _cimg_set_key(S); _cimg_set_key(D); + _cimg_set_key(F); _cimg_set_key(G); _cimg_set_key(H); _cimg_set_key(J); + _cimg_set_key(K); _cimg_set_key(L); _cimg_set_key(ENTER); + _cimg_set_key(SHIFTLEFT); _cimg_set_key(Z); _cimg_set_key(X); _cimg_set_key(C); + _cimg_set_key(V); _cimg_set_key(B); _cimg_set_key(N); _cimg_set_key(M); + _cimg_set_key(SHIFTRIGHT); _cimg_set_key(ARROWUP); _cimg_set_key(CTRLLEFT); + _cimg_set_key(APPLEFT); _cimg_set_key(ALT); _cimg_set_key(SPACE); _cimg_set_key(ALTGR); + _cimg_set_key(APPRIGHT); _cimg_set_key(MENU); _cimg_set_key(CTRLRIGHT); + _cimg_set_key(ARROWLEFT); _cimg_set_key(ARROWDOWN); _cimg_set_key(ARROWRIGHT); + _cimg_set_key(PAD0); _cimg_set_key(PAD1); _cimg_set_key(PAD2); + _cimg_set_key(PAD3); _cimg_set_key(PAD4); _cimg_set_key(PAD5); + _cimg_set_key(PAD6); _cimg_set_key(PAD7); _cimg_set_key(PAD8); + _cimg_set_key(PAD9); _cimg_set_key(PADADD); _cimg_set_key(PADSUB); + _cimg_set_key(PADMUL); _cimg_set_key(PADDIV); + if (is_pressed) { + if (*_keys) + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = keycode; + if (*_released_keys) { + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = 0; + } + } else { + if (*_keys) { + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = 0; + } + if (*_released_keys) + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = keycode; + } + _is_event = keycode?true:false; + if (keycode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all display events. + /** + \note Remove all passed events from the current display. + **/ + CImgDisplay& flush() { + set_key().set_button().set_wheel(); + _is_resized = _is_moved = _is_event = false; + _fps_timer = _fps_frames = _timer = 0; + _fps_fps = 0; + return *this; + } + + //! Wait for any user event occurring on the current display. + CImgDisplay& wait() { + wait(*this); + return *this; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \note Similar to cimg::wait(). + **/ + CImgDisplay& wait(const unsigned int milliseconds) { + cimg::wait(milliseconds,&_timer); + return *this; + } + + //! Wait for any event occurring on the display \c disp1. + static void wait(CImgDisplay& disp1) { + disp1._is_event = false; + while (!disp1._is_closed && !disp1._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1 or \c disp2. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2) { + disp1._is_event = disp2._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed) && + !disp1._is_event && !disp2._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2 or \c disp3. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3) { + disp1._is_event = disp2._is_event = disp3._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3 or \c disp4. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4 or \c disp5. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, + CImgDisplay& disp5) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event) + wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp6. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp7. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp8. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp9. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp10. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9, + CImgDisplay& disp10) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = disp10._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed || !disp10._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event && !disp10._is_event) + wait_all(); + } + +#if cimg_display==0 + + //! Wait for any window event occurring in any opened CImgDisplay. + static void wait_all() { + return _no_display_exception(); + } + + //! Render image into internal display buffer. + /** + \param img Input image data to render. + \note + - Convert image data representation into the internal display buffer (architecture-dependent structure). + - The content of the associated window is not modified, until paint() is called. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + template + CImgDisplay& render(const CImg& img) { + return assign(img); + } + + //! Paint internal display buffer on associated window. + /** + \note + - Update the content of the associated window with the internal display buffer, e.g. after a render() call. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + CImgDisplay& paint() { + return assign(); + } + + + //! Take a snapshot of the current screen content. + /** + \param x0 X-coordinate of the upper left corner. + \param y0 Y-coordinate of the upper left corner. + \param x1 X-coordinate of the lower right corner. + \param y1 Y-coordinate of the lower right corner. + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + cimg::unused(x0,y0,x1,y1,&img); + _no_display_exception(); + } + + //! Take a snapshot of the associated window content. + /** + \param[out] img Output snapshot. Can be empty on input. + **/ + template + const CImgDisplay& snapshot(CImg& img) const { + cimg::unused(img); + _no_display_exception(); + return *this; + } +#endif + + // X11-based implementation + //-------------------------- +#if cimg_display==1 + + Atom _wm_window_atom, _wm_protocol_atom; + Window _window, _background_window; + Colormap _colormap; + XImage *_image; + void *_data; + +#ifdef cimg_use_xshm + XShmSegmentInfo *_shminfo; +#endif + + static int screen_width() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_width(): Failed to open X11 display."); + res = DisplayWidth(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width; + else res = DisplayWidth(dpy,DefaultScreen(dpy)); +#else + res = DisplayWidth(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static int screen_height() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_height(): Failed to open X11 display."); + res = DisplayHeight(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height; + else res = DisplayHeight(dpy,DefaultScreen(dpy)); +#else + res = DisplayHeight(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static void wait_all() { + if (!cimg::X11_attr().display) return; + pthread_mutex_lock(&cimg::X11_attr().wait_event_mutex); + pthread_cond_wait(&cimg::X11_attr().wait_event,&cimg::X11_attr().wait_event_mutex); + pthread_mutex_unlock(&cimg::X11_attr().wait_event_mutex); + } + + void _handle_events(const XEvent *const pevent) { + Display *const dpy = cimg::X11_attr().display; + XEvent event = *pevent; + switch (event.type) { + case ClientMessage : { + if ((int)event.xclient.message_type==(int)_wm_protocol_atom && + (int)event.xclient.data.l[0]==(int)_wm_window_atom) { + XUnmapWindow(cimg::X11_attr().display,_window); + _is_closed = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case ConfigureNotify : { + while (XCheckWindowEvent(dpy,_window,StructureNotifyMask,&event)) {} + const unsigned int nw = event.xconfigure.width, nh = event.xconfigure.height; + const int nx = event.xconfigure.x, ny = event.xconfigure.y; + if (nw && nh && (nw!=_window_width || nh!=_window_height)) { + _window_width = nw; _window_height = nh; _mouse_x = _mouse_y = -1; + XResizeWindow(dpy,_window,_window_width,_window_height); + _is_resized = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + if (nx!=_window_x || ny!=_window_y) { + _window_x = nx; + _window_y = ny; + _is_moved = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case Expose : { + while (XCheckWindowEvent(dpy,_window,ExposureMask,&event)) {} + _paint(false); + if (_is_fullscreen) { + XWindowAttributes attr; + do { + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + XSetInputFocus(dpy,_window,RevertToParent,CurrentTime); + } + } break; + case ButtonPress : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1); break; + case 3 : set_button(2); break; + case 2 : set_button(3); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonPressMask,&event)); + } break; + case ButtonRelease : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1,false); break; + case 3 : set_button(2,false); break; + case 2 : set_button(3,false); break; + case 4 : set_wheel(1); break; + case 5 : set_wheel(-1); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonReleaseMask,&event)); + } break; + case KeyPress : { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,true); + } break; + case KeyRelease : { + char keys_return[32]; // Check that the key has been physically unpressed + XQueryKeymap(dpy,keys_return); + const unsigned int kc = event.xkey.keycode, kc1 = kc/8, kc2 = kc%8; + const bool is_key_pressed = kc1>=32?false:(keys_return[kc1]>>kc2)&1; + if (!is_key_pressed) { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,false); + } + } break; + case EnterNotify: { + while (XCheckWindowEvent(dpy,_window,EnterWindowMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + } break; + case LeaveNotify : { + while (XCheckWindowEvent(dpy,_window,LeaveWindowMask,&event)) {} + _mouse_x = _mouse_y = -1; _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + case MotionNotify : { + while (XCheckWindowEvent(dpy,_window,PointerMotionMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + } + } + + static void* _events_thread(void *arg) { // Thread to manage events for all opened display windows + Display *const dpy = cimg::X11_attr().display; + XEvent event; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); + if (!arg) for ( ; ; ) { + cimg_lock_display(); + bool event_flag = XCheckTypedEvent(dpy,ClientMessage,&event); + if (!event_flag) event_flag = XCheckMaskEvent(dpy, + ExposureMask | StructureNotifyMask | ButtonPressMask | + KeyPressMask | PointerMotionMask | EnterWindowMask | + LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask,&event); + if (event_flag) + for (unsigned int i = 0; i_is_closed && event.xany.window==cimg::X11_attr().wins[i]->_window) + cimg::X11_attr().wins[i]->_handle_events(&event); + cimg_unlock_display(); + pthread_testcancel(); + cimg::sleep(8); + } + return 0; + } + + void _set_colormap(Colormap& cmap, const unsigned int dim) { + XColor *const colormap = new XColor[256]; + switch (dim) { + case 1 : { // colormap for greyscale images + for (unsigned int index = 0; index<256; ++index) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].green = colormap[index].blue = (unsigned short)(index<<8); + colormap[index].flags = DoRed | DoGreen | DoBlue; + } + } break; + case 2 : { // colormap for RG images + for (unsigned int index = 0, r = 8; r<256; r+=16) + for (unsigned int g = 8; g<256; g+=16) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].blue = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } break; + default : { // colormap for RGB images + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap[index].pixel = index; + colormap[index].red = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index].blue = (unsigned short)(b<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } + } + XStoreColors(cimg::X11_attr().display,cmap,colormap,256); + delete[] colormap; + } + + void _map_window() { + Display *const dpy = cimg::X11_attr().display; + bool is_exposed = false, is_mapped = false; + XWindowAttributes attr; + XEvent event; + XMapRaised(dpy,_window); + do { // Wait for the window to be mapped + XWindowEvent(dpy,_window,StructureNotifyMask | ExposureMask,&event); + switch (event.type) { + case MapNotify : is_mapped = true; break; + case Expose : is_exposed = true; break; + } + } while (!is_exposed || !is_mapped); + do { // Wait for the window to be visible + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + _window_x = attr.x; + _window_y = attr.y; + } + + void _paint(const bool wait_expose=true) { + if (_is_closed || !_image) return; + Display *const dpy = cimg::X11_attr().display; + if (wait_expose) { // Send an expose event sticked to display window to force repaint + XEvent event; + event.xexpose.type = Expose; + event.xexpose.serial = 0; + event.xexpose.send_event = 1; + event.xexpose.display = dpy; + event.xexpose.window = _window; + event.xexpose.x = 0; + event.xexpose.y = 0; + event.xexpose.width = width(); + event.xexpose.height = height(); + event.xexpose.count = 0; + XSendEvent(dpy,_window,0,0,&event); + } else { // Repaint directly (may be called from the expose event) + GC gc = DefaultGC(dpy,DefaultScreen(dpy)); + +#ifdef cimg_use_xshm + if (_shminfo) XShmPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height,1); + else XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#else + XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#endif + } + } + + template + void _resize(T pixel_type, const unsigned int ndimx, const unsigned int ndimy, const bool force_redraw) { + Display *const dpy = cimg::X11_attr().display; + cimg::unused(pixel_type); + +#ifdef cimg_use_xshm + if (_shminfo) { + XShmSegmentInfo *const nshminfo = new XShmSegmentInfo; + XImage *const nimage = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy); + if (!nimage) { delete nshminfo; return; } + else { + nshminfo->shmid = shmget(IPC_PRIVATE,ndimx*ndimy*sizeof(T),IPC_CREAT | 0777); + if (nshminfo->shmid==-1) { XDestroyImage(nimage); delete nshminfo; return; } + else { + nshminfo->shmaddr = nimage->data = (char*)shmat(nshminfo->shmid,0,0); + if (nshminfo->shmaddr==(char*)-1) { + shmctl(nshminfo->shmid,IPC_RMID,0); XDestroyImage(nimage); delete nshminfo; return; + } else { + nshminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,nshminfo); + XFlush(dpy); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(nshminfo->shmaddr); + shmctl(nshminfo->shmid,IPC_RMID,0); + XDestroyImage(nimage); + delete nshminfo; + return; + } else { + T *const ndata = (T*)nimage->data; + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + XShmDetach(dpy,_shminfo); + XDestroyImage(_image); + shmdt(_shminfo->shmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = nshminfo; + _image = nimage; + _data = (void*)ndata; + } + } + } + } + } else +#endif + { + T *ndata = (T*)std::malloc(ndimx*ndimy*sizeof(T)); + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + _data = (void*)ndata; + XDestroyImage(_image); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,(char*)_data,ndimx,ndimy,8,0); + } + } + + void _init_fullscreen() { + if (!_is_fullscreen || _is_closed) return; + Display *const dpy = cimg::X11_attr().display; + _background_window = 0; + +#ifdef cimg_use_xrandr + int foo; + if (XRRQueryExtension(dpy,&foo,&foo)) { + XRRRotations(dpy,DefaultScreen(dpy),&cimg::X11_attr().curr_rotation); + if (!cimg::X11_attr().resolutions) { + cimg::X11_attr().resolutions = XRRSizes(dpy,DefaultScreen(dpy),&foo); + cimg::X11_attr().nb_resolutions = (unsigned int)foo; + } + if (cimg::X11_attr().resolutions) { + cimg::X11_attr().curr_resolution = 0; + for (unsigned int i = 0; i=_width && nh>=_height && + nw<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width) && + nh<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height)) + cimg::X11_attr().curr_resolution = i; + } + if (cimg::X11_attr().curr_resolution>0) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy), + cimg::X11_attr().curr_resolution,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + } + } + } + if (!cimg::X11_attr().resolutions) + cimg::warn(_cimgdisplay_instance + "init_fullscreen(): Xrandr extension not supported by the X server.", + cimgdisplay_instance); +#endif + + const unsigned int sx = screen_width(), sy = screen_height(); + if (sx==_width && sy==_height) return; + XSetWindowAttributes attr_set; + + attr_set.background_pixel = XBlackPixel(dpy,XDefaultScreen(dpy)); + attr_set.override_redirect = 1; + _background_window = XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,sx,sy,0,0, + InputOutput,CopyFromParent,CWBackPixel | CWOverrideRedirect,&attr_set); + XEvent event; + XSelectInput(dpy,_background_window,StructureNotifyMask); + XMapRaised(dpy,_background_window); + do XWindowEvent(dpy,_background_window,StructureNotifyMask,&event); + while (event.type!=MapNotify); + + XWindowAttributes attr; + do { + XGetWindowAttributes(dpy,_background_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + Display *const dpy = cimg::X11_attr().display; + XUngrabKeyboard(dpy,CurrentTime); + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy),0,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + cimg::X11_attr().curr_resolution = 0; + } +#endif + if (_background_window) XDestroyWindow(dpy,_background_window); + _background_window = 0; + _is_fullscreen = false; + } + + static int _assign_xshm(Display *dpy, XErrorEvent *error) { + cimg::unused(dpy,error); + cimg::X11_attr().is_shm_enabled = false; + return 0; + } + + void _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + cimg::mutex(14); + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous display window if existing + if (!is_empty()) assign(); + + // Open X11 display and retrieve graphical properties. + Display* &dpy = cimg::X11_attr().display; + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Failed to open X11 display.", + cimgdisplay_instance); + + cimg::X11_attr().nb_bits = DefaultDepth(dpy,DefaultScreen(dpy)); + if (cimg::X11_attr().nb_bits!=8 && cimg::X11_attr().nb_bits!=16 && + cimg::X11_attr().nb_bits!=24 && cimg::X11_attr().nb_bits!=32) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Invalid %u bits screen mode detected " + "(only 8, 16, 24 and 32 bits modes are managed).", + cimgdisplay_instance, + cimg::X11_attr().nb_bits); + XVisualInfo vtemplate; + vtemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy,DefaultScreen(dpy))); + int nb_visuals; + XVisualInfo *vinfo = XGetVisualInfo(dpy,VisualIDMask,&vtemplate,&nb_visuals); + if (vinfo && vinfo->red_maskblue_mask) cimg::X11_attr().is_blue_first = true; + cimg::X11_attr().byte_order = ImageByteOrder(dpy); + XFree(vinfo); + + cimg_lock_display(); + cimg::X11_attr().events_thread = new pthread_t; + pthread_create(cimg::X11_attr().events_thread,0,_events_thread,0); + } else cimg_lock_display(); + + // Set display variables. + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = cimg::type::min(); + _is_closed = closed_flag; + _title = tmp_title; + flush(); + + // Create X11 window (and LUT, if 8bits display) + if (_is_fullscreen) { + if (!_is_closed) _init_fullscreen(); + const unsigned int sx = screen_width(), sy = screen_height(); + XSetWindowAttributes attr_set; + attr_set.override_redirect = 1; + _window = XCreateWindow(dpy,DefaultRootWindow(dpy),(sx - _width)/2,(sy - _height)/2,_width,_height,0,0, + InputOutput,CopyFromParent,CWOverrideRedirect,&attr_set); + } else + _window = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,_width,_height,0,0L,0L); + + XSelectInput(dpy,_window, + ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask | + EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask); + + XStoreName(dpy,_window,_title?_title:" "); + if (cimg::X11_attr().nb_bits==8) { + _colormap = XCreateColormap(dpy,_window,DefaultVisual(dpy,DefaultScreen(dpy)),AllocAll); + _set_colormap(_colormap,3); + XSetWindowColormap(dpy,_window,_colormap); + } + + static const char *const _window_class = cimg_appname; + XClassHint *const window_class = XAllocClassHint(); + window_class->res_name = (char*)_window_class; + window_class->res_class = (char*)_window_class; + XSetClassHint(dpy,_window,window_class); + XFree(window_class); + + _window_width = _width; + _window_height = _height; + + // Create XImage +#ifdef cimg_use_xshm + _shminfo = 0; + if (XShmQueryExtension(dpy)) { + _shminfo = new XShmSegmentInfo; + _image = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,_shminfo,_width,_height); + if (!_image) { delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmid = shmget(IPC_PRIVATE,_image->bytes_per_line*_image->height,IPC_CREAT|0777); + if (_shminfo->shmid==-1) { XDestroyImage(_image); delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmaddr = _image->data = (char*)(_data = shmat(_shminfo->shmid,0,0)); + if (_shminfo->shmaddr==(char*)-1) { + shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); delete _shminfo; _shminfo = 0; + } else { + _shminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,_shminfo); + XSync(dpy,0); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(_shminfo->shmaddr); shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); + delete _shminfo; _shminfo = 0; + } + } + } + } + } + if (!_shminfo) +#endif + { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*(cimg::X11_attr().nb_bits==8?1: + (cimg::X11_attr().nb_bits==16?2:4)); + _data = std::malloc(buf_size); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,(char*)_data,_width,_height,8,0); + } + + _wm_window_atom = XInternAtom(dpy,"WM_DELETE_WINDOW",0); + _wm_protocol_atom = XInternAtom(dpy,"WM_PROTOCOLS",0); + XSetWMProtocols(dpy,_window,&_wm_window_atom,1); + + if (_is_fullscreen) XGrabKeyboard(dpy,_window,1,GrabModeAsync,GrabModeAsync,CurrentTime); + cimg::X11_attr().wins[cimg::X11_attr().nb_wins++]=this; + if (!_is_closed) _map_window(); else _window_x = _window_y = cimg::type::min(); + cimg_unlock_display(); + cimg::mutex(14,0); + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + + // Remove display window from event thread list. + unsigned int i; + for (i = 0; ishmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = 0; + } +#endif + + XDestroyImage(_image); + if (cimg::X11_attr().nb_bits==8) XFreeColormap(dpy,_colormap); + XDestroyWindow(dpy,_window); + XSync(dpy,0); + _window = 0; _colormap = 0; _data = 0; _image = 0; + + // Reset display variables. + delete[] _title; + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = cimg::type::min(); + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + + cimg_unlock_display(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + (cimg::X11_attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))* + (size_t)_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + cimg::X11_attr().nb_bits==16?sizeof(unsigned short): + sizeof(unsigned int))*(size_t)_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign(nwidth,nheight); + Display *const dpy = cimg::X11_attr().display; + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*width()/100), + tmpdimy = (nheight>0)?nheight:(-nheight*height()/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + show(); + cimg_lock_display(); + if (_window_width!=dimx || _window_height!=dimy) { + XWindowAttributes attr; + for (unsigned int i = 0; i<10; ++i) { + XResizeWindow(dpy,_window,dimx,dimy); + XGetWindowAttributes(dpy,_window,&attr); + if (attr.width==(int)dimx && attr.height==(int)dimy) break; + cimg::wait(5,&_timer); + } + } + if (_width!=dimx || _height!=dimy) switch (cimg::X11_attr().nb_bits) { + case 8 : { unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + case 16 : { unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + default : { unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } + } + _window_width = _width = dimx; _window_height = _height = dimy; + cimg_unlock_display(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - _width)/2,(screen_height() - _height)/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height* + (cimg::X11_attr().nb_bits==8?1:(cimg::X11_attr().nb_bits==16?2:4)); + void *image_data = std::malloc(buf_size); + std::memcpy(image_data,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,image_data,buf_size); + std::free(image_data); + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + cimg_lock_display(); + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + _map_window(); + cimg_unlock_display(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (_is_fullscreen) _desinit_fullscreen(); + XUnmapWindow(dpy,_window); + _window_x = _window_y = cimg::type::min(); + _is_closed = true; + cimg_unlock_display(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + show(); + if (_window_x!=posx || _window_y!=posy) { + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XMoveWindow(dpy,_window,posx,posy); + _window_x = posx; + _window_y = posy; + cimg_unlock_display(); + } + _is_moved = false; + return paint(); + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XUndefineCursor(dpy,_window); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + static const char pix_data[8] = { 0 }; + XColor col; + col.red = col.green = col.blue = 0; + Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8); + Cursor cur = XCreatePixmapCursor(dpy,pix,pix,&col,&col,0,0); + XFreePixmap(dpy,pix); + XDefineCursor(dpy,_window,cur); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XWarpPointer(dpy,0L,_window,0,0,0,0,posx,posy); + _mouse_x = posx; _mouse_y = posy; + _is_moved = false; + XSync(dpy,0); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XStoreName(dpy,_window,tmp); + cimg_unlock_display(); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(false); + } + + CImgDisplay& paint(const bool wait_expose=true) { + if (is_empty()) return *this; + cimg_lock_display(); + _paint(wait_expose); + cimg_unlock_display(); + return *this; + } + + template + CImgDisplay& render(const CImg& img, const bool flag8=false) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + if (cimg::X11_attr().nb_bits==8 && (img._width!=_width || img._height!=_height)) + return render(img.get_resize(_width,_height,1,-100,1)); + if (cimg::X11_attr().nb_bits==8 && !flag8 && img._spectrum==3) { + static const CImg::ucharT> default_colormap = CImg::ucharT>::default_LUT256(); + return render(img.get_index(default_colormap,1,false)); + } + + const T + *data1 = img._data, + *data2 = (img._spectrum>1)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>2)?img.data(0,0,0,2):data1; + + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + cimg_lock_display(); + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, no normalization + _set_colormap(_colormap,img._spectrum); + unsigned char + *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height], + *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + (*ptrd++) = (unsigned char)*(data1++); + break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, no normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (G>>1); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (G<<5) | (G>>1); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, no normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | + (unsigned char)*(data3++); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data3++)<<24) | ((unsigned char)*(data2++)<<16) | + ((unsigned char)*(data1++)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = 0; + ptrd[3] = 0; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = 0; + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = (unsigned char)*(data2++); + ptrd[3] = (unsigned char)*(data3++); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)*(data3++); + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { _min = (float)cimg::type::min(); _max = (float)cimg::type::max(); } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.f); + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, with normalization + _set_colormap(_colormap,img._spectrum); + unsigned char *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char R = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = R; + } break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, with normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (val>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (G<<5) | (val>>3); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, with normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<24) | (val<<16) | (val<<8); + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8) | + (unsigned char)((*(data3++) - _min)*mm); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data3++) - _min)*mm)<<24) | + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = 0; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = val; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = val; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[3] = (unsigned char)((*(data3++) - _min)*mm); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)((*(data3++) - _min)*mm); + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } + cimg_unlock_display(); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + img.assign(); + Display *dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException("CImgDisplay::screenshot(): Failed to open X11 display."); + } + Window root = DefaultRootWindow(dpy); + XWindowAttributes gwa; + XGetWindowAttributes(dpy,root,&gwa); + const int width = gwa.width, height = gwa.height; + int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1; + if (_x0>_x1) cimg::swap(_x0,_x1); + if (_y0>_y1) cimg::swap(_y0,_y1); + + XImage *image = 0; + if (_x1>=0 && _x0=0 && _y0red_mask, + green_mask = image->green_mask, + blue_mask = image->blue_mask; + img.assign(image->width,image->height,1,3); + T *pR = img.data(0,0,0,0), *pG = img.data(0,0,0,1), *pB = img.data(0,0,0,2); + cimg_forXY(img,x,y) { + const unsigned long pixel = XGetPixel(image,x,y); + *(pR++) = (T)((pixel & red_mask)>>16); + *(pG++) = (T)((pixel & green_mask)>>8); + *(pB++) = (T)(pixel & blue_mask); + } + XDestroyImage(image); + } + } + if (!cimg::X11_attr().display) XCloseDisplay(dpy); + cimg_unlock_display(); + if (img.is_empty()) + throw CImgDisplayException("CImgDisplay::screenshot(): Failed to take screenshot " + "with coordinates (%d,%d)-(%d,%d).", + x0,y0,x1,y1); + } + + template + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned char *ptrs = (unsigned char*)_data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + switch (cimg::X11_attr().nb_bits) { + case 8 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = *(ptrs++); + *(data1++) = (T)(val&0xe0); + *(data2++) = (T)((val&0x1c)<<3); + *(data3++) = (T)(val<<6); + } + } break; + case 16 : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val0&0xf8); + *(data2++) = (T)((val0<<5) | ((val1&0xe0)>>5)); + *(data3++) = (T)(val1<<3); + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned short + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val1&0xf8); + *(data2++) = (T)((val1<<5) | ((val0&0xe0)>>5)); + *(data3++) = (T)(val0<<3); + } + } break; + default : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ++ptrs; + *(data1++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data3++) = (T)ptrs[2]; + ptrs+=3; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + *(data3++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data1++) = (T)ptrs[2]; + ptrs+=3; + ++ptrs; + } + } + } + return *this; + } + + // Windows-based implementation. + //------------------------------- +#elif cimg_display==2 + + bool _is_mouse_tracked, _is_cursor_visible; + HANDLE _thread, _is_created, _mutex; + HWND _window, _background_window; + CLIENTCREATESTRUCT _ccs; + unsigned int *_data; + DEVMODE _curr_mode; + BITMAPINFO _bmi; + HDC _hdc; + + static int screen_width() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsWidth; + } + + static int screen_height() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsHeight; + } + + static void wait_all() { + WaitForSingleObject(cimg::Win32_attr().wait_event,INFINITE); + } + + static LRESULT APIENTRY _handle_events(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { +#ifdef _WIN64 + CImgDisplay *const disp = (CImgDisplay*)GetWindowLongPtr(window,GWLP_USERDATA); +#else + CImgDisplay *const disp = (CImgDisplay*)GetWindowLong(window,GWL_USERDATA); +#endif + MSG st_msg; + switch (msg) { + case WM_CLOSE : + disp->_mouse_x = disp->_mouse_y = -1; + disp->_window_x = disp->_window_y = cimg::type::min(); + disp->set_button().set_key(0).set_key(0,false)._is_closed = true; + ReleaseMutex(disp->_mutex); + ShowWindow(disp->_window,SW_HIDE); + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + return 0; + case WM_SIZE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam); + if (nw && nh && (nw!=disp->_width || nh!=disp->_height)) { + disp->_window_width = nw; + disp->_window_height = nh; + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_resized = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_MOVE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const int nx = (int)(short)(LOWORD(lParam)), ny = (int)(short)(HIWORD(lParam)); + if (nx!=disp->_window_x || ny!=disp->_window_y) { + disp->_window_x = nx; + disp->_window_y = ny; + disp->_is_moved = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_PAINT : + disp->paint(); + cimg_lock_display(); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE_WIN)>=0); + cimg_unlock_display(); + break; + case WM_ERASEBKGND : + // return 0; + break; + case WM_KEYDOWN : + disp->set_key((unsigned int)wParam); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_KEYUP : + disp->set_key((unsigned int)wParam,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MOUSEMOVE : { + while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE)) {} + disp->_mouse_x = LOWORD(lParam); + disp->_mouse_y = HIWORD(lParam); +#if (_WIN32_WINNT>=0x0400) && !defined(NOTRACKMOUSEEVENT) + if (!disp->_is_mouse_tracked) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = disp->_window; + if (TrackMouseEvent(&tme)) disp->_is_mouse_tracked = true; + } +#endif + if (disp->_mouse_x<0 || disp->_mouse_y<0 || disp->_mouse_x>=disp->width() || disp->_mouse_y>=disp->height()) + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + cimg_lock_display(); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE_WIN)>=0); + cimg_unlock_display(); + } break; + case WM_MOUSELEAVE : { + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_mouse_tracked = false; + cimg_lock_display(); + while (ShowCursor(TRUE)<0) {} + cimg_unlock_display(); + } break; + case WM_LBUTTONDOWN : + disp->set_button(1); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONDOWN : + disp->set_button(2); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONDOWN : + disp->set_button(3); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_LBUTTONUP : + disp->set_button(1,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONUP : + disp->set_button(2,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONUP : + disp->set_button(3,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case 0x020A : // WM_MOUSEWHEEL: + disp->set_wheel((int)((short)HIWORD(wParam))/120); + SetEvent(cimg::Win32_attr().wait_event); + } + return DefWindowProc(window,msg,wParam,lParam); + } + + static DWORD WINAPI _events_thread(void* arg) { + CImgDisplay *const disp = (CImgDisplay*)(((void**)arg)[0]); + const char *const title = (const char*)(((void**)arg)[1]); + MSG msg; + delete[] (void**)arg; + disp->_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + disp->_bmi.bmiHeader.biWidth = disp->width(); + disp->_bmi.bmiHeader.biHeight = -disp->height(); + disp->_bmi.bmiHeader.biPlanes = 1; + disp->_bmi.bmiHeader.biBitCount = 32; + disp->_bmi.bmiHeader.biCompression = BI_RGB; + disp->_bmi.bmiHeader.biSizeImage = 0; + disp->_bmi.bmiHeader.biXPelsPerMeter = 1; + disp->_bmi.bmiHeader.biYPelsPerMeter = 1; + disp->_bmi.bmiHeader.biClrUsed = 0; + disp->_bmi.bmiHeader.biClrImportant = 0; + disp->_data = new unsigned int[(size_t)disp->_width*disp->_height]; + if (!disp->_is_fullscreen) { // Normal window + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)disp->_width - 1; rect.bottom = (LONG)disp->_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int + border1 = (int)((rect.right - rect.left + 1 - disp->_width)/2), + border2 = (int)(rect.bottom - rect.top + 1 - disp->_height - border1), + ww = disp->width() + 2*border1, + wh = disp->height() + border1 + border2, + sw = CImgDisplay::screen_width(), + sh = CImgDisplay::screen_height(); + int + wx = (int)cimg::round(cimg::rand(0,sw - ww -1)), + wy = (int)cimg::round(cimg::rand(64,sh - wh - 65)); + if (wx + ww>=sw) wx = sw - ww; + if (wy + wh>=sh) wy = sh - wh; + if (wx<0) wx = 0; + if (wy<0) wy = 0; + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + (DWORD)(WS_OVERLAPPEDWINDOW | (disp->_is_closed?0:WS_VISIBLE)), + wx,wy,ww,wh,0,0,0,&(disp->_ccs)); + if (!disp->_is_closed) { + GetWindowRect(disp->_window,&rect); + disp->_window_x = rect.left; + disp->_window_y = rect.top; + } else disp->_window_x = disp->_window_y = cimg::type::min(); + } else { // Fullscreen window + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + (DWORD)(WS_POPUP | (disp->_is_closed?0:WS_VISIBLE)), + (int)(sx - disp->_width)/2, + (int)(sy - disp->_height)/2, + disp->width(),disp->height(),0,0,0,&(disp->_ccs)); + disp->_window_x = disp->_window_y = 0; + } + SetForegroundWindow(disp->_window); + disp->_hdc = GetDC(disp->_window); + disp->_window_width = disp->_width; + disp->_window_height = disp->_height; + disp->flush(); +#ifdef _WIN64 + SetWindowLongPtr(disp->_window,GWLP_USERDATA,(LONG_PTR)disp); + SetWindowLongPtr(disp->_window,GWLP_WNDPROC,(LONG_PTR)_handle_events); +#else + SetWindowLong(disp->_window,GWL_USERDATA,(LONG)disp); + SetWindowLong(disp->_window,GWL_WNDPROC,(LONG)_handle_events); +#endif + SetEvent(disp->_is_created); + while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg); + return 0; + } + + CImgDisplay& _update_window_pos() { + if (_is_closed) _window_x = _window_y = cimg::type::min(); + else { + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)_width - 1; rect.bottom = (LONG)_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + GetWindowRect(_window,&rect); + _window_x = rect.left; + _window_y = rect.top; + } + return *this; + } + + void _init_fullscreen() { + _background_window = 0; + if (!_is_fullscreen || _is_closed) _curr_mode.dmSize = 0; + else { + DEVMODE mode; + unsigned int imode = 0, ibest = 0, bestbpp = 0, bw = ~0U, bh = ~0U; + for (mode.dmSize = sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(0,imode,&mode); ++imode) { + const unsigned int nw = mode.dmPelsWidth, nh = mode.dmPelsHeight; + if (nw>=_width && nh>=_height && mode.dmBitsPerPel>=bestbpp && nw<=bw && nh<=bh) { + bestbpp = mode.dmBitsPerPel; + ibest = imode; + bw = nw; bh = nh; + } + } + if (bestbpp) { + _curr_mode.dmSize = sizeof(DEVMODE); _curr_mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&_curr_mode); + EnumDisplaySettings(0,ibest,&mode); + ChangeDisplaySettings(&mode,0); + } else _curr_mode.dmSize = 0; + + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + if (sx!=_width || sy!=_height) { + CLIENTCREATESTRUCT background_ccs = { 0,0 }; + _background_window = CreateWindowA("MDICLIENT","",WS_POPUP | WS_VISIBLE, + 0,0,(int)sx,(int)sy,0,0,0,&background_ccs); + SetForegroundWindow(_background_window); + } + } + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + if (_background_window) DestroyWindow(_background_window); + _background_window = 0; + if (_curr_mode.dmSize) ChangeDisplaySettings(&_curr_mode,0); + _is_fullscreen = false; + } + + CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous window if existing + if (!is_empty()) assign(); + + // Set display variables + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = cimg::type::min(); + _is_closed = closed_flag; + _is_cursor_visible = true; + _is_mouse_tracked = false; + _title = tmp_title; + flush(); + if (_is_fullscreen) _init_fullscreen(); + + // Create event thread + void *const arg = (void*)(new void*[2]); + ((void**)arg)[0] = (void*)this; + ((void**)arg)[1] = (void*)_title; + _mutex = CreateMutex(0,FALSE_WIN,0); + _is_created = CreateEvent(0,FALSE_WIN,FALSE_WIN,0); + _thread = CreateThread(0,0,_events_thread,arg,0,0); + WaitForSingleObject(_is_created,INFINITE); + return *this; + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + DestroyWindow(_window); + TerminateThread(_thread,0); + delete[] _data; + delete[] _title; + _data = 0; + _title = 0; + if (_is_fullscreen) _desinit_fullscreen(); + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = cimg::type::min(); + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,sizeof(unsigned int)*_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,sizeof(unsigned int)*_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign((unsigned int)nwidth,(unsigned int)nheight); + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*_width/100), + tmpdimy = (nheight>0)?nheight:(-nheight*_height/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + if (_window_width!=dimx || _window_height!=dimy) { + RECT rect; rect.left = rect.top = 0; rect.right = (LONG)dimx - 1; rect.bottom = (LONG)dimy - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1; + SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS); + } + if (_width!=dimx || _height!=dimy) { + unsigned int *const ndata = new unsigned int[dimx*dimy]; + if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy); + else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy); + delete[] _data; + _data = ndata; + _bmi.bmiHeader.biWidth = (LONG)dimx; + _bmi.bmiHeader.biHeight = -(int)dimy; + _width = dimx; + _height = dimy; + } + _window_width = dimx; _window_height = dimy; + show(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - width())/2,(screen_height() - height())/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*4; + void *odata = std::malloc(buf_size); + if (odata) { + std::memcpy(odata,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,odata,buf_size); + std::free(odata); + } + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + ShowWindow(_window,SW_SHOW); + _update_window_pos(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + _is_closed = true; + if (_is_fullscreen) _desinit_fullscreen(); + ShowWindow(_window,SW_HIDE); + _window_x = _window_y = cimg::type::min(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + if (_window_x!=posx || _window_y!=posy) { + SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER); + _window_x = posx; + _window_y = posy; + } + show(); + _is_moved = false; + return *this; + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = true; + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = false; + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed || posx<0 || posy<0) return *this; + if (!_is_closed) { + _update_window_pos(); + const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy); + if (res) { _mouse_x = posx; _mouse_y = posy; } + } + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + SetWindowTextA(_window, tmp); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(); + } + + CImgDisplay& paint() { + if (_is_closed) return *this; + WaitForSingleObject(_mutex,INFINITE); + SetDIBitsToDevice(_hdc,0,0,_width,_height,0,0,0,_height,_data,&_bmi,DIB_RGB_COLORS); + ReleaseMutex(_mutex); + return *this; + } + + template + CImgDisplay& render(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + + const T + *data1 = img._data, + *data2 = (img._spectrum>=2)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>=3)?img.data(0,0,0,2):data1; + + WaitForSingleObject(_mutex,INFINITE); + unsigned int + *const ndata = (img._width==_width && img._height==_height)?_data: + new unsigned int[(size_t)img._width*img._height], + *ptrd = ndata; + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { + _min = (float)cimg::type::min(); + _max = (float)cimg::type::max(); + } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.f); + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } + if (ndata!=_data) { _render_resize(ndata,img._width,img._height,_data,_width,_height); delete[] ndata; } + ReleaseMutex(_mutex); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + img.assign(); + HDC hScreen = GetDC(GetDesktopWindow()); + if (hScreen) { + const int + width = GetDeviceCaps(hScreen,HORZRES), + height = GetDeviceCaps(hScreen,VERTRES); + int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1; + if (_x0>_x1) cimg::swap(_x0,_x1); + if (_y0>_y1) cimg::swap(_y0,_y1); + if (_x1>=0 && _x0=0 && _y0 + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned int *ptrs = _data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned int val = *(ptrs++); + *(data1++) = (T)(unsigned char)(val>>16); + *(data2++) = (T)(unsigned char)((val>>8)&0xFF); + *(data3++) = (T)(unsigned char)(val&0xFF); + } + return *this; + } +#endif + + //@} + }; // struct CImgDisplay { ... + + /* + #-------------------------------------- + # + # + # + # Definition of the CImg structure + # + # + # + #-------------------------------------- + */ + + //! Class representing an image (up to 4 dimensions wide), each pixel being of type \c T. + /** + This is the main class of the %CImg Library. It declares and constructs + an image, allows access to its pixel values, and is able to perform various image operations. + + \par Image representation + + A %CImg image is defined as an instance of the container \c CImg, which contains a regular grid of pixels, + each pixel value being of type \c T. The image grid can have up to 4 dimensions: width, height, depth + and number of channels. + Usually, the three first dimensions are used to describe spatial coordinates (x,y,z), + while the number of channels is rather used as a vector-valued dimension + (it may describe the R,G,B color channels for instance). + If you need a fifth dimension, you can use image lists \c CImgList rather than simple images \c CImg. + + Thus, the \c CImg class is able to represent volumetric images of vector-valued pixels, + as well as images with less dimensions (1D scalar signal, 2D color images, ...). + Most member functions of the class CImg<\c T> are designed to handle this maximum case of (3+1) dimensions. + + Concerning the pixel value type \c T: + fully supported template types are the basic C++ types: unsigned char, char, short, unsigned int, int, + unsigned long, long, float, double, ... . + Typically, fast image display can be done using CImg images, + while complex image processing algorithms may be rather coded using CImg or CImg + images that have floating-point pixel values. The default value for the template T is \c float. + Using your own template types may be possible. However, you will certainly have to define the complete set + of arithmetic and logical operators for your class. + + \par Image structure + + The \c CImg structure contains \e six fields: + - \c _width defines the number of \a columns of the image (size along the X-axis). + - \c _height defines the number of \a rows of the image (size along the Y-axis). + - \c _depth defines the number of \a slices of the image (size along the Z-axis). + - \c _spectrum defines the number of \a channels of the image (size along the C-axis). + - \c _data defines a \a pointer to the \a pixel \a data (of type \c T). + - \c _is_shared is a boolean that tells if the memory buffer \c data is shared with + another image. + + You can access these fields publicly although it is recommended to use the dedicated functions + width(), height(), depth(), spectrum() and ptr() to do so. + Image dimensions are not limited to a specific range (as long as you got enough available memory). + A value of \e 1 usually means that the corresponding dimension is \a flat. + If one of the dimensions is \e 0, or if the data pointer is null, the image is considered as \e empty. + Empty images should not contain any pixel data and thus, will not be processed by CImg member functions + (a CImgInstanceException will be thrown instead). + Pixel data are stored in memory, in a non interlaced mode (See \ref cimg_storage). + + \par Image declaration and construction + + Declaring an image can be done by using one of the several available constructors. + Here is a list of the most used: + + - Construct images from arbitrary dimensions: + - CImg img; declares an empty image. + - CImg img(128,128); declares a 128x128 greyscale image with + \c unsigned \c char pixel values. + - CImg img(3,3); declares a 3x3 matrix with \c double coefficients. + - CImg img(256,256,1,3); declares a 256x256x1x3 (color) image + (colors are stored as an image with three channels). + - CImg img(128,128,128); declares a 128x128x128 volumetric and greyscale image + (with \c double pixel values). + - CImg<> img(128,128,128,3); declares a 128x128x128 volumetric color image + (with \c float pixels, which is the default value of the template parameter \c T). + - \b Note: images pixels are not automatically initialized to 0. You may use the function \c fill() to + do it, or use the specific constructor taking 5 parameters like this: + CImg<> img(128,128,128,3,0); declares a 128x128x128 volumetric color image with all pixel values to 0. + + - Construct images from filenames: + - CImg img("image.jpg"); reads a JPEG color image from the file "image.jpg". + - CImg img("analyze.hdr"); reads a volumetric image (ANALYZE7.5 format) from the + file "analyze.hdr". + - \b Note: You need to install ImageMagick + to be able to read common compressed image formats (JPG,PNG, ...) (See \ref cimg_files_io). + + - Construct images from C-style arrays: + - CImg img(data_buffer,256,256); constructs a 256x256 greyscale image from a \c int* buffer + \c data_buffer (of size 256x256=65536). + - CImg img(data_buffer,256,256,1,3); constructs a 256x256 color image + from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others). + + The complete list of constructors can be found here. + + \par Most useful functions + + The \c CImg class contains a lot of functions that operates on images. + Some of the most useful are: + + - operator()(): Read or write pixel values. + - display(): displays the image in a new window. + **/ + template + struct CImg { + + unsigned int _width, _height, _depth, _spectrum; + bool _is_shared; + T *_data; + + //! Simple iterator type, to loop through each pixel value of an image instance. + /** + \note + - The \c CImg::iterator type is defined to be a T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + CImg img("reference.jpg"); // Load image from file + // Set all pixels to '0', with a CImg iterator. + for (CImg::iterator it = img.begin(), it::const_iterator type is defined to be a \c const \c T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + const CImg img("reference.jpg"); // Load image from file + float sum = 0; + // Compute sum of all pixel values, with a CImg iterator. + for (CImg::iterator it = img.begin(), it::value_type type of a \c CImg is defined to be a \c T. + - \c CImg::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + // Return 'dx*dy*dz*dc' as a 'size_t' and check no overflow occurs. + static size_t safe_size(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + if (!(dx && dy && dz && dc)) return 0; + size_t siz = (size_t)dx, osiz = siz; + if ((dy==1 || (siz*=dy)>osiz) && + ((osiz = siz), dz==1 || (siz*=dz)>osiz) && + ((osiz = siz), dc==1 || (siz*=dc)>osiz) && + ((osiz = siz), sizeof(T)==1 || (siz*sizeof(T))>osiz)) return siz; + throw CImgArgumentException("CImg<%s>::safe_size(): Specified size (%u,%u,%u,%u) overflows 'size_t'.", + pixel_type(),dx,dy,dz,dc); + } + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimg_plugin +#include cimg_plugin +#endif +#ifdef cimg_plugin1 +#include cimg_plugin1 +#endif +#ifdef cimg_plugin2 +#include cimg_plugin2 +#endif +#ifdef cimg_plugin3 +#include cimg_plugin3 +#endif +#ifdef cimg_plugin4 +#include cimg_plugin4 +#endif +#ifdef cimg_plugin5 +#include cimg_plugin5 +#endif +#ifdef cimg_plugin6 +#include cimg_plugin6 +#endif +#ifdef cimg_plugin7 +#include cimg_plugin7 +#endif +#ifdef cimg_plugin8 +#include cimg_plugin8 +#endif + + //@} + //--------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //--------------------------------------------------------- + + //! Destroy image. + /** + \note + - The pixel buffer data() is deallocated if necessary, e.g. for non-empty and non-shared image instances. + - Destroying an empty or shared image does nothing actually. + \warning + - When destroying a non-shared image, make sure that you will \e not operate on a remaining shared image + that shares its buffer with the destroyed instance, in order to avoid further invalid memory access + (to a deallocated buffer). + **/ + ~CImg() { + if (!_is_shared) delete[] _data; + } + + //! Construct empty image. + /** + \note + - An empty image has no pixel data and all of its dimensions width(), height(), depth(), spectrum() + are set to \c 0, as well as its pixel buffer pointer data(). + - An empty image may be re-assigned afterwards, e.g. with the family of + assign(unsigned int,unsigned int,unsigned int,unsigned int) methods, + or by operator=(const CImg&). In all cases, the type of pixels stays \c T. + - An empty image is never shared. + \par Example + \code + CImg img1, img2; // Construct two empty images + img1.assign(256,256,1,3); // Re-assign 'img1' to be a 256x256x1x3 (color) image + img2 = img1.get_rand(0,255); // Re-assign 'img2' to be a random-valued version of 'img1' + img2.assign(); // Re-assign 'img2' to be an empty image again + \endcode + **/ + CImg():_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {} + + //! Construct image with specified size. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \note + - It is able to create only \e non-shared images, and allocates thus a pixel buffer data() + for each constructed image instance. + - Setting one dimension \c size_x,\c size_y,\c size_z or \c size_c to \c 0 leads to the construction of + an \e empty image. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values during construction (e.g. with \c 0), use constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) instead. + \par Example + \code + CImg img1(256,256,1,3); // Construct a 256x256x1x3 (color) image, filled with garbage values + CImg img2(256,256,1,3,0); // Construct a 256x256x1x3 (color) image, filled with value '0' + \endcode + **/ + explicit CImg(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1): + _is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value Initialization value. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), + but it also fills the pixel buffer with the specified \c value. + \warning + - It cannot be used to construct a vector-valued image and initialize it with \e vector-valued pixels + (e.g. RGB vector, for color images). + For this task, you may use fillC() after construction. + **/ + CImg(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value): + _is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(value); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified sequence of integers \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be an \e integer). + \param value1 Second value of the initialization sequence (must be an \e integer). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \warning + - You must specify \e exactly \c size_x*\c size_y*\c size_z*\c size_c integers in the initialization sequence. + Otherwise, the constructor may crash or fill your image pixels with garbage. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image + 0,255,0,255, // Set the 4 values for the red component + 0,0,255,255, // Set the 4 values for the green component + 64,64,64,64); // Set the 4 values for the blue component + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _CImg_stdarg(img,a0,a1,N,t) { \ + size_t _siz = (size_t)N; \ + if (_siz--) { \ + va_list ap; \ + va_start(ap,a1); \ + T *ptrd = (img)._data; \ + *(ptrd++) = (T)a0; \ + if (_siz--) { \ + *(ptrd++) = (T)a1; \ + for ( ; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \ + } \ + va_end(ap); \ + } \ + } + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),int); + } + +#if cimg_use_cpp11==1 + //! Construct image with specified size and initialize pixel values from an initializer list of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... } + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param { value0, value1, ... } Initialization list + \param repeat_values Tells if the value filling process is repeated over the image. + + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image + { 0,255,0,255, // Set the 4 values for the red component + 0,0,255,255, // Set the 4 values for the green component + 64,64,64,64 }); // Set the 4 values for the blue component + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _cimg_constructor_cpp11(repeat_values) \ + auto it = values.begin(); \ + size_t siz = size(); \ + if (repeat_values) for (T *ptrd = _data; siz--; ) { \ + *(ptrd++) = (T)(*(it++)); if (it==values.end()) it = values.begin(); } \ + else { siz = std::min(siz,values.size()); for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); } + assign(size_x,size_y,size_z,size_c); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, + std::initializer_list values, + const bool repeat_values=true):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x); + _cimg_constructor_cpp11(repeat_values); + } + + //! Construct single channel 1D image with pixel values and width obtained from an initializer list of integers. + /** + Construct a new image instance of size \c width x \c 1 x \c 1 x \c 1, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... }. Image width is + given by the size of the initializer list. + \param { value0, value1, ... } Initialization list + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int) with height=1, depth=1, and spectrum=1, + but it also fills the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img = {10,20,30,20,10 }; // Construct a 5x1 image with one channel, and set its pixel values + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const std::initializer_list values): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(values.size(),1,1,1); + auto it = values.begin(); + unsigned int siz = _width; + for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); + } + + template + CImg& operator=(std::initializer_list values) { + _cimg_constructor_cpp11(siz>values.size()); + return *this; + } +#endif + + //! Construct image with specified size and initialize pixel values from a sequence of doubles. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initialize pixel values from the specified sequence of doubles \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be a \e double). + \param value1 Second value of the initialization sequence (must be a \e double). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...), but + takes a sequence of double values instead of integers. + \warning + - You must specify \e exactly \c dx*\c dy*\c dz*\c dc doubles in the initialization sequence. + Otherwise, the constructor may crash or fill your image with garbage. + For instance, the code below will probably crash on most platforms: + \code + const CImg img(2,2,1,1, 0.5,0.5,255,255); // FAIL: The two last arguments are 'int', not 'double'! + \endcode + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),double); + } + + //! Construct image with specified size and initialize pixel values from a value string. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified string \c values. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param values Value string describing the way pixel values are set. + \param repeat_values Tells if the value filling process is repeated over the image. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with values described in the value string \c values. + - Value string \c values may describe two different filling processes: + - Either \c values is a sequences of values assigned to the image pixels, as in "1,2,3,7,8,2". + In this case, set \c repeat_values to \c true to periodically fill the image with the value sequence. + - Either, \c values is a formula, as in "cos(x/10)*sin(y/20)". + In this case, parameter \c repeat_values is pointless. + - For both cases, specifying \c repeat_values is mandatory. + It disambiguates the possible overloading of constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) with \c T being a const char*. + - A \c CImgArgumentException is thrown when an invalid value string \c values is specified. + \par Example + \code + const CImg img1(129,129,1,3,"0,64,128,192,255",true), // Construct image from a value sequence + img2(129,129,1,3,"if(c==0,255*abs(cos(x/10)),1.8*y)",false); // Construct image from a formula + (img1,img2).display(); + \endcode + \image html ref_constructor2.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values):_is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(values,repeat_values); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified \c t* memory buffer. + \param values Pointer to the input memory buffer. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param is_shared Tells if input memory buffer must be shared by the current instance. + \note + - If \c is_shared is \c false, the image instance allocates its own pixel buffer, + and values from the specified input buffer are copied to the instance buffer. + If buffer types \c T and \c t are different, a regular static cast is performed during buffer copy. + - Otherwise, the image instance does \e not allocate a new buffer, and uses the input memory buffer as its + own pixel buffer. This case requires that types \c T and \c t are the same. Later, destroying such a shared + image will not deallocate the pixel buffer, this task being obviously charged to the initial buffer allocator. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - You must take care when operating on a shared image, since it may have an invalid pixel buffer pointer data() + (e.g. already deallocated). + \par Example + \code + unsigned char tab[256*256] = { 0 }; + CImg img1(tab,256,256,1,1,false), // Construct new non-shared image from buffer 'tab' + img2(tab,256,256,1,1,true); // Construct new shared-image from buffer 'tab' + tab[1024] = 255; // Here, 'img2' is indirectly modified, but not 'img1' + \endcode + **/ + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a (%u,%u,%u,%u) shared instance " + "from a (%s*) buffer (pixel types are different).", + cimg_instance, + size_x,size_y,size_z,size_c,CImg::pixel_type()); + } + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + + } + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = is_shared; + if (_is_shared) _data = const_cast(values); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy(_data,values,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from memory buffer with specified size and pixel ordering scheme. + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const axes_order):_data(0),_is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = c; } + } + if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { + const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + int s0 = 0, s1 = 0, s2 = 0, s3 = 0; + const char *inv_order = 0; + switch (code) { + case 0x0123 : inv_order = "xyzc"; s0 = size_x; s1 = size_y; s2 = size_z; s3 = size_c; break; // xyzc + case 0x0132 : inv_order = "xyzc"; s0 = size_x; s1 = size_y; s2 = size_c; s3 = size_z; break; // xycz + case 0x0213 : inv_order = "xzyc"; s0 = size_x; s1 = size_z; s2 = size_y; s3 = size_c; break; // xzyc + case 0x0231 : inv_order = "xcyz"; s0 = size_x; s1 = size_z; s2 = size_c; s3 = size_y; break; // xzcy + case 0x0312 : inv_order = "xzcy"; s0 = size_x; s1 = size_c; s2 = size_y; s3 = size_z; break; // xcyz + case 0x0321 : inv_order = "xczy"; s0 = size_x; s1 = size_c; s2 = size_z; s3 = size_y; break; // xczy + case 0x1023 : inv_order = "yxzc"; s0 = size_y; s1 = size_x; s2 = size_z; s3 = size_c; break; // yxzc + case 0x1032 : inv_order = "yxcz"; s0 = size_y; s1 = size_x; s2 = size_c; s3 = size_z; break; // yxcz + case 0x1203 : inv_order = "zxyc"; s0 = size_y; s1 = size_z; s2 = size_x; s3 = size_c; break; // yzxc + case 0x1230 : inv_order = "cxyz"; s0 = size_y; s1 = size_z; s2 = size_c; s3 = size_x; break; // yzcx + case 0x1302 : inv_order = "zxcy"; s0 = size_y; s1 = size_c; s2 = size_x; s3 = size_z; break; // ycxz + case 0x1320 : inv_order = "cxzy"; s0 = size_y; s1 = size_c; s2 = size_z; s3 = size_x; break; // yczx + case 0x2013 : inv_order = "yzxc"; s0 = size_z; s1 = size_x; s2 = size_y; s3 = size_c; break; // zxyc + case 0x2031 : inv_order = "ycxz"; s0 = size_z; s1 = size_x; s2 = size_c; s3 = size_y; break; // zxcy + case 0x2103 : inv_order = "zyxc"; s0 = size_z; s1 = size_y; s2 = size_x; s3 = size_c; break; // zyxc + case 0x2130 : inv_order = "cyxz"; s0 = size_z; s1 = size_y; s2 = size_c; s3 = size_x; break; // zycx + case 0x2301 : inv_order = "zcxy"; s0 = size_z; s1 = size_c; s2 = size_x; s3 = size_y; break; // zcxy + case 0x2310 : inv_order = "czxy"; s0 = size_z; s1 = size_c; s2 = size_y; s3 = size_x; break; // zcyx + case 0x3012 : inv_order = "yzcx"; s0 = size_c; s1 = size_x; s2 = size_y; s3 = size_z; break; // cxyz + case 0x3021 : inv_order = "yczx"; s0 = size_c; s1 = size_x; s2 = size_z; s3 = size_y; break; // cxzy + case 0x3102 : inv_order = "zycx"; s0 = size_c; s1 = size_y; s2 = size_x; s3 = size_z; break; // cyxz + case 0x3120 : inv_order = "cyzx"; s0 = size_c; s1 = size_y; s2 = size_z; s3 = size_x; break; // cyzx + case 0x3201 : inv_order = "zcyx"; s0 = size_c; s1 = size_z; s2 = size_x; s3 = size_y; break; // czxy + case 0x3210 : inv_order = "czyx"; s0 = size_c; s1 = size_z; s2 = size_y; s3 = size_x; break; // czyx + } + CImg(values,s0,s1,s2,s3,true).get_permute_axes(inv_order).move_to(*this); + } else { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from reading an image file. + /** + Construct a new image instance with pixels of type \c T, and initialize pixel values with the data read from + an image file. + \param filename Filename, as a C-string. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it reads the image + dimensions and pixel values from the specified image file. + - The recognition of the image file format by %CImg higlhy depends on the tools installed on your system + and on the external libraries you used to link your code against. + - Considered pixel type \c T should better fit the file format specification, or data loss may occur during + file load (e.g. constructing a \c CImg from a float-valued image file). + - A \c CImgIOException is thrown when the specified \c filename cannot be read, or if the file format is not + recognized. + \par Example + \code + const CImg img("reference.jpg"); + img.display(); + \endcode + \image html ref_image.jpg + **/ + explicit CImg(const char *const filename):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(filename); + } + + //! Construct image copy. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance. + \param img Input image to copy. + \note + - Constructed copy has the same size width() x height() x depth() x spectrum() and pixel values as the + input image \c img. + - If input image \c img is \e shared and if types \c T and \c t are the same, the constructed copy is also + \e shared, and shares its pixel buffer with \c img. + Modifying a pixel value in the constructed copy will thus also modifies it in the input image \c img. + This behavior is needful to allow functions to return shared images. + - Otherwise, the constructed copy allocates its own pixel buffer, and copies pixel values from the input + image \c img into its buffer. The copied pixel values may be eventually statically casted if types \c T and + \c t are different. + - Constructing a copy from an image \c img when types \c t and \c T are the same is significantly faster than + with different types. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. not enough available memory). + **/ + template + CImg(const CImg& img):_is_shared(false) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image copy \specialization. + CImg(const CImg& img) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = img._is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Advanced copy constructor. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance, + while forcing the shared state of the constructed copy. + \param img Input image to copy. + \param is_shared Tells about the shared state of the constructed copy. + \note + - Similar to CImg(const CImg&), except that it allows to decide the shared state of + the constructed image, which does not depend anymore on the shared state of the input image \c img: + - If \c is_shared is \c true, the constructed copy will share its pixel buffer with the input image \c img. + For that case, the pixel types \c T and \c t \e must be the same. + - If \c is_shared is \c false, the constructed copy will allocate its own pixel buffer, whether the input + image \c img is shared or not. + - A \c CImgArgumentException is thrown when a shared copy is requested with different pixel types \c T and \c t. + **/ + template + CImg(const CImg& img, const bool is_shared):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a shared instance from a " + "CImg<%s> image (%u,%u,%u,%u,%p) (pixel types are different).", + cimg_instance, + CImg::pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data); + } + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Advanced copy constructor \specialization. + CImg(const CImg& img, const bool is_shared) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image with dimensions borrowed from another image. + /** + Construct a new image instance with pixels of type \c T, and size get from some dimensions of an existing + \c CImg instance. + \param img Input image from which dimensions are borrowed. + \param dimensions C-string describing the image size along the X,Y,Z and C-dimensions. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it takes the image dimensions + (\e not its pixel values) from an existing \c CImg instance. + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values (e.g. with \c 0), use constructor CImg(const CImg&,const char*,T) + instead. + \par Example + \code + const CImg img1(256,128,1,3), // 'img1' is a 256x128x1x3 image + img2(img1,"xyzc"), // 'img2' is a 256x128x1x3 image + img3(img1,"y,x,z,c"), // 'img3' is a 128x256x1x3 image + img4(img1,"c,x,y,3",0), // 'img4' is a 3x128x256x3 image (with pixels initialized to '0') + \endcode + **/ + template + CImg(const CImg& img, const char *const dimensions): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values. + /** + Construct a new image instance with pixels of type \c T, and size get from the dimensions of an existing + \c CImg instance, and set all pixel values to specified \c value. + \param img Input image from which dimensions are borrowed. + \param dimensions String describing the image size along the X,Y,Z and V-dimensions. + \param value Value used for initialization. + \note + - Similar to CImg(const CImg&,const char*), but it also fills the pixel buffer with the specified \c value. + **/ + template + CImg(const CImg& img, const char *const dimensions, const T& value): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions).fill(value); + } + + //! Construct image from a display window. + /** + Construct a new image instance with pixels of type \c T, as a snapshot of an existing \c CImgDisplay instance. + \param disp Input display window. + \note + - The width() and height() of the constructed image instance are the same as the specified \c CImgDisplay. + - The depth() and spectrum() of the constructed image instance are respectively set to \c 1 and \c 3 + (i.e. a 2D color image). + - The image pixels are read as 8-bits RGB values. + **/ + explicit CImg(const CImgDisplay &disp):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + disp.snapshot(*this); + } + + // Constructor and assignment operator for rvalue references (c++11). + // This avoids an additional image copy for methods returning new images. Can save RAM for big images ! +#if cimg_use_cpp11==1 + CImg(CImg&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + swap(img); + } + + CImg& operator=(CImg&& img) { + if (_is_shared) return assign(img); + return img.swap(*this); + } +#endif + + //! Construct empty image \inplace. + /** + In-place version of the default constructor CImg(). It simply resets the instance to an empty image. + **/ + CImg& assign() { + if (!_is_shared) delete[] _data; + _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; + return *this; + } + + //! Construct image with specified size \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (siz!=curr_siz) { + if (_is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from specified " + "image (%u,%u,%u,%u).", + cimg_instance, + size_x,size_y,size_z,size_c); + else { + delete[] _data; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + return *this; + } + + //! Construct image with specified size and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,T). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value) { + return assign(size_x,size_y,size_z,size_c).fill(value); + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),int); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a sequence of doubles \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,double,double,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),double); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a value string \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,const char*,bool). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values) { + return assign(size_x,size_y,size_z,size_c).fill(values,repeat_values); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \inplace. + /** + In-place version of the constructor CImg(const t*,unsigned int,unsigned int,unsigned int,unsigned int). + **/ + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + assign(size_x,size_y,size_z,size_c); + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (values==_data && siz==curr_siz) return assign(size_x,size_y,size_z,size_c); + if (_is_shared || values + siz<_data || values>=_data + size()) { + assign(size_x,size_y,size_z,size_c); + if (_is_shared) std::memmove((void*)_data,(void*)values,siz*sizeof(T)); + else std::memcpy((void*)_data,(void*)values,siz*sizeof(T)); + } else { + T *new_data = 0; + try { new_data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy((void*)new_data,(void*)values,siz*sizeof(T)); + delete[] _data; _data = new_data; _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + } + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + if (is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from (%s*) buffer" + "(pixel types are different).", + cimg_instance, + CImg::pixel_type()); + return assign(values,size_x,size_y,size_z,size_c); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); } + else { + if (!_is_shared) { + if (values + siz<_data || values>=_data + size()) assign(); + else cimg::warn(_cimg_instance + "assign(): Shared image instance has overlapping memory.", + cimg_instance); + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = true; + _data = const_cast(values); + } + return *this; + } + + //! Construct image from memory buffer with specified size and pixel ordering scheme. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const axes_order) { + CImg(values,size_x,size_y,size_z,size_c,axes_order).move_to(*this); + } + + //! Construct image from reading an image file \inplace. + /** + In-place version of the constructor CImg(const char*). + **/ + CImg& assign(const char *const filename) { + return load(filename); + } + + //! Construct image copy \inplace. + /** + In-place version of the constructor CImg(const CImg&). + **/ + template + CImg& assign(const CImg& img) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum); + } + + //! In-place version of the advanced copy constructor. + /** + In-place version of the constructor CImg(const CImg&,bool). + **/ + template + CImg& assign(const CImg& img, const bool is_shared) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum,is_shared); + } + + //! Construct image with dimensions borrowed from another image \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions) { + if (!dimensions || !*dimensions) return assign(img._width,img._height,img._depth,img._spectrum); + unsigned int siz[4] = { 0,1,1,1 }, k = 0; + CImg item(256); + for (const char *s = dimensions; *s && k<4; ++k) { + if (cimg_sscanf(s,"%255[^0-9%xyzvwhdcXYZVWHDC]",item._data)>0) s+=std::strlen(item); + if (*s) { + unsigned int val = 0; char sep = 0; + if (cimg_sscanf(s,"%u%c",&val,&sep)>0) { + if (sep=='%') siz[k] = val*(k==0?_width:k==1?_height:k==2?_depth:_spectrum)/100; + else siz[k] = val; + while (*s>='0' && *s<='9') ++s; + if (sep=='%') ++s; + } else switch (cimg::lowercase(*s)) { + case 'x' : case 'w' : siz[k] = img._width; ++s; break; + case 'y' : case 'h' : siz[k] = img._height; ++s; break; + case 'z' : case 'd' : siz[k] = img._depth; ++s; break; + case 'c' : case 's' : siz[k] = img._spectrum; ++s; break; + default : + throw CImgArgumentException(_cimg_instance + "assign(): Invalid character '%c' detected in specified dimension string '%s'.", + cimg_instance, + *s,dimensions); + } + } + } + return assign(siz[0],siz[1],siz[2],siz[3]); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*,T). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions, const T& value) { + return assign(img,dimensions).fill(value); + } + + //! Construct image from a display window \inplace. + /** + In-place version of the constructor CImg(const CImgDisplay&). + **/ + CImg& assign(const CImgDisplay &disp) { + disp.snapshot(*this); + return *this; + } + + //! Construct empty image \inplace. + /** + Equivalent to assign(). + \note + - It has been defined for compatibility with STL naming conventions. + **/ + CImg& clear() { + return assign(); + } + + //! Transfer content of an image instance into another one. + /** + Transfer the dimensions and the pixel buffer content of an image instance into another one, + and replace instance by an empty image. It avoids the copy of the pixel buffer + when possible. + \param img Destination image. + \note + - Pixel types \c T and \c t of source and destination images can be different, though the process is + designed to be instantaneous when \c T and \c t are the same. + \par Example + \code + CImg src(256,256,1,3,0), // Construct a 256x256x1x3 (color) image filled with value '0' + dest(16,16); // Construct a 16x16x1x1 (scalar) image + src.move_to(dest); // Now, 'src' is empty and 'dest' is the 256x256x1x3 image + \endcode + **/ + template + CImg& move_to(CImg& img) { + img.assign(*this); + assign(); + return img; + } + + //! Transfer content of an image instance into another one \specialization. + CImg& move_to(CImg& img) { + if (_is_shared || img._is_shared) img.assign(*this); + else swap(img); + assign(); + return img; + } + + //! Transfer content of an image instance into a new image in an image list. + /** + Transfer the dimensions and the pixel buffer content of an image instance + into a newly inserted image at position \c pos in specified \c CImgList instance. + \param list Destination list. + \param pos Position of the newly inserted image in the list. + \note + - When optional parameter \c pos is omitted, the image instance is transferred as a new + image at the end of the specified \c list. + - It is convenient to sequentially insert new images into image lists, with no + additional copies of memory buffer. + \par Example + \code + CImgList list; // Construct an empty image list + CImg img("reference.jpg"); // Read image from filename + img.move_to(list); // Transfer image content as a new item in the list (no buffer copy) + \endcode + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos=~0U) { + const unsigned int npos = pos>list._width?list._width:pos; + move_to(list.insert(1,npos)[npos]); + return list; + } + + //! Swap fields of two image instances. + /** + \param img Image to swap fields with. + \note + - It can be used to interchange the content of two images in a very fast way. Can be convenient when dealing + with algorithms requiring two swapping buffers. + \par Example + \code + CImg img1("lena.jpg"), + img2("milla.jpg"); + img1.swap(img2); // Now, 'img1' is 'milla' and 'img2' is 'lena' + \endcode + **/ + CImg& swap(CImg& img) { + cimg::swap(_width,img._width,_height,img._height,_depth,img._depth,_spectrum,img._spectrum); + cimg::swap(_data,img._data); + cimg::swap(_is_shared,img._is_shared); + return img; + } + + //! Return a reference to an empty image. + /** + \note + This function is useful mainly to declare optional parameters having type \c CImg in functions prototypes, + e.g. + \code + void f(const int x=0, const int y=0, const CImg& img=CImg::empty()); + \endcode + **/ + static CImg& empty() { + static CImg _empty; + return _empty.assign(); + } + + //! Return a reference to an empty image \const. + static const CImg& const_empty() { + static const CImg _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Access to a pixel value. + /** + Return a reference to a located pixel value of the image instance, + being possibly \e const, whether the image instance is \e const or not. + This is the standard method to get/set pixel values in \c CImg images. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Range of pixel coordinates start from (0,0,0,0) to + (width() - 1,height() - 1,depth() - 1,spectrum() - 1). + - Due to the particular arrangement of the pixel buffers defined in %CImg, you can omit one coordinate if the + corresponding dimension is equal to \c 1. + For instance, pixels of a 2D image (depth() equal to \c 1) can be accessed by img(x,y,c) instead of + img(x,y,0,c). + \warning + - There is \e no boundary checking done in this operator, to make it as fast as possible. + You \e must take care of out-of-bounds access by yourself, if necessary. + For debugging purposes, you may want to define macro \c 'cimg_verbosity'>=3 to enable additional boundary + checking operations in this operator. In that case, warning messages will be printed on the error output + when accessing out-of-bounds pixels. + \par Example + \code + CImg img(100,100,1,3,0); // Construct a 100x100x1x3 (color) image with pixels set to '0' + const float + valR = img(10,10,0,0), // Read red value at coordinates (10,10) + valG = img(10,10,0,1), // Read green value at coordinates (10,10) + valB = img(10,10,2), // Read blue value at coordinates (10,10) (Z-coordinate can be omitted) + avg = (valR + valG + valB)/3; // Compute average pixel value + img(10,10,0) = img(10,10,1) = img(10,10,2) = avg; // Replace the color pixel (10,10) by the average grey value + \endcode + **/ +#if cimg_verbosity>=3 + T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (!_data || off>=size()) { + cimg::warn(_cimg_instance + "operator(): Invalid pixel request, at coordinates (%d,%d,%d,%d) [offset=%u].", + cimg_instance, + (int)x,(int)y,(int)z,(int)c,off); + return *_data; + } + else return _data[off]; + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->operator()(x,y,z,c); + } + + //! Access to a pixel value. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param wh Precomputed offset, must be equal to width()*\ref height(). + \param whd Precomputed offset, must be equal to width()*\ref height()*\ref depth(). + \note + - Similar to (but faster than) operator()(). + It uses precomputed offsets to optimize memory access. You may use it to optimize + the reading/writing of several pixel values in the same image (e.g. in a loop). + **/ + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) const { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } +#else + T& operator()(const unsigned int x) { + return _data[x]; + } + + const T& operator()(const unsigned int x) const { + return _data[x]; + } + + T& operator()(const unsigned int x, const unsigned int y) { + return _data[x + y*_width]; + } + + const T& operator()(const unsigned int x, const unsigned int y) const { + return _data[x + y*_width]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) { + return _data[x + y*_width + z*wh]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) const { + return _data[x + y*_width + z*wh]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) { + return _data[x + y*_width + z*wh + c*whd]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) const { + return _data[x + y*_width + z*wh + c*whd]; + } +#endif + + //! Implicitly cast an image into a \c T*. + /** + Implicitly cast a \c CImg instance into a \c T* or \c const \c T* pointer, whether the image instance + is \e const or not. The returned pointer points on the first value of the image pixel buffer. + \note + - It simply returns the pointer data() to the pixel buffer. + - This implicit conversion is convenient to test the empty state of images (data() being \c 0 in this case), e.g. + \code + CImg img1(100,100), img2; // 'img1' is a 100x100 image, 'img2' is an empty image + if (img1) { // Test succeeds, 'img1' is not an empty image + if (!img2) { // Test succeeds, 'img2' is an empty image + std::printf("'img1' is not empty, 'img2' is empty."); + } + } + \endcode + - It also allows to use brackets to access pixel values, without need for a \c CImg::operator[](), e.g. + \code + CImg img(100,100); + const float value = img[99]; // Access to value of the last pixel on the first row + img[510] = 255; // Set pixel value at (10,5) + \endcode + **/ + operator T*() { + return _data; + } + + //! Implicitly cast an image into a \c T* \const. + operator const T*() const { + return _data; + } + + //! Assign a value to all image pixels. + /** + Assign specified \c value to each pixel value of the image instance. + \param value Value that will be assigned to image pixels. + \note + - The image size is never modified. + - The \c value may be casted to pixel type \c T if necessary. + \par Example + \code + CImg img(100,100); // Declare image (with garbage values) + img = 0; // Set all pixel values to '0' + img = 1.2; // Set all pixel values to '1' (cast of '1.2' as a 'char') + \endcode + **/ + CImg& operator=(const T& value) { + return fill(value); + } + + //! Assign pixels values from a specified expression. + /** + Initialize all pixel values from the specified string \c expression. + \param expression Value string describing the way pixel values are set. + \note + - String parameter \c expression may describe different things: + - If \c expression is a list of values (as in \c "1,2,3,8,3,2"), or a formula (as in \c "(x*y)%255"), + the pixel values are set from specified \c expression and the image size is not modified. + - If \c expression is a filename (as in \c "reference.jpg"), the corresponding image file is loaded and + replace the image instance. The image size is modified if necessary. + \par Example + \code + CImg img1(100,100), img2(img1), img3(img1); // Declare 3 scalar images 100x100 with uninitialized values + img1 = "0,50,100,150,200,250,200,150,100,50"; // Set pixel values of 'img1' from a value sequence + img2 = "10*((x*y)%25)"; // Set pixel values of 'img2' from a formula + img3 = "reference.jpg"; // Set pixel values of 'img3' from a file (image size is modified) + (img1,img2,img3).display(); + \endcode + \image html ref_operator_eq.jpg + **/ + CImg& operator=(const char *const expression) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + _fill(expression,true,1,0,0,"operator=",0); + } catch (CImgException&) { + cimg::exception_mode(omode); + load(expression); + } + cimg::exception_mode(omode); + return *this; + } + + //! Copy an image into the current image instance. + /** + Similar to the in-place copy constructor assign(const CImg&). + **/ + template + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy an image into the current image instance \specialization. + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy the content of a display window to the current image instance. + /** + Similar to assign(const CImgDisplay&). + **/ + CImg& operator=(const CImgDisplay& disp) { + disp.snapshot(*this); + return *this; + } + + //! In-place addition operator. + /** + Add specified \c value to all pixels of an image instance. + \param value Value to add. + \note + - Resulting pixel values are casted to fit the pixel type \c T. + For instance, adding \c 0.2 to a \c CImg is possible but does nothing indeed. + - Overflow values are treated as with standard C++ numeric types. For instance, + \code + CImg img(100,100,1,1,255); // Construct a 100x100 image with pixel values '255' + img+=1; // Add '1' to each pixels -> Overflow + // here all pixels of image 'img' are equal to '0'. + \endcode + - To prevent value overflow, you may want to consider pixel type \c T as \c float or \c double, + and use cut() after addition. + \par Example + \code + CImg img1("reference.jpg"); // Load a 8-bits RGB image (values in [0,255]) + CImg img2(img1); // Construct a float-valued copy of 'img1' + img2+=100; // Add '100' to pixel values -> goes out of [0,255] but no problems with floats + img2.cut(0,255); // Cut values in [0,255] to fit the 'unsigned char' constraint + img1 = img2; // Rewrite safe result in 'unsigned char' version 'img1' + const CImg img3 = (img1 + 100).cut(0,255); // Do the same in a more simple and elegant way + (img1,img2,img3).display(); + \endcode + \image html ref_operator_plus.jpg + **/ + template + CImg& operator+=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr + value,524288); + return *this; + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the specified string \c expression. + \param expression Value string describing the way pixel values are added. + \note + - Similar to operator=(const char*), except that it adds values to the pixels of the current image instance, + instead of assigning them. + **/ + CImg& operator+=(const char *const expression) { + return *this+=(+*this)._fill(expression,true,1,0,0,"operator+=",this); + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the values of the input image \c img. + \param img Input image to add. + \note + - The size of the image instance is never modified. + - It is not mandatory that input image \c img has the same size as the image instance. + If less values are available in \c img, then the values are added periodically. For instance, adding one + WxH scalar image (spectrum() equal to \c 1) to one WxH color image (spectrum() equal to \c 3) + means each color channel will be incremented with the same values at the same locations. + \par Example + \code + CImg img1("reference.jpg"); // Load a RGB color image (img1.spectrum()==3) + // Construct a scalar shading (img2.spectrum()==1). + const CImg img2(img1.width(),img.height(),1,1,"255*(x/w)^2"); + img1+=img2; // Add shading to each channel of 'img1' + img1.cut(0,255); // Prevent [0,255] overflow + (img2,img1).display(); + \endcode + \image html ref_operator_plus1.jpg + **/ + template + CImg& operator+=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this+=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator++() { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr + 1,524288); + return *this; + } + + //! In-place increment operator (postfix). + /** + Add \c 1 to all image pixels, and return a new copy of the initial (pre-incremented) image instance. + \note + - Use the prefixed version operator++() if you don't need a copy of the initial + (pre-incremented) image instance, since a useless image copy may be expensive in terms of memory usage. + **/ + CImg operator++(int) { + const CImg copy(*this,false); + ++*this; + return copy; + } + + //! Return a non-shared copy of the image instance. + /** + \note + - Use this operator to ensure you get a non-shared copy of an image instance with same pixel type \c T. + Indeed, the usual copy constructor CImg(const CImg&) returns a shared copy of a shared input image, + and it may be not desirable to work on a regular copy (e.g. for a resize operation) if you have no + information about the shared state of the input image. + - Writing \c (+img) is equivalent to \c CImg(img,false). + **/ + CImg operator+() const { + return CImg(*this,false); + } + + //! Addition operator. + /** + Similar to operator+=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const t value) const { + return CImg<_cimg_Tt>(*this,false)+=value; + } + + //! Addition operator. + /** + Similar to operator+=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator+(const char *const expression) const { + return CImg(*this,false)+=expression; + } + + //! Addition operator. + /** + Similar to operator+=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)+=img; + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const t), except that it performs a subtraction instead of an addition. + **/ + template + CImg& operator-=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr - value,524288); + return *this; + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const char*), except that it performs a subtraction instead of an addition. + **/ + CImg& operator-=(const char *const expression) { + return *this-=(+*this)._fill(expression,true,1,0,0,"operator-=",this); + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const CImg&), except that it performs a subtraction instead of an addition. + **/ + template + CImg& operator-=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this-=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator--() { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr - 1,524288); + return *this; + } + + //! In-place decrement operator (postfix). + /** + Similar to operator++(int), except that it performs a decrement instead of an increment. + **/ + CImg operator--(int) { + const CImg copy(*this,false); + --*this; + return copy; + } + + //! Replace each pixel by its opposite value. + /** + \note + - If the computed opposite values are out-of-range, they are treated as with standard C++ numeric types. + For instance, the \c unsigned \c char opposite of \c 1 is \c 255. + \par Example + \code + const CImg + img1("reference.jpg"), // Load a RGB color image + img2 = -img1; // Compute its opposite (in 'unsigned char') + (img1,img2).display(); + \endcode + \image html ref_operator_minus.jpg + **/ + CImg operator-() const { + return CImg(_width,_height,_depth,_spectrum,(T)0)-=*this; + } + + //! Subtraction operator. + /** + Similar to operator-=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const t value) const { + return CImg<_cimg_Tt>(*this,false)-=value; + } + + //! Subtraction operator. + /** + Similar to operator-=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator-(const char *const expression) const { + return CImg(*this,false)-=expression; + } + + //! Subtraction operator. + /** + Similar to operator-=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)-=img; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const t), except that it performs a multiplication instead of an addition. + **/ + template + CImg& operator*=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr * value,262144); + return *this; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const char*), except that it performs a multiplication instead of an addition. + **/ + CImg& operator*=(const char *const expression) { + return mul((+*this)._fill(expression,true,1,0,0,"operator*=",this)); + } + + //! In-place multiplication operator. + /** + Replace the image instance by the matrix multiplication between the image instance and the specified matrix + \c img. + \param img Second operand of the matrix multiplication. + \note + - It does \e not compute a pointwise multiplication between two images. For this purpose, use + mul(const CImg&) instead. + - The size of the image instance can be modified by this operator. + \par Example + \code + CImg A(2,2,1,1, 1,2,3,4); // Construct 2x2 matrix A = [1,2;3,4] + const CImg X(1,2,1,1, 1,2); // Construct 1x2 vector X = [1;2] + A*=X; // Assign matrix multiplication A*X to 'A' + // 'A' is now a 1x2 vector whose values are [5;11]. + \endcode + **/ + template + CImg& operator*=(const CImg& img) { + return ((*this)*img).move_to(*this); + } + + //! Multiplication operator. + /** + Similar to operator*=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const t value) const { + return CImg<_cimg_Tt>(*this,false)*=value; + } + + //! Multiplication operator. + /** + Similar to operator*=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator*(const char *const expression) const { + return CImg(*this,false)*=expression; + } + + //! Multiplication operator. + /** + Similar to operator*=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const CImg& img) const { + typedef _cimg_Ttdouble Ttdouble; + typedef _cimg_Tt Tt; + if (_width!=img._height || _depth!=1 || _spectrum!=1) + throw CImgArgumentException(_cimg_instance + "operator*(): Invalid multiplication of instance by specified " + "matrix (%u,%u,%u,%u,%p).", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + CImg res(img._width,_height); + + // Check for common cases to optimize. + if (img._width==1) { // Matrix * Vector + if (_height==1) switch (_width) { // Vector^T * Vector + case 1 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0]); + return res; + case 2 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1]); + return res; + case 3 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2]); + return res; + case 4 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2] + (Ttdouble)_data[3]*img[3]); + return res; + default : { + Ttdouble val = 0; + cimg_pragma_openmp(parallel for reduction(+:val) cimg_openmp_if_size(size(),4096)) + cimg_forX(*this,i) val+=(Ttdouble)_data[i]*img[i]; + res[0] = val; + return res; + } + } else if (_height==_width) switch (_width) { // Square_matrix * Vector + case 2 : // 2x2_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1]); + res[1] = (Tt)((Ttdouble)_data[2]*img[0] + (Ttdouble)_data[3]*img[1]); + return res; + case 3 : // 3x3_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2]); + res[1] = (Tt)((Ttdouble)_data[3]*img[0] + (Ttdouble)_data[4]*img[1] + + (Ttdouble)_data[5]*img[2]); + res[2] = (Tt)((Ttdouble)_data[6]*img[0] + (Ttdouble)_data[7]*img[1] + + (Ttdouble)_data[8]*img[2]); + return res; + case 4 : // 4x4_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2] + (Ttdouble)_data[3]*img[3]); + res[1] = (Tt)((Ttdouble)_data[4]*img[0] + (Ttdouble)_data[5]*img[1] + + (Ttdouble)_data[6]*img[2] + (Ttdouble)_data[7]*img[3]); + res[2] = (Tt)((Ttdouble)_data[8]*img[0] + (Ttdouble)_data[9]*img[1] + + (Ttdouble)_data[10]*img[2] + (Ttdouble)_data[11]*img[3]); + res[3] = (Tt)((Ttdouble)_data[12]*img[0] + (Ttdouble)_data[13]*img[1] + + (Ttdouble)_data[14]*img[2] + (Ttdouble)_data[15]*img[3]); + return res; + } + } else if (_height==_width) { + if (img._height==img._width) switch (_width) { // Square_matrix * Square_matrix + case 2 : // 2x2_matrix * 2x2_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[2]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[3]); + res[2] = (Tt)((Ttdouble)_data[2]*img[0] + (Ttdouble)_data[3]*img[2]); + res[3] = (Tt)((Ttdouble)_data[2]*img[1] + (Ttdouble)_data[3]*img[3]); + return res; + case 3 : // 3x3_matrix * 3x3_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[3] + + (Ttdouble)_data[2]*img[6]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[4] + + (Ttdouble)_data[2]*img[7]); + res[2] = (Tt)((Ttdouble)_data[0]*img[2] + (Ttdouble)_data[1]*img[5] + + (Ttdouble)_data[2]*img[8]); + res[3] = (Tt)((Ttdouble)_data[3]*img[0] + (Ttdouble)_data[4]*img[3] + + (Ttdouble)_data[5]*img[6]); + res[4] = (Tt)((Ttdouble)_data[3]*img[1] + (Ttdouble)_data[4]*img[4] + + (Ttdouble)_data[5]*img[7]); + res[5] = (Tt)((Ttdouble)_data[3]*img[2] + (Ttdouble)_data[4]*img[5] + + (Ttdouble)_data[5]*img[8]); + res[6] = (Tt)((Ttdouble)_data[6]*img[0] + (Ttdouble)_data[7]*img[3] + + (Ttdouble)_data[8]*img[6]); + res[7] = (Tt)((Ttdouble)_data[6]*img[1] + (Ttdouble)_data[7]*img[4] + + (Ttdouble)_data[8]*img[7]); + res[8] = (Tt)((Ttdouble)_data[6]*img[2] + (Ttdouble)_data[7]*img[5] + + (Ttdouble)_data[8]*img[8]); + return res; + case 4 : // 4x4_matrix * 4x4_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[4] + + (Ttdouble)_data[2]*img[8] + (Ttdouble)_data[3]*img[12]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[5] + + (Ttdouble)_data[2]*img[9] + (Ttdouble)_data[3]*img[13]); + res[2] = (Tt)((Ttdouble)_data[0]*img[2] + (Ttdouble)_data[1]*img[6] + + (Ttdouble)_data[2]*img[10] + (Ttdouble)_data[3]*img[14]); + res[3] = (Tt)((Ttdouble)_data[0]*img[3] + (Ttdouble)_data[1]*img[7] + + (Ttdouble)_data[2]*img[11] + (Ttdouble)_data[3]*img[15]); + res[4] = (Tt)((Ttdouble)_data[4]*img[0] + (Ttdouble)_data[5]*img[4] + + (Ttdouble)_data[6]*img[8] + (Ttdouble)_data[7]*img[12]); + res[5] = (Tt)((Ttdouble)_data[4]*img[1] + (Ttdouble)_data[5]*img[5] + + (Ttdouble)_data[6]*img[9] + (Ttdouble)_data[7]*img[13]); + res[6] = (Tt)((Ttdouble)_data[4]*img[2] + (Ttdouble)_data[5]*img[6] + + (Ttdouble)_data[6]*img[10] + (Ttdouble)_data[7]*img[14]); + res[7] = (Tt)((Ttdouble)_data[4]*img[3] + (Ttdouble)_data[5]*img[7] + + (Ttdouble)_data[6]*img[11] + (Ttdouble)_data[7]*img[15]); + res[8] = (Tt)((Ttdouble)_data[8]*img[0] + (Ttdouble)_data[9]*img[4] + + (Ttdouble)_data[10]*img[8] + (Ttdouble)_data[11]*img[12]); + res[9] = (Tt)((Ttdouble)_data[8]*img[1] + (Ttdouble)_data[9]*img[5] + + (Ttdouble)_data[10]*img[9] + (Ttdouble)_data[11]*img[13]); + res[10] = (Tt)((Ttdouble)_data[8]*img[2] + (Ttdouble)_data[9]*img[6] + + (Ttdouble)_data[10]*img[10] + (Ttdouble)_data[11]*img[14]); + res[11] = (Tt)((Ttdouble)_data[8]*img[3] + (Ttdouble)_data[9]*img[7] + + (Ttdouble)_data[10]*img[11] + (Ttdouble)_data[11]*img[15]); + res[12] = (Tt)((Ttdouble)_data[12]*img[0] + (Ttdouble)_data[13]*img[4] + + (Ttdouble)_data[14]*img[8] + (Ttdouble)_data[15]*img[12]); + res[13] = (Tt)((Ttdouble)_data[12]*img[1] + (Ttdouble)_data[13]*img[5] + + (Ttdouble)_data[14]*img[9] + (Ttdouble)_data[15]*img[13]); + res[14] = (Tt)((Ttdouble)_data[12]*img[2] + (Ttdouble)_data[13]*img[6] + + (Ttdouble)_data[14]*img[10] + (Ttdouble)_data[15]*img[14]); + res[15] = (Tt)((Ttdouble)_data[12]*img[3] + (Ttdouble)_data[13]*img[7] + + (Ttdouble)_data[14]*img[11] + (Ttdouble)_data[15]*img[15]); + return res; + } else switch (_width) { // Square_matrix * Matrix + case 2 : { // 2x2_matrix * Matrix + const t *const ps0 = img.data(), *const ps1 = img.data(0,1); + Tt *const pd0 = res.data(), *const pd1 = res.data(0,1); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], + a2 = (Ttdouble)_data[2], a3 = (Ttdouble)_data[3]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),4096)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i]; + pd0[i] = (Tt)(a0*x + a1*y); + pd1[i] = (Tt)(a2*x + a3*y); + } + return res; + } + case 3 : { // 3x3_matrix * Matrix + const t *const ps0 = img.data(), *const ps1 = img.data(0,1), *const ps2 = img.data(0,2); + Tt *const pd0 = res.data(), *const pd1 = res.data(0,1), *const pd2 = res.data(0,2); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], a2 = (Ttdouble)_data[2], + a3 = (Ttdouble)_data[3], a4 = (Ttdouble)_data[4], a5 = (Ttdouble)_data[5], + a6 = (Ttdouble)_data[6], a7 = (Ttdouble)_data[7], a8 = (Ttdouble)_data[8]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),1024)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i], z = (Ttdouble)ps2[i]; + pd0[i] = (Tt)(a0*x + a1*y + a2*z); + pd1[i] = (Tt)(a3*x + a4*y + a5*z); + pd2[i] = (Tt)(a6*x + a7*y + a8*z); + } + return res; + } + case 4 : { // 4x4_matrix * Matrix + const t + *const ps0 = img.data(), *const ps1 = img.data(0,1), + *const ps2 = img.data(0,2), *const ps3 = img.data(0,3); + Tt + *const pd0 = res.data(), *const pd1 = res.data(0,1), + *const pd2 = res.data(0,2), *const pd3 = res.data(0,3); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], a2 = (Ttdouble)_data[2], a3 = (Ttdouble)_data[3], + a4 = (Ttdouble)_data[4], a5 = (Ttdouble)_data[5], a6 = (Ttdouble)_data[6], a7 = (Ttdouble)_data[7], + a8 = (Ttdouble)_data[8], a9 = (Ttdouble)_data[9], a10 = (Ttdouble)_data[10], a11 = (Ttdouble)_data[11], + a12 = (Ttdouble)_data[12], a13 = (Ttdouble)_data[13], a14 = (Ttdouble)_data[14], + a15 = (Ttdouble)_data[15]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),512)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i], z = (Ttdouble)ps2[i], c = (Ttdouble)ps3[i]; + pd0[i] = (Tt)(a0*x + a1*y + a2*z + a3*c); + pd1[i] = (Tt)(a4*x + a5*y + a6*z + a7*c); + pd2[i] = (Tt)(a8*x + a9*y + a10*z + a11*c); + pd3[i] = (Tt)(a12*x + a13*y + a14*z + a15*c); + } + return res; + } + } + } + + // Fallback to generic version. +#if cimg_use_openmp!=0 + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(size()>(cimg_openmp_sizefactor)*1024 && + img.size()>(cimg_openmp_sizefactor)*1024)) + cimg_forXY(res,i,j) { + Ttdouble value = 0; + cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); + res(i,j) = (Tt)value; + } +#else + Tt *ptrd = res._data; + cimg_forXY(res,i,j) { + Ttdouble value = 0; + cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); + *(ptrd++) = (Tt)value; + } +#endif + return res; + } + + //! In-place division operator. + /** + Similar to operator+=(const t), except that it performs a division instead of an addition. + **/ + template + CImg& operator/=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr / value,32768); + return *this; + } + + //! In-place division operator. + /** + Similar to operator+=(const char*), except that it performs a division instead of an addition. + **/ + CImg& operator/=(const char *const expression) { + return div((+*this)._fill(expression,true,1,0,0,"operator/=",this)); + } + + //! In-place division operator. + /** + Replace the image instance by the (right) matrix division between the image instance and the specified + matrix \c img. + \param img Second operand of the matrix division. + \note + - It does \e not compute a pointwise division between two images. For this purpose, use + div(const CImg&) instead. + - It returns the matrix operation \c A*inverse(img). + - The size of the image instance can be modified by this operator. + **/ + template + CImg& operator/=(const CImg& img) { + return (*this*img.get_invert()).move_to(*this); + } + + //! Division operator. + /** + Similar to operator/=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const t value) const { + return CImg<_cimg_Tt>(*this,false)/=value; + } + + //! Division operator. + /** + Similar to operator/=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator/(const char *const expression) const { + return CImg(*this,false)/=expression; + } + + //! Division operator. + /** + Similar to operator/=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const CImg& img) const { + return (*this)*img.get_invert(); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const t), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::mod(*ptr,(T)value),16384); + return *this; + } + + //! In-place modulo operator. + /** + Similar to operator+=(const char*), except that it performs a modulo operation instead of an addition. + **/ + CImg& operator%=(const char *const expression) { + return *this%=(+*this)._fill(expression,true,1,0,0,"operator%=",this); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const CImg&), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this%=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> operator%(const t value) const { + return CImg<_cimg_Tt>(*this,false)%=value; + } + + //! Modulo operator. + /** + Similar to operator%=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator%(const char *const expression) const { + return CImg(*this,false)%=expression; + } + + //! Modulo operator. + /** + Similar to operator%=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator%(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)%=img; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const t), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr & (ulongT)value,32768); + return *this; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise AND operation instead of an addition. + **/ + CImg& operator&=(const char *const expression) { + return *this&=(+*this)._fill(expression,true,1,0,0,"operator&=",this); + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this&=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator&(const t value) const { + return (+*this)&=value; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator&(const char *const expression) const { + return (+*this)&=expression; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator&(const CImg& img) const { + return (+*this)&=img; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr | (ulongT)value,32768); + return *this; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise OR operation instead of an addition. + **/ + CImg& operator|=(const char *const expression) { + return *this|=(+*this)._fill(expression,true,1,0,0,"operator|=",this); + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this|=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator|(const t value) const { + return (+*this)|=value; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator|(const char *const expression) const { + return (+*this)|=expression; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator|(const CImg& img) const { + return (+*this)|=img; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const t) instead. + **/ + template + CImg& operator^=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr ^ (ulongT)value,32768); + return *this; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const char*) instead. + **/ + CImg& operator^=(const char *const expression) { + return *this^=(+*this)._fill(expression,true,1,0,0,"operator^=",this); + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const CImg&) instead. + **/ + template + CImg& operator^=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator^(const t value) const { + return (+*this)^=value; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator^(const char *const expression) const { + return (+*this)^=expression; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator^(const CImg& img) const { + return (+*this)^=img; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,((longT)*ptr) << (int)value,65536); + return *this; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise left shift instead of an addition. + **/ + CImg& operator<<=(const char *const expression) { + return *this<<=(+*this)._fill(expression,true,1,0,0,"operator<<=",this); + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator<<(const t value) const { + return (+*this)<<=value; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator<<(const char *const expression) const { + return (+*this)<<=expression; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator<<(const CImg& img) const { + return (+*this)<<=img; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,((longT)*ptr) >> (int)value,65536); + return *this; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise right shift instead of an addition. + **/ + CImg& operator>>=(const char *const expression) { + return *this>>=(+*this)._fill(expression,true,1,0,0,"operator>>=",this); + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs> (int)*(ptrs++)); + for (const t *ptrs = img._data; ptrd> (int)*(ptrs++)); + } + return *this; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const t value) const { + return (+*this)>>=value; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator>>(const char *const expression) const { + return (+*this)>>=expression; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const CImg& img) const { + return (+*this)>>=img; + } + + //! Bitwise inversion operator. + /** + Similar to operator-(), except that it compute the bitwise inverse instead of the opposite value. + **/ + CImg operator~() const { + CImg res(_width,_height,_depth,_spectrum); + const T *ptrs = _data; + cimg_for(res,ptrd,T) { const ulongT value = (ulongT)*(ptrs++); *ptrd = (T)~value; } + return res; + } + + //! Test if all pixels of an image have the same value. + /** + Return \c true is all pixels of the image instance are equal to the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator==(const t value) const { + if (is_empty()) return false; + typedef _cimg_Tt Tt; + bool is_equal = true; + for (T *ptrd = _data + size(); is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)value)) {} + return is_equal; + } + + //! Test if all pixel values of an image follow a specified expression. + /** + Return \c true is all pixels of the image instance are equal to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator==(const char *const expression) const { + return *this==(+*this)._fill(expression,true,1,0,0,"operator==",this); + } + + //! Test if two images have the same size and values. + /** + Return \c true if the image instance and the input image \c img have the same pixel values, + even if the dimensions of the two images do not match. It returns \c false otherwise. + \param img Input image to compare with. + \note + - The pixel buffer pointers data() of the two compared images do not have to be the same for operator==() + to return \c true. + Only the dimensions and the pixel values matter. Thus, the comparison can be \c true even for different + pixel types \c T and \c t. + \par Example + \code + const CImg img1(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'float' pixel values) + const CImg img2(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'char' pixel values) + if (img1==img2) { // Test succeeds, image dimensions and values are the same + std::printf("'img1' and 'img2' have same dimensions and values."); + } + \endcode + **/ + template + bool operator==(const CImg& img) const { + typedef _cimg_Tt Tt; + const ulongT siz = size(); + bool is_equal = true; + if (siz!=img.size()) return false; + t *ptrs = img._data + siz; + for (T *ptrd = _data + siz; is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)*(--ptrs))) {} + return is_equal; + } + + //! Test if pixels of an image are all different from a value. + /** + Return \c true is all pixels of the image instance are different than the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator!=(const t value) const { + return !((*this)==value); + } + + //! Test if all pixel values of an image are different from a specified expression. + /** + Return \c true is all pixels of the image instance are different to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator!=(const char *const expression) const { + return !((*this)==expression); + } + + //! Test if two images have different sizes or values. + /** + Return \c true if the image instance and the input image \c img have different dimensions or pixel values, + and \c false otherwise. + \param img Input image to compare with. + \note + - Writing \c img1!=img2 is equivalent to \c !(img1==img2). + **/ + template + bool operator!=(const CImg& img) const { + return !((*this)==img); + } + + //! Construct an image list from two images. + /** + Return a new list of image (\c CImgList instance) containing exactly two elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image \c img, at position [\c 1]. + + \param img Input image that will be the second image of the resulting list. + \note + - The family of operator,() is convenient to easily create list of images, but it is also \e quite \e slow + in practice (see warning below). + - Constructed lists contain no shared images. If image instance or input image \c img are shared, they are + inserted as new non-shared copies in the resulting list. + - The pixel type of the returned list may be a superset of the initial pixel type \c T, if necessary. + \warning + - Pipelining operator,() \c N times will perform \c N copies of the entire content of a (growing) image list. + This may become very expensive in terms of speed and used memory. You should avoid using this technique to + build a new CImgList instance from several images, if you are seeking for performance. + Fast insertions of images in an image list are possible with + CImgList::insert(const CImg&,unsigned int,bool) or move_to(CImgList&,unsigned int). + \par Example + \code + const CImg + img1("reference.jpg"), + img2 = img1.get_mirror('x'), + img3 = img2.get_blur(5); + const CImgList list = (img1,img2); // Create list of two elements from 'img1' and 'img2' + (list,img3).display(); // Display image list containing copies of 'img1','img2' and 'img3' + \endcode + \image html ref_operator_comma.jpg + **/ + template + CImgList<_cimg_Tt> operator,(const CImg& img) const { + return CImgList<_cimg_Tt>(*this,img); + } + + //! Construct an image list from image instance and an input image list. + /** + Return a new list of images (\c CImgList instance) containing exactly \c list.size() \c + \c 1 elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image list \c list, from positions [\c 1] to [\c list.size()]. + + \param list Input image list that will be appended to the image instance. + \note + - Similar to operator,(const CImg&) const, except that it takes an image list as an argument. + **/ + template + CImgList<_cimg_Tt> operator,(const CImgList& list) const { + return CImgList<_cimg_Tt>(list,false).insert(*this,0); + } + + //! Split image along specified axis. + /** + Return a new list of images (\c CImgList instance) containing the split components + of the instance image along the specified axis. + \param axis Splitting axis (can be '\c x','\c y','\c z' or '\c c') + \note + - Similar to get_split(char,int) const, with default second argument. + \par Example + \code + const CImg img("reference.jpg"); // Load a RGB color image + const CImgList list = (img<'c'); // Get a list of its three R,G,B channels + (img,list).display(); + \endcode + \image html ref_operator_less.jpg + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the number of image columns. + /** + Return the image width, i.e. the image dimension along the X-axis. + \note + - The width() of an empty image is equal to \c 0. + - width() is typically equal to \c 1 when considering images as \e vectors for matrix calculations. + - width() returns an \c int, although the image width is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._width. + **/ + int width() const { + return (int)_width; + } + + //! Return the number of image rows. + /** + Return the image height, i.e. the image dimension along the Y-axis. + \note + - The height() of an empty image is equal to \c 0. + - height() returns an \c int, although the image height is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._height. + **/ + int height() const { + return (int)_height; + } + + //! Return the number of image slices. + /** + Return the image depth, i.e. the image dimension along the Z-axis. + \note + - The depth() of an empty image is equal to \c 0. + - depth() is typically equal to \c 1 when considering usual 2D images. When depth()\c > \c 1, the image + is said to be \e volumetric. + - depth() returns an \c int, although the image depth is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._depth. + **/ + int depth() const { + return (int)_depth; + } + + //! Return the number of image channels. + /** + Return the number of image channels, i.e. the image dimension along the C-axis. + \note + - The spectrum() of an empty image is equal to \c 0. + - spectrum() is typically equal to \c 1 when considering scalar-valued images, to \c 3 + for RGB-coded color images, and to \c 4 for RGBA-coded color images (with alpha-channel). + The number of channels of an image instance is not limited. The meaning of the pixel values is not linked + up to the number of channels (e.g. a 4-channel image may indifferently stands for a RGBA or CMYK color image). + - spectrum() returns an \c int, although the image spectrum is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._spectrum. + **/ + int spectrum() const { + return (int)_spectrum; + } + + //! Return the total number of pixel values. + /** + Return width()*\ref height()*\ref depth()*\ref spectrum(), + i.e. the total number of values of type \c T in the pixel buffer of the image instance. + \note + - The size() of an empty image is equal to \c 0. + - The allocated memory size for a pixel buffer of a non-shared \c CImg instance is equal to + size()*sizeof(T). + \par Example + \code + const CImg img(100,100,1,3); // Construct new 100x100 color image + if (img.size()==30000) // Test succeeds + std::printf("Pixel buffer uses %lu bytes", + img.size()*sizeof(float)); + \endcode + **/ + ulongT size() const { + return (ulongT)_width*_height*_depth*_spectrum; + } + + //! Return a pointer to the first pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the first value in the pixel buffer of the image instance, + whether the instance is \c const or not. + \note + - The data() of an empty image is equal to \c 0 (null pointer). + - The allocated pixel buffer for the image instance starts from \c data() + and goes to data()+\ref size() - 1 (included). + - To get the pointer to one particular location of the pixel buffer, use + data(unsigned int,unsigned int,unsigned int,unsigned int) instead. + **/ + T* data() { + return _data; + } + + //! Return a pointer to the first pixel value \const. + const T* data() const { + return _data; + } + + //! Return a pointer to a located pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the value located at (\c x,\c y,\c z,\c c) in the pixel buffer + of the image instance, + whether the instance is \c const or not. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)). Thus, this method has the same + properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + **/ +#if cimg_verbosity>=3 + T *data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (off>=size()) + cimg::warn(_cimg_instance + "data(): Invalid pointer request, at coordinates (%u,%u,%u,%u) [offset=%u].", + cimg_instance, + x,y,z,c,off); + return _data + off; + } + + //! Return a pointer to a located pixel value \const. + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->data(x,y,z,c); + } +#else + T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } + + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } +#endif + + //! Return the offset to a located pixel value, with respect to the beginning of the pixel buffer. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)) - img.data(). + Thus, this method has the same properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + \par Example + \code + const CImg img(100,100,1,3); // Define a 100x100 RGB-color image + const long off = img.offset(10,10,0,2); // Get the offset of the blue value of the pixel located at (10,10) + const float val = img[off]; // Get the blue value of this pixel + \endcode + **/ + longT offset(const int x, const int y=0, const int z=0, const int c=0) const { + return x + (longT)y*_width + (longT)z*_width*_height + (longT)c*_width*_height*_depth; + } + + //! Return a CImg::iterator pointing to the first pixel value. + /** + \note + - Equivalent to data(). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + iterator begin() { + return _data; + } + + //! Return a CImg::iterator pointing to the first value of the pixel buffer \const. + const_iterator begin() const { + return _data; + } + + //! Return a CImg::iterator pointing next to the last pixel value. + /** + \note + - Writing \c img.end() is equivalent to img.data() + img.size(). + - It has been mainly defined for compatibility with STL naming conventions. + \warning + - The returned iterator actually points to a value located \e outside the acceptable bounds of the pixel buffer. + Trying to read or write the content of the returned iterator will probably result in a crash. + Use it mainly as a strict upper bound for a CImg::iterator. + \par Example + \code + CImg img(100,100,1,3); // Define a 100x100 RGB color image + // 'img.end()' used below as an upper bound for the iterator. + for (CImg::iterator it = img.begin(); it::iterator pointing next to the last pixel value \const. + const_iterator end() const { + return _data + size(); + } + + //! Return a reference to the first pixel value. + /** + \note + - Writing \c img.front() is equivalent to img[0], or img(0,0,0,0). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& front() { + return *_data; + } + + //! Return a reference to the first pixel value \const. + const T& front() const { + return *_data; + } + + //! Return a reference to the last pixel value. + /** + \note + - Writing \c img.back() is equivalent to img[img.size() - 1], or + img(img.width() - 1,img.height() - 1,img.depth() - 1,img.spectrum() - 1). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& back() { + return *(_data + size() - 1); + } + + //! Return a reference to the last pixel value \const. + const T& back() const { + return *(_data + size() - 1); + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to a specified default value in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note + - Writing \c img.at(offset,out_value) is similar to img[offset], except that if \c offset + is outside bounds (e.g. \c offset<0 or \c offset>=img.size()), a reference to a value \c out_value + is safely returned instead. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + **/ + T& at(const int offset, const T& out_value) { + return (offset<0 || offset>=(int)size())?(cimg::temporary(out_value)=out_value):(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions \const. + T at(const int offset, const T& out_value) const { + return (offset<0 || offset>=(int)size())?out_value:(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to the nearest pixel location in the image instance in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \note + - Similar to at(int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified offset, i.e. + - If \c offset<0, then \c img[0] is returned. + - If \c offset>=img.size(), then \c img[img.size() - 1] is returned. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + - If you know your image instance is \e not empty, you may rather use the slightly faster method \c _at(int). + **/ + T& at(const int offset) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + T& _at(const int offset) { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions \const. + const T& at(const int offset) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + const T& _at(const int offset) const { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to a specified default value in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c x,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to operator()(), except that an out-of-bounds access along the X-axis returns the specified value + \c out_value. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || x>=width())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate \const. + T atX(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || x>=width())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to the nearest pixel location in the image instance in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to at(int,int,int,int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified X-coordinate. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _at(int,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + T& _atX(const int x, const int y=0, const int z=0, const int c=0) { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate \const. + const T& atX(const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + const T& _atX(const int x, const int y=0, const int z=0, const int c=0) const { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on X and Y-coordinates. + **/ + T& atXY(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || x>=width() || y>=height())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y coordinates \const. + T atXY(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || x>=width() || y>=height())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXY(int,int,int,int). + **/ + T& atXY(const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + T& _atXY(const int x, const int y, const int z=0, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates \const. + const T& atXY(const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + const T& _atXY(const int x, const int y, const int z=0, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on + X,Y and Z-coordinates. + **/ + T& atXYZ(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates \const. + T atXYZ(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZ(int,int,int,int). + **/ + T& atXYZ(const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + T& _atXYZ(const int x, const int y, const int z, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates \const. + const T& atXYZ(const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + const T& _atXYZ(const int x, const int y, const int z, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed on all + X,Y,Z and C-coordinates. + **/ + T& atXYZC(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions \const. + T atXYZC(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())?out_value: + (*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed on all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZC(int,int,int,int). + **/ + T& atXYZC(const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + T& _atXYZC(const int x, const int y, const int z, const int c) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Access to a pixel value, using Neumann boundary conditions \const. + const T& atXYZC(const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + const T& _atXYZC(const int x, const int y, const int z, const int c) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to atX(int,int,int,int,const T), except that the returned pixel value is approximated by + a linear interpolation along the X-axis, if corresponding coordinates are not integers. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + const Tfloat + Ic = (Tfloat)atX(x,y,z,c,out_value), In = (Tfloat)atXY(nx,y,z,c,out_value); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access along + the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that an out-of-bounds access returns + the value of the nearest pixel in the image instance, regarding the specified X-coordinate. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX(): Empty instance.", + cimg_instance); + + return _linear_atX(fx,y,z,c); + } + + Tfloat _linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = dx>0?x + 1:x; + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X-coordinate. + Tfloat linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX_p(): Empty instance.", + cimg_instance); + + return _linear_atX_p(fx,y,z,c); + } + + Tfloat _linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = cimg::mod(x + 1,_width); + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X and Y-coordinates. + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + const Tfloat + Icc = (Tfloat)atXY(x,y,z,c,out_value), Inc = (Tfloat)atXY(nx,y,z,c,out_value), + Icn = (Tfloat)atXY(x,ny,z,c,out_value), Inn = (Tfloat)atXY(nx,ny,z,c,out_value); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXY(float,float,int,int). + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY(): Empty instance.", + cimg_instance); + + return _linear_atXY(fx,fy,z,c); + } + + Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y; + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X and Y-coordinates. + Tfloat linear_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY_p(): Empty instance.", + cimg_instance); + + return _linear_atXY_p(fx,fy,z,c); + } + + Tfloat _linear_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height); + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X,Y and Z-coordinates. + **/ + Tfloat linear_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + const Tfloat + Iccc = (Tfloat)atXYZ(x,y,z,c,out_value), Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), + Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), + Iccn = (Tfloat)atXYZ(x,y,nz,c,out_value), Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), + Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZ(float,float,float,int). + **/ + Tfloat linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ(): Empty instance.", + cimg_instance); + + return _linear_atXYZ(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z; + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X,Y and Z-coordinates. + Tfloat linear_atXYZ_p(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ_p(): Empty instance.", + cimg_instance); + + return _linear_atXYZ_p(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ_p(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f), + nfz = cimg::mod(fz,_depth - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height), + nz = cimg::mod(z + 1,_depth); + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for all X,Y,Z,C-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved for all X,Y,Z and C-coordinates. + **/ + Tfloat linear_atXYZC(const float fx, const float fy, const float fz, const float fc, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1, + c = (int)fc - (fc>=0?0:1), nc = c + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z, + dc = fc - c; + const Tfloat + Icccc = (Tfloat)atXYZC(x,y,z,c,out_value), Inccc = (Tfloat)atXYZC(nx,y,z,c,out_value), + Icncc = (Tfloat)atXYZC(x,ny,z,c,out_value), Inncc = (Tfloat)atXYZC(nx,ny,z,c,out_value), + Iccnc = (Tfloat)atXYZC(x,y,nz,c,out_value), Incnc = (Tfloat)atXYZC(nx,y,nz,c,out_value), + Icnnc = (Tfloat)atXYZC(x,ny,nz,c,out_value), Innnc = (Tfloat)atXYZC(nx,ny,nz,c,out_value), + Icccn = (Tfloat)atXYZC(x,y,z,nc,out_value), Inccn = (Tfloat)atXYZC(nx,y,z,nc,out_value), + Icncn = (Tfloat)atXYZC(x,ny,z,nc,out_value), Inncn = (Tfloat)atXYZC(nx,ny,z,nc,out_value), + Iccnn = (Tfloat)atXYZC(x,y,nz,nc,out_value), Incnn = (Tfloat)atXYZC(nx,y,nz,nc,out_value), + Icnnn = (Tfloat)atXYZC(x,ny,nz,nc,out_value), Innnn = (Tfloat)atXYZC(nx,ny,nz,nc,out_value); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn -Icccc); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for all X,Y,Z and C-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved for all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZC(float,float,float,float). + **/ + Tfloat linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC(): Empty instance.", + cimg_instance); + + return _linear_atXYZC(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1), + nfc = cimg::cut(fc,0,spectrum() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z, + nc = dc>0?c + 1:c; + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for all X,Y,Z and C-coordinates. + Tfloat linear_atXYZC_p(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC_p(): Empty instance.", + cimg_instance); + + return _linear_atXYZC_p(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC_p(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f), + nfz = cimg::mod(fz,_depth - 0.5f), + nfc = cimg::mod(fc,_spectrum - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height), + nz = cimg::mod(z + 1,_depth), + nc = cimg::mod(c + 1,_spectrum); + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + The cubic interpolation uses Hermite splines. + \param fx d X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a \e cubic interpolation along the X-axis. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2; + const float + dx = fx - x; + const Tfloat + Ip = (Tfloat)atX(px,y,z,c,out_value), Ic = (Tfloat)atX(x,y,z,c,out_value), + In = (Tfloat)atX(nx,y,z,c,out_value), Ia = (Tfloat)atX(ax,y,z,c,out_value); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atX_c(const float fx, const int y, const int z, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atX(fx,y,z,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access + along the X-axis. The cubic interpolation uses Hermite splines. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to cubic_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a cubic interpolation along the X-axis. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX(): Empty instance.", + cimg_instance); + return _cubic_atX(fx,y,z,c); + } + + Tfloat _cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2; + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atX_c(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(cubic_atX(fx,y,z,c)); + } + + T _cubic_atX_c(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(_cubic_atX(fx,y,z,c)); + } + + //! Return pixel value, using cubic interpolation and periodic boundary conditions for the X-coordinate. + Tfloat cubic_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX_p(): Empty instance.", + cimg_instance); + return _cubic_atX_p(fx,y,z,c); + } + + Tfloat _cubic_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()); + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atX_pc(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(cubic_atX_p(fx,y,z,c)); + } + + T _cubic_atX_pc(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(_cubic_atX_p(fx,y,z,c)); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X and Y-coordinates. + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2; + const float dx = fx - x, dy = fy - y; + const Tfloat + Ipp = (Tfloat)atXY(px,py,z,c,out_value), Icp = (Tfloat)atXY(x,py,z,c,out_value), + Inp = (Tfloat)atXY(nx,py,z,c,out_value), Iap = (Tfloat)atXY(ax,py,z,c,out_value), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)atXY(px,y,z,c,out_value), Icc = (Tfloat)atXY(x, y,z,c,out_value), + Inc = (Tfloat)atXY(nx,y,z,c,out_value), Iac = (Tfloat)atXY(ax,y,z,c,out_value), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)atXY(px,ny,z,c,out_value), Icn = (Tfloat)atXY(x,ny,z,c,out_value), + Inn = (Tfloat)atXY(nx,ny,z,c,out_value), Ian = (Tfloat)atXY(ax,ny,z,c,out_value), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)atXY(px,ay,z,c,out_value), Ica = (Tfloat)atXY(x,ay,z,c,out_value), + Ina = (Tfloat)atXY(nx,ay,z,c,out_value), Iaa = (Tfloat)atXY(ax,ay,z,c,out_value), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int,const T) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXY_c(const float fx, const float fy, const int z, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atXY(fx,fy,z,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved for both X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXY(float,float,int,int). + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY(): Empty instance.", + cimg_instance); + return _cubic_atXY(fx,fy,z,c); + } + + Tfloat _cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1), + nfy = cimg::type::is_nan(fy)?0:cimg::cut(fy,0,height() - 1); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = x - 1<0?0:x - 1, nx = dx<=0?x:x + 1, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy<=0?y:y + 1, ay = y + 2>=height()?height() - 1:y + 2; + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXY_c(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(cubic_atXY(fx,fy,z,c)); + } + + T _cubic_atXY_c(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(_cubic_atXY(fx,fy,z,c)); + } + + //! Return pixel value, using cubic interpolation and periodic boundary conditions for the X and Y-coordinates. + Tfloat cubic_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY_p(): Empty instance.", + cimg_instance); + return _cubic_atXY_p(fx,fy,z,c); + } + + Tfloat _cubic_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f), + nfy = cimg::type::is_nan(fy)?0:cimg::mod(fy,_height - 0.5f); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()), + py = cimg::mod(y - 1,height()), ny = cimg::mod(y + 1,height()), ay = cimg::mod(y + 2,height()); + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atXY_pc(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(cubic_atXY_p(fx,fy,z,c)); + } + + T _cubic_atXY_pc(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(_cubic_atXY_p(fx,fy,z,c)); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2, + z = (int)fz - (fz>=0?0:1), pz = z - 1, nz = z + 1, az = z + 2; + const float dx = fx - x, dy = fy - y, dz = fz - z; + const Tfloat + Ippp = (Tfloat)atXYZ(px,py,pz,c,out_value), Icpp = (Tfloat)atXYZ(x,py,pz,c,out_value), + Inpp = (Tfloat)atXYZ(nx,py,pz,c,out_value), Iapp = (Tfloat)atXYZ(ax,py,pz,c,out_value), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)atXYZ(px,y,pz,c,out_value), Iccp = (Tfloat)atXYZ(x, y,pz,c,out_value), + Incp = (Tfloat)atXYZ(nx,y,pz,c,out_value), Iacp = (Tfloat)atXYZ(ax,y,pz,c,out_value), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)atXYZ(px,ny,pz,c,out_value), Icnp = (Tfloat)atXYZ(x,ny,pz,c,out_value), + Innp = (Tfloat)atXYZ(nx,ny,pz,c,out_value), Ianp = (Tfloat)atXYZ(ax,ny,pz,c,out_value), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)atXYZ(px,ay,pz,c,out_value), Icap = (Tfloat)atXYZ(x,ay,pz,c,out_value), + Inap = (Tfloat)atXYZ(nx,ay,pz,c,out_value), Iaap = (Tfloat)atXYZ(ax,ay,pz,c,out_value), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)atXYZ(px,py,z,c,out_value), Icpc = (Tfloat)atXYZ(x,py,z,c,out_value), + Inpc = (Tfloat)atXYZ(nx,py,z,c,out_value), Iapc = (Tfloat)atXYZ(ax,py,z,c,out_value), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)atXYZ(px,y,z,c,out_value), Iccc = (Tfloat)atXYZ(x, y,z,c,out_value), + Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), Iacc = (Tfloat)atXYZ(ax,y,z,c,out_value), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)atXYZ(px,ny,z,c,out_value), Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), + Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), Ianc = (Tfloat)atXYZ(ax,ny,z,c,out_value), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)atXYZ(px,ay,z,c,out_value), Icac = (Tfloat)atXYZ(x,ay,z,c,out_value), + Inac = (Tfloat)atXYZ(nx,ay,z,c,out_value), Iaac = (Tfloat)atXYZ(ax,ay,z,c,out_value), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)atXYZ(px,py,nz,c,out_value), Icpn = (Tfloat)atXYZ(x,py,nz,c,out_value), + Inpn = (Tfloat)atXYZ(nx,py,nz,c,out_value), Iapn = (Tfloat)atXYZ(ax,py,nz,c,out_value), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)atXYZ(px,y,nz,c,out_value), Iccn = (Tfloat)atXYZ(x, y,nz,c,out_value), + Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), Iacn = (Tfloat)atXYZ(ax,y,nz,c,out_value), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)atXYZ(px,ny,nz,c,out_value), Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), + Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value), Iann = (Tfloat)atXYZ(ax,ny,nz,c,out_value), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)atXYZ(px,ay,nz,c,out_value), Ican = (Tfloat)atXYZ(x,ay,nz,c,out_value), + Inan = (Tfloat)atXYZ(nx,ay,nz,c,out_value), Iaan = (Tfloat)atXYZ(ax,ay,nz,c,out_value), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)atXYZ(px,py,az,c,out_value), Icpa = (Tfloat)atXYZ(x,py,az,c,out_value), + Inpa = (Tfloat)atXYZ(nx,py,az,c,out_value), Iapa = (Tfloat)atXYZ(ax,py,az,c,out_value), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)atXYZ(px,y,az,c,out_value), Icca = (Tfloat)atXYZ(x, y,az,c,out_value), + Inca = (Tfloat)atXYZ(nx,y,az,c,out_value), Iaca = (Tfloat)atXYZ(ax,y,az,c,out_value), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)atXYZ(px,ny,az,c,out_value), Icna = (Tfloat)atXYZ(x,ny,az,c,out_value), + Inna = (Tfloat)atXYZ(nx,ny,az,c,out_value), Iana = (Tfloat)atXYZ(ax,ny,az,c,out_value), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)atXYZ(px,ay,az,c,out_value), Icaa = (Tfloat)atXYZ(x,ay,az,c,out_value), + Inaa = (Tfloat)atXYZ(nx,ay,az,c,out_value), Iaaa = (Tfloat)atXYZ(ax,ay,az,c,out_value), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int,const T) const, except that the return value is clamped to stay + in the min/max range of the datatype \c T. + **/ + T cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atXYZ(fx,fy,fz,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ(): Empty instance.", + cimg_instance); + return _cubic_atXYZ(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1), + nfy = cimg::type::is_nan(fy)?0:cimg::cut(fy,0,height() - 1), + nfz = cimg::type::is_nan(fz)?0:cimg::cut(fz,0,depth() - 1); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy>0?y + 1:y, ay = y + 2>=height()?height() - 1:y + 2, + pz = z - 1<0?0:z - 1, nz = dz>0?z + 1:z, az = z + 2>=depth()?depth() - 1:z + 2; + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(cubic_atXYZ(fx,fy,fz,c)); + } + + T _cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(_cubic_atXYZ(fx,fy,fz,c)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ_p(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ_p(): Empty instance.", + cimg_instance); + return _cubic_atXYZ_p(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ_p(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f), + nfy = cimg::type::is_nan(fy)?0:cimg::mod(fy,_height - 0.5f), + nfz = cimg::type::is_nan(fz)?0:cimg::mod(fz,_depth - 0.5f); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()), + py = cimg::mod(y - 1,height()), ny = cimg::mod(y + 1,height()), ay = cimg::mod(y + 2,height()), + pz = cimg::mod(z - 1,depth()), nz = cimg::mod(z + 1,depth()), az = cimg::mod(z + 2,depth()); + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atXYZ_pc(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(cubic_atXYZ_p(fx,fy,fz,c)); + } + + T _cubic_atXYZ_pc(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(_cubic_atXYZ_p(fx,fy,fz,c)); + } + + //! Set pixel value, using linear interpolation for the X-coordinates. + /** + Set pixel value at specified coordinates (\c fx,\c y,\c z,\c c) in the image instance, in a way that + the value is spread amongst several neighbors if the pixel coordinates are float-valued. + \param value Pixel value to set. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param is_added Tells if the pixel value is added to (\c true), or simply replace (\c false) the current image + pixel(s). + \return A reference to the current image instance. + \note + - Calling this method with out-of-bounds coordinates does nothing. + **/ + CImg& set_linear_atX(const T& value, const float fx, const int y=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + if (y>=0 && y=0 && z=0 && c=0 && x=0 && nx& set_linear_atXY(const T& value, const float fx, const float fy=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + if (z>=0 && z=0 && c=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx& set_linear_atXYZ(const T& value, const float fx, const float fy=0, const float fz=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + if (c>=0 && c=0 && z=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx=0 && nz=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx image whose buffer data() is a \c char* string describing the list of all pixel values + of the image instance (written in base 10), separated by specified \c separator character. + \param separator A \c char character which specifies the separator between values in the returned C-string. + \param max_size Maximum size of the returned image (or \c 0 if no limits are set). + \param format For float/double-values, tell the printf format used to generate the text representation + of the numbers (or \c 0 for default representation). + \note + - The returned image is never empty. + - For an empty image instance, the returned string is "". + - If \c max_size is equal to \c 0, there are no limits on the size of the returned string. + - Otherwise, if the maximum number of string characters is exceeded, the value string is cut off + and terminated by character \c '\0'. In that case, the returned image size is max_size + 1. + **/ + CImg value_string(const char separator=',', const unsigned int max_size=0, + const char *const format=0) const { + if (is_empty() || max_size==1) return CImg(1,1,1,1,0); + CImgList items; + CImg s_item(256); *s_item = 0; + const T *ptrs = _data; + unsigned int string_size = 0; + const char *const _format = format?format:cimg::type::format(); + for (ulongT off = 0, siz = size(); off::format(*(ptrs++))); + CImg item(s_item._data,printed_size); + item[printed_size - 1] = separator; + item.move_to(items); + if (max_size) string_size+=printed_size; + } + CImg res; + (items>'x').move_to(res); + if (max_size && res._width>=max_size) res.crop(0,max_size - 1); + res.back() = 0; + return res; + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Test shared state of the pixel buffer. + /** + Return \c true if image instance has a shared memory buffer, and \c false otherwise. + \note + - A shared image do not own his pixel buffer data() and will not deallocate it on destruction. + - Most of the time, a \c CImg image instance will \e not be shared. + - A shared image can only be obtained by a limited set of constructors and methods (see list below). + **/ + bool is_shared() const { + return _is_shared; + } + + //! Test if image instance is empty. + /** + Return \c true, if image instance is empty, i.e. does \e not contain any pixel values, has dimensions + \c 0 x \c 0 x \c 0 x \c 0 and a pixel buffer pointer set to \c 0 (null pointer), and \c false otherwise. + **/ + bool is_empty() const { + return !(_data && _width && _height && _depth && _spectrum); + } + + //! Test if image instance contains a 'inf' value. + /** + Return \c true, if image instance contains a 'inf' value, and \c false otherwise. + **/ + bool is_inf() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_inf((float)*p)) return true; + return false; + } + + //! Test if image instance contains a NaN value. + /** + Return \c true, if image instance contains a NaN value, and \c false otherwise. + **/ + bool is_nan() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_nan((float)*p)) return true; + return false; + } + + //! Test if image width is equal to specified value. + bool is_sameX(const unsigned int size_x) const { + return _width==size_x; + } + + //! Test if image width is equal to specified value. + template + bool is_sameX(const CImg& img) const { + return is_sameX(img._width); + } + + //! Test if image width is equal to specified value. + bool is_sameX(const CImgDisplay& disp) const { + return is_sameX(disp._width); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const unsigned int size_y) const { + return _height==size_y; + } + + //! Test if image height is equal to specified value. + template + bool is_sameY(const CImg& img) const { + return is_sameY(img._height); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const CImgDisplay& disp) const { + return is_sameY(disp._height); + } + + //! Test if image depth is equal to specified value. + bool is_sameZ(const unsigned int size_z) const { + return _depth==size_z; + } + + //! Test if image depth is equal to specified value. + template + bool is_sameZ(const CImg& img) const { + return is_sameZ(img._depth); + } + + //! Test if image spectrum is equal to specified value. + bool is_sameC(const unsigned int size_c) const { + return _spectrum==size_c; + } + + //! Test if image spectrum is equal to specified value. + template + bool is_sameC(const CImg& img) const { + return is_sameC(img._spectrum); + } + + //! Test if image width and height are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameY(unsigned int) const are both verified. + **/ + bool is_sameXY(const unsigned int size_x, const unsigned int size_y) const { + return _width==size_x && _height==size_y; + } + + //! Test if image width and height are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameY(const CImg&) const are both verified. + **/ + template + bool is_sameXY(const CImg& img) const { + return is_sameXY(img._width,img._height); + } + + //! Test if image width and height are the same as that of an existing display window. + /** + Test if is_sameX(const CImgDisplay&) const and is_sameY(const CImgDisplay&) const are both verified. + **/ + bool is_sameXY(const CImgDisplay& disp) const { + return is_sameXY(disp._width,disp._height); + } + + //! Test if image width and depth are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXZ(const unsigned int size_x, const unsigned int size_z) const { + return _width==size_x && _depth==size_z; + } + + //! Test if image width and depth are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXZ(const CImg& img) const { + return is_sameXZ(img._width,img._depth); + } + + //! Test if image width and spectrum are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXC(const unsigned int size_x, const unsigned int size_c) const { + return _width==size_x && _spectrum==size_c; + } + + //! Test if image width and spectrum are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXC(const CImg& img) const { + return is_sameXC(img._width,img._spectrum); + } + + //! Test if image height and depth are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameYZ(const unsigned int size_y, const unsigned int size_z) const { + return _height==size_y && _depth==size_z; + } + + //! Test if image height and depth are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameYZ(const CImg& img) const { + return is_sameYZ(img._height,img._depth); + } + + //! Test if image height and spectrum are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYC(const unsigned int size_y, const unsigned int size_c) const { + return _height==size_y && _spectrum==size_c; + } + + //! Test if image height and spectrum are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYC(const CImg& img) const { + return is_sameYC(img._height,img._spectrum); + } + + //! Test if image depth and spectrum are equal to specified values. + /** + Test if is_sameZ(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameZC(const unsigned int size_z, const unsigned int size_c) const { + return _depth==size_z && _spectrum==size_c; + } + + //! Test if image depth and spectrum are the same as that of another image. + /** + Test if is_sameZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameZC(const CImg& img) const { + return is_sameZC(img._depth,img._spectrum); + } + + //! Test if image width, height and depth are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXYZ(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z) const { + return is_sameXY(size_x,size_y) && _depth==size_z; + } + + //! Test if image width, height and depth are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXYZ(const CImg& img) const { + return is_sameXYZ(img._width,img._height,img._depth); + } + + //! Test if image width, height and spectrum are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXYC(const unsigned int size_x, const unsigned int size_y, const unsigned int size_c) const { + return is_sameXY(size_x,size_y) && _spectrum==size_c; + } + + //! Test if image width, height and spectrum are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYC(const CImg& img) const { + return is_sameXYC(img._width,img._height,img._spectrum); + } + + //! Test if image width, depth and spectrum are equal to specified values. + /** + Test if is_sameXZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXZC(const unsigned int size_x, const unsigned int size_z, const unsigned int size_c) const { + return is_sameXZ(size_x,size_z) && _spectrum==size_c; + } + + //! Test if image width, depth and spectrum are the same as that of another image. + /** + Test if is_sameXZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXZC(const CImg& img) const { + return is_sameXZC(img._width,img._depth,img._spectrum); + } + + //! Test if image height, depth and spectrum are equal to specified values. + /** + Test if is_sameYZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYZC(const unsigned int size_y, const unsigned int size_z, const unsigned int size_c) const { + return is_sameYZ(size_y,size_z) && _spectrum==size_c; + } + + //! Test if image height, depth and spectrum are the same as that of another image. + /** + Test if is_sameYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYZC(const CImg& img) const { + return is_sameYZC(img._height,img._depth,img._spectrum); + } + + //! Test if image width, height, depth and spectrum are equal to specified values. + /** + Test if is_sameXYZ(unsigned int,unsigned int,unsigned int) const and is_sameC(unsigned int) const are both + verified. + **/ + bool is_sameXYZC(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c) const { + return is_sameXYZ(size_x,size_y,size_z) && _spectrum==size_c; + } + + //! Test if image width, height, depth and spectrum are the same as that of another image. + /** + Test if is_sameXYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYZC(const CImg& img) const { + return is_sameXYZC(img._width,img._height,img._depth,img._spectrum); + } + + //! Test if specified coordinates are inside image bounds. + /** + Return \c true if pixel located at (\c x,\c y,\c z,\c c) is inside bounds of the image instance, + and \c false otherwise. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Return \c true only if all these conditions are verified: + - The image instance is \e not empty. + - 0<=x<=\ref width() - 1. + - 0<=y<=\ref height() - 1. + - 0<=z<=\ref depth() - 1. + - 0<=c<=\ref spectrum() - 1. + **/ + bool containsXYZC(const int x, const int y=0, const int z=0, const int c=0) const { + return !is_empty() && x>=0 && x=0 && y=0 && z=0 && c img(100,100,1,3); // Construct a 100x100 RGB color image + const unsigned long offset = 1249; // Offset to the pixel (49,12,0,0) + unsigned int x,y,z,c; + if (img.contains(img[offset],x,y,z,c)) { // Convert offset to (x,y,z,c) coordinates + std::printf("Offset %u refers to pixel located at (%u,%u,%u,%u).\n", + offset,x,y,z,c); + } + \endcode + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z, t& c) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = (ulongT)(ppixel - _data); + const ulongT nc = off/whd; + off%=whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; c = (t)nc; + return true; + } + + //! Test if pixel value is inside image bounds and get its X,Y and Z-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X,Y and Z-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((ulongT)(ppixel - _data))%whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; + return true; + } + + //! Test if pixel value is inside image bounds and get its X and Y-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X and Y-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y) const { + const ulongT wh = (ulongT)_width*_height, siz = wh*_depth*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((unsigned int)(ppixel - _data))%wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; + return true; + } + + //! Test if pixel value is inside image bounds and get its X-coordinate. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X-coordinate is set. + **/ + template + bool contains(const T& pixel, t& x) const { + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + size()) return false; + x = (t)(((ulongT)(ppixel - _data))%_width); + return true; + } + + //! Test if pixel value is inside image bounds. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that no pixel coordinates are set. + **/ + bool contains(const T& pixel) const { + const T *const ppixel = &pixel; + return !is_empty() && ppixel>=_data && ppixel<_data + size(); + } + + //! Test if pixel buffers of instance and input images overlap. + /** + Return \c true, if pixel buffers attached to image instance and input image \c img overlap, + and \c false otherwise. + \param img Input image to compare with. + \note + - Buffer overlapping may happen when manipulating \e shared images. + - If two image buffers overlap, operating on one of the image will probably modify the other one. + - Most of the time, \c CImg instances are \e non-shared and do not overlap between each others. + \par Example + \code + const CImg + img1("reference.jpg"), // Load RGB-color image + img2 = img1.get_shared_channel(1); // Get shared version of the green channel + if (img1.is_overlapped(img2)) { // Test succeeds, 'img1' and 'img2' overlaps + std::printf("Buffers overlap!\n"); + } + \endcode + **/ + template + bool is_overlapped(const CImg& img) const { + const ulongT csiz = size(), isiz = img.size(); + return !((void*)(_data + csiz)<=(void*)img._data || (void*)_data>=(void*)(img._data + isiz)); + } + + //! Test if the set {\c *this,\c primitives,\c colors,\c opacities} defines a valid 3D object. + /** + Return \c true is the 3D object represented by the set {\c *this,\c primitives,\c colors,\c opacities} defines a + valid 3D object, and \c false otherwise. The vertex coordinates are defined by the instance image. + \param primitives List of primitives of the 3D object. + \param colors List of colors of the 3D object. + \param opacities List (or image) of opacities of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_checking to \c false to speed-up the 3D object checking. In this case, only the size of + each 3D object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + template + bool is_object3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true, + char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check consistency for the particular case of an empty 3D object. + if (is_empty()) { + if (primitives || colors || opacities) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines no vertices but %u primitives, " + "%u colors and %lu opacities", + _width,primitives._width,primitives._width, + colors._width,(unsigned long)opacities.size()); + return false; + } + return true; + } + + // Check consistency of vertices. + if (_height!=3 || _depth>1 || _spectrum>1) { // Check vertices dimensions + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) has invalid vertex dimensions (%u,%u,%u,%u)", + _width,primitives._width,_width,_height,_depth,_spectrum); + return false; + } + if (colors._width>primitives._width + 1) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines %u colors", + _width,primitives._width,colors._width); + return false; + } + if (opacities.size()>primitives._width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines %lu opacities", + _width,primitives._width,(unsigned long)opacities.size()); + return false; + } + if (!full_check) return true; + + // Check consistency of primitives. + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + const unsigned int psiz = (unsigned int)primitive.size(); + switch (psiz) { + case 1 : { // Point + const unsigned int i0 = (unsigned int)primitive(0); + if (i0>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex index %u in " + "point primitive [%u]", + _width,primitives._width,i0,l); + return false; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + if (i0>=_width || i1>=_width || i2>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + _width,primitives._width,i0,i1,i2,l); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + if (i0>=_width || i1>=_width || i2>=_width || i3>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + _width,primitives._width,i0,i1,i2,i3,l); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines an invalid primitive [%u] of size %u", + _width,primitives._width,l,(unsigned int)psiz); + return false; + } + } + + // Check consistency of colors. + cimglist_for(colors,c) { + const CImg& color = colors[c]; + if (!color) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines no color for primitive [%u]", + _width,primitives._width,c); + return false; + } + } + + // Check consistency of light texture. + if (colors._width>primitives._width) { + const CImg &light = colors.back(); + if (!light || light._depth>1) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines an invalid light texture (%u,%u,%u,%u)", + _width,primitives._width,light._width, + light._height,light._depth,light._spectrum); + return false; + } + } + + return true; + } + + //! Test if image instance represents a valid serialization of a 3D object. + /** + Return \c true if the image instance represents a valid serialization of a 3D object, and \c false otherwise. + \param full_check Tells if full checking of the instance must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_check to \c false to speed-up the 3D object checking. In this case, only the size of + each 3D object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + bool is_CImg3d(const bool full_check=true, char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check instance dimension and header. + if (_width!=1 || _height<8 || _depth!=1 || _spectrum!=1) { + if (error_message) cimg_sprintf(error_message, + "CImg3d has invalid dimensions (%u,%u,%u,%u)", + _width,_height,_depth,_spectrum); + return false; + } + const T *ptrs = _data, *const ptre = end(); + if (!_is_CImg3d(*(ptrs++),'C') || !_is_CImg3d(*(ptrs++),'I') || !_is_CImg3d(*(ptrs++),'m') || + !_is_CImg3d(*(ptrs++),'g') || !_is_CImg3d(*(ptrs++),'3') || !_is_CImg3d(*(ptrs++),'d')) { + if (error_message) cimg_sprintf(error_message, + "CImg3d header not found"); + return false; + } + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + + // Check consistency of number of vertices / primitives. + if (!full_check) { + const ulongT minimal_size = 8UL + 3*nb_points + 6*nb_primitives; + if (_data + minimal_size>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has only %lu values, while at least %lu values were expected", + nb_points,nb_primitives,(unsigned long)size(),(unsigned long)minimal_size); + return false; + } + } + + // Check consistency of vertex data. + if (!nb_points) { + if (nb_primitives) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no vertices but %u primitives", + nb_points,nb_primitives,nb_primitives); + return false; + } + if (ptrs!=ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) is an empty object but contains %u value%s " + "more than expected", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs),(ptre - ptrs)>1?"s":""); + return false; + } + return true; + } + if (ptrs + 3*nb_points>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines only %u vertices data", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs)/3); + return false; + } + ptrs+=3*nb_points; + + // Check consistency of primitive data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines %u vertices but no primitive", + nb_points,nb_primitives,nb_points); + return false; + } + + if (!full_check) return true; + + for (unsigned int p = 0; p=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex index %u in point primitive [%u]", + nb_points,nb_primitives,i0,p); + return false; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + ptrs+=3; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==6) ptrs+=4; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==9) ptrs+=6; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,p); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)), + i3 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==12) ptrs+=8; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points || i3>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,i3,p); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines an invalid primitive [%u] of size %u", + nb_points,nb_primitives,p,nb_inds); + return false; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete primitive data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,p,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of color data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no color/texture data", + nb_points,nb_primitives); + return false; + } + for (unsigned int c = 0; c=c) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared sprite/texture index %u " + "for primitive [%u]", + nb_points,nb_primitives,w,c); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete color/texture data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,c,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of opacity data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no opacity data", + nb_points,nb_primitives); + return false; + } + for (unsigned int o = 0; o=o) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared opacity index %u " + "for primitive [%u]", + nb_points,nb_primitives,w,o); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete opacity data for primitive [%u]", + nb_points,nb_primitives,o); + return false; + } + } + + // Check end of data. + if (ptrs1?"s":""); + return false; + } + return true; + } + + static bool _is_CImg3d(const T val, const char c) { + return val>=(T)c && val<(T)(c + 1); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + // Define the math formula parser/compiler and expression evaluator. + struct _cimg_math_parser { + CImg mem; + CImg memtype, memmerge; + CImgList _code, &code, code_begin, code_end, + _code_begin_t, &code_begin_t, _code_end_t, &code_end_t; + CImg opcode; + const CImg *p_code_end, *p_code; + const CImg *const p_break; + + CImg expr, pexpr; + const CImg& imgin; + const CImgList& listin; + CImg &imgout; + CImgList& listout; + + CImg _img_stats, &img_stats, constcache_vals; + CImgList _list_stats, &list_stats, _list_median, &list_median, _list_norm, &list_norm; + CImg mem_img_stats, constcache_inds; + + CImg level, variable_pos, reserved_label; + CImgList variable_def, macro_def, macro_body; + CImgList macro_body_is_string; + char *user_macro; + + unsigned int mempos, mem_img_median, mem_img_norm, mem_img_index, debug_indent, result_dim, break_type, + constcache_size; + bool is_parallelizable, is_end_code, is_fill, return_new_comp, need_input_copy; + double *result; + cimg_uint64 rng; + const char *const calling_function, *s_op, *ss_op; + typedef double (*mp_func)(_cimg_math_parser&); + +#define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant value? +#define _cimg_mp_is_scalar(arg) (memtype[arg]<2) // Is scalar value? +#define _cimg_mp_is_comp(arg) (!memtype[arg]) // Is computation value? +#define _cimg_mp_is_reserved(arg) (memtype[arg]==-1) // Is scalar and reserved (e.g. variable)? +#define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector? +#define _cimg_mp_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Size (0=scalar, N>0=vectorN) +#define _cimg_mp_calling_function s_calling_function()._data +#define _cimg_mp_op(s) s_op = s; ss_op = ss +#define _cimg_mp_check_type(arg,n_arg,mode,N) check_type(arg,n_arg,mode,N,ss,se,saved_char) +#define _cimg_mp_check_constant(arg,n_arg,mode) check_constant(arg,n_arg,mode,ss,se,saved_char) +#define _cimg_mp_check_constant_index(arg) check_constant_index(arg,ss,se,saved_char) +#define _cimg_mp_check_matrix_square(arg,n_arg) check_matrix_square(arg,n_arg,ss,se,saved_char) +#define _cimg_mp_check_list(is_out) check_list(is_out,ss,se,saved_char) +#define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp) +#define _cimg_mp_return(x) { *se = saved_char; s_op = previous_s_op; ss_op = previous_ss_op; return x; } +#define _cimg_mp_return_nan() _cimg_mp_return(_cimg_mp_slot_nan) +#define _cimg_mp_constant(val) _cimg_mp_return(constant((double)(val))) +#define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op)) +#define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1)) +#define _cimg_mp_scalar2(op,i1,i2) _cimg_mp_return(scalar2(op,i1,i2)) +#define _cimg_mp_scalar3(op,i1,i2,i3) _cimg_mp_return(scalar3(op,i1,i2,i3)) +#define _cimg_mp_scalar4(op,i1,i2,i3,i4) _cimg_mp_return(scalar4(op,i1,i2,i3,i4)) +#define _cimg_mp_scalar5(op,i1,i2,i3,i4,i5) _cimg_mp_return(scalar5(op,i1,i2,i3,i4,i5)) +#define _cimg_mp_scalar6(op,i1,i2,i3,i4,i5,i6) _cimg_mp_return(scalar6(op,i1,i2,i3,i4,i5,i6)) +#define _cimg_mp_scalar7(op,i1,i2,i3,i4,i5,i6,i7) _cimg_mp_return(scalar7(op,i1,i2,i3,i4,i5,i6,i7)) +#define _cimg_mp_vector1_v(op,i1) _cimg_mp_return(vector1_v(op,i1)) +#define _cimg_mp_vector2_sv(op,i1,i2) _cimg_mp_return(vector2_sv(op,i1,i2)) +#define _cimg_mp_vector2_vs(op,i1,i2) _cimg_mp_return(vector2_vs(op,i1,i2)) +#define _cimg_mp_vector2_vv(op,i1,i2) _cimg_mp_return(vector2_vv(op,i1,i2)) +#define _cimg_mp_vector3_vss(op,i1,i2,i3) _cimg_mp_return(vector3_vss(op,i1,i2,i3)) +#define _cimg_mp_strerr \ + *se = saved_char; \ + for (s0 = ss; s0>expr._data && *s0!=';'; --s0) {} \ + if (*s0==';') ++s0; \ + while (cimg::is_blank(*s0)) ++s0; \ + cimg::strellipsize(s0,64) + + // Constructors / Destructors. + ~_cimg_math_parser() { + cimg::srand(rng); + } + + _cimg_math_parser(const char *const expression, const char *const funcname=0, + const CImg& img_input=CImg::const_empty(), CImg *const img_output=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0, + const bool _is_fill=false): + code(_code),code_begin_t(_code_begin_t),code_end_t(_code_end_t), + p_break((CImg*)(cimg_ulong)-2), + imgin(img_input),listin(list_inputs?*list_inputs:CImgList::const_empty()), + imgout(img_output?*img_output:CImg::empty()),listout(list_outputs?*list_outputs:CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),list_norm(_list_norm),user_macro(0), + mem_img_median(~0U),mem_img_norm(~0U),mem_img_index(~0U),debug_indent(0),result_dim(0),break_type(0), + constcache_size(0),is_parallelizable(true),is_fill(_is_fill),need_input_copy(false), + rng((cimg::_rand(),cimg::rng())),calling_function(funcname?funcname:"cimg_math_parser") { + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + if (!expression || !*expression) + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Empty expression.", + pixel_type(),_cimg_mp_calling_function); + const char *_expression = expression; + while (*_expression && (cimg::is_blank(*_expression) || *_expression==';')) ++_expression; + CImg::string(_expression).move_to(expr); + char *ps = &expr.back() - 1; + while (ps>expr._data && (cimg::is_blank(*ps) || *ps==';')) --ps; + *(++ps) = 0; expr._width = (unsigned int)(ps - expr._data + 1); + + // Ease the retrieval of previous non-space characters afterwards. + pexpr.assign(expr._width); + char c, *pe = pexpr._data; + for (ps = expr._data, c = ' '; *ps; ++ps) { + if (!cimg::is_blank(*ps)) c = *ps; else *ps = ' '; + *(pe++) = c; + } + *pe = 0; + level = get_level(expr); + + // Init constant values. +#define _cimg_mp_interpolation (reserved_label[30]!=~0U?reserved_label[30]:0) +#define _cimg_mp_boundary (reserved_label[31]!=~0U?reserved_label[31]:0) +#define _cimg_mp_slot_t 17 +#define _cimg_mp_slot_nan 29 +#define _cimg_mp_slot_x 30 +#define _cimg_mp_slot_y 31 +#define _cimg_mp_slot_z 32 +#define _cimg_mp_slot_c 33 + + mem.assign(96); + for (unsigned int i = 0; i<=10; ++i) mem[i] = (double)i; // mem[0-10] = 0...10 + for (unsigned int i = 1; i<=5; ++i) mem[i + 10] = -(double)i; // mem[11-15] = -1...-5 + mem[16] = 0.5; + mem[_cimg_mp_slot_t] = 0; // thread_id + mem[18] = (double)imgin._width; // w + mem[19] = (double)imgin._height; // h + mem[20] = (double)imgin._depth; // d + mem[21] = (double)imgin._spectrum; // s + mem[22] = (double)imgin._is_shared; // r + mem[23] = (double)imgin._width*imgin._height; // wh + mem[24] = (double)imgin._width*imgin._height*imgin._depth; // whd + mem[25] = (double)imgin._width*imgin._height*imgin._depth*imgin._spectrum; // whds + mem[26] = (double)listin._width; // l + mem[27] = std::exp(1.); // e + mem[28] = cimg::PI; // pi + mem[_cimg_mp_slot_nan] = cimg::type::nan(); // nan + + // Set value property : + // { -1 = reserved (e.g. variable) | 0 = computation value | + // 1 = compile-time constant | N>1 = constant ptr to vector[N-1] }. + memtype.assign(mem._width,1,1,1,0); + for (unsigned int i = 0; i<_cimg_mp_slot_x; ++i) memtype[i] = 1; + memtype[_cimg_mp_slot_t] = memtype[_cimg_mp_slot_x] = memtype[_cimg_mp_slot_y] = + memtype[_cimg_mp_slot_z] = memtype[_cimg_mp_slot_c] = -1; + mempos = _cimg_mp_slot_c + 1; + variable_pos.assign(8); + + reserved_label.assign(128,1,1,1,~0U); + // reserved_label[0-31] are used to store the memory index of these variables: + // [0] = wh, [1] = whd, [2] = whds, [3] = pi, [4] = im, [5] = iM, [6] = ia, [7] = iv, + // [8] = is, [9] = ip, [10] = ic, [11] = in, [12] = xm, [13] = ym, [14] = zm, [15] = cm, [16] = xM, + // [17] = yM, [18] = zM, [19] = cM, [20] = i0...[29] = i9, [30] = interpolation, [31] = boundary + + // Compile expression into a sequence of opcodes. + s_op = ""; ss_op = expr._data; + const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0,false); + if (!_cimg_mp_is_constant(ind_result)) { + if (_cimg_mp_is_vector(ind_result)) + CImg(&mem[ind_result] + 1,_cimg_mp_size(ind_result),1,1,1,true). + fill(cimg::type::nan()); + else if (ind_result!=_cimg_mp_slot_t) mem[ind_result] = cimg::type::nan(); + } + + // Free resources used for compiling expression and prepare evaluation. + result_dim = _cimg_mp_size(ind_result); + if (mem._width>=256 && mem._width - mempos>=mem._width/2) mem.resize(mempos,1,1,1,-1); + result = mem._data + ind_result; + memtype.assign(); + constcache_vals.assign(); + constcache_inds.assign(); + level.assign(); + variable_pos.assign(); + reserved_label.assign(); + expr.assign(); + pexpr.assign(); + opcode.assign(); + opcode._is_shared = true; + + // Execute begin() bloc if any specified. + if (code_begin) { + mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_begin.end(); + for (p_code = code_begin; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + p_code_end = code.end(); + } + + _cimg_math_parser(): + code(_code),code_begin_t(_code_begin_t),code_end_t(_code_end_t), + p_code_end(0),p_break((CImg*)(cimg_ulong)-2), + imgin(CImg::const_empty()),listin(CImgList::const_empty()), + imgout(CImg::empty()),listout(CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),list_norm(_list_norm),debug_indent(0), + result_dim(0),break_type(0),constcache_size(0),is_parallelizable(true),is_fill(false), + need_input_copy(false),rng(0),calling_function(0) { + mem.assign(1 + _cimg_mp_slot_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()() + result = mem._data; + } + + _cimg_math_parser(const _cimg_math_parser& mp): + mem(mp.mem),code(mp.code),code_begin_t(mp.code_begin_t),code_end_t(mp.code_end_t), + p_code_end(mp.p_code_end),p_break(mp.p_break), + imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout), + img_stats(mp.img_stats),list_stats(mp.list_stats),list_median(mp.list_median),list_norm(mp.list_norm), + debug_indent(0),result_dim(mp.result_dim),break_type(0),constcache_size(0), + is_parallelizable(mp.is_parallelizable),is_fill(mp.is_fill), + need_input_copy(mp.need_input_copy),result(mem._data + (mp.result - mp.mem._data)), + rng((cimg::_rand(),cimg::rng())),calling_function(0) { + +#if cimg_use_openmp!=0 + mem[_cimg_mp_slot_t] = omp_get_thread_num(); + rng+=omp_get_thread_num(); +#endif + opcode.assign(); + opcode._is_shared = true; + } + + // Compilation procedure. + unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *const p_ref, + const bool is_critical) { + if (depth>256) { + cimg::strellipsize(expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Call stack overflow (infinite recursion?), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + (ss - 4)>expr._data?"...":"", + (ss - 4)>expr._data?ss - 4:expr._data, + se<&expr.back()?"...":""); + } + char c1, c2; + + // Simplify expression when possible. + do { + c2 = 0; + if (ssss && (cimg::is_blank(c1 = *(se - 1)) || c1==';')) --se; + } + while (*ss=='(' && *(se - 1)==')' && std::strchr(ss,')')==se - 1) { + ++ss; --se; c2 = 1; + } + } while (c2 && ss::%s: %s%s Missing %s, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + *s_op=='F'?"argument":"item", + (ss_op - 4)>expr._data?"...":"", + (ss_op - 4)>expr._data?ss_op - 4:expr._data, + ss_op + std::strlen(ss_op)<&expr.back()?"...":""); + } + + static const size_t siz_ref = 7*sizeof(unsigned int); + const char *const previous_s_op = s_op, *const previous_ss_op = ss_op; + const unsigned int depth1 = depth + 1; + unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6; + char + *const se1 = se - 1, *const se2 = se - 2, *const se3 = se - 3, + *const ss1 = ss + 1, *const ss2 = ss + 2, *const ss3 = ss + 3, *const ss4 = ss + 4, + *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8, + *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0; + double val = 0, val1, val2; + mp_func op; + return_new_comp = false; + + // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value + // linked to the returned memory slot (reference that cannot be determined at compile time). + // p_ref[0] can be { 0 = scalar (unlinked) | 1 = vector value | 2 = image value (offset) | + // 3 = image value (coordinates) | 4 = image value as a vector (offsets) | + // 5 = image value as a vector (coordinates) }. + // Depending on p_ref[0], the remaining p_ref[k] have the following meaning: + // When p_ref[0]==0, p_ref is actually unlinked. + // When p_ref[0]==1, p_ref = [ 1, vector_ind, offset ]. + // When p_ref[0]==2, p_ref = [ 2, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==3, p_ref = [ 3, image_ind (or ~0U), is_relative, x, y, z, c ]. + // When p_ref[0]==4, p_ref = [ 4, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==5, p_ref = [ 5, image_ind (or ~0U), is_relative, x, y, z ]. + if (p_ref) { *p_ref = 0; p_ref[1] = p_ref[2] = p_ref[3] = p_ref[4] = p_ref[5] = p_ref[6] = ~0U; } + + const char saved_char = *se; *se = 0; + const unsigned int clevel = level[ss - expr._data], clevel1 = clevel + 1; + bool is_sth, is_relative; + CImg ref; + CImg variable_name; + CImgList l_opcode; + + // Look for a single value or a pre-defined variable. + int nb = 0; + s = ss + (*ss=='+' || *ss=='-'?1:0); + if (*s=='i' || *s=='I' || *s=='n' || *s=='N') { // Particular cases : +/-NaN and +/-Inf + is_sth = *ss=='-'; + if (!cimg::strcasecmp(s,"inf")) { val = cimg::type::inf(); nb = 1; } + else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type::nan(); nb = 1; } + if (nb==1 && is_sth) val = -val; + } else if (*s=='0' && (s[1]=='x' || s[1]=='X')) { // Hexadecimal number + is_sth = *ss=='-'; + if (cimg_sscanf(s + 2,"%x%c",&arg1,&sep)==1) { + nb = 1; + val = (double)arg1; + if (is_sth) val = -val; + } + } + if (!nb) nb = cimg_sscanf(ss,"%lf%c%c",&val,&(sep=0),&(end=0)); + if (nb==1) _cimg_mp_constant(val); + if (nb==2 && sep=='%') _cimg_mp_constant(val/100); + + if (ss1==se) switch (*ss) { // One-char reserved variable + case 'c' : _cimg_mp_return(reserved_label[(int)'c']!=~0U?reserved_label[(int)'c']:_cimg_mp_slot_c); + case 'd' : _cimg_mp_return(reserved_label[(int)'d']!=~0U?reserved_label[(int)'d']:20); + case 'e' : _cimg_mp_return(reserved_label[(int)'e']!=~0U?reserved_label[(int)'e']:27); + case 'h' : _cimg_mp_return(reserved_label[(int)'h']!=~0U?reserved_label[(int)'h']:19); + case 'k' : + if (reserved_label[(int)'k']!=~0U) _cimg_mp_return(reserved_label[(int)'k']); + pos = get_mem_img_index(); + if (pos!=~0U) _cimg_mp_return(pos); + _cimg_mp_return_nan(); + case 'l' : _cimg_mp_return(reserved_label[(int)'l']!=~0U?reserved_label[(int)'l']:26); + case 'r' : _cimg_mp_return(reserved_label[(int)'r']!=~0U?reserved_label[(int)'r']:22); + case 's' : _cimg_mp_return(reserved_label[(int)'s']!=~0U?reserved_label[(int)'s']:21); + case 't' : _cimg_mp_return(reserved_label[(int)'t']!=~0U?reserved_label[(int)'t']:_cimg_mp_slot_t); + case 'w' : _cimg_mp_return(reserved_label[(int)'w']!=~0U?reserved_label[(int)'w']:18); + case 'x' : _cimg_mp_return(reserved_label[(int)'x']!=~0U?reserved_label[(int)'x']:_cimg_mp_slot_x); + case 'y' : _cimg_mp_return(reserved_label[(int)'y']!=~0U?reserved_label[(int)'y']:_cimg_mp_slot_y); + case 'z' : _cimg_mp_return(reserved_label[(int)'z']!=~0U?reserved_label[(int)'z']:_cimg_mp_slot_z); + case 'u' : + if (reserved_label[(int)'u']!=~0U) _cimg_mp_return(reserved_label[(int)'u']); + _cimg_mp_scalar2(mp_u,0,1); + case 'g' : + if (reserved_label[(int)'g']!=~0U) _cimg_mp_return(reserved_label[(int)'g']); + _cimg_mp_scalar0(mp_g); + case 'i' : + if (reserved_label[(int)'i']!=~0U) _cimg_mp_return(reserved_label[(int)'i']); + _cimg_mp_scalar0(mp_i); + case 'I' : + _cimg_mp_op("Variable 'I'"); + if (reserved_label[(int)'I']!=~0U) _cimg_mp_return(reserved_label[(int)'I']); + if (!imgin._spectrum) _cimg_mp_return(0); + need_input_copy = true; + pos = vector(imgin._spectrum); + CImg::vector((ulongT)mp_Joff,pos,0,0,imgin._spectrum).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + case 'R' : + if (reserved_label[(int)'R']!=~0U) _cimg_mp_return(reserved_label[(int)'R']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0,0,0); + case 'G' : + if (reserved_label[(int)'G']!=~0U) _cimg_mp_return(reserved_label[(int)'G']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1,0,0); + case 'B' : + if (reserved_label[(int)'B']!=~0U) _cimg_mp_return(reserved_label[(int)'B']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2,0,0); + case 'A' : + if (reserved_label[(int)'A']!=~0U) _cimg_mp_return(reserved_label[(int)'A']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3,0,0); + } + else if (ss2==se) { // Two-chars reserved variable + arg1 = arg2 = ~0U; + if (*ss=='w' && *ss1=='h') // wh + _cimg_mp_return(reserved_label[0]!=~0U?reserved_label[0]:23); + if (*ss=='p' && *ss1=='i') // pi + _cimg_mp_return(reserved_label[3]!=~0U?reserved_label[3]:28); + if (*ss=='i') { + if (*ss1>='0' && *ss1<='9') { // i0...i9 + pos = 20 + *ss1 - '0'; + if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,pos - 20,0,0); + } + switch (*ss1) { + case 'm' : arg1 = 4; arg2 = 0; break; // im + case 'M' : arg1 = 5; arg2 = 1; break; // iM + case 'a' : arg1 = 6; arg2 = 2; break; // ia + case 'v' : arg1 = 7; arg2 = 3; break; // iv + case 's' : arg1 = 8; arg2 = 12; break; // is + case 'p' : arg1 = 9; arg2 = 13; break; // ip + case 'c' : // ic + if (reserved_label[10]!=~0U) _cimg_mp_return(reserved_label[10]); + if (mem_img_median==~0U) mem_img_median = imgin?constant(imgin.median()):0; + _cimg_mp_return(mem_img_median); + break; + case 'n' : // in + if (reserved_label[11]!=~0U) _cimg_mp_return(reserved_label[11]); + if (mem_img_norm==~0U) mem_img_norm = imgin?constant(imgin.magnitude()):0; + _cimg_mp_return(mem_img_norm); + } + } + else if (*ss1=='m') switch (*ss) { + case 'x' : arg1 = 12; arg2 = 4; break; // xm + case 'y' : arg1 = 13; arg2 = 5; break; // ym + case 'z' : arg1 = 14; arg2 = 6; break; // zm + case 'c' : arg1 = 15; arg2 = 7; break; // cm + } + else if (*ss1=='M') switch (*ss) { + case 'x' : arg1 = 16; arg2 = 8; break; // xM + case 'y' : arg1 = 17; arg2 = 9; break; // yM + case 'z' : arg1 = 18; arg2 = 10; break; // zM + case 'c' : arg1 = 19; arg2 = 11; break; // cM + } + if (arg1!=~0U) { + if (reserved_label[arg1]!=~0U) _cimg_mp_return(reserved_label[arg1]); + if (!img_stats) { + img_stats.assign(1,14,1,1,0).fill(imgin.get_stats(),false); + mem_img_stats.assign(1,14,1,1,~0U); + } + if (mem_img_stats[arg2]==~0U) mem_img_stats[arg2] = constant(img_stats[arg2]); + _cimg_mp_return(mem_img_stats[arg2]); + } + } else if (ss3==se) { // Three-chars reserved variable + if (*ss=='w' && *ss1=='h' && *ss2=='d') // whd + _cimg_mp_return(reserved_label[1]!=~0U?reserved_label[1]:24); + } else if (ss4==se) { // Four-chars reserved variable + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='s') // whds + _cimg_mp_return(reserved_label[2]!=~0U?reserved_label[2]:25); + } + + pos = ~0U; + is_sth = false; + for (s0 = ss, s = ss1; s='i'?1:3,0); + if (_cimg_mp_is_vector(arg2)) { + if (p1!=~0U) { + _cimg_mp_check_constant_index(p1); + p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + p2 = listin[p3]._spectrum; + } else p2 = imgin._spectrum; + if (!p2) _cimg_mp_return(0); + _cimg_mp_check_type(arg2,2,2,p2); + } else p2 = 0; + + if (p_ref) { + *p_ref = _cimg_mp_is_vector(arg2)?4:2; + p_ref[1] = p1; + p_ref[2] = (unsigned int)is_relative; + p_ref[3] = arg1; + if (_cimg_mp_is_vector(arg2)) + set_reserved_vector(arg2); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; + if (_cimg_mp_is_comp(arg1)) memtype[arg1] = -1; + } + + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg1,_cimg_mp_size(arg2)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg1,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value + if (!is_critical) is_parallelizable = false; + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0='i'?1:3,0); + if (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + } else if (s1='i') + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg5,p1,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg5,p1,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg5,p1,arg1,arg2,arg3,_cimg_mp_size(arg5)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg5); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg5,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg5,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg5,arg1,arg2,arg3,_cimg_mp_size(arg5)).move_to(code); + } + _cimg_mp_return(arg5); + } + } + + // Assign vector value (direct). + if (l_variable_name>3 && *ve1==']' && *ss!='[') { + s0 = ve1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss && is_varname(ss,s0 - ss)) { + variable_name[s0 - ss] = 0; // Remove brackets in variable name + get_variable_pos(variable_name,arg1,arg2); + arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U; // Vector slot + if (arg1==~0U || _cimg_mp_is_scalar(arg1)) + compile(ss,s0,depth1,0,is_critical); // Variable does not exist or is not a vector -> error + + arg2 = compile(++s0,ve1,depth1,0,is_critical); // Index + arg3 = compile(s + 1,se,depth1,0,is_critical); // Value to assign + _cimg_mp_check_type(arg3,2,1,0); + + if (_cimg_mp_is_constant(arg2)) { // Constant index -> return corresponding variable slot directly + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_size(arg1)) { + arg1+=nb + 1; + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + _cimg_mp_return(arg1); + } + compile(ss,s,depth1,0,is_critical); // Out-of-bounds reference -> error + } + + // Case of non-constant index -> return assigned value + linked reference + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -1; // Prevent from being used in further optimization + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; + } + CImg::vector((ulongT)mp_vector_set_off,arg3,arg1,(ulongT)_cimg_mp_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg3); + } + } + + // Assign user-defined macro. + if (l_variable_name>2 && *ve1==')' && *ss!='(') { + s0 = ve1; while (s0>ss && *s0!='(') --s0; + if (is_varname(ss,s0 - ss) && std::strncmp(variable_name,"debug(",6) && + std::strncmp(variable_name,"print(",6)) { // Valid macro name + s0 = variable_name._data + (s0 - ss); + *s0 = 0; + s1 = variable_name._data + l_variable_name - 1; // Pointer to closing parenthesis + CImg(variable_name._data,(unsigned int)(s0 - variable_name._data + 1)).move_to(macro_def,0); + ++s; while (*s && cimg::is_blank(*s)) ++s; + CImg(s,(unsigned int)(se - s + 1)).move_to(macro_body,0); + + p1 = 1; // Index of current parsed argument + for (s = s0 + 1; s<=s1; ++p1, s = ns + 1) { // Parse function arguments + if (p1>24) { + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Too much specified arguments (>24) in macro " + "definition '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && p1==1) break; // Function has no arguments + + s2 = s; // Start of the argument name + is_sth = true; // is_valid_argument_name? + if (*s>='0' && *s<='9') is_sth = false; + else for (ns = s; ns::%s: %s: %s name specified for argument %u when defining " + "macro '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + is_sth?"Empty":"Invalid",p1, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (ns==s1 || *ns==',') { // New argument found + *s3 = 0; + p2 = (unsigned int)(s3 - s2); // Argument length + for (ps = std::strstr(macro_body[0],s2); ps; ps = std::strstr(ps,s2)) { // Replace by arg number + if (!((ps>macro_body[0]._data && is_varchar(*(ps - 1))) || + (ps + p2macro_body[0]._data && *(ps - 1)=='#') { // Remove pre-number sign + *(ps - 1) = (char)p1; + if (ps + p26 && !std::strncmp(variable_name,"const ",6); + s0 = variable_name._data; + if (is_const) { + s0+=6; while (cimg::is_blank(*s0)) ++s0; + variable_name.resize(variable_name.end() - s0,1,1,1,0,0,1); + } + if (is_varname(variable_name)) { // Valid variable name + + // Assign variable (direct). + get_variable_pos(variable_name,arg1,arg2); + arg3 = compile(s + 1,se,depth1,0,is_critical); + is_sth = return_new_comp; // is arg3 a new blank object? + if (is_const) _cimg_mp_check_constant(arg3,2,0); + arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U; + + if (arg1==~0U) { // Create new variable + if (_cimg_mp_is_vector(arg3)) { // Vector variable + arg1 = is_sth || is_comp_vector(arg3)?arg3:vector_copy(arg3); + set_reserved_vector(arg1); // Prevent from being used in further optimization + } else { // Scalar variable + if (is_const) arg1 = arg3; + else { + arg1 = is_sth || _cimg_mp_is_comp(arg3)?arg3:scalar1(mp_copy,arg3); + memtype[arg1] = -1; + } + } + + if (arg2!=~0U) reserved_label[arg2] = arg1; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg1; + variable_name.move_to(variable_def); + } + + } else { // Variable already exists -> assign a new value + if (is_const || _cimg_mp_is_constant(arg1)) { + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid assignment of %sconst variable '%s'%s, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"already-defined ":"non-", + variable_name._data, + !_cimg_mp_is_constant(arg1) && is_const?" as a new const variable":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(arg3,2,_cimg_mp_is_vector(arg1)?3:1,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1)) { // Vector + if (_cimg_mp_is_vector(arg3)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg3,(ulongT)_cimg_mp_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_size(arg1),arg3). + move_to(code); + } else // Scalar + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + } + return_new_comp = false; + _cimg_mp_return(arg1); + } + + // Assign lvalue (variable name was not valid for a direct assignment). + arg1 = ~0U; + is_sth = (bool)std::strchr(variable_name,'?'); // Contains_ternary_operator? + if (is_sth) break; // Do nothing and make ternary operator prioritary over assignment + + if (l_variable_name>2 && (std::strchr(variable_name,'(') || std::strchr(variable_name,'['))) { + ref.assign(7); + arg1 = compile(ss,s,depth1,ref,is_critical); // Lvalue slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Value to assign + + if (*ref==1) { // Vector value (scalar): V[k] = scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)mp_vector_set_off,arg2,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(arg2); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg3).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg2,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg2,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg3).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg3,_cimg_mp_size(arg2)).move_to(code); + } + + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg3,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg2,p1,arg3,arg4,arg5).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg2,p1,arg3,arg4,arg5,_cimg_mp_size(arg2)).move_to(code); + } + + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg2,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg2,arg3,arg4,arg5,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg2)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s = scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)mp_copy,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + } + + // No assignment expressions match -> error + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1!=~0U && _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Apply unary/binary/ternary operators. The operator precedences should be the same as in C++. + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps && + level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=) + _cimg_mp_op(*ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='"); + + ref.assign(7); + arg1 = compile(ss,ns,depth1,ref,is_critical); // Vector slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Right operand + _cimg_mp_check_type(arg1,1,2,2); + _cimg_mp_check_type(arg2,2,3,2); + if (_cimg_mp_is_vector(arg2)) { // Complex **= complex + if (*ps=='*') + CImg::vector((ulongT)mp_complex_mul,arg1,arg1,arg2).move_to(code); + else if (*ps=='/') + CImg::vector((ulongT)mp_complex_div_vv,arg1,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code); + } else { // Complex **= scalar + if (*ps=='*') { + if (arg2==1) _cimg_mp_return(arg1); + self_vector_s(arg1,mp_self_mul,arg2); + } else if (*ps=='/') { + if (arg2==1) _cimg_mp_return(arg1); + self_vector_s(arg1,mp_self_div,arg2); + } else { + if (arg2==1) _cimg_mp_return(arg1); + CImg::vector((ulongT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code); + } + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + + } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + + _cimg_mp_return(arg1); + } + + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='+' || *ps=='-' || *ps=='*' || *ps=='/' || *ps=='%' || + *ps=='&' || *ps=='^' || *ps=='|' || + (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) && + level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=) + switch (*ps) { + case '+' : op = mp_self_add; _cimg_mp_op("Operator '+='"); break; + case '-' : op = mp_self_sub; _cimg_mp_op("Operator '-='"); break; + case '*' : op = mp_self_mul; _cimg_mp_op("Operator '*='"); break; + case '/' : op = mp_self_div; _cimg_mp_op("Operator '/='"); break; + case '%' : op = mp_self_modulo; _cimg_mp_op("Operator '%='"); break; + case '<' : op = mp_self_bitwise_left_shift; _cimg_mp_op("Operator '<<='"); break; + case '>' : op = mp_self_bitwise_right_shift; _cimg_mp_op("Operator '>>='"); break; + case '&' : op = mp_self_bitwise_and; _cimg_mp_op("Operator '&='"); break; + case '|' : op = mp_self_bitwise_or; _cimg_mp_op("Operator '|='"); break; + default : op = mp_self_pow; _cimg_mp_op("Operator '^='"); break; + } + s1 = *ps=='>' || *ps=='<'?ns:ps; + + ref.assign(7); + arg1 = compile(ss,s1,depth1,ref,is_critical); // Variable slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Value to apply + + // Check for particular case to be simplified. + if ((op==mp_self_add || op==mp_self_sub) && !arg2) _cimg_mp_return(arg1); + if ((op==mp_self_mul || op==mp_self_div) && arg2==1) _cimg_mp_return(arg1); + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_reserved(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k] += scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(arg1); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) += value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg2)) self_vector_v(arg1,op,arg2); // Vector += vector + else self_vector_s(arg1,op,arg2); // Vector += scalar + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s += scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + + variable_name.assign(ss,(unsigned int)(s - ss)).back() = 0; + cimg::strpare(variable_name,false,true); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + for (s = ss1; s::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||') + _cimg_mp_op("Operator '||'"); + arg1 = compile(ss,s,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,1,0); + if (arg1>0 && arg1<=16) _cimg_mp_return(1); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] || mem[arg2]); + if (!arg1) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_or,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&') + _cimg_mp_op("Operator '&&'"); + arg1 = compile(ss,s,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,1,0); + if (!arg1) _cimg_mp_return(0); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] && mem[arg2]); + if (arg1>0 && arg1<=16) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_and,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|') + _cimg_mp_op("Operator '|'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1] | (longT)mem[arg2]); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_scalar2(mp_bitwise_or,arg1,arg2); + } + + for (s = se2; s>ss; --s) + if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&') + _cimg_mp_op("Operator '&'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1] & (longT)mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_bitwise_and,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=') + _cimg_mp_op("Operator '!='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + if (arg1==arg2) _cimg_mp_return(0); + p1 = _cimg_mp_size(arg1); + p2 = _cimg_mp_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(1); + pos = scalar(); + CImg::vector((ulongT)mp_vector_neq,pos,arg1,p1,arg2,p2,11,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]!=mem[arg2]); + _cimg_mp_scalar2(mp_neq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==') + _cimg_mp_op("Operator '=='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + if (arg1==arg2) _cimg_mp_return(1); + p1 = _cimg_mp_size(arg1); + p2 = _cimg_mp_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_vector_eq,pos,arg1,p1,arg2,p2,11,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]==mem[arg2]); + _cimg_mp_scalar2(mp_eq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=') + _cimg_mp_op("Operator '<='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]<=mem[arg2]); + if (arg1==arg2) _cimg_mp_return(1); + _cimg_mp_scalar2(mp_lte,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=') + _cimg_mp_op("Operator '>='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>=mem[arg2]); + if (arg1==arg2) _cimg_mp_return(1); + _cimg_mp_scalar2(mp_gte,arg1,arg2); + } + + for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) + if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<') + _cimg_mp_op("Operator '<'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]ss; --s, --ns, --ps) + if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greater than ('>') + _cimg_mp_op("Operator '>'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>mem[arg2]); + if (arg1==arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_gt,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<') + _cimg_mp_op("Operator '<<'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_left_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]<<(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_left_shift,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>') + _cimg_mp_op("Operator '>>'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_right_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]>>(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_right_shift,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='+' && (*ns!='+' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Addition ('+') + _cimg_mp_op("Operator '+'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] + mem[arg2]); + if (code) { // Try to spot linear case 'a*b + c' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_linear_add,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_increment,arg1); + if (arg1==1) _cimg_mp_scalar1(mp_increment,arg2); + _cimg_mp_scalar2(mp_add,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='-' && (*ns!='-' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Subtraction ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_vector1_v(mp_minus,arg2); + _cimg_mp_vector2_sv(mp_sub,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] - mem[arg2]); + if (!arg1) _cimg_mp_scalar1(mp_minus,arg2); + if (code) { // Try to spot linear cases 'a*b - c' and 'c - a*b' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)(arg3==arg1?mp_linear_sub_left:mp_linear_sub_right), + arg3,arg4,arg5,arg3==arg1?arg2:arg1).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_decrement,arg1); + _cimg_mp_scalar2(mp_sub,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex multiplication ('**') + _cimg_mp_op("Operator '**'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_mul,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//') + _cimg_mp_op("Operator '//'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_vv,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_sv,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*') + _cimg_mp_op("Operator '*'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + p2 = _cimg_mp_size(arg2); + if (p2>0 && (ulongT)_cimg_mp_size(arg1)==(ulongT)p2*p2) { // Particular case of matrix multiplication + pos = vector(p2); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,p2,p2,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + + if (code) { // Try to spot double multiplication 'a*b*c' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_mul2,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/') + _cimg_mp_op("Operator '/'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2, ns = se1; s>ss; --s, --ns) + if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%') + _cimg_mp_op("Operator '%'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(cimg::mod(mem[arg1],mem[arg2])); + _cimg_mp_scalar2(mp_modulo,arg1,arg2); + } + + if (se1>ss) { + if (*ss=='+' && (*ss1!='+' || (ss2='0' && *ss2<='9'))) { // Unary plus ('+') + _cimg_mp_op("Operator '+'"); + _cimg_mp_return(compile(ss1,se,depth1,0,is_critical)); + } + + if (*ss=='-' && (*ss1!='-' || (ss2='0' && *ss2<='9'))) { // Unary minus ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]); + _cimg_mp_scalar1(mp_minus,arg1); + } + + if (*ss=='!') { // Logical not ('!') + _cimg_mp_op("Operator '!'"); + if (*ss1=='!') { // '!!expr' optimized as 'bool(expr)' + arg1 = compile(ss2,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((bool)mem[arg1]); + _cimg_mp_scalar1(mp_bool,arg1); + } + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]); + _cimg_mp_scalar1(mp_logical_not,arg1); + } + + if (*ss=='~') { // Bitwise not ('~') + _cimg_mp_op("Operator '~'"); + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned int)mem[arg1]); + _cimg_mp_scalar1(mp_bitwise_not,arg1); + } + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^') + _cimg_mp_op("Operator '^^'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + pos = vector(2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + CImg::vector((ulongT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code); + else if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)mp_complex_pow_vs,pos,arg1,arg2).move_to(code); + else if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + CImg::vector((ulongT)mp_complex_pow_sv,pos,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_ss,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^') + _cimg_mp_op("Operator '^'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(std::pow(mem[arg1],mem[arg2])); + switch (arg2) { + case 0 : _cimg_mp_return(1); + case 2 : _cimg_mp_scalar1(mp_sqr,arg1); + case 3 : _cimg_mp_scalar1(mp_pow3,arg1); + case 4 : _cimg_mp_scalar1(mp_pow4,arg1); + default : + if (_cimg_mp_is_constant(arg2)) { + if (mem[arg2]==0.5) { _cimg_mp_scalar1(mp_sqrt,arg1); } + else if (mem[arg2]==0.25) { _cimg_mp_scalar1(mp_pow0_25,arg1); } + } + _cimg_mp_scalar2(mp_pow,arg1,arg2); + } + } + + // Percentage computation. + if (*se1=='%') { + arg1 = compile(ss,se1,depth1,0,is_critical); + arg2 = _cimg_mp_is_constant(arg1)?0:constant(100); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(mem[arg1]/100); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + is_sth = ss1ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment + if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) { + _cimg_mp_op("Operator '++'"); + op = mp_self_increment; + } else { + _cimg_mp_op("Operator '--'"); + op = mp_self_decrement; + } + ref.assign(7); + arg1 = is_sth?compile(ss2,se,depth1,ref,is_critical): + compile(ss,se2,depth1,ref,is_critical); // Variable slot + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_reserved(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (is_sth) pos = arg1; // Determine return index, depending on pre/post action + else { + if (_cimg_mp_is_vector(arg1)) pos = vector_copy(arg1); + else pos = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k]++ + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,1).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(pos); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off]++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++ + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s++ + CImg::vector((ulongT)op,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (is_sth) variable_name.assign(ss2,(unsigned int)(se - ss1)); + else variable_name.assign(ss,(unsigned int)(se1 - ss)); + variable_name.back() = 0; + cimg::strpare(variable_name,false,true); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Array-like access to vectors and image values 'i/j/I/J[_#ind,offset,_boundary]' and 'vector[offset]'. + if (*se1==']') { + _cimg_mp_op("Value accessor '[]'"); + + // Find opening bracket for the offset. + s0 = se1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { s1 = s0; do { --s1; } while (cimg::is_blank(*s1)); cimg::swap(*s0,*++s1); } + is_sth=s0>ss && *(s0-1)==']'; // Particular case s.a. '..[..][..]' ? + is_relative = *ss=='j' || *ss=='J'; + + if (!is_sth && (*ss=='I' || *ss=='J') && *ss1=='[' && + (reserved_label[(int)*ss]==~0U || + !_cimg_mp_is_vector(reserved_label[(int)*ss]))) { // Image value as a vector + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0::vector((ulongT)(is_relative?mp_list_Joff:mp_list_Ioff), + pos,p1,arg1,arg2==~0U?_cimg_mp_boundary:arg2,p2).move_to(code); + } else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Joff:mp_Ioff), + pos,arg1,arg2==~0U?_cimg_mp_boundary:arg2,p2).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!is_sth && (*ss=='i' || *ss=='j') && *ss1=='[' && + (reserved_label[(int)*ss]==~0U || + !_cimg_mp_is_vector(reserved_label[(int)*ss]))) { // Image value as a scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { // Vector element + arg1 = compile(ss,s0,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Array brackets used on non-vector variable '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + s1 = s0 + 1; while (s1 sub-vector extraction + p1 = _cimg_mp_size(arg1); + arg2 = compile(++s0,s1,depth1,0,is_critical); // Starting index + s0 = ++s1; while (s0::vector((ulongT)mp_vector_crop,pos,arg1,p1,arg2,arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // One argument -> vector value reference + arg2 = compile(++s0,se1,depth1,0,is_critical); + if (_cimg_mp_is_constant(arg2)) { // Constant index + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_size(arg1)) _cimg_mp_return(arg1 + 1 + nb); + variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Out-of-bounds reference '%s[%d]' " + "(vector '%s' has dimension %u), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data,nb, + variable_name._data,_cimg_mp_size(arg1), + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; // Prevent from being used in further optimization + } + pos = scalar3(mp_vector_off,arg1,_cimg_mp_size(arg1),arg2); + memtype[pos] = -1; // Prevent from being used in further optimization + _cimg_mp_return(pos); + } + } + + // Look for a function call, an access to image value, or a parenthesis. + if (*se1==')') { + if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref,is_critical)); // Simple parentheses + _cimg_mp_op("Value accessor '()'"); + is_relative = *ss=='j' || *ss=='J'; + s0 = s1 = std::strchr(ss,'('); if (s0) { do { --s1; } while (cimg::is_blank(*s1)); cimg::swap(*s0,*++s1); } + + // I/J(_#ind,_x,_y,_z,_interpolation,_boundary_conditions) + if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + if (s1::vector((ulongT)(is_relative?mp_list_Jxyz:mp_list_Ixyz), + pos,p1,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5,p2).move_to(code); + else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Jxyz:mp_Ixyz), + pos,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5,p2).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + // i/j(_#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions) + if ((*ss=='i' || *ss=='j') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + if (s1::vector((ulongT)(*ss3=='0'?mp_arg0:mp_arg),0,0,p2,arg1,arg2).move_to(l_opcode); + for (s = ++s2; s::vector(arg3).move_to(l_opcode); + ++p3; + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (_cimg_mp_is_constant(arg1)) { + p3-=1; // Number of args + if (*ss3=='0') arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1] + 1); + else arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1]); + if (arg1::vector((ulongT)mp_break,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"breakpoint(",11)) { // Break point (for abort test) + _cimg_mp_op("Function 'breakpoint()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_breakpoint,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"bool(",5)) { // Boolean cast + _cimg_mp_op("Function 'bool()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((bool)mem[arg1]); + _cimg_mp_scalar1(mp_bool,arg1); + } + + if (!std::strncmp(ss,"begin(",6)) { // Begin + _cimg_mp_op("Function 'begin()'"); + code.swap(code_begin); + arg1 = compile(ss6,se1,depth1,p_ref,true); + code.swap(code_begin); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"begin_t(",8)) { // Begin thread + _cimg_mp_op("Function 'begin_t()'"); + code.swap(code_begin_t); + arg1 = compile(ss8,se1,depth1,p_ref,true); + code.swap(code_begin_t); + _cimg_mp_return(arg1); + } + break; + + case 'c' : + if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value + _cimg_mp_op("Function 'cabs()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_scalar2(mp_complex_abs,arg1,0); + _cimg_mp_scalar2(mp_complex_abs,arg1 + 1,arg1 + 2); + } + + if (!std::strncmp(ss,"carg(",5)) { // Complex argument + _cimg_mp_op("Function 'carg()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_scalar2(mp_atan2,0,arg1); + _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1); + } + + if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root + _cimg_mp_op("Function 'cbrt()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::cbrt(mem[arg1])); + _cimg_mp_scalar1(mp_cbrt,arg1); + } + + if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate + _cimg_mp_op("Function 'cconj()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_conj,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_conj,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ceil(",5)) { // Ceil + _cimg_mp_op("Function 'ceil()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_ceil,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::ceil(mem[arg1])); + _cimg_mp_scalar1(mp_ceil,arg1); + } + + if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential + _cimg_mp_op("Function 'cexp()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_exp,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_exp,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm + _cimg_mp_op("Function 'clog()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_log,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_log,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ccos(",5)) { // Complex cosine + _cimg_mp_op("Function 'ccos()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_cos,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_cos,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"csin(",5)) { // Complex sine + _cimg_mp_op("Function 'csin()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_sin,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_sin,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ctan(",5)) { // Complex tangent + _cimg_mp_op("Function 'ctan()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_tan,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_tan,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ccosh(",6)) { // Complex hyperbolic cosine + _cimg_mp_op("Function 'ccosh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_cosh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_cosh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"csinh(",6)) { // Complex hyperbolic sine + _cimg_mp_op("Function 'csinh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_sinh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_sinh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ctanh(",6)) { // Complex hyperbolic tangent + _cimg_mp_op("Function 'ctanh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_tanh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_tanh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"continue(",9)) { // Continue loop + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_continue,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"copy(",5)) { // Memory copy + _cimg_mp_op("Function 'copy()'"); + ref.assign(14); + s1 = ss5; while (s1=4 && arg4==~0U) arg4 = scalar1(mp_image_whd,ref[1]); + } + if (_cimg_mp_is_vector(arg2)) { + if (arg3==~0U) arg3 = constant(_cimg_mp_size(arg2)); + if (!ref[7]) ++arg2; + if (ref[7]>=4 && arg5==~0U) arg5 = scalar1(mp_image_whd,ref[8]); + } + if (arg3==~0U) arg3 = 1; + if (arg4==~0U) arg4 = 1; + if (arg5==~0U) arg5 = 1; + _cimg_mp_check_type(arg3,3,1,0); + _cimg_mp_check_type(arg4,4,1,0); + _cimg_mp_check_type(arg5,5,1,0); + _cimg_mp_check_type(arg6,5,1,0); + CImg(1,22).move_to(code); + code.back().get_shared_rows(0,7).fill((ulongT)mp_memcopy,p1,arg1,arg2,arg3,arg4,arg5,arg6); + code.back().get_shared_rows(8,21).fill(ref); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"cos(",4)) { // Cosine + _cimg_mp_op("Function 'cos()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1])); + _cimg_mp_scalar1(mp_cos,arg1); + } + + if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine + _cimg_mp_op("Function 'cosh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1])); + _cimg_mp_scalar1(mp_cosh,arg1); + } + + if (!std::strncmp(ss,"critical(",9)) { // Critical section (single thread at a time) + _cimg_mp_op("Function 'critical()'"); + p1 = code._width; + arg1 = compile(ss + 9,se1,depth1,p_ref,true); + CImg::vector((ulongT)mp_critical,arg1,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"crop(",5)) { // Image crop + _cimg_mp_op("Function 'crop()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::sequence(_cimg_mp_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_size(arg1)); + opcode.resize(1,std::min(opcode._height,4U),1,1,0).move_to(l_opcode); + is_sth = true; + } else { + _cimg_mp_check_type(arg1,pos + 1,1,0); + CImg::vector(arg1).move_to(l_opcode); + } + s = ns; + } + (l_opcode>'y').move_to(opcode); + + arg1 = 0; arg2 = (p1!=~0U); + switch (opcode._height) { + case 0 : case 1 : + CImg::vector(0,0,0,0,~0U,~0U,~0U,~0U,0).move_to(opcode); + break; + case 2 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,_cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + 2; + break; + case 3 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,opcode[2]).move_to(opcode); + arg1 = arg2 + 2; + break; + case 4 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,_cimg_mp_boundary). + move_to(opcode); + arg1 = arg2 + (is_sth?2:3); + break; + case 5 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,opcode[4]). + move_to(opcode); + arg1 = arg2 + (is_sth?2:3); + break; + case 6 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + _cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + (is_sth?2:4); + break; + case 7 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + opcode[6]).move_to(opcode); + arg1 = arg2 + (is_sth?2:4); + break; + case 8 : + CImg::vector(*opcode,opcode[1],opcode[2],opcode[3],opcode[4],opcode[5],opcode[6], + opcode[7],_cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + (is_sth?2:5); + break; + case 9 : + arg1 = arg2 + (is_sth?2:5); + break; + default : // Error -> too much arguments + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Too much arguments specified, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + _cimg_mp_check_type((unsigned int)*opcode,arg2 + 1,1,0); + _cimg_mp_check_type((unsigned int)opcode[1],arg2 + 1 + (is_sth?0:1),1,0); + _cimg_mp_check_type((unsigned int)opcode[2],arg2 + 1 + (is_sth?0:2),1,0); + _cimg_mp_check_type((unsigned int)opcode[3],arg2 + 1 + (is_sth?0:3),1,0); + if (opcode[4]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[4],arg1,3); + opcode[4] = (ulongT)mem[opcode[4]]; + } + if (opcode[5]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[5],arg1 + 1,3); + opcode[5] = (ulongT)mem[opcode[5]]; + } + if (opcode[6]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[6],arg1 + 2,3); + opcode[6] = (ulongT)mem[opcode[6]]; + } + if (opcode[7]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[7],arg1 + 3,3); + opcode[7] = (ulongT)mem[opcode[7]]; + } + _cimg_mp_check_type((unsigned int)opcode[8],arg1 + 4,1,0); + + if (opcode[4]==(ulongT)~0U || opcode[5]==(ulongT)~0U || + opcode[6]==(ulongT)~0U || opcode[7]==(ulongT)~0U) { + p2 = 0; + if (p1!=~0U) { + _cimg_mp_check_constant(p1,1,1); + p2 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + } + const CImg &img = p1!=~0U?listin[p2]:imgin; + if (!img) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Cannot crop empty image when " + "some xyzc-coordinates are unspecified, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (opcode[4]==(ulongT)~0U) opcode[4] = (ulongT)img._width; + if (opcode[5]==(ulongT)~0U) opcode[5] = (ulongT)img._height; + if (opcode[6]==(ulongT)~0U) opcode[6] = (ulongT)img._depth; + if (opcode[7]==(ulongT)~0U) opcode[7] = (ulongT)img._spectrum; + } + + pos = vector((unsigned int)(opcode[4]*opcode[5]*opcode[6]*opcode[7])); + CImg::vector((ulongT)mp_crop, + pos,p1, + *opcode,opcode[1],opcode[2],opcode[3], + opcode[4],opcode[5],opcode[6],opcode[7], + opcode[8]).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cross(",6)) { // Cross product + _cimg_mp_op("Function 'cross()'"); + s1 = ss6; while (s1::vector((ulongT)mp_cross,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cut(",4)) { // Cut + _cimg_mp_op("Function 'cut()'"); + s1 = ss4; while (s1val2?val2:val); + } + _cimg_mp_scalar3(mp_cut,arg1,arg2,arg3); + } + + if (!std::strncmp(ss,"convolve(",9) || !std::strncmp(ss,"correlate(",10)) { // Convolve & Correlate + is_sth = *ss2=='n'; // is_convolve? + _cimg_mp_op(is_sth?"Function 'convolve()'":"Function 'correlate()'"); + op = is_sth?mp_convolve:mp_correlate; + const ulongT default_params[] = { (ulongT)op,0, // [0]=function, [1]=result vector + 0,0,0,0,0, // [2]=A, [3]=wA, [4]=hA, [5]=dA, [6]=sA + 0,0,0,0,0, // [7]=M, [8]=wM, [9]=hM, [10]=dM, [11]=sM + 1,0,1, // [12]=boundary_conditions, [13]=is_normalized, [14]=chan._mode + 11,11,11, // [15]=xcenter, [16]=ycenter, [17]=zcenter (default value:-1) + 0,0,0, // [18]=xstart, [19]=ystart, [20]=zstart + 11,11,11, // [21]=xend, [22]=yend, [23]=zend (default value: -1) + 1,1,1, // [24]=xstride, [25]=ystride, [26]=zstride + 1,1,1 }; // [27]=xdilation, [28]=ydilation, [29]=zdilation + + l_opcode.assign(); // Don't use 'opcode': it could be modified by further calls to 'compile()'! + CImg(default_params,1,sizeof(default_params)/sizeof(ulongT)).move_to(l_opcode); + + arg1 = 2; + for (s = std::strchr(ss,'(') + 1; s=opcode._height) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: %s arguments provided, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1<12?"Not enough":"Too much", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(opcode[2],1,2,0); // A + _cimg_mp_check_constant(opcode[3],2,3); // wA + _cimg_mp_check_constant(opcode[4],3,3); // hA + _cimg_mp_check_constant(opcode[5],4,3); // dA + _cimg_mp_check_constant(opcode[6],5,3); // sA + _cimg_mp_check_type(opcode[7],6,2,0); // M + _cimg_mp_check_constant(opcode[8],7,3); // wM + _cimg_mp_check_constant(opcode[9],8,3); // hM + _cimg_mp_check_constant(opcode[10],9,3); // dM + _cimg_mp_check_constant(opcode[11],10,3); // sM + _cimg_mp_check_type(opcode[12],11,1,0); // boundary_conditions + _cimg_mp_check_type(opcode[13],12,1,0); // is_normalized + _cimg_mp_check_constant(opcode[14],13,1); // channel_mode + _cimg_mp_check_type(opcode[15],14,1,0); // xcenter + _cimg_mp_check_type(opcode[16],15,1,0); // ycenter + _cimg_mp_check_type(opcode[17],16,1,0); // zcenter + _cimg_mp_check_constant(opcode[18],17,1); // xstart + _cimg_mp_check_constant(opcode[19],18,1); // ystart + _cimg_mp_check_constant(opcode[20],19,1); // zstart + _cimg_mp_check_constant(opcode[21],20,1); // xend + _cimg_mp_check_constant(opcode[22],21,1); // yend + _cimg_mp_check_constant(opcode[23],22,1); // zend + _cimg_mp_check_constant(opcode[24],23,3); // xstride + _cimg_mp_check_constant(opcode[25],24,3); // ystride + _cimg_mp_check_constant(opcode[26],25,3); // zstride + _cimg_mp_check_type(opcode[27],26,1,0); // xdilation + _cimg_mp_check_type(opcode[28],27,1,0); // ydilation + _cimg_mp_check_type(opcode[29],28,1,0); // zdilation + + const unsigned int + wA = (unsigned int)mem[opcode[3]], + hA = (unsigned int)mem[opcode[4]], + dA = (unsigned int)mem[opcode[5]], + sA = (unsigned int)mem[opcode[6]], + wM = (unsigned int)mem[opcode[8]], + hM = (unsigned int)mem[opcode[9]], + dM = (unsigned int)mem[opcode[10]], + sM = (unsigned int)mem[opcode[11]], + channel_mode = (unsigned int)mem[opcode[14]], + xstart = std::min((unsigned int)mem[opcode[18]],wA - 1), + ystart = std::min((unsigned int)mem[opcode[19]],hA - 1), + zstart = std::min((unsigned int)mem[opcode[20]],dA - 1), + xend = std::min((unsigned int)mem[opcode[21]],wA - 1), + yend = std::min((unsigned int)mem[opcode[22]],hA - 1), + zend = std::min((unsigned int)mem[opcode[23]],dA - 1); + + if (xstart>xend || ystart>yend || zstart>zend) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid xyz-start/end arguments " + "(start = (%u,%u,%u), end = (%u,%u,%u)), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + xstart,ystart,zstart,xend,yend,zend, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + const float + xstride = (float)mem[opcode[24]], + ystride = (float)mem[opcode[25]], + zstride = (float)mem[opcode[26]]; + + if (xstride<=0 || ystride<=0 || zstride<=0) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid stride arguments (%g,%g,%g), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + xstride,ystride,zstride, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + arg2 = 1 + (unsigned int)std::floor((xend - xstart)/xstride); + arg3 = 1 + (unsigned int)std::floor((yend - ystart)/ystride); + arg4 = 1 + (unsigned int)std::floor((zend + zstart)/zstride); + arg5 = channel_mode==0?sM:channel_mode==1?std::max(sA,sM):sA*sM; + + opcode[1] = pos = vector(arg2*arg3*arg4*arg5); + opcode[3] = (ulongT)wA; + opcode[4] = (ulongT)hA; + opcode[5] = (ulongT)dA; + opcode[6] = (ulongT)sA; + opcode[8] = (ulongT)wM; + opcode[9] = (ulongT)hM; + opcode[10] = (ulongT)dM; + opcode[11] = (ulongT)sM; + opcode[14] = (ulongT)channel_mode; + opcode[18] = (ulongT)xstart; + opcode[19] = (ulongT)ystart; + opcode[20] = (ulongT)zstart; + opcode[21] = (ulongT)xend; + opcode[22] = (ulongT)yend; + opcode[23] = (ulongT)zend; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'd' : + if (*ss1=='(') { // Image depth + _cimg_mp_op("Function 'd()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_d,p1); + } + + if (!std::strncmp(ss,"date(",5)) { // Current date or file date + _cimg_mp_op("Function 'date()'"); + s1 = ss5; while (s1::vector((ulongT)mp_date,pos,_cimg_mp_size(pos), + arg1,arg1==~0U?~0U:_cimg_mp_size(arg1), + arg2,arg2==~0U?~0U:_cimg_mp_size(arg2)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"debug(",6)) { // Print debug info + _cimg_mp_op("Function 'debug()'"); + p1 = code._width; + arg1 = compile(ss6,se1,depth1,p_ref,is_critical); + *se1 = 0; + variable_name.assign(CImg::string(ss6,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + ((CImg::vector((ulongT)mp_debug,arg1,0,code._width - p1), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code,p1); + *se1 = ')'; + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"display(",8)) { // Display memory, vector or image + _cimg_mp_op("Function 'display()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_display_memory,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + if (*ss8!='#') { // Vector + s1 = ss8; while (s1::string(ss8,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + if (_cimg_mp_is_vector(arg1)) + ((CImg::vector((ulongT)mp_vector_print,arg1,0,(ulongT)_cimg_mp_size(arg1),0), + variable_name)>'y').move_to(opcode); + else + ((CImg::vector((ulongT)mp_print,arg1,0,0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + + ((CImg::vector((ulongT)mp_display,arg1,0,(ulongT)_cimg_mp_size(arg1), + arg2,arg3,arg4,arg5), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *s1 = c1; + _cimg_mp_return(arg1); + + } else { // Image + p1 = compile(ss8 + 1,se1,depth1,0,is_critical); + _cimg_mp_check_list(true); + CImg::vector((ulongT)mp_image_display,_cimg_mp_slot_nan,p1).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"det(",4)) { // Matrix determinant + _cimg_mp_op("Function 'det()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + _cimg_mp_scalar2(mp_det,arg1,p1); + } + + if (!std::strncmp(ss,"diag(",5)) { // Diagonal matrix + _cimg_mp_op("Function 'diag()'"); + CImg::vector((ulongT)mp_diag,0,0).move_to(l_opcode); + for (s = ss5; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + arg1 = opcode._height - 3; + pos = vector(arg1*arg1); + opcode[1] = pos; + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"dot(",4)) { // Dot product + _cimg_mp_op("Function 'dot()'"); + s1 = ss4; while (s1::vector((ulongT)mp_do,p1,p2,arg2 - arg1,code._width - arg2,_cimg_mp_size(p1), + p1>=arg6 && !_cimg_mp_is_constant(p1), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"draw(",5)) { // Draw image + if (!is_critical) is_parallelizable = false; + _cimg_mp_op("Function 'draw()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s01) { + arg3 = arg2 + 1; + if (p2>2) { + arg4 = arg3 + 1; + if (p2>3) arg5 = arg4 + 1; + } + } + ++s0; + is_sth = true; + } else { + if (s0::vector((ulongT)mp_draw,arg1,(ulongT)_cimg_mp_size(arg1),p1,arg2,arg3,arg4,arg5, + 0,0,0,0,1,(ulongT)~0U,0,1).move_to(l_opcode); + + arg2 = arg3 = arg4 = arg5 = ~0U; + p2 = p1!=~0U?0:1; + if (s0::vector((ulongT)mp_echo,_cimg_mp_slot_nan,0).move_to(l_opcode); + for (s = ss5; s::vector(arg1,_cimg_mp_size(arg1)).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"eig(",4)) { // Matrix eigenvalues/eigenvector + _cimg_mp_op("Function 'eig()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + pos = vector((p1 + 1)*p1); + CImg::vector((ulongT)mp_matrix_eig,pos,arg1,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ellipse(",8)) { // Ellipse/circle drawing + if (!is_critical) is_parallelizable = false; + _cimg_mp_op("Function 'ellipse()'"); + if (*ss8=='#') { // Index specified + s0 = ss + 9; while (s0::vector((ulongT)mp_ellipse,_cimg_mp_slot_nan,0,p1).move_to(l_opcode); + for (s = s0; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"erf(",4)) { // Error function + _cimg_mp_op("Function 'erf()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_erf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::erf(mem[arg1])); + _cimg_mp_scalar1(mp_erf,arg1); + } + + if (!std::strncmp(ss,"erfinv(",7)) { // Inverse of error function + _cimg_mp_op("Function 'erfinv()'"); + arg1 = compile(ss7,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_erfinv,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::erfinv(mem[arg1])); + _cimg_mp_scalar1(mp_erfinv,arg1); + } + + if (!std::strncmp(ss,"exp(",4)) { // Exponential + _cimg_mp_op("Function 'exp()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1])); + _cimg_mp_scalar1(mp_exp,arg1); + } + + if (!std::strncmp(ss,"expr(",5)) { // Vector from expression + _cimg_mp_op("Function 'expr()'"); + s1 = ss5; while (s1::vector((ulongT)mp_expr,pos,arg1,p1,arg2,arg3,arg4,arg5).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"eye(",4)) { // Identity matrix + _cimg_mp_op("Function 'eye()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_constant(arg1,1,3); + p1 = (unsigned int)mem[arg1]; + pos = vector(p1*p1); + CImg::vector((ulongT)mp_eye,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"end(",4)) { // End + _cimg_mp_op("Function 'end()'"); + code.swap(code_end); + compile(ss4,se1,depth1,p_ref,true); + code.swap(code_end); + is_end_code = true; + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"end_t(",6)) { // End thread + _cimg_mp_op("Function 'end_t()'"); + code.swap(code_end_t); + compile(ss6,se1,depth1,p_ref,true); + code.swap(code_end_t); + is_end_code = true; + _cimg_mp_return_nan(); + } + break; + + case 'f' : + if (!std::strncmp(ss,"f2ui(",5)) { // Special float->uint conversion + _cimg_mp_op("Function 'f2ui()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_f2ui,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((double)cimg::float2uint((float)mem[arg1])); + _cimg_mp_scalar1(mp_f2ui,arg1); + } + + if (!std::strncmp(ss,"fact(",5)) { // Factorial + _cimg_mp_op("Function 'fact()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_factorial,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::factorial((int)mem[arg1])); + _cimg_mp_scalar1(mp_factorial,arg1); + } + + if (!std::strncmp(ss,"fibo(",5)) { // Fibonacci + _cimg_mp_op("Function 'fibo()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_fibonacci,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::fibonacci((int)mem[arg1])); + _cimg_mp_scalar1(mp_fibonacci,arg1); + } + + if (!std::strncmp(ss,"fill(",5)) { // Fill + _cimg_mp_op("Function 'fill()'"); + s0 = ss5; while (s0::%s: %s: Target scalar is constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss>expr._data?"...":"",ss,se<&expr.back()?"...":""); + s1 = ++s0; while (s1::%s: %s: Invalid loop variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + get_variable_pos(variable_name,arg2,arg3); + arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot + if (arg2!=~0U && (!_cimg_mp_is_scalar(arg2) || + _cimg_mp_is_constant(arg2))) { // Variable is not a vector or is a constant -> error + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' " + "(expected 'scalar'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg2)._data,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (arg2==~0U) { // Variable does not exist -> create it + arg2 = scalar(); + if (arg3!=~0U) reserved_label[arg3] = arg2; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg2; + variable_name.move_to(variable_def); + } + memtype[arg2] = -1; + } + arg3 = compile(++s1,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg3,3,1,0); + } else { // Version with 2 arguments + arg2 = ~0U; + arg3 = compile(s0,se1,depth1,0,is_critical); + } + // arg2 = variable slot, arg3 = fill expression. + _cimg_mp_check_type(arg3,3,1,0); + CImg::vector((ulongT)mp_fill,arg1,_cimg_mp_size(arg1),arg2,arg3,code._width - p1). + move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"find(",5)) { // Find + _cimg_mp_op("Function 'find()'"); + + // First argument: data to look at. + s0 = ss5; while (s01) + _cimg_mp_scalar5(mp_list_find_seq,p1,arg2,_cimg_mp_size(arg2),arg3,arg4); + _cimg_mp_scalar4(mp_list_find,p1,arg2 + (_cimg_mp_size(arg2)?1:0),arg3,arg4); + } + if (_cimg_mp_size(arg2)>1) + _cimg_mp_scalar6(mp_find_seq,arg1,_cimg_mp_size(arg1),arg2,_cimg_mp_size(arg2),arg3,arg4); + _cimg_mp_scalar5(mp_find,arg1,_cimg_mp_size(arg1),arg2 + (_cimg_mp_size(arg2)?1:0),arg3,arg4); + } + + if (*ss1=='o' && *ss2=='r' && *ss3=='(') { // For loop + _cimg_mp_op("Function 'for()'"); + s1 = ss4; while (s1::vector((ulongT)mp_for,p3,(ulongT)_cimg_mp_size(p3),p2,arg2 - arg1,arg3 - arg2, + arg4 - arg3,code._width - arg4, + p3>=arg6 && !_cimg_mp_is_constant(p3), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p3); + } + + if (!std::strncmp(ss,"floor(",6)) { // Floor + _cimg_mp_op("Function 'floor()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_floor,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::floor(mem[arg1])); + _cimg_mp_scalar1(mp_floor,arg1); + } + + if (!std::strncmp(ss,"fsize(",6)) { // File size + _cimg_mp_op("Function 'fsize()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,2,0); + pos = scalar(); + CImg::vector((ulongT)mp_fsize,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'g' : + if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function + _cimg_mp_op("Function 'gauss()'"); + s1 = ss6; while (s1::vector((ulongT)mp_get,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + break; + + case 'h' : + if (*ss1=='(') { // Image height + _cimg_mp_op("Function 'h()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_h,p1); + } + break; + + case 'i' : + if (*ss1=='c' && *ss2=='(') { // Image median + _cimg_mp_op("Function 'ic()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + pos = scalar(); + CImg::vector((ulongT)mp_image_median,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (*ss1=='n' && *ss2=='(') { // Image norm + _cimg_mp_op("Function 'in()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + pos = scalar(); + CImg::vector((ulongT)mp_image_norm,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (*ss1=='f' && *ss2=='(') { // If..then[..else.] + _cimg_mp_op("Function 'if()'"); + s1 = ss3; while (s1::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"inrange(",8)) { // Check value range + _cimg_mp_op("Function 'inrange()'"); + s1 = ss8; while (s1=val1) + is_sth = (mem[arg4]?(val>=val1):(val>val1)) && (mem[arg5]?(val<=val2):(val=val2):(val>val2)) && (mem[arg4]?(val<=val1):(val::vector((ulongT)mp_inrange,pos,arg6,arg1,p1,arg2,p2,arg3,p3,arg4,arg5).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"int(",4)) { // Integer cast + _cimg_mp_op("Function 'int()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((longT)mem[arg1]); + _cimg_mp_scalar1(mp_int,arg1); + } + + if (!std::strncmp(ss,"invert(",7)) { // Matrix/scalar inversion + _cimg_mp_op("Function 'invert()'"); + s1 = ss7; while (s1::vector((ulongT)mp_matrix_invert,pos,arg1,p1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(1/mem[arg1]); + _cimg_mp_scalar2(mp_div,1,arg1); + } + + if (*ss1=='s') { // Family of 'is_?()' functions + + if (!std::strncmp(ss,"isbool(",7)) { // Is boolean? + _cimg_mp_op("Function 'isbool()'"); + if (ss7==se1) _cimg_mp_return(0); + try { arg1 = compile(ss7,se1,depth1,0,is_critical); } + catch(CImgException&) { _cimg_mp_return(0); } + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return(mem[arg1]==0. || mem[arg1]==1.); + _cimg_mp_scalar1(mp_isbool,arg1); + } + + if (!std::strncmp(ss,"isdir(",6)) { // Is directory? + _cimg_mp_op("Function 'isdir()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_isdir,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isfile(",7)) { // Is file? + _cimg_mp_op("Function 'isfile()'"); + arg1 = compile(ss7,se1,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_isfile,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector? + if (ss5>=se1) _cimg_mp_return(0); + _cimg_mp_op("Function 'isin()'"); + pos = scalar(); + CImg::vector((ulongT)mp_isin,pos,0).move_to(l_opcode); + for (s = ss5; s::sequence(_cimg_mp_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_size(arg1)). + move_to(l_opcode); + else CImg::vector(arg1).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isinf(",6)) { // Is infinite? + _cimg_mp_op("Function 'isinf()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_inf(mem[arg1])); + _cimg_mp_scalar1(mp_isinf,arg1); + } + + if (!std::strncmp(ss,"isint(",6)) { // Is integer? + _cimg_mp_op("Function 'isint()'"); + if (ss6==se1) _cimg_mp_return(0); + try { arg1 = compile(ss6,se1,depth1,0,is_critical); } + catch(CImgException&) { _cimg_mp_return(0); } + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)((double)(longT)mem[arg1]==mem[arg1])); + _cimg_mp_scalar1(mp_isint,arg1); + } + + if (!std::strncmp(ss,"isnan(",6)) { // Is NaN? + _cimg_mp_op("Function 'isnan()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_nan(mem[arg1])); + _cimg_mp_scalar1(mp_isnan,arg1); + } + + if (!std::strncmp(ss,"isnum(",6)) { // Is number? + _cimg_mp_op("Function 'isnum()'"); + val = 0; + if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1); + _cimg_mp_return(0); + } + + if (!std::strncmp(ss,"isexpr(",7)) { // Is valid expression? + _cimg_mp_op("Function 'isexpr()'"); + if (ss7==se1) _cimg_mp_return(0); + try { arg1 = compile(ss7,se1,depth1,0,is_critical); } + catch (CImgException&) { _cimg_mp_return(0); } + _cimg_mp_return(1); + } + } + break; + + case 'l' : + if (*ss1=='(') { // Size of image list + _cimg_mp_op("Function 'l()'"); + if (ss2!=se1) break; + _cimg_mp_scalar0(mp_list_l); + } + + if (!std::strncmp(ss,"lerp(",5)) { // Linear interpolation + _cimg_mp_op("Function 'lerp()'"); + s1 = ss5; while (s1::vector((ulongT)mp_vector_lerp,pos,p1,arg1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"log(",4)) { // Natural logarithm + _cimg_mp_op("Function 'log()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1])); + _cimg_mp_scalar1(mp_log,arg1); + } + + if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm + _cimg_mp_op("Function 'log2()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1])); + _cimg_mp_scalar1(mp_log2,arg1); + } + + if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm + _cimg_mp_op("Function 'log10()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1])); + _cimg_mp_scalar1(mp_log10,arg1); + } + + if (!std::strncmp(ss,"lowercase(",10)) { // Lower case + _cimg_mp_op("Function 'lowercase()'"); + arg1 = compile(ss + 10,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_lowercase,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::lowercase(mem[arg1])); + _cimg_mp_scalar1(mp_lowercase,arg1); + } + break; + + case 'm' : + if (!std::strncmp(ss,"mul(",4)) { // Matrix multiplication + _cimg_mp_op("Function 'mul()'"); + s1 = ss4; while (s1::%s: %s: Types of first and second arguments ('%s' and '%s') " + "do not match with third argument 'nb_colsB=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data,p3, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"mproj(",6)) { // Project matrix onto dictionary + _cimg_mp_op("Function 'mproj()'"); + s1 = ss6; while (s1::%s: %s: Type of first argument ('%s') " + "do not match with second argument 'nb_colsS=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,wS, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (wD*hD!=p2) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Type of third argument ('%s') " + "do not match with fourth argument 'nb_colsD=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg3)._data,wD, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (hS!=hD) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Type of first argument ('%s') " + "do not match with third argument ('%s'), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg3)._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(wS*wD); + CImg::vector((ulongT)mp_mproj,pos,arg1,wS,hS,arg3,wD,arg5,arg6,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"merge(",6)) { // Merge inter-thread variables + _cimg_mp_op("Function 'merge()'"); + s1 = ss6; while (s1::%s: %s: Merge has already been requested before " + "for specified variable " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (arg1==~0U) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid specified operator " + "(should be one of '=,+,-,*,/,min,max'), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + memmerge.resize(3,memmerge._height + 1,1,1,0,0); + memmerge(0,memmerge._height - 1) = (int)pos; + memmerge(1,memmerge._height - 1) = (int)_cimg_mp_size(pos); + memmerge(2,memmerge._height - 1) = (int)arg1; + _cimg_mp_return(pos); + } + break; + + case 'n' : +#ifdef cimg_mp_func_name + if (!std::strncmp(ss,"name(",5)) { // Get image name as a string vector + _cimg_mp_op("Function 'name()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::vector((ulongT)mp_name,pos,p1,arg1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + + if (!std::strncmp(ss,"narg(",5)) { // Number of arguments + _cimg_mp_op("Function 'narg()'"); + if (ss5>=se1) _cimg_mp_return(0); + arg1 = 0; + for (s = ss5; s::vector((ulongT)mp_norm0,pos,0).move_to(l_opcode); break; + case 1 : + CImg::vector((ulongT)mp_norm1,pos,0).move_to(l_opcode); break; + case 2 : + CImg::vector((ulongT)mp_norm2,pos,0).move_to(l_opcode); break; + case ~0U : + CImg::vector((ulongT)mp_norminf,pos,0).move_to(l_opcode); break; + default : + CImg::vector((ulongT)mp_normp,pos,0,(ulongT)(arg1==~0U?-1:(int)arg1)). + move_to(l_opcode); + } + for ( ; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + + (l_opcode>'y').move_to(opcode); + if (arg1>0 && opcode._height==4) // Special case with one argument and p>=1 + _cimg_mp_scalar1(mp_abs,opcode[3]); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'p' : + if (!std::strncmp(ss,"permut(",7)) { // Number of permutations + _cimg_mp_op("Function 'permut()'"); + s1 = ss7; while (s1::vector((ulongT)mp_polygon,_cimg_mp_slot_nan,0,p1).move_to(l_opcode); + for (s = s0; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"print(",6) || !std::strncmp(ss,"prints(",7)) { // Print expressions + is_sth = ss[5]=='s'; // is prints() + _cimg_mp_op(is_sth?"Function 'prints()'":"Function 'print()'"); + s0 = is_sth?ss7:ss6; + if (*s0!='#' || is_sth) { // Regular expression + for (s = s0; s::string(s,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + if (_cimg_mp_is_vector(pos)) // Vector + ((CImg::vector((ulongT)mp_vector_print,pos,0,(ulongT)_cimg_mp_size(pos),is_sth?1:0), + variable_name)>'y').move_to(opcode); + else // Scalar + ((CImg::vector((ulongT)mp_print,pos,0,is_sth?1:0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *ns = c1; s = ns; + } + _cimg_mp_return(pos); + } else { // Image + p1 = compile(ss7,se1,depth1,0,is_critical); + _cimg_mp_check_list(true); + CImg::vector((ulongT)mp_image_print,_cimg_mp_slot_nan,p1).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"pseudoinvert(",13)) { // Matrix/scalar pseudo-inversion + _cimg_mp_op("Function 'pseudoinvert()'"); + s1 = ss + 13; while (s1::%s: %s: Type of first argument ('%s') " + "does not match with second argument 'nb_colsA=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1); + CImg::vector((ulongT)mp_matrix_pseudoinvert,pos,arg1,p2,p3,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'r' : + if (!std::strncmp(ss,"ref(",4)) { // Variable declaration + _cimg_mp_op("Function 'ref()'"); + s1 = ss4; while (s1=se1 || !*s1) compile(s1,s1,depth1,0,is_critical); // Will throw missing argument error + arg3 = compile(ss4,s1++,depth1,p_ref,is_critical); + *se1 = 0; + + if (!is_varname(s1)) { // Invalid variable name + variable_name.assign(s1,(unsigned int)(se1 + 1 - s1)).back() = 0; + cimg::strellipsize(variable_name,64); + *se1 = ')'; + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid specified variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + get_variable_pos(s1,arg1,arg2); + if (arg2!=~0U) reserved_label[arg2] = arg3; + else if (arg1!=~0U) variable_pos[arg1] = arg3; + else { // New variable + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg3; + CImg::string(s1).move_to(variable_def); + } + if (_cimg_mp_is_vector(arg3)) + set_reserved_vector(arg3); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -1; + *se1 = ')'; + _cimg_mp_return(arg3); + } + + if (!std::strncmp(ss,"repeat(",7)) { // Repeat + _cimg_mp_op("Function 'repeat()'"); + s0 = ss7; while (s0::%s: %s: Invalid loop variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + get_variable_pos(variable_name,arg2,arg3); + arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot + if (arg2!=~0U && (!_cimg_mp_is_scalar(arg2) || + _cimg_mp_is_constant(arg2))) { // Variable is not a vector or is a constant -> error + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' " + "(expected 'scalar'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg2)._data,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (arg2==~0U) { // Variable does not exist -> create it + arg2 = scalar(); + if (arg3!=~0U) reserved_label[arg3] = arg2; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg2; + variable_name.move_to(variable_def); + } + memtype[arg2] = -1; + } + arg3 = compile(++s1,se1,depth1,0,is_critical); + } else { // Version with 2 arguments + arg2 = ~0U; + arg3 = compile(s0,se1,depth1,0,is_critical); + } + // arg2 = variable slot, arg3 = fill expression. + CImg::vector((ulongT)mp_repeat,arg3,arg1,arg2,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg3); + } + + if (!std::strncmp(ss,"resize(",7)) { // Vector or image resize + _cimg_mp_op("Function 'resize()'"); + if (*ss7!='#') { // Vector + s1 = ss7; while (s1::vector((ulongT)mp_vector_resize,pos,arg2,arg1,(ulongT)_cimg_mp_size(arg1), + arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + + } else { // Image + if (!is_critical) is_parallelizable = false; + s0 = ss8; while (s0::vector((ulongT)mp_image_resize,_cimg_mp_slot_nan,p1,~0U,~0U,~0U,~0U,1,0,0,0,0,0). + move_to(l_opcode); + pos = 0; + for (s = s0; s10) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: %s arguments, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + pos<1?"Missing":"Too much", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + l_opcode[0].move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"reverse(",8)) { // Vector reverse + _cimg_mp_op("Function 'reverse()'"); + arg1 = compile(ss8,se1,depth1,0,is_critical); + if (!_cimg_mp_is_vector(arg1)) _cimg_mp_return(arg1); + p1 = _cimg_mp_size(arg1); + pos = vector(p1); + CImg::vector((ulongT)mp_vector_reverse,pos,arg1,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation + _cimg_mp_op(ss[2]=='l'?"Function 'rol()'":"Function 'ror()'"); + s1 = ss4; while (s11) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + arg4 = compile(++s1,se1,depth1,0,is_critical); + } else { + s2 = s1 + 1; while (s2::vector((ulongT)mp_rot3d,pos,arg1,arg2,arg3,arg4).move_to(code); + } else { // 2D rotation + _cimg_mp_check_type(arg1,1,1,0); + pos = vector(4); + CImg::vector((ulongT)mp_rot2d,pos,arg1).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"round(",6)) { // Value rounding + _cimg_mp_op("Function 'round()'"); + s1 = ss6; while (s1::vector((ulongT)mp_run,0,0).move_to(l_opcode); + pos = 1; + for (s = ss4; s::vector(arg1,_cimg_mp_size(arg1)).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + pos = scalar(); + opcode[1] = pos; + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + break; + + case 's' : + if (*ss1=='(') { // Image spectrum + _cimg_mp_op("Function 's()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_s,p1); + } + + if (!std::strncmp(ss,"same(",5)) { // Test if operands have the same values + _cimg_mp_op("Function 'same()'"); + s1 = ss5; while (s1::vector((ulongT)mp_shift,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sign(",5)) { // Sign + _cimg_mp_op("Function 'sign()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1])); + _cimg_mp_scalar1(mp_sign,arg1); + } + + if (!std::strncmp(ss,"sin(",4)) { // Sine + _cimg_mp_op("Function 'sin()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1])); + _cimg_mp_scalar1(mp_sin,arg1); + } + + if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal + _cimg_mp_op("Function 'sinc()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1])); + _cimg_mp_scalar1(mp_sinc,arg1); + } + + if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine + _cimg_mp_op("Function 'sinh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1])); + _cimg_mp_scalar1(mp_sinh,arg1); + } + + if (!std::strncmp(ss,"size(",5)) { // Vector size + _cimg_mp_op("Function 'size()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_size(arg1)); + } + + if (!std::strncmp(ss,"solve(",6)) { // Solve square linear system + _cimg_mp_op("Function 'solve()'"); + s1 = ss6; while (s1::%s: %s: Types of first and second arguments ('%s' and '%s') " + "do not match with third argument 'nb_colsB=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data,p3, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sort(",5)) { // Sort vector + _cimg_mp_op("Function 'sort()'"); + s1 = ss5; while (s1::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sqr(",4)) { // Square + _cimg_mp_op("Function 'sqr()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1])); + _cimg_mp_scalar1(mp_sqr,arg1); + } + + if (!std::strncmp(ss,"sqrt(",5)) { // Square root + _cimg_mp_op("Function 'sqrt()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1])); + _cimg_mp_scalar1(mp_sqrt,arg1); + } + + if (!std::strncmp(ss,"srand(",6)) { // Set RNG seed + _cimg_mp_op("Function 'srand()'"); + arg1 = ss6::vector((ulongT)mp_image_stats,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + +#ifdef cimg_mp_func_store + if (!std::strncmp(ss,"store(",6)) { // Store vector to variable + _cimg_mp_op("Function 'store()'"); + s1 = ss6; while (s1::vector((ulongT)mp_store,_cimg_mp_slot_nan,arg1,p1,arg2,p2, + arg3,arg4,arg5,arg6,pos).move_to(code); + _cimg_mp_return_nan(); + } +#endif + + if (!std::strncmp(ss,"stov(",5)) { // String to double + _cimg_mp_op("Function 'stov()'"); + s1 = ss5; while (s1::vector((ulongT)mp_stov,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"string(",7)) { // Construct string from list of arguments + _cimg_mp_op("Function 'string()'"); + CImg::vector((ulongT)mp_string,0,0,0).move_to(l_opcode); + + if (*ss7=='#') { // Output vector size specified, with '#' + s0 = ss8; while (s0::vector(arg2,p2).move_to(l_opcode); + s = ns; + } + if (arg1==~0U) arg1 = p1; + pos = vector(arg1,0); + (l_opcode>'y').move_to(opcode); + opcode[1] = pos; + opcode[2] = arg1; + opcode[3] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"svd(",4)) { // Matrix SVD + _cimg_mp_op("Function 'svd()'"); + s1 = ss4; while (s1::%s: %s: Type of first argument ('%s') " + "does not match with second argument 'nb_colsA=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1 + p2 + p2*p2); + CImg::vector((ulongT)mp_matrix_svd,pos,arg1,p2,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"swap(",5)) { // Swap values + _cimg_mp_op("Function 'swap()'"); + s1 = ss5; while (s1::%s: %s: %s argument cannot be a constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"First":"Second", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + CImg::vector((ulongT)mp_swap,arg1,arg2,p1).move_to(code); + + // Write back values of linked arg1 and arg2. + const unsigned int *_ref = ref; + is_sth = true; // Is first argument? + do { + switch (*_ref) { + case 1 : // arg1: V[k] + arg3 = _ref[1]; // Vector slot + arg4 = _ref[2]; // Index + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + break; + case 2 : // arg1: i/j[_#ind,off] + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // Offset + if (p1!=~0U) { + if (listout) + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (imgout) + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + break; + case 3 : // arg1: i/j(_#ind,_x,_y,_z,_c) + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // X + arg4 = _ref[4]; // Y + arg5 = _ref[5]; // Z + arg6 = _ref[6]; // C + if (p1!=~0U) { + if (listout) + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (imgout) + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + break; + case 4: // arg1: I/J[_#ind,off] + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // Offset + if (p1!=~0U) { + if (listout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg1,p1,arg3).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + } + } else { + if (imgout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg1,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + } + break; + case 5 : // arg1: I/J(_#ind,_x,_y,_z,_c) + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // X + arg4 = _ref[4]; // Y + arg5 = _ref[5]; // Z + if (p1!=~0U) { + if (listout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg1,p1,arg3,arg4,arg5).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + } else { + if (imgout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg1,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + break; + } + + _ref+=7; + arg1 = arg2; + is_sth = !is_sth; + } while (!is_sth); + + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + _cimg_mp_return(arg1); + } + break; + + case 't' : + if (!std::strncmp(ss,"tan(",4)) { // Tangent + _cimg_mp_op("Function 'tan()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1])); + _cimg_mp_scalar1(mp_tan,arg1); + } + + if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent + _cimg_mp_op("Function 'tanh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1])); + _cimg_mp_scalar1(mp_tanh,arg1); + } + + if (!std::strncmp(ss,"trace(",6)) { // Matrix trace + _cimg_mp_op("Function 'trace()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + _cimg_mp_scalar2(mp_trace,arg1,p1); + } + + if (!std::strncmp(ss,"transpose(",10)) { // Matrix transpose + _cimg_mp_op("Function 'transpose()'"); + s1 = ss + 10; while (s1::%s: %s: Size of first argument ('%s') does not match " + "second argument 'nb_cols=%u', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p3*p2); + CImg::vector((ulongT)mp_transpose,pos,arg1,p2,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'u' : + if (*ss1=='(') { // Random value with uniform distribution + _cimg_mp_op("Function 'u()'"); + if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1); + s1 = ss2; while (s1float conversion + _cimg_mp_op("Function 'ui2f()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_ui2f,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((double)cimg::uint2float((unsigned int)mem[arg1])); + _cimg_mp_scalar1(mp_ui2f,arg1); + } + + if (!std::strncmp(ss,"unref(",6)) { // Un-reference variable + _cimg_mp_op("Function 'unref()'"); + arg1=~0U; + for (s0 = ss6; s0ss6 && *s0==',') ++s0; + s1 = s0; while (s1s0) { + *s1 = 0; + get_variable_pos(s0,arg1,arg2); + if (arg2!=~0U) reserved_label[arg2] = ~0U; + else if (arg1!=~0U) { + variable_def.remove(arg1); + if (arg10) || + !std::strncmp(ss,"vector(",7) || + (!std::strncmp(ss,"vector",6) && ss7::sequence(arg4,arg3 + 1,arg3 + arg4).move_to(l_opcode); + arg2+=arg4; + } else { CImg::vector(arg3).move_to(l_opcode); ++arg2; } + s = ns; + } + if (arg1==~0U) arg1 = arg2; + if (!arg1) _cimg_mp_return(0); + pos = vector(arg1); + l_opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"vmax(",5) || !std::strncmp(ss,"vmin(",5) || + !std::strncmp(ss,"vmaxabs(",8) || !std::strncmp(ss,"vminabs(",8) || + !std::strncmp(ss,"vmed(",5) || !std::strncmp(ss,"vkth(",5) || + !std::strncmp(ss,"vsum(",5) || !std::strncmp(ss,"vavg(",5) || + !std::strncmp(ss,"vstd(",5) || !std::strncmp(ss,"vvar(",5) || + !std::strncmp(ss,"vprod(",6) || + !std::strncmp(ss,"vargmin(",8) || !std::strncmp(ss,"vargmax(",8) || + !std::strncmp(ss,"vargminabs(",11) || !std::strncmp(ss,"vargmaxabs(",11) || + !std::strncmp(ss,"vargkth(",8)) { // Multi-argument vector functions + _cimg_mp_op(ss[1]=='a'?(ss[2]=='v'?"Function 'vavg()'": + ss[4]=='k'?"Function 'vargkth()'": + ss[5]=='i' && ss[7]=='('?"Function 'vargmin()'": + ss[5]=='i'?"Function vargminabs()'": + ss[7]=='('?"Function 'vargmax()'": + "Function 'vargmaxabs()'"): + ss[1]=='s'?(ss[2]=='u'?"Function 'vsum()'":"Function 'vstd()'"): + ss[1]=='k'?"Function 'vkth()'": + ss[1]=='p'?"Function 'vprod()'": + ss[1]=='v'?"Function 'vvar()'": + ss[2]=='i'?(ss[4]=='('?"Function 'vmin()'": + "Function 'vminabs()'"): + ss[2]=='a'?(ss[4]=='('?"Function 'vmax()'": + "Function 'vmaxabs()'"): + "Function 'vmed()'"); + op = ss[1]=='a'?(ss[2]=='v'?mp_vavg: + ss[4]=='k'?mp_vargkth: + ss[5]=='i' && ss[7]=='('?mp_vargmin: + ss[5]=='i'?mp_vargminabs: + ss[7]=='('?mp_vargmax:mp_vargmaxabs): + ss[1]=='s'?(ss[2]=='u'?mp_vsum:mp_vstd): + ss[1]=='k'?mp_vkth: + ss[1]=='p'?mp_vprod: + ss[1]=='v'?mp_vvar: + ss[2]=='i'?(ss[4]=='('?mp_vmin:mp_vminabs): + ss[2]=='a'?(ss[4]=='('?mp_vmax:mp_vmaxabs): + mp_vmedian; + CImg::vector((ulongT)op,0,0,0).move_to(l_opcode); + p1 = ~0U; + p3 = 1; + for (s = std::strchr(ss,'(') + 1; s::vector(arg2,p2).move_to(l_opcode); + s = ns; + ++p3; + } + (l_opcode>'y').move_to(opcode); + if (p1==~0U) { pos = scalar(); p1 = 0; } else pos = vector(p1); + opcode[1] = pos; + opcode[2] = p1; + opcode[3] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"vtos(",5)) { // Double(s) to string + _cimg_mp_op("Function 'vtos()'"); + s1 = ss5; while (s1::vector((ulongT)mp_vtos,pos,p1,arg1,_cimg_mp_size(arg1),arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'w' : + if (*ss1=='(') { // Image width + _cimg_mp_op("Function 'w()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_w,p1); + } + + if (*ss1=='h' && *ss2=='(') { // Image width*height + _cimg_mp_op("Function 'wh()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_wh,p1); + } + + if (*ss1=='h' && *ss2=='d' && *ss3=='(') { // Image width*height*depth + _cimg_mp_op("Function 'whd()'"); + if (*ss4=='#') { // Index specified + p1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss4!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_whd,p1); + } + + if (*ss1=='h' && *ss2=='d' && *ss3=='s' && *ss4=='(') { // Image width*height*depth*spectrum + _cimg_mp_op("Function 'whds()'"); + if (*ss5=='#') { // Index specified + p1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss5!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_whds,p1); + } + + if (!std::strncmp(ss,"while(",6)) { // While...do + _cimg_mp_op("Function 'while()'"); + s0 = *ss5=='('?ss6:ss8; + s1 = s0; while (s1::vector((ulongT)mp_while,pos,arg1,p2 - p1,code._width - p2,arg2, + pos>=arg6 && !_cimg_mp_is_constant(pos), + arg1>=arg6 && !_cimg_mp_is_constant(arg1)).move_to(code,p1); + _cimg_mp_return(pos); + } + break; + + case 'x' : + if (!std::strncmp(ss,"xor(",4)) { // Xor + _cimg_mp_op("Function 'xor()'"); + s1 = ss4; while (s1::vector((ulongT)op,pos,0).move_to(l_opcode); + for (s = std::strchr(ss,'(') + 1; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + is_sth&=_cimg_mp_is_constant(arg2); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (is_sth) _cimg_mp_constant(op(*this)); + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // No corresponding built-in function -> Look for a user-defined macro call. + s0 = strchr(ss,'('); + if (s0) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + + // Count number of specified arguments. + p1 = 0; + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && !p1) break; + ns = s; while (ns _expr = macro_body[l]; // Expression to be substituted + + p1 = 1; // Index of current parsed argument + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { // Parse function arguments + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && p1==1) break; // Function has no arguments + if (p1>p2) { ++p1; break; } + ns = s; while (ns _pexpr(_expr._width); + ns = _pexpr._data; + for (ps = _expr._data, c1 = ' '; *ps; ++ps) { + if (!cimg::is_blank(*ps)) c1 = *ps; + *(ns++) = c1; + } + *ns = 0; + + CImg _level = get_level(_expr); + expr.swap(_expr); + pexpr.swap(_pexpr); + level.swap(_level); + s0 = user_macro; + user_macro = macro_def[l]; + pos = compile(expr._data,expr._data + expr._width - 1,depth1,p_ref,is_critical); + user_macro = s0; + level.swap(_level); + pexpr.swap(_pexpr); + expr.swap(_expr); + _cimg_mp_return(pos); + } + + if (arg3) { // Macro name matched but number of arguments does not + CImg sig_nargs(arg3); + arg1 = 0; + cimglist_for(macro_def,l) if (!std::strcmp(macro_def[l],variable_name)) + sig_nargs[arg1++] = (unsigned int)macro_def[l].back(); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + if (sig_nargs._width>1) { + sig_nargs.sort(); + arg1 = sig_nargs.back(); + --sig_nargs._width; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %s or %u arguments), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,sig_nargs.value_string()._data,arg1, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %u argument%s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,*sig_nargs,*sig_nargs!=1?"s":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + } // if (se1==')') + + // Char / string initializer. + if (*se1=='\'' && + ((se1>ss && *ss=='\'') || + (se1>ss1 && *ss=='_' && *ss1=='\''))) { + if (*ss=='_') { _cimg_mp_op("Char initializer"); s1 = ss2; } + else { _cimg_mp_op("String initializer"); s1 = ss1; } + arg1 = (unsigned int)(se1 - s1); // Original string length + if (arg1) { + CImg(s1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + if (*ss=='_') { + if (arg1==1) _cimg_mp_constant((unsigned char)*variable_name); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Literal %s contains more than one byte, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss1, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode); + std::memcpy((char*)l_opcode[1]._data,variable_name,arg1); + (l_opcode>'y').move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // Vector initializer [ ... ]. + if (*ss=='[' && *se1==']') { + _cimg_mp_op("Vector initializer"); + s1 = ss1; while (s1s1 && cimg::is_blank(*s2)) --s2; + if (s2>s1 && *s1=='\'' && *s2=='\'') { // Vector values provided as a string + arg1 = (unsigned int)(s2 - s1 - 1); // Original string length + if (arg1) { + CImg(s1 + 1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode); + std::memcpy((char*)l_opcode[1]._data,variable_name,arg1); + (l_opcode>'y').move_to(code); + } else { // Vector values provided as list of items + arg1 = 0; // Number of specified values + if (*ss1!=']') for (s = ss1; s::sequence(arg3,arg2 + 1,arg2 + arg3).move_to(l_opcode); + arg1+=arg3; + } else { CImg::vector(arg2).move_to(l_opcode); ++arg1; } + s = ns; + } + if (!arg1) _cimg_mp_return(0); + pos = vector(arg1); + l_opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + // Variables related to the input list of images. + if (*ss1=='#' && ss2::vector((ulongT)mp_list_Joff,pos,p1,0,0,p2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + case 'R' : // R#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0, + 0,_cimg_mp_boundary); + case 'G' : // G#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1, + 0,_cimg_mp_boundary); + case 'B' : // B#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2, + 0,_cimg_mp_boundary); + case 'A' : // A#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3, + 0,_cimg_mp_boundary); + } + } + + if (*ss1 && *ss2=='#' && ss3='0' && *ss1<='9') { // i0#ind...i9#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,*ss1 - '0', + 0,_cimg_mp_boundary); + } + + if (*ss1=='c') { // ic#ind + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_median) list_median.assign(listin._width); + if (!list_median[p1]) CImg::vector(listin[p1].median()).move_to(list_median[p1]); + _cimg_mp_constant(*list_median[p1]); + } + _cimg_mp_scalar1(mp_list_median,arg1); + } + + if (*ss1=='n') { // in#ind + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_norm) list_norm.assign(listin._width); + if (!list_norm[p1]) CImg::vector(listin[p1].magnitude()).move_to(list_norm[p1]); + _cimg_mp_constant(*list_norm[p1]); + } + _cimg_mp_scalar1(mp_list_norm,arg1); + } + + switch (*ss1) { + case 'm' : arg2 = 0; break; // im#ind + case 'M' : arg2 = 1; break; // iM#ind + case 'a' : arg2 = 2; break; // ia#ind + case 'v' : arg2 = 3; break; // iv#ind + case 's' : arg2 = 12; break; // is#ind + case 'p' : arg2 = 13; break; // ip#ind + } + } else if (*ss1=='m') switch (*ss) { + case 'x' : arg2 = 4; break; // xm#ind + case 'y' : arg2 = 5; break; // ym#ind + case 'z' : arg2 = 6; break; // zm#ind + case 'c' : arg2 = 7; break; // cm#ind + } else if (*ss1=='M') switch (*ss) { + case 'x' : arg2 = 8; break; // xM#ind + case 'y' : arg2 = 9; break; // yM#ind + case 'z' : arg2 = 10; break; // zM#ind + case 'c' : arg2 = 11; break; // cM#ind + } + if (arg2!=~0U) { + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_stats) list_stats.assign(listin._width); + if (!list_stats[p1]) list_stats[p1].assign(1,14,1,1,0).fill(listin[p1].get_stats(),false); + _cimg_mp_constant(list_stats(p1,arg2)); + } + _cimg_mp_scalar2(mp_list_stats,arg1,arg2); + } + } + + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='#' && ss4 error. + c1 = *se1; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + if (is_sth) + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Undefined variable '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + s1 = std::strchr(ss,'('); + s_op = s1 && c1==')'?"function call":"item"; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unrecognized %s '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + s_op,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Evaluation procedure. + double operator()(const double x, const double y, const double z, const double c) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = code; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + return *result; + } + + // Evaluation procedure (return output values in vector 'output'). + template + void operator()(const double x, const double y, const double z, const double c, t *const output) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = code; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + if (result_dim) { + const double *ptrs = result + 1; + t *ptrd = output; + for (unsigned int k = 0; k_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + p_code_end = code.end(); + } + + // Evaluation procedure for end_t() bloc. + void end_t() { + if (!code_end_t) return; + if (imgin) { + mem[_cimg_mp_slot_x] = imgin._width - 1.; + mem[_cimg_mp_slot_y] = imgin._height - 1.; + mem[_cimg_mp_slot_z] = imgin._depth - 1.; + mem[_cimg_mp_slot_c] = imgin._spectrum - 1.; + } else mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_end_t.end(); + for (p_code = code_end_t; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + + // Evaluation procedure the end() bloc. + void end() { + if (!code_end) return; + if (imgin) { + mem[_cimg_mp_slot_x] = imgin._width - 1.; + mem[_cimg_mp_slot_y] = imgin._height - 1.; + mem[_cimg_mp_slot_z] = imgin._depth - 1.; + mem[_cimg_mp_slot_c] = imgin._spectrum - 1.; + } else mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_end.end(); + for (p_code = code_end; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + + // Merge inter-thread variables. + // (argument 'mp' is the master instance). + void merge(_cimg_math_parser& mp) { + if (&mp==this) return; + cimg_rofY(mp.memmerge,k) { + const unsigned int + pos = (unsigned int)mp.memmerge(0,k), + siz = (unsigned int)mp.memmerge(1,k), + iop = (unsigned int)mp.memmerge(2,k); + if (!siz) switch (iop) { // Scalar value + case 0 : mp.mem[pos] = mem[pos]; break; // Assignment + case 1 : mp.mem[pos]+=mem[pos]; break; // Operator+ + case 2 : mp.mem[pos]-=mem[pos]; break; // Operator- + case 3 : mp.mem[pos]*=mem[pos]; break; // Operator* + case 4 : mp.mem[pos]/=mem[pos]; break; // Operator/ + case 5 : mp.mem[pos] = std::min(mp.mem[pos],mem[pos]); break; // Operator 'min' + case 6 : mp.mem[pos] = std::max(mp.mem[pos],mem[pos]); break; // Operator 'max' + } else switch (iop) { // Vector value + case 0 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true) = CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 1 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)+=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 2 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)-=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 3 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)*=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 4 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)/=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 5 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true).min(CImg(&mem[pos + 1],siz,1,1,1,true)); + break; + case 6 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true).max(CImg(&mem[pos + 1],siz,1,1,1,true)); + break; + } + } + } + + // Return specified argument number as a string. + static const char *s_argth(const unsigned int n_arg) { + const char + *_s_arg[] = { "", "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth","Ninth", + "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", + "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "One of the" }; + return _s_arg[n_arg s_calling_function() const { + CImg res; + const unsigned int + l1 = calling_function?(unsigned int)std::strlen(calling_function):0U, + l2 = user_macro?(unsigned int)std::strlen(user_macro):0U; + if (l2) { + res.assign(l1 + l2 + 48); + cimg_snprintf(res,res._width,"%s(): When substituting function '%s()'",calling_function,user_macro); + } else { + res.assign(l1 + l2 + 4); + cimg_snprintf(res,res._width,"%s()",calling_function); + } + return res; + } + + // Return type of a memory element as a string. + CImg s_type(const unsigned int arg) const { + CImg res; + if (_cimg_mp_is_vector(arg)) { // Vector + CImg::string("vectorXXXXXXXXXXXXXXXX").move_to(res); + cimg_sprintf(res._data + 6,"%u",_cimg_mp_size(arg)); + } else if (_cimg_mp_is_constant(arg)) CImg::string("const scalar").move_to(res); // Const scalar + else CImg::string("scalar").move_to(res); // Scalar + return res; + } + + // Count parentheses/brackets level of each character of the expression. + CImg get_level(CImg& _expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res(_expr._width - 1); + unsigned int *pd = res._data; + int _level = 0; + for (const char *ps = _expr._data; *ps && _level>=0; ++ps) { + if (!is_escaped && !next_is_escaped && *ps=='\\') next_is_escaped = true; + if (!is_escaped && *ps=='\'') { // Non-escaped character + if (!mode && ps>_expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string + else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string + else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string + } + *(pd++) = (unsigned int)(mode>=1 || is_escaped?_level + (mode==1): + *ps=='(' || *ps=='['?_level++: + *ps==')' || *ps==']'?--_level: + _level); + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + if (mode) { + cimg::strellipsize(_expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unterminated string literal, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + _expr._data); + } + if (_level) { + cimg::strellipsize(_expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unbalanced parentheses/brackets, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + _expr._data); + } + return res; + } + + // Find and return index of current image 'imgin' within image list 'listin'. + unsigned int get_mem_img_index() { + if (mem_img_index==~0U) { + if (&imgout>listout.data() && &imgout='0' && c2<='9') rp = 20 + c2 - '0'; // i0...i9 + else if (c2=='m') rp = 4; // im + else if (c2=='M') rp = 5; // iM + else if (c2=='a') rp = 6; // ia + else if (c2=='v') rp = 7; // iv + else if (c2=='s') rp = 8; // is + else if (c2=='p') rp = 9; // ip + else if (c2=='c') rp = 10; // ic + else if (c2=='n') rp = 11; // in + } else if (c2=='m') { + if (c1=='x') rp = 12; // xm + else if (c1=='y') rp = 13; // ym + else if (c1=='z') rp = 14; // zm + else if (c1=='c') rp = 15; // cm + } else if (c2=='M') { + if (c1=='x') rp = 16; // xM + else if (c1=='y') rp = 17; // yM + else if (c1=='z') rp = 18; // zM + else if (c1=='c') rp = 19; // cM + } + } else if (variable_name[1] && variable_name[2] && !variable_name[3]) { // Three-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + if (c1=='w' && c2=='h' && c3=='d') rp = 1; // whd + } else if (variable_name[1] && variable_name[2] && variable_name[3] && + !variable_name[4]) { // Four-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + c4 = variable_name[3]; + if (c1=='w' && c2=='h' && c3=='d' && c4=='s') rp = 2; // whds + } else if (!std::strcmp(variable_name,"interpolation")) rp = 30; // interpolation + else if (!std::strcmp(variable_name,"boundary")) rp = 31; // boundary + + if (rp!=~0U) { rpos = rp; return; } // One of the reserved labels + + // Multi-char variable name : check for existing variable with same name + cimglist_for(variable_def,i) + if (!std::strcmp(variable_name,variable_def[i])) { pos = i; break; } + } + + // Tell for each character of an expression if it is inside a string or not. + CImg is_inside_string(CImg& _expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res = CImg::string(_expr); + bool *pd = res._data; + for (const char *ps = _expr._data; *ps; ++ps) { + if (!next_is_escaped && *ps=='\\') next_is_escaped = true; + if (!is_escaped && *ps=='\'') { // Non-escaped character + if (!mode && ps>_expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string + else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string + else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string + } + *(pd++) = mode>=1 || is_escaped; + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + return res; + } + + // Return true if specified argument can be a part of an allowed variable name. + bool is_varchar(const char c) const { + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; + } + + // Return true if specified argument can be considered as a variable name. + bool is_varname(const char *const str, const unsigned int length=~0U) const { + if (*str>='0' && *str<='9') return false; + for (unsigned int l = 0; l128) return false; + const int *ptr = memtype.data(arg + 1); + bool is_tmp = true; + while (siz-->0) if (*(ptr++)) { is_tmp = false; break; } + return is_tmp; + } + + // Check if a memory slot is a positive integer constant scalar value. + // 'mode' can be: + // { 0=constant | 1=integer constant | 2=positive integer constant | 3=strictly-positive integer constant } + void check_constant(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,1,0); + if (!(_cimg_mp_is_constant(arg) && + (!mode || (double)(int)mem[arg]==mem[arg]) && + (mode<2 || mem[arg]>=(mode==3)))) { + const char *const s_arg = s_argth(n_arg); + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') is not a%s constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_arg?" argument":" Argument",s_type(arg)._data, + !mode?"":mode==1?"n integer": + mode==2?" positive integer":" strictly positive integer", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check if an image index is a constant value. + void check_constant_index(const unsigned int arg, + char *const ss, char *const se, const char saved_char) { + if (arg!=~0U && !_cimg_mp_is_constant(arg)) { + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s Specified image index is not a constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check a matrix is square. + void check_matrix_square(const unsigned int arg, const unsigned int n_arg, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,2,0); + const unsigned int + siz = _cimg_mp_size(arg), + n = (unsigned int)cimg::round(std::sqrt((float)siz)); + if (n*n!=siz) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand":"Right-hand"; + else s_arg = !n_arg?"":n_arg==1?"First":n_arg==2?"Second":n_arg==3?"Third":"One"; + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') " + "cannot be considered as a square matrix, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?" argument":" Argument"):(*s_arg?" operand":" Operand"), + s_type(arg)._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check type compatibility for one argument. + // Bits of 'mode' tells what types are allowed: + // { 1 = scalar | 2 = vectorN }. + // If 'N' is not zero, it also restricts the vectors to be of size N only. + void check_type(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, const unsigned int N, + char *const ss, char *const se, const char saved_char) { + const bool + is_scalar = _cimg_mp_is_scalar(arg), + is_vector = _cimg_mp_is_vector(arg) && (!N || _cimg_mp_size(arg)==N); + bool cond = false; + if (mode&1) cond|=is_scalar; + if (mode&2) cond|=is_vector; + if (!cond) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand":"Right-hand"; + else s_arg = s_argth(n_arg); + CImg sb_type(32); + if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'"); + else if (mode==2) { + if (N) cimg_snprintf(sb_type,sb_type._width,"'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'vector'"); + } else { + if (N) cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector'"); + } + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s has invalid type '%s' (should be %s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?" argument":" Argument"):(*s_arg?" operand":" Operand"), + s_type(arg)._data,sb_type._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check that listin or listout are not empty. + void check_list(const bool is_out, + char *const ss, char *const se, const char saved_char) { + if ((!is_out && !listin) || (is_out && !listout)) { + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s Invalid call with an empty image list, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Insert constant value in memory. + unsigned int constant(const double val) { + + // Search for built-in constant. + if (cimg::type::is_nan(val)) return _cimg_mp_slot_nan; + if (val==(double)(int)val) { + if (val>=0 && val<=10) return (unsigned int)val; + if (val<0 && val>=-5) return (unsigned int)(10 - val); + } + if (val==0.5) return 16; + + // Search for constant already requested before (in const cache). + unsigned int ind = ~0U; + if (constcache_size<1024) { + if (!constcache_size) { + constcache_vals.assign(16,1,1,1,0); + constcache_inds.assign(16,1,1,1,0); + *constcache_vals = val; + constcache_size = 1; + ind = 0; + } else { // Dichotomic search + const double val_beg = *constcache_vals, val_end = constcache_vals[constcache_size - 1]; + if (val_beg>=val) ind = 0; + else if (val_end==val) ind = constcache_size - 1; + else if (val_end=constcache_size || constcache_vals[ind]!=val) { + ++constcache_size; + if (constcache_size>constcache_vals._width) { + constcache_vals.resize(-200,1,1,1,0); + constcache_inds.resize(-200,1,1,1,0); + } + const int l = constcache_size - (int)ind - 1; + if (l>0) { + std::memmove(&constcache_vals[ind + 1],&constcache_vals[ind],l*sizeof(double)); + std::memmove(&constcache_inds[ind + 1],&constcache_inds[ind],l*sizeof(unsigned int)); + } + constcache_vals[ind] = val; + constcache_inds[ind] = 0; + } + } + if (constcache_inds[ind]) return constcache_inds[ind]; + } + + // Insert new constant in memory if necessary. + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(-200,1,1,1,0); } + const unsigned int pos = mempos++; + mem[pos] = val; + memtype[pos] = 1; // Set constant property + if (ind!=~0U) constcache_inds[ind] = pos; + return pos; + } + + // Insert new scalar in memory. + unsigned int scalar() { + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(mem._width,1,1,1,0); } + return mempos++; + } + + // Insert new vector of specified size in memory. + unsigned int vector(const unsigned int siz) { + if (mempos + siz>=mem._width) { + mem.resize(2*mem._width + siz,1,1,1,0); + memtype.resize(mem._width,1,1,1,0); + } + const unsigned int pos = mempos++; + mem[pos] = cimg::type::nan(); + memtype[pos] = siz + 1; + mempos+=siz; + return pos; + } + + // Insert new initialized vector. + unsigned int vector(const unsigned int siz, const double value) { + const unsigned int pos = vector(siz); + double *ptr = &mem[pos] + 1; + for (unsigned int i = 0; i::vector((ulongT)mp_vector_copy,pos,arg,siz).move_to(code); + return pos; + } + + // Set reserved status to all values of a vector. + void set_reserved_vector(const unsigned int arg) { + unsigned int siz = _cimg_mp_size(arg); + int *ptr = memtype.data(arg + 1); + while (siz-->0) *(ptr++) = -1; + } + + unsigned int scalar0(const mp_func op) { + const unsigned int pos = scalar(); + CImg::vector((ulongT)op,pos).move_to(code); + return_new_comp = true; + return pos; + } + + unsigned int scalar1(const mp_func op, const unsigned int arg1) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1) && op!=mp_copy?arg1: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1).move_to(code); + return pos; + } + + unsigned int scalar2(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2).move_to(code); + return pos; + } + + unsigned int scalar3(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3).move_to(code); + return pos; + } + + unsigned int scalar4(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4).move_to(code); + return pos; + } + + unsigned int scalar5(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5).move_to(code); + return pos; + } + + unsigned int scalar6(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code); + return pos; + } + + unsigned int scalar7(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6, + const unsigned int arg7) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + arg7!=~0U && arg7>_cimg_mp_slot_c && _cimg_mp_is_comp(arg7)?arg7: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6,arg7).move_to(code); + return pos; + } + + void self_vector_s(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_s,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1).move_to(code[code._width - 1 - siz + k]); + } + } + + void self_vector_v(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + } + + unsigned int vector1_v(const mp_func op, const unsigned int arg1) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_vv(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1:is_comp_vector(arg2)?arg2: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_vs(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vs,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_sv(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg2), + pos = is_comp_vector(arg2)?arg2: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_sv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector3_vss(const mp_func op, const unsigned int arg1, const unsigned int arg2, + const unsigned int arg3) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vss,pos,siz,(ulongT)op,arg1,arg2,arg3).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2,arg3).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + // Evaluation functions, known by the parser. + // Defining these functions 'static' ensures that sizeof(mp_func)==sizeof(ulongT), + // so we can store pointers to them directly in the opcode vectors. +#ifdef _mp_arg +#undef _mp_arg +#endif +#define _mp_arg(x) mp.mem[mp.opcode[x]] + + static double mp_abs(_cimg_math_parser& mp) { + return cimg::abs(_mp_arg(2)); + } + + static double mp_add(_cimg_math_parser& mp) { + return _mp_arg(2) + _mp_arg(3); + } + + static double mp_acos(_cimg_math_parser& mp) { + return std::acos(_mp_arg(2)); + } + + static double mp_acosh(_cimg_math_parser& mp) { + return cimg::acosh(_mp_arg(2)); + } + + static double mp_asinh(_cimg_math_parser& mp) { + return cimg::asinh(_mp_arg(2)); + } + + static double mp_atanh(_cimg_math_parser& mp) { + return cimg::atanh(_mp_arg(2)); + } + + static double mp_arg(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:(unsigned int)_ind, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_arg0(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:_ind + 1U, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_argkth(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = mp_kth(mp); + for (unsigned int i = 4; ival) { val = _val; argval = i - 3; } + } + return (double)argval; + } + + static double mp_argmaxabs(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3), absval = cimg::abs(val); + unsigned int argval = 0; + for (unsigned int i = 4; iabsval) { val = _val; absval = _absval; argval = i - 3; } + } + return (double)argval; + } + + static double mp_asin(_cimg_math_parser& mp) { + return std::asin(_mp_arg(2)); + } + + static double mp_atan(_cimg_math_parser& mp) { + return std::atan(_mp_arg(2)); + } + + static double mp_atan2(_cimg_math_parser& mp) { + return std::atan2(_mp_arg(2),_mp_arg(3)); + } + + static double mp_avg(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i>(unsigned int)_mp_arg(3)); + } + + static double mp_bitwise_xor(_cimg_math_parser& mp) { + return (double)((longT)_mp_arg(2) ^ (longT)_mp_arg(3)); + } + + static double mp_bool(_cimg_math_parser& mp) { + return (double)(bool)_mp_arg(2); + } + + static double mp_break(_cimg_math_parser& mp) { + mp.break_type = 1; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_breakpoint(_cimg_math_parser& mp) { + cimg_abort_init; + cimg_abort_test; + cimg::unused(mp); + return cimg::type::nan(); + } + +#ifdef cimg_mp_func_run + static double mp_run(_cimg_math_parser& mp) { + const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2; + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(3 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + CImg(1,1,1,1,0).move_to(_str); + CImg str = _str>'x'; + cimg_mp_func_run(str._data); + return cimg::type::nan(); + } +#endif + + static double mp_cbrt(_cimg_math_parser& mp) { + return cimg::cbrt(_mp_arg(2)); + } + + static double mp_ceil(_cimg_math_parser& mp) { + return std::ceil(_mp_arg(2)); + } + + static double mp_complex_abs(_cimg_math_parser& mp) { + return cimg::_hypot(_mp_arg(2),_mp_arg(3)); + } + + static double mp_complex_conj(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = real; + ptrd[1] = -imag; + return cimg::type::nan(); + } + + static double mp_complex_div_sv(_cimg_math_parser& mp) { + const double + *ptr2 = &_mp_arg(3) + 1, + r1 = _mp_arg(2), + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = r1*r2/denom; + *ptrd = -r1*i2/denom; + return cimg::type::nan(); + } + + static double mp_complex_div_vv(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = (r1*r2 + i1*i2)/denom; + *ptrd = (r2*i1 - r1*i2)/denom; + return cimg::type::nan(); + } + + static double mp_complex_exp(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), exp_real = std::exp(real); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = exp_real*std::cos(imag); + ptrd[1] = exp_real*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_log(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = 0.5*std::log(real*real + imag*imag); + ptrd[1] = std::atan2(imag,real); + return cimg::type::nan(); + } + + static double mp_complex_mul(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + *(ptrd++) = r1*r2 - i1*i2; + *(ptrd++) = r1*i2 + r2*i1; + return cimg::type::nan(); + } + + static void _mp_complex_pow(const double r1, const double i1, + const double r2, const double i2, + double *ptrd) { + double ro, io; + if (cimg::abs(i2)<1e-15) { // Exponent is real + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) { + if (cimg::abs(r2)<1e-15) { ro = 1; io = 0; } + else ro = io = 0; + } else { + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2), + phio = r2*phi1; + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + } else { // Exponent is complex + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) ro = io = 0; + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2)*std::exp(-i2*phi1), + phio = r2*phi1 + 0.5*i2*std::log(mod1_2); + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + *(ptrd++) = ro; + *ptrd = io; + } + + static double mp_complex_pow_ss(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_sv(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vs(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vv(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_cos(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::cos(real)*std::cosh(imag); + ptrd[1] = -std::sin(real)*std::sinh(imag); + return cimg::type::nan(); + } + + static double mp_complex_sin(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sin(real)*std::cosh(imag); + ptrd[1] = std::cos(real)*std::sinh(imag); + return cimg::type::nan(); + } + + static double mp_complex_tan(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), denom = std::cos(2*real) + std::cosh(2*imag); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sin(2*real)/denom; + ptrd[1] = std::sinh(2*imag)/denom; + return cimg::type::nan(); + } + + static double mp_complex_cosh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::cosh(real)*std::cos(imag); + ptrd[1] = std::sinh(real)*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_sinh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sinh(real)*std::cos(imag); + ptrd[1] = std::cosh(real)*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_tanh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), denom = std::cosh(2*real) + std::cos(2*imag); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sinh(2*real)/denom; + ptrd[1] = std::sin(2*imag)/denom; + return cimg::type::nan(); + } + + static double mp_continue(_cimg_math_parser& mp) { + mp.break_type = 2; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_convolve(_cimg_math_parser &mp) { + return _mp_correlate(mp,true); + } + + static double mp_copy(_cimg_math_parser& mp) { + return _mp_arg(2); + } + + static double mp_correlate(_cimg_math_parser &mp) { + return _mp_correlate(mp,false); + } + + static double _mp_correlate(_cimg_math_parser &mp, bool is_convolve) { + double *ptrd = &_mp_arg(1) + 1; + const double *const ptrA = &_mp_arg(2) + 1, *const ptrM = &_mp_arg(7) + 1; + const unsigned int + wA = (unsigned int)mp.opcode[3], + hA = (unsigned int)mp.opcode[4], + dA = (unsigned int)mp.opcode[5], + sA = (unsigned int)mp.opcode[6], + wM = (unsigned int)mp.opcode[8], + hM = (unsigned int)mp.opcode[9], + dM = (unsigned int)mp.opcode[10], + sM = (unsigned int)mp.opcode[11], + boundary_conditions = (unsigned int)_mp_arg(12), + channel_mode = (unsigned int)mp.opcode[14], + xcenter = (unsigned int)_mp_arg(15), + ycenter = (unsigned int)_mp_arg(16), + zcenter = (unsigned int)_mp_arg(17), + xstart = (unsigned int)mp.opcode[18], + ystart = (unsigned int)mp.opcode[19], + zstart = (unsigned int)mp.opcode[20], + xend = (unsigned int)mp.opcode[21], + yend = (unsigned int)mp.opcode[22], + zend = (unsigned int)mp.opcode[23]; + const bool + is_normalized = (bool)_mp_arg(13); + const float + xstride = (float)_mp_arg(24), + ystride = (float)_mp_arg(25), + zstride = (float)_mp_arg(26), + xdilation = (float)_mp_arg(27), + ydilation = (float)_mp_arg(28), + zdilation = (float)_mp_arg(29); + CImg res; + if (is_convolve) res = CImg(ptrA,wA,hA,dA,sA,true). + get_convolve(CImg(ptrM,wM,hM,dM,sM,true), + boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter, + xstart,ystart,zstart, + xend,yend,zend, + xstride,ystride,zstride, + xdilation,ydilation,zdilation); + else res = CImg(ptrA,wA,hA,dA,sA,true). + get_correlate(CImg(ptrM,wM,hM,dM,sM,true), + boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter, + xstart,ystart,zstart, + xend,yend,zend, + xstride,ystride,zstride, + xdilation,ydilation,zdilation); + CImg(ptrd,res._width,res._height,res._depth,res._spectrum,true) = res; + return cimg::type::nan(); + } + + static double mp_cos(_cimg_math_parser& mp) { + return std::cos(_mp_arg(2)); + } + + static double mp_cosh(_cimg_math_parser& mp) { + return std::cosh(_mp_arg(2)); + } + + static double mp_critical(_cimg_math_parser& mp) { + const ulongT g_target = mp.opcode[1]; + cimg_pragma_openmp(critical(mp_critical)) + { + for (const CImg *const p_end = ++mp.p_code + mp.opcode[2]; + mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const unsigned int + dx = (unsigned int)mp.opcode[7], + dy = (unsigned int)mp.opcode[8], + dz = (unsigned int)mp.opcode[9], + dc = (unsigned int)mp.opcode[10]; + const unsigned int boundary_conditions = (unsigned int)_mp_arg(11); + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgin:mp.listin[ind]; + if (!img) std::memset(ptrd,0,dx*dy*dz*dc*sizeof(double)); + else CImg(ptrd,dx,dy,dz,dc,true) = img.get_crop(x,y,z,c, + x + dx - 1,y + dy - 1, + z + dz - 1,c + dc - 1, + boundary_conditions); + return cimg::type::nan(); + } + + static double mp_cross(_cimg_math_parser& mp) { + CImg + vout(&_mp_arg(1) + 1,1,3,1,1,true), + v1(&_mp_arg(2) + 1,1,3,1,1,true), + v2(&_mp_arg(3) + 1,1,3,1,1,true); + (vout = v1).cross(v2); + return cimg::type::nan(); + } + + static double mp_cut(_cimg_math_parser& mp) { + double val = _mp_arg(2), cmin = _mp_arg(3), cmax = _mp_arg(4); + return valcmax?cmax:val; + } + + static double mp_date(_cimg_math_parser& mp) { + const unsigned int + siz_out = (unsigned int)mp.opcode[2], + siz_arg1 = (unsigned int)mp.opcode[4], + siz_arg2 = (unsigned int)mp.opcode[6]; + double *ptr_out = &_mp_arg(1) + (siz_out?1:0); + const double + *ptr_arg1 = siz_arg1==~0U?0:&_mp_arg(3) + (siz_arg1?1:0), + *ptr_arg2 = siz_arg2==~0U?0:&_mp_arg(5) + 1; + + if (!ptr_arg2) { // No filename specified + if (!siz_arg1) return cimg::date((unsigned int)*ptr_arg1); + if (siz_arg1==~0U) for (unsigned int k = 0; k::nan(); + } + + // Filename specified. + CImg ss(siz_arg2 + 1); + cimg_forX(ss,i) ss[i] = (char)ptr_arg2[i]; + ss.back() = 0; + if (!siz_arg1) return cimg::fdate(ss,(unsigned int)*ptr_arg1); + for (unsigned int k = 0; k::nan(); + } + + static double mp_debug(_cimg_math_parser& mp) { + CImg expr(mp.opcode[2] - 4); + { + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + } + cimg::strellipsize(expr); + const ulongT g_target = mp.opcode[1]; + +#if cimg_use_openmp==0 + const unsigned int n_thread = 0; +#else + const unsigned int n_thread = omp_get_thread_num(); +#endif + cimg_pragma_openmp(critical(mp_debug)) + { + std::fprintf(cimg::output(), + "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c" + "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)mp.opcode[3],(unsigned int)g_target,mp.mem._width); + std::fflush(cimg::output()); + mp.debug_indent+=3; + } + const CImg *const p_end = ++mp.p_code + mp.opcode[3]; + CImg _op; + for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + + _op.assign(1,op._height - 1); + const ulongT *ptrs = op._data + 1; + for (ulongT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd mem[%u] = %.17g", + (void*)&mp,n_thread,mp.debug_indent,' ', + (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(), + (unsigned int)target,mp.mem[target]); + std::fflush(cimg::output()); + } + } + cimg_pragma_openmp(critical(mp_debug)) + { + mp.debug_indent-=3; + std::fprintf(cimg::output(), + "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c" + "End debugging expression '%s' -> mem[%u] = %.17g (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width); + std::fflush(cimg::output()); + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_decrement(_cimg_math_parser& mp) { + return _mp_arg(2) - 1; + } + + static double mp_det(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + return CImg(ptrs,k,k,1,1,true).det(); + } + + static double mp_diag(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2], siz = mp.opcode[2] - 3; + double *ptrd = &_mp_arg(1) + 1; + std::memset(ptrd,0,siz*siz*sizeof(double)); + for (unsigned int i = 3; i::nan(); + } + + static double mp_display_memory(_cimg_math_parser& mp) { + cimg::unused(mp); + std::fputc('\n',cimg::output()); + CImg title(128); + cimg_snprintf(title,title._width,"%s (%u)","[" cimg_appname "_math_parser] Memory snapshot",mp.mem._width); + mp.mem.display(title); + return cimg::type::nan(); + } + + static double mp_display(_cimg_math_parser& mp) { + const unsigned int + _siz = (unsigned int)mp.opcode[3], + siz = _siz?_siz:1; + const double *const ptr = &_mp_arg(1) + (_siz?1:0); + const int + w = (int)_mp_arg(4), + h = (int)_mp_arg(5), + d = (int)_mp_arg(6), + s = (int)_mp_arg(7); + CImg img; + if (w>0 && h>0 && d>0 && s>0) { + if ((unsigned int)w*h*d*s<=siz) img.assign(ptr,w,h,d,s,true); + else img.assign(ptr,siz).resize(w,h,d,s,-1); + } else img.assign(ptr,1,siz,1,1,true); + + CImg expr(mp.opcode[2] - 8); + const ulongT *ptrs = mp.opcode._data + 8; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + ((CImg::string("[" cimg_appname "_math_parser] ",false,true),expr)>'x').move_to(expr); + cimg::strellipsize(expr); + std::fputc('\n',cimg::output()); + img.display(expr._data); + return cimg::type::nan(); + } + + static double mp_div(_cimg_math_parser& mp) { + return _mp_arg(2)/_mp_arg(3); + } + + static double mp_dot(_cimg_math_parser& mp) { + const unsigned int siz = (unsigned int)mp.opcode[4]; + return CImg(&_mp_arg(2) + 1,1,siz,1,1,true). + dot(CImg(&_mp_arg(3) + 1,1,siz,1,1,true)); + } + + static double mp_do(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_body = ++mp.p_code, + *const p_cond = p_body + mp.opcode[3], + *const p_end = p_cond + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (mp.mem[mem_cond]); + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_draw(_cimg_math_parser& mp) { + const int x = (int)_mp_arg(4), y = (int)_mp_arg(5), z = (int)_mp_arg(6), c = (int)_mp_arg(7); + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + unsigned int + dx = (unsigned int)mp.opcode[8], + dy = (unsigned int)mp.opcode[9], + dz = (unsigned int)mp.opcode[10], + dc = (unsigned int)mp.opcode[11]; + dx = dx==~0U?img._width:(unsigned int)_mp_arg(8); + dy = dy==~0U?img._height:(unsigned int)_mp_arg(9); + dz = dz==~0U?img._depth:(unsigned int)_mp_arg(10); + dc = dc==~0U?img._spectrum:(unsigned int)_mp_arg(11); + + const ulongT sizS = mp.opcode[2]; + if (sizS<(ulongT)dx*dy*dz*dc) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': " + "Sprite dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + CImg S(&_mp_arg(1) + 1,dx,dy,dz,dc,true); + const float opacity = (float)_mp_arg(12); + + if (img._data) { + if (mp.opcode[13]!=~0U) { // Opacity mask specified + const ulongT sizM = mp.opcode[14]; + if (sizM<(ulongT)dx*dy*dz) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': " + "Mask dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + const CImg M(&_mp_arg(13) + 1,dx,dy,dz,(unsigned int)(sizM/(dx*dy*dz)),true); + img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(15)); + } else img.draw_image(x,y,z,c,S,opacity); + } + return cimg::type::nan(); + } + + static double mp_echo(_cimg_math_parser& mp) { + const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2; + if (!nb_args) { std::fputc('\n',cimg::output()); return cimg::type::nan(); } // No arguments + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(3 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + CImg(1,1,1,1,0).move_to(_str); + const CImg str = _str>'x'; + std::fprintf(cimg::output(),"\n%s",str._data); + return cimg::type::nan(); + } + + static double mp_ellipse(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + CImg color(img._spectrum,1,1,1,0); + bool is_invalid_arguments = false, is_outlined = false; + float r1 = 0, r2 = 0, angle = 0, opacity = 1; + unsigned int i = 4, pattern = ~0U; + int x0 = 0, y0 = 0; + if (i>=i_end) is_invalid_arguments = true; + else { + x0 = (int)cimg::round(_mp_arg(i++)); + if (i>=i_end) is_invalid_arguments = true; + else { + y0 = (int)cimg::round(_mp_arg(i++)); + if (i>=i_end) is_invalid_arguments = true; + else { + r1 = (float)_mp_arg(i++); + if (i>=i_end) r2 = r1; + else { + r2 = (float)_mp_arg(i++); + if (i args(i_end - 4); + cimg_forX(args,k) args[k] = _mp_arg(4 + k); + if (ind==~0U) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'ellipse()': " + "Invalid arguments '%s'. ", + mp.imgin.pixel_type(),args.value_string()._data); + else + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'ellipse()': " + "Invalid arguments '#%u%s%s'. ", + mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data); + } + return cimg::type::nan(); + } + + static double mp_eq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)==_mp_arg(3)); + } + + static double mp_erf(_cimg_math_parser& mp) { + return std::erf(_mp_arg(2)); + } + + static double mp_erfinv(_cimg_math_parser& mp) { + return cimg::erfinv(_mp_arg(2)); + } + + static double mp_exp(_cimg_math_parser& mp) { + return std::exp(_mp_arg(2)); + } + + static double mp_expr(_cimg_math_parser& mp) { + const unsigned int + sizs = (unsigned int)mp.opcode[3], + w = (unsigned int)mp.opcode[4], + h = (unsigned int)mp.opcode[5], + d = (unsigned int)mp.opcode[6], + s = (unsigned int)mp.opcode[7], + sizd = w*h*d*s; + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1); + CImg ss(sizs + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + if (!sizd) return CImg(w,h,d,s,0).eval(ss,0,0,0,0,&mp.listin,&mp.listout); // Scalar result + CImg(++ptrd,w,h,d,s,true) = CImg(w,h,d,s,0).fill(ss,true,true,&mp.listin,&mp.listout); + return cimg::type::nan(); + } + + static double mp_eye(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int k = (unsigned int)mp.opcode[2]; + CImg(ptrd,k,k,1,1,true).identity_matrix(); + return cimg::type::nan(); + } + + static double mp_f2ui(_cimg_math_parser& mp) { + return (double)cimg::float2uint((float)_mp_arg(2)); + } + + static double mp_factorial(_cimg_math_parser& mp) { + return cimg::factorial((int)_mp_arg(2)); + } + + static double mp_fibonacci(_cimg_math_parser& mp) { + return cimg::fibonacci((int)_mp_arg(2)); + } + + static double mp_fill(_cimg_math_parser& mp) { + unsigned int siz = (unsigned int)mp.opcode[2]; + double + *ptrd = &_mp_arg(1), + *const ptrc = mp.opcode[3]!=~0U?&_mp_arg(3):0, + *const ptrs = &_mp_arg(4); + if (siz) ++ptrd; else ++siz; // Fill vector-valued slot + const CImg + *const p_body = ++mp.p_code, + *const p_end = p_body + mp.opcode[5]; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + unsigned int it = 0; + if (ptrc) { // Version with loop variable (3 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + else ptrd[it] = *ptrs; + ++it; + } + *ptrc = (double)it; + } else // Version without loop variable (2 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + else ptrd[it] = *ptrs; + ++it; + } + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return *ptrd; + } + + static double mp_find(_cimg_math_parser& mp) { + const int _step = (int)_mp_arg(6), step = _step?_step:-1; + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):step>0?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const double + *const ptrb = &_mp_arg(2) + 1, + *const ptre = ptrb + siz, + val = _mp_arg(4), + *ptr = ptrb + ind; + + // Forward search + if (step>0) { + while (ptr=ptre?-1.:(double)(ptr - ptrb); + } + + // Backward search. + while (ptr>=ptrb && *ptr!=val) ptr+=step; + return ptr0?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const double + *const ptr1b = &_mp_arg(2) + 1, + *const ptr1e = ptr1b + siz1, + *const ptr2b = &_mp_arg(4) + 1, + *const ptr2e = ptr2b + siz2, + *ptr1 = ptr1b + ind, + *p1 = 0, + *p2 = 0; + + // Forward search. + if (step>0) { + do { + while (ptr1=ptr1e) return -1.; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b && *ptr1!=*ptr2b) ptr1+=step; + if (ptr1=ptr1b); + return p2 + *const p_init = ++mp.p_code, + *const p_cond = p_init + mp.opcode[4], + *const p_body = p_cond + mp.opcode[5], + *const p_post = p_body + mp.opcode[6], + *const p_end = p_post + mp.opcode[7]; + const unsigned int vsiz = (unsigned int)mp.opcode[2]; + bool is_cond = false; + if (mp.opcode[8]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[9]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + for (mp.p_code = p_init; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + + if (!mp.break_type) do { + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) { + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + + for (mp.p_code = p_post; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_fsize(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const ulongT siz = (ulongT)mp.opcode[3]; + CImg ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::fsize(ss); + } + + static double mp_g(_cimg_math_parser& mp) { + cimg::unused(mp); + return cimg::grand(&mp.rng); + } + + static double mp_gauss(_cimg_math_parser& mp) { + const double x = _mp_arg(2), s = _mp_arg(3); + return std::exp(-x*x/(2*s*s))/(_mp_arg(4)?std::sqrt(2*s*s*cimg::PI):1); + } + +#ifdef cimg_mp_func_get + static double mp_get(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1); + const unsigned int + sizs = (unsigned int)mp.opcode[3], + sizd = (unsigned int)mp.opcode[4]; + const bool to_string = (bool)mp.opcode[5]; + CImg ss(sizs + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + if (sizd) cimg_mp_func_get(ptrd + 1,sizd,to_string,ss._data); + else cimg_mp_func_get(ptrd,0,to_string,ss._data); + return cimg::type::nan(); + } +#endif + + static double mp_gcd(_cimg_math_parser& mp) { + return cimg::gcd((long)_mp_arg(2),(long)_mp_arg(3)); + } + +#ifdef cimg_mp_func_name + static double mp_name(_cimg_math_parser& mp) { + double *const ptr = &_mp_arg(1) + 1; + const unsigned int siz = (unsigned int)mp.opcode[3]; + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind==~0U) std::memset(ptr,0,siz*sizeof(double)); + else { + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + cimg_mp_func_name(ind,ptr,siz); + } + return cimg::type::nan(); + } +#endif + + static double mp_gt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>_mp_arg(3)); + } + + static double mp_gte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>=_mp_arg(3)); + } + + static double mp_i(_cimg_math_parser& mp) { + return (double)mp.imgin.atXYZC((int)mp.mem[_cimg_mp_slot_x],(int)mp.mem[_cimg_mp_slot_y], + (int)mp.mem[_cimg_mp_slot_z],(int)mp.mem[_cimg_mp_slot_c],(T)0); + } + + static double mp_if(_cimg_math_parser& mp) { + const bool is_cond = (bool)_mp_arg(2); + const ulongT + mem_left = mp.opcode[3], + mem_right = mp.opcode[4]; + const CImg + *const p_right = ++mp.p_code + mp.opcode[5], + *const p_end = p_right + mp.opcode[6]; + const unsigned int vtarget = (unsigned int)mp.opcode[1], vsiz = (unsigned int)mp.opcode[7]; + if (is_cond) for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + else for (mp.p_code = p_right; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.p_code==mp.p_break) --mp.p_code; + else mp.p_code = p_end - 1; + if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[is_cond?mem_left:mem_right] + 1,sizeof(double)*vsiz); + return mp.mem[is_cond?mem_left:mem_right]; + } + + static double mp_image_d(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.depth(); + } + + static double mp_image_display(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + CImg title(256); + std::fputc('\n',cimg::output()); + cimg_snprintf(title,title._width,"[ Image #%u ]",ind); + img.display(title); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_h(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.height(); + } + + static double mp_image_median(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.median(); + } + + static double mp_image_norm(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.magnitude(); + } + + static double mp_image_print(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + CImg title(256); + std::fputc('\n',cimg::output()); + cimg_snprintf(title,title._width,"[ Image #%u ]",ind); + img.print(title); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_resize(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + const double + _w = mp.opcode[3]==~0U?-100:_mp_arg(3), + _h = mp.opcode[4]==~0U?-100:_mp_arg(4), + _d = mp.opcode[5]==~0U?-100:_mp_arg(5), + _s = mp.opcode[6]==~0U?-100:_mp_arg(6); + const unsigned int + w = (unsigned int)(_w>=0?_w:-_w*img.width()/100), + h = (unsigned int)(_h>=0?_h:-_h*img.height()/100), + d = (unsigned int)(_d>=0?_d:-_d*img.depth()/100), + s = (unsigned int)(_s>=0?_s:-_s*img.spectrum()/100), + interp = (int)_mp_arg(7); + if (mp.is_fill && img._data==mp.imgout._data) { + cimg::mutex(6,0); + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'resize()': " + "Cannot both fill and resize image (%u,%u,%u,%u) " + "to new dimensions (%u,%u,%u,%u).", + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,w,h,d,s); + } + const unsigned int + boundary = (int)_mp_arg(8); + const float + cx = (float)_mp_arg(9), + cy = (float)_mp_arg(10), + cz = (float)_mp_arg(11), + cc = (float)_mp_arg(12); + img.resize(w,h,d,s,interp,boundary,cx,cy,cz,cc); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_s(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.spectrum(); + } + + static double mp_image_sort(_cimg_math_parser& mp) { + const bool is_increasing = (bool)_mp_arg(3); + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()), + axis = (unsigned int)_mp_arg(4); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + img.sort(is_increasing, + axis==0 || axis=='x'?'x': + axis==1 || axis=='y'?'y': + axis==2 || axis=='z'?'z': + axis==3 || axis=='c'?'c':0); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_stats(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind==~0U) CImg(ptrd,14,1,1,1,true) = mp.imgout.get_stats(); + else { + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg(ptrd,14,1,1,1,true) = mp.listout[ind].get_stats(); + } + return cimg::type::nan(); + } + + static double mp_image_w(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width(); + } + + static double mp_image_wh(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height(); + } + + static double mp_image_whd(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height()*img.depth(); + } + + static double mp_image_whds(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height()*img.depth()*img.spectrum(); + } + + static double mp_increment(_cimg_math_parser& mp) { + return _mp_arg(2) + 1; + } + + static double mp_inrange(_cimg_math_parser& mp) { + const unsigned int sizd = (unsigned int)mp.opcode[2]; + const bool + include_m = (bool)_mp_arg(9), + include_M = (bool)_mp_arg(10); + if (!sizd) { // Scalar result + const double val = _mp_arg(3); + const double m = _mp_arg(5), M = _mp_arg(7); + if (M>=m) return (double)((include_m?(val>=m):(val>m)) && (include_M?(val<=M):(val=M):(val>M)) && (include_m?(val<=m):(val=m) + ptrd[k] = (double)((include_m?(val>=m):(val>m)) && (include_M?(val<=M):(val=M):(val>M)) && (include_m?(val<=m):(val::nan(); + } + + static double mp_int(_cimg_math_parser& mp) { + return (double)(longT)_mp_arg(2); + } + + static double mp_ioff(_cimg_math_parser& mp) { + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3); + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off>=0 && off ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::is_directory(ss); + } + + static double mp_isin(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = _mp_arg(3); + for (unsigned int i = 4; i::is_inf(_mp_arg(2)); + } + + static double mp_isint(_cimg_math_parser& mp) { + return (double)((double)(longT)_mp_arg(2)==_mp_arg(2)); + } + + static double mp_isfile(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const ulongT siz = (ulongT)mp.opcode[3]; + CImg ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::is_file(ss); + } + + static double mp_isnan(_cimg_math_parser& mp) { + return (double)cimg::type::is_nan(_mp_arg(2)); + } + + static double mp_ixyzc(_cimg_math_parser& mp) { + const unsigned int + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.imgin; + const double + x = _mp_arg(2), y = _mp_arg(3), + z = _mp_arg(4), c = _mp_arg(5); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx &img = mp.imgin; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), + z = oz + _mp_arg(4), c = oc + _mp_arg(5); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx vals(i_end - 4); + double *p = vals.data(); + for (unsigned int i = 4; i &img = mp.listin[indi]; + const int _step = (int)_mp_arg(5), step = _step?_step:-1; + const ulongT siz = (ulongT)img.size(); + longT ind = (longT)(mp.opcode[4]!=_cimg_mp_slot_nan?_mp_arg(4):step>0?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const T + *const ptrb = img.data(), + *const ptre = img.end(), + *ptr = ptrb + ind; + const double val = _mp_arg(3); + + // Forward search + if (step>0) { + while (ptr=ptre?-1.:(double)(ptr - ptrb); + } + + // Backward search. + while (ptr>=ptrb && (double)*ptr!=val) ptr+=step; + return ptr &img = mp.listin[indi]; + const int _step = (bool)_mp_arg(6), step = _step?_step:-1; + const ulongT + siz1 = (ulongT)img.size(), + siz2 = (ulongT)mp.opcode[4]; + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):step>0?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const T + *const ptr1b = img.data(), + *const ptr1e = ptr1b + siz1, + *ptr1 = ptr1b + ind, + *p1 = 0; + const double + *const ptr2b = &_mp_arg(3) + 1, + *const ptr2e = ptr2b + siz2, + *p2 = 0; + + // Forward search. + if (step>0) { + do { + while (ptr1=ptr1e) return -1.; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b && *ptr1!=*ptr2b) ptr1+=step; + if (ptr1=ptr1b); + return p2 &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.listin[ind]; + const double + x = _mp_arg(3), y = _mp_arg(4), + z = _mp_arg(5), c = _mp_arg(6); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), + z = oz + _mp_arg(5), c = oc + _mp_arg(6); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx::vector(mp.listin[ind].median()).move_to(mp.list_median[ind]); + return *mp.list_median[ind]; + } + + static double mp_list_norm(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + if (!mp.list_norm) mp.list_norm.assign(mp.listin._width); + if (!mp.list_norm[ind]) CImg::vector(mp.listin[ind].magnitude()).move_to(mp.list_norm[ind]); + return *mp.list_norm[ind]; + } + + static double mp_list_set_ioff(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), y = (int)_mp_arg(4), + z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Ixyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_set_Joff_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Jxyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_spectrum(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._spectrum; + } + + static double mp_list_stats(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + k = (unsigned int)mp.opcode[3]; + if (!mp.list_stats) mp.list_stats.assign(mp.listin._width); + if (!mp.list_stats[ind]) mp.list_stats[ind].assign(1,14,1,1,0).fill(mp.listin[ind].get_stats(),false); + return mp.list_stats(ind,k); + } + + static double mp_list_wh(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height; + } + + static double mp_list_whd(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth; + } + + static double mp_list_whds(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth*mp.listin[ind]._spectrum; + } + + static double mp_list_width(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width; + } + + static double mp_list_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4), + vsiz = (unsigned int)mp.opcode[5]; + const CImg &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_list_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7), + vsiz = (unsigned int)mp.opcode[8]; + const CImg &img = mp.listin[ind]; + const double x = _mp_arg(3), y = _mp_arg(4), z = _mp_arg(5); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_list_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4), + vsiz = (unsigned int)mp.opcode[5]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], oz = (int)mp.mem[_cimg_mp_slot_z]; + const CImg &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_list_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7), + vsiz = (unsigned int)mp.opcode[8]; + const CImg &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), z = oz + _mp_arg(5); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_log(_cimg_math_parser& mp) { + return std::log(_mp_arg(2)); + } + + static double mp_log10(_cimg_math_parser& mp) { + return std::log10(_mp_arg(2)); + } + + static double mp_log2(_cimg_math_parser& mp) { + return cimg::log2(_mp_arg(2)); + } + + static double mp_logical_and(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (!val_left) { mp.p_code = p_end - 1; return 0; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_logical_not(_cimg_math_parser& mp) { + return (double)!_mp_arg(2); + } + + static double mp_logical_or(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (val_left) { mp.p_code = p_end - 1; return 1; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_lowercase(_cimg_math_parser& mp) { + return cimg::lowercase(_mp_arg(2)); + } + + static double mp_lt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<_mp_arg(3)); + } + + static double mp_lte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<=_mp_arg(3)); + } + + static double mp_matrix_eig(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + CImg val, vec; + CImg(ptr1,k,k,1,1,true).symmetric_eigen(val,vec); + CImg(ptrd,1,k,1,1,true) = val; + CImg(ptrd + k,k,k,1,1,true) = vec.get_transpose(); + return cimg::type::nan(); + } + + static double mp_matrix_invert(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptr1 = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + const bool use_LU = (bool)_mp_arg(4); + CImg(ptrd,k,k,1,1,true) = CImg(ptr1,k,k,1,1,true).get_invert(use_LU); + return cimg::type::nan(); + } + + static double mp_matrix_mul(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr1,l,k,1,1,true)*CImg(ptr2,m,l,1,1,true); + return cimg::type::nan(); + } + + static double mp_matrix_pseudoinvert(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + const bool use_LU = (bool)_mp_arg(5); + CImg(ptrd,l,k,1,1,true) = CImg(ptr1,k,l,1,1,true).get_pseudoinvert(use_LU); + return cimg::type::nan(); + } + + static double mp_matrix_svd(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg U, S, V; + CImg(ptr1,k,l,1,1,true).SVD(U,S,V); + CImg(ptrd,k,l,1,1,true) = U; + CImg(ptrd + k*l,1,k,1,1,true) = S; + CImg(ptrd + k*l + k,k,k,1,1,true) = V; + return cimg::type::nan(); + } + + static double mp_max(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; iabsval) { val = _val; absval = _absval; } + } + return val; + } + + static double* _mp_memcopy_double(_cimg_math_parser& mp, const unsigned int ind, const ulongT *const p_ref, + const longT siz, const long inc) { + const longT + off = *p_ref?p_ref[1] + (longT)mp.mem[(longT)p_ref[2]] + 1:ind, + eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=mp.mem.width()) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds variable pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %u).", + mp.imgin.pixel_type(),siz,inc,off,eoff,mp.mem._width - 1); + return &mp.mem[off]; + } + + static float* _mp_memcopy_float(_cimg_math_parser& mp, const ulongT *const p_ref, + const longT siz, const long inc, const bool is_out) { + const unsigned ind = (unsigned int)p_ref[1]; + const CImg &img = is_out? + (ind==~0U?mp.imgout:mp.listout[cimg::mod((int)mp.mem[ind],mp.listout.width())]): + (ind==~0U?mp.imgin:mp.listin[cimg::mod((int)mp.mem[ind],mp.listin.width())]); + const bool is_relative = (bool)p_ref[2]; + int ox, oy, oz, oc; + longT off = 0; + if (is_relative) { + ox = (int)mp.mem[_cimg_mp_slot_x]; + oy = (int)mp.mem[_cimg_mp_slot_y]; + oz = (int)mp.mem[_cimg_mp_slot_z]; + oc = (int)mp.mem[_cimg_mp_slot_c]; + off = img.offset(ox,oy,oz,oc); + } + if ((*p_ref)%2) { + const int + x = (int)mp.mem[p_ref[3]], + y = (int)mp.mem[p_ref[4]], + z = (int)mp.mem[p_ref[5]], + c = *p_ref==5?0:(int)mp.mem[p_ref[6]]; + off+=img.offset(x,y,z,c); + } else off+=(longT)mp.mem[p_ref[3]]; + const longT eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=(longT)img.size()) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds image pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %lu).", + mp.imgin.pixel_type(),siz,inc,off,eoff,img.size() - 1); + return (float*)&img[off]; + } + + static double mp_memcopy(_cimg_math_parser& mp) { + longT siz = (longT)_mp_arg(4); + const longT inc_d = (longT)_mp_arg(5), inc_s = (longT)_mp_arg(6); + const float + _opacity = (float)_mp_arg(7), + opacity = (float)cimg::abs(_opacity), + omopacity = 1 - std::max(_opacity,0.f); + if (siz>0) { + const bool + is_doubled = mp.opcode[8]<=1, + is_doubles = mp.opcode[15]<=1; + if (is_doubled && is_doubles) { // (double*) <- (double*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(double)); + else std::memmove(ptrd,ptrs,siz*sizeof(double)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,double) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } else if (is_doubled && !is_doubles) { // (double*) <- (float*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s,false); + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + _opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else if (!is_doubled && is_doubles) { // (float*) <- (double*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d,true); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (_opacity>=1) while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = (float)(omopacity**ptrd + opacity**ptrs); ptrd+=inc_d; ptrs+=inc_s; } + } else { // (float*) <- (float*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d,true); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s,false); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(float)); + else std::memmove(ptrd,ptrs,siz*sizeof(float)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,float) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } + } + return _mp_arg(1); + } + + static double mp_min(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i(ptrd,wS,wD,1,1,true) = CImg(ptrS,wS,hS,1,1,false). + project_matrix(CImg(ptrD,wD,hS,1,1,true),method,max_iter,max_residual); + return cimg::type::nan(); + } + + static double mp_mul(_cimg_math_parser& mp) { + return _mp_arg(2)*_mp_arg(3); + } + + static double mp_mul2(_cimg_math_parser& mp) { + return _mp_arg(2)*_mp_arg(3)*_mp_arg(4); + } + + static double mp_neq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)!=_mp_arg(3)); + } + + static double mp_norm0(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + switch (i_end - 3) { + case 1 : return _mp_arg(3)!=0; + case 2 : return (_mp_arg(3)!=0) + (_mp_arg(4)!=0); + } + double res = 0; + for (unsigned int i = 3; ires) res = val; + } + return res; + } + + static double mp_normp(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + if (i_end==4) return cimg::abs(_mp_arg(3)); + const double p = (double)mp.opcode[3]; + double res = 0; + for (unsigned int i = 4; i0?res:0.; + } + + static double mp_permutations(_cimg_math_parser& mp) { + return cimg::permutations((int)_mp_arg(2),(int)_mp_arg(3),(bool)_mp_arg(4)); + } + + static double mp_polygon(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + bool is_invalid_arguments = i_end<=4, is_outlined = false; + if (!is_invalid_arguments) { + int nbv = (int)_mp_arg(4); + if (!nbv) is_invalid_arguments = true; + else { + if (nbv<0) { nbv = -nbv; is_outlined = true; } + CImg points(nbv,2,1,1,0); + CImg color(img._spectrum,1,1,1,0); + float opacity = 1; + unsigned int i = 5, pattern=~0U; + cimg_foroff(points,k) if (i args(i_end - 4); + cimg_forX(args,k) args[k] = _mp_arg(4 + k); + if (ind==~0U) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': " + "Invalid arguments '%s'. ", + mp.imgin.pixel_type(),args.value_string()._data); + else + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': " + "Invalid arguments '#%u%s%s'. ", + mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data); + } + return cimg::type::nan(); + } + + static double mp_pow(_cimg_math_parser& mp) { + const double v = _mp_arg(2), p = _mp_arg(3); + return std::pow(v,p); + } + + static double mp_pow0_25(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return std::sqrt(std::sqrt(val)); + } + + static double mp_pow3(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val; + } + + static double mp_pow4(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val*val; + } + + static double mp_print(_cimg_math_parser& mp) { + const double val = _mp_arg(1); + const bool print_char = (bool)mp.opcode[3]; + cimg_pragma_openmp(critical(mp_print)) + { + CImg _expr(mp.opcode[2] - 4); + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(_expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(_expr); + cimg::mutex(6); + if (print_char) + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = %.17g = '%c'", + _expr._data,val,(int)val); + else + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = %.17g", + _expr._data,val); + std::fflush(cimg::output()); + cimg::mutex(6,0); + } + return val; + } + + static double mp_prod(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i + *const p_body = ++mp.p_code, + *const p_end = p_body + mp.opcode[4]; + + if (nb_it>0) { + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + double it = 0; + if (ptrc) { // Version with loop variable (3 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + ++it; + } + *ptrc = it; + } else // Version without loop variable (2 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + ++it; + } + mp.break_type = _break_type; + } + + mp.p_code = p_end - 1; + return *ptrs; + } + + static double mp_rol(_cimg_math_parser& mp) { + return cimg::rol(_mp_arg(2),(unsigned int)_mp_arg(3)); + } + + static double mp_ror(_cimg_math_parser& mp) { + return cimg::ror(_mp_arg(2),(unsigned int)_mp_arg(3)); + } + + static double mp_rot2d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float + theta = (float)_mp_arg(2)*cimg::PI/180, + ca = std::cos(theta), + sa = std::sin(theta); + *(ptrd++) = ca; + *(ptrd++) = -sa; + *(ptrd++) = sa; + *ptrd = ca; + return cimg::type::nan(); + } + + static double mp_rot3d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5); + CImg(ptrd,3,3,1,1,true) = CImg::rotation_matrix(x,y,z,theta); + return cimg::type::nan(); + } + + static double mp_round(_cimg_math_parser& mp) { + return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4)); + } + + static double mp_self_add(_cimg_math_parser& mp) { + return _mp_arg(1)+=_mp_arg(2); + } + + static double mp_self_bitwise_and(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val & (longT)_mp_arg(2)); + } + + static double mp_self_bitwise_left_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val<<(unsigned int)_mp_arg(2)); + } + + static double mp_self_bitwise_or(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val | (longT)_mp_arg(2)); + } + + static double mp_self_bitwise_right_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val>>(unsigned int)_mp_arg(2)); + } + + static double mp_self_decrement(_cimg_math_parser& mp) { + return --_mp_arg(1); + } + + static double mp_self_increment(_cimg_math_parser& mp) { + return ++_mp_arg(1); + } + + static double mp_self_map_vector_s(_cimg_math_parser& mp) { // Vector += scalar + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2]; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode[2] = mp.opcode[4]; // Scalar argument + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1]; + while (siz-->0) { target = ptrd++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_map_vector_v(_cimg_math_parser& mp) { // Vector += vector + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1], &argument = mp.opcode[2]; + while (siz-->0) { target = ptrd++; argument = ptrs++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_mul(_cimg_math_parser& mp) { + return _mp_arg(1)*=_mp_arg(2); + } + + static double mp_self_div(_cimg_math_parser& mp) { + return _mp_arg(1)/=_mp_arg(2); + } + + static double mp_self_modulo(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = cimg::mod(val,_mp_arg(2)); + } + + static double mp_self_pow(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = std::pow(val,_mp_arg(2)); + } + + static double mp_self_sub(_cimg_math_parser& mp) { + return _mp_arg(1)-=_mp_arg(2); + } + + static double mp_set_ioff(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + x = (int)_mp_arg(2), y = (int)_mp_arg(3), + z = (int)_mp_arg(4), c = (int)_mp_arg(5); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Ixyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_set_Joff_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Jxyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_shift(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int siz = (unsigned int)mp.opcode[3]; + const int + shift = (int)_mp_arg(4), + boundary_conditions = (int)_mp_arg(5); + CImg(ptrd,siz,1,1,1,true) = CImg(ptrs,siz,1,1,1,true).shift(shift,0,0,0,boundary_conditions); + return cimg::type::nan(); + } + + static double mp_sign(_cimg_math_parser& mp) { + return cimg::sign(_mp_arg(2)); + } + + static double mp_sin(_cimg_math_parser& mp) { + return std::sin(_mp_arg(2)); + } + + static double mp_sinc(_cimg_math_parser& mp) { + return cimg::sinc(_mp_arg(2)); + } + + static double mp_sinh(_cimg_math_parser& mp) { + return std::sinh(_mp_arg(2)); + } + + static double mp_solve(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr2,m,l,1,1,false).solve(CImg(ptr1,k,l,1,1,true)); + return cimg::type::nan(); + } + + static double mp_sort(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const bool is_increasing = (bool)_mp_arg(4); + const unsigned int + siz = (unsigned int)mp.opcode[3], + nb_elts = mp.opcode[5]==~0U?siz:(unsigned int)_mp_arg(5), + siz_elt = (unsigned int)_mp_arg(6); + const ulongT sn = siz_elt*nb_elts; + if (sn>siz || siz_elt<1) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'sort()': " + "Arguments 'nb_elts=%g' and 'siz_elt=%g' are invalid " + "for sorting a vector of size %u.", + mp.imgin.pixel_type(),_mp_arg(5),_mp_arg(6),siz); + CImg(ptrd,siz_elt,nb_elts,1,1,true) = CImg(ptrs,siz_elt,nb_elts,1,1,true). + get_sort(is_increasing,siz_elt>1?'y':0); + if (sn(ptrd + sn,siz - sn,1,1,1,true) = CImg(ptrs + sn,siz - sn,1,1,1,true); + return cimg::type::nan(); + } + + static double mp_sqr(_cimg_math_parser& mp) { + return cimg::sqr(_mp_arg(2)); + } + + static double mp_sqrt(_cimg_math_parser& mp) { + return std::sqrt(_mp_arg(2)); + } + + static double mp_srand(_cimg_math_parser& mp) { + mp.rng = (cimg_uint64)_mp_arg(2); + return cimg::type::nan(); + } + + static double mp_srand0(_cimg_math_parser& mp) { + cimg::srand(&mp.rng); + +#if cimg_use_openmp!=0 + mp.rng+=omp_get_thread_num(); +#endif + return cimg::type::nan(); + } + + static double mp_std(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i0) mp.mem[ptrd++] = (double)*(ptrs++); + return cimg::type::nan(); + } + +#ifdef cimg_mp_func_store + static double mp_store(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2), + *ptr2 = &_mp_arg(4) + 1; + const unsigned int + siz1 = (unsigned int)mp.opcode[3], + siz2 = (unsigned int)mp.opcode[5]; + const int + w = (int)_mp_arg(6), + h = (int)_mp_arg(7), + d = (int)_mp_arg(8), + s = (int)_mp_arg(9); + + const bool is_compressed = (bool)_mp_arg(10); + if (w<0 || h<0 || d<0 || s<0) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'store()': " + "Specified image dimensions (%d,%d,%d,%d) are invalid.", + pixel_type(),w,h,d,s); + CImg ss(siz2 + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptr2[i]; + ss.back() = 0; + if (siz1) cimg_mp_func_store(ptr1 + 1,siz1, + (unsigned int)w,(unsigned int)h,(unsigned int)d,(unsigned int)s, + is_compressed,ss._data); + else cimg_mp_func_store(ptr1,1,(unsigned int)w,(unsigned int)h,(unsigned int)d,(unsigned int)s, + is_compressed,ss._data); + return cimg::type::nan(); + } +#endif + + static double mp_stov(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2); + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)_mp_arg(4); + const bool is_strict = (bool)_mp_arg(5); + double val = cimg::type::nan(); + if (ind<0 || ind>=(longT)siz) return val; + if (!siz) return *ptrs>='0' && *ptrs<='9'?*ptrs - '0':val; + + CImg ss(siz + 1 - ind); + ptrs+=1 + ind; + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + + const char *s = ss._data; + while (*s && *s<=32) ++s; + const bool is_negative = *s=='-'; + if (is_negative || *s=='+') ++s; + int err = 0; + char sep; + + if (*s=='0' && (s[1]=='x' || s[1]=='X') && s[2]>32) { // Hexadecimal number + unsigned int ival; + err = cimg_sscanf(s + 2,"%x%c",&ival,&sep); + if (err>0) val = (double)ival; + } else if (*s>32) { // Decimal number + err = cimg_sscanf(s,"%lf%c",&val,&sep); +#if cimg_OS==2 + // Check for +/-NaN and +/-inf as Microsoft's sscanf() version is not able + // to read those particular values. + if (!err && (*s=='i' || *s=='I' || *s=='n' || *s=='N')) { + if (!cimg::strncasecmp(s,"inf",3)) { val = cimg::type::inf(); err = 1 + (s[3]!=0); } + else if (!cimg::strncasecmp(s,"nan",3)) { val = cimg::type::nan(); err = 1 + (s[3]!=0); } + } +#endif + } + if (err<=0 || (is_strict && err!=1)) return cimg::type::nan(); + if (is_negative) val = -val; + return val; + } + + static double mp_string(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int nb_args = (unsigned int)(mp.opcode[3] - 3)/2; + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(4 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(4 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + const CImg str = _str>'x'; + const unsigned int sizd = std::min(str._width,(unsigned int)mp.opcode[2]); + std::memset(ptrd,0,mp.opcode[2]*sizeof(double)); + for (unsigned int k = 0; k::nan(); + } + + static double mp_sub(_cimg_math_parser& mp) { + return _mp_arg(2) - _mp_arg(3); + } + + static double mp_sum(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i(ptrs,k,k,1,1,true).trace(); + } + + static double mp_transpose(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg(ptrd,l,k,1,1,true) = CImg(ptrs,k,l,1,1,true).get_transpose(); + return cimg::type::nan(); + } + + static double mp_u(_cimg_math_parser& mp) { + return cimg::rand(_mp_arg(2),_mp_arg(3),&mp.rng); + } + + static double mp_ui2f(_cimg_math_parser& mp) { + return (double)cimg::uint2float((unsigned int)_mp_arg(2)); + } + + static double mp_uppercase(_cimg_math_parser& mp) { + return cimg::uppercase(_mp_arg(2)); + } + + static double mp_var(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i::nan(); + } + + static double mp_vector_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const longT + length = (longT)mp.opcode[3], + start = (longT)_mp_arg(4), + sublength = (longT)mp.opcode[5], + step = (longT)_mp_arg(6); + if (start<0 || start + step*(sublength-1)>=length) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Value accessor '[]': " + "Out-of-bounds sub-vector request " + "(length: %ld, start: %ld, sub-length: %ld, step: %ld).", + mp.imgin.pixel_type(),length,start,sublength,step); + ptrs+=start; + if (step==1) std::memcpy(ptrd,ptrs,sublength*sizeof(double)); + else for (longT k = 0; k::nan(); + } + + static double mp_vector_init(_cimg_math_parser& mp) { + unsigned int + ptrs = 4U, + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[3]; + switch (mp.opcode[2] - 4) { + case 0 : std::memset(mp.mem._data + ptrd,0,siz*sizeof(double)); break; // 0 values given + case 1 : { const double val = _mp_arg(ptrs); while (siz-->0) mp.mem[ptrd++] = val; } break; + default : while (siz-->0) { mp.mem[ptrd++] = _mp_arg(ptrs++); if (ptrs>=mp.opcode[2]) ptrs = 4U; } + } + return cimg::type::nan(); + } + + static double mp_vector_eq(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(4) + 1; + unsigned int p1 = (unsigned int)mp.opcode[3], p2 = (unsigned int)mp.opcode[5], n; + const int N = (int)_mp_arg(6); + const bool case_sensitive = (bool)_mp_arg(7); + bool still_equal = true; + double value; + if (!N) return true; + + // Compare all values. + if (N<0) { + if (p1>0 && p2>0) { // Vector == vector + if (p1!=p2) return false; + if (case_sensitive) + while (still_equal && p1--) still_equal = *(ptr1++)==*(ptr2++); + else + while (still_equal && p1--) + still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p1--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p2--) still_equal = *(ptr2++)==value; + return still_equal; + } else { // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + else return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + } + + // Compare only first N values. + if (p1>0 && p2>0) { // Vector == vector + n = cimg::min((unsigned int)N,p1,p2); + if (case_sensitive) + while (still_equal && n--) still_equal = *(ptr1++)==(*ptr2++); + else + while (still_equal && n--) still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + n = std::min((unsigned int)N,p1); + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + n = std::min((unsigned int)N,p2); + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr2++)==value; + return still_equal; + } // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + + static double mp_vector_lerp(_cimg_math_parser& mp) { + unsigned int siz = (unsigned int)mp.opcode[2]; + double *ptrd = &_mp_arg(1) + 1; + const double + *ptrs1 = &_mp_arg(3) + 1, + *ptrs2 = &_mp_arg(4) + 1, + t = _mp_arg(5); + for (unsigned int k = 0; k::nan(); + } + + static double mp_vector_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + return off>=0 && off<(int)siz?mp.mem[ptr + off]:cimg::type::nan(); + } + + static double mp_vector_map_sv(_cimg_math_parser& mp) { // Operator(scalar,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(4); + l_opcode[2] = mp.opcode[4]; // Scalar argument1 + l_opcode.swap(mp.opcode); + ulongT &argument2 = mp.opcode[3]; + while (siz-->0) { argument2 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_v(_cimg_math_parser& mp) { // Operator(vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode.swap(mp.opcode); + ulongT &argument = mp.opcode[2]; + while (siz-->0) { argument = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vs(_cimg_math_parser& mp) { // Operator(vector,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vss(_cimg_math_parser& mp) { // Operator(vector,scalar,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,5); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode[4] = mp.opcode[6]; // Scalar argument3 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vv(_cimg_math_parser& mp) { // Operator(vector,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs1 = (unsigned int)mp.opcode[4] + 1, + ptrs2 = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2], &argument2 = mp.opcode[3]; + while (siz-->0) { argument1 = ptrs1++; argument2 = ptrs2++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_neq(_cimg_math_parser& mp) { + return !mp_vector_eq(mp); + } + + static double mp_vector_print(_cimg_math_parser& mp) { + const bool print_string = (bool)mp.opcode[4]; + cimg_pragma_openmp(critical(mp_vector_print)) + { + CImg _expr(mp.opcode[2] - 5); + const ulongT *ptrs = mp.opcode._data + 5; + cimg_for(_expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(_expr); + unsigned int + ptr = (unsigned int)mp.opcode[1] + 1, + siz0 = (unsigned int)mp.opcode[3], + siz = siz0; + cimg::mutex(6); + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = [ ",_expr._data); + unsigned int count = 0; + while (siz-->0) { + if (count>=64 && siz>=64) { + std::fprintf(cimg::output(),"...,"); + ptr = (unsigned int)mp.opcode[1] + 1 + siz0 - 64; + siz = 64; + } else std::fprintf(cimg::output(),"%.17g%s",mp.mem[ptr++],siz?",":""); + ++count; + } + if (print_string) { + CImg str(siz0 + 1); + ptr = (unsigned int)mp.opcode[1] + 1; + for (unsigned int k = 0; k::nan(); + } + + static double mp_vector_resize(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[2], p2 = (unsigned int)mp.opcode[4]; + const int + interpolation = (int)_mp_arg(5), + boundary_conditions = (int)_mp_arg(6); + if (p2) { // Resize vector + const double *const ptrs = &_mp_arg(3) + 1; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p2,1,1,1,true). + get_resize(p1,1,1,1,interpolation,boundary_conditions); + } else { // Resize scalar + const double value = _mp_arg(3); + CImg(ptrd,p1,1,1,1,true) = CImg(1,1,1,1,value).resize(p1,1,1,1,interpolation, + boundary_conditions); + } + return cimg::type::nan(); + } + + static double mp_vector_reverse(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[3]; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p1,1,1,1,true).get_mirror('x'); + return cimg::type::nan(); + } + + static double mp_vector_set_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + if (off>=0 && off<(int)siz) mp.mem[ptr + off] = _mp_arg(1); + return _mp_arg(1); + } + +#define _cimg_mp_vfunc(func) \ + const longT sizd = (longT)mp.opcode[2];\ + const unsigned int nbargs = (unsigned int)(mp.opcode[3] - 4)/2; \ + double *const ptrd = &_mp_arg(1) + (sizd?1:0); \ + cimg_pragma_openmp(parallel cimg_openmp_if_size(sizd,256)) \ + { CImg vec(nbargs); double res; \ + cimg_pragma_openmp(for) for (longT k = sizd?sizd - 1:0; k>=0; --k) { \ + cimg_forX(vec,n) vec[n] = *(&_mp_arg(4 + 2*n) + (k+1)*(mp.opcode[4 + 2*n + 1]?1:0)); \ + func; ptrd[k] = res; \ + }} \ + return sizd?cimg::type::nan():*ptrd; + + static double _mp_vargkth(CImg& vec) { + const double val = (+vec).get_shared_points(1,vec.width() - 1). + kth_smallest((ulongT)cimg::cut((longT)*vec - 1,(longT)0,(longT)vec.width() - 2)); + cimg_for_inX(vec,1,vec.width()-1,ind) if (vec[ind]==val) return ind - 1.; + return 1.; + } + + static double mp_vargkth(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = _mp_vargkth(vec)); + } + + static double mp_vargmax(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.max() - vec.data())); + } + + static double mp_vargmaxabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.maxabs() - vec.data())); + } + + static double mp_vargmin(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.min() - vec.data())); + } + + static double mp_vargminabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.minabs() - vec.data())); + } + + static double mp_vavg(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.mean()); + } + + static double mp_vkth(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.get_shared_points(1,vec.width() - 1). + kth_smallest((ulongT)cimg::cut((longT)*vec - 1,(longT)0,(longT)vec.width() - 2))); + } + + static double mp_vmax(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.max()); + } + + static double mp_vmaxabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.maxabs()); + } + + static double mp_vmedian(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.median()); + } + + static double mp_vmin(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.min()); + } + + static double mp_vminabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.minabs()); + } + + static double mp_vprod(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.product()); + } + + static double mp_vstd(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = std::sqrt(vec.get_stats()[3])); + } + + static double mp_vsum(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.sum()); + } + + static double mp_vvar(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.get_stats()[3]); + } + + static double mp_vtos(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + sizd = (unsigned int)mp.opcode[2], + sizs = (unsigned int)mp.opcode[4]; + std::memset(ptrd,0,sizd*sizeof(double)); + const int nb_digits = (int)_mp_arg(5); + CImg format(8); + switch (nb_digits) { + case -1 : std::strcpy(format,"%g"); break; + case 0 : std::strcpy(format,"%.17g"); break; + default : cimg_snprintf(format,format._width,"%%.%dg",nb_digits); + } + CImg str; + if (sizs) { // Vector expression + const double *ptrs = &_mp_arg(3) + 1; + CImg(ptrs,sizs,1,1,1,true).value_string(',',sizd + 1,format).move_to(str); + } else { // Scalar expression + str.assign(sizd + 1); + cimg_snprintf(str,sizd + 1,format,_mp_arg(3)); + } + const unsigned int l = std::min(sizd,(unsigned int)std::strlen(str) + 1); + CImg(ptrd,l,1,1,1,true) = str.get_shared_points(0,l - 1); + return cimg::type::nan(); + } + + static double mp_while(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_cond = ++mp.p_code, + *const p_body = p_cond + mp.opcode[3], + *const p_end = p_body + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + bool is_cond = false; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) // Evaluate body + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3), + vsiz = (unsigned int)mp.opcode[4]; + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6), + vsiz = (unsigned int)mp.opcode[7]; + const CImg &img = mp.imgin; + const double x = _mp_arg(2), y = _mp_arg(3), z = _mp_arg(4); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3), + vsiz = (unsigned int)mp.opcode[4]; + const CImg &img = mp.imgin; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], + oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6), + vsiz = (unsigned int)mp.opcode[7]; + const CImg &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), z = oz + _mp_arg(4); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + +#undef _mp_arg + + }; // struct _cimg_math_parser {} + +#define _cimg_create_pointwise_functions(name,func,min_size) \ + CImg& name() { \ + if (is_empty()) return *this; \ + cimg_openmp_for(*this,func((double)*ptr),min_size); \ + return *this; \ + } \ + CImg get_##name() const { \ + return CImg(*this,false).name(); \ + } + + //! Compute the square value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square value \f$I_{(x,y,z,c)}^2\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqr().normalize(0,255)).display(); + \endcode + \image html ref_sqr.jpg + **/ + _cimg_create_pointwise_functions(sqr,cimg::sqr,524288) + + //! Compute the square root of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square root \f$\sqrt{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqrt().normalize(0,255)).display(); + \endcode + \image html ref_sqrt.jpg + **/ + _cimg_create_pointwise_functions(sqrt,std::sqrt,8192) + + //! Compute the exponential of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its exponential \f$e^{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(exp,std::exp,4096) + + //! Compute the logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its logarithm + \f$\mathrm{log}_{e}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log,std::log,262144) + + //! Compute the base-2 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-2 logarithm + \f$\mathrm{log}_{2}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log2,cimg::log2,4096) + + //! Compute the base-10 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-10 logarithm + \f$\mathrm{log}_{10}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log10,std::log10,4096) + + //! Compute the absolute value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its absolute value \f$|I_{(x,y,z,c)}|\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(abs,cimg::abs,524288) + + //! Compute the sign of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sign + \f$\mathrm{sign}(I_{(x,y,z,c)})\f$. + \note + - The sign is set to: + - \c 1 if pixel value is strictly positive. + - \c -1 if pixel value is strictly negative. + - \c 0 if pixel value is equal to \c 0. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sign,cimg::sign,32768) + + //! Compute the cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its cosine \f$\cos(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(cos,std::cos,8192) + + //! Compute the sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sine \f$\sin(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sin,std::sin,8192) + + //! Compute the sinc of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sinc + \f$\mathrm{sinc}(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sinc,cimg::sinc,2048) + + //! Compute the tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its tangent \f$\tan(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(tan,std::tan,2048) + + //! Compute the hyperbolic cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic cosine + \f$\mathrm{cosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(cosh,std::cosh,2048) + + //! Compute the hyperbolic sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic sine + \f$\mathrm{sinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sinh,std::sinh,2048) + + //! Compute the hyperbolic tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic tangent + \f$\mathrm{tanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(tanh,std::tanh,2048) + + //! Compute the arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosine + \f$\mathrm{acos}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(acos,std::acos,8192) + + //! Compute the arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arcsine + \f$\mathrm{asin}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(asin,std::asin,8192) + + //! Compute the arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent + \f$\mathrm{atan}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(atan,std::atan,8192) + + //! Compute the arctangent2 of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent2 + \f$\mathrm{atan2}(I_{(x,y,z,c)})\f$. + \param img Image whose pixel values specify the second argument of the \c atan2() function. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img_x(100,100,1,1,"x-w/2",false), // Define an horizontal centered gradient, from '-width/2' to 'width/2' + img_y(100,100,1,1,"y-h/2",false), // Define a vertical centered gradient, from '-height/2' to 'height/2' + img_atan2 = img_y.get_atan2(img_x); // Compute atan2(y,x) for each pixel value + (img_x,img_y,img_atan2).display(); + \endcode + **/ + template + CImg& atan2(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return atan2(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_atan2(const CImg& img) const { + return CImg(*this,false).atan2(img); + } + + //! Compute the hyperbolic arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosineh + \f$\mathrm{acosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(acosh,cimg::acosh,8192) + + //! Compute the hyperbolic arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic arcsine + \f$\mathrm{asinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(asinh,cimg::asinh,8192) + + //! Compute the hyperbolic arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic arctangent + \f$\mathrm{atanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(atanh,cimg::atanh,8192) + + //! In-place pointwise multiplication. + /** + Compute the pointwise multiplication between the image instance and the specified input image \c img. + \param img Input image, as the second operand of the multiplication. + \note + - Similar to operator+=(const CImg&), except that it performs a pointwise multiplication + instead of an addition. + - It does \e not perform a \e matrix multiplication. For this purpose, use operator*=(const CImg&) instead. + \par Example + \code + CImg + img("reference.jpg"), + shade(img.width,img.height(),1,1,"-(x-w/2)^2-(y-h/2)^2",false); + shade.normalize(0,1); + (img,shade,img.get_mul(shade)).display(); + \endcode + **/ + template + CImg& mul(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return mul(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_mul(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).mul(img); + } + + //! In-place pointwise division. + /** + Similar to mul(const CImg&), except that it performs a pointwise division instead of a multiplication. + **/ + template + CImg& div(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return div(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_div(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).div(img); + } + + //! Raise each pixel value to a specified power. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its power \f$I_{(x,y,z,c)}^p\f$. + \param p Exponent value. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img0("reference.jpg"), // Load reference color image + img1 = (img0/255).pow(1.8)*=255, // Compute gamma correction, with gamma = 1.8 + img2 = (img0/255).pow(0.5)*=255; // Compute gamma correction, with gamma = 0.5 + (img0,img1,img2).display(); + \endcode + **/ + CImg& pow(const double p) { + if (is_empty()) return *this; + if (p==-4) { cimg_openmp_for(*this,1/(Tfloat)cimg::pow4(*ptr),32768); return *this; } + if (p==-3) { cimg_openmp_for(*this,1/(Tfloat)cimg::pow3(*ptr),32768); return *this; } + if (p==-2) { cimg_openmp_for(*this,1/(Tfloat)cimg::sqr(*ptr),32768); return *this; } + if (p==-1) { cimg_openmp_for(*this,1/(Tfloat)*ptr,32768); return *this; } + if (p==-0.5) { cimg_openmp_for(*this,1/std::sqrt((Tfloat)*ptr),8192); return *this; } + if (p==0) return fill((T)1); + if (p==0.5) return sqrt(); + if (p==1) return *this; + if (p==2) return sqr(); + if (p==3) { cimg_openmp_for(*this,cimg::pow3(*ptr),262144); return *this; } + if (p==4) { cimg_openmp_for(*this,cimg::pow4(*ptr),131072); return *this; } + cimg_openmp_for(*this,std::pow((Tfloat)*ptr,(Tfloat)p),1024); + return *this; + } + + //! Raise each pixel value to a specified power \newinstance. + CImg get_pow(const double p) const { + return CImg(*this,false).pow(p); + } + + //! Raise each pixel value to a power, specified from an expression. + /** + Similar to operator+=(const char*), except it performs a pointwise exponentiation instead of an addition. + **/ + CImg& pow(const char *const expression) { + return pow((+*this)._fill(expression,true,1,0,0,"pow",this)); + } + + //! Raise each pixel value to a power, specified from an expression \newinstance. + CImg get_pow(const char *const expression) const { + return CImg(*this,false).pow(expression); + } + + //! Raise each pixel value to a power, pointwisely specified from another image. + /** + Similar to operator+=(const CImg& img), except that it performs an exponentiation instead of an addition. + **/ + template + CImg& pow(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return pow(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_pow(const CImg& img) const { + return CImg(*this,false).pow(img); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(unsigned int), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::rol(*ptr,n),32768); + return *this; + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const unsigned int n=1) const { + return (+*this).rol(n); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const char*), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const char *const expression) { + return rol((+*this)._fill(expression,true,1,0,0,"rol",this)); + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const char *const expression) const { + return (+*this).rol(expression); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const CImg&), except that it performs a left rotation instead of a left shift. + **/ + template + CImg& rol(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return rol(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_rol(const CImg& img) const { + return (+*this).rol(img); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(unsigned int), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::ror(*ptr,n),32768); + return *this; + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const unsigned int n=1) const { + return (+*this).ror(n); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const char*), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const char *const expression) { + return ror((+*this)._fill(expression,true,1,0,0,"ror",this)); + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const char *const expression) const { + return (+*this).ror(expression); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const CImg&), except that it performs a right rotation instead of a right shift. + **/ + template + CImg& ror(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return ror(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_ror(const CImg& img) const { + return (+*this).ror(img); + } + + //! Pointwise min operator between instance image and a value. + /** + \param val Value used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& min(const T& value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,std::min(*ptr,value),65536); + return *this; + } + + //! Pointwise min operator between instance image and a value \newinstance. + CImg get_min(const T& value) const { + return (+*this).min(value); + } + + //! Pointwise min operator between two images. + /** + \param img Image used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& min(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return min(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_min(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).min(img); + } + + //! Pointwise min operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& min(const char *const expression) { + return min((+*this)._fill(expression,true,1,0,0,"min",this)); + } + + //! Pointwise min operator between an image and an expression \newinstance. + CImg get_min(const char *const expression) const { + return CImg(*this,false).min(expression); + } + + //! Pointwise max operator between instance image and a value. + /** + \param val Value used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& max(const T& value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,std::max(*ptr,value),65536); + return *this; + } + + //! Pointwise max operator between instance image and a value \newinstance. + CImg get_max(const T& value) const { + return (+*this).max(value); + } + + //! Pointwise max operator between two images. + /** + \param img Image used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& max(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return max(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_max(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).max(img); + } + + //! Pointwise max operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& max(const char *const expression) { + return max((+*this)._fill(expression,true,1,0,0,"max",this)); + } + + //! Pointwise max operator between an image and an expression \newinstance. + CImg get_max(const char *const expression) const { + return CImg(*this,false).max(expression); + } + + //! Pointwise minabs operator between instance image and a value. + /** + \param val Value used as the reference argument of the minabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& minabs(const T& value) { + if (is_empty()) return *this; + const T absvalue = cimg::abs(value); + cimg_openmp_for(*this,cimg::minabs(*ptr,value,absvalue),65536); + return *this; + } + + //! Pointwise minabs operator between instance image and a value \newinstance. + CImg get_minabs(const T& value) const { + return (+*this).minabs(value); + } + + //! Pointwise minabs operator between two images. + /** + \param img Image used as the reference argument of the minabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& minabs(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return minabs(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_minabs(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).minabs(img); + } + + //! Pointwise minabs operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& minabs(const char *const expression) { + return minabs((+*this)._fill(expression,true,1,0,0,"minabs",this)); + } + + //! Pointwise minabs operator between an image and an expression \newinstance. + CImg get_minabs(const char *const expression) const { + return CImg(*this,false).minabs(expression); + } + + //! Pointwise maxabs operator between instance image and a value. + /** + \param val Value used as the reference argument of the maxabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& maxabs(const T& value) { + if (is_empty()) return *this; + const T absvalue = cimg::abs(value); + cimg_openmp_for(*this,cimg::maxabs(*ptr,value,absvalue),65536); + return *this; + } + + //! Pointwise maxabs operator between instance image and a value \newinstance. + CImg get_maxabs(const T& value) const { + return (+*this).maxabs(value); + } + + //! Pointwise maxabs operator between two images. + /** + \param img Image used as the reference argument of the maxabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& maxabs(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return maxabs(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_maxabs(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).maxabs(img); + } + + //! Pointwise maxabs operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& maxabs(const char *const expression) { + return maxabs((+*this)._fill(expression,true,1,0,0,"maxabs",this)); + } + + //! Pointwise maxabs operator between an image and an expression \newinstance. + CImg get_maxabs(const char *const expression) const { + return CImg(*this,false).maxabs(expression); + } + + //! Return a reference to the minimum pixel value. + /** + **/ + T& min() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min; + cimg_for(*this,ptrs,T) if (*ptrsmax_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value \const. + const T& max() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max; + cimg_for(*this,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value in absolute value. + /** + **/ + T& maxabs() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "maxabs(): Empty instance.", + cimg_instance); + T *ptr_maxabs = _data; + T maxabs_value = *ptr_maxabs; + cimg_for(*this,ptrs,T) { + const T ma = cimg::abs(*ptrs); + if (ma>maxabs_value) { maxabs_value = ma; ptr_maxabs = ptrs; } + } + return *ptr_maxabs; + } + + //! Return a reference to the maximum pixel value in absolute value \const. + const T& maxabs() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "maxabs(): Empty instance.", + cimg_instance); + const T *ptr_maxabs = _data; + T maxabs_value = *ptr_maxabs; + cimg_for(*this,ptrs,T) { + const T ma = cimg::abs(*ptrs); + if (ma>maxabs_value) { maxabs_value = ma; ptr_maxabs = ptrs; } + } + return *ptr_maxabs; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value. + /** + \param[out] max_val Maximum pixel value. + **/ + template + T& min_max(t& max_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value \const. + template + const T& min_max(t& max_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + const T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the maximum pixel value as well as the minimum pixel value. + /** + \param[out] min_val Minimum pixel value. + **/ + template + T& max_min(t& min_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val=size()) return max(); + CImg arr(*this,false); + ulongT l = 0, ir = size() - 1; + for ( ; ; ) { + if (ir<=l + 1) { + if (ir==l + 1 && arr[ir]>1; + cimg::swap(arr[mid],arr[l + 1]); + if (arr[l]>arr[ir]) cimg::swap(arr[l],arr[ir]); + if (arr[l + 1]>arr[ir]) cimg::swap(arr[l + 1],arr[ir]); + if (arr[l]>arr[l + 1]) cimg::swap(arr[l],arr[l + 1]); + ulongT i = l + 1, j = ir; + const T pivot = arr[l + 1]; + for ( ; ; ) { + do ++i; while (arr[i]pivot); + if (j=k) ir = j - 1; + if (j<=k) l = i; + } + } + } + + //! Return the median pixel value. + /** + **/ + T median() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "median(): Empty instance.", + cimg_instance); + const ulongT s = size(); + switch (s) { + case 1 : return _data[0]; + case 2 : return cimg::median(_data[0],_data[1]); + case 3 : return cimg::median(_data[0],_data[1],_data[2]); + case 5 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4]); + case 7 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6]); + case 9 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8]); + case 13 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8], + _data[9],_data[10],_data[11],_data[12]); + } + const T res = kth_smallest(s>>1); + return (s%2)?res:(T)((res + kth_smallest((s>>1) - 1))/2); + } + + //! Return the product of all the pixel values. + /** + **/ + double product() const { + if (is_empty()) return 0; + double res = 1; + cimg_for(*this,ptrs,T) res*=(double)*ptrs; + return res; + } + + //! Return the sum of all the pixel values. + /** + **/ + double sum() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res; + } + + //! Return the average pixel value. + /** + **/ + double mean() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res/size(); + } + + //! Return the variance of the pixel values. + /** + \param variance_method Method used to estimate the variance. Can be: + - \c 0: Second moment, computed as + \f$1/N \sum\limits_{k=1}^{N} (x_k - \bar x)^2 = + 1/N \left( \sum\limits_{k=1}^N x_k^2 - \left( \sum\limits_{k=1}^N x_k \right)^2 / N \right)\f$ + with \f$ \bar x = 1/N \sum\limits_{k=1}^N x_k \f$. + - \c 1: Best unbiased estimator, computed as \f$\frac{1}{N - 1} \sum\limits_{k=1}^{N} (x_k - \bar x)^2 \f$. + - \c 2: Least median of squares. + - \c 3: Least trimmed of squares. + **/ + double variance(const unsigned int variance_method=1) const { + double foo; + return variance_mean(variance_method,foo); + } + + //! Return the variance as well as the average of the pixel values. + /** + \param variance_method Method used to estimate the variance (see variance(const unsigned int) const). + \param[out] mean Average pixel value. + **/ + template + double variance_mean(const unsigned int variance_method, t& mean) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_mean(): Empty instance.", + cimg_instance); + + double variance = 0, average = 0; + const ulongT siz = size(); + switch (variance_method) { + case 0 : { // Least mean square (standard definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = (S2 - S*S/siz)/siz; + average = S; + } break; + case 1 : { // Least mean square (robust definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + average = S; + } break; + case 2 : { // Least Median of Squares (MAD) + CImg buf(*this,false); + buf.sort(); + const ulongT siz2 = siz>>1; + const double med_i = (double)buf[siz2]; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; *ptrs = (Tfloat)cimg::abs(val - med_i); average+=val; + } + buf.sort(); + const double sig = (double)(1.4828*buf[siz2]); + variance = sig*sig; + } break; + default : { // Least trimmed of Squares + CImg buf(*this,false); + const ulongT siz2 = siz>>1; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; (*ptrs)=(Tfloat)((*ptrs)*val); average+=val; + } + buf.sort(); + double a = 0; + const Tfloat *ptrs = buf._data; + for (ulongT j = 0; j0?variance:0; + } + + //! Return estimated variance of the noise. + /** + \param variance_method Method used to compute the variance (see variance(const unsigned int) const). + \note Because of structures such as edges in images it is + recommended to use a robust variance estimation. The variance of the + noise is estimated by computing the variance of the Laplacian \f$(\Delta + I)^2 \f$ scaled by a factor \f$c\f$ insuring \f$ c E[(\Delta I)^2]= + \sigma^2\f$ where \f$\sigma\f$ is the noise variance. + **/ + double variance_noise(const unsigned int variance_method=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_noise(): Empty instance.", + cimg_instance); + + const ulongT siz = size(); + if (!siz || !_data) return 0; + if (variance_method>1) { // Compute a scaled version of the Laplacian + CImg tmp(*this,false); + if (_depth==1) { + const double cste = 1./std::sqrt(20.); // Depends on how the Laplacian is computed + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*262144 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3(I,T); + cimg_for3x3(*this,x,y,0,c,I,T) { + tmp(x,y,c) = cste*((double)Inc + (double)Ipc + (double)Icn + + (double)Icp - 4*(double)Icc); + } + } + } else { + const double cste = 1./std::sqrt(42.); // Depends on how the Laplacian is computed + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*262144 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,T); + cimg_for3x3x3(*this,x,y,z,c,I,T) { + tmp(x,y,z,c) = cste*( + (double)Incc + (double)Ipcc + (double)Icnc + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + } + } + } + return tmp.variance(variance_method); + } + + // Version that doesn't need intermediate images. + double variance = 0, S = 0, S2 = 0; + if (_depth==1) { + const double cste = 1./std::sqrt(20.); + CImg_3x3(I,T); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,T) { + const double val = cste*((double)Inc + (double)Ipc + + (double)Icn + (double)Icp - 4*(double)Icc); + S+=val; S2+=val*val; + } + } else { + const double cste = 1./std::sqrt(42.); + CImg_3x3x3(I,T); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,T) { + const double val = cste * + ((double)Incc + (double)Ipcc + (double)Icnc + + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + S+=val; S2+=val*val; + } + } + if (variance_method) variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + else variance = (S2 - S*S/siz)/siz; + return variance>0?variance:0; + } + + //! Compute the MSE (Mean-Squared Error) between two images. + /** + \param img Image used as the second argument of the MSE operator. + **/ + template + double MSE(const CImg& img) const { + if (img.size()!=size()) + throw CImgArgumentException(_cimg_instance + "MSE(): Instance and specified image (%u,%u,%u,%u,%p) have different dimensions.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + double vMSE = 0; + const t* ptr2 = img._data; + cimg_for(*this,ptr1,T) { + const double diff = (double)*ptr1 - (double)*(ptr2++); + vMSE+=diff*diff; + } + const ulongT siz = img.size(); + if (siz) vMSE/=siz; + return vMSE; + } + + //! Compute the PSNR (Peak Signal-to-Noise Ratio) between two images. + /** + \param img Image used as the second argument of the PSNR operator. + \param max_value Maximum theoretical value of the signal. + **/ + template + double PSNR(const CImg& img, const double max_value=255) const { + const double vMSE = (double)std::sqrt(MSE(img)); + return (vMSE!=0)?(double)(20*std::log10(max_value/vMSE)):(double)(cimg::type::max()); + } + + //! Evaluate math formula. + /** + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,x,y,z,c,list_inputs,list_outputs); + } + + // Fast function to pre-evaluate common expressions. + // (return 'true' in case of success, and set value of 'res'). + template + bool __eval(const char *const expression, t &res) const { + if (!expression || !*expression) { res = (t)0; return true; } + const char c = *expression; + bool is_success = false; + char c1, end; + double val; + if (c>='0' && c<='9') { // Possible value + if (!expression[1]) { // Single digit + res = (t)(c - '0'); + is_success = true; + } else if (std::sscanf(expression,"%lf%c",&val,&end)==1) { // Single value + res = (t)val; + is_success = true; + } + } else if ((c=='+' || c=='-' || c=='!') && // +Value, -Value or !Value + (c1=expression[1])>='0' && c1<='0') { + if (!expression[2]) { // [+-!] + Single digit + const int ival = c1 - '0'; + res = (t)(c=='+'?ival:c=='-'?-ival:!ival); + is_success = true; + } else if (std::sscanf(expression + 1,"%lf%c",&val,&end)==1) { // [+-!] Single value + res = (t)(c=='+'?val:c=='-'?-val:(double)!val); + is_success = true; + } + } else if (!expression[1]) switch (*expression) { // Other common single-char expressions + case 'w' : res = (t)_width; is_success = true; break; + case 'h' : res = (t)_height; is_success = true; break; + case 'd' : res = (t)_depth; is_success = true; break; + case 's' : res = (t)_spectrum; is_success = true; break; + case 'r' : res = (t)_is_shared; is_success = true; break; + } + return is_success; + } + + double _eval(CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression || !*expression) return 0; + double _val = 0; + if (__eval(expression,_val)) return _val; + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs,false); + mp.begin_t(); + const double val = mp(x,y,z,c); + mp.end_t(); + mp.end(); + return val; + } + + //! Evaluate math formula. + /** + \param[out] output Contains values of output vector returned by the evaluated expression + (or is empty if the returned type is scalar). + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + void eval(CImg &output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + _eval(output,this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + template + void eval(CImg& output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + _eval(output,0,expression,x,y,z,c,list_inputs,list_outputs); + } + + template + void _eval(CImg& output, CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression || !*expression) { output.assign(1); *output = 0; return; } + double _val = 0; + if (__eval(expression,_val)) { output.assign(1); *output = _val; return; } + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs,false); + output.assign(1,std::max(1U,mp.result_dim)); + mp.begin_t(); + mp(x,y,z,c,output._data); + mp.end_t(); + mp.end(); + } + + //! Evaluate math formula on a set of variables. + /** + \param expression Math formula, as a C-string. + \param xyzc Set of values (x,y,z,c) used for the evaluation. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,xyzc,list_inputs,list_outputs); + } + + //! Evaluate math formula on a set of variables \const. + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,xyzc,list_inputs,list_outputs); + } + + template + CImg _eval(CImg *const output, const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + CImg res(1,xyzc.size()/4); + if (!expression || !*expression) return res.fill(0); + _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs,false); + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel if (res._height>=512)) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_eval)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + cimg_pragma_openmp(for) + for (int i = 0; i[min, max, mean, variance, xmin, ymin, zmin, cmin, xmax, ymax, zmax, cmax, sum, product]. + **/ + CImg get_stats(const unsigned int variance_method=1) const { + if (is_empty()) return CImg(); + const ulongT siz = size(); + const longT off_end = (longT)siz; + double S = 0, S2 = 0, P = 1; + longT offm = 0, offM = 0; + T m = *_data, M = m; + + cimg_pragma_openmp(parallel reduction(+:S,S2) reduction(*:P) cimg_openmp_if_size(siz,131072)) { + longT loffm = 0, loffM = 0; + T lm = *_data, lM = lm; + cimg_pragma_openmp(for) + for (longT off = 0; offlM) { lM = val; loffM = off; } + S+=_val; + S2+=_val*_val; + P*=_val; + } + cimg_pragma_openmp(critical(get_stats)) { + if (lmM || (lM==M && loffM1?(S2 - S*S/siz)/(siz - 1):0): + variance(variance_method)), + variance_value = _variance_value>0?_variance_value:0; + int + xm = 0, ym = 0, zm = 0, cm = 0, + xM = 0, yM = 0, zM = 0, cM = 0; + contains(_data[offm],xm,ym,zm,cm); + contains(_data[offM],xM,yM,zM,cM); + return CImg(1,14).fill((double)m,(double)M,mean_value,variance_value, + (double)xm,(double)ym,(double)zm,(double)cm, + (double)xM,(double)yM,(double)zM,(double)cM, + S,P); + } + + //! Compute statistics vector from the pixel values \inplace. + CImg& stats(const unsigned int variance_method=1) { + return get_stats(variance_method).move_to(*this); + } + + //@} + //------------------------------------- + // + //! \name Vector / Matrix Operations + //@{ + //------------------------------------- + + //! Compute norm of the image, viewed as a matrix. + /** + \param magnitude_type Norm type. Can be: + - \c -1: Linf-norm + - \c 0: L0-norm + - \c 1: L1-norm + - \c 2: L2-norm + **/ + double magnitude(const int magnitude_type=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "magnitude(): Empty instance.", + cimg_instance); + const ulongT siz = size(); + double res = 0; + switch (magnitude_type) { + case -1 : { + cimg_for(*this,ptrs,T) { const double val = (double)cimg::abs(*ptrs); if (val>res) res = val; } + } break; + case 1 : { + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(size(),8192)) + for (longT off = 0; off<(longT)siz; ++off) res+=(double)cimg::abs(_data[off]); + } break; + default : { + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(size(),8192)) + for (longT off = 0; off<(longT)siz; ++off) res+=(double)cimg::sqr(_data[off]); + res = (double)std::sqrt(res); + } + } + return res; + } + + //! Compute the trace of the image, viewed as a matrix. + /** + **/ + double trace() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "trace(): Empty instance.", + cimg_instance); + double res = 0; + cimg_forX(*this,k) res+=(double)(*this)(k,k); + return res; + } + + //! Compute the determinant of the image, viewed as a matrix. + /** + **/ + double det() const { + if (is_empty() || _width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "det(): Instance is not a square matrix.", + cimg_instance); + + switch (_width) { + case 1 : return (double)((*this)(0,0)); + case 2 : return (double)((*this)(0,0))*(double)((*this)(1,1)) - (double)((*this)(0,1))*(double)((*this)(1,0)); + case 3 : { + const double + a = (double)_data[0], d = (double)_data[1], g = (double)_data[2], + b = (double)_data[3], e = (double)_data[4], h = (double)_data[5], + c = (double)_data[6], f = (double)_data[7], i = (double)_data[8]; + return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e; + } + default : { + CImg lu(*this,false); + CImg indx; + bool d; + lu._LU(indx,d); + double res = d?(double)1:(double)-1; + cimg_forX(lu,i) res*=lu(i,i); + return res; + } + } + } + + //! Compute the dot product between instance and argument, viewed as matrices. + /** + \param img Image used as a second argument of the dot product. + **/ + template + double dot(const CImg& img) const { + const ulongT nb = std::min(size(),img.size()); + double res = 0; + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(nb,8192)) + for (longT off = 0; off<(longT)nb; ++off) res+=(double)_data[off]*(double)img[off]; + return res; + } + + //! Get vector-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + CImg res; + if (res._height!=_spectrum) res.assign(1,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + const T *ptrs = data(x,y,z); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get (square) matrix-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \note - The spectrum() of the image must be a square. + **/ + CImg get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const { + const int n = (int)cimg::round(std::sqrt((double)_spectrum)); + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(n,n); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get tensor-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + if (_spectrum==6) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd),*(ptrs + 3*whd),*(ptrs + 4*whd),*(ptrs + 5*whd)); + if (_spectrum==3) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd)); + return tensor(*ptrs); + } + + //! Set vector-valued pixel at specified position. + /** + \param vec Vector to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_vector_at(const CImg& vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0) { + if (x<_width && y<_height && z<_depth) { + const t *ptrs = vec._data; + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = data(x,y,z); + for (unsigned int k = std::min((unsigned int)vec.size(),_spectrum); k; --k) { + *ptrd = (T)*(ptrs++); ptrd+=whd; + } + } + return *this; + } + + //! Set (square) matrix-valued pixel at specified position. + /** + \param mat Matrix to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_matrix_at(const CImg& mat, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + return set_vector_at(mat,x,y,z); + } + + //! Set tensor-valued pixel at specified position. + /** + \param ten Tensor to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_tensor_at(const CImg& ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + T *ptrd = data(x,y,z,0); + const ulongT siz = (ulongT)_width*_height*_depth; + if (ten._height==2) { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[3]; + } + else { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[2]; ptrd+=siz; + *ptrd = (T)ten[4]; ptrd+=siz; + *ptrd = (T)ten[5]; ptrd+=siz; + *ptrd = (T)ten[8]; + } + return *this; + } + + //! Resize image to become a diagonal matrix. + /** + \note Transform the image as a diagonal matrix so that each of its initial value becomes a diagonal coefficient. + **/ + CImg& diagonal() { + return get_diagonal().move_to(*this); + } + + //! Resize image to become a diagonal matrix \newinstance. + CImg get_diagonal() const { + if (is_empty()) return *this; + const unsigned int siz = (unsigned int)size(); + CImg res(siz,siz,1,1,0); + cimg_foroff(*this,off) res((unsigned int)off,(unsigned int)off) = (*this)[off]; + return res; + } + + //! Replace the image by an identity matrix. + /** + \note If the instance image is not square, it is resized to a square matrix using its maximum + dimension as a reference. + **/ + CImg& identity_matrix() { + return identity_matrix(std::max(_width,_height)).move_to(*this); + } + + //! Replace the image by an identity matrix \newinstance. + CImg get_identity_matrix() const { + return identity_matrix(std::max(_width,_height)); + } + + //! Fill image with a linear sequence of values. + /** + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + CImg& sequence(const T& a0, const T& a1) { + if (is_empty()) return *this; + const ulongT siz = size() - 1; + T* ptr = _data; + if (siz) { + const double delta = (double)a1 - (double)a0; + cimg_foroff(*this,l) *(ptr++) = (T)(a0 + delta*l/siz); + } else *ptr = a0; + return *this; + } + + //! Fill image with a linear sequence of values \newinstance. + CImg get_sequence(const T& a0, const T& a1) const { + return (+*this).sequence(a0,a1); + } + + //! Transpose the image, viewed as a matrix. + /** + \note Equivalent to \code permute_axes("yxzc"); \endcode. + **/ + CImg& transpose() { + if (_width==1) { _width = _height; _height = 1; return *this; } + if (_height==1) { _height = _width; _width = 1; return *this; } + if (_width==_height) { + cimg_forYZC(*this,y,z,c) for (int x = y; x get_transpose() const { + return get_permute_axes("yxzc"); + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors. + /** + \param img Image used as the second argument of the cross product. + \note The first argument of the cross product is \c *this. + **/ + template + CImg& cross(const CImg& img) { + if (_width!=1 || _height<3 || img._width!=1 || img._height<3) + throw CImgInstanceException(_cimg_instance + "cross(): Instance and/or specified image (%u,%u,%u,%u,%p) are not 3D vectors.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + + const T x = (*this)[0], y = (*this)[1], z = (*this)[2]; + (*this)[0] = (T)(y*img[2] - z*img[1]); + (*this)[1] = (T)(z*img[0] - x*img[2]); + (*this)[2] = (T)(x*img[1] - y*img[0]); + return *this; + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors \newinstance. + template + CImg<_cimg_Tt> get_cross(const CImg& img) const { + return CImg<_cimg_Tt>(*this).cross(img); + } + + //! Invert the instance image, viewed as a matrix. + /** + \param use_LU Choose the inverting algorithm. Can be: + - \c true: LU-based matrix inversion. + - \c false: SVD-based matrix inversion. + **/ + CImg& invert(const bool use_LU=true) { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "invert(): Instance is not a square matrix.", + cimg_instance); + const double dete = _width>3?-1.:det(); + if (dete!=0. && _width==2) { + const double + a = _data[0], c = _data[1], + b = _data[2], d = _data[3]; + _data[0] = (T)(d/dete); _data[1] = (T)(-c/dete); + _data[2] = (T)(-b/dete); _data[3] = (T)(a/dete); + } else if (dete!=0. && _width==3) { + const double + a = _data[0], d = _data[1], g = _data[2], + b = _data[3], e = _data[4], h = _data[5], + c = _data[6], f = _data[7], i = _data[8]; + _data[0] = (T)((i*e - f*h)/dete), _data[1] = (T)((g*f - i*d)/dete), _data[2] = (T)((d*h - g*e)/dete); + _data[3] = (T)((h*c - i*b)/dete), _data[4] = (T)((i*a - c*g)/dete), _data[5] = (T)((g*b - a*h)/dete); + _data[6] = (T)((b*f - e*c)/dete), _data[7] = (T)((d*c - a*f)/dete), _data[8] = (T)((a*e - d*b)/dete); + } else { + +#ifdef cimg_use_lapack + int INFO = (int)use_LU, N = _width, LWORK = 4*N, *const IPIV = new int[N]; + Tfloat + *const lapA = new Tfloat[N*N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetri_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)(lapA[k*N + l]); else fill(0); + delete[] IPIV; delete[] lapA; delete[] WORK; +#else + if (use_LU) { // LU-based + CImg A(*this,false), indx; + bool d; + A._LU(indx,d); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16*16)) + cimg_forX(*this,j) { + CImg col(1,_width,1,1,0); + col(j) = 1; + col._solve(A,indx); + cimg_forX(*this,i) (*this)(j,i) = (T)col(i); + } + } else pseudoinvert(false); // SVD-based +#endif + } + return *this; + } + + //! Invert the instance image, viewed as a matrix \newinstance. + CImg get_invert(const bool use_LU=true) const { + return CImg(*this,false).invert(use_LU); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix. + /** + **/ + CImg& pseudoinvert(const bool use_LU=false) { + return get_pseudoinvert(use_LU).move_to(*this); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix \newinstance. + CImg get_pseudoinvert(const bool use_LU=false) const { + + // LU-based method. + if (use_LU) { + CImg AtA(width(),width()); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,128*128)) + cimg_forY(AtA,i) + for (int j = 0; j<=i; ++j) { + double res = 0; + cimg_forY(*this,k) res+=(*this)(i,k)*(*this)(j,k); + AtA(j,i) = AtA(i,j) = (Tfloat)res; + } + AtA.invert(true); + return AtA*get_transpose(); + } + + // SVD-based method. + CImg U, S, V; + SVD(U,S,V,false); + const Tfloat epsilon = (sizeof(Tfloat)<=4?5.96e-8f:1.11e-16f)*std::max(_width,_height)*S.max(); + cimg_forX(V,x) { + const Tfloat s = S(x), invs = s>epsilon?1/s:0; + cimg_forY(V,y) V(x,y)*=invs; + } + return V*U.transpose(); + } + + //! Solve a system of linear equations. + /** + \param A Matrix of the linear system. + \param use_LU In case of non square system (least-square solution), + choose between SVD-based (\c false) or LU-based (\c true) method. + LU method is faster for large matrices, but numerically less stable. + \note Solve \c AX = B where \c B=*this. + **/ + template + CImg& solve(const CImg& A, const bool use_LU=false) { + if (_depth!=1 || _spectrum!=1 || _height!=A._height || A._depth!=1 || A._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "solve(): Instance and specified matrix (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + + if (A.size()==1) return (*this)/=A[0]; + if (A._width==2 && A._height==2 && _height==2) { // 2x2 linear system + const double a = (double)A[0], b = (double)A[1], c = (double)A[2], d = (double)A[3], + fa = std::fabs(a), fb = std::fabs(b), fc = std::fabs(c), fd = std::fabs(d), + det = a*d - b*c, fM = cimg::max(fa,fb,fc,fd); + if (fM==fa) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), y = (a*v - c*u)/det; + (*this)(k,0) = (T)((u - b*y)/a); (*this)(k,1) = (T)y; + } else if (fM==fc) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), y = (a*v - c*u)/det; + (*this)(k,0) = (T)((v - d*y)/c); (*this)(k,1) = (T)y; + } else if (fM==fb) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), x = (d*u - b*v)/det; + (*this)(k,0) = (T)x; (*this)(k,1) = (T)((u - a*x)/b); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), x = (d*u - b*v)/det; + (*this)(k,0) = (T)x; (*this)(k,1) = (T)((v - c*x)/d); + } + return *this; + } + + if (A._width==A._height) { // Square linear system +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N]; + Ttfloat + *const lapA = new Ttfloat[N*N], + *const lapB = new Ttfloat[N], + *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*N + l] = (Ttfloat)(A(k,l)); + cimg_forX(*this,i) { + cimg_forY(*this,j) lapB[j] = (Ttfloat)((*this)(i,j)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getrs(TRANS,N,lapA,IPIV,lapB,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrs_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forY(*this,j) (*this)(i,j) = (T)(lapB[j]); else cimg_forY(*this,j) (*this)(i,j) = (T)0; + } + delete[] IPIV; delete[] lapA; delete[] lapB; delete[] WORK; +#else + CImg lu(A,false); + CImg indx; + bool d; + lu._LU(indx,d); + CImg res(_width,A._width); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16)) + cimg_forX(*this,i) res.draw_image(i,get_column(i)._solve(lu,indx)); + res.move_to(*this); +#endif + } else { // Least-square solution for non-square systems + +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width; + Ttfloat WORK_QUERY; + Ttfloat + * const lapA = new Ttfloat[M*N], + * const lapB = new Ttfloat[M*NRHS]; + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, &WORK_QUERY, LWORK, INFO); + LWORK = (int) WORK_QUERY; + Ttfloat *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*M + l] = (Ttfloat)(A(k,l)); + cimg_forXY(*this,k,l) lapB[k*M + l] = (Ttfloat)((*this)(k,l)); + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, WORK, LWORK, INFO); + if (INFO != 0) + cimg::warn(_cimg_instance + "solve(): LAPACK library function sgels() returned error code %d.", + cimg_instance, + INFO); + assign(NRHS, N); + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)lapB[k*M + l]; + else (A.get_pseudoinvert(use_LU)*(*this)).move_to(*this); + delete[] lapA; delete[] lapB; delete[] WORK; +#else + (A.get_pseudoinvert(use_LU)*(*this)).move_to(*this); +#endif + } + return *this; + } + + //! Solve a system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve(const CImg& A, const bool use_LU=false) const { + typedef _cimg_Ttfloat Ttfloat; + return CImg(*this,false).solve(A,use_LU); + } + + template + CImg& _solve(const CImg& A, const CImg& indx) { + typedef _cimg_Ttfloat Ttfloat; + const int N = height(); + int ii = -1; + Ttfloat sum; + for (int i = 0; i=0) for (int j = ii; j<=i - 1; ++j) sum-=A(j,i)*(*this)(j); + else if (sum!=0) ii = i; + (*this)(i) = (T)sum; + } + for (int i = N - 1; i>=0; --i) { + sum = (*this)(i); + for (int j = i + 1; j + CImg& solve_tridiagonal(const CImg& A) { + const unsigned int siz = (unsigned int)size(); + if (A._width!=3 || A._height!=siz) + throw CImgArgumentException(_cimg_instance + "solve_tridiagonal(): Instance and tridiagonal matrix " + "(%u,%u,%u,%u,%p) have incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = 1e-4f; + CImg B = A.get_column(1), V(*this,false); + for (int i = 1; i<(int)siz; ++i) { + const Ttfloat m = A(0,i)/(B[i - 1]?B[i - 1]:epsilon); + B[i] -= m*A(2,i - 1); + V[i] -= m*V[i - 1]; + } + (*this)[siz - 1] = (T)(V[siz - 1]/(B[siz - 1]?B[siz - 1]:epsilon)); + for (int i = (int)siz - 2; i>=0; --i) (*this)[i] = (T)((V[i] - A(2,i)*(*this)[i + 1])/(B[i]?B[i]:epsilon)); + return *this; + } + + //! Solve a tridiagonal system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve_tridiagonal(const CImg& A) const { + return CImg<_cimg_Ttfloat>(*this,false).solve_tridiagonal(A); + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& eigen(CImg& val, CImg &vec) const { + if (is_empty()) { val.assign(); vec.assign(); } + else { + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + + if (val.size()<(ulongT)_width) val.assign(1,_width); + if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width); + switch (_width) { + case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break; + case 2 : { + const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d; + double f = e*e - 4*(a*d - b*c); + if (f<0) cimg::warn(_cimg_instance + "eigen(): Complex eigenvalues found.", + cimg_instance); + f = std::sqrt(f); + const double + l1 = 0.5*(e - f), + l2 = 0.5*(e + f), + b2 = b*b, + norm1 = std::sqrt(cimg::sqr(l2 - a) + b2), + norm2 = std::sqrt(cimg::sqr(l1 - a) + b2); + val[0] = (t)l2; + val[1] = (t)l1; + if (norm1>0) { vec(0,0) = (t)(b/norm1); vec(0,1) = (t)((l2 - a)/norm1); } else { vec(0,0) = 1; vec(0,1) = 0; } + if (norm2>0) { vec(1,0) = (t)(b/norm2); vec(1,1) = (t)((l1 - a)/norm2); } else { vec(1,0) = 1; vec(1,1) = 0; } + } break; + default : + throw CImgInstanceException(_cimg_instance + "eigen(): Eigenvalues computation of general matrices is limited " + "to 2x2 matrices.", + cimg_instance); + } + } + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \return A list of two images [val; vec], whose meaning is similar as in eigen(CImg&,CImg&) const. + **/ + CImgList get_eigen() const { + CImgList res(2); + eigen(res[0],res[1]); + return res; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& symmetric_eigen(CImg& val, CImg& vec) const { + if (is_empty()) { val.assign(); vec.assign(); return *this; } + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + val.assign(1,_width); + vec.assign(_width,_width); + + if (_width==1) { val[0] = cimg::abs((*this)[0]); vec[0] = 1; return *this; } + if (_width==2) { + const double + a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], + e = a + d, f = std::sqrt(std::max(e*e - 4*(a*d - b*c),0.0)), + l1 = 0.5*(e - f), l2 = 0.5*(e + f), + n = std::sqrt(cimg::sqr(l2 - a) + b*b); + val[0] = (t)l2; + val[1] = (t)l1; + if (n>0) { vec[0] = (t)(b/n); vec[2] = (t)((l2 - a)/n); } else { vec[0] = 1; vec[2] = 0; } + vec[1] = -vec[2]; + vec[3] = vec[0]; + return *this; + } + +#ifdef cimg_use_lapack + char JOB = 'V', UPLO = 'U'; + int N = _width, LWORK = 4*N, INFO; + Tfloat + *const lapA = new Tfloat[N*N], + *const lapW = new Tfloat[N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.", + cimg_instance, + INFO); + if (!INFO) { + cimg_forY(val,i) val(i) = (T)lapW[N - 1 -i]; + cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N - 1 - k)*N + l]); + } else { val.fill(0); vec.fill(0); } + delete[] lapA; delete[] lapW; delete[] WORK; + +#else + CImg V(_width,_width); + Tfloat M = 0, m = (Tfloat)min_max(M), maxabs = cimg::max((Tfloat)1,cimg::abs(m),cimg::abs(M)); + (CImg(*this,false)/=maxabs).SVD(vec,val,V,false); + if (maxabs!=1) val*=maxabs; + + bool is_ambiguous = false; + float eig = 0; + cimg_forY(val,p) { // Check for ambiguous cases + if (val[p]>eig) eig = (float)val[p]; + t scal = 0; + cimg_forY(vec,y) scal+=vec(p,y)*V(p,y); + if (cimg::abs(scal)<0.9f) is_ambiguous = true; + if (scal<0) val[p] = -val[p]; + } + if (is_ambiguous) { + ++(eig*=2); + SVD(vec,val,V,false,40,eig); + val-=eig; + } + + CImg permutations; // Sort eigenvalues in decreasing order + CImg tmp(_width); + val.sort(permutations,false); + cimg_forY(vec,k) { + cimg_forY(permutations,y) tmp(y) = vec(permutations(y),k); + std::memcpy(vec.data(0,k),tmp._data,sizeof(t)*_width); + } +#endif + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \return A list of two images [val; vec], whose meaning are similar as in + symmetric_eigen(CImg&,CImg&) const. + **/ + CImgList get_symmetric_eigen() const { + CImgList res(2); + symmetric_eigen(res[0],res[1]); + return res; + } + + //! Sort pixel values and get sorting permutations. + /** + \param[out] permutations Permutation map used for the sorting. + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + **/ + template + CImg& sort(CImg& permutations, const bool is_increasing=true) { + permutations.assign(_width,_height,_depth,_spectrum); + if (is_empty()) return *this; + cimg_foroff(permutations,off) permutations[off] = (t)off; + return _quicksort(0,size() - 1,permutations,is_increasing,true); + } + + //! Sort pixel values and get sorting permutations \newinstance. + template + CImg get_sort(CImg& permutations, const bool is_increasing=true) const { + return (+*this).sort(permutations,is_increasing); + } + + //! Sort pixel values. + /** + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + \param axis Tells if the value sorting must be done along a specific axis. Can be: + - \c 0: All pixel values are sorted, independently on their initial position. + - \c 'x': Image columns are sorted, according to the first value in each column. + - \c 'y': Image rows are sorted, according to the first value in each row. + - \c 'z': Image slices are sorted, according to the first value in each slice. + - \c 'c': Image channels are sorted, according to the first value in each channel. + **/ + CImg& sort(const bool is_increasing=true, const char axis=0) { + if (is_empty()) return *this; + CImg perm; + switch (cimg::lowercase(axis)) { + case 0 : + _quicksort(0,size() - 1,perm,is_increasing,false); + break; + case 'x' : { + perm.assign(_width); + get_crop(0,0,0,0,_width - 1,0,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(perm[x],y,z,c); + } break; + case 'y' : { + perm.assign(_height); + get_crop(0,0,0,0,0,_height - 1,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,perm[y],z,c); + } break; + case 'z' : { + perm.assign(_depth); + get_crop(0,0,0,0,0,0,_depth - 1,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,perm[z],c); + } break; + case 'c' : { + perm.assign(_spectrum); + get_crop(0,0,0,0,0,0,0,_spectrum - 1).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,z,perm[c]); + } break; + default : + throw CImgArgumentException(_cimg_instance + "sort(): Invalid specified axis '%c' " + "(should be { x | y | z | c }).", + cimg_instance,axis); + } + return *this; + } + + //! Sort pixel values \newinstance. + CImg get_sort(const bool is_increasing=true, const char axis=0) const { + return (+*this).sort(is_increasing,axis); + } + + template + CImg& _quicksort(const long indm, const long indM, CImg& permutations, + const bool is_increasing, const bool is_permutations) { + if (indm(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]>(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]>(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } else { + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]<(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } + if (indM - indm>=3) { + const T pivot = (*this)[mid]; + long i = indm, j = indM; + if (is_increasing) { + do { + while ((*this)[i]pivot) --j; + if (i<=j) { + if (is_permutations) cimg::swap(permutations[i],permutations[j]); + cimg::swap((*this)[i++],(*this)[j--]); + } + } while (i<=j); + } else { + do { + while ((*this)[i]>pivot) ++i; + while ((*this)[j] A; // Input matrix (assumed to contain some values) + CImg<> U,S,V; + A.SVD(U,S,V) + \endcode + **/ + template + const CImg& SVD(CImg& U, CImg& S, CImg& V, const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = (Ttfloat)1e-25; + + if (is_empty()) { U.assign(); S.assign(); V.assign(); } + else if (_depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "SVD(): Instance has invalid dimensions (depth or channels different from 1).", + cimg_instance); + else { + U = *this; + if (lambda!=0) { + const unsigned int delta = std::min(U._width,U._height); + for (unsigned int i = 0; i rv1(_width); + Ttfloat anorm = 0, c, f, g = 0, h, s, scale = 0; + int l = 0; + + cimg_forX(U,i) { + l = i + 1; + rv1[i] = scale*g; + g = s = scale = 0; + if (i=0?-1:1)*std::sqrt(s)); + h = f*g - s; + U(i,i) = f - g; + for (int j = l; j=0?-1:1)*std::sqrt(s)); + h = f*g - s; + U(l,i) = f - g; + for (int k = l; k=0; --i) { + if (i=0; --i) { + l = i + 1; + g = S[i]; + for (int j = l; j=0; --k) { + int nm = 0; + for (unsigned int its = 0; its=1; --l) { + nm = l - 1; + if ((cimg::abs(rv1[l]) + anorm)==anorm) { flag = false; break; } + if ((cimg::abs(S[nm]) + anorm)==anorm) break; + } + if (flag) { + c = 0; + s = 1; + for (int i = l; i<=k; ++i) { + f = s*rv1[i]; + rv1[i] = c*rv1[i]; + if ((cimg::abs(f) + anorm)==anorm) break; + g = S[i]; + h = cimg::_hypot(f,g); + S[i] = h; + h = 1/h; + c = g*h; + s = -f*h; + cimg_forY(U,j) { + const t y = U(nm,j), z = U(i,j); + U(nm,j) = y*c + z*s; + U(i,j) = z*c - y*s; + } + } + } + + const t z = S[k]; + if (l==k) { if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); } break; } + nm = k - 1; + t x = S[l], y = S[nm]; + g = rv1[nm]; + h = rv1[k]; + f = ((y - z)*(y + z) + (g - h)*(g + h))/std::max(epsilon,(Ttfloat)2*h*y); + g = cimg::_hypot(f,(Ttfloat)1); + f = ((x - z)*(x + z) + h*((y/(f + (f>=0?g:-g))) - h))/std::max(epsilon,(Ttfloat)x); + c = s = 1; + for (int j = l; j<=nm; ++j) { + const int i = j + 1; + g = rv1[i]; + h = s*g; + g = c*g; + t y1 = S[i], z1 = cimg::_hypot(f,h); + rv1[j] = z1; + c = f/std::max(epsilon,(Ttfloat)z1); + s = h/std::max(epsilon,(Ttfloat)z1); + f = x*c + g*s; + g = g*c - x*s; + h = y1*s; + y1*=c; + cimg_forX(U,jj) { + const t x2 = V(j,jj), z2 = V(i,jj); + V(j,jj) = x2*c + z2*s; + V(i,jj) = z2*c - x2*s; + } + z1 = cimg::_hypot(f,h); + S[j] = z1; + if (z1) { + z1 = 1/std::max(epsilon,(Ttfloat)z1); + c = f*z1; + s = h*z1; + } + f = c*g + s*y1; + x = c*y1 - s*g; + cimg_forY(U,jj) { + const t y2 = U(j,jj), z2 = U(i,jj); + U(j,jj) = y2*c + z2*s; + U(i,jj) = z2*c - y2*s; + } + } + rv1[l] = 0; + rv1[k] = f; + S[k] = x; + } + } + + if (sorting) { + CImg permutations; + CImg tmp(_width); + S.sort(permutations,false); + cimg_forY(U,k) { + cimg_forY(permutations,y) tmp(y) = U(permutations(y),k); + std::memcpy(U.data(0,k),tmp._data,sizeof(t)*_width); + } + cimg_forY(V,k) { + cimg_forY(permutations,y) tmp(y) = V(permutations(y),k); + std::memcpy(V.data(0,k),tmp._data,sizeof(t)*_width); + } + } + } + return *this; + } + + //! Compute the SVD of the instance image, viewed as a general matrix. + /** + \return A list of three images [U; S; V], whose meaning is similar as in + SVD(CImg&,CImg&,CImg&,bool,unsigned int,float) const. + **/ + CImgList get_SVD(const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + CImgList res(3); + SVD(res[0],res[1],res[2],sorting,max_iteration,lambda); + return res; + } + + // [internal] Compute the LU decomposition of a permuted matrix. + template + CImg& _LU(CImg& indx, bool& d) { + const int N = width(); + int imax = 0; + CImg vv(N); + indx.assign(N); + d = true; + + bool return0 = false; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=512)) + cimg_forX(*this,i) { + Tfloat vmax = 0; + cimg_forX(*this,j) { + const Tfloat tmp = cimg::abs((*this)(j,i)); + if (tmp>vmax) vmax = tmp; + } + if (vmax==0) return0 = true; else vv[i] = 1/vmax; + } + if (return0) { indx.fill(0); return fill(0); } + + cimg_forX(*this,j) { + for (int i = 0; i=vmax) { vmax = tmp; imax = i; } + } + if (j!=imax) { + cimg_forX(*this,k) cimg::swap((*this)(k,imax),(*this)(k,j)); + d = !d; + vv[imax] = vv[j]; + } + indx[j] = (t)imax; + if ((*this)(j,j)==0) (*this)(j,j) = (T)1e-20; + if (j=3 = orthogonal matching pursuit where an orthogonal projection step is performed + every 'method-2' iterations. + \param max_iter Sets the max number of iterations processed for each signal. + If set to '0' (default), 'max_iter' is set to the number of dictionary columns. + (only meaningful for matching pursuit and its variants). + \param max_residual Gives a stopping criterion on signal reconstruction accuracy. + (only meaningful for matching pursuit and its variants). + \return A matrix W whose columns correspond to the sparse weights of associated to each input matrix column. + Thus, the matrix product D*W is an approximation of the input matrix. + **/ + template + CImg& project_matrix(const CImg& dictionary, const unsigned int method=0, + const unsigned int max_iter=0, const double max_residual=1e-6) { + return get_project_matrix(dictionary,method,max_iter,max_residual).move_to(*this); + } + + template + CImg get_project_matrix(const CImg& dictionary, const unsigned int method=0, + const unsigned int max_iter=0, const double max_residual=1e-6) const { + if (_depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "project_matrix(): Instance image is not a matrix.", + cimg_instance); + if (dictionary._height!=_height || dictionary._depth!=1 || dictionary._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "project_matrix(): Specified dictionary (%u,%u,%u,%u) has an invalid size.", + cimg_instance, + dictionary._width,dictionary._height,dictionary._depth,dictionary._spectrum); + + if (!method) return get_solve(dictionary,true); + CImg W(_width,dictionary._width,1,1,0); + + // Compute dictionary norm and normalize it. + CImg D(dictionary,false), Dnorm(D._width); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=2 && _width*_height>=32)) + cimg_forX(Dnorm,d) { + Tfloat norm = 0; + cimg_forY(D,y) norm+=cimg::sqr(D(d,y)); + Dnorm[d] = std::max((Tfloat)1e-8,std::sqrt(norm)); + } + cimg_forXY(D,d,y) D(d,y)/=Dnorm[d]; + + // Matching pursuit. + const unsigned int proj_step = method<3?1:method - 2; + bool is_orthoproj = false; + + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=2 && _width*_height>=32)) + cimg_forX(*this,x) { + CImg S = get_column(x); + const CImg S0 = method<2?CImg():S; + Tfloat residual = S.magnitude()/S._height; + const unsigned int nmax = max_iter?max_iter:D._width; + + for (unsigned int n = 0; nmax_residual; ++n) { + + // Find best matching column in D. + int dmax = 0; + Tfloat absdotmax = 0, dotmax = 0; + cimg_pragma_openmp(parallel for cimg_openmp_if(D._width>=2 && D._width*D._height>=32)) + cimg_forX(D,d) { + Tfloat _dot = 0; + cimg_forY(D,y) _dot+=S[y]*D(d,y); + Tfloat absdot = cimg::abs(_dot); + cimg_pragma_openmp(critical(get_project_matrix)) { + if (absdot>absdotmax) { + absdotmax = absdot; + dotmax = _dot; + dmax = d; + } + } + } + + if (!n || method<3 || n%proj_step) { + // Matching Pursuit: Subtract component to signal. + W(x,dmax)+=dotmax; + residual = 0; + cimg_forY(S,y) { + S[y]-=dotmax*D(dmax,y); + residual+=cimg::sqr(S[y]); + } + residual = std::sqrt(residual)/S._height; + is_orthoproj = false; + + } else { + // Orthogonal Matching Pursuit: Orthogonal projection step. + W(x,dmax) = 1; // Used as a marker only. + unsigned int nbW = 0; + cimg_forY(W,d) if (W(x,d)) ++nbW; + CImg sD(nbW,D._height); + CImg inds(nbW); + int sd = 0; + cimg_forY(W,d) if (W(x,d)) { + cimg_forY(sD,y) sD(sd,y) = D(d,y); + inds[sd++] = d; + } + S0.get_solve(sD,true).move_to(sD); // sD is now a one-column vector of weights + + // Recompute residual signal. + S = S0; + cimg_forY(sD,k) { + const Tfloat weight = sD[k]; + const unsigned int ind = inds[k]; + W(x,ind) = weight; + cimg_forY(S,y) S[y]-=weight*D(ind,y); + } + residual = S.magnitude()/S._height; + is_orthoproj = true; + } + } + + // Perform last orthoprojection step if needed. + if (method>=2 && !is_orthoproj) { + unsigned int nbW = 0; + cimg_forY(W,d) if (W(x,d)) ++nbW; + if (nbW) { // Avoid degenerated case where 0 coefs are used + CImg sD(nbW,D._height); + CImg inds(nbW); + int sd = 0; + cimg_forY(W,d) if (W(x,d)) { + cimg_forY(sD,y) sD(sd,y) = D(d,y); + inds[sd++] = d; + } + S0.get_solve(sD,true).move_to(sD); + cimg_forY(sD,k) W(x,inds[k]) = sD[k]; + } + } + } + + // Normalize resulting coefficients according to initial (non-normalized) dictionary. + cimg_forXY(W,x,y) W(x,y)/=Dnorm[y]; + return W; + } + + //! Compute minimal path in a graph, using the Dijkstra algorithm. + /** + \param distance An object having operator()(unsigned int i, unsigned int j) which returns distance + between two nodes (i,j). + \param nb_nodes Number of graph nodes. + \param starting_node Index of the starting node. + \param ending_node Index of the ending node (set to ~0U to ignore ending node). + \param previous_node Array that gives the previous node index in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + **/ + template + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + if (starting_node>=nb_nodes) + throw CImgArgumentException("CImg<%s>::dijkstra(): Specified index of starting node %u is higher " + "than number of nodes %u.", + pixel_type(),starting_node,nb_nodes); + CImg dist(1,nb_nodes,1,1,cimg::type::max()); + dist(starting_node) = 0; + previous_node.assign(1,nb_nodes,1,1,(t)-1); + previous_node(starting_node) = (t)starting_node; + CImg Q(nb_nodes); + cimg_forX(Q,u) Q(u) = (unsigned int)u; + cimg::swap(Q(starting_node),Q(0)); + unsigned int sizeQ = nb_nodes; + while (sizeQ) { + // Update neighbors from minimal vertex + const unsigned int umin = Q(0); + if (umin==ending_node) sizeQ = 0; + else { + const T dmin = dist(umin); + const T infty = cimg::type::max(); + for (unsigned int q = 1; qdist(Q(left))) || + (rightdist(Q(right)));) { + if (right + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node=~0U) { + CImg foo; + return dijkstra(distance,nb_nodes,starting_node,ending_node,foo); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + /** + \param starting_node Index of the starting node. + \param ending_node Index of the ending node. + \param previous_node Array that gives the previous node index in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + \note image instance corresponds to the adjacency matrix of the graph. + **/ + template + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + return get_dijkstra(starting_node,ending_node,previous_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + template + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) const { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "dijkstra(): Instance is not a graph adjacency matrix.", + cimg_instance); + + return dijkstra(*this,_width,starting_node,ending_node,previous_node); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) { + return get_dijkstra(starting_node,ending_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) const { + CImg foo; + return get_dijkstra(starting_node,ending_node,foo); + } + + //! Return an image containing the character codes of specified string. + /** + \param str input C-string to encode as an image. + \param is_last_zero Tells if the ending \c '0' character appear in the resulting image. + \param is_shared Return result that shares its buffer with \p str. + **/ + static CImg string(const char *const str, const bool is_last_zero=true, const bool is_shared=false) { + if (!str) return CImg(); + return CImg(str,(unsigned int)std::strlen(str) + (is_last_zero?1:0),1,1,1,is_shared); + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg row_vector(const T& a0) { + return vector(a0); + } + + //! Return a \c 2x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg row_vector(const T& a0, const T& a1) { + CImg r(2,1); + r[0] = a0; r[1] = a1; + return r; + } + + //! Return a \c 3x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg row_vector(const T& a0, const T& a1, const T& a2) { + CImg r(3,1); + r[0] = a0; r[1] = a1; r[2] = a2; + return r; + } + + //! Return a \c 4x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(4,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; + return r; + } + + //! Return a \c 5x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(5,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; + return r; + } + + //! Return a \c 6x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(6,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; + return r; + } + + //! Return a \c 7x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(7,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; + return r; + } + + //! Return a \c 8x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(8,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; + return r; + } + + //! Return a \c 9x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(9,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; + return r; + } + + //! Return a \c 10x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(10,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + return r; + } + + //! Return a \c 11x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(11,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; + return r; + } + + //! Return a \c 12x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(12,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; + return r; + } + + //! Return a \c 13x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(13,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; + return r; + } + + //! Return a \c 14x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(14,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; + return r; + } + + //! Return a \c 15x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(15,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; + return r; + } + + //! Return a \c 16x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(16,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; r[15] = a15; + return r; + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg vector(const T& a0) { + CImg r(1,1); + r[0] = a0; + return r; + } + + //! Return a \c 1x2 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg vector(const T& a0, const T& a1) { + CImg r(1,2); + r[0] = a0; r[1] = a1; + return r; + } + + //! Return a \c 1x3 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2) { + CImg r(1,3); + r[0] = a0; r[1] = a1; r[2] = a2; + return r; + } + + //! Return a \c 1x4 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(1,4); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; + return r; + } + + //! Return a \c 1x5 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(1,5); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; + return r; + } + + //! Return a \c 1x6 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(1,6); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; + return r; + } + + //! Return a \c 1x7 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(1,7); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; + return r; + } + + //! Return a \c 1x8 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(1,8); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; + return r; + } + + //! Return a \c 1x9 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(1,9); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; + return r; + } + + //! Return a \c 1x10 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(1,10); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + return r; + } + + //! Return a \c 1x11 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(1,11); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; + return r; + } + + //! Return a \c 1x12 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(1,12); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; + return r; + } + + //! Return a \c 1x13 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(1,13); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; + return r; + } + + //! Return a \c 1x14 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(1,14); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; + return r; + } + + //! Return a \c 1x15 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(1,15); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; + return r; + } + + //! Return a \c 1x16 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(1,16); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; r[15] = a15; + return r; + } + + //! Return a 1x1 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg matrix(const T& a0) { + return vector(a0); + } + + //! Return a 2x2 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, + const T& a2, const T& a3) { + CImg r(2,2); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; + *(ptr++) = a2; *(ptr++) = a3; + return r; + } + + //! Return a 3x3 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + \param a4 Fifth matrix value. + \param a5 Sixth matrix value. + \param a6 Seventh matrix value. + \param a7 Eighth matrix value. + \param a8 Ninth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, const T& a2, + const T& a3, const T& a4, const T& a5, + const T& a6, const T& a7, const T& a8) { + CImg r(3,3); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; + *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; + *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; + return r; + } + + //! Return a 4x4 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(4,4); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; + return r; + } + + //! Return a 5x5 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, + const T& a5, const T& a6, const T& a7, const T& a8, const T& a9, + const T& a10, const T& a11, const T& a12, const T& a13, const T& a14, + const T& a15, const T& a16, const T& a17, const T& a18, const T& a19, + const T& a20, const T& a21, const T& a22, const T& a23, const T& a24) { + CImg r(5,5); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; + *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; *(ptr++) = a9; + *(ptr++) = a10; *(ptr++) = a11; *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; + *(ptr++) = a15; *(ptr++) = a16; *(ptr++) = a17; *(ptr++) = a18; *(ptr++) = a19; + *(ptr++) = a20; *(ptr++) = a21; *(ptr++) = a22; *(ptr++) = a23; *(ptr++) = a24; + return r; + } + + //! Return a 1x1 symmetric matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg tensor(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 symmetric matrix tensor containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2) { + return matrix(a0,a1,a1,a2); + } + + //! Return a 3x3 symmetric matrix containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + return matrix(a0,a1,a2,a1,a3,a4,a2,a4,a5); + } + + //! Return a 1x1 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1) { + return matrix(a0,0,0,a1); + } + + //! Return a 3x3 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2) { + return matrix(a0,0,0,0,a1,0,0,0,a2); + } + + //! Return a 4x4 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3) { + return matrix(a0,0,0,0,0,a1,0,0,0,0,a2,0,0,0,0,a3); + } + + //! Return a 5x5 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + return matrix(a0,0,0,0,0,0,a1,0,0,0,0,0,a2,0,0,0,0,0,a3,0,0,0,0,0,a4); + } + + //! Return a NxN identity matrix. + /** + \param N Dimension of the matrix. + **/ + static CImg identity_matrix(const unsigned int N) { + CImg res(N,N,1,1,0); + cimg_forX(res,x) res(x,x) = 1; + return res; + } + + //! Return a N-numbered sequence vector from \p a0 to \p a1. + /** + \param N Size of the resulting vector. + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + static CImg sequence(const unsigned int N, const T& a0, const T& a1) { + if (N) return CImg(1,N).sequence(a0,a1); + return CImg(); + } + + //! Return a 3x3 rotation matrix from an { axis + angle } or a quaternion. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or third quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + static CImg rotation_matrix(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + double X, Y, Z, W, N; + if (is_quaternion) { + N = std::sqrt((double)x*x + (double)y*y + (double)z*z + (double)w*w); + if (N>0) { X = x/N; Y = y/N; Z = z/N; W = w/N; } + else { X = Y = Z = 0; W = 1; } + return CImg::matrix((T)(X*X + Y*Y - Z*Z - W*W),(T)(2*Y*Z - 2*X*W),(T)(2*X*Z + 2*Y*W), + (T)(2*X*W + 2*Y*Z),(T)(X*X - Y*Y + Z*Z - W*W),(T)(2*Z*W - 2*X*Y), + (T)(2*Y*W - 2*X*Z),(T)(2*X*Y + 2*Z*W),(T)(X*X - Y*Y - Z*Z + W*W)); + } + N = cimg::hypot((double)x,(double)y,(double)z); + if (N>0) { X = x/N; Y = y/N; Z = z/N; } + else { X = Y = 0; Z = 1; } + const double ang = w*cimg::PI/180, c = std::cos(ang), omc = 1 - c, s = std::sin(ang); + return CImg::matrix((T)(X*X*omc + c),(T)(X*Y*omc - Z*s),(T)(X*Z*omc + Y*s), + (T)(X*Y*omc + Z*s),(T)(Y*Y*omc + c),(T)(Y*Z*omc - X*s), + (T)(X*Z*omc - Y*s),(T)(Y*Z*omc + X*s),(T)(Z*Z*omc + c)); + } + + //@} + //----------------------------------- + // + //! \name Value Manipulation + //@{ + //----------------------------------- + + //! Fill all pixel values with specified value. + /** + \param val Fill value. + **/ + CImg& fill(const T& val) { + if (is_empty()) return *this; + if (val && sizeof(T)!=1) cimg_for(*this,ptrd,T) *ptrd = val; + else std::memset(_data,(int)(ulongT)val,sizeof(T)*size()); // Double cast to allow val to be (void*) + return *this; + } + + //! Fill all pixel values with specified value \newinstance. + CImg get_fill(const T& val) const { + return CImg(_width,_height,_depth,_spectrum).fill(val); + } + + //! Fill sequentially all pixel values with specified values. + /** + \param val0 First fill value. + \param val1 Second fill value. + **/ + CImg& fill(const T& val0, const T& val1) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 1; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 2; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 3; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 4; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 5; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 6; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 7; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 8; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 9; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 10; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 11; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 12; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 13; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 14; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 15; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14,val15); + } + + //! Fill sequentially pixel values according to a given expression. + /** + \param expression C-string describing a math formula, or a sequence of values. + \param repeat_values In case a list of values is provided, tells if this list must be repeated for the filling. + \param allow_formula Tells that mathematical formulas are authorized for the filling. + \param list_inputs In case of a mathematical expression, attach a list of images to the specified expression. + \param[out] list_outputs In case of a math expression, list of images atatched to the specified expression. + **/ + CImg& fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _fill(expression,repeat_values,allow_formula?1:0,list_inputs,list_outputs,"fill",0); + } + + // 'formula_mode' = { 0 = does not allow formula | 1 = allow formula | + // 2 = allow formula and do not fill image values }. + CImg& _fill(const char *const expression, const bool repeat_values, const unsigned int formula_mode, + const CImgList *const list_inputs, CImgList *const list_outputs, + const char *const calling_function, const CImg *provides_copy) { + if (is_empty() || !expression || !*expression) return *this; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + CImg is_error; + bool is_value_sequence = false; + cimg_abort_init; + + if (formula_mode) { + + // Try to pre-detect regular value sequence to avoid exception thrown by _cimg_math_parser. + double value; + char sep; + const int err = cimg_sscanf(expression,"%lf %c",&value,&sep); + if (err==1 || (err==2 && sep==',')) { + if (err==1) { if (formula_mode==2) return *this; return fill((T)value); } + else is_value_sequence = true; + } + + // Try to fill values according to a formula. + _cimg_abort_init_openmp; + if (!is_value_sequence) try { + CImg base = provides_copy?provides_copy->get_shared():get_shared(); + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'), + calling_function,base,this,list_inputs,list_outputs,true); + if (!provides_copy && expression && *expression!='>' && *expression!='<' && *expression!=':' && + mp.need_input_copy) + base.assign().assign(*this,false); // Needs input copy + + // Determine 2nd largest image dimension (used as axis for inner loop in parallelized evaluation). + unsigned int M; + if (mp.result_dim) { + M = cimg::max(_width,_height,_depth); + M = M==_width?std::max(_height,_depth):M==_height?std::max(_width,_depth):std::max(_width,_height); + } else { + M = cimg::max(_width,_height,_depth,_spectrum); + M = M==_width?cimg::max(_height,_depth,_spectrum): + M==_height?cimg::max(_width,_depth,_spectrum): + M==_depth?cimg::max(_width,_height,_spectrum):cimg::max(_width,_height,_depth); + } + + bool do_in_parallel = false; +#if cimg_use_openmp!=0 + cimg_openmp_if(*expression=='*' || *expression==':' || + (mp.is_parallelizable && M>=(cimg_openmp_sizefactor)*320 && size()/M>=2)) + do_in_parallel = true; +#endif + if (mp.result_dim) { // Vector-valued expression + const unsigned int N = std::min(mp.result_dim,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = *expression=='<'?_data + _width*_height*_depth - 1:_data; + if (*expression=='<') { + CImg res(1,mp.result_dim); + mp.begin_t(); + cimg_rofYZ(*this,y,z) { + cimg_abort_test; + if (formula_mode==2) cimg_rofX(*this,x) mp(x,y,z,0); + else cimg_rofX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd--; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + mp.end_t(); + + } else if (*expression=='>' || !do_in_parallel) { + CImg res(1,mp.result_dim); + mp.begin_t(); + cimg_forYZ(*this,y,z) { + cimg_abort_test; + if (formula_mode==2) cimg_forX(*this,x) mp(x,y,z,0); + else cimg_forX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + mp.end_t(); + + } else { + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_fill)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + lmp.is_fill = true; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + +#define _cimg_fill_openmp_vector(_YZ,_y,_z,_X,_x,_sx,_sy,_sz,_off) \ + cimg_pragma_openmp(for cimg_openmp_collapse(2)) \ + cimg_for##_YZ(*this,_y,_z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + if (formula_mode==2) cimg_for##_X(*this,_x) lmp(x,y,z,0); \ + else { \ + CImg res(1,lmp.result_dim); \ + T *__ptrd = data(_sx,_sy,_sz,0); \ + const ulongT off = (ulongT)_off; \ + cimg_for##_X(*this,_x) { \ + lmp(x,y,z,0,res._data); \ + const double *ptrs = res._data; \ + T *_ptrd = __ptrd; \ + for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } \ + __ptrd+=off; \ + } \ + } \ + } _cimg_abort_catch_openmp _cimg_abort_catch_fill_openmp + + if (M==_width) { _cimg_fill_openmp_vector(YZ,y,z,X,x,0,y,z,1) } + else if (M==_height) { _cimg_fill_openmp_vector(XZ,x,z,Y,y,x,0,z,_width) } + else { _cimg_fill_openmp_vector(XY,x,y,Z,z,x,y,0,_width*_height) } + + lmp.end_t(); + cimg_pragma_openmp(barrier) cimg_pragma_openmp(critical) { lmp.merge(mp); } + if (&lmp!=&mp) delete &lmp; + } +#endif + } + + } else { // Scalar-valued expression + T *ptrd = *expression=='<'?end() - 1:_data; + if (*expression=='<') { + mp.begin_t(); + if (formula_mode==2) cimg_rofYZC(*this,y,z,c) { cimg_abort_test; cimg_rofX(*this,x) mp(x,y,z,c); } + else cimg_rofYZC(*this,y,z,c) { cimg_abort_test; cimg_rofX(*this,x) *(ptrd--) = (T)mp(x,y,z,c); } + mp.end_t(); + + } else if (*expression=='>' || !do_in_parallel) { + mp.begin_t(); + if (formula_mode==2) cimg_forYZC(*this,y,z,c) { cimg_abort_test; cimg_forX(*this,x) mp(x,y,z,c); } + else cimg_forYZC(*this,y,z,c) { cimg_abort_test; cimg_forX(*this,x) *(ptrd++) = (T)mp(x,y,z,c); } + mp.end_t(); + + } else { + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_fill)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + lmp.is_fill = true; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + +#define _cimg_fill_openmp_scalar(_YZC,_y,_z,_c,_X,_x,_sx,_sy,_sz,_sc,_off) \ + cimg_pragma_openmp(for cimg_openmp_collapse(3)) \ + cimg_for##_YZC(*this,_y,_z,_c) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + if (formula_mode==2) cimg_for##_X(*this,_x) lmp(x,y,z,c); \ + else { \ + T *_ptrd = data(_sx,_sy,_sz,_sc); \ + const ulongT off = (ulongT)_off; \ + cimg_for##_X(*this,_x) { *_ptrd = (T)lmp(x,y,z,c); _ptrd+=off; } \ + } \ + } _cimg_abort_catch_openmp _cimg_abort_catch_fill_openmp + + if (M==_width) { _cimg_fill_openmp_scalar(YZC,y,z,c,X,x,0,y,z,c,1) } + else if (M==_height) { _cimg_fill_openmp_scalar(XZC,x,z,c,Y,y,x,0,z,c,_width) } + else if (M==_depth) { _cimg_fill_openmp_scalar(XYC,x,y,c,Z,z,x,y,0,c,_width*_height) } + else { _cimg_fill_openmp_scalar(XYZ,x,y,z,C,c,x,y,z,0,_width*_height*_depth) } + + lmp.end_t(); + cimg_pragma_openmp(barrier) cimg_pragma_openmp(critical) { lmp.merge(mp); } + if (&lmp!=&mp) delete &lmp; + } +#endif + } + } + mp.end(); + } catch (CImgException& e) { CImg::string(e._message).move_to(is_error); } + } + + // Try to fill values according to a value sequence. + if (!formula_mode || is_value_sequence || is_error) { + CImg item(256); + char sep = 0; + const char *nexpression = expression; + ulongT nb = 0; + const ulongT siz = size(); + T *ptrd = _data; + for (double val = 0; *nexpression && nb0 && cimg_sscanf(item,"%lf",&val)==1 && (sep==',' || sep==';' || err==1)) { + nexpression+=std::strlen(item) + (err>1); + *(ptrd++) = (T)val; + } else break; + } + cimg::exception_mode(omode); + if (nb get_fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return (+*this).fill(expression,repeat_values,allow_formula?1:0,list_inputs,list_outputs); + } + + //! Fill sequentially pixel values according to the values found in another image. + /** + \param values Image containing the values used for the filling. + \param repeat_values In case there are less values than necessary in \c values, tells if these values must be + repeated for the filling. + **/ + template + CImg& fill(const CImg& values, const bool repeat_values=true) { + if (is_empty() || !values) return *this; + T *ptrd = _data, *ptre = ptrd + size(); + for (t *ptrs = values._data, *ptrs_end = ptrs + values.size(); ptrs + CImg get_fill(const CImg& values, const bool repeat_values=true) const { + return repeat_values?CImg(_width,_height,_depth,_spectrum).fill(values,repeat_values): + (+*this).fill(values,repeat_values); + } + + //! Fill pixel values along the X-axis at a specified pixel position. + /** + \param y Y-coordinate of the filled column. + \param z Z-coordinate of the filled column. + \param c C-coordinate of the filled column. + \param a0 First fill value. + **/ + CImg& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const int a0, ...) { +#define _cimg_fill1(x,y,z,c,off,siz,t) { \ + va_list ap; va_start(ap,a0); T *ptrd = data(x,y,z,c); *ptrd = (T)a0; \ + for (unsigned int k = 1; k& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const double a0, ...) { + if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,double); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position. + /** + \param x X-coordinate of the filled row. + \param z Z-coordinate of the filled row. + \param c C-coordinate of the filled row. + \param a0 First fill value. + **/ + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const int a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,int); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position \overloading. + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const double a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,double); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position. + /** + \param x X-coordinate of the filled slice. + \param y Y-coordinate of the filled slice. + \param c C-coordinate of the filled slice. + \param a0 First fill value. + **/ + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,int); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position \overloading. + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const double a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,double); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position. + /** + \param x X-coordinate of the filled channel. + \param y Y-coordinate of the filled channel. + \param z Z-coordinate of the filled channel. + \param a0 First filling value. + **/ + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const int a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,int); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position \overloading. + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const double a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,double); + return *this; + } + + //! Discard specified sequence of values in the image buffer, along a specific axis. + /** + \param values Sequence of values to discard. + \param axis Axis along which the values are discarded. If set to \c 0 (default value) + the method does it for all the buffer values and returns a one-column vector. + \note Discarded values will change the image geometry, so the resulting image + is returned as a one-column vector. + **/ + template + CImg& discard(const CImg& values, const char axis=0) { + if (is_empty() || !values) return *this; + return get_discard(values,axis).move_to(*this); + } + + template + CImg get_discard(const CImg& values, const char axis=0) const { + if (!values) return +*this; + CImg res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + ulongT j = 0; + unsigned int k = 0; + int i0 = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) { + if ((*this)(i)!=(T)values[j]) { + if (j) --i; + res.draw_image(k,get_columns(i0,i)); + k+=i - i0 + 1; i0 = i + 1; j = 0; + } else { ++j; if (j>=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = (int)i + 1; }} + } + if ((ulongT)i0& discard(const char axis=0) { + return get_discard(axis).move_to(*this); + } + + //! Discard neighboring duplicates in the image buffer, along the specified axis \newinstance. + CImg get_discard(const char axis=0) const { + CImg res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + T current = *_data?(T)0:(T)1; + int j = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) + if ((*this)(i)!=current) { res.draw_image(j++,get_column(i)); current = (*this)(i); } + res.resize(j,-100,-100,-100,0); + } break; + case 'y' : { + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { res.draw_image(0,j++,get_row(i)); current = (*this)(0,i); } + res.resize(-100,j,-100,-100,0); + } break; + case 'z' : { + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { res.draw_image(0,0,j++,get_slice(i)); current = (*this)(0,0,i); } + res.resize(-100,-100,j,-100,0); + } break; + case 'c' : { + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { res.draw_image(0,0,0,j++,get_channel(i)); current = (*this)(0,0,0,i); } + res.resize(-100,-100,-100,j,0); + } break; + default : { + res.unroll('y'); + cimg_foroff(*this,i) { + const T val = (*this)[i]; + if (val!=current) res[j++] = current = val; + } + res.resize(-100,j,-100,-100,0); + } + } + return res; + } + + //! Invert endianness of all pixel values. + /** + **/ + CImg& invert_endianness() { + cimg::invert_endianness(_data,size()); + return *this; + } + + //! Invert endianness of all pixel values \newinstance. + CImg get_invert_endianness() const { + return (+*this).invert_endianness(); + } + + //! Fill image with random values in specified range. + /** + \param val_min Minimal authorized random value. + \param val_max Maximal authorized random value. + \note Random variables are uniformly distributed in [val_min,val_max]. + **/ + CImg& rand(const T& val_min, const T& val_max) { + const float delta = (float)val_max - (float)val_min + (cimg::type::is_float()?0:1); + if (cimg::type::is_float()) cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),524288)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) _data[off] = (T)(val_min + delta*cimg::rand(1,&rng)); + cimg::srand(rng); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),524288)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) _data[off] = std::min(val_max,(T)(val_min + delta*cimg::rand(1,&rng))); + cimg::srand(rng); + } + return *this; + } + + //! Fill image with random values in specified range \newinstance. + CImg get_rand(const T& val_min, const T& val_max) const { + return (+*this).rand(val_min,val_max); + } + + //! Round pixel values. + /** + \param y Rounding precision. + \param rounding_type Rounding type. Can be: + - \c -1: Backward. + - \c 0: Nearest. + - \c 1: Forward. + **/ + CImg& round(const double y=1, const int rounding_type=0) { + if (y>0) cimg_openmp_for(*this,cimg::round(*ptr,y,rounding_type),8192); + return *this; + } + + //! Round pixel values \newinstance. + CImg get_round(const double y=1, const unsigned int rounding_type=0) const { + return (+*this).round(y,rounding_type); + } + + //! Add random noise to pixel values. + /** + \param sigma Amplitude of the random additive noise. If \p sigma<0, it stands for a percentage of the + global value range. + \param noise_type Type of additive noise (can be \p 0=gaussian, \p 1=uniform, \p 2=Salt and Pepper, + \p 3=Poisson or \p 4=Rician). + \return A reference to the modified image instance. + \note + - For Poisson noise (\p noise_type=3), parameter \p sigma is ignored, as Poisson noise only depends on + the image value itself. + - Function \p CImg::get_noise() is also defined. It returns a non-shared modified copy of the image instance. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_noise(40); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_noise.jpg + **/ + CImg& noise(const double sigma, const unsigned int noise_type=0) { + if (is_empty()) return *this; + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + Tfloat nsigma = (Tfloat)sigma, m = 0, M = 0; + if (nsigma==0 && noise_type!=3) return *this; + if (nsigma<0 || noise_type==2) m = (Tfloat)min_max(M); + if (nsigma<0) nsigma = (Tfloat)(-nsigma*(M-m)/100.); + switch (noise_type) { + case 0 : { // Gaussian noise + cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) { + Tfloat val = (Tfloat)(_data[off] + nsigma*cimg::grand(&rng)); + if (val>vmax) val = vmax; + if (valvmax) val = vmax; + if (val::is_float()) { --m; ++M; } + else { m = (Tfloat)cimg::type::min(); M = (Tfloat)cimg::type::max(); } + } + cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) if (cimg::rand(100,&rng)vmax) val = vmax; + if (val get_noise(const double sigma, const unsigned int noise_type=0) const { + return (+*this).noise(sigma,noise_type); + } + + //! Linearly normalize pixel values. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \param constant_case_ratio In case of instance image having a constant value, tell what ratio + of [min_value,max_value] is used to fill the normalized image + (=0 for min_value, =1 for max_value, =0.5 for (min_value + max_value)/2). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(160,220); + (img,res).display(); + \endcode + \image html ref_normalize2.jpg + **/ + CImg& normalize(const T& min_value, const T& max_value, + const float constant_case_ratio=0) { + if (is_empty()) return *this; + const T a = min_value get_normalize(const T& min_value, const T& max_value, + const float ratio_if_constant_image=0) const { + return CImg(*this,false).normalize((Tfloat)min_value,(Tfloat)max_value,ratio_if_constant_image); + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm. + /** + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_normalize.jpg + **/ + CImg& normalize() { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + T *ptrd = data(0,y,z,0); + cimg_forX(*this,x) { + const T *ptrs = ptrd; + float n = 0; + cimg_forC(*this,c) { n+=cimg::sqr((float)*ptrs); ptrs+=whd; } + n = (float)std::sqrt(n); + T *_ptrd = ptrd++; + if (n>0) cimg_forC(*this,c) { *_ptrd = (T)(*_ptrd/n); _ptrd+=whd; } + else cimg_forC(*this,c) { *_ptrd = (T)0; _ptrd+=whd; } + } + } + return *this; + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm \newinstance. + CImg get_normalize() const { + return CImg(*this,false).normalize(); + } + + //! Compute Lp-norm of each multi-valued pixel of the image instance. + /** + \param norm_type Type of computed vector norm (can be \p -1=Linf, or \p greater or equal than 0). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_norm(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_norm.jpg + **/ + CImg& norm(const int norm_type=2) { + if (_spectrum==1 && norm_type) return abs(); + return get_norm(norm_type).move_to(*this); + } + + //! Compute L2-norm of each multi-valued pixel of the image instance \newinstance. + CImg get_norm(const int norm_type=2) const { + if (is_empty()) return *this; + if (_spectrum==1 && norm_type) return get_abs(); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(_width,_height,_depth); + switch (norm_type) { + case -1 : { // Linf-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { const Tfloat val = (Tfloat)cimg::abs(*_ptrs); if (val>n) n = val; _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 0 : { // L0-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + unsigned int n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=*_ptrs==0?0:1; _ptrs+=whd; } + *(ptrd++) = (Tfloat)n; + } + } + } break; + case 1 : { // L1-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::abs(*_ptrs); _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 2 : { // L2-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::sqr((Tfloat)*_ptrs); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::sqrt((Tfloat)n); + } + } + } break; + default : { // Linf-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=std::pow(cimg::abs((Tfloat)*_ptrs),(Tfloat)norm_type); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::pow((Tfloat)n,1/(Tfloat)norm_type); + } + } + } + } + return res; + } + + //! Cut pixel values in specified range. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_cut(160,220); + (img,res).display(); + \endcode + \image html ref_cut.jpg + **/ + CImg& cut(const T& min_value, const T& max_value) { + if (is_empty()) return *this; + const T a = min_value get_cut(const T& min_value, const T& max_value) const { + return (+*this).cut(min_value,max_value); + } + + //! Uniformly quantize pixel values. + /** + \param nb_levels Number of quantization levels. + \param keep_range Tells if resulting values keep the same range as the original ones. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_quantize(4); + (img,res).display(); + \endcode + \image html ref_quantize.jpg + **/ + CImg& quantize(const unsigned int nb_levels, const bool keep_range=true) { + if (!nb_levels) + throw CImgArgumentException(_cimg_instance + "quantize(): Invalid quantization request with 0 values.", + cimg_instance); + + if (is_empty()) return *this; + Tfloat m, M = (Tfloat)max_min(m), range = M - m; + if (range>0) { + if (keep_range) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range); + _data[off] = (T)(m + std::min(val,nb_levels - 1)*range/nb_levels); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range); + _data[off] = (T)std::min(val,nb_levels - 1); + } + } + return *this; + } + + //! Uniformly quantize pixel values \newinstance. + CImg get_quantize(const unsigned int n, const bool keep_range=true) const { + return (+*this).quantize(n,keep_range); + } + + //! Threshold pixel values. + /** + \param value Threshold value + \param soft_threshold Tells if soft thresholding must be applied (instead of hard one). + \param strict_threshold Tells if threshold value is strict. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_threshold(128); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_threshold.jpg + **/ + CImg& threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) { + if (is_empty()) return *this; + if (strict_threshold) { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const T v = _data[off]; + _data[off] = v>value?(T)(v-value):v<-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),65536)) + cimg_rofoff(*this,off) _data[off] = _data[off]>value?(T)1:(T)0; + } else { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const T v = _data[off]; + _data[off] = v>=value?(T)(v-value):v<=-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),65536)) + cimg_rofoff(*this,off) _data[off] = _data[off]>=value?(T)1:(T)0; + } + return *this; + } + + //! Threshold pixel values \newinstance. + CImg get_threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) const { + return (+*this).threshold(value,soft_threshold,strict_threshold); + } + + //! Compute the histogram of pixel values. + /** + \param nb_levels Number of desired histogram levels. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \note + - The histogram H of an image I is the 1D function where H(x) counts the number of occurrences of the value x + in the image I. + - The resulting histogram is always defined in 1D. Histograms of multi-valued images are not multi-dimensional. + \par Example + \code + const CImg img = CImg("reference.jpg").histogram(256); + img.display_graph(0,3); + \endcode + \image html ref_histogram.jpg + **/ + CImg& histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) { + return get_histogram(nb_levels,min_value,max_value).move_to(*this); + } + + //! Compute the histogram of pixel values \overloading. + CImg& histogram(const unsigned int nb_levels) { + return get_histogram(nb_levels).move_to(*this); + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) const { + if (!nb_levels || is_empty()) return CImg(); + const double + vmin = (double)(min_value res(nb_levels,1,1,1,0); + cimg_rof(*this,ptrs,T) { + const T val = *ptrs; + if (val>=vmin && val<=vmax) ++res[val==vmax?nb_levels - 1:(unsigned int)((val - vmin)*nb_levels/(vmax - vmin))]; + } + return res; + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels) const { + if (!nb_levels || is_empty()) return CImg(); + T vmax = 0, vmin = min_max(vmax); + return get_histogram(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values. + /** + \param nb_levels Number of histogram levels used for the equalization. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_equalize(256); + (img,res).display(); + \endcode + \image html ref_equalize.jpg + **/ + CImg& equalize(const unsigned int nb_levels, const T& min_value, const T& max_value) { + if (!nb_levels || is_empty()) return *this; + const T + vmin = min_value hist = get_histogram(nb_levels,vmin,vmax); + ulongT cumul = 0; + cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; } + if (!cumul) cumul = 1; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),1048576)) + cimg_rofoff(*this,off) { + const int pos = (int)((_data[off] - vmin)*(nb_levels - 1.)/(vmax - vmin)); + if (pos>=0 && pos<(int)nb_levels) _data[off] = (T)(vmin + (vmax - vmin)*hist[pos]/cumul); + } + return *this; + } + + //! Equalize histogram of pixel values \overloading. + CImg& equalize(const unsigned int nb_levels) { + if (!nb_levels || is_empty()) return *this; + T vmax = 0, vmin = min_max(vmax); + return equalize(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels, const T& val_min, const T& val_max) const { + return (+*this).equalize(nblevels,val_min,val_max); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels) const { + return (+*this).equalize(nblevels); + } + + //! Index multi-valued pixels regarding to a specified colormap. + /** + \param colormap Multi-valued colormap used as the basis for multi-valued pixel indexing. + \param dithering Level of dithering (0=disable, 1=standard level). + \param map_indexes Tell if the values of the resulting image are the colormap indices or the colormap vectors. + \note + - \p img.index(colormap,dithering,1) is equivalent to img.index(colormap,dithering,0).map(colormap). + \par Example + \code + const CImg img("reference.jpg"), colormap(3,1,1,3, 0,128,255, 0,128,255, 0,128,255); + const CImg res = img.get_index(colormap,1,true); + (img,res).display(); + \endcode + \image html ref_index.jpg + **/ + template + CImg& index(const CImg& colormap, const float dithering=1, const bool map_indexes=false) { + return get_index(colormap,dithering,map_indexes).move_to(*this); + } + + //! Index multi-valued pixels regarding to a specified colormap \newinstance. + template + CImg::Tuint> + get_index(const CImg& colormap, const float dithering=1, const bool map_indexes=true) const { + if (colormap._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "index(): Instance and specified colormap (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + typedef typename CImg::Tuint tuint; + if (is_empty()) return CImg(); + const ulongT + whd = (ulongT)_width*_height*_depth, + pwhd = (ulongT)colormap._width*colormap._height*colormap._depth; + CImg res(_width,_height,_depth,map_indexes?_spectrum:1); + if (dithering>0) { // Dithered versions + tuint *ptrd = res._data; + const float ndithering = cimg::cut(dithering,0,1)/16; + Tfloat valm = 0, valM = (Tfloat)max_min(valm); + if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; } + CImg cache = get_crop(-1,0,0,0,_width,1,0,_spectrum - 1); + Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0); + const ulongT cwhd = (ulongT)cache._width*cache._height*cache._depth; + switch (_spectrum) { + case 1 : { // Optimized for scalars + cimg_forYZ(*this,y,z) { + if (yvalM?valM:_val0; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1, + _val2 = (Tfloat)*ptrs2, val2 = _val2valM?valM:_val2; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrpvalM?valM:_val; + dist+=cimg::sqr((*_ptrs=val) - (Tfloat)*_ptrp); _ptrs+=cwhd; _ptrp+=pwhd; + } + if (dist=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs0 = data(0,y,z), *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd, + *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs = data(0,y,z), *ptrs_end = ptrs + _width; ptrs::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp img("reference.jpg"), + colormap1(3,1,1,3, 0,128,255, 0,128,255, 0,128,255), + colormap2(3,1,1,3, 255,0,0, 0,255,0, 0,0,255), + res = img.get_index(colormap1,0).map(colormap2); + (img,res).display(); + \endcode + \image html ref_map.jpg + **/ + template + CImg& map(const CImg& colormap, const unsigned int boundary_conditions=0) { + return get_map(colormap,boundary_conditions).move_to(*this); + } + + //! Map predefined colormap on the scalar (indexed) image instance \newinstance. + template + CImg get_map(const CImg& colormap, const unsigned int boundary_conditions=0) const { + const ulongT + whd = (ulongT)_width*_height*_depth, siz = size(), + cwhd = (ulongT)colormap._width*colormap._height*colormap._depth, + cwhd2 = 2*cwhd; + CImg res(_width,_height,_depth,_spectrum*colormap._spectrum); + switch (colormap._spectrum) { + + case 1 : { // Optimized for scalars + switch (boundary_conditions) { + case 3 : // Mirror + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),256)) + for (longT off = 0; off<(longT)siz; ++off) { + const ulongT ind = ((ulongT)_data[off])%cwhd2; + res[off] = colormap[ind& label(const bool is_high_connectivity=false, const Tfloat tolerance=0, + const bool is_L2_norm=true) { + if (is_empty()) return *this; + return get_label(is_high_connectivity,tolerance,is_L2_norm).move_to(*this); + } + + //! Label connected components \newinstance. + CImg get_label(const bool is_high_connectivity=false, const Tfloat tolerance=0, + const bool is_L2_norm=true) const { + if (is_empty()) return CImg(); + + // Create neighborhood tables. + int dx[13], dy[13], dz[13], nb = 0; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 0; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 0; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 0; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 0; + } + if (_depth>1) { // 3D version + dx[nb] = 0; dy[nb] = 0; dz[nb++]=1; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = -1; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = -1; + + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 1; + } + } + return _label(nb,dx,dy,dz,tolerance,is_L2_norm); + } + + //! Label connected components \overloading. + /** + \param connectivity_mask Mask of the neighboring pixels. + \param tolerance Tolerance used to determine if two neighboring pixels belong to the same region. + \param is_L2_norm If true, tolerance is compared against L2 difference, otherwise L1 is used. + **/ + template + CImg& label(const CImg& connectivity_mask, const Tfloat tolerance=0, + const bool is_L2_norm=true) { + if (is_empty()) return *this; + return get_label(connectivity_mask,tolerance,is_L2_norm).move_to(*this); + } + + //! Label connected components \newinstance. + template + CImg get_label(const CImg& connectivity_mask, const Tfloat tolerance=0, + const bool is_L2_norm=true) const { + if (is_empty()) return CImg(); + int nb = 0; + cimg_for(connectivity_mask,ptr,t) if (*ptr) ++nb; + CImg dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0); + nb = 0; + cimg_forXYZ(connectivity_mask,x,y,z) if ((x || y || z) && + connectivity_mask(x,y,z)) { + dx[nb] = x; dy[nb] = y; dz[nb++] = z; + } + return _label(nb,dx,dy,dz,tolerance,is_L2_norm); + } + + CImg _label(const unsigned int nb, const int *const dx, + const int *const dy, const int *const dz, + const Tfloat tolerance, const bool is_L2_norm) const { + CImg res(_width,_height,_depth); + const Tfloat _tolerance = _spectrum>1 && is_L2_norm?cimg::sqr(tolerance):tolerance; + + // Init label numbers. + ulongT *ptr = res.data(); + cimg_foroff(res,p) *(ptr++) = p; + + // For each neighbour-direction, label. + for (unsigned int n = 0; n& _system_strescape() { +#define cimg_system_strescape(c,s) case c : if (p!=ptrs) CImg(ptrs,(unsigned int)(p-ptrs),1,1,1,false).\ + move_to(list); \ + CImg(s,(unsigned int)std::strlen(s),1,1,1,false).move_to(list); ptrs = p + 1; break + CImgList list; + const T *ptrs = _data; + cimg_for(*this,p,T) switch ((int)*p) { + cimg_system_strescape('\\',"\\\\"); + cimg_system_strescape('\"',"\\\""); + cimg_system_strescape('!',"\"\\!\""); + cimg_system_strescape('`',"\\`"); + cimg_system_strescape('$',"\\$"); + } + if (ptrs(ptrs,(unsigned int)(end()-ptrs),1,1,1,false).move_to(list); + return (list>'x').move_to(*this); + } + + //@} + //--------------------------------- + // + //! \name Color Base Management + //@{ + //--------------------------------- + + //! Return colormap \e "default", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_default.jpg + **/ + static const CImg& default_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,256,1,3); + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap(0,index,0) = (Tuchar)r; + colormap(0,index,1) = (Tuchar)g; + colormap(0,index++,2) = (Tuchar)b; + } + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "HSV", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hsv.jpg + **/ + static const CImg& HSV_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + CImg tmp(1,256,1,3,1); + tmp.get_shared_channel(0).sequence(0,359); + colormap = tmp.HSVtoRGB(); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "lines", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_lines.jpg + **/ + static const CImg& lines_LUT256() { + static const unsigned char pal[] = { + 0,255,255,0,0,28,125,125,235,210,186,182,36,0,125,255, + 53,32,255,210,89,186,65,45,125,210,210,97,130,194,0,125, + 206,53,190,89,255,146,20,190,154,73,255,36,130,215,0,138, + 101,210,61,194,206,0,77,45,255,154,174,0,190,239,89,125, + 16,36,158,223,117,0,97,69,223,255,40,239,0,0,255,0, + 97,170,93,255,138,40,117,210,0,170,53,158,186,255,0,121, + 227,121,186,40,20,190,89,255,77,57,130,142,255,73,186,85, + 210,8,32,166,243,130,210,40,255,45,61,142,223,49,121,255, + 20,162,158,73,89,255,53,138,210,190,57,235,36,73,255,49, + 210,0,210,85,57,97,255,121,85,174,40,255,162,178,0,121, + 166,125,53,146,166,255,97,121,65,89,235,231,12,170,36,190, + 85,255,166,97,198,77,20,146,109,166,255,28,40,202,121,81, + 247,0,210,255,49,0,65,255,36,166,93,77,255,85,251,0, + 170,178,0,182,255,0,162,16,154,142,162,223,223,0,0,81, + 215,4,215,162,215,125,77,206,121,36,125,231,101,16,255,121, + 0,57,190,215,65,125,89,142,255,101,73,53,146,223,125,125, + 0,255,0,255,0,206,93,138,49,255,0,202,154,85,45,219, + 251,53,0,255,40,130,219,158,16,117,186,130,202,49,65,239, + 89,202,49,28,247,134,150,0,255,117,202,4,215,81,186,57, + 202,89,73,210,40,93,45,251,206,28,223,142,40,134,162,125, + 32,247,97,170,0,255,57,134,73,247,162,0,251,40,142,142, + 8,166,206,81,154,194,93,89,125,243,28,109,227,0,190,65, + 194,186,0,255,53,45,109,186,186,0,255,130,49,170,69,210, + 154,0,109,227,45,255,125,105,81,81,255,0,219,134,170,85, + 146,28,170,89,223,97,8,210,255,158,49,40,125,174,174,125, + 0,227,166,28,219,130,0,93,239,0,85,255,81,178,125,49, + 89,255,53,206,73,113,146,255,0,150,36,219,162,0,210,125, + 69,134,255,85,40,89,235,49,215,121,0,206,36,223,174,69, + 40,182,178,130,69,45,255,210,85,77,215,0,231,146,0,194, + 125,174,0,255,40,89,121,206,57,0,206,170,231,150,81,0, + 125,255,4,174,4,190,121,255,4,166,109,130,49,239,170,93, + 16,174,210,0,255,16,105,158,93,255,0,125,0,255,158,85, + 0,255,0,0,255,170,166,61,121,28,198,215,45,243,61,97, + 255,53,81,130,109,255,8,117,235,121,40,178,174,0,182,49, + 162,121,255,69,206,0,219,125,0,101,255,239,121,32,210,130, + 36,231,32,125,81,142,215,158,4,178,255,0,40,251,125,125, + 219,89,130,0,166,255,24,65,194,125,255,125,77,125,93,125, + 202,24,138,174,178,32,255,85,194,40,85,36,174,174,125,210, + 85,255,53,16,93,206,40,130,170,202,93,255,0,24,117,255, + 97,113,105,81,255,186,194,57,69,206,57,53,223,190,4,255, + 85,97,130,255,85,0,125,223,85,219,0,215,146,77,40,239, + 89,36,142,154,227,0,255,85,162,0,162,0,235,178,45,166, + 0,247,255,20,69,210,89,142,53,255,40,146,166,255,69,0, + 174,154,142,130,162,0,215,255,0,89,40,255,166,61,146,69, + 162,40,255,32,121,255,117,178,0,186,206,0,57,215,215,81, + 158,77,166,210,77,89,210,0,24,202,150,186,0,255,20,97, + 57,170,235,251,16,73,142,251,93,0,202,0,255,121,219,4, + 73,219,8,162,206,16,219,93,117,0,255,8,130,174,223,45 }; + static const CImg colormap(pal,1,256,1,3,false); + return colormap; + } + + //! Return colormap \e "hot", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hot.jpg + **/ + static const CImg& hot_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[1] = colormap[2] = colormap[3] = colormap[6] = colormap[7] = colormap[11] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cool", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cool.jpg + **/ + static const CImg& cool_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) colormap.assign(1,2,1,3).fill((T)0,(T)255,(T)255,(T)0,(T)255,(T)255).resize(1,256,1,3,3); + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "jet", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_jet.jpg + **/ + static const CImg& jet_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[2] = colormap[3] = colormap[5] = colormap[6] = colormap[8] = colormap[9] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "flag", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_flag.jpg + **/ + static const CImg& flag_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[0] = colormap[1] = colormap[5] = colormap[9] = colormap[10] = 255; + colormap.resize(1,256,1,3,0,2); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cube", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cube.jpg + **/ + static const CImg& cube_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,8,1,3,(T)0); + colormap[1] = colormap[3] = colormap[5] = colormap[7] = + colormap[10] = colormap[11] = colormap[12] = colormap[13] = + colormap[20] = colormap[21] = colormap[22] = colormap[23] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Convert pixel values from sRGB to RGB color spaces. + CImg& sRGBtoRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32)) + cimg_rofoff(*this,off) { + const Tfloat + sval = (Tfloat)_data[off]/255, + val = (Tfloat)(sval<=0.04045f?sval/12.92f:std::pow((sval + 0.055f)/(1.055f),2.4f)); + _data[off] = (T)cimg::cut(val*255,0,255); + } + return *this; + } + + //! Convert pixel values from sRGB to RGB color spaces \newinstance. + CImg get_sRGBtoRGB() const { + return CImg(*this,false).sRGBtoRGB(); + } + + //! Convert pixel values from RGB to sRGB color spaces. + CImg& RGBtosRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32)) + cimg_rofoff(*this,off) { + const Tfloat + val = (Tfloat)_data[off]/255, + sval = (Tfloat)(val<=0.0031308f?val*12.92f:1.055f*std::pow(val,0.416667f) - 0.055f); + _data[off] = (T)cimg::cut(sval*255,0,255); + } + return *this; + } + + //! Convert pixel values from RGB to sRGB color spaces \newinstance. + CImg get_RGBtosRGB() const { + return CImg(*this,false).RGBtosRGB(); + } + + //! Convert pixel values from RGB to HSI color spaces. + CImg& RGBtoHSI() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSI(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSI() const { + return CImg(*this,false).RGBtoHSI(); + } + + //! Convert pixel values from HSI to RGB color spaces. + CImg& HSItoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSItoRGB(): Instance is not a HSI image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSItoRGB() const { + return CImg< Tuchar>(*this,false).HSItoRGB(); + } + + //! Convert pixel values from RGB to HSL color spaces. + CImg& RGBtoHSL() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSL(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSL() const { + return CImg(*this,false).RGBtoHSL(); + } + + //! Convert pixel values from HSL to RGB color spaces. + CImg& HSLtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSLtoRGB(): Instance is not a HSL image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSLtoRGB() const { + return CImg(*this,false).HSLtoRGB(); + } + + //! Convert pixel values from RGB to HSV color spaces. + CImg& RGBtoHSV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSV(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSV() const { + return CImg(*this,false).RGBtoHSV(); + } + + //! Convert pixel values from HSV to RGB color spaces. + CImg& HSVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSVtoRGB(): Instance is not a HSV image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSVtoRGB() const { + return CImg(*this,false).HSVtoRGB(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& RGBtoYCbCr() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYCbCr(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,512)) + for (longT N = 0; N get_RGBtoYCbCr() const { + return CImg(*this,false).RGBtoYCbCr(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& YCbCrtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YCbCrtoRGB(): Instance is not a YCbCr image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,512)) + for (longT N = 0; N get_YCbCrtoRGB() const { + return CImg(*this,false).YCbCrtoRGB(); + } + + //! Convert pixel values from RGB to YUV color spaces. + CImg& RGBtoYUV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYUV(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,16384)) + for (longT N = 0; N get_RGBtoYUV() const { + return CImg(*this,false).RGBtoYUV(); + } + + //! Convert pixel values from YUV to RGB color spaces. + CImg& YUVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YUVtoRGB(): Instance is not a YUV image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,16384)) + for (longT N = 0; N get_YUVtoRGB() const { + return CImg< Tuchar>(*this,false).YUVtoRGB(); + } + + //! Convert pixel values from RGB to CMY color spaces. + CImg& RGBtoCMY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoCMY(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_RGBtoCMY() const { + return CImg(*this,false).RGBtoCMY(); + } + + //! Convert pixel values from CMY to RGB color spaces. + CImg& CMYtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoRGB(): Instance is not a CMY image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_CMYtoRGB() const { + return CImg(*this,false).CMYtoRGB(); + } + + //! Convert pixel values from CMY to CMYK color spaces. + CImg& CMYtoCMYK() { + return get_CMYtoCMYK().move_to(*this); + } + + //! Convert pixel values from CMY to CMYK color spaces \newinstance. + CImg get_CMYtoCMYK() const { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoCMYK(): Instance is not a CMY image.", + cimg_instance); + + CImg res(_width,_height,_depth,4); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024)) + for (longT N = 0; N=255) C = M = Y = 0; + else { const Tfloat K1 = 255 - K; C = 255*(C - K)/K1; M = 255*(M - K)/K1; Y = 255*(Y - K)/K1; } + pd1[N] = (Tfloat)cimg::cut(C,0,255), + pd2[N] = (Tfloat)cimg::cut(M,0,255), + pd3[N] = (Tfloat)cimg::cut(Y,0,255), + pd4[N] = (Tfloat)cimg::cut(K,0,255); + } + return res; + } + + //! Convert pixel values from CMYK to CMY color spaces. + CImg& CMYKtoCMY() { + return get_CMYKtoCMY().move_to(*this); + } + + //! Convert pixel values from CMYK to CMY color spaces \newinstance. + CImg get_CMYKtoCMY() const { + if (_spectrum!=4) + throw CImgInstanceException(_cimg_instance + "CMYKtoCMY(): Instance is not a CMYK image.", + cimg_instance); + + CImg res(_width,_height,_depth,3); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2), *ps4 = data(0,0,0,3); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024)) + for (longT N = 0; N& RGBtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoXYZ(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_RGBtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).RGBtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to RGB color spaces. + /** + \param use_D65 Tell to use the D65 illuminant (D50 otherwise). + **/ + CImg& XYZtoRGB(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoRGB(): Instance is not a XYZ image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_XYZtoRGB(const bool use_D65=true) const { + return CImg(*this,false).XYZtoRGB(use_D65); + } + + //! Convert pixel values from XYZ to Lab color spaces. + CImg& XYZtoLab(const bool use_D65=true) { +#define _cimg_Labf(x) (24389*(x)>216?cimg::cbrt(x):(24389*(x)/27 + 16)/116) + + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoLab(): Instance is not a XYZ image.", + cimg_instance); + const CImg white = CImg(1,1,1,3,255).RGBtoXYZ(use_D65); + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128)) + for (longT N = 0; N get_XYZtoLab(const bool use_D65=true) const { + return CImg(*this,false).XYZtoLab(use_D65); + } + + //! Convert pixel values from Lab to XYZ color spaces. + CImg& LabtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "LabtoXYZ(): Instance is not a Lab image.", + cimg_instance); + const CImg white = CImg(1,1,1,3,255).RGBtoXYZ(use_D65); + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128)) + for (longT N = 0; N216?cX*cX*cX:(116*cX - 16)*27/24389), + Y = (Tfloat)(27*L>216?cY*cY*cY:27*L/24389), + Z = (Tfloat)(24389*cZ>216?cZ*cZ*cZ:(116*cZ - 16)*27/24389); + p1[N] = (T)(X*white[0]); + p2[N] = (T)(Y*white[1]); + p3[N] = (T)(Z*white[2]); + } + return *this; + } + + //! Convert pixel values from Lab to XYZ color spaces \newinstance. + CImg get_LabtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).LabtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to xyY color spaces. + CImg& XYZtoxyY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoxyY(): Instance is not a XYZ image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096)) + for (longT N = 0; N0?sum:1; + p1[N] = (T)(X/nsum); + p2[N] = (T)(Y/nsum); + p3[N] = (T)Y; + } + return *this; + } + + //! Convert pixel values from XYZ to xyY color spaces \newinstance. + CImg get_XYZtoxyY() const { + return CImg(*this,false).XYZtoxyY(); + } + + //! Convert pixel values from xyY pixels to XYZ color spaces. + CImg& xyYtoXYZ() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "xyYtoXYZ(): Instance is not a xyY image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096)) + for (longT N = 0; N0?py:1; + p1[N] = (T)(px*Y/ny); + p2[N] = (T)Y; + p3[N] = (T)((1 - px - py)*Y/ny); + } + return *this; + } + + //! Convert pixel values from xyY pixels to XYZ color spaces \newinstance. + CImg get_xyYtoXYZ() const { + return CImg(*this,false).xyYtoXYZ(); + } + + //! Convert pixel values from RGB to Lab color spaces. + CImg& RGBtoLab(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoLab(use_D65); + } + + //! Convert pixel values from RGB to Lab color spaces \newinstance. + CImg get_RGBtoLab(const bool use_D65=true) const { + return CImg(*this,false).RGBtoLab(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces. + CImg& LabtoRGB(const bool use_D65=true) { + return LabtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces \newinstance. + CImg get_LabtoRGB(const bool use_D65=true) const { + return CImg(*this,false).LabtoRGB(use_D65); + } + + //! Convert pixel values from RGB to xyY color spaces. + CImg& RGBtoxyY(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoxyY(); + } + + //! Convert pixel values from RGB to xyY color spaces \newinstance. + CImg get_RGBtoxyY(const bool use_D65=true) const { + return CImg(*this,false).RGBtoxyY(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces. + CImg& xyYtoRGB(const bool use_D65=true) { + return xyYtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces \newinstance. + CImg get_xyYtoRGB(const bool use_D65=true) const { + return CImg(*this,false).xyYtoRGB(use_D65); + } + + //! Convert pixel values from RGB to CMYK color spaces. + CImg& RGBtoCMYK() { + return RGBtoCMY().CMYtoCMYK(); + } + + //! Convert pixel values from RGB to CMYK color spaces \newinstance. + CImg get_RGBtoCMYK() const { + return CImg(*this,false).RGBtoCMYK(); + } + + //! Convert pixel values from CMYK to RGB color spaces. + CImg& CMYKtoRGB() { + return CMYKtoCMY().CMYtoRGB(); + } + + //! Convert pixel values from CMYK to RGB color spaces \newinstance. + CImg get_CMYKtoRGB() const { + return CImg(*this,false).CMYKtoRGB(); + } + + //@} + //------------------------------------------ + // + //! \name Geometric / Spatial Manipulation + //@{ + //------------------------------------------ + + static float _cimg_lanczos(const float x) { + if (x<=-2 || x>=2) return 0; + const float a = (float)cimg::PI*x, b = 0.5f*a; + return (float)(x?std::sin(a)*std::sin(b)/(a*b):1); + } + + //! Resize image to new dimensions. + /** + \param size_x Number of columns (new size along the X-axis). + \param size_y Number of rows (new size along the Y-axis). + \param size_z Number of slices (new size along the Z-axis). + \param size_c Number of vector-channels (new size along the C-axis). + \param interpolation_type Method of interpolation: + - -1 = no interpolation: raw memory resizing. + - 0 = no interpolation: additional space is filled according to \p boundary_conditions. + - 1 = nearest-neighbor interpolation. + - 2 = moving average interpolation. + - 3 = linear interpolation. + - 4 = grid interpolation. + - 5 = cubic interpolation. + - 6 = lanczos interpolation. + \param boundary_conditions Type of boundary conditions used if necessary. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). + **/ + CImg& resize(const int size_x, const int size_y=-100, + const int size_z=-100, const int size_c=-100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + if (!size_x || !size_y || !size_z || !size_c) return assign(); + const unsigned int + _sx = (unsigned int)(size_x<0?-size_x*width()/100:size_x), + _sy = (unsigned int)(size_y<0?-size_y*height()/100:size_y), + _sz = (unsigned int)(size_z<0?-size_z*depth()/100:size_z), + _sc = (unsigned int)(size_c<0?-size_c*spectrum()/100:size_c), + sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1; + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return *this; + if (is_empty()) return assign(sx,sy,sz,sc,(T)0); + if (interpolation_type==-1 && sx*sy*sz*sc==size()) { + _width = sx; _height = sy; _depth = sz; _spectrum = sc; + return *this; + } + return get_resize(sx,sy,sz,sc,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c).move_to(*this); + } + + //! Resize image to new dimensions \newinstance. + CImg get_resize(const int size_x, const int size_y = -100, + const int size_z = -100, const int size_c = -100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + if (centering_x<0 || centering_x>1 || centering_y<0 || centering_y>1 || + centering_z<0 || centering_z>1 || centering_c<0 || centering_c>1) + throw CImgArgumentException(_cimg_instance + "resize(): Specified centering arguments (%g,%g,%g,%g) are outside range [0,1].", + cimg_instance, + centering_x,centering_y,centering_z,centering_c); + + if (!size_x || !size_y || !size_z || !size_c) return CImg(); + const unsigned int + sx = std::max(1U,(unsigned int)(size_x>=0?size_x:-size_x*width()/100)), + sy = std::max(1U,(unsigned int)(size_y>=0?size_y:-size_y*height()/100)), + sz = std::max(1U,(unsigned int)(size_z>=0?size_z:-size_z*depth()/100)), + sc = std::max(1U,(unsigned int)(size_c>=0?size_c:-size_c*spectrum()/100)); + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return +*this; + if (is_empty()) return CImg(sx,sy,sz,sc,(T)0); + CImg res; + switch (interpolation_type) { + + // Raw resizing. + // + case -1 : + std::memcpy(res.assign(sx,sy,sz,sc,(T)0)._data,_data,sizeof(T)*std::min(size(),(ulongT)sx*sy*sz*sc)); + break; + + // No interpolation. + // + case 0 : { + const int + xc = (int)(centering_x*((int)sx - width())), + yc = (int)(centering_y*((int)sy - height())), + zc = (int)(centering_z*((int)sz - depth())), + cc = (int)(centering_c*((int)sc - spectrum())); + + switch (boundary_conditions) { + case 3 : { // Mirror + res.assign(sx,sy,sz,sc); + const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1024*1024)) + cimg_forXYZC(res,x,y,z,c) { + const int + mx = cimg::mod(x - xc,w2), my = cimg::mod(y - yc,h2), + mz = cimg::mod(z - zc,d2), mc = cimg::mod(c - cc,s2); + res(x,y,z,c) = (*this)(mx sprite; + if (xc>0) { // X-backward + res.get_crop(xc,yc,zc,cc,xc,yc + height() - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc - 1; x>=0; --x) res.draw_image(x,yc,zc,cc,sprite); + } + if (xc + width()<(int)sx) { // X-forward + res.get_crop(xc + width() - 1,yc,zc,cc,xc + width() - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc + width(); x<(int)sx; ++x) res.draw_image(x,yc,zc,cc,sprite); + } + if (yc>0) { // Y-backward + res.get_crop(0,yc,zc,cc,sx - 1,yc,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc - 1; y>=0; --y) res.draw_image(0,y,zc,cc,sprite); + } + if (yc + height()<(int)sy) { // Y-forward + res.get_crop(0,yc + height() - 1,zc,cc,sx - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc + height(); y<(int)sy; ++y) res.draw_image(0,y,zc,cc,sprite); + } + if (zc>0) { // Z-backward + res.get_crop(0,0,zc,cc,sx - 1,sy - 1,zc,cc + spectrum() - 1).move_to(sprite); + for (int z = zc - 1; z>=0; --z) res.draw_image(0,0,z,cc,sprite); + } + if (zc + depth()<(int)sz) { // Z-forward + res.get_crop(0,0,zc +depth() - 1,cc,sx - 1,sy - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int z = zc + depth(); z<(int)sz; ++z) res.draw_image(0,0,z,cc,sprite); + } + if (cc>0) { // C-backward + res.get_crop(0,0,0,cc,sx - 1,sy - 1,sz - 1,cc).move_to(sprite); + for (int c = cc - 1; c>=0; --c) res.draw_image(0,0,0,c,sprite); + } + if (cc + spectrum()<(int)sc) { // C-forward + res.get_crop(0,0,0,cc + spectrum() - 1,sx - 1,sy - 1,sz - 1,cc + spectrum() - 1).move_to(sprite); + for (int c = cc + spectrum(); c<(int)sc; ++c) res.draw_image(0,0,0,c,sprite); + } + } break; + default : // Dirichlet + res.assign(sx,sy,sz,sc,(T)0).draw_image(xc,yc,zc,cc,*this); + } + break; + } break; + + // Nearest neighbor interpolation. + // + case 1 : { + res.assign(sx,sy,sz,sc); + CImg off_x(sx), off_y(sy + 1), off_z(sz + 1), off_c(sc + 1); + const ulongT + wh = (ulongT)_width*_height, + whd = (ulongT)_width*_height*_depth, + sxy = (ulongT)sx*sy, + sxyz = (ulongT)sx*sy*sz, + one = (ulongT)1; + if (sx==_width) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + cimg_forX(res,x) { + const ulongT old = curr; + curr = (x + one)*_width/sx; + *(poff_x++) = curr - old; + } + } + if (sy==_height) off_y.fill(_width); + else { + ulongT *poff_y = off_y._data, curr = 0; + cimg_forY(res,y) { + const ulongT old = curr; + curr = (y + one)*_height/sy; + *(poff_y++) = _width*(curr - old); + } + *poff_y = 0; + } + if (sz==_depth) off_z.fill(wh); + else { + ulongT *poff_z = off_z._data, curr = 0; + cimg_forZ(res,z) { + const ulongT old = curr; + curr = (z + one)*_depth/sz; + *(poff_z++) = wh*(curr - old); + } + *poff_z = 0; + } + if (sc==_spectrum) off_c.fill(whd); + else { + ulongT *poff_c = off_c._data, curr = 0; + cimg_forC(res,c) { + const ulongT old = curr; + curr = (c + one)*_spectrum/sc; + *(poff_c++) = whd*(curr - old); + } + *poff_c = 0; + } + + T *ptrd = res._data; + const T* ptrc = _data; + const ulongT *poff_c = off_c._data; + for (unsigned int c = 0; c_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(res); + else { + CImg tmp(sx,_height,_depth,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sx>=256 && _height*_depth*_spectrum>=256)) + cimg_forYZC(tmp,y,z,v) { + for (unsigned int a = _width*sx, b = _width, c = sx, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + tmp(t,y,z,v)+=(Tfloat)(*this)(s,y,z,v)*d; + if (!b) { tmp(t++,y,z,v)/=_width; b = _width; } + if (!c) { ++s; c = sx; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sy!=_height) { + if (sy>_height) get_resize(sx,sy,_depth,_spectrum,1).move_to(res); + else { + CImg tmp(sx,sy,_depth,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sy>=256 && _width*_depth*_spectrum>=256)) + cimg_forXZC(tmp,x,z,v) { + for (unsigned int a = _height*sy, b = _height, c = sy, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,t,z,v)+=(Tfloat)(*this)(x,s,z,v)*d; + else tmp(x,t,z,v)+=(Tfloat)res(x,s,z,v)*d; + if (!b) { tmp(x,t++,z,v)/=_height; b = _height; } + if (!c) { ++s; c = sy; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sz!=_depth) { + if (sz>_depth) get_resize(sx,sy,sz,_spectrum,1).move_to(res); + else { + CImg tmp(sx,sy,sz,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sz>=256 && _width*_height*_spectrum>=256)) + cimg_forXYC(tmp,x,y,v) { + for (unsigned int a = _depth*sz, b = _depth, c = sz, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,y,t,v)+=(Tfloat)(*this)(x,y,s,v)*d; + else tmp(x,y,t,v)+=(Tfloat)res(x,y,s,v)*d; + if (!b) { tmp(x,y,t++,v)/=_depth; b = _depth; } + if (!c) { ++s; c = sz; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sc!=_spectrum) { + if (sc>_spectrum) get_resize(sx,sy,sz,sc,1).move_to(res); + else { + CImg tmp(sx,sy,sz,sc,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sc>=256 && _width*_height*_depth>=256)) + cimg_forXYZ(tmp,x,y,z) { + for (unsigned int a = _spectrum*sc, b = _spectrum, c = sc, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,y,z,t)+=(Tfloat)(*this)(x,y,z,s)*d; + else tmp(x,y,z,t)+=(Tfloat)res(x,y,z,s)*d; + if (!b) { tmp(x,y,z,t++)/=_spectrum; b = _spectrum; } + if (!c) { ++s; c = sc; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + } break; + + // Linear interpolation. + // + case 3 : { + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *ptrs = data(0,y,z,c), *const ptrsmax = ptrs + _width - 1; + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *ptrs = resx.data(x,0,z,c), *const ptrsmax = ptrs + (_height - 1)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *ptrs = resy.data(x,y,0,c), *const ptrsmax = ptrs + (_depth - 1)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *ptrs = resz.data(x,y,z,0), *const ptrsmax = ptrs + (_spectrum - 1)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrs resx, resy, resz, resc; + if (sx!=_width) { + if (sx<_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + resx.assign(sx,_height,_depth,_spectrum,(T)0); + const int dx = (int)(2*sx), dy = 2*width(); + int err = (int)(dy + centering_x*(sx*dy/width() - dy)), xs = 0; + cimg_forX(resx,x) if ((err-=dy)<=0) { + cimg_forYZC(resx,y,z,c) resx(x,y,z,c) = (*this)(xs,y,z,c); + ++xs; + err+=dx; + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (sy<_height) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + resy.assign(sx,sy,_depth,_spectrum,(T)0); + const int dx = (int)(2*sy), dy = 2*height(); + int err = (int)(dy + centering_y*(sy*dy/height() - dy)), ys = 0; + cimg_forY(resy,y) if ((err-=dy)<=0) { + cimg_forXZC(resy,x,z,c) resy(x,y,z,c) = resx(x,ys,z,c); + ++ys; + err+=dx; + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (sz<_depth) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + resz.assign(sx,sy,sz,_spectrum,(T)0); + const int dx = (int)(2*sz), dy = 2*depth(); + int err = (int)(dy + centering_z*(sz*dy/depth() - dy)), zs = 0; + cimg_forZ(resz,z) if ((err-=dy)<=0) { + cimg_forXYC(resz,x,y,c) resz(x,y,z,c) = resy(x,y,zs,c); + ++zs; + err+=dx; + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (sc<_spectrum) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + resc.assign(sx,sy,sz,sc,(T)0); + const int dx = (int)(2*sc), dy = 2*spectrum(); + int err = (int)(dy + centering_c*(sc*dy/spectrum() - dy)), cs = 0; + cimg_forC(resc,c) if ((err-=dy)<=0) { + cimg_forXYZ(resc,x,y,z) resc(x,y,z,c) = resz(x,y,z,cs); + ++cs; + err+=dx; + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Cubic interpolation. + // + case 5 : { + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_width - 2); + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - 1):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + 1):val1, + val3 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sx):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sx):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxy):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxyz):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Lanczos interpolation. + // + case 6 : { + const double vmin = (double)cimg::type::min(), vmax = (double)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + 1, + *const ptrsmax = ptrs0 + (_width - 2); + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - 1):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + 1):val2, + val4 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sx, + *const ptrsmax = ptrs0 + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sx):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sx):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sx):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxy, + *const ptrsmax = ptrs0 + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sxy):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxy):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxyz, + *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sxyz):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxyz):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Unknown interpolation. + // + default : + throw CImgArgumentException(_cimg_instance + "resize(): Invalid specified interpolation %d " + "(should be { -1=raw | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | " + "5=cubic | 6=lanczos }).", + cimg_instance, + interpolation_type); + } + return res; + } + + //! Resize image to dimensions of another image. + /** + \param src Reference image used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + template + CImg& resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of another image \newinstance. + template + CImg get_resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window. + /** + \param disp Reference display window used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + CImg& resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window \newinstance. + CImg get_resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to half-size along XY axes, using an optimized filter. + CImg& resize_halfXY() { + return get_resize_halfXY().move_to(*this); + } + + //! Resize image to half-size along XY axes, using an optimized filter \newinstance. + CImg get_resize_halfXY() const { + if (is_empty()) return *this; + static const Tfloat kernel[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f, + 0.1231940459f, 0.1935127547f, 0.1231940459f, + 0.07842776544f, 0.1231940459f, 0.07842776544f }; + CImg I(9), res(_width/2,_height/2,_depth,_spectrum); + T *ptrd = res._data; + cimg_forZC(*this,z,c) cimg_for3x3(*this,x,y,z,c,I,T) + if (x%2 && y%2) *(ptrd++) = (T) + (I[0]*kernel[0] + I[1]*kernel[1] + I[2]*kernel[2] + + I[3]*kernel[3] + I[4]*kernel[4] + I[5]*kernel[5] + + I[6]*kernel[6] + I[7]*kernel[7] + I[8]*kernel[8]); + return res; + } + + //! Resize image to double-size, using the Scale2X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_doubleXY() { + return get_resize_doubleXY().move_to(*this); + } + + //! Resize image to double-size, using the Scale2X algorithm \newinstance. + CImg get_resize_doubleXY() const { +#define _cimg_gs2x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=(res)._width, ptrd2+=(res)._width) + +#define _cimg_gs2x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs2x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(_width<<1,_height<<1,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width; + _cimg_gs2x_for3x3(*this,x,y,z,c,I,T) { + if (Icp!=Icn && Ipc!=Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = Ipc==Icn?Ipc:Icc; + *(ptrd2++) = Icn==Inc?Inc:Icc; + } else { *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; } + } + } + return res; + } + + //! Resize image to triple-size, using the Scale3X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_tripleXY() { + return get_resize_tripleXY().move_to(*this); + } + + //! Resize image to triple-size, using the Scale3X algorithm \newinstance. + CImg get_resize_tripleXY() const { +#define _cimg_gs3x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=2*(res)._width, ptrd2+=2*(res)._width, ptrd3+=2*(res)._width) + +#define _cimg_gs3x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs3x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(3*_width,3*_height,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width, + *ptrd3 = ptrd2 + res._width; + _cimg_gs3x_for3x3(*this,x,y,z,c,I,T) { + if (Icp != Icn && Ipc != Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = (Ipc==Icp && Icc!=Inp) || (Icp==Inc && Icc!=Ipp)?Icp:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = (Ipc==Icp && Icc!=Ipn) || (Ipc==Icn && Icc!=Ipp)?Ipc:Icc; + *(ptrd2++) = Icc; + *(ptrd2++) = (Icp==Inc && Icc!=Inn) || (Icn==Inc && Icc!=Inp)?Inc:Icc; + *(ptrd3++) = Ipc==Icn?Ipc:Icc; + *(ptrd3++) = (Ipc==Icn && Icc!=Inn) || (Icn==Inc && Icc!=Ipn)?Icn:Icc; + *(ptrd3++) = Icn==Inc?Inc:Icc; + } else { + *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd1++) = Icc; + *(ptrd2++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; + *(ptrd3++) = Icc; *(ptrd3++) = Icc; *(ptrd3++) = Icc; + } + } + } + return res; + } + + //! Mirror image content along specified axis. + /** + \param axis Mirror axis + **/ + CImg& mirror(const char axis) { + if (is_empty()) return *this; + T *pf, *pb, *buf = 0; + switch (cimg::lowercase(axis)) { + case 'x' : { + pf = _data; pb = data(_width - 1); + const unsigned int width2 = _width/2; + for (unsigned int yzv = 0; yzv<_height*_depth*_spectrum; ++yzv) { + for (unsigned int x = 0; x get_mirror(const char axis) const { + return (+*this).mirror(axis); + } + + //! Mirror image content along specified axes. + /** + \param axes Mirror axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& mirror(const char *const axes) { + for (const char *s = axes; *s; ++s) mirror(*s); + return *this; + } + + //! Mirror image content along specified axes \newinstance. + CImg get_mirror(const char *const axes) const { + return (+*this).mirror(axes); + } + + //! Shift image content. + /** + \param delta_x Amount of displacement along the X-axis. + \param delta_y Amount of displacement along the Y-axis. + \param delta_z Amount of displacement along the Z-axis. + \param delta_c Amount of displacement along the C-axis. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const unsigned int boundary_conditions=0) { + if (is_empty()) return *this; + if (boundary_conditions==3) + return get_crop(-delta_x,-delta_y,-delta_z,-delta_c, + width() - delta_x - 1, + height() - delta_y - 1, + depth() - delta_z - 1, + spectrum() - delta_c - 1,3).move_to(*this); + if (delta_x) // Shift along X-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_x,width()), ndelta_x = (ml<=width()/2)?ml:(ml-width()); + if (!ndelta_x) return *this; + CImg buf(cimg::abs(ndelta_x)); + if (ndelta_x>0) cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(0,y,z,c),ndelta_x*sizeof(T)); + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + std::memcpy(data(_width-ndelta_x,y,z,c),buf,ndelta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(_width + ndelta_x,y,z,c),-ndelta_x*sizeof(T)); + std::memmove(data(-ndelta_x,y,z,c),data(0,y,z,c),(_width + ndelta_x)*sizeof(T)); + std::memcpy(data(0,y,z,c),buf,-ndelta_x*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_x<0) { + const int ndelta_x = (-delta_x>=width())?width() - 1:-delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(_width - 1,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width())?width() - 1:delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(ndelta_x,y,z,c),data(0,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(0,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width()) return fill((T)0); + if (delta_x<0) cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(-delta_x,y,z,c),(_width + delta_x)*sizeof(T)); + std::memset(data(_width + delta_x,y,z,c),0,-delta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memmove(data(delta_x,y,z,c),data(0,y,z,c),(_width-delta_x)*sizeof(T)); + std::memset(data(0,y,z,c),0,delta_x*sizeof(T)); + } + } + + if (delta_y) // Shift along Y-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_y,height()), ndelta_y = (ml<=height()/2)?ml:(ml-height()); + if (!ndelta_y) return *this; + CImg buf(width(),cimg::abs(ndelta_y)); + if (ndelta_y>0) cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,0,z,c),_width*ndelta_y*sizeof(T)); + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + std::memcpy(data(0,_height-ndelta_y,z,c),buf,_width*ndelta_y*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,_height + ndelta_y,z,c),-ndelta_y*_width*sizeof(T)); + std::memmove(data(0,-ndelta_y,z,c),data(0,0,z,c),_width*(_height + ndelta_y)*sizeof(T)); + std::memcpy(data(0,0,z,c),buf,-ndelta_y*_width*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_y<0) { + const int ndelta_y = (-delta_y>=height())?height() - 1:-delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,_height-ndelta_y,z,c), *ptrs = data(0,_height - 1,z,c); + for (int l = 0; l=height())?height() - 1:delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,ndelta_y,z,c),data(0,0,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,1,z,c), *ptrs = data(0,0,z,c); + for (int l = 0; l=height()) return fill((T)0); + if (delta_y<0) cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,-delta_y,z,c),_width*(_height + delta_y)*sizeof(T)); + std::memset(data(0,_height + delta_y,z,c),0,-delta_y*_width*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memmove(data(0,delta_y,z,c),data(0,0,z,c),_width*(_height-delta_y)*sizeof(T)); + std::memset(data(0,0,z,c),0,delta_y*_width*sizeof(T)); + } + } + + if (delta_z) // Shift along Z-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_z,depth()), ndelta_z = (ml<=depth()/2)?ml:(ml-depth()); + if (!ndelta_z) return *this; + CImg buf(width(),height(),cimg::abs(ndelta_z)); + if (ndelta_z>0) cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,0,c),_width*_height*ndelta_z*sizeof(T)); + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,_depth-ndelta_z,c),buf,_width*_height*ndelta_z*sizeof(T)); + } else cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,_depth + ndelta_z,c),-ndelta_z*_width*_height*sizeof(T)); + std::memmove(data(0,0,-ndelta_z,c),data(0,0,0,c),_width*_height*(_depth + ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,0,c),buf,-ndelta_z*_width*_height*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_z<0) { + const int ndelta_z = (-delta_z>=depth())?depth() - 1:-delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,_depth-ndelta_z,c), *ptrs = data(0,0,_depth - 1,c); + for (int l = 0; l=depth())?depth() - 1:delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,ndelta_z,c),data(0,0,0,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,1,c), *ptrs = data(0,0,0,c); + for (int l = 0; l=depth()) return fill((T)0); + if (delta_z<0) cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,-delta_z,c),_width*_height*(_depth + delta_z)*sizeof(T)); + std::memset(data(0,0,_depth + delta_z,c),0,_width*_height*(-delta_z)*sizeof(T)); + } else cimg_forC(*this,c) { + std::memmove(data(0,0,delta_z,c),data(0,0,0,c),_width*_height*(_depth-delta_z)*sizeof(T)); + std::memset(data(0,0,0,c),0,delta_z*_width*_height*sizeof(T)); + } + } + + if (delta_c) // Shift along C-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_c,spectrum()), ndelta_c = (ml<=spectrum()/2)?ml:(ml-spectrum()); + if (!ndelta_c) return *this; + CImg buf(width(),height(),depth(),cimg::abs(ndelta_c)); + if (ndelta_c>0) { + std::memcpy(buf,_data,_width*_height*_depth*ndelta_c*sizeof(T)); + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + std::memcpy(data(0,0,0,_spectrum-ndelta_c),buf,_width*_height*_depth*ndelta_c*sizeof(T)); + } else { + std::memcpy(buf,data(0,0,0,_spectrum + ndelta_c),-ndelta_c*_width*_height*_depth*sizeof(T)); + std::memmove(data(0,0,0,-ndelta_c),_data,_width*_height*_depth*(_spectrum + ndelta_c)*sizeof(T)); + std::memcpy(_data,buf,-ndelta_c*_width*_height*_depth*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_c<0) { + const int ndelta_c = (-delta_c>=spectrum())?spectrum() - 1:-delta_c; + if (!ndelta_c) return *this; + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,_spectrum-ndelta_c), *ptrs = data(0,0,0,_spectrum - 1); + for (int l = 0; l=spectrum())?spectrum() - 1:delta_c; + if (!ndelta_c) return *this; + std::memmove(data(0,0,0,ndelta_c),_data,_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,1); + for (int l = 0; l=spectrum()) return fill((T)0); + if (delta_c<0) { + std::memmove(_data,data(0,0,0,-delta_c),_width*_height*_depth*(_spectrum + delta_c)*sizeof(T)); + std::memset(data(0,0,0,_spectrum + delta_c),0,_width*_height*_depth*(-delta_c)*sizeof(T)); + } else { + std::memmove(data(0,0,0,delta_c),_data,_width*_height*_depth*(_spectrum-delta_c)*sizeof(T)); + std::memset(_data,0,delta_c*_width*_height*_depth*sizeof(T)); + } + } + return *this; + } + + //! Shift image content \newinstance. + CImg get_shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const unsigned int boundary_conditions=0) const { + return (+*this).shift(delta_x,delta_y,delta_z,delta_c,boundary_conditions); + } + + //! Permute axes order. + /** + \param axes_order Axes permutations, as a C-string of 4 characters. + This function permutes image content regarding the specified axes permutation. + **/ + CImg& permute_axes(const char *const axes_order) { + return get_permute_axes(axes_order).move_to(*this); + } + + //! Permute axes order \newinstance. + CImg get_permute_axes(const char *const axes_order) const { + const T foo = (T)0; + return _permute_axes(axes_order,foo); + } + + template + CImg _permute_axes(const char *const axes_order, const t&) const { + if (is_empty() || !axes_order) return CImg(*this,false); + CImg res; + const T* ptrs = _data; + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = (unsigned char)c; } + } + if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { + const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + ulongT wh, whd; + switch (code) { + case 0x0123 : // xyzc + return +*this; + case 0x0132 : // xycz + res.assign(_width,_height,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0213 : // xzyc + res.assign(_width,_depth,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x0231 : // xzcy + res.assign(_width,_depth,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x0312 : // xcyz + res.assign(_width,_spectrum,_height,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0321 : // xczy + res.assign(_width,_spectrum,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x1023 : // yxzc + res.assign(_height,_width,_depth,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1032 : // yxcz + res.assign(_height,_width,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1203 : // yzxc + res.assign(_height,_depth,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1230 : // yzcx + res.assign(_height,_depth,_spectrum,_width); + switch (_width) { + case 1 : { + t *ptr_r = res.data(0,0,0,0); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)*(ptrs++); + } + } break; + case 2 : { + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + ptrs+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + ptrs+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA + t + *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), + *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + *(ptr_a++) = (t)ptrs[3]; + ptrs+=4; + } + } break; + default : { + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++); + return res; + } + } + break; + case 0x1302 : // ycxz + res.assign(_height,_spectrum,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1320 : // yczx + res.assign(_height,_spectrum,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2013 : // zxyc + res.assign(_depth,_width,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2031 : // zxcy + res.assign(_depth,_width,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2103 : // zyxc + res.assign(_depth,_height,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2130 : // zycx + res.assign(_depth,_height,_spectrum,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2301 : // zcxy + res.assign(_depth,_spectrum,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2310 : // zcyx + res.assign(_depth,_spectrum,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3012 : // cxyz + res.assign(_spectrum,_width,_height,_depth); + switch (_spectrum) { + case 1 : { + const T *ptr_r = data(0,0,0,0); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++); + } break; + case 2 : { + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd[3] = (t)*(ptr_a++); + ptrd+=4; + } + } break; + default : { + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++); + } + } + break; + case 0x3021 : // cxzy + res.assign(_spectrum,_width,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3102 : // cyxz + res.assign(_spectrum,_height,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x3120 : // cyzx + res.assign(_spectrum,_height,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3201 : // czxy + res.assign(_spectrum,_depth,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3210 : // czyx + res.assign(_spectrum,_depth,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++); + break; + } + } + if (!res) + throw CImgArgumentException(_cimg_instance + "permute_axes(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + return res; + } + + //! Unroll pixel values along specified axis. + /** + \param axis Unroll axis (can be \c 'x', \c 'y', \c 'z' or c 'c'). + **/ + CImg& unroll(const char axis) { + const unsigned int siz = (unsigned int)size(); + if (siz) switch (cimg::lowercase(axis)) { + case 'x' : _width = siz; _height = _depth = _spectrum = 1; break; + case 'y' : _height = siz; _width = _depth = _spectrum = 1; break; + case 'z' : _depth = siz; _width = _height = _spectrum = 1; break; + case 'c' : _spectrum = siz; _width = _height = _depth = 1; break; + } + return *this; + } + + //! Unroll pixel values along specified axis \newinstance. + CImg get_unroll(const char axis) const { + return (+*this).unroll(axis); + } + + //! Rotate image with arbitrary angle. + /** + \param angle Rotation angle, in degrees. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. + Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \note The size of the image is modified. + **/ + CImg& rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle \newinstance. + CImg get_rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res; + const float nangle = cimg::mod(angle,360.f); + if (boundary_conditions!=1 && cimg::mod(nangle,90.f)==0) { // Optimized version for orthogonal angles + const int wm1 = width() - 1, hm1 = height() - 1; + const int iangle = (int)nangle/90; + switch (iangle) { + case 1 : { // 90 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(y,hm1 - x,z,c); + } break; + case 2 : { // 180 deg + res.assign(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - x,hm1 - y,z,c); + } break; + case 3 : { // 270 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - y,x,z,c); + } break; + default : // 0 deg + return *this; + } + } else { // Generic angle + const float + rad = (float)(nangle*cimg::PI/180.), + ca = (float)std::cos(rad), sa = (float)std::sin(rad), + ux = cimg::abs((_width - 1)*ca), uy = cimg::abs((_width - 1)*sa), + vx = cimg::abs((_height - 1)*sa), vy = cimg::abs((_height - 1)*ca), + w2 = 0.5f*(_width - 1), h2 = 0.5f*(_height - 1); + res.assign((int)cimg::round(1 + ux + vx),(int)cimg::round(1 + uy + vy),_depth,_spectrum); + const float rw2 = 0.5f*(res._width - 1), rh2 = 0.5f*(res._height - 1); + _rotate(res,nangle,interpolation,boundary_conditions,w2,h2,rw2,rh2); + } + return res; + } + + //! Rotate image with arbitrary angle, around a center point. + /** + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param interpolation Type of interpolation, { 0=nearest | 1=linear | 2=cubic | 3=mirror }. + \param boundary_conditions Boundary conditions, { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) { + return get_rotate(angle,cx,cy,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle, around a center point \newinstance. + CImg get_rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + _rotate(res,angle,interpolation,boundary_conditions,cx,cy,cx,cy); + return res; + } + + // [internal] Perform 2D rotation with arbitrary angle. + void _rotate(CImg& res, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, + const float rw2, const float rh2) const { + const float + rad = (float)(angle*cimg::PI/180.), + ca = (float)std::cos(rad), sa = (float)std::sin(rad); + + switch (boundary_conditions) { + case 3 : { // Mirror + + switch (interpolation) { + case 2 : { // Cubic interpolation + const float ww = 2.f*width(), hh = 2.f*height(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2, + mx = cimg::mod(w2 + xc*ca + yc*sa,ww), + my = cimg::mod(h2 - xc*sa + yc*ca,hh); + res(x,y,z,c) = _cubic_atXY_c(mx{ 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. + Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(u,v,w,nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) const { + if (is_empty()) return *this; + CImg res; + const float + w1 = _width - 1, h1 = _height - 1, d1 = _depth -1, + w2 = 0.5f*w1, h2 = 0.5f*h1, d2 = 0.5f*d1; + CImg R = CImg::rotation_matrix(u,v,w,angle); + const CImg + X = R*CImg(8,3,1,1, + 0.f,w1,w1,0.f,0.f,w1,w1,0.f, + 0.f,0.f,h1,h1,0.f,0.f,h1,h1, + 0.f,0.f,0.f,0.f,d1,d1,d1,d1); + float + xm, xM = X.get_shared_row(0).max_min(xm), + ym, yM = X.get_shared_row(1).max_min(ym), + zm, zM = X.get_shared_row(2).max_min(zm); + const int + dx = (int)cimg::round(xM - xm), + dy = (int)cimg::round(yM - ym), + dz = (int)cimg::round(zM - zm); + R.transpose(); + res.assign(1 + dx,1 + dy,1 + dz,_spectrum); + const float rw2 = 0.5f*dx, rh2 = 0.5f*dy, rd2 = 0.5f*dz; + _rotate(res,R,interpolation,boundary_conditions,w2,h2,d2,rw2,rh2,rd2); + return res; + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point. + /** + \param u X-coordinate of the 3D rotation axis. + \param v Y-coordinate of the 3D rotation axis. + \param w Z-coordinate of the 3D rotation axis. + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param cz Z-coordinate of the rotation center. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic | 3=mirror }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(u,v,w,nangle,cx,cy,cz,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + CImg R = CImg::rotation_matrix(u,v,w,-angle); + _rotate(res,R,interpolation,boundary_conditions,cx,cy,cz,cx,cy,cz); + return res; + } + + // [internal] Perform 3D rotation with arbitrary axis and angle. + void _rotate(CImg& res, const CImg& R, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, const float d2, + const float rw2, const float rh2, const float rd2) const { + switch (boundary_conditions) { + case 3 : // Mirror + switch (interpolation) { + case 2 : { // Cubic interpolation + const float ww = 2.f*width(), hh = 2.f*height(), dd = 2.f*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(res.size(),2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = cimg::mod((float)(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc),ww), + Y = cimg::mod((float)(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc),hh), + Z = cimg::mod((float)(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc),dd); + cimg_forC(res,c) res(x,y,z,c) = _cubic_atXYZ_c(X{ 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + template + CImg& warp(const CImg& p_warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + return get_warp(p_warp,mode,interpolation,boundary_conditions).move_to(*this); + } + + //! Warp image content by a warping field \newinstance + template + CImg get_warp(const CImg& p_warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty() || !p_warp) return *this; + if (mode && !is_sameXYZ(p_warp)) + throw CImgArgumentException(_cimg_instance + "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) " + "have different XYZ dimensions.", + cimg_instance, + p_warp._width,p_warp._height,p_warp._depth,p_warp._spectrum,p_warp._data); + + CImg res(p_warp._width,p_warp._height,p_warp._depth,_spectrum); + + if (p_warp._spectrum==1) { // 1D warping + if (mode>=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),x + (float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),(float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)), Y = y + (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)), Y = (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++), + z + (float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = x + (int)cimg::round(*(ptrs0++)), + Y = y + (int)cimg::round(*(ptrs1++)), + Z = z + (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = (int)cimg::round(*(ptrs0++)), + Y = (int)cimg::round(*(ptrs1++)), + Z = (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) const { + if (is_empty() || _depth<2) return +*this; + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + const CImg + img_xy = get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1), + img_zy = get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).permute_axes("xzyc"). + resize(_depth,_height,1,-100,-1), + img_xz = get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1); + return CImg(_width + _depth,_height + _depth,1,_spectrum,cimg::min(img_xy.min(),img_zy.min(),img_xz.min())). + draw_image(0,0,img_xy).draw_image(img_xy._width,0,img_zy). + draw_image(0,img_xy._height,img_xz); + } + + //! Construct a 2D representation of a 3D image, with XY,XZ and YZ views \inplace. + CImg& projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) { + if (_depth<2) return *this; + return get_projections2d(x0,y0,z0).move_to(*this); + } + + //! Crop image region. + /** + \param x0 = X-coordinate of the upper-left crop rectangle corner. + \param y0 = Y-coordinate of the upper-left crop rectangle corner. + \param z0 = Z-coordinate of the upper-left crop rectangle corner. + \param c0 = C-coordinate of the upper-left crop rectangle corner. + \param x1 = X-coordinate of the lower-right crop rectangle corner. + \param y1 = Y-coordinate of the lower-right crop rectangle corner. + \param z1 = Z-coordinate of the lower-right crop rectangle corner. + \param c1 = C-coordinate of the lower-right crop rectangle corner. + \param boundary_conditions = Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const unsigned int boundary_conditions=0) { + return get_crop(x0,y0,z0,c0,x1,y1,z1,c1,boundary_conditions).move_to(*this); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "crop(): Empty instance.", + cimg_instance); + const int + nx0 = x0=0 && nx1=0 && ny1=0 && nz1=0 && nc1 res(1U + nx1 - nx0,1U + ny1 - ny0,1U + nz1 - nz0,1U + nc1 - nc0); + if (nx0<0 || nx1>=width() || ny0<0 || ny1>=height() || nz0<0 || nz1>=depth() || nc0<0 || nc1>=spectrum()) + switch (_boundary_conditions) { + case 3 : { // Mirror + const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) { + const int + mx = cimg::mod(nx0 + x,w2), + my = cimg::mod(ny0 + y,h2), + mz = cimg::mod(nz0 + z,d2), + mc = cimg::mod(nc0 + c,s2); + res(x,y,z,c) = (*this)(mx=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) { + res(x,y,z,c) = (*this)(cimg::mod(nx0 + x,width()),cimg::mod(ny0 + y,height()), + cimg::mod(nz0 + z,depth()),cimg::mod(nc0 + c,spectrum())); + } + } break; + case 1 : // Neumann + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) res(x,y,z,c) = _atXYZC(nx0 + x,ny0 + y,nz0 + z,nc0 + c); + break; + default : // Dirichlet + res.fill((T)0).draw_image(-nx0,-ny0,-nz0,-nc0,*this); + } + else res.draw_image(-nx0,-ny0,-nz0,-nc0,*this); + return res; + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const unsigned int boundary_conditions=0) { + return crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const unsigned int boundary_conditions=0) const { + return get_crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, + const int x1, const int y1, + const unsigned int boundary_conditions=0) { + return crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, + const int x1, const int y1, + const unsigned int boundary_conditions=0) const { + return get_crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int x1, const unsigned int boundary_conditions=0) { + return crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int x1, const unsigned int boundary_conditions=0) const { + return get_crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Autocrop image region, regarding the specified background value. + CImg& autocrop(const T& value, const char *const axes="czyx") { + if (is_empty()) return *this; + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + const CImg coords = _autocrop(value,axis); + if (coords[0]==-1 && coords[1]==-1) return assign(); // Image has only 'value' pixels + else switch (axis) { + case 'x' : { + const int x0 = coords[0], x1 = coords[1]; + if (x0>=0 && x1>=0) crop(x0,x1); + } break; + case 'y' : { + const int y0 = coords[0], y1 = coords[1]; + if (y0>=0 && y1>=0) crop(0,y0,_width - 1,y1); + } break; + case 'z' : { + const int z0 = coords[0], z1 = coords[1]; + if (z0>=0 && z1>=0) crop(0,0,z0,_width - 1,_height - 1,z1); + } break; + default : { + const int c0 = coords[0], c1 = coords[1]; + if (c0>=0 && c1>=0) crop(0,0,0,c0,_width - 1,_height - 1,_depth - 1,c1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background value \newinstance. + CImg get_autocrop(const T& value, const char *const axes="czyx") const { + return (+*this).autocrop(value,axes); + } + + //! Autocrop image region, regarding the specified background color. + /** + \param color Color used for the crop. If \c 0, color is guessed. + \param axes Axes used for the crop. + **/ + CImg& autocrop(const T *const color=0, const char *const axes="zyx") { + if (is_empty()) return *this; + if (!color) { // Guess color + const CImg col1 = get_vector_at(0,0,0); + const unsigned int w = _width, h = _height, d = _depth, s = _spectrum; + autocrop(col1,axes); + if (_width==w && _height==h && _depth==d && _spectrum==s) { + const CImg col2 = get_vector_at(w - 1,h - 1,d - 1); + autocrop(col2,axes); + } + return *this; + } + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + switch (axis) { + case 'x' : { + int x0 = width(), x1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'x'); + const int nx0 = coords[0], nx1 = coords[1]; + if (nx0>=0 && nx1>=0) { x0 = std::min(x0,nx0); x1 = std::max(x1,nx1); } + } + if (x0==width() && x1==-1) return assign(); else crop(x0,x1); + } break; + case 'y' : { + int y0 = height(), y1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'y'); + const int ny0 = coords[0], ny1 = coords[1]; + if (ny0>=0 && ny1>=0) { y0 = std::min(y0,ny0); y1 = std::max(y1,ny1); } + } + if (y0==height() && y1==-1) return assign(); else crop(0,y0,_width - 1,y1); + } break; + default : { + int z0 = depth(), z1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'z'); + const int nz0 = coords[0], nz1 = coords[1]; + if (nz0>=0 && nz1>=0) { z0 = std::min(z0,nz0); z1 = std::max(z1,nz1); } + } + if (z0==depth() && z1==-1) return assign(); else crop(0,0,z0,_width - 1,_height - 1,z1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background color \newinstance. + CImg get_autocrop(const T *const color=0, const char *const axes="zyx") const { + return (+*this).autocrop(color,axes); + } + + CImg _autocrop(const T& value, const char axis) const { + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { + int x0 = -1, x1 = -1; + cimg_forX(*this,x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x0 = x; x = width(); y = height(); z = depth(); c = spectrum(); } + if (x0>=0) { + for (int x = width() - 1; x>=0; --x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x1 = x; x = 0; y = height(); z = depth(); c = spectrum(); } + } + res = CImg::vector(x0,x1); + } break; + case 'y' : { + int y0 = -1, y1 = -1; + cimg_forY(*this,y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y0 = y; x = width(); y = height(); z = depth(); c = spectrum(); } + if (y0>=0) { + for (int y = height() - 1; y>=0; --y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y1 = y; x = width(); y = 0; z = depth(); c = spectrum(); } + } + res = CImg::vector(y0,y1); + } break; + case 'z' : { + int z0 = -1, z1 = -1; + cimg_forZ(*this,z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z0 = z; x = width(); y = height(); z = depth(); c = spectrum(); } + if (z0>=0) { + for (int z = depth() - 1; z>=0; --z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z1 = z; x = width(); y = height(); z = 0; c = spectrum(); } + } + res = CImg::vector(z0,z1); + } break; + default : { + int c0 = -1, c1 = -1; + cimg_forC(*this,c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c0 = c; x = width(); y = height(); z = depth(); c = spectrum(); } + if (c0>=0) { + for (int c = spectrum() - 1; c>=0; --c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c1 = c; x = width(); y = height(); z = depth(); c = 0; } + } + res = CImg::vector(c0,c1); + } + } + return res; + } + + //! Return specified image column. + /** + \param x0 Image column. + **/ + CImg get_column(const int x0) const { + return get_columns(x0,x0); + } + + //! Return specified image column \inplace. + CImg& column(const int x0) { + return columns(x0,x0); + } + + //! Return specified range of image columns. + /** + \param x0 Starting image column. + \param x1 Ending image column. + **/ + CImg& columns(const int x0, const int x1) { + return get_columns(x0,x1).move_to(*this); + } + + //! Return specified range of image columns \inplace. + CImg get_columns(const int x0, const int x1) const { + return get_crop(x0,0,0,0,x1,height() - 1,depth() - 1,spectrum() - 1); + } + + //! Return specified image row. + CImg get_row(const int y0) const { + return get_rows(y0,y0); + } + + //! Return specified image row \inplace. + /** + \param y0 Image row. + **/ + CImg& row(const int y0) { + return rows(y0,y0); + } + + //! Return specified range of image rows. + /** + \param y0 Starting image row. + \param y1 Ending image row. + **/ + CImg get_rows(const int y0, const int y1) const { + return get_crop(0,y0,0,0,width() - 1,y1,depth() - 1,spectrum() - 1); + } + + //! Return specified range of image rows \inplace. + CImg& rows(const int y0, const int y1) { + return get_rows(y0,y1).move_to(*this); + } + + //! Return specified image slice. + /** + \param z0 Image slice. + **/ + CImg get_slice(const int z0) const { + return get_slices(z0,z0); + } + + //! Return specified image slice \inplace. + CImg& slice(const int z0) { + return slices(z0,z0); + } + + //! Return specified range of image slices. + /** + \param z0 Starting image slice. + \param z1 Ending image slice. + **/ + CImg get_slices(const int z0, const int z1) const { + return get_crop(0,0,z0,0,width() - 1,height() - 1,z1,spectrum() - 1); + } + + //! Return specified range of image slices \inplace. + CImg& slices(const int z0, const int z1) { + return get_slices(z0,z1).move_to(*this); + } + + //! Return specified image channel. + /** + \param c0 Image channel. + **/ + CImg get_channel(const int c0) const { + return get_channels(c0,c0); + } + + //! Return specified image channel \inplace. + CImg& channel(const int c0) { + return channels(c0,c0); + } + + //! Return specified range of image channels. + /** + \param c0 Starting image channel. + \param c1 Ending image channel. + **/ + CImg get_channels(const int c0, const int c1) const { + return get_crop(0,0,0,c0,width() - 1,height() - 1,depth() - 1,c1); + } + + //! Return specified range of image channels \inplace. + CImg& channels(const int c0, const int c1) { + return get_channels(c0,c1).move_to(*this); + } + + //! Return stream line of a 2D or 3D vector field. + CImg get_streamline(const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false) const { + if (_spectrum!=2 && _spectrum!=3) + throw CImgInstanceException(_cimg_instance + "streamline(): Instance is not a 2D or 3D vector field.", + cimg_instance); + if (_spectrum==2) { + if (is_oriented_only) { + typename CImg::_functor4d_streamline2d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.f,_height - 1.f,0.f); + } else { + typename CImg::_functor4d_streamline2d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.f,_height - 1.f,0.f); + } + } + if (is_oriented_only) { + typename CImg::_functor4d_streamline3d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.f,_height - 1.f,_depth - 1.f); + } + typename CImg::_functor4d_streamline3d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.f,_height - 1.f,_depth - 1.f); + } + + //! Return stream line of a 3D vector field. + /** + \param func Vector field function. + \param x X-coordinate of the starting point of the streamline. + \param y Y-coordinate of the starting point of the streamline. + \param z Z-coordinate of the starting point of the streamline. + \param L Streamline length. + \param dl Streamline length increment. + \param interpolation_type Type of interpolation. + Can be { 0=nearest int | 1=linear | 2=2nd-order RK | 3=4th-order RK. }. + \param is_backward_tracking Tells if the streamline is estimated forward or backward. + \param is_oriented_only Tells if the direction of the vectors must be ignored. + \param x0 X-coordinate of the first bounding-box vertex. + \param y0 Y-coordinate of the first bounding-box vertex. + \param z0 Z-coordinate of the first bounding-box vertex. + \param x1 X-coordinate of the second bounding-box vertex. + \param y1 Y-coordinate of the second bounding-box vertex. + \param z1 Z-coordinate of the second bounding-box vertex. + **/ + template + static CImg streamline(const tfunc& func, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + if (dl<=0) + throw CImgArgumentException("CImg<%s>::streamline(): Invalid specified integration length %g " + "(should be >0).", + pixel_type(), + dl); + + const bool is_bounded = (x0!=x1 || y0!=y1 || z0!=z1); + if (L<=0 || (is_bounded && (xx1 || yy1 || zz1))) return CImg(); + const unsigned int size_L = (unsigned int)cimg::round(L/dl + 1); + CImg coordinates(size_L,3); + const float dl2 = dl/2; + float + *ptr_x = coordinates.data(0,0), + *ptr_y = coordinates.data(0,1), + *ptr_z = coordinates.data(0,2), + pu = (float)(dl*func(x,y,z,0)), + pv = (float)(dl*func(x,y,z,1)), + pw = (float)(dl*func(x,y,z,2)), + X = x, Y = y, Z = z; + + switch (interpolation_type) { + case 0 : { // Nearest integer interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + const int + xi = (int)(X>0?X + 0.5f:X - 0.5f), + yi = (int)(Y>0?Y + 0.5f:Y - 0.5f), + zi = (int)(Z>0?Z + 0.5f:Z - 0.5f); + float + u = (float)(dl*func((float)xi,(float)yi,(float)zi,0)), + v = (float)(dl*func((float)xi,(float)yi,(float)zi,1)), + w = (float)(dl*func((float)xi,(float)yi,(float)zi,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 1 : { // First-order interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u = (float)(dl*func(X,Y,Z,0)), + v = (float)(dl*func(X,Y,Z,1)), + w = (float)(dl*func(X,Y,Z,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 2 : { // Second order interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u = (float)(dl*func(X + u0,Y + v0,Z + w0,0)), + v = (float)(dl*func(X + u0,Y + v0,Z + w0,1)), + w = (float)(dl*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + default : { // Fourth order interpolation + cimg_forX(coordinates,k) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,0)), + v1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,1)), + w1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u1*pu + v1*pv + w1*pw<0) { u1 = -u1; v1 = -v1; w1 = -w1; } + float + u2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,0)), + v2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,1)), + w2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u2 = -u2; v2 = -v2; w2 = -w2; } + float + u3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,0)), + v3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,1)), + w3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u3 = -u3; v3 = -v3; w3 = -w3; } + const float + u = (u0 + u3)/3 + (u1 + u2)/1.5f, + v = (v0 + v3)/3 + (v1 + v2)/1.5f, + w = (w0 + w3)/3 + (w1 + w2)/1.5f; + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } + } + if (ptr_x!=coordinates.data(0,1)) coordinates.resize((int)(ptr_x-coordinates.data()),3,1,1,0); + return coordinates; + } + + //! Return stream line of a 3D vector field \overloading. + static CImg streamline(const char *const expression, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=true, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + _functor4d_streamline_expr func(expression); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,is_oriented_only,x0,y0,z0,x1,y1,z1); + } + + struct _functor4d_streamline2d_directed { + const CImg& ref; + _functor4d_streamline2d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return c<2?(float)ref._linear_atXY(x,y,(int)z,c):0; + } + }; + + struct _functor4d_streamline3d_directed { + const CImg& ref; + _functor4d_streamline3d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref._linear_atXYZ(x,y,z,c); + } + }; + + struct _functor4d_streamline2d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline2d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,1,2); } + ~_functor4d_streamline2d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign2d(i,j) \ + if (I(i,j,0)*I(0,0,0) + I(i,j,1)*I(0,0,1)<0) { I(i,j,0) = -I(i,j,0); I(i,j,1) = -I(i,j,1); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z; + const float + dx = x - xi, + dy = y - yi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + I(0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,1) = (float)ref(xi,yi,zi,1); + I(1,0,0) = (float)ref(nxi,yi,zi,0); I(1,0,1) = (float)ref(nxi,yi,zi,1); + I(1,1,0) = (float)ref(nxi,nyi,zi,0); I(1,1,1) = (float)ref(nxi,nyi,zi,1); + I(0,1,0) = (float)ref(xi,nyi,zi,0); I(0,1,1) = (float)ref(xi,nyi,zi,1); + _cimg_vecalign2d(1,0); _cimg_vecalign2d(1,1); _cimg_vecalign2d(0,1); + } + return c<2?(float)pI->_linear_atXY(dx,dy,0,c):0; + } + }; + + struct _functor4d_streamline3d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline3d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,2,3); } + ~_functor4d_streamline3d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign3d(i,j,k) if (I(i,j,k,0)*I(0,0,0,0) + I(i,j,k,1)*I(0,0,0,1) + I(i,j,k,2)*I(0,0,0,2)<0) { \ + I(i,j,k,0) = -I(i,j,k,0); I(i,j,k,1) = -I(i,j,k,1); I(i,j,k,2) = -I(i,j,k,2); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z - (z>=0?0:1), nzi = zi + 1; + const float + dx = x - xi, + dy = y - yi, + dz = z - zi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + if (zi<0) zi = 0; + if (nzi<0) nzi = 0; + if (zi>=ref.depth()) zi = ref.depth() - 1; + if (nzi>=ref.depth()) nzi = ref.depth() - 1; + I(0,0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,0,1) = (float)ref(xi,yi,zi,1); + I(0,0,0,2) = (float)ref(xi,yi,zi,2); I(1,0,0,0) = (float)ref(nxi,yi,zi,0); + I(1,0,0,1) = (float)ref(nxi,yi,zi,1); I(1,0,0,2) = (float)ref(nxi,yi,zi,2); + I(1,1,0,0) = (float)ref(nxi,nyi,zi,0); I(1,1,0,1) = (float)ref(nxi,nyi,zi,1); + I(1,1,0,2) = (float)ref(nxi,nyi,zi,2); I(0,1,0,0) = (float)ref(xi,nyi,zi,0); + I(0,1,0,1) = (float)ref(xi,nyi,zi,1); I(0,1,0,2) = (float)ref(xi,nyi,zi,2); + I(0,0,1,0) = (float)ref(xi,yi,nzi,0); I(0,0,1,1) = (float)ref(xi,yi,nzi,1); + I(0,0,1,2) = (float)ref(xi,yi,nzi,2); I(1,0,1,0) = (float)ref(nxi,yi,nzi,0); + I(1,0,1,1) = (float)ref(nxi,yi,nzi,1); I(1,0,1,2) = (float)ref(nxi,yi,nzi,2); + I(1,1,1,0) = (float)ref(nxi,nyi,nzi,0); I(1,1,1,1) = (float)ref(nxi,nyi,nzi,1); + I(1,1,1,2) = (float)ref(nxi,nyi,nzi,2); I(0,1,1,0) = (float)ref(xi,nyi,nzi,0); + I(0,1,1,1) = (float)ref(xi,nyi,nzi,1); I(0,1,1,2) = (float)ref(xi,nyi,nzi,2); + _cimg_vecalign3d(1,0,0); _cimg_vecalign3d(1,1,0); _cimg_vecalign3d(0,1,0); + _cimg_vecalign3d(0,0,1); _cimg_vecalign3d(1,0,1); _cimg_vecalign3d(1,1,1); _cimg_vecalign3d(0,1,1); + } + return (float)pI->_linear_atXYZ(dx,dy,dz,c); + } + }; + + struct _functor4d_streamline_expr { + _cimg_math_parser *mp; + ~_functor4d_streamline_expr() { mp->end(); delete mp; } + _functor4d_streamline_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,"streamline",CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)(*mp)(x,y,z,c); + } + }; + + //! Return a shared-memory image referencing a range of pixels of the image instance. + /** + \param x0 X-coordinate of the starting pixel. + \param x1 X-coordinate of the ending pixel. + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(x0,y0,z0,c0), + end = (ulongT)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of pixels of the image instance \const. + const CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(x0,y0,z0,c0), + end = (ulongT)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance. + /** + \param y0 Y-coordinate of the starting row. + \param y1 Y-coordinate of the ending row. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(0,y0,z0,c0), + end = (ulongT)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance \const. + const CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(0,y0,z0,c0), + end = (ulongT)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing one row of the image instance. + /** + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared-memory image referencing one row of the image instance \const. + const CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) const { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared memory image referencing a range of slices of the image instance. + /** + \param z0 Z-coordinate of the starting slice. + \param z1 Z-coordinate of the ending slice. + \param c0 C-coordinate. + **/ + CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(0,0,z0,c0), + end = (ulongT)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared memory image referencing a range of slices of the image instance \const. + const CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(0,0,z0,c0), + end = (ulongT)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared-memory image referencing one slice of the image instance. + /** + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing one slice of the image instance \const. + const CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) const { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing a range of channels of the image instance. + /** + \param c0 C-coordinate of the starting channel. + \param c1 C-coordinate of the ending channel. + **/ + CImg get_shared_channels(const unsigned int c0, const unsigned int c1) { + const ulongT + beg = (ulongT)offset(0,0,0,c0), + end = (ulongT)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing a range of channels of the image instance \const. + const CImg get_shared_channels(const unsigned int c0, const unsigned int c1) const { + const ulongT + beg = (ulongT)offset(0,0,0,c0), + end = (ulongT)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing one channel of the image instance. + /** + \param c0 C-coordinate. + **/ + CImg get_shared_channel(const unsigned int c0) { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory image referencing one channel of the image instance \const. + const CImg get_shared_channel(const unsigned int c0) const { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory version of the image instance. + CImg get_shared() { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Return a shared-memory version of the image instance \const. + const CImg get_shared() const { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Split image into a list along specified axis. + /** + \param axis Splitting axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param nb Number of split parts. + \note + - If \c nb==0, instance image is split into blocs of egal values along the specified axis. + - If \c nb<=0, instance image is split into blocs of -\c nb pixel wide. + - If \c nb>0, instance image is split into \c nb blocs. + **/ + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + + if (nb<0) { // Split by bloc size + const unsigned int dp = (unsigned int)(nb?-nb:1); + switch (_axis) { + case 'x': { + if (_width>dp) { + res.assign(_width/dp + (_width%dp?1:0),1,1); + const unsigned int pe = _width - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _height*_depth*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(p,0,0,0,p + dp - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop((res._width - 1)*dp,0,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'y': { + if (_height>dp) { + res.assign(_height/dp + (_height%dp?1:0),1,1); + const unsigned int pe = _height - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_depth*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,p,0,0,_width - 1,p + dp - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop(0,(res._width - 1)*dp,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'z': { + if (_depth>dp) { + res.assign(_depth/dp + (_depth%dp?1:0),1,1); + const unsigned int pe = _depth - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_height*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,0,p,0,_width - 1,_height - 1,p + dp - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop(0,0,(res._width - 1)*dp,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'c' : { + if (_spectrum>dp) { + res.assign(_spectrum/dp + (_spectrum%dp?1:0),1,1); + const unsigned int pe = _spectrum - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_height*_depth>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,0,0,p,_width - 1,_height - 1,_depth - 1,p + dp - 1).move_to(res[p/dp]); + get_crop(0,0,0,(res._width - 1)*dp,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } + } + } else if (nb>0) { // Split by number of (non-homogeneous) blocs + const unsigned int siz = _axis=='x'?_width:_axis=='y'?_height:_axis=='z'?_depth:_axis=='c'?_spectrum:0; + if ((unsigned int)nb>siz) + throw CImgArgumentException(_cimg_instance + "get_split(): Instance cannot be split along %c-axis into %u blocs.", + cimg_instance, + axis,nb); + if (nb==1) res.assign(*this); + else { + int err = (int)siz; + unsigned int _p = 0; + switch (_axis) { + case 'x' : { + cimg_forX(*this,p) if ((err-=nb)<=0) { + get_crop(_p,0,0,0,p,_height - 1,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'y' : { + cimg_forY(*this,p) if ((err-=nb)<=0) { + get_crop(0,_p,0,0,_width - 1,p,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'z' : { + cimg_forZ(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,_p,0,_width - 1,_height - 1,p,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'c' : { + cimg_forC(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,0,_p,_width - 1,_height - 1,_depth - 1,p).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } + } + } + } else { // Split by egal values according to specified axis + T current = *_data; + switch (_axis) { + case 'x' : { + int i0 = 0; + cimg_forX(*this,i) + if ((*this)(i)!=current) { get_columns(i0,i - 1).move_to(res); i0 = i; current = (*this)(i); } + get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + int i0 = 0; + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { get_rows(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,i); } + get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + int i0 = 0; + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { get_slices(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,i); } + get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + int i0 = 0; + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { get_channels(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,0,i); } + get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + longT i0 = 0; + cimg_foroff(*this,i) + if ((*this)[i]!=current) { + CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = (longT)i; current = (*this)[i]; + } + CImg(_data + i0,1,(unsigned int)(size() - i0)).move_to(res); + } + } + } + return res; + } + + //! Split image into a list of sub-images, according to a specified splitting value sequence and optionally axis. + /** + \param values Splitting value sequence. + \param axis Axis along which the splitting is performed. Can be '0' to ignore axis. + \param keep_values Tells if the splitting sequence must be kept in the split blocs. + **/ + template + CImgList get_split(const CImg& values, const char axis=0, const bool keep_values=true) const { + typedef _cimg_Tt Tt; + + CImgList res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + if (!vsiz) return CImgList(*this); + if (vsiz==1) { // Split according to a single value + const T value = (T)*values; + switch (_axis) { + case 'x' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_width && (*this)(i)==value) ++i; + if (i>i0) { if (keep_values) get_columns(i0,i - 1).move_to(res); i0 = i; } + while (i<_width && (*this)(i)!=value) ++i; + if (i>i0) { get_columns(i0,i - 1).move_to(res); i0 = i; } + } while (i<_width); + } break; + case 'y' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_height && (*this)(0,i)==value) ++i; + if (i>i0) { if (keep_values) get_rows(i0,i - 1).move_to(res); i0 = i; } + while (i<_height && (*this)(0,i)!=value) ++i; + if (i>i0) { get_rows(i0,i - 1).move_to(res); i0 = i; } + } while (i<_height); + } break; + case 'z' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_depth && (*this)(0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_slices(i0,i - 1).move_to(res); i0 = i; } + while (i<_depth && (*this)(0,0,i)!=value) ++i; + if (i>i0) { get_slices(i0,i - 1).move_to(res); i0 = i; } + } while (i<_depth); + } break; + case 'c' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_spectrum && (*this)(0,0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_channels(i0,i - 1).move_to(res); i0 = i; } + while (i<_spectrum && (*this)(0,0,0,i)!=value) ++i; + if (i>i0) { get_channels(i0,i - 1).move_to(res); i0 = i; } + } while (i<_spectrum); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i = 0; + do { + while (ii0) { + if (keep_values) CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = i; + } + while (ii0) { CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; } + } while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_columns(i0,i1 - 1).move_to(res); + if (keep_values) get_columns(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_width); + if (i0<_width) get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_height && (Tt)(*this)(0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_rows(i0,i1 - 1).move_to(res); + if (keep_values) get_rows(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_height); + if (i0<_height) get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_depth && (Tt)(*this)(0,0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_slices(i0,i1 - 1).move_to(res); + if (keep_values) get_slices(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_depth); + if (i0<_depth) get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,0,0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_spectrum && (Tt)(*this)(0,0,0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_channels(i0,i1 - 1).move_to(res); + if (keep_values) get_channels(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_spectrum); + if (i0<_spectrum) get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)[i]==(Tt)*values) { + i1 = i; j = 0; + while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) CImg(_data + i0,1,(unsigned int)(i1 - i0)).move_to(res); + if (keep_values) CImg(_data + i1,1,(unsigned int)(i - i1)).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i(_data + i0,1,(unsigned int)(siz - i0)).move_to(res); + } break; + } + } + return res; + } + + //! Append two images along specified axis. + /** + \param img Image to append with instance image. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Append alignment in \c [0,1]. + **/ + template + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,true).insert(img).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \specialization. + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,img,true).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \const. + template + CImg<_cimg_Tt> get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList<_cimg_Tt>(*this,true).insert(img).get_append(axis,align); + } + + //! Append two images along specified axis \specialization. + CImg get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList(*this,img,true).get_append(axis,align); + } + + //@} + //--------------------------------------- + // + //! \name Filtering / Transforms + //@{ + //--------------------------------------- + + //! Correlate image by a kernel. + /** + \param kernel = the correlation kernel. + \param boundary_conditions Boundary condition. Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \param is_normalized = enable local normalization. + \param channel mode Channel processing mode. Can be { 0=sum inputs | 1=one-for-one | 2=expand } + \param xcenter X-coordinate of the kernel center (~0U means 'centered'). + \param xstart Starting X-coordinate of the instance image. + \param xend Ending X-coordinate of the instance image. + \param xstride Stride along the X-axis. + \param xdilation Dilation along the X-axis. + \param ycenter Y-coordinate of the kernel center (~0U means 'centered'). + \param ystart Starting Y-coordinate of the instance image. + \param yend Ending Y-coordinate of the instance image. + \param ystride Stride along the Y-axis. + \param ydilation Dilation along the Y-axis. + \param zcenter Z-coordinate of the kernel center (~0U means 'centered'). + \param zstart Starting Z-coordinate of the instance image. + \param zend Ending Z-coordinate of the instance image. + \param zstride Stride along the Z-axis. + \param zdilation Dilation along the Z-axis. + \note + - The correlation of the image instance \p *this by the kernel \p kernel is defined to be: + res(x,y,z) = sum_{i,j,k} (*this)(\alpha_x\;x + \beta_x\;(i - c_x),\alpha_y\;y + \beta_y\;(j - + c_y),\alpha_z\;z + \beta_z\;(k - c_z))*kernel(i,j,k). + **/ + template + CImg& correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) { + if (is_empty() || !kernel) return *this; + return get_correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation).move_to(*this); + } + + template + CImg<_cimg_Ttfloat> get_correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, + const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, + const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) const { + return _correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation,false); + } + + //! Correlate image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> _correlate(const CImg& kernel, const unsigned int boundary_conditions, + const bool is_normalized, const unsigned int channel_mode, + const unsigned int xcenter, const unsigned int ycenter, const unsigned int zcenter, + const unsigned int xstart, const unsigned int ystart, const unsigned zstart, + const unsigned int xend, const unsigned int yend, const unsigned int zend, + const float xstride, const float ystride, const float zstride, + const float xdilation, const float ydilation, const float zdilation, + const bool is_convolve) const { + if (is_empty() || !kernel) return *this; + typedef _cimg_Ttfloat Ttfloat; + CImg res; + _cimg_abort_init_openmp; + cimg_abort_init; + + if (xstart>xend || ystart>yend || zstart>zend) + throw CImgArgumentException(_cimg_instance + "%s(): Invalid xyz-start/end arguments (start = (%u,%u,%u), end = (%u,%u,%u)).", + cimg_instance, + is_convolve?"convolve":"correlate", + xstart,ystart,zstart,xend,yend,zend); + if (xstride<=0 || ystride<=0 || zstride<=0) + throw CImgArgumentException(_cimg_instance + "%s(): Invalid stride arguments (%g,%g,%g).", + cimg_instance, + is_convolve?"convolve":"correlate", + xstride,ystride,zstride); + const int + _xstart = (int)std::min(xstart,_width - 1), + _ystart = (int)std::min(ystart,_height - 1), + _zstart = (int)std::min(zstart,_depth - 1), + _xend = (int)std::min(xend,_width - 1), + _yend = (int)std::min(yend,_height - 1), + _zend = (int)std::min(zend,_depth - 1), + nwidth = 1 + (int)std::floor((_xend - _xstart)/xstride), + nheight = 1 + (int)std::floor((_yend - _ystart)/ystride), + ndepth = 1 + (int)std::floor((_zend + _zstart)/zstride), + _xstride = (int)cimg::round(xstride), + _ystride = (int)cimg::round(ystride), + _zstride = (int)cimg::round(zstride); + + const ulongT + res_whd = (ulongT)nwidth*nheight*ndepth, + res_size = res_whd*res._spectrum; + const bool + is_inner_parallel = res_whd>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res_size>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + + int + _xcenter = xcenter==~0U?kernel.width()/2 - 1 + (kernel.width()%2):(int)std::min(xcenter,kernel._width - 1), + _ycenter = ycenter==~0U?kernel.height()/2 - 1 + (kernel.height()%2):(int)std::min(ycenter,kernel._height - 1), + _zcenter = zcenter==~0U?kernel.depth()/2 - 1 + (kernel.depth()%2):(int)std::min(zcenter,kernel._depth - 1), + _xdilation = (int)cimg::round(xdilation), + _ydilation = (int)cimg::round(ydilation), + _zdilation = (int)cimg::round(zdilation); + + const bool is_int_stride_dilation = + xstride==_xstride && ystride==_ystride && zstride==_zstride && + xdilation==_xdilation && ydilation==_ydilation && zdilation==_zdilation; + + CImg _kernel; + if (is_convolve) { // If convolution, go back to correlation + _kernel = CImg(kernel._data,kernel.size()/kernel._spectrum,1,1,kernel._spectrum,true). + get_mirror('x').resize(kernel,-1); + _xcenter = kernel.width() - 1 - _xcenter; + _ycenter = kernel.height() - 1 - _ycenter; + _zcenter = kernel.depth() - 1 - _zcenter; + } else _kernel = kernel.get_shared(); + + if (_kernel._width==_kernel._height && _kernel._width>1 && _kernel._height>1 && + ((_kernel._depth==1 && _kernel._width<=5) || (_kernel._depth==_kernel._width && _kernel._width<=3)) && + boundary_conditions<=1 && channel_mode && + _xcenter==_kernel.width()/2 - 1 + (_kernel.width()%2) && + _ycenter==_kernel.height()/2 - 1 + (_kernel.height()%2) && + _zcenter==_kernel.depth()/2 - 1 + (_kernel.depth()%2) && + is_int_stride_dilation && _xdilation>=0 && _ydilation>=0 && _zdilation>=0) { + + // Optimized versions for centered 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 kernels. + const int dw = 1 - (_kernel.width()%2), dh = 1 - (_kernel.height()%2), dd = 1 - (_kernel.depth()%2); + if (dw || dh || dd) // Force kernel size to be odd + _kernel.get_resize(_kernel.width() + dw,_kernel.height() + dh,_kernel.depth() + dd,_kernel.spectrum(), + 0,0,1,1,1).move_to(_kernel.assign()); + + if (!boundary_conditions) { // Dirichlet -> Add a 1px zero border, then use _correlate() with Neumann + const int + dx = _kernel._width==1?0:1, + dy = _kernel._height==1?0:1, + dz = _kernel._depth==1?0:1; + return get_crop(-dx,-dy,-dz,width() - 1 + dx,height() - 1 + dy,depth() - 1 + dz). + _correlate(_kernel,true,is_normalized,channel_mode,_xcenter,_ycenter,_zcenter, + _xstart + dx,_ystart + dy,_zstart + dz,_xend + dx,_yend + dy,_zend + dz, + xstride,ystride,zstride,xdilation,ydilation,zdilation,false); + + } else { // Neumann boundaries + res.assign(nwidth,nheight,ndepth,std::max(_spectrum,_kernel._spectrum)); + + switch (_kernel._depth) { + case 3 : { // 3x3x3 centered kernel + cimg_forC(res,c) { + cimg_abort_test; + const CImg I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + const int w1 = I.width() - 1, h1 = I.height() - 1, d1 = I.depth() - 1; + CImg _res = res.get_shared_channel(c); + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,Z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, z = _zstart + _zstride*Z, + px = x - _xdilation>0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?z - _zdilation:0, nz = z + _zdilation0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?z - _zdilation:0, nz = z + _zdilation I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + const int w1 = I.width() - 1, h1 = I.height() - 1; + CImg _res = res.get_shared_channel(c); + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, + px = x - _xdilation>0?x - _xdilation:0, bx = px - _xdilation>0?px - _xdilation:0, + nx = x + _xdilation0?y - _ydilation:0, by = py - _ydilation>0?py - _ydilation:0, + ny = y + _ydilation0?x - _xdilation:0, bx = px - _xdilation>0?px - _xdilation:0, + nx = x + _xdilation0?y - _ydilation:0, by = py - _ydilation>0?py - _ydilation:0, + ny = y + _ydilation I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + CImg _res = res.get_shared_channel(c); + const int w1 = I.width() - 1, h1 = I.height() - 1; + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, + px = x - _xdilation>0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation res0 = res.get_shared_channel(0); + for (int c = 1; c K = _kernel.get_shared_channel(kc%_kernel._spectrum); + int w2 = 0, h2 = 0, d2 = 0; + Ttfloat M = 0, M2 = 0; + if (is_normalized) { M = (Ttfloat)K.magnitude(2); M2 = M*M; } + if (boundary_conditions>=3) { w2 = 2*width(); h2 = 2*height(); d2 = 2*depth(); } + res.fill(0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + cimg_forXYZC(res,x,y,z,c) { + Ttfloat _val, val = 0, N = 0; + + if (is_int_stride_dilation) + cimg_forXYZ(_kernel,p,q,r) { + const int + ix = (int)xstart + _xstride*x + _xdilation*(p - _xcenter), + iy = (int)ystart + _ystride*y + _ydilation*(q - _ycenter), + iz = (int)zstart + _zstride*z + _zdilation*(r - _zcenter); + switch (boundary_conditions) { + case 0 : _val = atXYZ(ix,iy,iz,c,0); break; // Dirichlet + case 1 : _val = _atXYZ(ix,iy,iz,c); break; // Neumann + case 2 : _val = (*this)(cimg::mod(ix,width()),cimg::mod(iy,height()), // Periodic + cimg::mod(iz,depth()),c); break; + default : { // Mirror + const int mx = cimg::mod(ix,w2), my = cimg::mod(iy,h2), mz = cimg::mod(iz,d2); + _val = (*this)(mx I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(channel_mode==1?c%_kernel._spectrum:c/_spectrum); + int w2 = 0, h2 = 0, d2 = 0; + Ttfloat M = 0, M2 = 0; + if (is_normalized) { M = (Ttfloat)K.magnitude(2); M2 = M*M; } + if (boundary_conditions>=3) { w2 = 2*I.width(); h2 = 2*I.height(); d2 = 2*I.depth(); } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + cimg_forXYZ(res,x,y,z) { + Ttfloat _val, val = 0, N = 0; + + if (is_int_stride_dilation) + cimg_forXYZ(_kernel,p,q,r) { + const int + ix = (int)xstart + _xstride*x + _xdilation*(p - _xcenter), + iy = (int)ystart + _ystride*y + _ydilation*(q - _ycenter), + iz = (int)zstart + _zstride*z + _zdilation*(r - _zcenter); + switch (boundary_conditions) { + case 0 : _val = I.atXYZ(ix,iy,iz,0,0); break; // Dirichlet + case 1 : _val = I._atXYZ(ix,iy,iz); break; // Neumann + case 2 : _val = I(cimg::mod(ix,I.width()),cimg::mod(iy,I.height()), // Periodic + cimg::mod(iz,I.depth())); break; + default : { // Mirror + const int mx = cimg::mod(ix,w2), my = cimg::mod(iy,h2), mz = cimg::mod(iz,d2); + _val = I(mx + CImg& convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) { + if (is_empty() || !kernel) return *this; + return get_convolve(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation).move_to(*this); + } + + //! Convolve image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> get_convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, + const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, + const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) const { + return _correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation,true); + } + + //! Cumulate image values, optionally along specified axis. + /** + \param axis Cumulation axis. Set it to 0 to cumulate all values globally without taking axes into account. + **/ + CImg& cumulate(const char axis=0) { + switch (cimg::lowercase(axis)) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { + T *ptrd = data(0,y,z,c); + Tlong cumul = (Tlong)0; + cimg_forX(*this,x) { cumul+=(Tlong)*ptrd; *(ptrd++) = (T)cumul; } + } + break; + case 'y' : { + const ulongT w = (ulongT)_width; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 && + _width*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { + T *ptrd = data(x,0,z,c); + Tlong cumul = (Tlong)0; + cimg_forY(*this,y) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=w; } + } + } break; + case 'z' : { + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 && + _width*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { + T *ptrd = data(x,y,0,c); + Tlong cumul = (Tlong)0; + cimg_forZ(*this,z) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=wh; } + } + } break; + case 'c' : { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(_spectrum>=(cimg_openmp_sizefactor)*512 && _width*_height*_depth>=16)) + cimg_forXYZ(*this,x,y,z) { + T *ptrd = data(x,y,z,0); + Tlong cumul = (Tlong)0; + cimg_forC(*this,c) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=whd; } + } + } break; + default : { // Global cumulation + Tlong cumul = (Tlong)0; + cimg_for(*this,ptrd,T) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; } + } + } + return *this; + } + + //! Cumulate image values, optionally along specified axis \newinstance. + CImg get_cumulate(const char axis=0) const { + return CImg(*this,false).cumulate(axis); + } + + //! Cumulate image values, along specified axes. + /** + \param axes Cumulation axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& cumulate(const char *const axes) { + for (const char *s = axes; *s; ++s) cumulate(*s); + return *this; + } + + //! Cumulate image values, along specified axes \newinstance. + CImg get_cumulate(const char *const axes) const { + return CImg(*this,false).cumulate(axes); + } + + //! Erode image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the erosion in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& erode(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_erode(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Erode image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_erode(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) const { + if (is_empty() || !kernel) return *this; + if (!is_real && kernel==0) return CImg(width(),height(),depth(),spectrum(),0); + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = kernel.depth()/2, + mx1 = kernel.width() - mx2 - 1, my1 = kernel.height() - my2 - 1, mz1 = kernel.depth() - mz2 - 1, + mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2; + const bool + is_inner_parallel = _width*_height*_depth>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res.size()>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + _cimg_abort_init_openmp; + cimg_abort_init; + cimg_pragma_openmp(parallel for cimg_openmp_if(!is_inner_parallel && is_outer_parallel)) + cimg_forC(res,c) _cimg_abort_try_openmp { + cimg_abort_test; + const CImg img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real erosion + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img(x + xm,y + ym,z + zm) - mval); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img._atXYZ(x + xm,y + ym,z + zm) - mval); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) - mval); + if (cval::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img(x + xm,y + ym,z + zm); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img._atXYZ(x + xm,y + ym,z + zm); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval& erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) { + if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this; + if (sx>1 && _width>1) { // Along X-axis + const int L = width(), off = 1, s = (int)sx, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = buf._data, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; }} + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _height>1) { // Along Y-axis + const int L = height(), off = width(), s = (int)sy, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _depth>1) { // Along Z-axis + const int L = depth(), off = width()*height(), s = (int)sz, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val get_erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).erode(sx,sy,sz); + } + + //! Erode the image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& erode(const unsigned int s) { + return erode(s,s,s); + } + + //! Erode the image by a square structuring element of specified size \newinstance. + CImg get_erode(const unsigned int s) const { + return (+*this).erode(s); + } + + //! Dilate image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the dilation in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& dilate(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_dilate(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Dilate image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_dilate(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) const { + if (is_empty() || !kernel || (!is_real && kernel==0)) return *this; + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx1 = kernel.width()/2, my1 = kernel.height()/2, mz1 = kernel.depth()/2, + mx2 = kernel.width() - mx1 - 1, my2 = kernel.height() - my1 - 1, mz2 = kernel.depth() - mz1 - 1, + mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2; + const bool + is_inner_parallel = _width*_height*_depth>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res.size()>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + _cimg_abort_init_openmp; + cimg_abort_init; + cimg_pragma_openmp(parallel for cimg_openmp_if(!is_inner_parallel && is_outer_parallel)) + cimg_forC(res,c) _cimg_abort_try_openmp { + cimg_abort_test; + const CImg img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real dilation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } _cimg_abort_catch_openmp2 + if (boundary_conditions) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img._atXYZ(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(*this,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + } else { // Binary dilation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } _cimg_abort_catch_openmp2 + if (boundary_conditions) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img._atXYZ(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + } + } _cimg_abort_catch_openmp + cimg_abort_test; + return res; + } + + //! Dilate image by a rectangular structuring element of specified size. + /** + \param sx Width of the structuring element. + \param sy Height of the structuring element. + \param sz Depth of the structuring element. + **/ + CImg& dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) { + if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this; + if (sx>1 && _width>1) { // Along X-axis + const int L = width(), off = 1, s = (int)sx, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(0,y,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + if (sy>1 && _height>1) { // Along Y-axis + const int L = height(), off = width(), s = (int)sy, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,0,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + if (sz>1 && _depth>1) { // Along Z-axis + const int L = depth(), off = width()*height(), s = (int)sz, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,y,0,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + return *this; + } + + //! Dilate image by a rectangular structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).dilate(sx,sy,sz); + } + + //! Dilate image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& dilate(const unsigned int s) { + return dilate(s,s,s); + } + + //! Dilate image by a square structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int s) const { + return (+*this).dilate(s); + } + + //! Compute watershed transform. + /** + \param priority Priority map. + \param is_high_connectivity Boolean that choose between 4(false)- or 8(true)-connectivity + in 2D case, and between 6(false)- or 26(true)-connectivity in 3D case. + \note Non-zero values of the instance instance are propagated to zero-valued ones according to + specified the priority map. + **/ + template + CImg& watershed(const CImg& priority, const bool is_high_connectivity=false) { +#define _cimg_watershed_init(cond,X,Y,Z) \ + if (cond && !(*this)(X,Y,Z)) Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,nb_seeds) + +#define _cimg_watershed_propagate(cond,X,Y,Z) \ + if (cond) { \ + if ((*this)(X,Y,Z)) { \ + ns = labels(X,Y,Z) - 1; xs = seeds(ns,0); ys = seeds(ns,1); zs = seeds(ns,2); \ + d = cimg::sqr((float)x - xs) + cimg::sqr((float)y - ys) + cimg::sqr((float)z - zs); \ + if (d labels(_width,_height,_depth,1,0), seeds(64,3); + CImg::type> Q; + unsigned int sizeQ = 0; + int px, nx, py, ny, pz, nz; + bool is_px, is_nx, is_py, is_ny, is_pz, is_nz; + const bool is_3d = _depth>1; + + // Find seed points and insert them in priority queue. + unsigned int nb_seeds = 0; + const T *ptrs = _data; + cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) { // 3D version + if (nb_seeds>=seeds._width) seeds.resize(2*seeds._width,3,1,1,0); + seeds(nb_seeds,0) = x; seeds(nb_seeds,1) = y; seeds(nb_seeds++,2) = z; + px = x - 1; nx = x + 1; + py = y - 1; ny = y + 1; + pz = z - 1; nz = z + 1; + is_px = px>=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz::inf(); + T nlabel = (T)0; + _cimg_watershed_propagate(is_px,px,y,z); + _cimg_watershed_propagate(is_nx,nx,y,z); + _cimg_watershed_propagate(is_py,x,py,z); + _cimg_watershed_propagate(is_ny,x,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_pz,x,y,pz); + _cimg_watershed_propagate(is_nz,x,y,nz); + } + if (is_high_connectivity) { + _cimg_watershed_propagate(is_px && is_py,px,py,z); + _cimg_watershed_propagate(is_nx && is_py,nx,py,z); + _cimg_watershed_propagate(is_px && is_ny,px,ny,z); + _cimg_watershed_propagate(is_nx && is_ny,nx,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_px && is_pz,px,y,pz); + _cimg_watershed_propagate(is_nx && is_pz,nx,y,pz); + _cimg_watershed_propagate(is_px && is_nz,px,y,nz); + _cimg_watershed_propagate(is_nx && is_nz,nx,y,nz); + _cimg_watershed_propagate(is_py && is_pz,x,py,pz); + _cimg_watershed_propagate(is_ny && is_pz,x,ny,pz); + _cimg_watershed_propagate(is_py && is_nz,x,py,nz); + _cimg_watershed_propagate(is_ny && is_nz,x,ny,nz); + _cimg_watershed_propagate(is_px && is_py && is_pz,px,py,pz); + _cimg_watershed_propagate(is_nx && is_py && is_pz,nx,py,pz); + _cimg_watershed_propagate(is_px && is_ny && is_pz,px,ny,pz); + _cimg_watershed_propagate(is_nx && is_ny && is_pz,nx,ny,pz); + _cimg_watershed_propagate(is_px && is_py && is_nz,px,py,nz); + _cimg_watershed_propagate(is_nx && is_py && is_nz,nx,py,nz); + _cimg_watershed_propagate(is_px && is_ny && is_nz,px,ny,nz); + _cimg_watershed_propagate(is_nx && is_ny && is_nz,nx,ny,nz); + } + } + (*this)(x,y,z) = nlabel; + labels(x,y,z) = ++nmin; + } + return *this; + } + + //! Compute watershed transform \newinstance. + template + CImg get_watershed(const CImg& priority, const bool is_high_connectivity=false) const { + return (+*this).watershed(priority,is_high_connectivity); + } + + // [internal] Insert/Remove items in priority queue, for watershed/distance transforms. + template + bool _priority_queue_insert(CImg& is_queued, unsigned int& siz, const tv value, + const unsigned int x, const unsigned int y, const unsigned int z, + const unsigned int n=1) { + if (is_queued(x,y,z)) return false; + is_queued(x,y,z) = (tq)n; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; + (*this)(siz - 1,1) = (T)x; + (*this)(siz - 1,2) = (T)y; + (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(tv)(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); + cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); + cimg::swap((*this)(pos,3),(*this)(par,3)); + } + return true; + } + + CImg& _priority_queue_remove(unsigned int& siz) { + (*this)(0,0) = (*this)(--siz,0); + (*this)(0,1) = (*this)(siz,1); + (*this)(0,2) = (*this)(siz,2); + (*this)(0,3) = (*this)(siz,3); + const float value = (*this)(0,0); + unsigned int pos = 0, swap = 0; + do { + const unsigned int left = 2*pos + 1, right = left + 1; + if (right(*this)(right,0)?left:right; + else if (left{ 0=smooth-filter | 1=1st-derivative | 2=2nd-derivative }. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + **/ + CImg& deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) { +#define _cimg_deriche_apply \ + CImg Y(N); \ + double *ptrY = Y._data, yb = 0, yp = 0; \ + T xp = (T)0; \ + if (boundary_conditions) { xp = *ptrX; yb = yp = (double)(coefp*xp); } \ + for (int m = 0; m=0; --n) { \ + const T xc = *(ptrX-=off); \ + const double yc = (double)(a2*xn + a3*xa - b1*yn - b2*ya); \ + xa = xn; xn = xc; ya = yn; yn = yc; \ + *ptrX = (T)(*(--ptrY)+yc); \ + } + const char naxis = cimg::lowercase(axis); + const double nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width: + naxis=='y'?_height: + naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.1f && !order)) return *this; + const double + nnsigma = nsigma<0.1f?0.1f:nsigma, + alpha = 1.695f/nnsigma, + ema = std::exp(-alpha), + ema2 = std::exp(-2*alpha), + b1 = -2*ema, + b2 = ema2; + double a0 = 0, a1 = 0, a2 = 0, a3 = 0, coefp = 0, coefn = 0; + switch (order) { + case 0 : { + const double k = (1-ema)*(1-ema)/(1 + 2*alpha*ema-ema2); + a0 = k; + a1 = k*(alpha - 1)*ema; + a2 = k*(alpha + 1)*ema; + a3 = -k*ema2; + } break; + case 1 : { + const double k = -(1-ema)*(1-ema)*(1-ema)/(2*(ema + 1)*ema); + a0 = a3 = 0; + a1 = k*ema; + a2 = -a1; + } break; + case 2 : { + const double + ea = std::exp(-alpha), + k = -(ema2 - 1)/(2*alpha*ema), + kn = (-2*(-1 + 3*ea - 3*ea*ea + ea*ea*ea)/(3*ea + 1 + 3*ea*ea + ea*ea*ea)); + a0 = kn; + a1 = -kn*(1 + k*alpha)*ema; + a2 = kn*(1 - k*alpha)*ema; + a3 = -kn*ema2; + } break; + default : + throw CImgArgumentException(_cimg_instance + "deriche(): Invalid specified filter order %u " + "(should be { 0=smoothing | 1=1st-derivative | 2=2nd-derivative }).", + cimg_instance, + order); + } + coefp = (a0 + a1)/(1 + b1 + b2); + coefn = (a2 + a3)/(1 + b1 + b2); + switch (naxis) { + case 'x' : { + const int N = width(); + const ulongT off = 1U; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { T *ptrX = data(0,y,z,c); _cimg_deriche_apply; } + } break; + case 'y' : { + const int N = height(); + const ulongT off = (ulongT)_width; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { T *ptrX = data(x,0,z,c); _cimg_deriche_apply; } + } break; + case 'z' : { + const int N = depth(); + const ulongT off = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { T *ptrX = data(x,y,0,c); _cimg_deriche_apply; } + } break; + default : { + const int N = spectrum(); + const ulongT off = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) { T *ptrX = data(x,y,z,0); _cimg_deriche_apply; } + } + } + return *this; + } + + //! Apply recursive Deriche filter \newinstance. + CImg get_deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).deriche(sigma,order,axis,boundary_conditions); + } + + // [internal] Apply a recursive filter (used by CImg::vanvliet()). + /* + \param ptr the pointer of the data + \param filter the coefficient of the filter in the following order [n,n - 1,n - 2,n - 3]. + \param N size of the data + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivative, 2nd derivative, 3rd derivative + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note Boundary condition using B. Triggs method (IEEE trans on Sig Proc 2005). + */ + static void _cimg_recursive_apply(T *data, const double filter[], const int N, const ulongT off, + const unsigned int order, const bool boundary_conditions) { + double val[4] = { 0 }; // res[n,n - 1,n - 2,n - 3,..] or res[n,n + 1,n + 2,n + 3,..] + const double + sumsq = filter[0], sum = sumsq * sumsq, + a1 = filter[1], a2 = filter[2], a3 = filter[3], + scaleM = 1. / ( (1. + a1 - a2 + a3) * (1. - a1 - a2 - a3) * (1. + a2 + (a1 - a3) * a3) ); + double M[9]; // Triggs matrix + M[0] = scaleM * (-a3 * a1 + 1. - a3 * a3 - a2); + M[1] = scaleM * (a3 + a1) * (a2 + a3 * a1); + M[2] = scaleM * a3 * (a1 + a3 * a2); + M[3] = scaleM * (a1 + a3 * a2); + M[4] = -scaleM * (a2 - 1.) * (a2 + a3 * a1); + M[5] = -scaleM * a3 * (a3 * a1 + a3 * a3 + a2 - 1.); + M[6] = scaleM * (a3 * a1 + a2 + a1 * a1 - a2 * a2); + M[7] = scaleM * (a1 * a2 + a3 * a2 * a2 - a1 * a3 * a3 - a3 * a3 * a3 - a3 * a2 + a3); + M[8] = scaleM * a3 * (a1 + a3 * a2); + switch (order) { + case 0 : { + const double iplus = (boundary_conditions?data[(N - 1)*off]:(T)0); + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 1; k<4; ++k) val[k] = (boundary_conditions?*data/sumsq:0); + } else { + // Apply Triggs boundary conditions + const double + uplus = iplus/(1. - a1 - a2 - a3), vplus = uplus/(1. - a1 - a2 - a3), + unp = val[1] - uplus, unp1 = val[2] - uplus, unp2 = val[3] - uplus; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2 + vplus) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2 + vplus) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2 + vplus) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) val[k] = val[k - 1]; + } + if (!pass) data -= off; + } + } break; + case 1 : { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + } else { data-=off;} + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 2: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 3: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + } + } + + //! Van Vliet recursive Gaussian filter. + /** + \param sigma standard deviation of the Gaussian filter + \param order the order of the filter 0,1,2,3 + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note dirichlet boundary condition has a strange behavior + + I.T. Young, L.J. van Vliet, M. van Ginkel, Recursive Gabor filtering. + IEEE Trans. Sig. Proc., vol. 50, pp. 2799-2805, 2002. + + (this is an improvement over Young-Van Vliet, Sig. Proc. 44, 1995) + + Boundary conditions (only for order 0) using Triggs matrix, from + B. Triggs and M. Sdika. Boundary conditions for Young-van Vliet + recursive filtering. IEEE Trans. Signal Processing, + vol. 54, pp. 2365-2367, 2006. + **/ + CImg& vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) { + if (is_empty()) return *this; + if (!cimg::type::is_float()) + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions).move_to(*this); + const char naxis = cimg::lowercase(axis); + const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.5f && !order)) return *this; + const double + nnsigma = nsigma<0.5f?0.5f:nsigma, + m0 = 1.16680, m1 = 1.10783, m2 = 1.40586, + m1sq = m1 * m1, m2sq = m2 * m2, + q = (nnsigma<3.556?-0.2568 + 0.5784*nnsigma + 0.0561*nnsigma*nnsigma:2.5091 + 0.9804*(nnsigma - 3.556)), + qsq = q * q, + scale = (m0 + q) * (m1sq + m2sq + 2 * m1 * q + qsq), + b1 = -q * (2 * m0 * m1 + m1sq + m2sq + (2 * m0 + 4 * m1) * q + 3 * qsq) / scale, + b2 = qsq * (m0 + 2 * m1 + 3 * q) / scale, + b3 = -qsq * q / scale, + B = ( m0 * (m1sq + m2sq) ) / scale; + double filter[4]; + filter[0] = B; filter[1] = -b1; filter[2] = -b2; filter[3] = -b3; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_recursive_apply(data(0,y,z,c),filter,_width,1U,order,boundary_conditions); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_recursive_apply(data(x,0,z,c),filter,_height,(ulongT)_width,order,boundary_conditions); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(ulongT)_width*_height, + order,boundary_conditions); + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions); + } + } + return *this; + } + + //! Blur image using Van Vliet recursive Gaussian filter. \newinstance. + CImg get_vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions); + } + + //! Blur image. + /** + \param sigma_x Standard deviation of the blur, along the X-axis. + \param sigma_y Standard deviation of the blur, along the Y-axis. + \param sigma_z Standard deviation of the blur, along the Z-axis. + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param is_gaussian Tells if the blur uses a gaussian (\c true) or quasi-gaussian (\c false) kernel. + \note + - The blur is computed as a 0-order Vanvliet (gaussian) or Deriche filter (quasi-gaussian). + - This is a recursive algorithm, not depending on the values of the standard deviations. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=true) { + if (is_empty()) return *this; + if (is_gaussian) { + if (_width>1) vanvliet(sigma_x,0,'x',boundary_conditions); + if (_height>1) vanvliet(sigma_y,0,'y',boundary_conditions); + if (_depth>1) vanvliet(sigma_z,0,'z',boundary_conditions); + } else { + if (_width>1) deriche(sigma_x,0,'x',boundary_conditions); + if (_height>1) deriche(sigma_y,0,'y',boundary_conditions); + if (_depth>1) deriche(sigma_z,0,'z',boundary_conditions); + } + return *this; + } + + //! Blur image \newinstance. + CImg get_blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=true) const { + return CImg(*this,false).blur(sigma_x,sigma_y,sigma_z,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically. + /** + \param sigma Standard deviation of the blur. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \param is_gaussian Use a gaussian kernel (VanVliet) is set, a quasi-gaussian (Deriche) otherwise. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=true) { + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur(nsigma,nsigma,nsigma,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically \newinstance. + CImg get_blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=true) const { + return CImg(*this,false).blur(sigma,boundary_conditions,is_gaussian); + } + + //! Blur image anisotropically, directed by a field of diffusion tensors. + /** + \param G Field of square roots of diffusion tensors/vectors used to drive the smoothing. + \param amplitude Amplitude of the smoothing. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=1) { + + // Check arguments and init variables + if (!is_sameXYZ(G) || (G._spectrum!=3 && G._spectrum!=6)) + throw CImgArgumentException(_cimg_instance + "blur_anisotropic(): Invalid specified diffusion tensor field (%u,%u,%u,%u,%p).", + cimg_instance, + G._width,G._height,G._depth,G._spectrum,G._data); + if (is_empty() || dl<0) return *this; + const float namplitude = amplitude>=0?amplitude:-amplitude*cimg::max(_width,_height,_depth)/100; + unsigned int iamplitude = cimg::round(namplitude); + const bool is_3d = (G._spectrum==6); + T val_min, val_max = max_min(val_min); + _cimg_abort_init_openmp; + cimg_abort_init; + + if (da<=0) { // Iterated oriented Laplacians + CImg velocity(_width,_height,_depth,_spectrum); + for (unsigned int iteration = 0; iterationveloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + else // 2D version + cimg_forZC(*this,z,c) { + cimg_abort_test; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + veloc = (Tfloat)(G(x,y,0,0)*ixx + 2*G(x,y,0,1)*ixy + G(x,y,0,2)*iyy); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + if (veloc_max>0) *this+=(velocity*=dl/veloc_max); + } + } else { // LIC-based smoothing + const ulongT whd = (ulongT)_width*_height*_depth; + const float sqrt2amplitude = (float)std::sqrt(2*namplitude); + const int dx1 = width() - 1, dy1 = height() - 1, dz1 = depth() - 1; + CImg res(_width,_height,_depth,_spectrum,0), W(_width,_height,_depth,is_3d?4:3), val(_spectrum,1,1,1,0); + int N = 0; + if (is_3d) { // 3D version + for (float phi = cimg::mod(180.f,da)/2.f; phi<=180; phi+=da) { + const float phir = (float)(phi*cimg::PI/180), datmp = (float)(da/std::cos(phir)), + da2 = datmp<1?360.f:datmp; + for (float theta = 0; theta<360; (theta+=da2),++N) { + const float + thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)*std::cos(phir)), + vy = (float)(std::sin(thetar)*std::cos(phir)), + vz = (float)std::sin(phir); + const t + *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2), + *pd = G.data(0,0,0,3), *pe = G.data(0,0,0,4), *pf = G.data(0,0,0,5); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2), *pd3 = W.data(0,0,0,3); + cimg_forXYZ(G,xg,yg,zg) { + const t a = *(pa++), b = *(pb++), c = *(pc++), d = *(pd++), e = *(pe++), f = *(pf++); + const float + u = (float)(a*vx + b*vy + c*vz), + v = (float)(b*vx + d*vy + e*vz), + w = (float)(c*vx + e*vy + f*vz), + n = 1e-5f + cimg::hypot(u,v,w), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)(w*dln); + *(pd3++) = (Tfloat)n; + } + + cimg_abort_test; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && _height*_depth>=2) + firstprivate(val)) + cimg_forYZ(*this,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,z,3), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y, + Z = (float)z; + switch (interpolation_type) { + case 0 : { // Nearest neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f), + cz = (int)(Z + 0.5f); + const float + u = (float)W(cx,cy,cz,0), + v = (float)W(cx,cy,cz,1), + w = (float)W(cx,cy,cz,2); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,cz,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,cz,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u = (float)(W._linear_atXYZ(X,Y,Z,0)), + v = (float)(W._linear_atXYZ(X,Y,Z,1)), + w = (float)(W._linear_atXYZ(X,Y,Z,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + default : { // 2nd order Runge Kutta + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)), + v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)), + w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)), + u = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,0)), + v = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,1)), + w = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + } + Tfloat *ptrd = res.data(x,y,z); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,z,c)); ptrd+=whd; } + } + } _cimg_abort_catch_openmp2 + } + } + } else { // 2D LIC algorithm + for (float theta = cimg::mod(360.f,da)/2.f; theta<360; (theta+=da),++N) { + const float thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar)); + const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2); + cimg_forXY(G,xg,yg) { + const t a = *(pa++), b = *(pb++), c = *(pc++); + const float + u = (float)(a*vx + b*vy), + v = (float)(b*vx + c*vy), + n = std::max(1e-5f,cimg::hypot(u,v)), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)n; + } + + cimg_abort_test; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && _height>=2) + firstprivate(val)) + cimg_forY(*this,y) _cimg_abort_try_openmp2 { + cimg_abort_test2; + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,0,2), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y; + switch (interpolation_type) { + case 0 : { // Nearest-neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f); + const float + u = (float)W(cx,cy,0,0), + v = (float)W(cx,cy,0,1); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u = (float)(W._linear_atXY(X,Y,0,0)), + v = (float)(W._linear_atXY(X,Y,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + default : { // 2nd-order Runge-kutta interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)), + v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)), + u = (float)(W._linear_atXY(X + u0,Y + v0,0,0)), + v = (float)(W._linear_atXY(X + u0,Y + v0,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } + } + Tfloat *ptrd = res.data(x,y); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,0,c)); ptrd+=whd; } + } + } _cimg_abort_catch_openmp2 + } + } + const Tfloat *ptrs = res._data; + cimg_for(*this,ptrd,T) { + const Tfloat _val = *(ptrs++)/N; + *ptrd = _valval_max?val_max:(T)_val); + } + } + cimg_abort_test; + return *this; + } + + //! Blur image anisotropically, directed by a field of diffusion tensors \newinstance. + template + CImg get_blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way. + /** + \param amplitude Amplitude of the smoothing. + \param sharpness Sharpness. + \param anisotropy Anisotropy. + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + CImg& blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) { + const float nalpha = alpha>=0?alpha:-alpha*cimg::max(_width,_height,_depth)/100; + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur_anisotropic(get_diffusion_tensors(sharpness,anisotropy,nalpha,nsigma,interpolation_type!=3), + amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way \newinstance. + CImg get_blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, + const float da=30, const float gauss_prec=2, + const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec, + interpolation_type,is_fast_approx); + } + + //! Blur image, with the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_x Amount of blur along the X-axis. + \param sigma_y Amount of blur along the Y-axis. + \param sigma_z Amount of blur along the Z-axis. + \param sigma_r Amount of blur along the value axis. + \param sampling_x Amount of downsampling along the X-axis used for the approximation. + Defaults (0) to sigma_x. + \param sampling_y Amount of downsampling along the Y-axis used for the approximation. + Defaults (0) to sigma_y. + \param sampling_z Amount of downsampling along the Z-axis used for the approximation. + Defaults (0) to sigma_z. + \param sampling_r Amount of downsampling along the value axis used for the approximation. + Defaults (0) to sigma_r. + \note This algorithm uses the optimisation technique proposed by S. Paris and F. Durand, in ECCV'2006 + (extended for 3D volumetric images). + It is based on the reference implementation http://people.csail.mit.edu/jiawen/software/bilateralFilter.m + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_bilateral(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || (!sigma_x && !sigma_y && !sigma_z)) return *this; + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return blur(sigma_x,sigma_y,sigma_z); + const float + edge_delta = (float)(edge_max - edge_min), + _sigma_x = sigma_x>=0?sigma_x:-sigma_x*_width/100, + _sigma_y = sigma_y>=0?sigma_y:-sigma_y*_height/100, + _sigma_z = sigma_z>=0?sigma_z:-sigma_z*_depth/100, + _sigma_r = sigma_r>=0?sigma_r:-sigma_r*edge_delta/100, + _sampling_x = sampling_x?sampling_x:std::max(_sigma_x,1.f), + _sampling_y = sampling_y?sampling_y:std::max(_sigma_y,1.f), + _sampling_z = sampling_z?sampling_z:std::max(_sigma_z,1.f), + _sampling_r = sampling_r?sampling_r:std::max(_sigma_r,edge_delta/256), + derived_sigma_x = _sigma_x / _sampling_x, + derived_sigma_y = _sigma_y / _sampling_y, + derived_sigma_z = _sigma_z / _sampling_z, + derived_sigma_r = _sigma_r / _sampling_r; + const int + padding_x = (int)(2*derived_sigma_x) + 1, + padding_y = (int)(2*derived_sigma_y) + 1, + padding_z = (int)(2*derived_sigma_z) + 1, + padding_r = (int)(2*derived_sigma_r) + 1; + const unsigned int + bx = (unsigned int)((_width - 1)/_sampling_x + 1 + 2*padding_x), + by = (unsigned int)((_height - 1)/_sampling_y + 1 + 2*padding_y), + bz = (unsigned int)((_depth - 1)/_sampling_z + 1 + 2*padding_z), + br = (unsigned int)(edge_delta/_sampling_r + 1 + 2*padding_r); + if (bx>0 || by>0 || bz>0 || br>0) { + const bool is_3d = (_depth>1); + if (is_3d) { // 3D version of the algorithm + CImg bgrid(bx,by,bz,br), bgridw(bx,by,bz,br); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); bgridw.fill(0); + cimg_forXYZ(*this,x,y,z) { + const T val = (*this)(x,y,z,c); + const float edge = (float)_guide(x,y,z); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + Z = (int)cimg::round(z/_sampling_z) + padding_z, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,Z,R)+=(float)val; + bgridw(X,Y,Z,R)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + bgridw.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),4096)) + cimg_forXYZ(*this,x,y,z) { + const float edge = (float)_guide(x,y,z); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + Z = z/_sampling_z + padding_z, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid._linear_atXYZC(X,Y,Z,R), bval1 = bgridw._linear_atXYZC(X,Y,Z,R); + (*this)(x,y,z,c) = (T)(bval0/bval1); + } + } + } else { // 2D version of the algorithm + CImg bgrid(bx,by,br,2); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); + cimg_forXY(*this,x,y) { + const T val = (*this)(x,y,c); + const float edge = (float)_guide(x,y); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,R,0)+=(float)val; + bgrid(X,Y,R,1)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,0,true).blur(0,0,derived_sigma_r,false); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(size(),4096)) + cimg_forXY(*this,x,y) { + const float edge = (float)_guide(x,y); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid._linear_atXYZ(X,Y,R,0), bval1 = bgrid._linear_atXYZ(X,Y,R,1); + (*this)(x,y,c) = (T)(bval0/bval1); + } + } + } + } + return *this; + } + + //! Blur image, with the joint bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) const { + return CImg(*this,false).blur_bilateral(guide,sigma_x,sigma_y,sigma_z,sigma_r, + sampling_x,sampling_y,sampling_z,sampling_r); + } + + //! Blur image using the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param sampling_s Amount of downsampling along the XYZ-axes used for the approximation. Defaults to sigma_s. + \param sampling_r Amount of downsampling along the value axis used for the approximation. Defaults to sigma_r. + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) { + const float _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100; + return blur_bilateral(guide,_sigma_s,_sigma_s,_sigma_s,sigma_r,sampling_s,sampling_s,sampling_s,sampling_r); + } + + //! Blur image using the bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) const { + return CImg(*this,false).blur_bilateral(guide,sigma_s,sigma_r,sampling_s,sampling_r); + } + + // [internal] Apply a box filter (used by CImg::boxfilter() and CImg::blur_box()). + /* + \param ptr the pointer of the data + \param N size of the data + \param boxsize Size of the box filter (can be subpixel). + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivative and 2nd derivative. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + */ + static void _cimg_blur_box_apply(T *ptr, const float boxsize, const int N, const ulongT off, + const int order, const bool boundary_conditions, + const unsigned int nb_iter) { + // Smooth. + if (boxsize>1 && nb_iter) { + const int w2 = (int)(boxsize - 1)/2; + const unsigned int winsize = 2*w2 + 1U; + const double frac = (boxsize - winsize)/2.; + CImg win(winsize); + for (unsigned int iter = 0; iter=N) return boundary_conditions?ptr[(N - 1)*off]:T(); + return ptr[x*off]; + } + + // Apply box filter of order 0,1,2. + /** + \param boxsize Size of the box window (can be subpixel) + \param order the order of the filter 0,1 or 2. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \param nb_iter Number of filter iterations. + **/ + CImg& boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true, + const unsigned int nb_iter=1) { + if (is_empty() || !boxsize || (boxsize<=1 && !order)) return *this; + const char naxis = cimg::lowercase(axis); + const float nboxsize = boxsize>=0?boxsize:-boxsize* + (naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_blur_box_apply(data(0,y,z,c),nboxsize,_width,1U,order,boundary_conditions,nb_iter); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_blur_box_apply(data(x,0,z,c),nboxsize,_height,(ulongT)_width,order,boundary_conditions,nb_iter); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_blur_box_apply(data(x,y,0,c),nboxsize,_depth,(ulongT)_width*_height,order,boundary_conditions,nb_iter); + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_blur_box_apply(data(x,y,z,0),nboxsize,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions,nb_iter); + } + } + return *this; + } + + // Apply box filter of order 0,1 or 2 \newinstance. + CImg get_boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true, + const unsigned int nb_iter=1) const { + return CImg(*this,false).boxfilter(boxsize,order,axis,boundary_conditions,nb_iter); + } + + //! Blur image with a box filter. + /** + \param boxsize_x Size of the box window, along the X-axis (can be subpixel). + \param boxsize_y Size of the box window, along the Y-axis (can be subpixel). + \param boxsize_z Size of the box window, along the Z-axis (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param nb_iter Number of filter iterations. + \note + - This is a recursive algorithm, not depending on the values of the box kernel size. + \see blur(). + **/ + CImg& blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true, + const unsigned int nb_iter=1) { + if (is_empty()) return *this; + if (_width>1) boxfilter(boxsize_x,0,'x',boundary_conditions,nb_iter); + if (_height>1) boxfilter(boxsize_y,0,'y',boundary_conditions,nb_iter); + if (_depth>1) boxfilter(boxsize_z,0,'z',boundary_conditions,nb_iter); + return *this; + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize_x,boxsize_y,boxsize_z,boundary_conditions); + } + + //! Blur image with a box filter. + /** + \param boxsize Size of the box window (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \see deriche(), vanvliet(). + **/ + CImg& blur_box(const float boxsize, const bool boundary_conditions=true) { + const float nboxsize = boxsize>=0?boxsize:-boxsize*cimg::max(_width,_height,_depth)/100; + return blur_box(nboxsize,nboxsize,nboxsize,boundary_conditions); + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize, const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize,boundary_conditions); + } + + //! Blur image, with the image guided filter. + /** + \param guide Image used to guide the smoothing process. + \param radius Spatial radius. If negative, it is expressed as a percentage of the largest image size. + \param regularization Regularization parameter. + If negative, it is expressed as a percentage of the guide value range. + \note This method implements the filtering algorithm described in: + He, Kaiming; Sun, Jian; Tang, Xiaoou, "Guided Image Filtering," Pattern Analysis and Machine Intelligence, + IEEE Transactions on , vol.35, no.6, pp.1397,1409, June 2013 + **/ + template + CImg& blur_guided(const CImg& guide, const float radius, const float regularization) { + return get_blur_guided(guide,radius,regularization).move_to(*this); + } + + //! Blur image, with the image guided filter \newinstance. + template + CImg get_blur_guided(const CImg& guide, const float radius, const float regularization) const { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_guided(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !radius) return *this; + const int _radius = radius>=0?(int)radius:(int)(-radius*cimg::max(_width,_height,_depth)/100); + float _regularization = regularization; + if (regularization<0) { + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return *this; + _regularization = -regularization*(edge_max - edge_min)/100; + } + _regularization = std::max(_regularization,0.01f); + const unsigned int psize = (unsigned int)(1 + 2*_radius); + CImg + mean_p = get_blur_box(psize,true), + mean_I = guide.get_blur_box(psize,true).resize(mean_p), + cov_Ip = get_mul(guide).blur_box(psize,true)-=mean_p.get_mul(mean_I), + var_I = guide.get_sqr().blur_box(psize,true)-=mean_I.get_sqr(), + &a = cov_Ip.div(var_I+=_regularization), + &b = mean_p-=a.get_mul(mean_I); + a.blur_box(psize,true); + b.blur_box(psize,true); + return a.mul(guide)+=b; + } + + //! Blur image using patch-based space. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param patch_size Size of the patches. + \param lookup_size Size of the window to search similar patches. + \param smoothness Smoothness for the patch comparison. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_patch(const CImg& guide, + const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + if (is_empty() || !patch_size || !lookup_size) return *this; + return get_blur_patch(guide,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx).move_to(*this); + } + + //! Blur image using patch-based space \newinstance. + template + CImg get_blur_patch(const CImg& guide, + const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + +#define _cimg_blur_patch3d_fast(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) \ + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) \ + firstprivate(P,Q)) \ + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N##x##N(res,x,y,z); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,x,y,z,c,pP,tfloat); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + tfloat sum_weights = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) \ + if (cimg::abs(_guide(x,y,z,0) - _guide(p,q,r,0))3?0:1; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); \ + } \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch3d(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) \ + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) \ + firstprivate(P,Q)) \ + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N##x##N(res,x,y,z); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,x,y,z,c,pP,tfloat); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + tfloat sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { \ + tfloat *pQ = Q._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,p,q,r,c,pQ,tfloat); pQ+=N3; } \ + tfloat distance2 = 0; \ + pQ = Q._data; cimg_for(P,_pP,tfloat) { const tfloat dI = *_pP - *(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const tfloat dx = (tfloat)p - x, dy = (tfloat)q - y, dz = (tfloat)r - z, \ + alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight_max*(*this)(x,y,z,c); \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch2d_fast(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) \ + firstprivate(P,Q)) \ + cimg_forXY(res,x,y) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N(res,x,y); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,x,y,0,c,pP,tfloat); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + tfloat sum_weights = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) \ + if (cimg::abs(_guide(x,y,0,0) - _guide(p,q,0,0))3?0:1; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); \ + } \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch2d(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) \ + firstprivate(P,Q)) \ + cimg_forXY(res,x,y) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N(res,x,y); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,x,y,0,c,pP,tfloat); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + tfloat sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { \ + tfloat *pQ = Q._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,p,q,0,c,pQ,tfloat); pQ+=N2; } \ + tfloat distance2 = 0; \ + pQ = Q._data; cimg_for(P,_pP,tfloat) { const tfloat dI = *_pP - *(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const tfloat dx = (tfloat)p - x, dy = (tfloat)q - y, \ + alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight_max*(*this)(x,y,c); \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } _cimg_abort_catch_openmp } + + typedef _cimg_tfloat tfloat; + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_patch(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !patch_size || !lookup_size) return +*this; + Tfloat val_min, val_max = (Tfloat)max_min(val_min); + _cimg_abort_init_openmp; + cimg_abort_init; + + CImg res(_width,_height,_depth,_spectrum,0); + const CImg + __guide = guide?CImg(guide,guide.pixel_type()==cimg::type::string()): + CImg(*this,pixel_type()==cimg::type::string()), + _guide = smoothness>0?__guide.get_blur(smoothness):__guide.get_shared(); + CImg P(_guide._spectrum*patch_size*patch_size*(_depth>1?patch_size:1)), Q(P); + + t guide_min = (t)0, guide_max = (t)0; + if (sigma_r<0) guide_max = guide.max_min(guide_min); + const float + guide_delta = (float)(guide_max - guide_min), + _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100, + _sigma_r = sigma_r>=0?sigma_r:-sigma_r*guide_delta/100, + sigma_s2 = _sigma_s*_sigma_s, + sigma_r2 = _sigma_r*_sigma_r, + sigma_r3 = 3*_sigma_r, + Pnorm = P.size()*sigma_r2; + const int rsize2 = (int)lookup_size/2, rsize1 = (int)lookup_size - rsize2 - 1; + const unsigned int N2 = patch_size*patch_size, N3 = N2*patch_size; + cimg::unused(N2,N3); + if (_depth>1) switch (patch_size) { // 3D + case 2 : if (is_fast_approx) _cimg_blur_patch3d_fast(2) else _cimg_blur_patch3d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch3d_fast(3) else _cimg_blur_patch3d(3) break; + default : { + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) + firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { // Fast + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + tfloat sum_weights = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) + if (cimg::abs(_guide(x,y,z,0) - _guide(p,q,r,0))3?0:1; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); + } + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } _cimg_abort_catch_openmp + } else { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) + firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { // Exact + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + tfloat sum_weights = 0, weight_max = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { + (Q = _guide.get_crop(p - psize1,q - psize1,r - psize1,p + psize2,q + psize2,r + psize2,true))-=P; + const tfloat + dx = (tfloat)x - p, dy = (tfloat)y - q, dz = (tfloat)z - r, + distance2 = (tfloat)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2), + weight = std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight_max*(*this)(x,y,z,c); + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } _cimg_abort_catch_openmp + } + } + } else switch (patch_size) { // 2D + case 2 : if (is_fast_approx) _cimg_blur_patch2d_fast(2) else _cimg_blur_patch2d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch2d_fast(3) else _cimg_blur_patch2d(3) break; + case 4 : if (is_fast_approx) _cimg_blur_patch2d_fast(4) else _cimg_blur_patch2d(4) break; + case 5 : if (is_fast_approx) _cimg_blur_patch2d_fast(5) else _cimg_blur_patch2d(5) break; + case 6 : if (is_fast_approx) _cimg_blur_patch2d_fast(6) else _cimg_blur_patch2d(6) break; + case 7 : if (is_fast_approx) _cimg_blur_patch2d_fast(7) else _cimg_blur_patch2d(7) break; + case 8 : if (is_fast_approx) _cimg_blur_patch2d_fast(8) else _cimg_blur_patch2d(8) break; + case 9 : if (is_fast_approx) _cimg_blur_patch2d_fast(9) else _cimg_blur_patch2d(9) break; + default : { // Fast + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) { + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) + firstprivate(P,Q)) + cimg_forXY(res,x,y) _cimg_abort_try_openmp { // Fast + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + tfloat sum_weights = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) + if (cimg::abs(_guide(x,y,0) - _guide(p,q,0))3?0:1; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); + } + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } _cimg_abort_catch_openmp + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) + firstprivate(P,Q)) + cimg_forXY(res,x,y) _cimg_abort_try_openmp { // Exact + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + tfloat sum_weights = 0, weight_max = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { + (Q = _guide.get_crop(p - psize1,q - psize1,p + psize2,q + psize2,true))-=P; + const tfloat + dx = (tfloat)x - p, dy = (tfloat)y - q, + distance2 = (tfloat)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2), + weight = std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight_max*(*this)(x,y,c); + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } _cimg_abort_catch_openmp + } + } + } + return res.cut(val_min,val_max); + } + + //! Blur image using patch-based space \simplification. + CImg& blur_patch(const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + return blur_patch(*this,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx); + } + + //! Blur image using patch-based space \simplification \newinstance. + CImg get_blur_patch(const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + return get_blur_patch(*this,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx); + } + + //! Blur image with the median filter. + /** + \param n Size of the median filter. + \param threshold Threshold used to discard pixels too far from the current pixel value in the median computation. + **/ + CImg& blur_median(const unsigned int n, const float threshold=0) { + if (!n) return *this; + return get_blur_median(n,threshold).move_to(*this); + } + + //! Blur image with the median filter \newinstance. + CImg get_blur_median(const unsigned int n, const float threshold=0) const { + if (is_empty() || n<=1) return +*this; + CImg res(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg::unused(ptrd); + const int hr = (int)n/2, hl = n - hr - 1; + if (res._depth!=1) { // 3D + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // With threshold + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + const Tfloat val0 = (Tfloat)(*this)(x,y,z,c); + CImg values(n*n*n); + unsigned int nb_values = 0; + T *_ptrd = values.data(); + cimg_for_inXYZ(*this,nx0,ny0,nz0,nx1,ny1,nz1,p,q,r) + if (cimg::abs((*this)(p,q,r,c) - val0)<=threshold) { *(_ptrd++) = (*this)(p,q,r,c); ++nb_values; } + res(x,y,z,c) = nb_values?values.get_shared_points(0,nb_values - 1).median():(*this)(x,y,z,c); + } + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // Without threshold + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + res(x,y,z,c) = get_crop(nx0,ny0,nz0,c,nx1,ny1,nz1,c).median(); + } + } else { + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { // With threshold + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + const Tfloat val0 = (Tfloat)(*this)(x,y,c); + CImg values(n*n); + unsigned int nb_values = 0; + T *_ptrd = values.data(); + cimg_for_inXY(*this,nx0,ny0,nx1,ny1,p,q) + if (cimg::abs((*this)(p,q,c) - val0)<=threshold) { *(_ptrd++) = (*this)(p,q,c); ++nb_values; } + res(x,y,c) = nb_values?values.get_shared_points(0,nb_values - 1).median():(*this)(x,y,c); + } + else { + const int + w1 = width() - 1, h1 = height() - 1, + w2 = width() - 2, h2 = height() - 2, + w3 = width() - 3, h3 = height() - 3, + w4 = width() - 4, h4 = height() - 4; + switch (n) { // Without threshold + case 3 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(9); + cimg_for_in3x3(*this,1,1,w2,h2,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6],I[7],I[8]); + cimg_for_borderXY(*this,x,y,1) + res(x,y,c) = get_crop(std::max(0,x - 1),std::max(0,y - 1),0,c, + std::min(w1,x + 1),std::min(h1,y + 1),0,c).median(); + } + } break; + case 5 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(25); + cimg_for_in5x5(*this,2,2,w3,h3,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4], + I[5],I[6],I[7],I[8],I[9], + I[10],I[11],I[12],I[13],I[14], + I[15],I[16],I[17],I[18],I[19], + I[20],I[21],I[22],I[23],I[24]); + cimg_for_borderXY(*this,x,y,2) + res(x,y,c) = get_crop(std::max(0,x - 2),std::max(0,y - 2),0,c, + std::min(w1,x + 2),std::min(h1,y + 2),0,c).median(); + } + } break; + case 7 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(49); + cimg_for_in7x7(*this,3,3,w4,h4,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6], + I[7],I[8],I[9],I[10],I[11],I[12],I[13], + I[14],I[15],I[16],I[17],I[18],I[19],I[20], + I[21],I[22],I[23],I[24],I[25],I[26],I[27], + I[28],I[29],I[30],I[31],I[32],I[33],I[34], + I[35],I[36],I[37],I[38],I[39],I[40],I[41], + I[42],I[43],I[44],I[45],I[46],I[47],I[48]); + cimg_for_borderXY(*this,x,y,3) + res(x,y,c) = get_crop(std::max(0,x - 3),std::max(0,y - 3),0,c, + std::min(w1,x + 3),std::min(h1,y + 3),0,c).median(); + } + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + res(x,y,c) = get_crop(nx0,ny0,0,c,nx1,ny1,0,c).median(); + } + } + } + } + } + return res; + } + + //! Sharpen image. + /** + \param amplitude Sharpening amplitude + \param sharpen_type Select sharpening method. Can be { false=inverse diffusion | true=shock filters }. + \param edge Edge threshold (shock filters only). + \param alpha Gradient smoothness (shock filters only). + \param sigma Tensor smoothness (shock filters only). + **/ + CImg& sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) { + if (is_empty()) return *this; + T val_min, val_max = max_min(val_min); + const float nedge = edge/2; + CImg velocity(_width,_height,_depth,_spectrum), _veloc_max(_spectrum); + + if (_depth>1) { // 3D + if (sharpen_type) { // Shock filters + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*32 && + _height*_depth>=16)) + cimg_forYZ(G,y,z) { + Tfloat *ptrG0 = G.data(0,y,z,0), *ptrG1 = G.data(0,y,z,1), + *ptrG2 = G.data(0,y,z,2), *ptrG3 = G.data(0,y,z,3); + CImg val, vec; + cimg_forX(G,x) { + G.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + if (val[2]<0) val[2] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = vec(0,2); + *(ptrG3++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1] + val[2],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + u = G(x,y,z,0), + v = G(x,y,z,1), + w = G(x,y,z,2), + amp = G(x,y,z,3), + ixx = Incc + Ipcc - 2*Iccc, + ixy = (Innc + Ippc - Inpc - Ipnc)/4, + ixz = (Incn + Ipcp - Incp - Ipcn)/4, + iyy = Icnc + Icpc - 2*Iccc, + iyz = (Icnn + Icpp - Icnp - Icpn)/4, + izz = Iccn + Iccp - 2*Iccc, + ixf = Incc - Iccc, + ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, + iyb = Iccc - Icpc, + izf = Iccn - Iccc, + izb = Iccc - Iccp, + itt = u*u*ixx + v*v*iyy + w*w*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb) + w*cimg::minmod(izf,izb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat veloc = -Ipcc - Incc - Icpc - Icnc - Iccp - Iccn + 6*Iccc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else { // 2D + if (sharpen_type) { // Shock filters + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*32 && + _height>=(cimg_openmp_sizefactor)*16)) + cimg_forY(G,y) { + CImg val, vec; + Tfloat *ptrG0 = G.data(0,y,0,0), *ptrG1 = G.data(0,y,0,1), *ptrG2 = G.data(0,y,0,2); + cimg_forX(G,x) { + G.get_tensor_at(x,y).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + u = G(x,y,0), + v = G(x,y,1), + amp = G(x,y,2), + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + ixf = Inc - Icc, + ixb = Icc - Ipc, + iyf = Icn - Icc, + iyb = Icc - Icp, + itt = u*u*ixx + v*v*iyy + 2*u*v*ixy, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat veloc = -Ipc - Inc - Icp - Icn + 4*Icc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } + const Tfloat veloc_max = _veloc_max.max(); + if (veloc_max<=0) return *this; + return ((velocity*=amplitude/veloc_max)+=*this).cut(val_min,val_max).move_to(*this); + } + + //! Sharpen image \newinstance. + CImg get_sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) const { + return (+*this).sharpen(amplitude,sharpen_type,edge,alpha,sigma); + } + + //! Return image gradient. + /** + \param axes Axes considered for the gradient computation, as a C-string (e.g "xy"). + \param scheme = Numerical scheme used for the gradient computation: + - -1 = Backward finite differences + - 0 = Centered finite differences (default) + - 1 = Forward finite differences + - 2 = Using Sobel kernels + - 3 = Using rotation invariant kernels + - 4 = Using Deriche recursive filter. + - 5 = Using Van Vliet recursive filter. + **/ + CImgList get_gradient(const char *const axes=0, const int scheme=0) const { + CImgList res; + char __axes[4] = { 0 }; + const char *_axes = axes?axes:__axes; + if (!axes) { + unsigned int k = 0; + if (_width>1) __axes[k++] = 'x'; + if (_height>1) __axes[k++] = 'y'; + if (_depth>1) __axes[k++] = 'z'; + } + + CImg grad; + while (*_axes) { + const char axis = cimg::lowercase(*(_axes++)); + if (axis!='x' && axis!='y' && axis!='z') + throw CImgArgumentException(_cimg_instance + "get_gradient(): Invalid specified axes '%s'.", + cimg_instance, + axes); + const longT off = axis=='x'?1:axis=='y'?_width:_width*_height; + if ((axis=='x' && _width==1) || (axis=='y' && _height==1) || (axis=='z' && _depth==1)) { + grad.assign(_width,_height,_depth,_spectrum,0).move_to(res); + continue; + } + + const int _scheme = axis=='z' && (scheme==2 || scheme==3)?0:scheme; + switch (_scheme) { + case -1 : { // Backward finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && !x) || (axis=='y' && !y) || (axis=='z' && !z)) + grad[pos] = 0; + else + grad[pos] = (Tfloat)_data[pos] - _data[pos - off]; + } + grad.move_to(res); + } break; + case 1 : { // Forward finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && x==width() - 1) || (axis=='y' && y==height() - 1) || (axis=='z' && z==depth() - 1)) + grad[pos] = 0; + else + grad[pos] = (Tfloat)_data[pos + off] - _data[pos]; + } + grad.move_to(res); + } break; + case 2 : { // Sobel scheme + grad.assign(_width,_height,_depth,_spectrum); + if (axis=='x') // X-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = - Ipp + Inp - 2*Ipc + 2*Inc - Ipn + Inn; + } + else // Y-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = - Ipp - 2*Icp - Inp + Ipn + 2*Icn + Inn; + } + grad.move_to(res); + } break; + case 3 : { // Rotation invariant scheme + const Tfloat a = (Tfloat)(0.25f*(2 - std::sqrt(2.f))), b = (Tfloat)(0.5f*(std::sqrt(2.f) - 1)); + grad.assign(_width,_height,_depth,_spectrum); + if (axis=='x') // X-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn; + } + else // Y-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn; + } + grad.move_to(res); + } break; + case 4 : // Deriche filter + get_deriche(0,1,axis).move_to(res); + break; + case 5 : // Van Vliet filter + get_vanvliet(0,1,axis).move_to(res); + break; + default : { // Central finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && !x) || (axis=='y' && !y) || (axis=='z' && !z)) + grad[pos] = ((Tfloat)_data[pos + off] - _data[pos])/2; + else if ((axis=='x' && x==width() - 1) || (axis=='y' && y==height() - 1) || (axis=='z' && z==depth() - 1)) + grad[pos] = ((Tfloat)_data[pos] - _data[pos - off])/2; + else + grad[pos] = ((Tfloat)_data[pos + off] - _data[pos - off])/2; + } + grad.move_to(res); + } break; + } + } + return res; + } + + //! Return image hessian. + /** + \param axes Axes considered for the hessian computation, as a C-string (e.g "xy"). + **/ + CImgList get_hessian(const char *const axes=0) const { + CImgList res; + char __axes[12] = { 0 }; + const char *_axes = axes?axes:__axes; + if (!axes) { + unsigned int k = 0; + if (_width>1) { __axes[k++] = 'x'; __axes[k++] = 'x'; } + if (_width>1 && _height>1) { __axes[k++] = 'x'; __axes[k++] = 'y'; } + if (_width>1 && _depth>1) { __axes[k++] = 'x'; __axes[k++] = 'z'; } + if (_height>1) { __axes[k++] = 'y'; __axes[k++] = 'y'; } + if (_height>1 && _depth>1) { __axes[k++] = 'y'; __axes[k++] = 'z'; } + if (_depth>1) { __axes[k++] = 'z'; __axes[k++] = 'z'; } + } + const unsigned int len = (unsigned int)std::strlen(_axes); + if (len%2) + throw CImgArgumentException(_cimg_instance + "get_hessian(): Invalid specified axes '%s'.", + cimg_instance, + axes); + CImg hess; + for (unsigned int k = 0; k=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Inn + Ipp - Inp - Ipn)/4; + } + else if (axis1=='x' && axis2=='z') // Ixz + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*16384 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Incn + Ipcp - Incp - Ipcn)/4; + } + else // Iyz + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*16384 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Icnn + Icpp - Icnp - Icpn)/4; + } + hess.move_to(res); + } + return res; + } + + //! Compute image Laplacian. + CImg& laplacian() { + return get_laplacian().move_to(*this); + } + + //! Compute image Laplacian \newinstance. + CImg get_laplacian() const { + if (is_empty()) return CImg(); + CImg res(_width,_height,_depth,_spectrum); + if (_depth>1) { // 3D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Incc + Ipcc + Icnc + Icpc + Iccn + Iccp - 6*Iccc; + } + } else if (_height>1) { // 2D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc + Icn + Icp - 4*Icc; + } + } else { // 1D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*1048576 && + _height*_depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc - 2*Icc; + } + } + return res; + } + + //! Compute the structure tensor field of an image. + /** + \param is_fwbw_scheme scheme. Can be { false=centered | true=forward-backward } + **/ + CImg& structure_tensors(const bool is_fwbw_scheme=false) { + return get_structure_tensors(is_fwbw_scheme).move_to(*this); + } + + //! Compute the structure tensor field of an image \newinstance. + CImg get_structure_tensors(const bool is_fwbw_scheme=false) const { + if (is_empty()) return *this; + CImg res; + if (_depth>1) { // 3D + res.assign(_width,_height,_depth,6,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ix = (Incc - Ipcc)/2, + iy = (Icnc - Icpc)/2, + iz = (Iccn - Iccp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=ix*iz; + *(ptrd3++)+=iy*iy; + *(ptrd4++)+=iy*iz; + *(ptrd5++)+=iz*iz; + } + } + } else { // Forward/backward finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixf = Incc - Iccc, ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, iyb = Iccc - Icpc, + izf = Iccn - Iccc, izb = Iccc - Iccp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4; + *(ptrd3++)+=(iyf*iyf + iyb*iyb)/2; + *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4; + *(ptrd5++)+=(izf*izf + izb*izb)/2; + } + } + } + } else { // 2D + res.assign(_width,_height,_depth,3,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ix = (Inc - Ipc)/2, + iy = (Icn - Icp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=iy*iy; + } + } + } else { // Forward/backward finite differences (version 2) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ixf = Inc - Icc, ixb = Icc - Ipc, + iyf = Icn - Icc, iyb = Icc - Icp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2; + } + } + } + } + return res; + } + + //! Compute field of diffusion tensors for edge-preserving smoothing. + /** + \param sharpness Sharpness + \param anisotropy Anisotropy + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param is_sqrt Tells if the square root of the tensor field is computed instead. + **/ + CImg& diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) { + CImg res; + const float + nsharpness = std::max(sharpness,1e-5f), + power1 = (is_sqrt?0.5f:1)*nsharpness, + power2 = power1/(1e-7f + 1 - anisotropy); + blur(alpha).normalize(0,(T)255); + + if (_depth>1) { // 3D + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth>=(cimg_openmp_sizefactor)*256)) + cimg_forYZ(*this,y,z) { + Tfloat + *ptrd0 = res.data(0,y,z,0), *ptrd1 = res.data(0,y,z,1), *ptrd2 = res.data(0,y,z,2), + *ptrd3 = res.data(0,y,z,3), *ptrd4 = res.data(0,y,z,4), *ptrd5 = res.data(0,y,z,5); + CImg val(3), vec(3,3); + cimg_forX(*this,x) { + res.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + const float + _l1 = val[2], _l2 = val[1], _l3 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, l3 = _l3>0?_l3:0, + ux = vec(0,0), uy = vec(0,1), uz = vec(0,2), + vx = vec(1,0), vy = vec(1,1), vz = vec(1,2), + wx = vec(2,0), wy = vec(2,1), wz = vec(2,2), + n1 = (float)std::pow(1 + l1 + l2 + l3,-power1), + n2 = (float)std::pow(1 + l1 + l2 + l3,-power2); + *(ptrd0++) = n1*(ux*ux + vx*vx) + n2*wx*wx; + *(ptrd1++) = n1*(ux*uy + vx*vy) + n2*wx*wy; + *(ptrd2++) = n1*(ux*uz + vx*vz) + n2*wx*wz; + *(ptrd3++) = n1*(uy*uy + vy*vy) + n2*wy*wy; + *(ptrd4++) = n1*(uy*uz + vy*vz) + n2*wy*wz; + *(ptrd5++) = n1*(uz*uz + vz*vz) + n2*wz*wz; + } + } + } else { // for 2D images + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height>=(cimg_openmp_sizefactor)*256)) + cimg_forY(*this,y) { + Tfloat *ptrd0 = res.data(0,y,0,0), *ptrd1 = res.data(0,y,0,1), *ptrd2 = res.data(0,y,0,2); + CImg val(2), vec(2,2); + cimg_forX(*this,x) { + res.get_tensor_at(x,y).symmetric_eigen(val,vec); + const float + _l1 = val[1], _l2 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, + ux = vec(1,0), uy = vec(1,1), + vx = vec(0,0), vy = vec(0,1), + n1 = (float)std::pow(1 + l1 + l2,-power1), + n2 = (float)std::pow(1 + l1 + l2,-power2); + *(ptrd0++) = n1*ux*ux + n2*vx*vx; + *(ptrd1++) = n1*ux*uy + n2*vx*vy; + *(ptrd2++) = n1*uy*uy + n2*vy*vy; + } + } + } + return res.move_to(*this); + } + + //! Compute field of diffusion tensors for edge-preserving smoothing \newinstance. + CImg get_diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) const { + return CImg(*this,false).diffusion_tensors(sharpness,anisotropy,alpha,sigma,is_sqrt); + } + + //! Estimate displacement field between two images. + /** + \param source Reference image. + \param smoothness Smoothness of estimated displacement field. + \param precision Precision required for algorithm convergence. + \param nb_scales Number of scales used to estimate the displacement field. + \param iteration_max Maximum number of iterations allowed for one scale. + \param is_backward If false, match I2(X + U(X)) = I1(X), else match I2(X) = I1(X - U(X)). + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + **/ + CImg& displacement(const CImg& source, const float smoothness=0.1f, const float precision=5.f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) { + return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward,guide). + move_to(*this); + } + + //! Estimate displacement field between two images \newinstance. + CImg get_displacement(const CImg& source, + const float smoothness=0.1f, const float precision=5.f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) const { + if (is_empty() || !source) return +*this; + if (!is_sameXYZC(source)) + throw CImgArgumentException(_cimg_instance + "displacement(): Instance and source image (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + source._width,source._height,source._depth,source._spectrum,source._data); + if (precision<0) + throw CImgArgumentException(_cimg_instance + "displacement(): Invalid specified precision %g " + "(should be >=0)", + cimg_instance, + precision); + + const bool is_3d = source._depth>1; + const unsigned int constraint = is_3d?3:2; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum0?nb_scales: + (unsigned int)cimg::round(std::log(mins/8.)/std::log(1.5),1,1); + + const float _precision = (float)std::pow(10.,-(double)precision); + float sm, sM = source.max_min(sm), tm, tM = max_min(tm); + const float sdelta = sm==sM?1:(sM - sm), tdelta = tm==tM?1:(tM - tm); + + CImg U, V; + floatT bound = 0; + for (int scale = (int)_nb_scales - 1; scale>=0; --scale) { + const float factor = (float)std::pow(1.5,(double)scale); + const unsigned int + _sw = (unsigned int)(_width/factor), sw = _sw?_sw:1, + _sh = (unsigned int)(_height/factor), sh = _sh?_sh:1, + _sd = (unsigned int)(_depth/factor), sd = _sd?_sd:1; + if (sw<5 && sh<5 && (!is_3d || sd<5)) continue; // Skip too small scales + const CImg + I1 = (source.get_resize(sw,sh,sd,-100,2)-=sm)/=sdelta, + I2 = (get_resize(I1,2)-=tm)/=tdelta; + if (guide._spectrum>constraint) guide.get_resize(I2._width,I2._height,I2._depth,-100,1).move_to(V); + if (U) (U*=1.5f).resize(I2._width,I2._height,I2._depth,-100,3); + else { + if (guide) + guide.get_shared_channels(0,is_3d?2:1).get_resize(I2._width,I2._height,I2._depth,-100,2).move_to(U); + else U.assign(I2._width,I2._height,I2._depth,is_3d?3:2,0); + } + + float dt = 2, energy = cimg::type::max(); + const CImgList dI = is_backward?I1.get_gradient():I2.get_gradient(); + cimg_abort_init; + + for (unsigned int iteration = 0; iteration=0) // Isotropic regularization + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height*_depth>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,_x,_y,_z) if (V(_x,_y,_z,3)) { // Apply constraints + U(_x,_y,_z,0) = V(_x,_y,_z,0)/factor; + U(_x,_y,_z,1) = V(_x,_y,_z,1)/factor; + U(_x,_y,_z,2) = V(_x,_y,_z,2)/factor; + } + } else { // Anisotropic regularization + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height*_depth>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,_x,_y,_z) if (V(_x,_y,_z,3)) { // Apply constraints + U(_x,_y,_z,0) = V(_x,_y,_z,0)/factor; + U(_x,_y,_z,1) = V(_x,_y,_z,1)/factor; + U(_x,_y,_z,2) = V(_x,_y,_z,2)/factor; + } + } + } + } else { // 2D version + if (smoothness>=0) // Isotropic regularization + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXY(V,_x,_y) if (V(_x,_y,2)) { // Apply constraints + U(_x,_y,0) = V(_x,_y,0)/factor; + U(_x,_y,1) = V(_x,_y,1)/factor; + } + } else { // Anisotropic regularization + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXY(V,_x,_y) if (V(_x,_y,2)) { // Apply constraints + U(_x,_y,0) = V(_x,_y,0)/factor; + U(_x,_y,1) = V(_x,_y,1)/factor; + } + } + } + } + const float d_energy = (_energy - energy)/(sw*sh*sd); + if (d_energy<=0 && -d_energy<_precision) break; + if (d_energy>0) dt*=0.5f; + energy = _energy; + } + } + return U; + } + + //! Compute correspondence map between two images, using a patch-matching algorithm. + /** + \param patch_image The image containing the reference patches to match with the instance image. + \param patch_width Width of the patch used for matching. + \param patch_height Height of the patch used for matching. + \param patch_depth Depth of the patch used for matching. + \param nb_iterations Number of patch-match iterations. + \param nb_randoms Number of randomization attempts (per pixel). + \param patch_penalization Penalization factor in score related patch occurrences. + if negative, also tells that identity result is not avoided. + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + \param[out] matching_score Returned as the image of matching scores. + **/ + template + CImg& matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + CImg &matching_score) { + return get_matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide,matching_score).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \newinstance. + template + CImg get_matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + CImg &matching_score) const { + return _matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization, + guide,true,matching_score); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg& matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5, + const float patch_penalization=0, + const CImg &guide=CImg::const_empty()) { + return get_matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg get_matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5, + const float patch_penalization=0, + const CImg &guide=CImg::const_empty()) const { + CImg matching_score; + return _matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide,false,matching_score); + } + + template + CImg _matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + const bool is_matching_score, + CImg &matching_score) const { + if (is_empty()) return CImg::const_empty(); + if (patch_image._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Instance image and specified patch image (%u,%u,%u,%u,%p) " + "have different spectrums.", + cimg_instance, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + if (patch_width>_width || patch_height>_height || patch_depth>_depth) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the instance image.", + cimg_instance,patch_width,patch_height,patch_depth); + if (patch_width>patch_image._width || patch_height>patch_image._height || patch_depth>patch_image._depth) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the patch image image (%u,%u,%u,%u,%p).", + cimg_instance,patch_width,patch_height,patch_depth, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + const unsigned int + _constraint = patch_image._depth>1?3:2, + constraint = guide._spectrum>_constraint?_constraint:0; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum<_constraint)) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified guide (%u,%u,%u,%u,%p) has invalid dimensions " + "considering instance and patch image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + + CImg a_map(_width,_height,_depth,patch_image._depth>1?3:2); + CImg is_updated(_width,_height,_depth,1,3); + CImg score(_width,_height,_depth); + CImg occ; + const float _patch_penalization = cimg::abs(patch_penalization); + const bool allow_identity = patch_penalization>=0; + if (_patch_penalization!=0) occ.assign(patch_image._width,patch_image._height,patch_image._depth,1,0); + const int + psizew = (int)patch_width, psizew1 = psizew/2, psizew2 = psizew - psizew1 - 1, + psizeh = (int)patch_height, psizeh1 = psizeh/2, psizeh2 = psizeh - psizeh1 - 1, + psized = (int)patch_depth, psized1 = psized/2, psized2 = psized - psized1 - 1; + + // Interleave image buffers to speed up patch comparison (cache-friendly). + CImg in_this = get_permute_axes("cxyz"); + in_this._width = _width*_spectrum; + in_this._height = _height; + in_this._depth = _depth; + in_this._spectrum = 1; + CImg in_patch = patch_image.get_permute_axes("cxyz"); + in_patch._width = patch_image._width*patch_image._spectrum; + in_patch._height = patch_image._height; + in_patch._depth = patch_image._depth; + in_patch._spectrum = 1; + + if (_depth>1 || patch_image._depth>1) { // 3D version + + // Initialize correspondence map. + if (guide) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(_width,64)) + cimg_forXYZ(*this,x,y,z) { // User-defined initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(_width,64)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for cimg_openmp_collapse(2)) + cimg_forXYZ(*this,x,y,z) { // Random initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } + cimg::srand(rng); + } + + // Start iteration loop. + cimg_abort_init; + for (unsigned int iter = 0; iter=(cimg_openmp_sizefactor)*64 && + iter0 && (is_updated(x - 1,y,z)&cmask)) { // Compare with left neighbor + u = a_map(x - 1,y,z,0); + v = a_map(x - 1,y,z,1); + w = a_map(x - 1,y,z,2); + if (u>=cx1 - 1 && u=cy1 && v=cz1 && w0 && (is_updated(x,y - 1,z)&cmask)) { // Compare with up neighbor + u = a_map(x,y - 1,z,0); + v = a_map(x,y - 1,z,1); + w = a_map(x,y - 1,z,2); + if (u>=cx1 && u=cy1 - 1 && v=cz1 && w0 && (is_updated(x,y,z - 1)&cmask)) { // Compare with backward neighbor + u = a_map(x,y,z - 1,0); + v = a_map(x,y,z - 1,1); + w = a_map(x,y,z - 1,2); + if (u>=cx1 && u=cy1 && v=cz1 - 1 && w=cx1 + 1 && u=cy1 && v=cz1 && w=cx1 && u=cy1 + 1 && v=cz1 && w=cx1 && u=cy1 && v=cz1 + 1 && w::inf()); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(_width,64)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_forXY(*this,x,y) { // Random initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } + cimg::srand(rng); + } + + // Start iteration loop. + cimg_abort_init; + for (unsigned int iter = 0; iter=(cimg_openmp_sizefactor)*64 && + iter0 && (is_updated(x - 1,y)&cmask)) { // Compare with left neighbor + u = a_map(x - 1,y,0); + v = a_map(x - 1,y,1); + if (u>=cx1 - 1 && u=cy1 && v0 && (is_updated(x,y - 1)&cmask)) { // Compare with up neighbor + u = a_map(x,y - 1,0); + v = a_map(x,y - 1,1); + if (u>=cx1 && u=cy1 - 1 && v=cx1 + 1 && u=cy1 && v=cx1 && u=cy1 + 1 && v& img1, const CImg& img2, const CImg& occ, + const unsigned int psizew, const unsigned int psizeh, + const unsigned int psized, const unsigned int psizec, + const int x1, const int y1, const int z1, + const int x2, const int y2, const int z2, + const int xc, const int yc, const int zc, + const float patch_penalization, + const bool allow_identity, + const float max_score) { // 3D version + if (!allow_identity && cimg::hypot((float)x1-x2,(float)y1-y2,(float)z1-z2)::inf(); + const T *p1 = img1.data(x1*psizec,y1,z1), *p2 = img2.data(x2*psizec,y2,z2); + const unsigned int psizewc = psizew*psizec; + const ulongT + offx1 = (ulongT)img1._width - psizewc, + offx2 = (ulongT)img2._width - psizewc, + offy1 = (ulongT)img1._width*img1._height - (ulongT)psizeh*img1._width, + offy2 = (ulongT)img2._width*img2._height - (ulongT)psizeh*img2._width; + float ssd = 0; + for (unsigned int k = 0; kmax_score) return max_score; + p1+=offx1; p2+=offx2; + } + p1+=offy1; p2+=offy2; + } + return patch_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + + patch_penalization*psizewc*psizeh*psized*occ(xc,yc,zc)/100); + } + + static float _matchpatch(const CImg& img1, const CImg& img2, const CImg& occ, + const unsigned int psizew, const unsigned int psizeh, const unsigned int psizec, + const int x1, const int y1, + const int x2, const int y2, + const int xc, const int yc, + const float patch_penalization, + const bool allow_identity, + const float max_score) { // 2D version + if (!allow_identity && cimg::hypot((float)x1-x2,(float)y1-y2)::inf(); + const T *p1 = img1.data(x1*psizec,y1), *p2 = img2.data(x2*psizec,y2); + const unsigned int psizewc = psizew*psizec; + const ulongT + offx1 = (ulongT)img1._width - psizewc, + offx2 = (ulongT)img2._width - psizewc; + float ssd = 0; + for (unsigned int j = 0; jmax_score) return max_score; + p1+=offx1; p2+=offx2; + } + return patch_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + + patch_penalization*psizewc*psizeh*occ(xc,yc)/100); + } + + //! Compute Euclidean distance function to a specified value. + /** + \param value Reference value. + \param metric Type of metric. Can be { 0=Chebyshev | 1=Manhattan | 2=Euclidean | 3=Squared-euclidean }. + \note + The distance transform implementation has been submitted by A. Meijster, and implements + the article 'W.H. Hesselink, A. Meijster, J.B.T.M. Roerdink, + "A general algorithm for computing distance transforms in linear time.", + In: Mathematical Morphology and its Applications to Image and Signal Processing, + J. Goutsias, L. Vincent, and D.S. Bloomberg (eds.), Kluwer, 2000, pp. 331-340.' + The submitted code has then been modified to fit CImg coding style and constraints. + **/ + CImg& distance(const T& value, const unsigned int metric=2) { + if (is_empty()) return *this; + if (cimg::type::string()!=pixel_type()) // For datatype < int + return CImg(*this,false).distance((Tint)value,metric). + cut((Tint)cimg::type::min(),(Tint)cimg::type::max()).move_to(*this); + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,(T)0:(T)std::max(0,99999999); // (avoid VC++ warning) + if (!is_value) return fill(cimg::type::max()); + switch (metric) { + case 0 : return _distance_core(_distance_sep_cdt,_distance_dist_cdt); // Chebyshev + case 1 : return _distance_core(_distance_sep_mdt,_distance_dist_mdt); // Manhattan + case 3 : return _distance_core(_distance_sep_edt,_distance_dist_edt); // Squared Euclidean + default : return _distance_core(_distance_sep_edt,_distance_dist_edt).sqrt(); // Euclidean + } + return *this; + } + + //! Compute distance to a specified value \newinstance. + CImg get_distance(const T& value, const unsigned int metric=2) const { + return CImg(*this,false).distance((Tfloat)value,metric); + } + + static longT _distance_sep_edt(const longT i, const longT u, const longT *const g) { + return (u*u - i*i + g[u] - g[i])/(2*(u - i)); + } + + static longT _distance_dist_edt(const longT x, const longT i, const longT *const g) { + return (x - i)*(x - i) + g[i]; + } + + static longT _distance_sep_mdt(const longT i, const longT u, const longT *const g) { + return (u - i<=g[u] - g[i]?999999999:(g[u] - g[i] + u + i)/2); + } + + static longT _distance_dist_mdt(const longT x, const longT i, const longT *const g) { + return (x=0) && f(t[q],s[q],g)>f(t[q],u,g)) { --q; } + if (q<0) { q = 0; s[0] = u; } + else { const longT w = 1 + sep(s[q], u, g); if (w<(longT)len) { ++q; s[q] = u; t[q] = w; }} + } + for (int u = (int)len - 1; u>=0; --u) { dt[u] = f(u,s[q],g); if (u==t[q]) --q; } // Backward scan + } + + CImg& _distance_core(longT (*const sep)(const longT, const longT, const longT *const), + longT (*const f)(const longT, const longT, const longT *const)) { + // Check for g++ 4.9.X, as OpenMP seems to crash for this particular function. I have no clues why. +#define cimg_is_gcc49x (__GNUC__==4 && __GNUC_MINOR__==9) + + const ulongT wh = (ulongT)_width*_height; +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) +#endif + cimg_forC(*this,c) { + CImg g(_width), dt(_width), s(_width), t(_width); + CImg img = get_shared_channel(c); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forYZ(*this,y,z) { // Over X-direction + cimg_forX(*this,x) g[x] = (longT)img(x,y,z,0,wh); + _distance_scan(_width,g,sep,f,s,t,dt); + cimg_forX(*this,x) img(x,y,z,0,wh) = (T)dt[x]; + } + if (_height>1) { + g.assign(_height); dt.assign(_height); s.assign(_height); t.assign(_height); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 && _width*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXZ(*this,x,z) { // Over Y-direction + cimg_forY(*this,y) g[y] = (longT)img(x,y,z,0,wh); + _distance_scan(_height,g,sep,f,s,t,dt); + cimg_forY(*this,y) img(x,y,z,0,wh) = (T)dt[y]; + } + } + if (_depth>1) { + g.assign(_depth); dt.assign(_depth); s.assign(_depth); t.assign(_depth); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 && _width*_height>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXY(*this,x,y) { // Over Z-direction + cimg_forZ(*this,z) g[z] = (longT)img(x,y,z,0,wh); + _distance_scan(_depth,g,sep,f,s,t,dt); + cimg_forZ(*this,z) img(x,y,z,0,wh) = (T)dt[z]; + } + } + } + return *this; + } + + //! Compute chamfer distance to a specified value, with a custom metric. + /** + \param value Reference value. + \param metric_mask Metric mask. + \note The algorithm code has been initially proposed by A. Meijster, and modified by D. Tschumperlé. + **/ + template + CImg& distance(const T& value, const CImg& metric_mask) { + if (is_empty()) return *this; + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,0:(T)999999999; + if (!is_value) return fill(cimg::type::max()); + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg img = get_shared_channel(c); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1024)) + cimg_forXYZ(metric_mask,dx,dy,dz) { + const t weight = metric_mask(dx,dy,dz); + if (weight) { + for (int z = dz, nz = 0; z=0; --z,--nz) { // Backward scan + for (int y = height() - 1 - dy, ny = height() - 1; y>=0; --y,--ny) { + for (int x = width() - 1 - dx, nx = width() - 1; x>=0; --x,--nx) { + const T dd = img(nx,ny,nz,0,wh) + weight; + if (dd + CImg get_distance(const T& value, const CImg& metric_mask) const { + return CImg(*this,false).distance(value,metric_mask); + } + + //! Compute distance to a specified value, according to a custom metric (use dijkstra algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + \param is_high_connectivity Tells if the algorithm uses low or high connectivity. + \param[out] return_path An image containing the nodes of the minimal path. + **/ + template + CImg& distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) { + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm) \newinstance. + template + CImg::type> + get_distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) const { + if (is_empty()) return return_path.assign(); + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_dijkstra(): image instance and metric map (%u,%u,%u,%u) " + "have incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + typedef typename cimg::superset::type td; // Type used for computing cumulative distances + CImg result(_width,_height,_depth,_spectrum), Q; + CImg is_queued(_width,_height,_depth,1); + if (return_path) return_path.assign(_width,_height,_depth,_spectrum); + + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + CImg path = return_path?return_path.get_shared_channel(c):CImg(); + unsigned int sizeQ = 0; + + // Detect initial seeds. + is_queued.fill(0); + cimg_forXYZ(img,x,y,z) if (img(x,y,z)==value) { + Q._priority_queue_insert(is_queued,sizeQ,0,x,y,z); + res(x,y,z) = 0; + if (path) path(x,y,z) = (to)0; + } + + // Start distance propagation. + while (sizeQ) { + + // Get and remove point with minimal potential from the queue. + const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3); + const td P = (td)-Q(0,0); + Q._priority_queue_remove(sizeQ); + + // Update neighbors. + td npot = 0; + if (x - 1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x - 1,y,z) + P),x - 1,y,z)) { + res(x - 1,y,z) = npot; if (path) path(x - 1,y,z) = (to)2; + } + if (x + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y - 1,z) + P),x,y - 1,z)) { + res(x,y - 1,z) = npot; if (path) path(x,y - 1,z) = (to)8; + } + if (y + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y,z - 1) + P),x,y,z - 1)) { + res(x,y,z - 1) = npot; if (path) path(x,y,z - 1) = (to)32; + } + if (z + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y - 1,z) + P)),x - 1,y - 1,z)) { + res(x - 1,y - 1,z) = npot; if (path) path(x - 1,y - 1,z) = (to)10; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x + 1,y - 1,z) + P)),x + 1,y - 1,z)) { + res(x + 1,y - 1,z) = npot; if (path) path(x + 1,y - 1,z) = (to)9; + } + if (x - 1>=0 && y + 1=0) { // Diagonal neighbors on slice z - 1 + if (x - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z - 1) + P)),x - 1,y,z - 1)) { + res(x - 1,y,z - 1) = npot; if (path) path(x - 1,y,z - 1) = (to)34; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z - 1) + P)),x,y - 1,z - 1)) { + res(x,y - 1,z - 1) = npot; if (path) path(x,y - 1,z - 1) = (to)40; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z - 1) + P)), + x - 1,y - 1,z - 1)) { + res(x - 1,y - 1,z - 1) = npot; if (path) path(x - 1,y - 1,z - 1) = (to)42; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z - 1) + P)), + x + 1,y - 1,z - 1)) { + res(x + 1,y - 1,z - 1) = npot; if (path) path(x + 1,y - 1,z - 1) = (to)41; + } + if (x - 1>=0 && y + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z + 1) + P)),x - 1,y,z + 1)) { + res(x - 1,y,z + 1) = npot; if (path) path(x - 1,y,z + 1) = (to)18; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z + 1) + P)),x,y - 1,z + 1)) { + res(x,y - 1,z + 1) = npot; if (path) path(x,y - 1,z + 1) = (to)24; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z + 1) + P)), + x - 1,y - 1,z + 1)) { + res(x - 1,y - 1,z + 1) = npot; if (path) path(x - 1,y - 1,z + 1) = (to)26; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z + 1) + P)), + x + 1,y - 1,z + 1)) { + res(x + 1,y - 1,z + 1) = npot; if (path) path(x + 1,y - 1,z + 1) = (to)25; + } + if (x - 1>=0 && y + 1 + CImg& distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) { + return get_distance_dijkstra(value,metric,is_high_connectivity).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm). \newinstance. + template + CImg get_distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) const { + CImg return_path; + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + **/ + template + CImg& distance_eikonal(const T& value, const CImg& metric) { + return get_distance_eikonal(value,metric).move_to(*this); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + template + CImg get_distance_eikonal(const T& value, const CImg& metric) const { + if (is_empty()) return *this; + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have " + "incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + CImg result(_width,_height,_depth,_spectrum,cimg::type::max()), Q; + CImg state(_width,_height,_depth); // -1=far away, 0=narrow, 1=frozen + + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2) firstprivate(Q,state)) + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + unsigned int sizeQ = 0; + state.fill(-1); + + // Detect initial seeds. + Tfloat *ptr1 = res._data; char *ptr2 = state._data; + cimg_for(img,ptr0,T) { if (*ptr0==value) { *ptr1 = 0; *ptr2 = 1; } ++ptr1; ++ptr2; } + + // Initialize seeds neighbors. + ptr2 = state._data; + cimg_forXYZ(img,x,y,z) if (*(ptr2++)==1) { + if (x - 1>=0 && state(x - 1,y,z)==-1) { + const Tfloat dist = res(x - 1,y,z) = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x - 1,y,z); + } + if (x + 1=0 && state(x,y - 1,z)==-1) { + const Tfloat dist = res(x,y - 1,z) = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y - 1,z); + } + if (y + 1=0 && state(x,y,z - 1)==-1) { + const Tfloat dist = res(x,y,z - 1) = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z - 1); + } + if (z + 1=0) { + if (x - 1>=0 && state(x - 1,y,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + if (dist=0 && state(x,y - 1,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + if (dist=0 && state(x,y,z - 1)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + if (dist& res, const Tfloat P, + const int x=0, const int y=0, const int z=0) const { + const Tfloat M = (Tfloat)cimg::type::max(); + T T1 = (T)std::min(x - 1>=0?res(x - 1,y,z):M,x + 11) { // 3D + T + T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1=0?res(x,y,z - 1):M,z + 1T2) cimg::swap(T1,T2); + if (T2>T3) cimg::swap(T2,T3); + if (T1>T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T31) { // 2D + T T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T2 + void _eik_priority_queue_insert(CImg& state, unsigned int& siz, const t value, + const unsigned int x, const unsigned int y, const unsigned int z) { + if (state(x,y,z)>0) return; + state(x,y,z) = 0; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(t)(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3)); + } + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE. + /** + \param nb_iterations Number of PDE iterations. + \param band_size Size of the narrow band. + \param time_step Time step of the PDE iterations. + **/ + CImg& distance_eikonal(const unsigned int nb_iterations, const float band_size=0, const float time_step=0.5f) { + if (is_empty()) return *this; + CImg velocity(*this,false); + for (unsigned int iteration = 0; iteration1) { // 3D + CImg_3x3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) if (band_size<=0 || cimg::abs(Iccc)0?(Incc - Iccc):(Iccc - Ipcc), + iy = gy*sgn>0?(Icnc - Iccc):(Iccc - Icpc), + iz = gz*sgn>0?(Iccn - Iccc):(Iccc - Iccp), + ng = 1e-5f + cimg::hypot(gx,gy,gz), + ngx = gx/ng, + ngy = gy/ng, + ngz = gz/ng, + veloc = sgn*(ngx*ix + ngy*iy + ngz*iz - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } else { // 2D version + CImg_3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,Tfloat) if (band_size<=0 || cimg::abs(Icc)0?(Inc - Icc):(Icc - Ipc), + iy = gy*sgn>0?(Icn - Icc):(Icc - Icp), + ng = std::max((Tfloat)1e-5,cimg::hypot(gx,gy)), + ngx = gx/ng, + ngy = gy/ng, + veloc = sgn*(ngx*ix + ngy*iy - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } + if (veloc_max>0) *this+=(velocity*=time_step/veloc_max); + } + return *this; + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE \newinstance. + CImg get_distance_eikonal(const unsigned int nb_iterations, const float band_size=0, + const float time_step=0.5f) const { + return CImg(*this,false).distance_eikonal(nb_iterations,band_size,time_step); + } + + //! Compute Haar multiscale wavelet transform. + /** + \param axis Axis considered for the transform. + \param invert Set inverse of direct transform. + \param nb_scales Number of scales used for the transform. + **/ + CImg& haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(axis,invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const { + if (is_empty() || !nb_scales) return +*this; + CImg res; + const Tfloat sqrt2 = std::sqrt(2.f); + if (nb_scales==1) { + switch (cimg::lowercase(axis)) { // Single scale transform + case 'x' : { + const unsigned int w = _width/2; + if (w) { + if ((w%2) && w!=1) + throw CImgInstanceException(_cimg_instance + "haar(): Sub-image width %u is not even.", + cimg_instance, + w); + + res.assign(_width,_height,_depth,_spectrum); + if (invert) cimg_forYZC(*this,y,z,c) { // Inverse transform along X + for (unsigned int x = 0, xw = w, x2 = 0; x& haar(const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const bool invert=false, const unsigned int nb_scales=1) const { + CImg res; + if (nb_scales==1) { // Single scale transform + if (_width>1) get_haar('x',invert,1).move_to(res); + if (_height>1) { if (res) res.haar('y',invert,1); else get_haar('y',invert,1).move_to(res); } + if (_depth>1) { if (res) res.haar('z',invert,1); else get_haar('z',invert,1).move_to(res); } + if (res) return res; + } else { // Multi-scale transform + if (invert) { // Inverse transform + res.assign(*this,false); + if (_width>1) { + if (_height>1) { + if (_depth>1) { + unsigned int w = _width, h = _height, d = _depth; + for (unsigned int s = 1; w && h && d && s1) { + unsigned int w = _width, d = _depth; + for (unsigned int s = 1; w && d && s1) { + if (_depth>1) { + unsigned int h = _height, d = _depth; + for (unsigned int s = 1; h && d && s1) { + unsigned int d = _depth; + for (unsigned int s = 1; d && s1) { + if (_height>1) { + if (_depth>1) + for (unsigned int s = 1, w = _width/2, h = _height/2, d = _depth/2; w && h && d && s1) for (unsigned int s = 1, w = _width/2, d = _depth/2; w && d && s1) { + if (_depth>1) + for (unsigned int s = 1, h = _height/2, d = _depth/2; h && d && s1) for (unsigned int s = 1, d = _depth/2; d && s get_FFT(const char axis, const bool is_inverse=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],axis,is_inverse); + return res; + } + + //! Compute n-D Fast Fourier Transform. + /* + \param is_inverse Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + CImgList get_FFT(const bool is_inverse=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],is_inverse); + return res; + } + + //! Compute 1D Fast Fourier Transform, along a specified axis. + /** + \param[in,out] real Real part of the pixel values. + \param[in,out] imag Imaginary part of the pixel values. + \param axis Axis along which the FFT is computed. + \param is_inverse Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + static void FFT(CImg& real, CImg& imag, const char axis, const bool is_inverse=false, + const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part is empty.", + pixel_type()); + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + const char _axis = cimg::lowercase(axis); + if (_axis!='x' && _axis!='y' && _axis!='z') + throw CImgArgumentException("CImgList<%s>::FFT(): Invalid specified axis '%c' for real and imaginary parts " + "(%u,%u,%u,%u) " + "(should be { x | y | z }).", + pixel_type(),axis, + real._width,real._height,real._depth,real._spectrum); + cimg::unused(nb_threads); +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus()); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) + throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u) along the X-axis.", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width*real._height*real._depth), + real._width,real._height,real._depth,real._spectrum); + double *const ptrf = (double*)data_in; + fftw_plan data_plan = + _axis=='x'?fftw_plan_many_dft(1,(int*)&real._width,real.height()*real.depth(), + data_in,0,1,real.width(), + data_in,0,1,real.width(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + _axis=='y'?fftw_plan_many_dft(1,(int*)&real._height,real.width()*real.depth(), + data_in,0,1,real.height(), + data_in,0,1,real.height(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + fftw_plan_many_dft(1,(int*)&real._depth,real.width()*real.height(), + data_in,0,1,real.depth(), + data_in,0,1,real.depth(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + CImg realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c); + switch (_axis) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(x + (ulongT)y*realc._width + (ulongT)z*realc._width*realc._height); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + break; + case 'y' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(y + (ulongT)x*realc._height + (ulongT)z*realc._width*realc._height); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + break; + default : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(z + (ulongT)x*realc._depth + (ulongT)y*realc._width*realc._depth); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + } + + fftw_execute(data_plan); + + const double a = is_inverse?1.0/(_axis=='x'?real.width():_axis=='y'?real.height():real.depth()):1.0; + switch (_axis) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(x + (ulongT)y*realc._width + (ulongT)z*realc._width*realc._height), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + break; + case 'y' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(y + (ulongT)x*realc._height + (ulongT)z*realc._width*realc._height), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + break; + default : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(z + (ulongT)x*realc._depth + (ulongT)y*realc._width*realc._depth), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + } + } + + fftw_destroy_plan(data_plan); + fftw_free(data_in); +#ifndef cimg_use_fftw3_singlethread + fftw_cleanup_threads(); +#endif + cimg::mutex(12,0); +#else + switch (_axis) { + case 'x' : { // Fourier along X, using built-in functions + const unsigned int N = real._width, N2 = N>>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the X-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forYZC(real,y,z,c) { + cimg::swap(real(i,y,z,c),real(j,y,z,c)); + cimg::swap(imag(i,y,z,c),imag(j,y,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = delta>>1; + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Y-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXZC(real,x,z,c) { + cimg::swap(real(x,i,z,c),real(x,j,z,c)); + cimg::swap(imag(x,i,z,c),imag(x,j,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Z-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXYC(real,x,y,c) { + cimg::swap(real(x,y,i,c),real(x,y,j,c)); + cimg::swap(imag(x,y,i,c),imag(x,y,j,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i& real, CImg& imag, const bool is_inverse=false, + const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImgList<%s>::FFT(): Empty specified real part.", + pixel_type()); + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + cimg::unused(nb_threads); +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus()); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) + throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u).", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width* + real._height*real._depth*real._spectrum), + real._width,real._height,real._depth,real._spectrum); + double *const ptrf = (double*)data_in; + fftw_plan data_plan = + real._depth>1?fftw_plan_dft_3d(real._depth,real._height,real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + real._height>1?fftw_plan_dft_2d(real._height,real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + fftw_plan_dft_1d(real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + CImg realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; ptrf[i2] = (double)realc[i]; ptrf[i2 + 1] = (double)imagc[i]; } + fftw_execute(data_plan); + if (is_inverse) { + const double a = 1.0/(real.width()*real.height()*real.depth()); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)(a*ptrf[i2]); imagc[i] = (T)(a*ptrf[i2 + 1]); } + } else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)ptrf[i2]; imagc[i] = (T)ptrf[i2 + 1]; } + } + fftw_destroy_plan(data_plan); + fftw_free(data_in); +#ifndef cimg_use_fftw3_singlethread + fftw_cleanup_threads(); +#endif + cimg::mutex(12,0); +#else + if (real._depth>1) FFT(real,imag,'z',is_inverse); + if (real._height>1) FFT(real,imag,'y',is_inverse); + if (real._width>1) FFT(real,imag,'x',is_inverse); +#endif + } + + //@} + //------------------------------------- + // + //! \name 3D Objects Management + //@{ + //------------------------------------- + + //! Rotate 3D object's vertices. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or second quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + CImg& rotate_object3d(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + return get_rotate_object3d(x,y,z,w,is_quaternion).move_to(*this); + } + + CImg get_rotate_object3d(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) const { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "rotate_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + return CImg::rotation_matrix(x,y,z,w,is_quaternion)**this; + } + + //! Shift 3D object's vertices. + /** + \param tx X-coordinate of the 3D displacement vector. + \param ty Y-coordinate of the 3D displacement vector. + \param tz Z-coordinate of the 3D displacement vector. + **/ + CImg& shift_object3d(const float tx, const float ty=0, const float tz=0) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + get_shared_row(0)+=tx; get_shared_row(1)+=ty; get_shared_row(2)+=tz; + return *this; + } + + //! Shift 3D object's vertices \newinstance. + CImg get_shift_object3d(const float tx, const float ty=0, const float tz=0) const { + return CImg(*this,false).shift_object3d(tx,ty,tz); + } + + //! Shift 3D object's vertices, so that it becomes centered. + /** + \note The object center is computed as its barycenter. + **/ + CImg& shift_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + xcoords-=(xm + xM)/2; ycoords-=(ym + yM)/2; zcoords-=(zm + zM)/2; + return *this; + } + + //! Shift 3D object's vertices, so that it becomes centered \newinstance. + CImg get_shift_object3d() const { + return CImg(*this,false).shift_object3d(); + } + + //! Resize 3D object. + /** + \param sx Width of the 3D object's bounding box. + \param sy Height of the 3D object's bounding box. + \param sz Depth of the 3D object's bounding box. + **/ + CImg& resize_object3d(const float sx, const float sy=-100, const float sz=-100) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + if (xm0) xcoords*=sx/(xM-xm); else xcoords*=-sx/100; } + if (ym0) ycoords*=sy/(yM-ym); else ycoords*=-sy/100; } + if (zm0) zcoords*=sz/(zM-zm); else zcoords*=-sz/100; } + return *this; + } + + //! Resize 3D object \newinstance. + CImg get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const { + return CImg(*this,false).resize_object3d(sx,sy,sz); + } + + //! Resize 3D object to unit size. + CImg resize_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + const float dx = xM - xm, dy = yM - ym, dz = zM - zm, dmax = cimg::max(dx,dy,dz); + if (dmax>0) { xcoords/=dmax; ycoords/=dmax; zcoords/=dmax; } + return *this; + } + + //! Resize 3D object to unit size \newinstance. + CImg get_resize_object3d() const { + return CImg(*this,false).resize_object3d(); + } + + //! Merge two 3D objects together. + /** + \param[in,out] primitives Primitives data of the current 3D object. + \param obj_vertices Vertices data of the additional 3D object. + \param obj_primitives Primitives data of the additional 3D object. + **/ + template + CImg& append_object3d(CImgList& primitives, const CImg& obj_vertices, + const CImgList& obj_primitives) { + if (!obj_vertices || !obj_primitives) return *this; + if (obj_vertices._height!=3 || obj_vertices._depth>1 || obj_vertices._spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Specified vertice image (%u,%u,%u,%u,%p) is not a " + "set of 3D vertices.", + cimg_instance, + obj_vertices._width,obj_vertices._height, + obj_vertices._depth,obj_vertices._spectrum,obj_vertices._data); + + if (is_empty()) { primitives.assign(obj_primitives); return assign(obj_vertices); } + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + const unsigned int P = _width; + append(obj_vertices,'x'); + const unsigned int N = primitives._width; + primitives.insert(obj_primitives); + for (unsigned int i = N; i &p = primitives[i]; + switch (p.size()) { + case 1 : p[0]+=P; break; // Point + case 5 : p[0]+=P; p[1]+=P; break; // Sphere + case 2 : case 6 : p[0]+=P; p[1]+=P; break; // Segment + case 3 : case 9 : p[0]+=P; p[1]+=P; p[2]+=P; break; // Triangle + case 4 : case 12 : p[0]+=P; p[1]+=P; p[2]+=P; p[3]+=P; break; // Rectangle + } + } + return *this; + } + + //! Texturize primitives of a 3D object. + /** + \param[in,out] primitives Primitives data of the 3D object. + \param[in,out] colors Colors data of the 3D object. + \param texture Texture image to map to 3D object. + \param coords Texture-mapping coordinates. + **/ + template + const CImg& texturize_object3d(CImgList& primitives, CImgList& colors, + const CImg& texture, const CImg& coords=CImg::const_empty()) const { + if (is_empty()) return *this; + if (_height!=3) + throw CImgInstanceException(_cimg_instance + "texturize_object3d(): image instance is not a set of 3D points.", + cimg_instance); + if (coords && (coords._width!=_width || coords._height!=2)) + throw CImgArgumentException(_cimg_instance + "texturize_object3d(): Invalid specified texture coordinates (%u,%u,%u,%u,%p).", + cimg_instance, + coords._width,coords._height,coords._depth,coords._spectrum,coords._data); + CImg _coords; + if (!coords) { // If no texture coordinates specified, do a default XY-projection + _coords.assign(_width,2); + float + xmin, xmax = (float)get_shared_row(0).max_min(xmin), + ymin, ymax = (float)get_shared_row(1).max_min(ymin), + dx = xmax>xmin?xmax-xmin:1, + dy = ymax>ymin?ymax-ymin:1; + cimg_forX(*this,p) { + _coords(p,0) = (int)(((*this)(p,0) - xmin)*texture._width/dx); + _coords(p,1) = (int)(((*this)(p,1) - ymin)*texture._height/dy); + } + } else _coords = coords; + + int texture_ind = -1; + cimglist_for(primitives,l) { + CImg &p = primitives[l]; + const unsigned int siz = p.size(); + switch (siz) { + case 1 : { // Point + const unsigned int i0 = (unsigned int)p[0]; + const int x0 = _coords(i0,0), y0 = _coords(i0,1); + texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).move_to(colors[l]); + } break; + case 2 : case 6 : { // Line + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,x0,y0,x1,y1).move_to(p); + } break; + case 3 : case 9 : { // Triangle + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,x0,y0,x1,y1,x2,y2).move_to(p); + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2], i3 = (unsigned int)p[3]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1), + x3 = _coords(i3,0), y3 = _coords(i3,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,i3,x0,y0,x1,y1,x2,y2,x3,y3).move_to(p); + } break; + } + } + return *this; + } + + //! Generate a 3D elevation of the image instance. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param[out] colors The returned list of the 3D object colors. + \param elevation The input elevation map. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + CImgList colors3d; + const CImg points3d = img.get_elevation3d(faces3d,colors3d,img.get_norm()*0.2); + CImg().display_object3d("Elevation3d",points3d,faces3d,colors3d); + \endcode + \image html ref_elevation3d.jpg + **/ + template + CImg get_elevation3d(CImgList& primitives, CImgList& colors, const CImg& elevation) const { + if (!is_sameXY(elevation) || elevation._depth>1 || elevation._spectrum>1) + throw CImgArgumentException(_cimg_instance + "get_elevation3d(): Instance and specified elevation (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + elevation._width,elevation._height,elevation._depth, + elevation._spectrum,elevation._data); + if (is_empty()) return *this; + float m, M = (float)max_min(m); + if (M==m) ++M; + colors.assign(); + const unsigned int size_x1 = _width - 1, size_y1 = _height - 1; + for (unsigned int y = 0; y1?((*this)(x,y,1) - m)*255/(M-m):r), + b = (unsigned char)(_spectrum>2?((*this)(x,y,2) - m)*255/(M-m):_spectrum>1?0:r); + CImg::vector((tc)r,(tc)g,(tc)b).move_to(colors); + } + const typename CImg::_functor2d_int func(elevation); + return elevation3d(primitives,func,0,0,_width - 1.f,_height - 1.f,_width,_height); + } + + //! Generate the 3D projection planes of the image instance. + /** + \param[out] primitives Primitives data of the returned 3D object. + \param[out] colors Colors data of the returned 3D object. + \param x0 X-coordinate of the projection point. + \param y0 Y-coordinate of the projection point. + \param z0 Z-coordinate of the projection point. + \param normalize_colors Tells if the created textures have normalized colors. + **/ + template + CImg get_projections3d(CImgList& primitives, CImgList& colors, + const unsigned int x0, const unsigned int y0, const unsigned int z0, + const bool normalize_colors=false) const { + float m = 0, M = 0, delta = 1; + if (normalize_colors) { m = (float)min_max(M); delta = 255/(m==M?1:M-m); } + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + CImg img_xy, img_xz, img_yz; + if (normalize_colors) { + ((get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1)-=m)*=delta).move_to(img_xy); + ((get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_width,_depth,1,-100,-1). + move_to(img_xz); + ((get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_height,_depth,1,-100,-1). + move_to(img_yz); + } else { + get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1).move_to(img_xy); + get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1).move_to(img_xz); + get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).resize(_height,_depth,1,-100,-1).move_to(img_yz); + } + CImg points(12,3,1,1, + 0,_width - 1,_width - 1,0, 0,_width - 1,_width - 1,0, _x0,_x0,_x0,_x0, + 0,0,_height - 1,_height - 1, _y0,_y0,_y0,_y0, 0,_height - 1,_height - 1,0, + _z0,_z0,_z0,_z0, 0,0,_depth - 1,_depth - 1, 0,0,_depth - 1,_depth - 1); + primitives.assign(); + CImg::vector(0,1,2,3,0,0,img_xy._width - 1,0,img_xy._width - 1,img_xy._height - 1,0,img_xy._height - 1). + move_to(primitives); + CImg::vector(4,5,6,7,0,0,img_xz._width - 1,0,img_xz._width - 1,img_xz._height - 1,0,img_xz._height - 1). + move_to(primitives); + CImg::vector(8,9,10,11,0,0,img_yz._width - 1,0,img_yz._width - 1,img_yz._height - 1,0,img_yz._height - 1). + move_to(primitives); + colors.assign(); + img_xy.move_to(colors); + img_xz.move_to(colors); + img_yz.move_to(colors); + return points; + } + + //! Generate a isoline of the image instance as a 3D object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3D object colors. + \param size_x The number of subdivisions along the X-axis. + \param size_y The number of subdisivions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + const CImg points3d = img.get_isoline3d(faces3d,100); + CImg().display_object3d("Isoline3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isoline3d.jpg + **/ + template + CImg get_isoline3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a scalar image.", + cimg_instance); + if (_depth>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a 2D image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100) || (size_x==width() && size_y==height())) { + const _functor2d_int func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.f,height() - 1.f,width(),height()); + } else { + const _functor2d_float func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.f,height() - 1.f,size_x,size_y); + } + return vertices; + } + + //! Compute isolines of a function, as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Elevation functor. Must have operator()(x,y) defined. + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static CImg isoline3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + CImgList vertices; + primitives.assign(); + typename CImg::_functor_isoline3d add_vertex(vertices); + typename CImg::_functor_isoline3d add_segment(primitives); + isoline3d(add_vertex,add_segment,func,isovalue,x0,y0,x1,y1,size_x,size_y); + return vertices>'x'; + } + + //! Compute isolines of a function, as a 3D object. + /** + \param[out] add_vertex : Functor with operator()(x,y,z) defined for adding new vertex. + \param[out] add_segment : Functor with operator()(i,j) defined for adding new segment. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static void isoline3d(tv& add_vertex, tf& add_segment, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x, const int size_y) { + static const unsigned int edges[16] = { 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc, + 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 }; + static const int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 }, + { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 }, + { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 }, + { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } }; + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nxm1 = nx - 1, + nym1 = ny - 1; + + if (!nxm1 || !nym1) return; + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1; + CImg indices1(nx,1,1,2,-1), indices2(nx,1,1,2); + CImg values1(nx), values2(nx); + float X = x0, Y = y0, nX = X + dx, nY = Y + dy; + int nb_vertices = 0; + + // Fill first line with values + cimg_forX(values1,x) { values1(x) = (float)func(X,Y); X+=dx; } + + // Run the marching squares algorithm + for (unsigned int yi = 0, nyi = 1; yi + static CImg isoline3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return isoline3d(primitives,func,isovalue,x0,y0,x1,y1,size_x,size_y); + } + + template + static int _isoline3d_index(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int nx) { + switch (edge) { + case 0 : return (int)indices1(x,0); + case 1 : return (int)indices1(nx,1); + case 2 : return (int)indices2(x,0); + case 3 : return (int)indices1(x,1); + } + return 0; + } + + //! Generate an isosurface of the image instance as a 3D object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3D object colors. + \param size_x Number of subdivisions along the X-axis. + \param size_y Number of subdisivions along the Y-axis. + \param size_z Number of subdisivions along the Z-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img = CImg("reference.jpg").resize(-100,-100,20); + CImgList faces3d; + const CImg points3d = img.get_isosurface3d(faces3d,100); + CImg().display_object3d("Isosurface3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isosurface3d.jpg + **/ + template + CImg get_isosurface3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100, const int size_z=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isosurface3d(): Instance is not a scalar image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100 && size_z==-100) || (size_x==width() && size_y==height() && size_z==depth())) { + const _functor3d_int func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f, + width(),height(),depth()); + } else { + const _functor3d_float func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f, + size_x,size_y,size_z); + } + return vertices; + } + + //! Compute isosurface of a function, as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static CImg isosurface3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x=32, const int size_y=32, const int size_z=32) { + CImgList vertices; + primitives.assign(); + typename CImg::_functor_isosurface3d add_vertex(vertices); + typename CImg::_functor_isosurface3d add_triangle(primitives); + isosurface3d(add_vertex,add_triangle,func,isovalue,x0,y0,z0,x1,y1,z1,size_x,size_y,size_z); + return vertices>'x'; + } + + //! Compute isosurface of a function, as a 3D object. + /** + \param[out] add_vertex : Functor with operator()(x,y,z) defined for adding new vertex. + \param[out] add_triangle : Functor with operator()(i,j) defined for adding new segment. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static void isosurface3d(tv& add_vertex, tf& add_triangle, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x, const int size_y, const int size_z) { + static const unsigned int edges[256] = { + 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, + 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, + 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, + 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, + 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, + 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, + 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, + 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, + 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, + 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, + 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, + 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, + 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, + 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 + }; + + static const int triangles[256][16] = { + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, + { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, + { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, + { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, + { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, + { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, + { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, + { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, + { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, + { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, + { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, + { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, + { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, + { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, + { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, + { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, + { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, + { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, + { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, + { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, + { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, + { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, + { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, + { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, + { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, + { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, + { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, + { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, + { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, + { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, + { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, + { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, + { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, + { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, + { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, + { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, + { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, + { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, + { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, + { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, + { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, + { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, + { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, + { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, + { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, + { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, + { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, + { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, + { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, + { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, + { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, + { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, + { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, + { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, + { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, + { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, + { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, + { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, + { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, + { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, + { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, + { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, + { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, + { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, + { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, + { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, + { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, + { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, + { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, + { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, + { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, + { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, + { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, + { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, + { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, + { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, + { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, + { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, + { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, + { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, + { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, + { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, + { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, + { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, + { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, + { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, + { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, + { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, + { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, + { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, + { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, + { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, + { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } + }; + + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + _nz = (unsigned int)(size_z>=0?size_z:cimg::round((z1-z0)*-size_z/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nz = _nz?_nz:1, + nxm1 = nx - 1, + nym1 = ny - 1, + nzm1 = nz - 1; + if (!nxm1 || !nym1 || !nzm1) return; + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1, dz = (z1 - z0)/nzm1; + CImg indices1(nx,ny,1,3,-1), indices2(indices1); + CImg values1(nx,ny), values2(nx,ny); + float X = 0, Y = 0, Z = 0, nX = 0, nY = 0, nZ = 0; + int nb_vertices = 0; + + // Fill the first plane with function values + Y = y0; + cimg_forY(values1,y) { + X = x0; + cimg_forX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=dx; } + Y+=dy; + } + + // Run Marching Cubes algorithm + Z = z0; nZ = Z + dz; + for (unsigned int zi = 0; zi + static CImg isosurface3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int dx=32, const int dy=32, const int dz=32) { + const _functor3d_expr func(expression); + return isosurface3d(primitives,func,isovalue,x0,y0,z0,x1,y1,z1,dx,dy,dz); + } + + template + static int _isosurface3d_index(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int y, + const unsigned int nx, const unsigned int ny) { + switch (edge) { + case 0 : return indices1(x,y,0); + case 1 : return indices1(nx,y,1); + case 2 : return indices1(x,ny,0); + case 3 : return indices1(x,y,1); + case 4 : return indices2(x,y,0); + case 5 : return indices2(nx,y,1); + case 6 : return indices2(x,ny,0); + case 7 : return indices2(x,y,1); + case 8 : return indices1(x,y,2); + case 9 : return indices1(nx,y,2); + case 10 : return indices1(nx,ny,2); + case 11 : return indices1(x,ny,2); + } + return 0; + } + + // Define functors for accessing image values (used in previous functions). + struct _functor2d_int { + const CImg& ref; + _functor2d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref((int)x,(int)y); + } + }; + + struct _functor2d_float { + const CImg& ref; + _functor2d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref._linear_atXY(x,y); + } + }; + + struct _functor2d_expr { + _cimg_math_parser *mp; + ~_functor2d_expr() { mp->end(); delete mp; } + _functor2d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y) const { + return (float)(*mp)(x,y,0,0); + } + }; + + struct _functor3d_int { + const CImg& ref; + _functor3d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref((int)x,(int)y,(int)z); + } + }; + + struct _functor3d_float { + const CImg& ref; + _functor3d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref._linear_atXYZ(x,y,z); + } + }; + + struct _functor3d_expr { + _cimg_math_parser *mp; + ~_functor3d_expr() { mp->end(); delete mp; } + _functor3d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z) const { + return (float)(*mp)(x,y,z,0); + } + }; + + struct _functor4d_int { + const CImg& ref; + _functor4d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref((int)x,(int)y,(int)z,c); + } + }; + + struct _functor_isoline3d { + CImgList& list; + _functor_isoline3d(CImgList& _list):list(_list) {} + template + void operator()(const t x, const t y, const t z) { CImg::vector((T)x,(T)y,(T)z).move_to(list); } + template + void operator()(const t i, const t j) { CImg::vector((T)i,(T)j).move_to(list); } + }; + + struct _functor_isosurface3d { + CImgList& list; + _functor_isosurface3d(CImgList& _list):list(_list) {} + template + void operator()(const t x, const t y, const t z) { CImg::vector((T)x,(T)y,(T)z).move_to(list); } + }; + + //! Compute 3D elevation of a function as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + **/ + template + static CImg elevation3d(CImgList& primitives, const tfunc& func, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const float + nx0 = x0=0?size_x:(nx1-nx0)*-size_x/100), + nsize_x = _nsize_x?_nsize_x:1, nsize_x1 = nsize_x - 1, + _nsize_y = (unsigned int)(size_y>=0?size_y:(ny1-ny0)*-size_y/100), + nsize_y = _nsize_y?_nsize_y:1, nsize_y1 = nsize_y - 1; + if (nsize_x<2 || nsize_y<2) + throw CImgArgumentException("CImg<%s>::elevation3d(): Invalid specified size (%d,%d).", + pixel_type(), + nsize_x,nsize_y); + + CImg vertices(nsize_x*nsize_y,3); + floatT *ptr_x = vertices.data(0,0), *ptr_y = vertices.data(0,1), *ptr_z = vertices.data(0,2); + for (unsigned int y = 0; y + static CImg elevation3d(CImgList& primitives, const char *const expression, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return elevation3d(primitives,func,x0,y0,x1,y1,size_x,size_y); + } + + //! Generate a 3D box object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the box (dimension along the X-axis). + \param size_y The height of the box (dimension along the Y-axis). + \param size_z The depth of the box (dimension along the Z-axis). + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::box3d(faces3d,10,20,30); + CImg().display_object3d("Box3d",points3d,faces3d); + \endcode + \image html ref_box3d.jpg + **/ + template + static CImg box3d(CImgList& primitives, + const float size_x=200, const float size_y=100, const float size_z=100) { + primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 0,1,5,4, 3,7,6,2, 0,4,7,3, 1,2,6,5); + return CImg(8,3,1,1, + 0.,size_x,size_x, 0., 0.,size_x,size_x, 0., + 0., 0.,size_y,size_y, 0., 0.,size_y,size_y, + 0., 0., 0., 0.,size_z,size_z,size_z,size_z); + } + + //! Generate a 3D cone. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cone basis. + \param size_z The cone's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cone3d(faces3d,50); + CImg().display_object3d("Cone3d",points3d,faces3d); + \endcode + \image html ref_cone3d.jpg + **/ + template + static CImg cone3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,size_z, + 0.,0.,0.); + for (float delta = 360.f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0).move_to(vertices); + } + const unsigned int nbr = vertices._width - 2; + for (unsigned int p = 0; p::vector(1,next,curr).move_to(primitives); + CImg::vector(0,curr,next).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D cylinder. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cylinder basis. + \param size_z The cylinder's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cylinder3d(faces3d,50); + CImg().display_object3d("Cylinder3d",points3d,faces3d); + \endcode + \image html ref_cylinder3d.jpg + **/ + template + static CImg cylinder3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,0., + 0.,0.,size_z); + for (float delta = 360.f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0.f).move_to(vertices); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),size_z).move_to(vertices); + } + const unsigned int nbr = (vertices._width - 2)/2; + for (unsigned int p = 0; p::vector(0,next,curr).move_to(primitives); + CImg::vector(1,curr + 1,next + 1).move_to(primitives); + CImg::vector(curr,next,next + 1,curr + 1).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D torus. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius1 The large radius. + \param radius2 The small radius. + \param subdivisions1 The number of angular subdivisions for the large radius. + \param subdivisions2 The number of angular subdivisions for the small radius. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::torus3d(faces3d,20,4); + CImg().display_object3d("Torus3d",points3d,faces3d); + \endcode + \image html ref_torus3d.jpg + **/ + template + static CImg torus3d(CImgList& primitives, + const float radius1=100, const float radius2=30, + const unsigned int subdivisions1=24, const unsigned int subdivisions2=12) { + primitives.assign(); + if (!subdivisions1 || !subdivisions2) return CImg(); + CImgList vertices; + for (unsigned int v = 0; v::vector(x,y,z).move_to(vertices); + } + } + for (unsigned int vv = 0; vv::vector(svv + nu,svv + uu,snv + uu,snv + nu).move_to(primitives); + } + } + return vertices>'x'; + } + + //! Generate a 3D XY-plane. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the plane (dimension along the X-axis). + \param size_y The height of the plane (dimensions along the Y-axis). + \param subdivisions_x The number of planar subdivisions along the X-axis. + \param subdivisions_y The number of planar subdivisions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::plane3d(faces3d,100,50); + CImg().display_object3d("Plane3d",points3d,faces3d); + \endcode + \image html ref_plane3d.jpg + **/ + template + static CImg plane3d(CImgList& primitives, + const float size_x=100, const float size_y=100, + const unsigned int subdivisions_x=10, const unsigned int subdivisions_y=10) { + primitives.assign(); + if (!subdivisions_x || !subdivisions_y) return CImg(); + CImgList vertices; + const unsigned int w = subdivisions_x + 1, h = subdivisions_y + 1; + const float fx = (float)size_x/w, fy = (float)size_y/h; + for (unsigned int y = 0; y::vector(fx*x,fy*y,0).move_to(vertices); + for (unsigned int y = 0; y::vector(off1,off4,off3,off2).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D sphere. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the sphere (dimension along the X-axis). + \param subdivisions The number of recursive subdivisions from an initial icosahedron. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::sphere3d(faces3d,100,4); + CImg().display_object3d("Sphere3d",points3d,faces3d); + \endcode + \image html ref_sphere3d.jpg + **/ + template + static CImg sphere3d(CImgList& primitives, + const float radius=50, const unsigned int subdivisions=3) { + + // Create initial icosahedron + primitives.assign(); + const double tmp = (1 + std::sqrt(5.f))/2, a = 1./std::sqrt(1 + tmp*tmp), b = tmp*a; + CImgList vertices(12,1,3,1,1, b,a,0., -b,a,0., -b,-a,0., b,-a,0., a,0.,b, a,0.,-b, + -a,0.,-b, -a,0.,b, 0.,b,a, 0.,-b,a, 0.,-b,-a, 0.,b,-a); + primitives.assign(20,1,3,1,1, 4,8,7, 4,7,9, 5,6,11, 5,10,6, 0,4,3, 0,3,5, 2,7,1, 2,1,6, + 8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3, + 5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2); + // edge - length/2 + float he = (float)a; + + // Recurse subdivisions + for (unsigned int i = 0; i::vector(nx0,ny0,nz0).move_to(vertices); i0 = vertices.width() - 1; } + if (i1<0) { CImg::vector(nx1,ny1,nz1).move_to(vertices); i1 = vertices.width() - 1; } + if (i2<0) { CImg::vector(nx2,ny2,nz2).move_to(vertices); i2 = vertices.width() - 1; } + primitives.remove(0); + CImg::vector(p0,i0,i1).move_to(primitives); + CImg::vector((tf)i0,(tf)p1,(tf)i2).move_to(primitives); + CImg::vector((tf)i1,(tf)i2,(tf)p2).move_to(primitives); + CImg::vector((tf)i1,(tf)i0,(tf)i2).move_to(primitives); + } + } + return (vertices>'x')*=radius; + } + + //! Generate a 3D ellipsoid. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param tensor The tensor which gives the shape and size of the ellipsoid. + \param subdivisions The number of recursive subdivisions from an initial stretched icosahedron. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg tensor = CImg::diagonal(10,7,3), + points3d = CImg::ellipsoid3d(faces3d,tensor,4); + CImg().display_object3d("Ellipsoid3d",points3d,faces3d); + \endcode + \image html ref_ellipsoid3d.jpg + **/ + template + static CImg ellipsoid3d(CImgList& primitives, + const CImg& tensor, const unsigned int subdivisions=3) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImg S, V; + tensor.symmetric_eigen(S,V); + const float orient = + (V(0,1)*V(1,2) - V(0,2)*V(1,1))*V(2,0) + + (V(0,2)*V(1,0) - V(0,0)*V(1,2))*V(2,1) + + (V(0,0)*V(1,1) - V(0,1)*V(1,0))*V(2,2); + if (orient<0) { V(2,0) = -V(2,0); V(2,1) = -V(2,1); V(2,2) = -V(2,2); } + const float l0 = S[0], l1 = S[1], l2 = S[2]; + CImg vertices = sphere3d(primitives,1.,subdivisions); + vertices.get_shared_row(0)*=l0; + vertices.get_shared_row(1)*=l1; + vertices.get_shared_row(2)*=l2; + return V*vertices; + } + + //! Convert 3D object into a CImg3d representation. + /** + \param primitives Primitives data of the 3D object. + \param colors Colors data of the 3D object. + \param opacities Opacities data of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + **/ + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + CImg& object3dtoCImg3d(const bool full_check=true) { + return get_object3dtoCImg3d(full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \newinstance. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "object3dtoCImg3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,_width,primitives._width,error_message.data()); + CImg res(1,_size_object3dtoCImg3d(primitives,colors,opacities)); + float *ptrd = res._data; + + // Put magick number. + *(ptrd++) = 'C' + 0.5f; *(ptrd++) = 'I' + 0.5f; *(ptrd++) = 'm' + 0.5f; + *(ptrd++) = 'g' + 0.5f; *(ptrd++) = '3' + 0.5f; *(ptrd++) = 'd' + 0.5f; + + // Put number of vertices and primitives. + *(ptrd++) = cimg::uint2float(_width); + *(ptrd++) = cimg::uint2float(primitives._width); + + // Put vertex data. + if (is_empty() || !primitives) return res; + const T *ptrx = data(0,0), *ptry = data(0,1), *ptrz = data(0,2); + cimg_forX(*this,p) { + *(ptrd++) = (float)*(ptrx++); + *(ptrd++) = (float)*(ptry++); + *(ptrd++) = (float)*(ptrz++); + } + + // Put primitive data. + cimglist_for(primitives,p) { + *(ptrd++) = (float)primitives[p].size(); + const tp *ptrp = primitives[p]._data; + cimg_foroff(primitives[p],i) *(ptrd++) = cimg::uint2float((unsigned int)*(ptrp++)); + } + + // Put color/texture data. + const unsigned int csiz = std::min(colors._width,primitives._width); + for (int c = 0; c<(int)csiz; ++c) { + const CImg& color = colors[c]; + const tc *ptrc = color._data; + if (color.size()==3) { *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*ptrc; } + else { + *(ptrd++) = -128.f; + int shared_ind = -1; + if (color.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImgList& opacities, float *ptrd) const { + cimglist_for(opacities,o) { + const CImg& opacity = opacities[o]; + const to *ptro = opacity._data; + if (opacity.size()==1) *(ptrd++) = (float)*ptro; + else { + *(ptrd++) = -128.f; + int shared_ind = -1; + if (opacity.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImg& opacities, float *ptrd) const { + const to *ptro = opacities._data; + cimg_foroff(opacities,o) *(ptrd++) = (float)*(ptro++); + return ptrd; + } + + template + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImgList& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + if (colors[c].is_shared()) siz+=4; + else { const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; } + } + if (colors._width + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImg& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; + } + if (colors._width + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) const { + CImgList opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) const { + CImgList colors, opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3D object into a CImg3d representation \overloading. + CImg get_object3dtoCImg3d(const bool full_check=true) const { + CImgList opacities, colors; + CImgList primitives(width(),1,1,1,1); + cimglist_for(primitives,p) primitives(p,0) = p; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert CImg3d representation into a 3D object. + /** + \param[out] primitives Primitives data of the 3D object. + \param[out] colors Colors data of the 3D object. + \param[out] opacities Opacities data of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + **/ + template + CImg& CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) { + return get_CImg3dtoobject3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert CImg3d representation into a 3D object \newinstance. + template + CImg get_CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_CImg3d(full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "CImg3dtoobject3d(): image instance is not a CImg3d (%s).", + cimg_instance,error_message.data()); + const T *ptrs = _data + 6; + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + const CImg points = CImg(ptrs,3,nb_points,1,1,true).get_transpose(); + ptrs+=3*nb_points; + primitives.assign(nb_primitives); + cimglist_for(primitives,p) { + const unsigned int nb_inds = (unsigned int)*(ptrs++); + primitives[p].assign(1,nb_inds); + tp *ptrp = primitives[p]._data; + for (unsigned int i = 0; i::max(),(T)cimg::type::max()); \ + const float _sc_nopacity = cimg::abs((float)opacity), _sc_copacity = 1 - std::max((float)opacity,0.f); \ + const ulongT _sc_whd = (ulongT)_width*_height*_depth; \ + cimg::unused(_sc_maxval); + +#define cimg_draw_scanline(x0,x1,y,color,opacity,brightness) \ + _draw_scanline(x0,x1,y,color,opacity,brightness,_sc_nopacity,_sc_copacity,_sc_whd,_sc_maxval) + + // [internal] The following _draw_scanline() routines are *non user-friendly functions*, + // used only for internal purpose. + // Pre-requisites: x0<=x1, y-coordinate is valid, col is valid. + template + CImg& _draw_scanline(const int x0, const int x1, const int y, + const tc *const color, const float opacity, + const float brightness, + const float nopacity, const float copacity, const ulongT whd, const T _sc_maxval) { + const int nx0 = x0>0?x0:0, nx1 = x1=0) { + const tc *col = color; + const ulongT off = whd - dx - 1; + T *ptrd = data(nx0,y); + if (opacity>=1) { // ** Opaque drawing ** + if (brightness==1) { // Brightness==1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)*(col++); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)*(col++); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else if (brightness<1) { // Brightness<1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else { // Brightness>1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*_sc_maxval); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*_sc_maxval); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } + } else { // ** Transparent drawing ** + if (brightness==1) { // Brightness==1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else if (brightness<=1) { // Brightness<1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*brightness*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else { // Brightness>1 + cimg_forC(*this,c) { + const Tfloat val = ((2-brightness)**(col++) + (brightness - 1)*_sc_maxval)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } + } + } + return *this; + } + + //! Draw a 3D point. + /** + \param x0 X-coordinate of the point. + \param y0 Y-coordinate of the point. + \param z0 Z-coordinate of the point. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - To set pixel values without clipping needs, you should use the faster CImg::operator()() function. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_point(50,50,color); + \endcode + **/ + template + CImg& draw_point(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_point(): Specified color is (null).", + cimg_instance); + if (x0>=0 && y0>=0 && z0>=0 && x0=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } + } + return *this; + } + + //! Draw a 2D point \simplification. + template + CImg& draw_point(const int x0, const int y0, + const tc *const color, const float opacity=1) { + return draw_point(x0,y0,0,color,opacity); + } + + // Draw a points cloud. + /** + \param points Image of vertices coordinates. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_point(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_point(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),color,opacity); + } break; + default : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),(int)points(i,2),color,opacity); + } + } + return *this; + } + + //! Draw a 2D line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + \note + - Line routine uses Bresenham's algorithm. + - Set \p init_hatch = false to draw consecutive hatched segments without breaking the line pattern. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,color); + \endcode + **/ + template + CImg& draw_line(int x0, int y0, + int x1, int y1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !opacity || !pattern || + std::min(y0,y1)>=height() || std::max(y0,y1)<0 || + std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1); + dx01*=-1; dy01*=-1; + } + + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + const int + step = y0<=y1?1:-1,hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + T *const ptrd = is_horizontal?data(y,x):data(x,y); + cimg_forC(*this,c) { + const T val = color[c]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a 2D line, with z-buffering. + /** + \param zbuffer Zbuffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + **/ + template + CImg& draw_line(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_line(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float diz01 = iz1 - iz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1); + dx01*=-1; dy01*=-1; diz01*=-1; + } + + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float iz = iz0 + diz01*yy0/dy01; + tz *const ptrz = is_horizontal?zbuffer.data(y,x):zbuffer.data(x,y); + + if (x>=0 && x<=w1 && pattern&hatch && iz>=*ptrz) { + *ptrz = (tz)iz; + T *const ptrd = is_horizontal?data(y,x):data(x,y); + cimg_forC(*this,c) { + const T val = color[c]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + \note + - Line routine uses the well known Bresenham's algorithm. + \par Example: + \code + CImg img(100,100,1,3,0), texture("texture256x256.ppm"); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,texture,0,0,255,255); + \endcode + **/ + template + CImg& draw_line(int x0, int y0, + int x1, int y1, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + + if (is_empty() || !opacity || !pattern) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_line(x0,y0,x1,y1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + int + dtx01 = tx1 - tx0, dty01 = ty1 - ty0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1); + dx01*=-1; dy01*=-1; dtx01*=-1; dty01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy01ty = dy01*cimg::sign(dty01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01, + tx = tx0 + (dtx01*yy0 + hdy01tx)/dy01, + ty = ty0 + (dty01*yy0 + hdy01ty)/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line, with perspective correction. + /** + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(int x0, int y0, const float z0, + int x1, int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float + diz01 = iz1 - iz0, + txz0 = tx0*iz0, txz1 = tx1*iz1, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, + dtxz01 = txz1 - txz0, dtyz01 = tyz1 - tyz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1,txz0,txz1,tyz0,tyz1); + dx01*=-1; dy01*=-1; diz01*=-1; dtxz01*=-1; dtyz01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float + iz = iz0 + diz01*yy0/dy01, + txz = txz0 + dtxz01*yy0/dy01, + tyz = tyz0 + dtyz01*yy0/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line, with perspective correction and z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float + diz01 = iz1 - iz0, + txz0 = tx0*iz0, txz1 = tx1*iz1, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, + dtxz01 = txz1 - txz0, dtyz01 = tyz1 - tyz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1,txz0,txz1,tyz0,tyz1); + dx01*=-1; dy01*=-1; diz01*=-1; dtxz01*=-1; dtyz01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float + iz = iz0 + diz01*yy0/dy01, + txz = txz0 + dtxz01*yy0/dy01, + tyz = tyz0 + dtyz01*yy0/dy01; + tz *const ptrz = is_horizontal?zbuffer.data(y,x):zbuffer.data(x,y); + + if (x>=0 && x<=w1 && pattern&hatch && iz>=*ptrz) { + *ptrz = (tz)iz; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a set of consecutive lines. + /** + \param points Coordinates of vertices, stored as a list of vectors. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If set to true, init hatch motif. + \note + - This function uses several call to the single CImg::draw_line() procedure, + depending on the vectors size in \p points. + **/ + template + CImg& draw_line(const CImg& points, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + default : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + int ox = x0, oy = y0; + for (unsigned int i = 1; i + CImg& draw_arrow(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1, + const float angle=30, const float length=-10, + const unsigned int pattern=~0U) { + if (is_empty()) return *this; + const float u = (float)(x0 - x1), v = (float)(y0 - y1), sq = u*u + v*v, + deg = (float)(angle*cimg::PI/180), ang = (sq>0)?(float)std::atan2(v,u):0.f, + l = (length>=0)?length:-length*(float)std::sqrt(sq)/100; + if (sq>0) { + const float + cl = (float)std::cos(ang - deg), sl = (float)std::sin(ang - deg), + cr = (float)std::cos(ang + deg), sr = (float)std::sin(ang + deg); + const int + xl = x1 + (int)(l*cl), yl = y1 + (int)(l*sl), + xr = x1 + (int)(l*cr), yr = y1 + (int)(l*sr), + xc = x1 + (int)((l + 1)*(cl + cr))/2, yc = y1 + (int)((l + 1)*(sl + sr))/2; + draw_line(x0,y0,xc,yc,color,opacity,pattern).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity); + } else draw_point(x0,y0,color,opacity); + return *this; + } + + //! Draw a 2D spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + \note + - The curve is a 2D cubic Bezier spline, from the set of specified starting/ending points + and corresponding velocity vectors. + - The spline is drawn as a sequence of connected segments. The \p precision parameter sets the + average number of pixels in each drawn segment. + - A cubic Bezier curve is sometimes defined by a set of 4 points { (\p x0,\p y0), (\p xa,\p ya), + (\p xb,\p yb), (\p x1,\p y1) } where (\p x0,\p y0) is the starting point, (\p x1,\p y1) is the ending point + and (\p xa,\p ya), (\p xb,\p yb) are two + \e control points. + The starting and ending velocities (\p u0,\p v0) and (\p u1,\p v1) can be deduced easily from + the control points as + \p u0 = (\p xa - \p x0), \p v0 = (\p ya - \p y0), \p u1 = (\p x1 - \p xb) and \p v1 = (\p y1 - \p yb). + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,255,255 }; + img.draw_spline(30,30,0,100,90,40,0,-100,color); + \endcode + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const tc *const color, const float opacity=1, + const float precision=0.25, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Specified color is (null).", + cimg_instance); + if (x0==x1 && y0==y1) return draw_point(x0,y0,color,opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0; + for (float t = 0; t<1; t+=_precision) { + const float t2 = t*t, t3 = t2*t; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), + ny = (int)(ay*t3 + by*t2 + v0*t + y0); + draw_line(ox,oy,nx,ny,color,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; + } + return draw_line(ox,oy,x1,y1,color,opacity,pattern,false); + } + + //! Draw a textured 2D spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param texture Texture image defining line pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch if \c true, reinit hatch motif. + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const CImg& texture, + const int tx0, const int ty0, const int tx1, const int ty1, + const float opacity=1, + const float precision=4, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_empty()) return *this; + if (is_overlapped(texture)) + return draw_spline(x0,y0,u0,v0,x1,y1,u1,v1,+texture,tx0,ty0,tx1,ty1,precision,opacity,pattern,init_hatch); + if (x0==x1 && y0==y1) + return draw_point(x0,y0,texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).data(), + opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0, otx = tx0, oty = ty0; + for (float t1 = 0; t1<1; t1+=_precision) { + const float t2 = t1*t1, t3 = t2*t1; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t1 + x0), + ny = (int)(ay*t3 + by*t2 + v0*t1 + y0), + ntx = tx0 + (int)((tx1 - tx0)*t1), + nty = ty0 + (int)((ty1 - ty0)*t1); + draw_line(ox,oy,nx,ny,texture,otx,oty,ntx,nty,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; otx = ntx; oty = nty; + } + return draw_line(ox,oy,x1,y1,texture,otx,oty,tx1,ty1,opacity,pattern,false); + } + + //! Draw a set of consecutive splines. + /** + \param points Vertices data. + \param tangents Tangents data. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param is_closed_set Tells if the drawn spline set is closed. + \param precision Precision of the drawing. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + **/ + template + CImg& draw_spline(const CImg& points, const CImg& tangents, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || !tangents || points._width<2 || tangents._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + default : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1); + int ox = x0, oy = y0; + float ou = u0, ov = v0; + for (unsigned int i = 1; i + CImg& draw_spline(const CImg& points, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + CImg tangents; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + tangents.assign(points._width,points._height); + cimg_forX(points,p) { + const unsigned int + p0 = is_closed_set?(p + points.width() - 1)%points.width():(p?p - 1:0), + p1 = is_closed_set?(p + 1)%points.width():(p + 1 + CImg& _draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, const float opacity, + const float brightness) { + if (y0>y1) cimg::swap(x0,x1,y0,y1); + if (y0>y2) cimg::swap(x0,x2,y0,y2); + if (y1>y2) cimg::swap(x1,x2,y1,y2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM); + cimg_draw_scanline(xm,xM,y,color,opacity,cbs); + } + return *this; + } + + //! Draw a filled 2D triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + _draw_triangle(x0,y0,x1,y1,x2,y2,color,opacity,1); + return *this; + } + + //! Draw a outlined 2D triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + draw_line(x0,y0,x1,y1,color,opacity,pattern,true). + draw_line(x1,y1,x2,y2,color,opacity,pattern,false). + draw_line(x2,y2,x0,y0,color,opacity,pattern,false); + return *this; + } + + //! Draw a filled 2D triangle, with z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param z0 Z-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param z1 Z-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param z2 Z-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param brightness Brightness factor. + **/ + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1; + + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param bs0 Brightness factor of the first vertex (in [0,2]). + \param bs1 brightness factor of the second vertex (in [0,2]). + \param bs2 brightness factor of the third vertex (in [0,2]). + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2D triangle, with z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, + float bs0, + float bs1, + float bs2, + float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a color-interpolated 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color1 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the first vertex. + \param color2 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the second vertex. + \param color3 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc1 *const color1, + const tc2 *const color2, + const tc3 *const color3, + const float opacity=1) { + const unsigned char one = 1; + cimg_forC(*this,c) + get_shared_channel(c).draw_triangle(x0,y0,x1,y1,x2,y2,&one,color1[c],color2[c],color3[c],opacity); + return *this; + } + + //! Draw a textured 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param opacity Drawing opacity. + \param brightness Brightness factor of the drawing (in [0,2]). + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,ty1,tx2,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2; + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM; + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a 2D textured triangle, with perspective correction. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured 2D triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a Phong-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + + const ulongT lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,lxm,lxM,lym,lyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dlxmM = lxM - lxm, dlymM = lyM - lym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a Phong-shaded 2D triangle, with z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (is_overlapped(light)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + const float diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1; + + const ulongT lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,lxm,lxM,lym,lyM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dlxmM = lxM - lxm, dlymM = lyM - lym; + const float dizmM = izM - izm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const int + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const tc col = color[c]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param bs0 Brightness factor of the first vertex. + \param bs1 Brightness factor of the second vertex. + \param bs2 Brightness factor of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + bs0,bs1,bs2,opacity); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2; + const float dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym; + const float dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle, with perspective correction \overloading. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + bs0,bs1,bs2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle, with perspective correction and z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,bs0,bs1,bs2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM,lxm,lxM,lym,lyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym, + dlxmM = lxM - lxm, dlymM = lyM - lym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM, + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle, with perspective correction. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2, + lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2, + dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1, + dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float + dizmM = izM - izm, + dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, + dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + lxz = lxzm + dlxzmM*xxm/dxmM, + lyz = lyzm + dlyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz), + lx = (int)cimg::round(lxz/iz), + ly = (int)cimg::round(lyz/iz); + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + +texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2, + lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2, + dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1, + dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float + dizmM = izM - izm, + dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, + dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + lxz = lxzm + dlxzmM*xxm/dxmM, + lyz = lyzm + dlyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz), + lx = (int)cimg::round(lxz/iz), + ly = (int)cimg::round(lyz/iz); + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a filled 4D rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param z0 Z-coordinate of the upper-left rectangle corner. + \param c0 C-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param z1 Z-coordinate of the lower-right rectangle corner. + \param c1 C-coordinate of the lower-right rectangle corner. + \param val Scalar value used to fill the rectangle area. + \param opacity Drawing opacity. + **/ + CImg& draw_rectangle(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const T val, const float opacity=1) { + if (is_empty()) return *this; + const int + nx0 = x0=width()?width() - 1 - nx1:0) + (nx0<0?nx0:0), + ly = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0), + lz = (1 + nz1 - nz0) + (nz1>=depth()?depth() - 1 - nz1:0) + (nz0<0?nz0:0), + lc = (1 + nc1 - nc0) + (nc1>=spectrum()?spectrum() - 1 - nc1:0) + (nc0<0?nc0:0); + const ulongT + offX = (ulongT)_width - lx, + offY = (ulongT)_width*(_height - ly), + offZ = (ulongT)_width*_height*(_depth - lz); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + T *ptrd = data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0); + if (lx>0 && ly>0 && lz>0 && lc>0) + for (int v = 0; v=1) { + if (sizeof(T)!=1) { for (int x = 0; x + CImg& draw_rectangle(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_rectangle(): Specified color is (null).", + cimg_instance); + cimg_forC(*this,c) draw_rectangle(x0,y0,z0,c,x1,y1,z1,c,(T)color[c],opacity); + return *this; + } + + //! Draw a filled 2D rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1) { + return draw_rectangle(x0,y0,0,x1,y1,_depth - 1,color,opacity); + } + + //! Draw a outlined 2D rectangle \overloading. + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (y0==y1) return draw_line(x0,y0,x1,y0,color,opacity,pattern,true); + if (x0==x1) return draw_line(x0,y0,x0,y1,color,opacity,pattern,true); + const int + nx0 = x0 + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points.height()!=2) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set (%u,%u,%u,%u).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum); + if (points._width==1) return draw_point(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)),color,opacity); + if (points._width==2) return draw_line(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)), + cimg::uiround(points(1,0)),cimg::uiround(points(1,1)),color,opacity); + if (points._width==3) return draw_triangle(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)), + cimg::uiround(points(1,0)),cimg::uiround(points(1,1)), + cimg::uiround(points(2,0)),cimg::uiround(points(2,1)),color,opacity); + cimg_init_scanline(opacity); + int + xmin = 0, ymin = 0, + xmax = points.get_shared_row(0).max_min(xmin), + ymax = points.get_shared_row(1).max_min(ymin); + if (xmax<0 || xmin>=width() || ymax<0 || ymin>=height()) return *this; + if (ymin==ymax) return draw_line(xmin,ymin,xmax,ymax,color,opacity); + + ymin = std::max(0,ymin); + ymax = std::min(height() - 1,ymax); + CImg Xs(points._width,ymax - ymin + 1); + CImg count(Xs._height,1,1,1,0); + unsigned int n = 0, nn = 1; + bool go_on = true; + + while (go_on) { + unsigned int an = (nn + 1)%points._width; + const int + x0 = cimg::uiround(points(n,0)), + y0 = cimg::uiround(points(n,1)); + if (points(nn,1)==y0) while (points(an,1)==y0) { nn = an; (an+=1)%=points._width; } + const int + x1 = cimg::uiround(points(nn,0)), + y1 = cimg::uiround(points(nn,1)); + unsigned int tn = an; + while (points(tn,1)==y1) (tn+=1)%=points._width; + + if (y0!=y1) { + const int + y2 = cimg::uiround(points(tn,1)), + x01 = x1 - x0, y01 = y1 - y0, y12 = y2 - y1, + step = cimg::sign(y01), + tmax = std::max(1,cimg::abs(y01)), htmax = tmax*cimg::sign(x01)/2, + tend = tmax - (step==cimg::sign(y12)); + unsigned int y = (unsigned int)y0 - ymin; + for (int t = 0; t<=tend; ++t, y+=step) + if (yn; + n = nn; + nn = an; + } + + cimg_pragma_openmp(parallel for cimg_openmp_if(Xs._height>=(cimg_openmp_sizefactor)*512)) + cimg_forY(Xs,y) { + const CImg Xsy = Xs.get_shared_points(0,count[y] - 1,y).sort(); + int px = width(); + for (unsigned int k = 0; k + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity, const unsigned int pattern) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points._width==1) return draw_point((int)points(0,0),(int)points(0,1),color,opacity); + if (points._width==2) return draw_line((int)points(0,0),(int)points(0,1), + (int)points(1,0),(int)points(1,1),color,opacity,pattern); + bool ninit_hatch = true; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set (%u,%u,%u,%u).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum); + default : { + CImg npoints(points._width,2); + int x = npoints(0,0) = (int)points(0,0), y = npoints(0,1) = (int)points(0,1); + unsigned int nb_points = 1; + for (unsigned int p = 1; p + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity=1) { + return _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,0U,true); + } + + //! Draw a filled 2D ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity=1) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity); + } + + //! Draw an outlined 2D ellipse. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param r1 First radius of the ellipse. + \param r2 Second radius of the ellipse. + \param angle Angle of the first radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity, const unsigned int pattern) { + if (pattern) _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,pattern,false); + return *this; + } + + //! Draw an outlined 2D ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity, + const unsigned int pattern) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity,pattern); + } + + template + CImg& _draw_ellipse(const int x0, const int y0, const float radius1, const float radius2, const float angle, + const tc *const color, const float opacity, + const unsigned int pattern, const bool is_filled) { + if (is_empty() || (!is_filled && !pattern)) return *this; + const float radiusM = std::max(radius1,radius2); + if (radius1<0 || radius2<0 || x0 - radiusM>=width() || y0 + radiusM<0 || y0 - radiusM>=height()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_ellipse(): Specified color is (null).", + cimg_instance); + const int iradius1 = (int)cimg::round(radius1), iradius2 = (int)cimg::round(radius2); + if (!iradius1 && !iradius2) return draw_point(x0,y0,color,opacity); + if (iradius1==iradius2) { + if (is_filled) return draw_circle(x0,y0,iradius1,color,opacity); + else if (pattern==~0U) return draw_circle(x0,y0,iradius1,color,opacity,pattern); + } + const float ang = (float)(angle*cimg::PI/180); + + if (!is_filled) { // Outlined + const float ca = std::cos(ang), sa = std::sin(ang); + CImg points((unsigned int)cimg::round(6*radiusM),2); + cimg_forX(points,k) { + const float + _ang = (float)(2*cimg::PI*k/points._width), + X = (float)(radius1*std::cos(_ang)), + Y = (float)(radius2*std::sin(_ang)); + points(k,0) = (int)cimg::round(x0 + (X*ca - Y*sa)); + points(k,1) = (int)cimg::round(y0 + (X*sa + Y*ca)); + } + draw_polygon(points,color,opacity,pattern); + } else { // Filled + cimg_init_scanline(opacity); + const float + ca = std::cos(ang), + sa = -std::sin(ang), + ca2 = ca*ca, + sa2 = sa*sa, + casa = ca*sa, + i1 = 1/cimg::sqr(radius1), + i2 = 1/cimg::sqr(radius2), + t1 = i1*ca2 + i2*sa2, + t2 = (i2 - i1)*casa, + t3 = i2*ca2 + i1*sa2, + t12 = t1*2; + const int + _ymin = (int)std::floor(y0 - radiusM), + _ymax = (int)std::ceil(y0 + radiusM), + ymin = _ymin<0?0:_ymin, + ymax = _ymax>=height()?height() - 1:_ymax; + for (int y = ymin; y<=ymax; ++y) { + const float + Y = y - y0 + 0.5f, + B = 2*t2*Y, + C = t3*Y*Y - 1, + D = B*B - 4*t1*C; + if (D>=0) { + const float sD = std::sqrt(D); + const int + xmin = (int)(x0 + cimg::round((-B - sD)/t12)), + xmax = (int)(x0 + cimg::round((-B + sD)/t12)); + cimg_draw_scanline(xmin,xmax,y,color,opacity,1); + } + } + } + return *this; + } + + //! Draw a filled 2D circle. + /** + \param x0 X-coordinate of the circle center. + \param y0 Y-coordinate of the circle center. + \param radius Circle radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - Circle version of the Bresenham's algorithm is used. + **/ + template + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (!radius) return draw_point(x0,y0,color,opacity); + cimg_init_scanline(opacity); + if (y0>=0 && y0=0) { + const int x1 = x0 - x, x2 = x0 + x, y1 = y0 - y, y2 = y0 + y; + if (y1>=0 && y1=0 && y2=0 && y1=0 && y2 + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (pattern!=~0U) return draw_ellipse(x0,y0,radius,radius,0,color,opacity,pattern); + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!radius) return draw_point(x0,y0,color,opacity); + + draw_point(x0 - radius,y0,color,opacity).draw_point(x0 + radius,y0,color,opacity). + draw_point(x0,y0 - radius,color,opacity).draw_point(x0,y0 + radius,color,opacity); + if (radius==1) return *this; + for (int f = 1 - radius, ddFx = 0, ddFy = -(radius<<1), x = 0, y = radius; x=0) { f+=(ddFy+=2); --y; } + ++x; ++(f+=(ddFx+=2)); + if (x!=y + 1) { + const int x1 = x0 - y, x2 = x0 + y, y1 = y0 - x, y2 = y0 + x, + x3 = x0 - x, x4 = x0 + x, y3 = y0 - y, y4 = y0 + y; + draw_point(x1,y1,color,opacity).draw_point(x1,y2,color,opacity). + draw_point(x2,y1,color,opacity).draw_point(x2,y2,color,opacity); + if (x!=y) + draw_point(x3,y3,color,opacity).draw_point(x4,y4,color,opacity). + draw_point(x4,y3,color,opacity).draw_point(x3,y4,color,opacity); + } + } + return *this; + } + + //! Draw an image. + /** + \param sprite Sprite image. + \param x0 X-coordinate of the sprite position. + \param y0 Y-coordinate of the sprite position. + \param z0 Z-coordinate of the sprite position. + \param c0 C-coordinate of the sprite position. + \param opacity Drawing opacity. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c=1) for (int x = 0; x& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + const ulongT slx = lx*sizeof(T); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c=1) std::memcpy(ptrd,ptrs,slx); + else for (int x = 0; x + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,z0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const CImg& sprite, const float opacity=1) { + return draw_image(0,sprite,opacity); + } + + //! Draw a masked image. + /** + \param sprite Sprite image. + \param mask Mask image. + \param x0 X-coordinate of the sprite position in the image instance. + \param y0 Y-coordinate of the sprite position in the image instance. + \param z0 Z-coordinate of the sprite position in the image instance. + \param c0 C-coordinate of the sprite position in the image instance. + \param mask_max_value Maximum pixel value of the mask image \c mask. + \param opacity Drawing opacity. + \note + - Pixel values of \c mask set the opacity of the corresponding pixels in \c sprite. + - Dimensions along x,y and z of \p sprite and \p mask must be the same. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + if (is_empty() || !sprite || !mask) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,mask,opacity,mask_max_value); + if (is_overlapped(mask)) return draw_image(x0,y0,z0,c0,sprite,+mask,opacity,mask_max_value); + if (mask._width!=sprite._width || mask._height!=sprite._height || mask._depth!=sprite._depth) + throw CImgArgumentException(_cimg_instance + "draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + sprite._width,sprite._height,sprite._depth,sprite._spectrum,sprite._data, + mask._width,mask._height,mask._depth,mask._spectrum,mask._data); + + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + const ulongT msize = mask.size(); + + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,z0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw an image. + template + CImg& draw_image(const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a text string. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Pointer to \c spectrum() consecutive values, defining the foreground drawing color. + \param background_color Pointer to \c spectrum() consecutive values, defining the background drawing color. + \param opacity Drawing opacity. + \param font Font used for drawing text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent background is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,(tc*)0,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent foreground is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,(tc*)0,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Array of spectrum() values of type \c T, + defining the foreground color (0 means 'transparent'). + \param background_color Array of spectrum() values of type \c T, + defining the background color (0 means 'transparent'). + \param opacity Drawing opacity. + \param font_height Height of the text font (exact match for 13,23,53,103, interpolated otherwise). + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + const CImgList& font = CImgList::font(font_height,true); + _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,true); + return *this; + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int background_color=0, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + cimg::unused(background_color); + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",foreground_color,(const tc*)0,opacity,font_height,tmp._data); + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",(tc*)0,background_color,opacity,font_height,tmp._data); + } + + template + CImg& _draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, + const bool is_native_font) { + if (!text) return *this; + if (!font) + throw CImgArgumentException(_cimg_instance + "draw_text(): Empty specified font.", + cimg_instance); + + const unsigned int text_length = (unsigned int)std::strlen(text); + const int padding_x = font[0]._height<48?1:font[0]._height<128?(int)std::ceil(font[0]._height/51.0f + 0.745f):4; + unsigned char o_ch, ch = 0; + int x, y, w; + CImg left_paddings(text_length,1,1,1,0); + const CImg empty = CImg::empty(); + + if (is_empty() || is_native_font) { + // Pre-compute necessary size of the image as well as left paddings of each character. + x = y = w = 0; + o_ch = 0; + for (unsigned int i = 0; iw) w = x; x = 0; break; + case '\t' : x+=4*font[(int)' ']._width; break; + case ' ' : x+=font[(int)' ']._width; break; + default : if (ch'9')) || o_ch==';' || o_ch==':' || o_ch=='!') + left_padding = 4*padding_x; + else if (((o_ch=='i' || o_ch=='l' || o_ch=='I' || o_ch=='J' || o_ch=='M' || o_ch=='N') && + ((ch>='0' && ch<='9') || + (ch>='a' && ch<='z' && ch!='v' && ch!='x' && ch!='y') || + (ch>='B' && ch<='Z' && ch!='J' && ch!='T' && ch!='V' && ch!='X' && ch!='Y'))) || + o_ch=='.' || o_ch=='\'' || ch=='\'') + left_padding = padding_x; + else if ((o_ch<'0' || o_ch>'9') && ch!='-') { + const CImg &mask = ch + 256U' ' && o_ch>' ' && mask._height>13) { + const CImg &o_mask = o_ch + 256U13) { + const int w1 = mask.width()>0?o_mask.width() - 1:0, w2 = w1>1?w1 - 1:0, w3 = w2>1?w2 - 1:0; + left_padding = -10; + cimg_forY(mask,k) { + const int + lpad = o_mask(w1,k)>=8?0: + o_mask._width<=2 || o_mask(w2,k)>=8?-1: + o_mask._width<=3 || o_mask(w3,k)>=8?-2:-3, + rpad = mask(0,k)>=8?0: + mask._width<=2 || mask(1,k)>=8?-1: + mask._width<=3 || mask(2,k)>=8?-2:-3; + left_padding = std::max(left_padding,lpad + rpad); + } + } + } + } + left_paddings[i] = left_padding; + } + x+=left_padding + font[ch]._width + padding_x; + o_ch = ch; + } + } + } + if (x!=0 || ch=='\n') { if (x>w) w = x; y+=font[0]._height; } + if (is_empty()) assign(x0 + w,y0 + y,1,is_native_font?1:font[0]._spectrum,(T)0); + } + + // Draw font characters on image. + x = x0; y = y0; + for (unsigned int i = 0; i letter = font[ch]; + if (letter) { + const CImg &mask = ch + 256Uletter._spectrum) + letter.assign(letter.get_resize(-100,-100,1,_spectrum,0,2),false); + const unsigned int cmin = std::min(_spectrum,letter._spectrum); + if (foreground_color) + for (unsigned int c = 0; c& __draw_text(const char *const text, unsigned int &font_size, const int is_down, ...) { + CImg tmp(2048); + std::va_list ap; + va_start(ap,is_down); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + CImg a_label, a_labelmask; + const unsigned char a_labelcolor = 255; + unsigned int ofs = font_size, fs = ofs; + do { // Determine best font size + a_label.assign().draw_text(0,0,"%s",&a_labelcolor,0,1,fs,tmp._data); + if (a_label._width<7*_width/10 && a_label._height>_height/20 && a_label._height<_height/5) { + font_size = fs; break; + } else if ((a_label._width>7*_width/10 || a_label._height>_height/5) && fs>13 && ofs>=fs) { + ofs = fs; fs = std::max(13U,(unsigned int)cimg::round(fs/1.25f)); + } else if (a_label._width<3*_width/10 && a_label._height<_height/20 && fs<64 && ofs<=fs) { + ofs = fs; fs = std::min(64U,(unsigned int)cimg::round(fs*1.25f)); + } else { font_size = fs; break; } + } while (true); + a_label.normalize(0,255); + a_label+=(255 - a_label.get_dilate(3)).normalize(0,80); + a_label.resize(-100,-100,1,3,1); + return draw_image(0,is_down?height() - a_label.height():0,a_label,0.85f); + } + + //! Draw a 2D vector field. + /** + \param flow Image of 2D vectors used as input data. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const t2 *const color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + return draw_quiver(flow,CImg(color,_spectrum,1,1,1,true),opacity,sampling,factor,is_arrow,pattern); + } + + //! Draw a 2D vector field, using a field of colors. + /** + \param flow Image of 2D vectors used as input data. + \param color Image of spectrum()-D vectors corresponding to the color of each arrow. + \param opacity Opacity of the drawing. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const CImg& color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + if (is_empty()) return *this; + if (!flow || flow._spectrum!=2) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).", + cimg_instance, + flow._width,flow._height,flow._depth,flow._spectrum,flow._data); + if (sampling<=0) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid sampling value %g " + "(should be >0)", + cimg_instance, + sampling); + const bool colorfield = (color._width==flow._width && color._height==flow._height && + color._depth==1 && color._spectrum==_spectrum); + if (is_overlapped(flow)) return draw_quiver(+flow,color,opacity,sampling,factor,is_arrow,pattern); + float vmax,fact; + if (factor<=0) { + float m, M = (float)flow.get_norm(2).max_min(m); + vmax = (float)std::max(cimg::abs(m),cimg::abs(M)); + if (!vmax) vmax = 1; + fact = -factor; + } else { fact = factor; vmax = 1; } + + for (unsigned int y = sampling/2; y<_height; y+=sampling) + for (unsigned int x = sampling/2; x<_width; x+=sampling) { + const unsigned int X = x*flow._width/_width, Y = y*flow._height/_height; + float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax; + if (is_arrow) { + const int xx = (int)(x + u), yy = (int)(y + v); + if (colorfield) draw_arrow(x,y,xx,yy,color.get_vector_at(X,Y)._data,opacity,45,sampling/5.f,pattern); + else draw_arrow(x,y,xx,yy,color._data,opacity,45,sampling/5.f,pattern); + } else { + if (colorfield) + draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color.get_vector_at(X,Y)._data,opacity,pattern); + else draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color._data,opacity,pattern); + } + } + return *this; + } + + //! Draw a labeled horizontal axis. + /** + \param values_x Values along the horizontal axis. + \param y Y-coordinate of the horizontal axis in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const CImg& values_x, const int y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true, const float round_x=0) { + if (is_empty()) return *this; + const int yt = (y + 3 + font_height)<_height?y + 3:y - 2 - (int)font_height; + const int siz = (int)values_x.size() - 1; + CImg txt(32); + CImg a_label; + if (siz<=0) { // Degenerated case + draw_line(0,y,_width - 1,y,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",round_x?cimg::round((double)*values_x,round_x):(double)*values_x); + a_label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _xt = (width() - a_label.width())/2, + xt = _xt<3?3:_xt + a_label.width()>=width() - 2?width() - 3 - a_label.width():_xt; + draw_point(width()/2,y - 1,color,opacity).draw_point(width()/2,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case + if (values_x[0]=width() - 2?width() - 3 - a_label.width():_xt; + draw_point(xi,y - 1,color,opacity).draw_point(xi,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw a labeled vertical axis. + /** + \param x X-coordinate of the vertical axis in the image instance. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const int x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true, const float round_y=0) { + if (is_empty()) return *this; + int siz = (int)values_y.size() - 1; + CImg txt(32); + CImg a_label; + if (siz<=0) { // Degenerated case + draw_line(x,0,x,_height - 1,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",round_y?cimg::round((double)*values_y,round_y):(double)*values_y); + a_label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _yt = (height() - a_label.height())/2, + yt = _yt<0?0:_yt + a_label.height()>=height()?height() - 1 - a_label.height():_yt, + _xt = x - 2 - a_label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,height()/2,color,opacity).draw_point(x + 1,height()/2,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case + if (values_y[0]=height()?height() - 1 - a_label.height():_yt, + _xt = x - 2 - a_label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,yi,color,opacity).draw_point(x + 1,yi,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes. + /** + \param values_x Values along the X-axis. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for the X-axis. + \param pattern_y Drawing pattern for the Y-axis. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axes(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13, const bool allow_zero=true, + const float round_x=0, const float round_y=0) { + if (is_empty()) return *this; + const CImg nvalues_x(values_x._data,values_x.size(),1,1,1,true); + const int sizx = (int)values_x.size() - 1, wm1 = width() - 1; + if (sizx>=0) { + float ox = (float)*nvalues_x; + for (unsigned int x = sizx?1U:0U; x<_width; ++x) { + const float nx = (float)nvalues_x._linear_atX((float)x*sizx/wm1); + if (nx*ox<=0) { + draw_axis(nx==0?x:x - 1,values_y,color,opacity,pattern_y,font_height,allow_zero,round_y); + break; + } + ox = nx; + } + } + const CImg nvalues_y(values_y._data,values_y.size(),1,1,1,true); + const int sizy = (int)values_y.size() - 1, hm1 = height() - 1; + if (sizy>0) { + float oy = (float)nvalues_y[0]; + for (unsigned int y = sizy?1U:0U; y<_height; ++y) { + const float ny = (float)nvalues_y._linear_atX((float)y*sizy/hm1); + if (ny*oy<=0) { + draw_axis(values_x,ny==0?y:y - 1,color,opacity,pattern_x,font_height,allow_zero,round_x); + break; + } + oy = ny; + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes \overloading. + template + CImg& draw_axes(const float x0, const float x1, const float y0, const float y1, + const tc *const color, const float opacity=1, + const int subdivisionx=-60, const int subdivisiony=-60, + const float precisionx=0, const float precisiony=0, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13) { + if (is_empty()) return *this; + const bool allow_zero = (x0*x1>0) || (y0*y1>0); + const float + dx = cimg::abs(x1 - x0), dy = cimg::abs(y1 - y0), + px = dx<=0?1:precisionx==0?(float)std::pow(10.,(int)std::log10(dx) - 2.):precisionx, + py = dy<=0?1:precisiony==0?(float)std::pow(10.,(int)std::log10(dy) - 2.):precisiony; + if (x0!=x1 && y0!=y1) + draw_axes(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1), + CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1), + color,opacity,pattern_x,pattern_y,font_height,allow_zero,px,py); + else if (x0==x1 && y0!=y1) + draw_axis((int)x0,CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1), + color,opacity,pattern_y,font_height,py); + else if (x0!=x1 && y0==y1) + draw_axis(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1),(int)y0, + color,opacity,pattern_x,font_height,px); + return *this; + } + + //! Draw 2D grid. + /** + \param values_x X-coordinates of the vertical lines. + \param values_y Y-coordinates of the horizontal lines. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for vertical lines. + \param pattern_y Drawing pattern for horizontal lines. + **/ + template + CImg& draw_grid(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + if (values_x) cimg_foroff(values_x,x) { + const int xi = (int)values_x[x]; + if (xi>=0 && xi=0 && yi + CImg& draw_grid(const float delta_x, const float delta_y, + const float offsetx, const float offsety, + const bool invertx, const bool inverty, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + CImg seqx, seqy; + if (delta_x!=0) { + const float dx = delta_x>0?delta_x:_width*-delta_x/100; + const unsigned int nx = (unsigned int)(_width/dx); + seqx = CImg::sequence(1 + nx,0,(unsigned int)(dx*nx)); + if (offsetx) cimg_foroff(seqx,x) seqx(x) = (unsigned int)cimg::mod(seqx(x) + offsetx,(float)_width); + if (invertx) cimg_foroff(seqx,x) seqx(x) = _width - 1 - seqx(x); + } + if (delta_y!=0) { + const float dy = delta_y>0?delta_y:_height*-delta_y/100; + const unsigned int ny = (unsigned int)(_height/dy); + seqy = CImg::sequence(1 + ny,0,(unsigned int)(dy*ny)); + if (offsety) cimg_foroff(seqy,y) seqy(y) = (unsigned int)cimg::mod(seqy(y) + offsety,(float)_height); + if (inverty) cimg_foroff(seqy,y) seqy(y) = _height - 1 - seqy(y); + } + return draw_grid(seqx,seqy,color,opacity,pattern_x,pattern_y); + } + + //! Draw 1D graph. + /** + \param data Image containing the graph values I = f(x). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + + \param plot_type Define the type of the plot: + - 0 = No plot. + - 1 = Plot using segments. + - 2 = Plot using cubic splines. + - 3 = Plot with bars. + \param vertex_type Define the type of points: + - 0 = No points. + - 1 = Point. + - 2 = Straight cross. + - 3 = Diagonal cross. + - 4 = Filled circle. + - 5 = Outlined circle. + - 6 = Square. + - 7 = Diamond. + \param ymin Lower bound of the y-range. + \param ymax Upper bound of the y-range. + \param pattern Drawing pattern. + \note + - if \c ymin==ymax==0, the y-range is computed automatically from the input samples. + **/ + template + CImg& draw_graph(const CImg& data, + const tc *const color, const float opacity=1, + const unsigned int plot_type=1, const int vertex_type=1, + const double ymin=0, const double ymax=0, const unsigned int pattern=~0U) { + if (is_empty() || _height<=1) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_graph(): Specified color is (null).", + cimg_instance); + + // Create shaded colors for displaying bar plots. + CImg color1, color2; + if (plot_type==3) { + color1.assign(_spectrum); color2.assign(_spectrum); + cimg_forC(*this,c) { + color1[c] = (tc)std::min((float)cimg::type::max(),(float)color[c]*1.2f); + color2[c] = (tc)(color[c]*0.4f); + } + } + + // Compute min/max and normalization factors. + const ulongT + siz = data.size(), + _siz1 = siz - (plot_type!=3), + siz1 = _siz1?_siz1:1; + const unsigned int + _width1 = _width - (plot_type!=3), + width1 = _width1?_width1:1; + double m = ymin, M = ymax; + if (ymin==ymax) m = (double)data.max_min(M); + if (m==M) { --m; ++M; } + const float ca = (float)(M-m)/(_height - 1); + bool init_hatch = true; + + // Draw graph edges + switch (plot_type%4) { + case 1 : { // Segments + int oX = 0, oY = (int)cimg::round((data[0] - m)/ca); + if (siz==1) { + const int Y = (int)cimg::round((*data - m)/ca); + draw_line(0,Y,width() - 1,Y,color,opacity,pattern); + } else { + const float fx = (float)_width/siz1; + for (ulongT off = 1; off ndata(data._data,siz,1,1,1,true); + int oY = (int)cimg::round((data[0] - m)/ca); + cimg_forX(*this,x) { + const int Y = (int)cimg::round((ndata._cubic_atX((float)x*siz1/width1)-m)/ca); + if (x>0) draw_line(x,oY,x + 1,Y,color,opacity,pattern,init_hatch); + init_hatch = false; + oY = Y; + } + } break; + case 3 : { // Bars + const int Y0 = (int)cimg::round(-m/ca); + const float fx = (float)_width/siz1; + int oX = 0; + cimg_foroff(data,off) { + const int + X = (int)cimg::round((off + 1)*fx) - 1, + Y = (int)cimg::round((data[off] - m)/ca); + draw_rectangle(oX,Y0,X,Y,color,opacity). + draw_line(oX,Y,oX,Y0,color2.data(),opacity). + draw_line(oX,Y0,X,Y0,Y<=Y0?color2.data():color1.data(),opacity). + draw_line(X,Y,X,Y0,color1.data(),opacity). + draw_line(oX,Y,X,Y,Y<=Y0?color1.data():color2.data(),opacity); + oX = X + 1; + } + } break; + default : break; // No edges + } + + // Draw graph points + const unsigned int wb2 = plot_type==3?_width1/(2*siz):0; + const float fx = (float)_width1/siz1; + switch (vertex_type%8) { + case 1 : { // Point + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_point(X,Y,color,opacity); + } + } break; + case 2 : { // Straight Cross + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X - 3,Y,X + 3,Y,color,opacity).draw_line(X,Y - 3,X,Y + 3,color,opacity); + } + } break; + case 3 : { // Diagonal Cross + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X - 3,Y - 3,X + 3,Y + 3,color,opacity).draw_line(X - 3,Y + 3,X + 3,Y - 3,color,opacity); + } + } break; + case 4 : { // Filled Circle + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity); + } + } break; + case 5 : { // Outlined circle + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity,~0U); + } + } break; + case 6 : { // Square + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_rectangle(X - 3,Y - 3,X + 3,Y + 3,color,opacity,~0U); + } + } break; + case 7 : { // Diamond + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X,Y - 4,X + 4,Y,color,opacity). + draw_line(X + 4,Y,X,Y + 4,color,opacity). + draw_line(X,Y + 4,X - 4,Y,color,opacity). + draw_line(X - 4,Y,X,Y - 4,color,opacity); + } + } break; + default : break; // No points + } + return *this; + } + + bool _draw_fill(const int x, const int y, const int z, + const CImg& ref, const float tolerance2) const { + const T *ptr1 = data(x,y,z), *ptr2 = ref._data; + const ulongT off = _width*_height*_depth; + float diff = 0; + cimg_forC(*this,c) { diff += cimg::sqr(*ptr1 - *(ptr2++)); ptr1+=off; } + return diff<=tolerance2; + } + + //! Draw filled 3D region with the flood fill algorithm. + /** + \param x0 X-coordinate of the starting point of the region to fill. + \param y0 Y-coordinate of the starting point of the region to fill. + \param z0 Z-coordinate of the starting point of the region to fill. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param[out] region Image that will contain the mask of the filled region mask, as an output. + \param tolerance Tolerance concerning neighborhood values. + \param opacity Opacity of the drawing. + \param is_high_connectivity Tells if 8-connexity must be used. + \return \c region is initialized with the binary mask of the filled region. + **/ + template + CImg& draw_fill(const int x0, const int y0, const int z0, + const tc *const color, const float opacity, + CImg ®ion, + const float tolerance = 0, + const bool is_high_connectivity = false) { +#define _draw_fill_push(x,y,z) if (N>=stack._width) stack.resize(2*N + 1,1,1,3,0); \ + stack[N] = x; stack(N,1) = y; stack(N++,2) = z +#define _draw_fill_pop(x,y,z) x = stack[--N]; y = stack(N,1); z = stack(N,2) +#define _draw_fill_is_inside(x,y,z) !_region(x,y,z) && _draw_fill(x,y,z,ref,tolerance2) + + if (!containsXYZC(x0,y0,z0,0)) return *this; + const float nopacity = cimg::abs((float)opacity), copacity = 1 - std::max((float)opacity,0.f); + const float tolerance2 = cimg::sqr(tolerance); + const CImg ref = get_vector_at(x0,y0,z0); + CImg stack(256,1,1,3); + CImg _region(_width,_height,_depth,1,0); + unsigned int N = 0; + int x, y, z; + + _draw_fill_push(x0,y0,z0); + while (N>0) { + _draw_fill_pop(x,y,z); + if (!_region(x,y,z)) { + const int yp = y - 1, yn = y + 1, zp = z - 1, zn = z + 1; + int xl = x, xr = x; + + // Using these booleans reduces the number of pushes drastically. + bool is_yp = false, is_yn = false, is_zp = false, is_zn = false; + for (int step = -1; step<2; step+=2) { + while (x>=0 && x=0 && _draw_fill_is_inside(x,yp,z)) { + if (!is_yp) { _draw_fill_push(x,yp,z); is_yp = true; } + } else is_yp = false; + if (yn1) { + if (zp>=0 && _draw_fill_is_inside(x,y,zp)) { + if (!is_zp) { _draw_fill_push(x,y,zp); is_zp = true; } + } else is_zp = false; + if (zn=0 && !is_yp) { + if (xp>=0 && _draw_fill_is_inside(xp,yp,z)) { + _draw_fill_push(xp,yp,z); if (step<0) is_yp = true; + } + if (xn0) is_yp = true; + } + } + if (yn=0 && _draw_fill_is_inside(xp,yn,z)) { + _draw_fill_push(xp,yn,z); if (step<0) is_yn = true; + } + if (xn0) is_yn = true; + } + } + if (depth()>1) { + if (zp>=0 && !is_zp) { + if (xp>=0 && _draw_fill_is_inside(xp,y,zp)) { + _draw_fill_push(xp,y,zp); if (step<0) is_zp = true; + } + if (xn0) is_zp = true; + } + + if (yp>=0 && !is_yp) { + if (_draw_fill_is_inside(x,yp,zp)) { _draw_fill_push(x,yp,zp); } + if (xp>=0 && _draw_fill_is_inside(xp,yp,zp)) { _draw_fill_push(xp,yp,zp); } + if (xn=0 && _draw_fill_is_inside(xp,yn,zp)) { _draw_fill_push(xp,yn,zp); } + if (xn=0 && _draw_fill_is_inside(xp,y,zn)) { + _draw_fill_push(xp,y,zn); if (step<0) is_zn = true; + } + if (xn0) is_zn = true; + } + + if (yp>=0 && !is_yp) { + if (_draw_fill_is_inside(x,yp,zn)) { _draw_fill_push(x,yp,zn); } + if (xp>=0 && _draw_fill_is_inside(xp,yp,zn)) { _draw_fill_push(xp,yp,zn); } + if (xn=0 && _draw_fill_is_inside(xp,yn,zn)) { _draw_fill_push(xp,yn,zn); } + if (xn + CImg& draw_fill(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1, + const float tolerance=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x0,y0,z0,color,opacity,tmp,tolerance,is_high_connexity); + } + + //! Draw filled 2D region with the flood fill algorithm \simplification. + template + CImg& draw_fill(const int x0, const int y0, + const tc *const color, const float opacity=1, + const float tolerance=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x0,y0,0,color,opacity,tmp,tolerance,is_high_connexity); + } + + //! Draw a random plasma texture. + /** + \param alpha Alpha-parameter. + \param beta Beta-parameter. + \param scale Scale-parameter. + \note Use the mid-point algorithm to render. + **/ + CImg& draw_plasma(const float alpha=1, const float beta=0, const unsigned int scale=8) { + if (is_empty()) return *this; + const int w = width(), h = height(); + const Tfloat m = (Tfloat)cimg::type::min(), M = (Tfloat)cimg::type::max(); + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + cimg_forZC(*this,z,c) { + CImg ref = get_shared_slice(z,c); + for (int delta = 1<1; delta>>=1) { + const int delta2 = delta>>1; + const float r = alpha*delta + beta; + + // Square step. + for (int y0 = 0; y0M?M:val); + } + + // Diamond steps. + for (int y = -delta2; yM?M:val); + } + for (int y0 = 0; y0M?M:val); + } + for (int y = -delta2; yM?M:val); + } + } + } + cimg::srand(rng); + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2D fractal. + /** + \param x0 X-coordinate of the upper-left pixel. + \param y0 Y-coordinate of the upper-left pixel. + \param x1 X-coordinate of the lower-right pixel. + \param y1 Y-coordinate of the lower-right pixel. + \param colormap Colormap. + \param opacity Drawing opacity. + \param z0r Real part of the upper-left fractal vertex. + \param z0i Imaginary part of the upper-left fractal vertex. + \param z1r Real part of the lower-right fractal vertex. + \param z1i Imaginary part of the lower-right fractal vertex. + \param iteration_max Maximum number of iterations for each estimated point. + \param is_normalized_iteration Tells if iterations are normalized. + \param is_julia_set Tells if the Mandelbrot or Julia set is rendered. + \param param_r Real part of the Julia set parameter. + \param param_i Imaginary part of the Julia set parameter. + \note Fractal rendering is done by the Escape Time Algorithm. + **/ + template + CImg& draw_mandelbrot(const int x0, const int y0, const int x1, const int y1, + const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + if (is_empty()) return *this; + CImg palette; + if (colormap) palette.assign(colormap._data,colormap.size()/colormap._spectrum,1,1,colormap._spectrum,true); + if (palette && palette._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_mandelbrot(): Instance and specified colormap (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f), ln2 = (float)std::log(2.); + const int + _x0 = cimg::cut(x0,0,width() - 1), + _y0 = cimg::cut(y0,0,height() - 1), + _x1 = cimg::cut(x1,0,width() - 1), + _y1 = cimg::cut(y1,0,height() - 1); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if((1 + _x1 - _x0)*(1 + _y1 - _y0)>=(cimg_openmp_sizefactor)*2048)) + for (int q = _y0; q<=_y1; ++q) + for (int p = _x0; p<=_x1; ++p) { + unsigned int iteration = 0; + const double x = z0r + p*(z1r-z0r)/_width, y = z0i + q*(z1i-z0i)/_height; + double zr, zi, cr, ci; + if (is_julia_set) { zr = x; zi = y; cr = param_r; ci = param_i; } + else { zr = param_r; zi = param_i; cr = x; ci = y; } + for (iteration=1; zr*zr + zi*zi<=4 && iteration<=iteration_max; ++iteration) { + const double temp = zr*zr - zi*zi + cr; + zi = 2*zr*zi + ci; + zr = temp; + } + if (iteration>iteration_max) { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette(0,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(0,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)0; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)((*this)(p,q,0,c)*copacity); + } + } else if (is_normalized_iteration) { + const float + normz = (float)cimg::abs(zr*zr + zi*zi), + niteration = (float)(iteration + 1 - std::log(std::log(normz))/ln2); + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._linear_atX(niteration,c); + else cimg_forC(*this,c) + (*this)(p,q,0,c) = (T)(palette._linear_atX(niteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)niteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(niteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } else { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._atX(iteration,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(iteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)iteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(iteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } + } + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2D fractal \overloading. + template + CImg& draw_mandelbrot(const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + return draw_mandelbrot(0,0,_width - 1,_height - 1,colormap,opacity, + z0r,z0i,z1r,z1i,iteration_max,is_normalized_iteration,is_julia_set,param_r,param_i); + } + + //! Draw a 1D gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param sigma Standard variation of the gaussian distribution. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float sigma, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + const float sigma2 = 2*sigma*sigma, nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forX(*this,x) { + const float dx = (x - xc), val = (float)std::exp(-dx*dx/sigma2); + T *ptrd = data(x,0,0,0); + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 2D gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param yc Y-coordinate of the gaussian center. + \param tensor Covariance matrix (must be 2x2). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float yc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (tensor._width!=2 || tensor._height!=2 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 2x2 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + typedef typename CImg::Tfloat tfloat; + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/=-2.; + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + float dy = -yc; + cimg_forY(*this,y) { + float dx = -xc; + cimg_forX(*this,x) { + const float val = (float)std::exp(a*dx*dx + b*dx*dy + c*dy*dy); + T *ptrd = data(x,y,0,0); + if (opacity>=1) cimg_forC(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + ++dx; + } + ++dy; + } + return *this; + } + + //! Draw a 2D gaussian function \overloading. + template + CImg& draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, + const tc *const color, const float opacity=1) { + const double + a = r1*ru*ru + r2*rv*rv, + b = (r1-r2)*ru*rv, + c = r1*rv*rv + r2*ru*ru; + const CImg tensor(2,2,1,1, a,b,b,c); + return draw_gaussian(xc,yc,tensor,color,opacity); + } + + //! Draw a 2D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,CImg::diagonal(sigma,sigma),color,opacity); + } + + //! Draw a 3D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + typedef typename CImg::Tfloat tfloat; + if (tensor._width!=3 || tensor._height!=3 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 3x3 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/=-2.; + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = 2*invT2(2,0), d = invT2(1,1), e = 2*invT2(2,1), f = invT2(2,2); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forXYZ(*this,x,y,z) { + const float + dx = (x - xc), dy = (y - yc), dz = (z - zc), + val = (float)std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz); + T *ptrd = data(x,y,z,0); + if (opacity>=1) cimg_forC(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 3D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,zc,CImg::diagonal(sigma,sigma,sigma),color,opacity); + } + + //! Draw a 3D object. + /** + \param x0 X-coordinate of the 3D object position + \param y0 Y-coordinate of the 3D object position + \param z0 Z-coordinate of the 3D object position + \param vertices Image Nx3 describing 3D point coordinates + \param primitives List of P primitives + \param colors List of P color (or textures) + \param opacities Image or list of P opacities + \param render_type d Render type (0=Points, 1=Lines, 2=Faces (no light), 3=Faces (flat), 4=Faces(Gouraud) + \param is_double_sided Tells if object faces have two sides or are oriented. + \param focale length of the focale (0 for parallel projection) + \param lightx X-coordinate of the light + \param lighty Y-coordinate of the light + \param lightz Z-coordinate of the light + \param specular_lightness Amount of specular light. + \param specular_shininess Shininess of the object + \param g_opacity Global opacity of the object. + **/ + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } +#endif + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } +#endif + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,zbuffer); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,zbuffer); + } +#endif + + template + static float __draw_object3d(const CImgList& opacities, const unsigned int n_primitive, CImg& opacity) { + if (n_primitive>=opacities._width || opacities[n_primitive].is_empty()) { opacity.assign(); return 1; } + if (opacities[n_primitive].size()==1) { opacity.assign(); return opacities(n_primitive,0); } + opacity.assign(opacities[n_primitive],true); + return 1.f; + } + + template + static float __draw_object3d(const CImg& opacities, const unsigned int n_primitive, CImg& opacity) { + opacity.assign(); + return n_primitive>=opacities._width?1.f:(float)opacities[n_primitive]; + } + + template + static float ___draw_object3d(const CImgList& opacities, const unsigned int n_primitive) { + return n_primitive + static float ___draw_object3d(const CImg& opacities, const unsigned int n_primitive) { + return n_primitive + CImg& _draw_object3d(void *const pboard, CImg& zbuffer, + const float X, const float Y, const float Z, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, const float sprite_scale) { + typedef typename cimg::superset2::type tpfloat; + typedef typename to::value_type _to; + if (is_empty() || !vertices || !primitives) return *this; + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,false,error_message)) + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); +#ifndef cimg_use_board + if (pboard) return *this; +#endif + if (render_type==5) cimg::mutex(10); // Static variable used in this case, breaks thread-safety + + const float + nspec = 1 - (specular_lightness<0.f?0.f:(specular_lightness>1.f?1.f:specular_lightness)), + nspec2 = 1 + (specular_shininess<0.f?0.f:specular_shininess), + nsl1 = (nspec2 - 1)/cimg::sqr(nspec - 1), + nsl2 = 1 - 2*nsl1*nspec, + nsl3 = nspec2 - nsl1 - nsl2; + + // Create light texture for phong-like rendering. + CImg light_texture; + if (render_type==5) { + if (colors._width>primitives._width) { + static CImg default_light_texture; + static const tc *lptr = 0; + static tc ref_values[64] = { 0 }; + const CImg& img = colors.back(); + bool is_same_texture = (lptr==img._data); + if (is_same_texture) + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + if (ref_values[r++]!=img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum)) { + is_same_texture = false; break; + } + if (!is_same_texture || default_light_texture._spectrum<_spectrum) { + (default_light_texture.assign(img,false)/=255).resize(-100,-100,1,_spectrum); + lptr = colors.back().data(); + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + ref_values[r++] = img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum); + } + light_texture.assign(default_light_texture,true); + } else { + static CImg default_light_texture; + static float olightx = 0, olighty = 0, olightz = 0, ospecular_shininess = 0; + if (!default_light_texture || + lightx!=olightx || lighty!=olighty || lightz!=olightz || + specular_shininess!=ospecular_shininess || default_light_texture._spectrum<_spectrum) { + default_light_texture.assign(512,512); + const float + dlx = lightx - X, + dly = lighty - Y, + dlz = lightz - Z, + nl = cimg::hypot(dlx,dly,dlz), + nlx = (default_light_texture._width - 1)/2*(1 + dlx/nl), + nly = (default_light_texture._height - 1)/2*(1 + dly/nl), + white[] = { 1 }; + default_light_texture.draw_gaussian(nlx,nly,default_light_texture._width/3.f,white); + cimg_forXY(default_light_texture,x,y) { + const float factor = default_light_texture(x,y); + if (factor>nspec) default_light_texture(x,y) = std::min(2.f,nsl1*factor*factor + nsl2*factor + nsl3); + } + default_light_texture.resize(-100,-100,1,_spectrum); + olightx = lightx; olighty = lighty; olightz = lightz; ospecular_shininess = specular_shininess; + } + light_texture.assign(default_light_texture,true); + } + } + + // Compute 3D to 2D projection. + CImg projections(vertices._width,2); + tpfloat parallzmin = cimg::type::max(); + const float absfocale = focale?cimg::abs(focale):0; + if (absfocale) { + cimg_pragma_openmp(parallel for cimg_openmp_if_size(projections.size(),4096)) + cimg_forX(projections,l) { // Perspective projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + const tpfloat projectedz = z + Z + absfocale; + projections(l,1) = Y + absfocale*y/projectedz; + projections(l,0) = X + absfocale*x/projectedz; + } + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if_size(projections.size(),4096)) + cimg_forX(projections,l) { // Parallel projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + if (z visibles(primitives._width,1,1,1,~0U); + CImg zrange(primitives._width); + const tpfloat zmin = absfocale?(tpfloat)(1.5f - absfocale):cimg::type::min(); + bool is_forward = zbuffer?true:false; + + cimg_pragma_openmp(parallel for cimg_openmp_if_size(primitives.size(),4096)) + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + switch (primitive.size()) { + case 1 : { // Point + CImg<_to> _opacity; + __draw_object3d(opacities,l,_opacity); + if (l<=colors.width() && (colors[l].size()!=_spectrum || _opacity)) is_forward = false; + const unsigned int i0 = (unsigned int)primitive(0); + const tpfloat z0 = Z + vertices(i0,2); + if (z0>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = z0; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + Xc = 0.5f*((float)vertices(i0,0) + (float)vertices(i1,0)), + Yc = 0.5f*((float)vertices(i0,1) + (float)vertices(i1,1)), + Zc = 0.5f*((float)vertices(i0,2) + (float)vertices(i1,2)), + _zc = Z + Zc, + zc = _zc + _focale, + xc = X + Xc*(absfocale?absfocale/zc:1), + yc = Y + Yc*(absfocale?absfocale/zc:1), + radius = 0.5f*cimg::hypot(vertices(i1,0) - vertices(i0,0), + vertices(i1,1) - vertices(i0,1), + vertices(i1,2) - vertices(i0,2))*(absfocale?absfocale/zc:1), + xm = xc - radius, + ym = yc - radius, + xM = xc + radius, + yM = yc + radius; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && _zc>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = _zc; + } + is_forward = false; + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2); + tpfloat xm, xM, ym, yM; + if (x0=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1)/2; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (y0yM) yM = y2; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) { + const tpfloat d = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2)/3; + } + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2), + x3 = projections(i3,0), y3 = projections(i3,1), z3 = Z + vertices(i3,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (x3xM) xM = x3; + if (y0yM) yM = y2; + if (y3yM) yM = y3; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin && z3>zmin) { + const float d = (x1 - x0)*(y2 - y0) - (x2 - x0)*(y1 - y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2 + z3)/4; + } + } + } break; + default : + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid primitive[%u] with size %u " + "(should have size 1,2,3,4,5,6,9 or 12).", + cimg_instance, + l,primitive.size()); + } + } + + // Force transparent primitives to be drawn last when zbuffer is activated + // (and if object contains no spheres or sprites). + if (is_forward) + cimglist_for(primitives,l) + if (___draw_object3d(opacities,l)!=1) zrange(l) = 2*zmax - zrange(l); + + // Sort only visibles primitives. + unsigned int *p_visibles = visibles._data; + tpfloat *p_zrange = zrange._data; + const tpfloat *ptrz = p_zrange; + cimg_for(visibles,ptr,unsigned int) { + if (*ptr!=~0U) { *(p_visibles++) = *ptr; *(p_zrange++) = *ptrz; } + ++ptrz; + } + const unsigned int nb_visibles = (unsigned int)(p_zrange - zrange._data); + if (!nb_visibles) { + if (render_type==5) cimg::mutex(10,0); + return *this; + } + CImg permutations; + CImg(zrange._data,nb_visibles,1,1,1,true).sort(permutations,is_forward); + + // Compute light properties + CImg lightprops; + switch (render_type) { + case 3 : { // Flat Shading + lightprops.assign(nb_visibles); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const CImg& primitive = primitives(visibles(permutations(l))); + const unsigned int psize = (unsigned int)primitive.size(); + if (psize==3 || psize==4 || psize==9 || psize==12) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nx = dy1*dz2 - dz1*dy2, + ny = dz1*dx2 - dx1*dz2, + nz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + (x0 + x1 + x2)/3 - lightx, + ly = Y + (y0 + y1 + y2)/3 - lighty, + lz = Z + (z0 + z1 + z2)/3 - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max(cimg::abs(-lx*nx - ly*ny - lz*nz)/(norm*nl),(tpfloat)0); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } else lightprops[l] = 1; + } + } break; + + case 4 : // Gouraud Shading + case 5 : { // Phong-Shading + CImg vertices_normals(vertices._width,6,1,1,0); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + for (int l = 0; l<(int)nb_visibles; ++l) { + const CImg& primitive = primitives[visibles(l)]; + const unsigned int psize = (unsigned int)primitive.size(); + const bool + triangle_flag = (psize==3) || (psize==9), + quadrangle_flag = (psize==4) || (psize==12); + if (triangle_flag || quadrangle_flag) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = quadrangle_flag?(unsigned int)primitive(3):0; + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nnx = dy1*dz2 - dz1*dy2, + nny = dz1*dx2 - dx1*dz2, + nnz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nnx,nny,nnz), + nx = nnx/norm, + ny = nny/norm, + nz = nnz/norm; + unsigned int ix = 0, iy = 1, iz = 2; + if (is_double_sided && nz>0) { ix = 3; iy = 4; iz = 5; } + vertices_normals(i0,ix)+=nx; vertices_normals(i0,iy)+=ny; vertices_normals(i0,iz)+=nz; + vertices_normals(i1,ix)+=nx; vertices_normals(i1,iy)+=ny; vertices_normals(i1,iz)+=nz; + vertices_normals(i2,ix)+=nx; vertices_normals(i2,iy)+=ny; vertices_normals(i2,iz)+=nz; + if (quadrangle_flag) { + vertices_normals(i3,ix)+=nx; vertices_normals(i3,iy)+=ny; vertices_normals(i3,iz)+=nz; + } + } + } + + if (is_double_sided) cimg_forX(vertices_normals,p) { + const float + nx0 = vertices_normals(p,0), ny0 = vertices_normals(p,1), nz0 = vertices_normals(p,2), + nx1 = vertices_normals(p,3), ny1 = vertices_normals(p,4), nz1 = vertices_normals(p,5), + n0 = nx0*nx0 + ny0*ny0 + nz0*nz0, n1 = nx1*nx1 + ny1*ny1 + nz1*nz1; + if (n1>n0) { + vertices_normals(p,0) = -nx1; + vertices_normals(p,1) = -ny1; + vertices_normals(p,2) = -nz1; + } + } + + if (render_type==4) { + lightprops.assign(vertices._width); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + vertices(l,0) - lightx, + ly = Y + vertices(l,1) - lighty, + lz = Z + vertices(l,2) - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max((-lx*nx - ly*ny - lz*nz)/(norm*nl),(tpfloat)0); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } + } else { + const unsigned int + lw2 = light_texture._width/2 - 1, + lh2 = light_texture._height/2 - 1; + lightprops.assign(vertices._width,2); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + nnx = nx/norm, + nny = ny/norm; + lightprops(l,0) = lw2*(1 + nnx); + lightprops(l,1) = lh2*(1 + nny); + } + } + } break; + } + + // Draw visible primitives + const CImg default_color(1,_spectrum,1,1,(tc)200); + CImg<_to> _opacity; + + for (unsigned int l = 0; l& primitive = primitives[n_primitive]; + const CImg + &__color = n_primitive(), + _color = (__color && __color.size()!=_spectrum && __color._spectrum<_spectrum)? + __color.get_resize(-100,-100,-100,_spectrum,0):CImg(), + &color = _color?_color:(__color?__color:default_color); + const tc *const pcolor = color._data; + float opacity = __draw_object3d(opacities,n_primitive,_opacity); + if (_opacity.is_empty()) opacity*=g_opacity; + +#ifdef cimg_use_board + LibBoard::Board &board = *(LibBoard::Board*)pboard; +#endif + + switch (primitive.size()) { + case 1 : { // Colored point or sprite + const unsigned int n0 = (unsigned int)primitive[0]; + const int x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)); + + if (_opacity.is_empty()) { // Scalar opacity + + if (color.size()==_spectrum) { // Colored point + draw_point(x0,y0,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height()-(float)y0); + } +#endif + } else { // Sprite + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(color._width*factor), + _sh = (unsigned int)(color._height*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + draw_image(nx0,ny0,sprite,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } else { // Opacity mask + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(std::max(color._width,_opacity._width)*factor), + _sh = (unsigned int)(std::max(color._height,_opacity._height)*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + const CImg<_to> + _nopacity = (sw!=_opacity._width || sh!=_opacity._height)? + _opacity.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<_to>(), + &nopacity = _nopacity?_nopacity:_opacity; + draw_image(nx0,ny0,sprite,nopacity,g_opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } break; + case 2 : { // Colored line + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity); + else draw_line(x0,y0,x1,y1,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 5 : { // Colored sphere + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + is_wireframe = (unsigned int)primitive[2], + is_radius = (unsigned int)primitive[3]; + float Xc,Yc,Zc,radius; + if (is_radius) { + Xc = (float)vertices(n0,0); + Yc = (float)vertices(n0,1); + Zc = (float)vertices(n0,2); + radius = cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2)); + } else { + Xc = 0.5f*((float)vertices(n0,0) + (float)vertices(n1,0)); + Yc = 0.5f*((float)vertices(n0,1) + (float)vertices(n1,1)); + Zc = 0.5f*((float)vertices(n0,2) + (float)vertices(n1,2)); + radius = 0.5f*cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2)); + } + const float + zc = Z + Zc + _focale, + af = absfocale?absfocale/zc:1, + xc = X + Xc*af, + yc = Y + Yc*af; + radius*=af; + + switch (render_type) { + case 0 : + draw_point((int)xc,(int)yc,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot(xc,height() - yc); + } +#endif + break; + case 1 : + draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } +#endif + break; + default : + if (is_wireframe) draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + else draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + if (!is_wireframe) board.fillCircle(xc,height() - yc,radius); + else { + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } + } +#endif + break; + } + } break; + case 6 : { // Textured line + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for line primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + tx0 = (int)primitive[2], ty0 = (int)primitive[3], + tx1 = (int)primitive[4], ty1 = (int)primitive[5], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + else draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 3 : { // Colored triangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity).draw_point(x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x0,y0,z0,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x0,y0,x2,y2,pcolor,opacity). + draw_line(x1,y1,x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)); + else _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprops(n0),lightprops(n1),lightprops(n2),opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + } break; + } + } break; + case 4 : { // Colored quadrangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)), + x3 = cimg::uiround(projections(n3,0)), y3 = cimg::uiround(projections(n3,1)), + xc = (x0 + x1 + x2 + x3)/4, yc = (y0 + y1 + y2 + y3)/4; + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale, + zc = (z0 + z1 + z2 + z3)/4; + + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity). + draw_point(x2,y2,pcolor,opacity).draw_point(x3,y3,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,pcolor,opacity).draw_line(zbuffer,x3,y3,z3,x0,y0,z0,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x1,y1,x2,y2,pcolor,opacity). + draw_line(x2,y2,x3,y3,pcolor,opacity).draw_line(x3,y3,x0,y0,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity); + else + draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity).draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity,lightprops(l)); + else + _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)). + _draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp),(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3), + lightpropc = (lightprop0 + lightprop1 + lightprop2 + lightprop2)/4; + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,xc,yc,zc,pcolor,lightprop0,lightprop1,lightpropc,opacity). + draw_triangle(zbuffer,x1,y1,z1,x2,y2,z2,xc,yc,zc,pcolor,lightprop1,lightprop2,lightpropc,opacity). + draw_triangle(zbuffer,x2,y2,z2,x3,y3,z3,xc,yc,zc,pcolor,lightprop2,lightprop3,lightpropc,opacity). + draw_triangle(zbuffer,x3,y3,z3,x0,y0,z0,xc,yc,zc,pcolor,lightprop3,lightprop0,lightpropc,opacity); + else + draw_triangle(x0,y0,x1,y1,xc,yc,pcolor,lightprop0,lightprop1,lightpropc,opacity). + draw_triangle(x1,y1,x2,y2,xc,yc,pcolor,lightprop1,lightprop2,lightpropc,opacity). + draw_triangle(x2,y2,x3,y3,xc,yc,pcolor,lightprop2,lightprop3,lightpropc,opacity). + draw_triangle(x3,y3,x0,y0,xc,yc,pcolor,lightprop3,lightprop0,lightpropc,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)), + lx3 = (unsigned int)cimg::uiround(lightprops(n3,0)), ly3 = (unsigned int)cimg::uiround(lightprops(n3,1)), + lxc = (lx0 + lx1 + lx2 + lx3)/4, lyc = (ly0 + ly1 + ly2 + ly3)/4; + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,xc,yc,zc,pcolor,light_texture,lx0,ly0,lx1,ly1,lxc,lyc,opacity). + draw_triangle(zbuffer,x1,y1,z1,x2,y2,z2,xc,yc,zc,pcolor,light_texture,lx1,ly1,lx2,ly2,lxc,lyc,opacity). + draw_triangle(zbuffer,x2,y2,z2,x3,y3,z3,xc,yc,zc,pcolor,light_texture,lx2,ly2,lx3,ly3,lxc,lyc,opacity). + draw_triangle(zbuffer,x3,y3,z3,x0,y0,z0,xc,yc,zc,pcolor,light_texture,lx3,ly3,lx0,ly0,lxc,lyc,opacity); + else + draw_triangle(x0,y0,x1,y1,xc,yc,pcolor,light_texture,lx0,ly0,lx1,ly1,lxc,lyc,opacity). + draw_triangle(x1,y1,x2,y2,xc,yc,pcolor,light_texture,lx1,ly1,lx2,ly2,lxc,lyc,opacity). + draw_triangle(x2,y2,x3,y3,xc,yc,pcolor,light_texture,lx2,ly2,lx3,ly3,lxc,lyc,opacity). + draw_triangle(x3,y3,x0,y0,xc,yc,pcolor,light_texture,lx3,ly3,lx0,ly0,lxc,lyc,opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + case 9 : { // Textured triangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for triangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + tx0 = (int)primitive[3], ty0 = (int)primitive[4], + tx1 = (int)primitive[5], ty1 = (int)primitive[6], + tx2 = (int)primitive[7], ty2 = (int)primitive[8], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + break; + } + } break; + case 12 : { // Textured quadrangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for quadrangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + tx0 = (int)primitive[4], ty0 = (int)primitive[5], + tx1 = (int)primitive[6], ty1 = (int)primitive[7], + tx2 = (int)primitive[8], ty2 = (int)primitive[9], + tx3 = (int)primitive[10], ty3 = (int)primitive[11], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)), + x3 = cimg::uiround(projections(n3,0)), y3 = cimg::uiround(projections(n3,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale; + + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity). + draw_point(x3,y3,color.get_vector_at(tx3<=0?0:tx3>=color.width()?color.width() - 1:tx3, + ty3<=0?0:ty3>=color.height()?color.height() - 1:ty3)._data,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)), + lx3 = (unsigned int)cimg::uiround(lightprops(n3,0)), ly3 = (unsigned int)cimg::uiround(lightprops(n3,1)); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + } + } + if (render_type==5) cimg::mutex(10,0); + return *this; + } + + //@} + //--------------------------- + // + //! \name Data Input + //@{ + //--------------------------- + + //! Launch simple interface to select a shape from an image. + /** + \param disp Display window to use. + \param feature_type Type of feature to select. Can be { 0=point | 1=line | 2=rectangle | 3=ellipse }. + \param XYZ Pointer to 3 values X,Y,Z which tells about the projection point coordinates, for volumetric images. + \param exit_on_anykey Exit function when any key is pressed. + **/ + CImg& select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) { + return get_select(disp,feature_type,XYZ,exit_on_anykey,is_deep_selection_default).move_to(*this); + } + + //! Simple interface to select a shape from an image \overloading. + CImg& select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) { + return get_select(title,feature_type,XYZ,exit_on_anykey,is_deep_selection_default).move_to(*this); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) const { + return _select(disp,0,feature_type,XYZ,0,0,0,exit_on_anykey,true,false,is_deep_selection_default); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false,is_deep_selection_default); + } + + CImg _select(CImgDisplay &disp, const char *const title, + const unsigned int feature_type, unsigned int *const XYZ, + const int origX, const int origY, const int origZ, + const bool exit_on_anykey, + const bool reset_view3d, + const bool force_display_z_coord, + const bool is_deep_selection_default) const { + if (is_empty()) return CImg(1,feature_type==0?3:6,1,1,-1); + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + } else { + if (title) disp.set_title("%s",title); + disp.move_inside_screen(); + } + + CImg thumb; + if (width()>disp.screen_width() || height()>disp.screen_height()) + get_resize(cimg_fitscreen(width(),height(),depth()),depth(),-100).move_to(thumb); + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).set_wheel().show_mouse(); + + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + int area = 0, area_started = 0, area_clicked = 0, phase = 0, + X0 = (int)((XYZ?XYZ[0]:_width/2)%_width), + Y0 = (int)((XYZ?XYZ[1]:_height/2)%_height), + Z0 = (int)((XYZ?XYZ[2]:_depth/2)%_depth), + X1 =-1, Y1 = -1, Z1 = -1, + X3d = -1, Y3d = -1, + oX3d = X3d, oY3d = -1, + omx = -1, omy = -1; + float X = -1, Y = -1, Z = -1; + unsigned int key = 0, font_size = 32; + + bool is_deep_selection = is_deep_selection_default, + shape_selected = false, text_down = false, visible_cursor = true; + static CImg pose3d; + static bool is_view3d = false, is_axes = true; + if (reset_view3d) { pose3d.assign(); is_view3d = false; } + CImg points3d, opacities3d, sel_opacities3d; + CImgList primitives3d, sel_primitives3d; + CImgList colors3d, sel_colors3d; + CImg visu, visu0, view3d; + CImg text(1024); *text = 0; + + while (!key && !disp.is_closed() && !shape_selected) { + + // Handle mouse motion and selection + int + mx = disp.mouse_x(), + my = disp.mouse_y(); + + const float + mX = mx<0?-1.f:(float)mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my<0?-1.f:(float)my*(height() + (depth()>1?depth():0))/disp.height(); + + area = 0; + if (mX>=0 && mY>=0 && mX=0 && mX=height()) { area = 2; X = mX; Z = mY - _height; Y = (float)(phase?Y1:Y0); } + if (mY>=0 && mX>=width() && mY=width() && mY>=height()) area = 4; + if (disp.button()) { if (!area_clicked) area_clicked = area; } else area_clicked = 0; + + CImg filename(32); + + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(1); key = 0; } break; + case cimg::keyPAGEDOWN : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(-1); key = 0; } break; + case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_axes = !is_axes; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_view3d = !is_view3d; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).__draw_text(" Saving snapshot...",font_size,(int)text_down).display(disp); + visu0.save(filename); + (+visu0).__draw_text(" Snapshot '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + } + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).__draw_text(" Saving instance... ",font_size,(int)text_down).display(disp); + save(filename); + (+visu0).__draw_text(" Instance '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + } + + switch (area) { + + case 0 : // When mouse is out of image range + mx = my = -1; X = Y = Z = -1; + break; + + case 1 : case 2 : case 3 : { // When mouse is over the XY,XZ or YZ projections + const unsigned int but = disp.button(); + const bool b1 = (bool)(but&1), b2 = (bool)(but&2), b3 = (bool)(but&4); + + if (b1 && phase==1 && area_clicked==area) { // When selection has been started (1st step) + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } + if (!b1 && phase==2 && area_clicked!=area) { // When selection is at 2nd step (for volumes) + switch (area_started) { + case 1 : if (Z1!=(int)Z) visu0.assign(); Z1 = (int)Z; break; + case 2 : if (Y1!=(int)Y) visu0.assign(); Y1 = (int)Y; break; + case 3 : if (X1!=(int)X) visu0.assign(); X1 = (int)X; break; + } + } + if (b2 && area_clicked==area) { // When moving through the image/volume + if (phase) { + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } else { + if (_depth>1 && (X0!=(int)X || Y0!=(int)Y || Z0!=(int)Z)) visu0.assign(); + X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z; + } + } + if (b3) { // Reset selection + X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = area_clicked = area_started = 0; + visu0.assign(); + } + if (disp.wheel()) { // When moving through the slices of the volume (with mouse wheel) + if (_depth>1 && !disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT() && + !disp.is_keySHIFTLEFT() && !disp.is_keySHIFTRIGHT()) { + switch (area) { + case 1 : + if (phase) Z = (float)(Z1+=disp.wheel()); else Z = (float)(Z0+=disp.wheel()); + visu0.assign(); break; + case 2 : + if (phase) Y = (float)(Y1+=disp.wheel()); else Y = (float)(Y0+=disp.wheel()); + visu0.assign(); break; + case 3 : + if (phase) X = (float)(X1+=disp.wheel()); else X = (float)(X0+=disp.wheel()); + visu0.assign(); break; + } + disp.set_wheel(); + } else key = ~0U; + } + + if ((phase==0 && b1) || + (phase==1 && !b1) || + (phase==2 && b1)) switch (phase) { // Detect change of phase + case 0 : + if (area==area_clicked) { + X0 = X1 = (int)X; Y0 = Y1 = (int)Y; Z0 = Z1 = (int)Z; area_started = area; ++phase; + } break; + case 1 : + if (area==area_started) { + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; ++phase; + if (_depth>1) { + if (disp.is_keyCTRLLEFT()) is_deep_selection = !is_deep_selection_default; + if (is_deep_selection) ++phase; + } + } else if (!b1) { X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = 0; visu0.assign(); } + break; + case 2 : ++phase; break; + } + } break; + + case 4 : // When mouse is over the 3D view + if (is_view3d && points3d) { + X3d = mx - width()*disp.width()/(width() + (depth()>1?depth():0)); + Y3d = my - height()*disp.height()/(height() + (depth()>1?depth():0)); + if (oX3d<0) { oX3d = X3d; oY3d = Y3d; } + // Left + right buttons: reset. + if ((disp.button()&3)==3) { pose3d.assign(); view3d.assign(); oX3d = oY3d = X3d = Y3d = -1; } + else if (disp.button()&1 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Left button: rotate + const float + R = 0.45f*std::min(view3d._width,view3d._height), + R2 = R*R, + u0 = (float)(oX3d - view3d.width()/2), + v0 = (float)(oY3d - view3d.height()/2), + u1 = (float)(X3d - view3d.width()/2), + v1 = (float)(Y3d - view3d.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + pose3d.draw_image(CImg::rotation_matrix(u,v,w,-alpha)*pose3d.get_crop(0,0,2,2)); + view3d.assign(); + } else if (disp.button()&2 && pose3d && oY3d!=Y3d) { // Right button: zoom + pose3d(3,2)+=(Y3d - oY3d)*1.5f; view3d.assign(); + } + if (disp.wheel()) { // Wheel: zoom + pose3d(3,2)-=disp.wheel()*15; view3d.assign(); disp.set_wheel(); + } + if (disp.button()&4 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Middle button: shift + pose3d(3,0)-=oX3d - X3d; pose3d(3,1)-=oY3d - Y3d; view3d.assign(); + } + oX3d = X3d; oY3d = Y3d; + } + mx = my = -1; X = Y = Z = -1; + break; + } + + if (phase) { + if (!feature_type) shape_selected = phase?true:false; + else { + if (_depth>1) shape_selected = (phase==3)?true:false; + else shape_selected = (phase==2)?true:false; + } + } + + if (X0<0) X0 = 0; + if (X0>=width()) X0 = width() - 1; + if (Y0<0) Y0 = 0; + if (Y0>=height()) Y0 = height() - 1; + if (Z0<0) Z0 = 0; + if (Z0>=depth()) Z0 = depth() - 1; + if (X1<1) X1 = 0; + if (X1>=width()) X1 = width() - 1; + if (Y1<0) Y1 = 0; + if (Y1>=height()) Y1 = height() - 1; + if (Z1<0) Z1 = 0; + if (Z1>=depth()) Z1 = depth() - 1; + + // Draw visualization image on the display + if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) { + + if (!visu0) { // Create image of projected planes + if (thumb) thumb._get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + else _get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + visu0.resize(disp); + view3d.assign(); + points3d.assign(); + } + + if (is_view3d && _depth>1 && !view3d) { // Create 3D view for volumetric images + const unsigned int + _x3d = (unsigned int)cimg::round((float)_width*visu0._width/(_width + _depth),1,1), + _y3d = (unsigned int)cimg::round((float)_height*visu0._height/(_height + _depth),1,1), + x3d = _x3d>=visu0._width?visu0._width - 1:_x3d, + y3d = _y3d>=visu0._height?visu0._height - 1:_y3d; + CImg(1,2,1,1,64,128).resize(visu0._width - x3d,visu0._height - y3d,1,visu0._spectrum,3). + move_to(view3d); + if (!points3d) { + get_projections3d(primitives3d,colors3d,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0,true).move_to(points3d); + points3d.append(CImg(8,3,1,1, + 0,_width - 1,_width - 1,0,0,_width - 1,_width - 1,0, + 0,0,_height - 1,_height - 1,0,0,_height - 1,_height - 1, + 0,0,0,0,_depth - 1,_depth - 1,_depth - 1,_depth - 1),'x'); + CImg::vector(12,13).move_to(primitives3d); CImg::vector(13,14).move_to(primitives3d); + CImg::vector(14,15).move_to(primitives3d); CImg::vector(15,12).move_to(primitives3d); + CImg::vector(16,17).move_to(primitives3d); CImg::vector(17,18).move_to(primitives3d); + CImg::vector(18,19).move_to(primitives3d); CImg::vector(19,16).move_to(primitives3d); + CImg::vector(12,16).move_to(primitives3d); CImg::vector(13,17).move_to(primitives3d); + CImg::vector(14,18).move_to(primitives3d); CImg::vector(15,19).move_to(primitives3d); + colors3d.insert(12,CImg::vector(255,255,255)); + opacities3d.assign(primitives3d.width(),1,1,1,0.5f); + if (!phase) { + opacities3d[0] = opacities3d[1] = opacities3d[2] = 0.8f; + sel_primitives3d.assign(); + sel_colors3d.assign(); + sel_opacities3d.assign(); + } else { + if (feature_type==2) { + points3d.append(CImg(8,3,1,1, + X0,X1,X1,X0,X0,X1,X1,X0, + Y0,Y0,Y1,Y1,Y0,Y0,Y1,Y1, + Z0,Z0,Z0,Z0,Z1,Z1,Z1,Z1),'x'); + sel_primitives3d.assign(); + CImg::vector(20,21).move_to(sel_primitives3d); + CImg::vector(21,22).move_to(sel_primitives3d); + CImg::vector(22,23).move_to(sel_primitives3d); + CImg::vector(23,20).move_to(sel_primitives3d); + CImg::vector(24,25).move_to(sel_primitives3d); + CImg::vector(25,26).move_to(sel_primitives3d); + CImg::vector(26,27).move_to(sel_primitives3d); + CImg::vector(27,24).move_to(sel_primitives3d); + CImg::vector(20,24).move_to(sel_primitives3d); + CImg::vector(21,25).move_to(sel_primitives3d); + CImg::vector(22,26).move_to(sel_primitives3d); + CImg::vector(23,27).move_to(sel_primitives3d); + } else { + points3d.append(CImg(2,3,1,1, + X0,X1, + Y0,Y1, + Z0,Z1),'x'); + sel_primitives3d.assign(CImg::vector(20,21)); + } + sel_colors3d.assign(sel_primitives3d._width,CImg::vector(255,255,255)); + sel_opacities3d.assign(sel_primitives3d._width,1,1,1,0.8f); + } + points3d.shift_object3d(-0.5f*(_width - 1),-0.5f*(_height - 1),-0.5f*(_depth - 1)).resize_object3d(); + points3d*=0.75f*std::min(view3d._width,view3d._height); + } + + if (!pose3d) CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose3d); + CImg zbuffer3d(view3d._width,view3d._height,1,1,0); + const CImg rotated_points3d = pose3d.get_crop(0,0,2,2)*points3d; + if (sel_primitives3d) + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,sel_primitives3d,sel_colors3d,sel_opacities3d, + 2,true,500,0,0,0,0,0,1,zbuffer3d); + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,primitives3d,colors3d,opacities3d, + 2,true,500,0,0,0,0,0,1,zbuffer3d); + visu0.draw_image(x3d,y3d,view3d); + } + visu = visu0; + + if (X<0 || Y<0 || Z<0) { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + else { + if (is_axes) { if (visible_cursor) { disp.hide_mouse(); visible_cursor = false; }} + else { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + const int d = (depth()>1)?depth():0; + int _vX = (int)X, _vY = (int)Y, _vZ = (int)Z; + if (phase>=2) { _vX = X1; _vY = Y1; _vZ = Z1; } + int + w = disp.width(), W = width() + d, + h = disp.height(), H = height() + d, + _xp = (int)(_vX*(float)w/W), xp = _xp + ((int)(_xp*(float)W/w)!=_vX), + _yp = (int)(_vY*(float)h/H), yp = _yp + ((int)(_yp*(float)H/h)!=_vY), + _xn = (int)((_vX + 1.f)*w/W - 1), xn = _xn + ((int)((_xn + 1.f)*W/w)!=_vX + 1), + _yn = (int)((_vY + 1.f)*h/H - 1), yn = _yn + ((int)((_yn + 1.f)*H/h)!=_vY + 1), + _zxp = (int)((_vZ + width())*(float)w/W), zxp = _zxp + ((int)(_zxp*(float)W/w)!=_vZ + width()), + _zyp = (int)((_vZ + height())*(float)h/H), zyp = _zyp + ((int)(_zyp*(float)H/h)!=_vZ + height()), + _zxn = (int)((_vZ + width() + 1.f)*w/W - 1), + zxn = _zxn + ((int)((_zxn + 1.f)*W/w)!=_vZ + width() + 1), + _zyn = (int)((_vZ + height() + 1.f)*h/H - 1), + zyn = _zyn + ((int)((_zyn + 1.f)*H/h)!=_vZ + height() + 1), + _xM = (int)(width()*(float)w/W - 1), xM = _xM + ((int)((_xM + 1.f)*W/w)!=width()), + _yM = (int)(height()*(float)h/H - 1), yM = _yM + ((int)((_yM + 1.f)*H/h)!=height()), + xc = (xp + xn)/2, + yc = (yp + yn)/2, + zxc = (zxp + zxn)/2, + zyc = (zyp + zyn)/2, + xf = (int)(X*w/W), + yf = (int)(Y*h/H), + zxf = (int)((Z + width())*w/W), + zyf = (int)((Z + height())*h/H); + + if (is_axes) { // Draw axes + visu.draw_line(0,yf,visu.width() - 1,yf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,yf,visu.width() - 1,yf,background_color,0.7f,0x00FF00FF). + draw_line(xf,0,xf,visu.height() - 1,foreground_color,0.7f,0xFF00FF00). + draw_line(xf,0,xf,visu.height() - 1,background_color,0.7f,0x00FF00FF); + if (_depth>1) + visu.draw_line(zxf,0,zxf,yM,foreground_color,0.7f,0xFF00FF00). + draw_line(zxf,0,zxf,yM,background_color,0.7f,0x00FF00FF). + draw_line(0,zyf,xM,zyf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,zyf,xM,zyf,background_color,0.7f,0x00FF00FF); + } + + // Draw box cursor. + if (xn - xp>=4 && yn - yp>=4) + visu.draw_rectangle(xp,yp,xn,yn,foreground_color,0.2f). + draw_rectangle(xp,yp,xn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,yp,xn,yn,background_color,1,0x55555555); + if (_depth>1) { + if (yn - yp>=4 && zxn - zxp>=4) + visu.draw_rectangle(zxp,yp,zxn,yn,background_color,0.2f). + draw_rectangle(zxp,yp,zxn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(zxp,yp,zxn,yn,background_color,1,0x55555555); + if (xn - xp>=4 && zyn - zyp>=4) + visu.draw_rectangle(xp,zyp,xn,zyn,background_color,0.2f). + draw_rectangle(xp,zyp,xn,zyn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,zyp,xn,zyn,background_color,1,0x55555555); + } + + // Draw selection. + if (phase && (phase!=1 || area_started==area)) { + const int + _xp0 = (int)(X0*(float)w/W), xp0 = _xp0 + ((int)(_xp0*(float)W/w)!=X0), + _yp0 = (int)(Y0*(float)h/H), yp0 = _yp0 + ((int)(_yp0*(float)H/h)!=Y0), + _xn0 = (int)((X0 + 1.f)*w/W - 1), xn0 = _xn0 + ((int)((_xn0 + 1.f)*W/w)!=X0 + 1), + _yn0 = (int)((Y0 + 1.f)*h/H - 1), yn0 = _yn0 + ((int)((_yn0 + 1.f)*H/h)!=Y0 + 1), + _zxp0 = (int)((Z0 + width())*(float)w/W), zxp0 = _zxp0 + ((int)(_zxp0*(float)W/w)!=Z0 + width()), + _zyp0 = (int)((Z0 + height())*(float)h/H), zyp0 = _zyp0 + ((int)(_zyp0*(float)H/h)!=Z0 + height()), + _zxn0 = (int)((Z0 + width() + 1.f)*w/W - 1), + zxn0 = _zxn0 + ((int)((_zxn0 + 1.f)*W/w)!=Z0 + width() + 1), + _zyn0 = (int)((Z0 + height() + 1.f)*h/H - 1), + zyn0 = _zyn0 + ((int)((_zyn0 + 1.f)*H/h)!=Z0 + height() + 1), + xc0 = (xp0 + xn0)/2, + yc0 = (yp0 + yn0)/2, + zxc0 = (zxp0 + zxn0)/2, + zyc0 = (zyp0 + zyn0)/2; + + switch (feature_type) { + case 1 : { // Vector + visu.draw_arrow(xc0,yc0,xc,yc,background_color,0.9f,30,5,0x33333333). + draw_arrow(xc0,yc0,xc,yc,foreground_color,0.9f,30,5,0xCCCCCCCC); + if (d) { + visu.draw_arrow(zxc0,yc0,zxc,yc,background_color,0.9f,30,5,0x33333333). + draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.9f,30,5,0xCCCCCCCC). + draw_arrow(xc0,zyc0,xc,zyc,background_color,0.9f,30,5,0x33333333). + draw_arrow(xc0,zyc0,xc,zyc,foreground_color,0.9f,30,5,0xCCCCCCCC); + } + } break; + case 2 : { // Box + visu.draw_rectangle(X0=0 && my<13) text_down = true; else if (my>=visu.height() - 13) text_down = false; + if (!feature_type || !phase) { + if (X>=0 && Y>=0 && Z>=0 && X1 || force_display_z_coord) + cimg_snprintf(text,text._width," Point (%d,%d,%d) = [ ",origX + (int)X,origY + (int)Y,origZ + (int)Z); + else cimg_snprintf(text,text._width," Point (%d,%d) = [ ",origX + (int)X,origY + (int)Y); + CImg values = get_vector_at((int)X,(int)Y,(int)Z); + const bool is_large_spectrum = values._height>8; + if (is_large_spectrum) + values.draw_image(0,4,values.get_rows(values._height - 4,values._height - 1)).resize(1,8,1,1,0); + char *ctext = text._data + std::strlen(text), *const ltext = text._data + 512; + for (unsigned int c = 0; c::format_s(), + cimg::type::format(values[c])); + ctext += std::strlen(ctext); + if (c==3 && is_large_spectrum) { + cimg_snprintf(ctext,24," ..."); + ctext += std::strlen(ctext); + } + *(ctext++) = ' '; *ctext = 0; + } + std::strcpy(text._data + std::strlen(text),"] "); + } + } else switch (feature_type) { + case 1 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + length = cimg::round(cimg::hypot(dX,dY,dZ),0.1); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width," Vect (%d,%d,%d)-(%d,%d,%d), Length = %g ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1,length); + else if (_width!=1 && _height!=1) + cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g, Angle = %g\260 ", + origX + X0,origY + Y0,origX + X1,origY + Y1,length, + cimg::round(cimg::mod(180*std::atan2(-dY,-dX)/cimg::PI,360.),0.1)); + else + cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g ", + origX + X0,origY + Y0,origX + X1,origY + Y1,length); + } break; + case 2 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + length = cimg::round(cimg::hypot(dX,dY,dZ),0.1); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width, + " Box ( %d,%d,%d ) - ( %d,%d,%d )\n Size = ( %d,%d,%d ), Length = %g ", + origX + (X01 || force_display_z_coord) + cimg_snprintf(text,text._width," Ellipse ( %d,%d,%d ) - ( %d,%d,%d ), Radii = ( %d,%d,%d ) ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),1 + cimg::abs(Z0 - Z1)); + else cimg_snprintf(text,text._width," Ellipse ( %d,%d ) - ( %d,%d ), Radii = ( %d,%d ) ", + origX + X0,origY + Y0,origX + X1,origY + Y1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1)); + } + if (phase || (mx>=0 && my>=0)) visu.__draw_text("%s",font_size,(int)text_down,text._data); + } + + disp.display(visu); + } + if (!shape_selected) disp.wait(); + if (disp.is_resized()) { disp.resize(false)._is_resized = false; old_is_resized = true; visu0.assign(); } + omx = mx; omy = my; + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + + // Return result. + CImg res(1,feature_type==0?3:6,1,1,-1); + if (XYZ) { XYZ[0] = (unsigned int)X0; XYZ[1] = (unsigned int)Y0; XYZ[2] = (unsigned int)Z0; } + if (shape_selected) { + if (feature_type==2) { + if (is_deep_selection) switch (area_started) { + case 1 : Z0 = 0; Z1 = _depth - 1; break; + case 2 : Y0 = 0; Y1 = _height - 1; break; + case 3 : X0 = 0; X1 = _width - 1; break; + } + if (X0>X1) cimg::swap(X0,X1); + if (Y0>Y1) cimg::swap(Y0,Y1); + if (Z0>Z1) cimg::swap(Z0,Z1); + } + if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1; + switch (feature_type) { + case 1 : case 2 : res[0] = X0; res[1] = Y0; res[2] = Z0; res[3] = X1; res[4] = Y1; res[5] = Z1; break; + case 3 : + res[3] = cimg::abs(X1 - X0); res[4] = cimg::abs(Y1 - Y0); res[5] = cimg::abs(Z1 - Z0); + res[0] = X0; res[1] = Y0; res[2] = Z0; + break; + default : res[0] = X0; res[1] = Y0; res[2] = Z0; + } + } + if (!exit_on_anykey || !(disp.button()&4)) disp.set_button(); + if (!visible_cursor) disp.show_mouse(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + if (key!=~0U) disp.set_key(key); + return res; + } + + // Return a visualizable uchar8 image for display routines. + CImg _get_select(const CImgDisplay& disp, const int normalization, + const int x, const int y, const int z) const { + if (is_empty()) return CImg(1,1,1,1,0); + const CImg crop = get_shared_channels(0,std::min(2,spectrum() - 1)); + CImg img2d; + if (_depth>1) { + const int mdisp = std::min(disp.screen_width(),disp.screen_height()); + if (depth()>mdisp) { + crop.get_resize(-100,-100,mdisp,-100,0).move_to(img2d); + img2d.projections2d(x,y,z*img2d._depth/_depth); + } else crop.get_projections2d(x,y,z).move_to(img2d); + } else CImg(crop,false).move_to(img2d); + + // Check for inf and NaN values. + if (cimg::type::is_float() && normalization) { + bool is_inf = false, is_nan = false; + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) { is_inf = true; break; } + else if (cimg::type::is_nan(*ptr)) { is_nan = true; break; } + if (is_inf || is_nan) { + Tint m0 = (Tint)cimg::type::max(), M0 = (Tint)cimg::type::min(); + if (!normalization) { m0 = 0; M0 = 255; } + else if (normalization==2) { m0 = (Tint)disp._min; M0 = (Tint)disp._max; } + else + cimg_for(img2d,ptr,Tuchar) + if (!cimg::type::is_inf(*ptr) && !cimg::type::is_nan(*ptr)) { + if (*ptr<(Tuchar)m0) m0 = *ptr; + if (*ptr>(Tuchar)M0) M0 = *ptr; + } + const T + val_minf = (T)(normalization==1 || normalization==3?m0 - (M0 - m0)*20 - 1:m0), + val_pinf = (T)(normalization==1 || normalization==3?M0 + (M0 - m0)*20 + 1:M0); + if (is_nan) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_nan(*ptr)) *ptr = val_minf; // Replace NaN values + if (is_inf) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) *ptr = (float)*ptr<0?val_minf:val_pinf; // Replace +-inf values + } + } + + switch (normalization) { + case 1 : img2d.normalize((ucharT)0,(ucharT)255); break; + case 2 : { + const float m = disp._min, M = disp._max; + (img2d-=m)*=255.f/(M - m>0?M - m:1); + } break; + case 3 : + if (cimg::type::is_float()) img2d.normalize((ucharT)0,(ucharT)255); + else { + const float + m = (float)cimg::type::min(), + M = (float)cimg::type::max(); + (img2d-=m)*=255.f/(M - m>0?M - m:1); + } break; + } + if (img2d.spectrum()==2) img2d.channels(0,2); + return img2d; + } + + //! Select sub-graph in a graph. + CImg get_select_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "select_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title("CImg<%s>",pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth; + const unsigned int old_normalization = disp.normalization(); + disp.show().set_button().set_wheel()._normalization = 0; + + double nymin = ymin, nymax = ymax, nxmin = xmin, nxmax = xmax; + if (nymin==nymax) { nymin = (Tfloat)min_max(nymax); const double dy = nymax - nymin; nymin-=dy/20; nymax+=dy/20; } + if (nymin==nymax) { --nymin; ++nymax; } + if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.; } + + static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 }; + static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 }; + + CImg colormap(3,_spectrum); + if (_spectrum==1) { colormap[0] = colormap[1] = 120; colormap[2] = 200; } + else { + colormap(0,0) = 220; colormap(1,0) = 10; colormap(2,0) = 10; + if (_spectrum>1) { colormap(0,1) = 10; colormap(1,1) = 220; colormap(2,1) = 10; } + if (_spectrum>2) { colormap(0,2) = 10; colormap(1,2) = 10; colormap(2,2) = 220; } + if (_spectrum>3) { colormap(0,3) = 220; colormap(1,3) = 220; colormap(2,3) = 10; } + if (_spectrum>4) { colormap(0,4) = 220; colormap(1,4) = 10; colormap(2,4) = 220; } + if (_spectrum>5) { colormap(0,5) = 10; colormap(1,5) = 220; colormap(2,5) = 220; } + if (_spectrum>6) { + cimg_uint64 rng = 10; + cimg_for_inY(colormap,6,colormap.height()-1,k) { + colormap(0,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + colormap(1,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + colormap(2,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + } + } + } + + CImg visu0, visu, graph, text, axes; + int x0 = -1, x1 = -1, y0 = -1, y1 = -1, omouse_x = -2, omouse_y = -2; + const unsigned int one = plot_type==3?0U:1U; + unsigned int okey = 0, obutton = 0, font_size = 32; + CImg message(1024); + CImg_3x3(I,unsigned char); + + for (bool selected = false; !selected && !disp.is_closed() && !okey && !disp.wheel(); ) { + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + const unsigned int key = disp.key(), button = disp.button(); + + // Generate graph representation. + if (!visu0) { + visu0.assign(disp.width(),disp.height(),1,3,220); + const int gdimx = disp.width() - 32, gdimy = disp.height() - 32; + if (gdimx>0 && gdimy>0) { + graph.assign(gdimx,gdimy,1,3,255); + if (siz<32) { + if (siz>1) graph.draw_grid(gdimx/(float)(siz - one),gdimy/(float)(siz - one),0,0, + false,true,black,0.2f,0x33333333,0x33333333); + } else graph.draw_grid(-10,-10,0,0,false,true,black,0.2f,0x33333333,0x33333333); + cimg_forC(*this,c) + graph.draw_graph(get_shared_channel(c),&colormap(0,c),(plot_type!=3 || _spectrum==1)?1:0.6f, + plot_type,vertex_type,nymax,nymin); + + axes.assign(gdimx,gdimy,1,1,0); + const float + dx = (float)cimg::abs(nxmax - nxmin), dy = (float)cimg::abs(nymax - nymin), + px = (float)std::pow(10.,(int)std::log10(dx?dx:1) - 2.), + py = (float)std::pow(10.,(int)std::log10(dy?dy:1) - 2.); + const CImg + seqx = dx<=0?CImg::vector(nxmin): + CImg::sequence(1 + gdimx/60,nxmin,one?nxmax:nxmin + (nxmax - nxmin)*(siz + 1)/siz), + seqy = CImg::sequence(1 + gdimy/60,nymax,nymin); + + const bool allow_zero = (nxmin*nxmax>0) || (nymin*nymax>0); + axes.draw_axes(seqx,seqy,white,1,~0U,~0U,13,allow_zero,px,py); + if (nymin>0) axes.draw_axis(seqx,gdimy - 1,gray,1,~0U,13,allow_zero,px); + if (nymax<0) axes.draw_axis(seqx,0,gray,1,~0U,13,allow_zero,px); + if (nxmin>0) axes.draw_axis(0,seqy,gray,1,~0U,13,allow_zero,py); + if (nxmax<0) axes.draw_axis(gdimx - 1,seqy,gray,1,~0U,13,allow_zero,py); + + cimg_for3x3(axes,x,y,0,0,I,unsigned char) + if (Icc) { + if (Icc==255) cimg_forC(graph,c) graph(x,y,c) = 0; + else cimg_forC(graph,c) graph(x,y,c) = (unsigned char)(2*graph(x,y,c)/3); + } + else if (Ipc || Inc || Icp || Icn || Ipp || Inn || Ipn || Inp) + cimg_forC(graph,c) graph(x,y,c) = (unsigned char)((graph(x,y,c) + 511)/3); + + visu0.draw_image(16,16,graph); + visu0.draw_line(15,15,16 + gdimx,15,gray2).draw_line(16 + gdimx,15,16 + gdimx,16 + gdimy,gray2). + draw_line(16 + gdimx,16 + gdimy,15,16 + gdimy,white).draw_line(15,16 + gdimy,15,15,white); + } else graph.assign(); + text.assign().draw_text(0,0,labelx?labelx:"X-axis",white,ngray,1,13).resize(-100,-100,1,3); + visu0.draw_image((visu0.width() - text.width())/2,visu0.height() - 14,~text); + text.assign().draw_text(0,0,labely?labely:"Y-axis",white,ngray,1,13).rotate(-90).resize(-100,-100,1,3); + visu0.draw_image(1,(visu0.height() - text.height())/2,~text); + visu.assign(); + } + + // Generate and display current view. + if (!visu) { + visu.assign(visu0); + if (graph && x0>=0 && x1>=0) { + const int + nx0 = x0<=x1?x0:x1, + nx1 = x0<=x1?x1:x0, + ny0 = y0<=y1?y0:y1, + ny1 = y0<=y1?y1:y0, + sx0 = (int)(16 + nx0*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sx1 = (int)(15 + (nx1 + 1)*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sy0 = 16 + ny0, + sy1 = 16 + ny1; + if (y0>=0 && y1>=0) + visu.draw_rectangle(sx0,sy0,sx1,sy1,gray,0.5f).draw_rectangle(sx0,sy0,sx1,sy1,black,0.5f,0xCCCCCCCCU); + else visu.draw_rectangle(sx0,0,sx1,visu.height() - 17,gray,0.5f). + draw_line(sx0,16,sx0,visu.height() - 17,black,0.5f,0xCCCCCCCCU). + draw_line(sx1,16,sx1,visu.height() - 17,black,0.5f,0xCCCCCCCCU); + } + if (mouse_x>=16 && mouse_y>=16 && mouse_x=7) + cimg_snprintf(message,message._width,"Value[%u:%g] = ( %g %g %g ... %g %g %g )",x,cx, + (double)(*this)(x,0,0,0),(double)(*this)(x,0,0,1),(double)(*this)(x,0,0,2), + (double)(*this)(x,0,0,_spectrum - 4),(double)(*this)(x,0,0,_spectrum - 3), + (double)(*this)(x,0,0,_spectrum - 1)); + else { + cimg_snprintf(message,message._width,"Value[%u:%g] = ( ",x,cx); + cimg_forC(*this,c) cimg_sprintf(message._data + std::strlen(message),"%g ",(double)(*this)(x,0,0,c)); + cimg_sprintf(message._data + std::strlen(message),")"); + } + if (x0>=0 && x1>=0) { + const unsigned int + nx0 = (unsigned int)(x0<=x1?x0:x1), + nx1 = (unsigned int)(x0<=x1?x1:x0), + ny0 = (unsigned int)(y0<=y1?y0:y1), + ny1 = (unsigned int)(y0<=y1?y1:y0); + const double + cx0 = nxmin + nx0*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cx1 = nxmin + (nx1 + one)*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cy0 = nymax - ny0*(nymax - nymin)/(visu._height - 32), + cy1 = nymax - ny1*(nymax - nymin)/(visu._height - 32); + if (y0>=0 && y1>=0) + cimg_sprintf(message._data + std::strlen(message)," - Range ( %u:%g, %g ) - ( %u:%g, %g )", + x0,cx0,cy0,x1 + one,cx1,cy1); + else + cimg_sprintf(message._data + std::strlen(message)," - Range [ %u:%g - %u:%g ]", + x0,cx0,x1 + one,cx1); + } + text.assign().draw_text(0,0,message,white,ngray,1,13).resize(-100,-100,1,3); + visu.draw_image((visu.width() - text.width())/2,1,~text); + } + visu.display(disp); + } + + // Test keys. + CImg filename(32); + switch (okey = key) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : okey = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).__draw_text(" Saving snapshot... ",font_size,0).display(disp); + screen.save(filename); + (+screen).__draw_text(" Snapshot '%s' saved. ",font_size,0,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).__draw_text(" Saving instance... ",font_size,0).display(disp); + save(filename); + (+screen).__draw_text(" Instance '%s' saved. ",font_size,0,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + } + + // Handle mouse motion and mouse buttons. + if (obutton!=button || omouse_x!=mouse_x || omouse_y!=mouse_y) { + visu.assign(); + if (disp.mouse_x()>=0 && disp.mouse_y()>=0) { + const int + mx = (mouse_x - 16)*(int)(siz - one)/(disp.width() - 32), + cx = cimg::cut(mx,0,(int)(siz - 1 - one)), + my = mouse_y - 16, + cy = cimg::cut(my,0,disp.height() - 32); + if (button&1) { + if (!obutton) { x0 = cx; y0 = -1; } else { x1 = cx; y1 = -1; } + } + else if (button&2) { + if (!obutton) { x0 = cx; y0 = cy; } else { x1 = cx; y1 = cy; } + } + else if (obutton) { x1 = x1>=0?cx:-1; y1 = y1>=0?cy:-1; selected = true; } + } else if (!button && obutton) selected = true; + obutton = button; omouse_x = mouse_x; omouse_y = mouse_y; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (visu && visu0) disp.wait(); + if (!exit_on_anykey && okey && okey!=cimg::keyESC && + (okey!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + okey = 0; + } + } + + disp._normalization = old_normalization; + if (x1>=0 && x1(4,1,1,1,x0,y0,x1>=0?x1 + (int)one:-1,y1); + } + + //! Load image from a file. + /** + \param filename Filename, as a C-string. + \note The extension of \c filename defines the file format. If no filename + extension is provided, CImg::get_load() will try to load the file as a .cimg or .cimgz file. + **/ + CImg& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load(): Specified filename is (null).", + cimg_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimg_load_plugin + cimg_load_plugin(filename); +#endif +#ifdef cimg_load_plugin1 + cimg_load_plugin1(filename); +#endif +#ifdef cimg_load_plugin2 + cimg_load_plugin2(filename); +#endif +#ifdef cimg_load_plugin3 + cimg_load_plugin3(filename); +#endif +#ifdef cimg_load_plugin4 + cimg_load_plugin4(filename); +#endif +#ifdef cimg_load_plugin5 + cimg_load_plugin5(filename); +#endif +#ifdef cimg_load_plugin6 + cimg_load_plugin6(filename); +#endif +#ifdef cimg_load_plugin7 + cimg_load_plugin7(filename); +#endif +#ifdef cimg_load_plugin8 + cimg_load_plugin8(filename); +#endif + // Text formats + if (!cimg::strcasecmp(ext,"asc")) load_ascii(filename); + else if (!cimg::strcasecmp(ext,"csv") || + !cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) load_dlm(filename); + else if (!cimg::strcasecmp(ext,"pdf")) load_pdf_external(filename); + + // 2D binary formats + else if (!cimg::strcasecmp(ext,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) load_jpeg(filename); + else if (!cimg::strcasecmp(ext,"png")) load_png(filename); + else if (!cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"pnm") || + !cimg::strcasecmp(ext,"pbm") || + !cimg::strcasecmp(ext,"pnk")) load_pnm(filename); + else if (!cimg::strcasecmp(ext,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"exr")) load_exr(filename); + else if (!cimg::strcasecmp(ext,"cr2") || + !cimg::strcasecmp(ext,"crw") || + !cimg::strcasecmp(ext,"dcr") || + !cimg::strcasecmp(ext,"mrw") || + !cimg::strcasecmp(ext,"nef") || + !cimg::strcasecmp(ext,"orf") || + !cimg::strcasecmp(ext,"pix") || + !cimg::strcasecmp(ext,"ptx") || + !cimg::strcasecmp(ext,"raf") || + !cimg::strcasecmp(ext,"srf")) load_dcraw_external(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"heic") || + !cimg::strcasecmp(ext,"avif")) load_heif(filename); + + // 3D binary formats + else if (!cimg::strcasecmp(ext,"dcm") || + !cimg::strcasecmp(ext,"dicom")) load_medcon_external(filename); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) load_analyze(filename); + else if (!cimg::strcasecmp(ext,"par") || + !cimg::strcasecmp(ext,"rec")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"mnc")) load_minc2(filename); + else if (!cimg::strcasecmp(ext,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(ext,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) return load_cimg(filename); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + + // Image sequences + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded) { + std::FILE *file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to open file '%s'.", + cimg_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + cimg::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"pnm")) load_pnm(filename); + else if (!cimg::strcasecmp(f_type,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(f_type,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(f_type,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(f_type,"jpg")) load_jpeg(filename); + else if (!cimg::strcasecmp(f_type,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(f_type,"png")) load_png(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"dcm")) load_medcon_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file with other means. + if (!is_loaded) { + try { + load_other(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image from a file \newinstance. + static CImg get_load(const char *const filename) { + return CImg().load(filename); + } + + //! Load image from an ascii file. + /** + \param filename Filename, as a C -string. + **/ + CImg& load_ascii(const char *const filename) { + return _load_ascii(0,filename); + } + + //! Load image from an ascii file \inplace. + static CImg get_load_ascii(const char *const filename) { + return CImg().load_ascii(filename); + } + + //! Load image from an ascii file \overloading. + CImg& load_ascii(std::FILE *const file) { + return _load_ascii(file,0); + } + + //! Loadimage from an ascii file \newinstance. + static CImg get_load_ascii(std::FILE *const file) { + return CImg().load_ascii(file); + } + + CImg& _load_ascii(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_ascii(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg line(256); *line = 0; + int err = std::fscanf(nfile,"%255[^\n]",line._data); + unsigned int dx = 0, dy = 1, dz = 1, dc = 1; + cimg_sscanf(line,"%u%*c%u%*c%u%*c%u",&dx,&dy,&dz,&dc); + err = std::fscanf(nfile,"%*[^0-9.eEinfa+-]"); + if (!dx || !dy || !dz || !dc) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_ascii(): Invalid ascii header in file '%s', image dimensions are set " + "to (%u,%u,%u,%u).", + cimg_instance, + filename?filename:"(FILE*)",dx,dy,dz,dc); + } + assign(dx,dy,dz,dc); + const ulongT siz = size(); + ulongT off = 0; + double val; + T *ptr = _data; + for (err = 1, off = 0; off& load_dlm(const char *const filename) { + return _load_dlm(0,filename); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(const char *const filename) { + return CImg().load_dlm(filename); + } + + //! Load image from a DLM file \overloading. + CImg& load_dlm(std::FILE *const file) { + return _load_dlm(file,0); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(std::FILE *const file) { + return CImg().load_dlm(file); + } + + CImg& _load_dlm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_dlm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + CImg delimiter(256), tmp(256); *delimiter = *tmp = 0; + unsigned int cdx = 0, dx = 0, dy = 0; + int err = 0; + double val; + assign(256,256,1,1,(T)0); + while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) { + if (err>0) (*this)(cdx++,dy) = (T)val; + if (cdx>=_width) resize(3*_width/2,_height,1,1,0); + char c = 0; + if (!cimg_sscanf(delimiter,"%255[^\n]%c",tmp._data,&c) || c=='\n') { + dx = std::max(cdx,dx); + if (++dy>=_height) resize(_width,3*_height/2,1,1,0); + cdx = 0; + } + } + if (cdx && err==1) { dx = cdx; ++dy; } + if (!dx || !dy) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_dlm(): Invalid DLM file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + resize(dx,dy,1,1,0); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a BMP file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_bmp(const char *const filename) { + return _load_bmp(0,filename); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(const char *const filename) { + return CImg().load_bmp(filename); + } + + //! Load image from a BMP file \overloading. + CImg& load_bmp(std::FILE *const file) { + return _load_bmp(file,0); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(std::FILE *const file) { + return CImg().load_bmp(file); + } + + CImg& _load_bmp(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_bmp(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(54); + cimg::fread(header._data,54,nfile); + if (*header!='B' || header[1]!='M') { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_bmp(): Invalid BMP file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read header and pixel buffer + int + file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24), + offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24), + header_size = header[0x0E] + (header[0x0F]<<8) + (header[0x10]<<16) + (header[0x11]<<24), + dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24), + dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24), + compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24), + nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24), + bpp = header[0x1C] + (header[0x1D]<<8); + + if (!file_size || file_size==offset) { + cimg::fseek(nfile,0,SEEK_END); + file_size = (int)cimg::ftell(nfile); + cimg::fseek(nfile,54,SEEK_SET); + } + if (header_size>40) cimg::fseek(nfile,header_size - 40,SEEK_CUR); + + const int + dx_bytes = (bpp==1)?(dx/8 + (dx%8?1:0)):((bpp==4)?(dx/2 + (dx%2)):(int)((longT)dx*bpp/8)), + align_bytes = (4 - dx_bytes%4)%4; + const ulongT + cimg_iobuffer = (ulongT)24*1024*1024, + buf_size = (ulongT)cimg::abs(dy)*(dx_bytes + align_bytes); + + CImg colormap; + if (bpp<16) { if (!nb_colors) nb_colors = 1<0) cimg::fseek(nfile,xoffset,SEEK_CUR); + + CImg buffer; + if (buf_size=2) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0x80, val = 0; + cimg_forX(*this,x) { + if (mask==0x80) val = *(ptrs++); + const unsigned char *col = (unsigned char*)(colormap._data + (val&mask?1:0)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask); + } + ptrs+=align_bytes; + } + } break; + case 4 : { // 16 colors + if (colormap._width>=16) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0xF0, val = 0; + cimg_forX(*this,x) { + if (mask==0xF0) val = *(ptrs++); + const unsigned char color = (unsigned char)((mask<16)?(val&mask):((val&mask)>>4)); + const unsigned char *col = (unsigned char*)(colormap._data + color); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask,4); + } + ptrs+=align_bytes; + } + } break; + case 8 : { // 256 colors + if (colormap._width>=256) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char *col = (unsigned char*)(colormap._data + *(ptrs++)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + } + ptrs+=align_bytes; + } + } break; + case 16 : { // 16 bits colors (RGB565) + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char c1 = *(ptrs++), c2 = *(ptrs++); + const unsigned short col = (unsigned short)c2<<8 | c1; + (*this)(x,y,2) = (T)((col&0x1F)<<3); + (*this)(x,y,1) = (T)(((col>>5)&0x3F)<<3); + (*this)(x,y,0) = (T)(((col>>11)&0x1F)<<3); + } + ptrs+=align_bytes; + } + } break; + case 24 : { // 24 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + } + ptrs+=align_bytes; + } + } break; + case 32 : { // 32 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + ++ptrs; + } + ptrs+=align_bytes; + } + } break; + } + if (dy<0) mirror('y'); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a JPEG file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_jpeg(const char *const filename) { + return _load_jpeg(0,filename); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(const char *const filename) { + return CImg().load_jpeg(filename); + } + + //! Load image from a JPEG file \overloading. + CImg& load_jpeg(std::FILE *const file) { + return _load_jpeg(file,0); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(std::FILE *const file) { + return CImg().load_jpeg(file); + } + + // Custom error handler for libjpeg. +#ifdef cimg_use_jpeg + struct _cimg_error_mgr { + struct jpeg_error_mgr original; + jmp_buf setjmp_buffer; + char message[JMSG_LENGTH_MAX]; + }; + + typedef struct _cimg_error_mgr *_cimg_error_ptr; + + METHODDEF(void) _cimg_jpeg_error_exit(j_common_ptr cinfo) { + _cimg_error_ptr c_err = (_cimg_error_ptr) cinfo->err; // Return control to the setjmp point + (*cinfo->err->format_message)(cinfo,c_err->message); + jpeg_destroy(cinfo); // Clean memory and temp files + longjmp(c_err->setjmp_buffer,1); + } +#endif + + CImg& _load_jpeg(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_jpeg(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_jpeg + if (file) + throw CImgIOException(_cimg_instance + "load_jpeg(): Unable to load data from '(FILE*)' unless libjpeg is enabled.", + cimg_instance); + else return load_other(filename); +#else + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + struct jpeg_decompress_struct cinfo; + struct _cimg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.original); + jerr.original.error_exit = _cimg_jpeg_error_exit; + if (setjmp(jerr.setjmp_buffer)) { // JPEG error + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_jpeg(): Error message returned by libjpeg: %s.", + cimg_instance,jerr.message); + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo,nfile); + jpeg_read_header(&cinfo,TRUE); + jpeg_start_decompress(&cinfo); + + if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) { + if (!file) { + cimg::fclose(nfile); + return load_other(filename); + } else + throw CImgIOException(_cimg_instance + "load_jpeg(): Failed to load JPEG data from file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + } + CImg buffer(cinfo.output_width*cinfo.output_components); + JSAMPROW row_pointer[1]; + try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); } + catch (...) { if (!file) cimg::fclose(nfile); throw; } + T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height, + *ptr_a = _data + 3UL*_width*_height; + while (cinfo.output_scanline + // This is experimental code, not much tested, use with care. + CImg& load_magick(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_magick(): Specified filename is (null).", + cimg_instance); + +#ifdef cimg_use_magick + Magick::Image image(filename); + const unsigned int W = image.size().width(), H = image.size().height(); + switch (image.type()) { + case Magick::PaletteMatteType : + case Magick::TrueColorMatteType : + case Magick::ColorSeparationType : { + assign(W,H,1,4); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + case Magick::PaletteType : + case Magick::TrueColorType : { + assign(W,H,1,3); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + ++pixels; + } + } break; + case Magick::GrayscaleMatteType : { + assign(W,H,1,2); + T *ptr_r = data(0,0,0,0), *ptr_a = data(0,0,0,1); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + default : { + assign(W,H,1,1); + T *ptr_r = data(0,0,0,0); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + ++pixels; + } + } + } + return *this; +#else + throw CImgIOException(_cimg_instance + "load_magick(): Unable to load file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Load image from a file, using Magick++ library \newinstance. + static CImg get_load_magick(const char *const filename) { + return CImg().load_magick(filename); + } + + //! Load image from a PNG file. + /** + \param filename Filename, as a C-string. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + **/ + CImg& load_png(const char *const filename, unsigned int *const bits_per_value=0) { + return _load_png(0,filename,bits_per_value); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(const char *const filename, unsigned int *const bits_per_value=0) { + return CImg().load_png(filename,bits_per_value); + } + + //! Load image from a PNG file \overloading. + CImg& load_png(std::FILE *const file, unsigned int *const bits_per_value=0) { + return _load_png(file,0,bits_per_value); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(std::FILE *const file, unsigned int *const bits_per_value=0) { + return CImg().load_png(file,bits_per_value); + } + + // (Note: Most of this function has been written by Eric Fausett) + CImg& _load_png(std::FILE *const file, const char *const filename, unsigned int *const bits_per_value) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_png(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_png + cimg::unused(bits_per_value); + if (file) + throw CImgIOException(_cimg_instance + "load_png(): Unable to load data from '(FILE*)' unless libpng is enabled.", + cimg_instance); + + else return load_other(filename); +#else + // Open file and check for PNG validity +#if defined __GNUC__ + const char *volatile nfilename = filename; // Use 'volatile' to avoid (wrong) g++ warning + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb"); +#else + const char *nfilename = filename; + std::FILE *nfile = file?file:cimg::fopen(nfilename,"rb"); +#endif + unsigned char pngCheck[8] = { 0 }; + cimg::fread(pngCheck,8,(std::FILE*)nfile); + if (png_sig_cmp(pngCheck,0,8)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Invalid PNG file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Setup PNG structures for read + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn); + if (!png_ptr) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'png_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,(png_infopp)0,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'info_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'end_info' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Error handling callback for png file reading + if (setjmp(png_jmpbuf(png_ptr))) { + if (!file) cimg::fclose((std::FILE*)nfile); + png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Encountered unknown fatal error in libpng for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + png_set_sig_bytes(png_ptr, 8); + + // Get PNG Header Info up to data block + png_read_info(png_ptr,info_ptr); + png_uint_32 W, H; + int bit_depth, color_type, interlace_type; + bool is_gray = false; + png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,(int*)0,(int*)0); + if (bits_per_value) *bits_per_value = (unsigned int)bit_depth; + + // Transforms to unify image data + if (color_type==PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + color_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + } + if (color_type==PNG_COLOR_TYPE_GRAY && bit_depth<8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + is_gray = true; + bit_depth = 8; + } + if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_ptr); + color_type |= PNG_COLOR_MASK_ALPHA; + } + if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + color_type |= PNG_COLOR_MASK_COLOR; + is_gray = true; + } + if (color_type==PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr,0xffffU,PNG_FILLER_AFTER); + + png_read_update_info(png_ptr,info_ptr); + if (bit_depth!=8 && bit_depth!=16) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Invalid bit depth %u in file '%s'.", + cimg_instance, + bit_depth,nfilename?nfilename:"(FILE*)"); + } + const int byte_depth = bit_depth>>3; + + // Allocate memory for image reading + png_bytep *const imgData = new png_bytep[H]; + for (unsigned int row = 0; row& load_pnm(const char *const filename) { + return _load_pnm(0,filename); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(const char *const filename) { + return CImg().load_pnm(filename); + } + + //! Load image from a PNM file \overloading. + CImg& load_pnm(std::FILE *const file) { + return _load_pnm(file,0); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(std::FILE *const file) { + return CImg().load_pnm(file); + } + + CImg& _load_pnm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pnm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + unsigned int ppm_type, W, H, D = 1, colormax = 255; + CImg item(16384,1,1,1,0); + int err, rval, gval, bval; + const longT cimg_iobuffer = (longT)24*1024*1024; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%u",&ppm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %u %u %u %u",&W,&H,&D,&colormax))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): WIDTH and HEIGHT fields undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (ppm_type!=1 && ppm_type!=4) { + if (err==2 || (err==3 && (ppm_type==5 || ppm_type==7 || ppm_type==8 || ppm_type==9))) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%u",&colormax)!=1) + cimg::warn(_cimg_instance + "load_pnm(): COLORMAX field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else { colormax = D; D = 1; } + } + std::fgetc(nfile); + + if (filename) { // Check that dimensions specified in file does not exceed the buffer dimension + const cimg_int64 siz = cimg::fsize(filename); + if (W*H*D>siz) + throw CImgIOException(_cimg_instance + "load_pnm(): Specified image dimensions in file '%s' exceed file size.", + cimg_instance, + filename); + } + + switch (ppm_type) { + case 1 : { // 2D B&W ascii + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)(rval?0:255); else break; } + } break; + case 2 : { // 2D grey ascii + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)rval; else break; } + } break; + case 3 : { // 2D color ascii + assign(W,H,1,3); + T *ptrd = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forXY(*this,x,y) { + if (std::fscanf(nfile,"%d %d %d",&rval,&gval,&bval)==3) { + *(ptrd++) = (T)rval; *(ptr_g++) = (T)gval; *(ptr_b++) = (T)bval; + } else break; + } + } break; + case 4 : { // 2D b&w binary (support 3D PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + unsigned int w = 0, h = 0, d = 0; + for (longT to_read = (longT)((W/8 + (W%8?1:0))*H*D); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + unsigned char mask = 0, val = 0; + for (ulongT off = (ulongT)raw._width; off || mask; mask>>=1) { + if (!mask) { if (off--) val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?0:255); + if (++w==W) { w = 0; mask = 0; if (++h==H) { h = 0; if (++d==D) break; }} + } + } + } break; + case 5 : case 7 : { // 2D/3D grey binary (support 3D PINK extension) + if (colormax<256) { // 8 bits + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } else { // 16 bits + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } + } break; + case 6 : { // 2D color binary + if (colormax<256) { // 8 bits + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { // 16 bits + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } + } break; + case 8 : { // 2D/3D grey binary with int32 integers (PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const int *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + case 9 : { // 2D/3D grey binary with float values (PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const float *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + default : + assign(); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM type 'P%d' found, but type is not supported.", + cimg_instance, + filename?filename:"(FILE*)",ppm_type); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PFM file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pfm(const char *const filename) { + return _load_pfm(0,filename); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(const char *const filename) { + return CImg().load_pfm(filename); + } + + //! Load image from a PFM file \overloading. + CImg& load_pfm(std::FILE *const file) { + return _load_pfm(file,0); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(std::FILE *const file) { + return CImg().load_pfm(file); + } + + CImg& _load_pfm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pfm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + char pfm_type; + CImg item(16384,1,1,1,0); + int W = 0, H = 0, err = 0; + double scale = 0; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%c",&pfm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): PFM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %d %d",&W,&H))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH and HEIGHT fields are undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else if (W<=0 || H<=0) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH (%d) and HEIGHT (%d) fields are invalid in file '%s'.", + cimg_instance,W,H, + filename?filename:"(FILE*)"); + } + if (err==2) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%lf",&scale)!=1) + cimg::warn(_cimg_instance + "load_pfm(): SCALE field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + std::fgetc(nfile); + const bool is_color = (pfm_type=='F'), is_inverted = (scale>0)!=cimg::endianness(); + if (is_color) { + assign(W,H,1,3,(T)0); + CImg buf(3*W); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forY(*this,y) { + cimg::fread(buf._data,3*W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,3*W); + const float *ptrs = buf._data; + cimg_forX(*this,x) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { + assign(W,H,1,1,(T)0); + CImg buf(W); + T *ptrd = data(0,0,0,0); + cimg_forY(*this,y) { + cimg::fread(buf._data,W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,W); + const float *ptrs = buf._data; + cimg_forX(*this,x) *(ptrd++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return mirror('y'); // Most of the .pfm files are flipped along the y-axis + } + + //! Load image from a RGB file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(0,filename,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(filename,dimw,dimh); + } + + //! Load image from a RGB file \overloading. + CImg& load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(file,0,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(file,dimw,dimh); + } + + CImg& _load_rgb(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgb(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/3UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a RGBA file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(0,filename,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(filename,dimw,dimh); + } + + //! Load image from a RGBA file \overloading. + CImg& load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(file,0,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(file,dimw,dimh); + } + + CImg& _load_rgba(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgba(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,4); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2), + *ptr_a = data(0,0,0,3); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/4UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a TIFF file. + /** + \param filename Filename, as a C-string. + \param first_frame First frame to read (for multi-pages tiff). + \param last_frame Last frame to read (for multi-pages tiff). + \param step_frame Step value of frame reading. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + \param[out] voxel_size Voxel size, as stored in the filename. + \param[out] description Description, as stored in the filename. + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tiff is not defined at compile time the + function uses CImg& load_other(const char*). + **/ + CImg& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Specified filename is (null).", + cimg_instance); + + const unsigned int + nfirst_frame = first_frame1) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.", + cimg_instance, + filename); + return load_other(filename); +#else +#if cimg_verbosity<3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimg_instance + "load_tiff(): File '%s' contains %u image(s) while specified frame range is [%u,%u] (step %u).", + cimg_instance, + filename,nb_images,nfirst_frame,nlast_frame,nstep_frame); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + TIFFSetDirectory(tif,0); + CImg frame; + for (unsigned int l = nfirst_frame; l<=nlast_frame; l+=nstep_frame) { + frame._load_tiff(tif,l,bits_per_value,voxel_size,description); + if (l==nfirst_frame) + assign(frame._width,frame._height,1 + (nlast_frame - nfirst_frame)/nstep_frame,frame._spectrum); + if (frame._width>_width || frame._height>_height || frame._spectrum>_spectrum) + resize(std::max(frame._width,_width), + std::max(frame._height,_height),-100, + std::max(frame._spectrum,_spectrum),0); + draw_image(0,0,(l - nfirst_frame)/nstep_frame,frame); + } + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "load_tiff(): Failed to open file '%s'.", + cimg_instance, + filename); + return *this; +#endif + } + + //! Load image from a TIFF file \newinstance. + static CImg get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + return CImg().load_tiff(filename,first_frame,last_frame,step_frame,bits_per_value,voxel_size,description); + } + + // (Original contribution by Jerome Boulanger). +#ifdef cimg_use_tiff + template + void _load_tiff_tiled_contig(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int row = 0; row + void _load_tiff_tiled_separate(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int vv = 0; vv + void _load_tiff_contig(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (row = 0; rowny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, 0); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0; rr + void _load_tiff_separate(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (unsigned int vv = 0; vvny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, vv); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0;rr& _load_tiff(TIFF *const tif, const unsigned int directory, unsigned int *const bits_per_value, + float *const voxel_size, CImg *const description) { + if (!TIFFSetDirectory(tif,directory)) return assign(); + uint16 samplesperpixel = 1, bitspersample = 8, photo = 0; + uint16 sampleformat = 1; + uint32 nx = 1, ny = 1; + const char *const filename = TIFFFileName(tif); + const bool is_spp = (bool)TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel); + TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx); + TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleformat); + TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample); + TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo); + if (bits_per_value) *bits_per_value = (unsigned int)bitspersample; + if (voxel_size) { + const char *s_description = 0; + float vx = 0, vy = 0, vz = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) { + const char *s_desc = std::strstr(s_description,"VX="); + if (s_desc && cimg_sscanf(s_desc,"VX=%f VY=%f VZ=%f",&vx,&vy,&vz)==3) { // CImg format + voxel_size[0] = vx; voxel_size[1] = vy; voxel_size[2] = vz; + } + s_desc = std::strstr(s_description,"spacing="); + if (s_desc && cimg_sscanf(s_desc,"spacing=%f",&vz)==1) { // Fiji format + voxel_size[2] = vz; + } + } + TIFFGetField(tif,TIFFTAG_XRESOLUTION,voxel_size); + TIFFGetField(tif,TIFFTAG_YRESOLUTION,voxel_size + 1); + voxel_size[0] = 1.f/voxel_size[0]; + voxel_size[1] = 1.f/voxel_size[1]; + } + if (description) { + const char *s_description = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) + CImg::string(s_description).move_to(*description); + } + const unsigned int spectrum = !is_spp || photo>=3?(photo>1?3:1):samplesperpixel; + assign(nx,ny,1,spectrum); + + if ((photo>=3 && sampleformat==1 && + (bitspersample==4 || bitspersample==8) && + (samplesperpixel==1 || samplesperpixel==3 || samplesperpixel==4)) || + (bitspersample==1 && samplesperpixel==1)) { + // Special case for unsigned color images. + uint32 *const raster = (uint32*)_TIFFmalloc(nx*ny*sizeof(uint32)); + if (!raster) { + _TIFFfree(raster); TIFFClose(tif); + throw CImgException(_cimg_instance + "load_tiff(): Failed to allocate memory (%s) for file '%s'.", + cimg_instance, + cimg::strbuffersize(nx*ny*sizeof(uint32)),filename); + } + TIFFReadRGBAImage(tif,nx,ny,raster,0); + switch (spectrum) { + case 1 : + cimg_forXY(*this,x,y) + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]); + break; + case 3 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + } + break; + case 4 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny - 1 - y) + x]); + } + break; + } + _TIFFfree(raster); + } else { // Other cases + uint16 config; + TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config); + if (TIFFIsTiled(tif)) { + uint32 tw = 1, th = 1; + TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw); + TIFFGetField(tif,TIFFTAG_TILELENGTH,&th); + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + } + } else { + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + } + } + } + return *this; + } +#endif + + //! Load image from a MINC2 file. + /** + \param filename Filename, as a C-string. + **/ + // (Original code by Haz-Edine Assemlal). + CImg& load_minc2(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_minc2(): Specified filename is (null).", + cimg_instance); +#ifndef cimg_use_minc2 + return load_other(filename); +#else + minc::minc_1_reader rdr; + rdr.open(filename); + assign(rdr.ndim(1)?rdr.ndim(1):1, + rdr.ndim(2)?rdr.ndim(2):1, + rdr.ndim(3)?rdr.ndim(3):1, + rdr.ndim(4)?rdr.ndim(4):1); + if (pixel_type()==cimg::type::string()) + rdr.setup_read_byte(); + else if (pixel_type()==cimg::type::string()) + rdr.setup_read_int(); + else if (pixel_type()==cimg::type::string()) + rdr.setup_read_double(); + else + rdr.setup_read_float(); + minc::load_standard_volume(rdr,this->_data); + return *this; +#endif + } + + //! Load image from a MINC2 file \newinstance. + static CImg get_load_minc2(const char *const filename) { + return CImg().load_analyze(filename); + } + + //! Load image from an ANALYZE7.5/NIFTI file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_analyze(const char *const filename, float *const voxel_size=0) { + return _load_analyze(0,filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(const char *const filename, float *const voxel_size=0) { + return CImg().load_analyze(filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \overloading. + CImg& load_analyze(std::FILE *const file, float *const voxel_size=0) { + return _load_analyze(file,0,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(std::FILE *const file, float *const voxel_size=0) { + return CImg().load_analyze(file,voxel_size); + } + + CImg& _load_analyze(std::FILE *const file, const char *const filename, float *const voxel_size=0) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_analyze(): Specified filename is (null).", + cimg_instance); + + std::FILE *nfile_header = 0, *nfile = 0; + if (!file) { + CImg body(1024); + const char *const ext = cimg::split_filename(filename,body); + if (!cimg::strcasecmp(ext,"hdr")) { // File is an Analyze header file + nfile_header = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".img"); + nfile = cimg::fopen(body,"rb"); + } else if (!cimg::strcasecmp(ext,"img")) { // File is an Analyze data file + nfile = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".hdr"); + nfile_header = cimg::fopen(body,"rb"); + } else nfile_header = nfile = cimg::fopen(filename,"rb"); // File is a Niftii file + } else nfile_header = nfile = file; // File is a Niftii file + if (!nfile || !nfile_header) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid Analyze7.5 or NIFTI header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + // Read header. + bool endian = false; + unsigned int header_size; + cimg::fread(&header_size,1,nfile_header); + if (!header_size) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid zero-size header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (header_size>=4096) { endian = true; cimg::invert_endianness(header_size); } + + unsigned char *const header = new unsigned char[header_size]; + cimg::fread(header + 4,header_size - 4,nfile_header); + if (!file && nfile_header!=nfile) cimg::fclose(nfile_header); + if (endian) { + cimg::invert_endianness((short*)(header + 40),5); + cimg::invert_endianness((short*)(header + 70),1); + cimg::invert_endianness((short*)(header + 72),1); + cimg::invert_endianness((float*)(header + 76),4); + cimg::invert_endianness((float*)(header + 108),1); + cimg::invert_endianness((float*)(header + 112),1); + } + + if (nfile_header==nfile) { + const unsigned int vox_offset = (unsigned int)*(float*)(header + 108); + std::fseek(nfile,vox_offset,SEEK_SET); + } + + unsigned short *dim = (unsigned short*)(header + 40), dimx = 1, dimy = 1, dimz = 1, dimv = 1; + if (!dim[0]) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with zero dimensions.", + cimg_instance, + filename?filename:"(FILE*)"); + + if (dim[0]>4) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with %u dimensions, reading only the 4 first.", + cimg_instance, + filename?filename:"(FILE*)",dim[0]); + + if (dim[0]>=1) dimx = dim[1]; + if (dim[0]>=2) dimy = dim[2]; + if (dim[0]>=3) dimz = dim[3]; + if (dim[0]>=4) dimv = dim[4]; + float scalefactor = *(float*)(header + 112); if (scalefactor==0) scalefactor = 1; + const unsigned short datatype = *(unsigned short*)(header + 70); + if (voxel_size) { + const float *vsize = (float*)(header + 76); + voxel_size[0] = vsize[1]; voxel_size[1] = vsize[2]; voxel_size[2] = vsize[3]; + } + delete[] header; + + // Read pixel data. + assign(dimx,dimy,dimz,dimv); + const size_t pdim = (size_t)dimx*dimy*dimz*dimv; + switch (datatype) { + case 2 : { + unsigned char *const buffer = new unsigned char[pdim]; + cimg::fread(buffer,pdim,nfile); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 4 : { + short *const buffer = new short[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 8 : { + int *const buffer = new int[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 16 : { + float *const buffer = new float[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 64 : { + double *const buffer = new double[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_analyze(): Unable to load datatype %d in file '%s'", + cimg_instance, + datatype,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a .cimg[z] file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(const char *const filename, const char axis='z', const float align=0) { + return CImg().load_cimg(filename,axis,align); + } + + //! Load image from a .cimg[z] file \overloading. + CImg& load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + return CImg().load_cimg(file,axis,align); + } + + //! Load sub-images of a .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Starting frame. + \param n1 Ending frame (~0U for max). + \param x0 X-coordinate of the starting sub-image vertex. + \param y0 Y-coordinate of the starting sub-image vertex. + \param z0 Z-coordinate of the starting sub-image vertex. + \param c0 C-coordinate of the starting sub-image vertex. + \param x1 X-coordinate of the ending sub-image vertex (~0U for max). + \param y1 Y-coordinate of the ending sub-image vertex (~0U for max). + \param z1 Z-coordinate of the ending sub-image vertex (~0U for max). + \param c1 C-coordinate of the ending sub-image vertex (~0U for max). + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load sub-images of a .cimg file \overloading. + CImg& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load image from an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_inr(const char *const filename, float *const voxel_size=0) { + return _load_inr(0,filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(const char *const filename, float *const voxel_size=0) { + return CImg().load_inr(filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \overloading. + CImg& load_inr(std::FILE *const file, float *const voxel_size=0) { + return _load_inr(file,0,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(std::FILE *const file, float *voxel_size=0) { + return CImg().load_inr(file,voxel_size); + } + + static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) { + CImg item(1024), tmp1(64), tmp2(64); + *item = *tmp1 = *tmp2 = 0; + out[0] = std::fscanf(file,"%63s",item._data); + out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1; + if (cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0) + throw CImgIOException("CImg<%s>::load_inr(): INRIMAGE-4 header not found.", + pixel_type()); + + while (std::fscanf(file," %63[^\n]%*c",item._data)!=EOF && std::strncmp(item,"##}",3)) { + cimg_sscanf(item," XDIM%*[^0-9]%d",out); + cimg_sscanf(item," YDIM%*[^0-9]%d",out + 1); + cimg_sscanf(item," ZDIM%*[^0-9]%d",out + 2); + cimg_sscanf(item," VDIM%*[^0-9]%d",out + 3); + cimg_sscanf(item," PIXSIZE%*[^0-9]%d",out + 6); + if (voxel_size) { + cimg_sscanf(item," VX%*[^0-9.+-]%f",voxel_size); + cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1); + cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2); + } + if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1; + switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) { + case 0 : break; + case 2 : + out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; + std::strncpy(tmp1,tmp2,tmp1._width - 1); // fallthrough + case 1 : + if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5)) out[4] = 0; + if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1; + if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2; + if (out[4]>=0) break; // fallthrough + default : + throw CImgIOException("CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.", + pixel_type(), + tmp2._data); + } + } + if (out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0) + throw CImgIOException("CImg<%s>::load_inr(): Invalid dimensions (%d,%d,%d,%d) defined in header.", + pixel_type(), + out[0],out[1],out[2],out[3]); + if (out[4]<0 || out[5]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete pixel type defined in header.", + pixel_type()); + if (out[6]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete PIXSIZE field defined in header.", + pixel_type()); + if (out[7]<0) + throw CImgIOException("CImg<%s>::load_inr(): Big/Little Endian coding type undefined in header.", + pixel_type()); + } + + CImg& _load_inr(std::FILE *const file, const char *const filename, float *const voxel_size) { +#define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \ + if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \ + Ts *xval, *const val = new Ts[(size_t)fopt[0]*fopt[3]]; \ + cimg_forYZ(*this,y,z) { \ + cimg::fread(val,fopt[0]*fopt[3],nfile); \ + if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \ + xval = val; cimg_forX(*this,x) cimg_forC(*this,c) (*this)(x,y,z,c) = (T)*(xval++); \ + } \ + delete[] val; \ + loaded = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_inr(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + int fopt[8], endian = cimg::endianness()?1:0; + bool loaded = false; + if (voxel_size) voxel_size[0] = voxel_size[1] = voxel_size[2] = 1; + _load_inr_header(nfile,fopt,voxel_size); + assign(fopt[0],fopt[1],fopt[2],fopt[3]); + _cimg_load_inr_case(0,0,8,unsigned char); + _cimg_load_inr_case(0,1,8,char); + _cimg_load_inr_case(0,0,16,unsigned short); + _cimg_load_inr_case(0,1,16,short); + _cimg_load_inr_case(0,0,32,unsigned int); + _cimg_load_inr_case(0,1,32,int); + _cimg_load_inr_case(1,0,32,float); + _cimg_load_inr_case(1,1,32,float); + _cimg_load_inr_case(1,0,64,double); + _cimg_load_inr_case(1,1,64,double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_inr(): Unknown pixel type defined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a EXR file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_exr(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_exr(): Specified filename is (null).", + cimg_instance); +#if defined(cimg_use_openexr) + Imf::RgbaInputFile file(filename); + Imath::Box2i dw = file.dataWindow(); + const int + inwidth = dw.max.x - dw.min.x + 1, + inheight = dw.max.y - dw.min.y + 1; + Imf::Array2D pixels; + pixels.resizeErase(inheight,inwidth); + file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y*inwidth, 1, inwidth); + file.readPixels(dw.min.y, dw.max.y); + assign(inwidth,inheight,1,4); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + cimg_forXY(*this,x,y) { + *(ptr_r++) = (T)pixels[y][x].r; + *(ptr_g++) = (T)pixels[y][x].g; + *(ptr_b++) = (T)pixels[y][x].b; + *(ptr_a++) = (T)pixels[y][x].a; + } + return *this; +#elif defined(cimg_use_tinyexr) + float *res; + const char *err = 0; + int width = 0, height = 0; + const int ret = LoadEXR(&res,&width,&height,filename,&err); + if (ret) throw CImgIOException(_cimg_instance + "load_exr(): Unable to load EXR file '%s'.", + cimg_instance,filename); + CImg(res,4,width,height,1,true).get_permute_axes("yzcx").move_to(*this); + std::free(res); + return *this; +#else + return load_other(filename); +#endif + } + + //! Load image from a EXR file \newinstance. + static CImg get_load_exr(const char *const filename) { + return CImg().load_exr(filename); + } + + //! Load image from a PANDORE-5 file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pandore(const char *const filename) { + return _load_pandore(0,filename); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(const char *const filename) { + return CImg().load_pandore(filename); + } + + //! Load image from a PANDORE-5 file \overloading. + CImg& load_pandore(std::FILE *const file) { + return _load_pandore(file,0); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(std::FILE *const file) { + return CImg().load_pandore(file); + } + + CImg& _load_pandore(std::FILE *const file, const char *const filename) { +#define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \ + cimg::fread(dims,nbdim,nfile); \ + if (endian) cimg::invert_endianness(dims,nbdim); \ + assign(nwidth,nheight,ndepth,ndim); \ + const size_t siz = size(); \ + stype *buffer = new stype[siz]; \ + cimg::fread(buffer,siz,nfile); \ + if (endian) cimg::invert_endianness(buffer,siz); \ + T *ptrd = _data; \ + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \ + buffer-=siz; \ + delete[] buffer + +#define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \ + if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \ + else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \ + else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \ + else throw CImgIOException(_cimg_instance \ + "load_pandore(): Unknown pixel datatype in file '%s'.", \ + cimg_instance, \ + filename?filename:"(FILE*)"); } + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pandore(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(32); + cimg::fread(header._data,12,nfile); + if (cimg::strncasecmp("PANDORE",header,7)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): PANDORE header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + unsigned int imageid, dims[8] = { 0 }; + int ptbuf[4] = { 0 }; + cimg::fread(&imageid,1,nfile); + const bool endian = imageid>255; + if (endian) cimg::invert_endianness(imageid); + cimg::fread(header._data,20,nfile); + + switch (imageid) { + case 2 : _cimg_load_pandore_case(2,dims[1],1,1,1,unsigned char,unsigned char,unsigned char,1); break; + case 3 : _cimg_load_pandore_case(2,dims[1],1,1,1,long,int,short,4); break; + case 4 : _cimg_load_pandore_case(2,dims[1],1,1,1,double,float,float,4); break; + case 5 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,unsigned char,unsigned char,unsigned char,1); break; + case 6 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,long,int,short,4); break; + case 7 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,double,float,float,4); break; + case 8 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,unsigned char,unsigned char,unsigned char,1); break; + case 9 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,long,int,short,4); break; + case 10 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,double,float,float,4); break; + case 11 : { // Region 1D + cimg::fread(dims,3,nfile); + if (endian) cimg::invert_endianness(dims,3); + assign(dims[1],1,1,1); + const unsigned siz = size(); + if (dims[2]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[2]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 12 : { // Region 2D + cimg::fread(dims,4,nfile); + if (endian) cimg::invert_endianness(dims,4); + assign(dims[2],dims[1],1,1); + const size_t siz = size(); + if (dims[3]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[3]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 13 : { // Region 3D + cimg::fread(dims,5,nfile); + if (endian) cimg::invert_endianness(dims,5); + assign(dims[3],dims[2],dims[1],1); + const size_t siz = size(); + if (dims[4]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[4]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 16 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,unsigned char,unsigned char,unsigned char,1); break; + case 17 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,long,int,short,4); break; + case 18 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,double,float,float,4); break; + case 19 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,unsigned char,unsigned char,unsigned char,1); break; + case 20 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,long,int,short,4); break; + case 21 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,double,float,float,4); break; + case 22 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 23 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],long,int,short,4); break; + case 24 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 25 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],double,float,float,4); break; + case 26 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 27 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],long,int,short,4); break; + case 28 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 29 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],double,float,float,4); break; + case 30 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned char,unsigned char,unsigned char,1); + break; + case 31 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],long,int,short,4); break; + case 32 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned long,unsigned int,unsigned short,4); + break; + case 33 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break; + case 34 : { // Points 1D + cimg::fread(ptbuf,1,nfile); + if (endian) cimg::invert_endianness(ptbuf,1); + assign(1); (*this)(0) = (T)ptbuf[0]; + } break; + case 35 : { // Points 2D + cimg::fread(ptbuf,2,nfile); + if (endian) cimg::invert_endianness(ptbuf,2); + assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0]; + } break; + case 36 : { // Points 3D + cimg::fread(ptbuf,3,nfile); + if (endian) cimg::invert_endianness(ptbuf,3); + assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0]; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): Unable to load data with ID_type %u in file '%s'.", + cimg_instance, + imageid,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PAR-REC (Philips) file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_parrec(const char *const filename, const char axis='c', const float align=0) { + CImgList list; + list.load_parrec(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a PAR-REC (Philips) file \newinstance. + static CImg get_load_parrec(const char *const filename, const char axis='c', const float align=0) { + return CImg().load_parrec(filename,axis,align); + } + + //! Load image from a raw binary file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the image buffer. + \param size_y Height of the image buffer. + \param size_z Depth of the image buffer. + \param size_c Spectrum of the image buffer. + \param is_multiplexed Tells if the image values are multiplexed along the C-axis. + \param invert_endianness Tells if the endianness of the image buffer must be inverted. + \param offset Starting offset of the read in the specified file. + **/ + CImg& load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(0,filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \overloading. + CImg& load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(file,0,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(file,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + CImg& _load_raw(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const bool is_multiplexed, const bool invert_endianness, + const ulongT offset) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename is (null).", + cimg_instance); + if (cimg::is_directory(filename)) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename '%s' is a directory.", + cimg_instance,filename); + const bool is_bool = pixel_type()==cimg::type::string(); + ulongT siz = (ulongT)size_x*size_y*size_z*size_c; + unsigned int + _size_x = size_x, + _size_y = size_y, + _size_z = size_z, + _size_c = size_c; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + if (!siz) { // Retrieve file size + const longT fpos = cimg::ftell(nfile); + if (fpos<0) throw CImgArgumentException(_cimg_instance + "load_raw(): Cannot determine size of input file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + cimg::fseek(nfile,0,SEEK_END); + siz = (ulongT)cimg::ftell(nfile); + if (!is_bool) { siz/=sizeof(T); _size_y = (unsigned int)siz; } + else _size_y = (unsigned int)(siz*8); + _size_x = _size_z = _size_c = 1; + cimg::fseek(nfile,fpos,SEEK_SET); + } + cimg::fseek(nfile,(longT)offset,SEEK_SET); + assign(_size_x,_size_y,_size_z,_size_c,0); + + if (is_bool) { // Boolean data (bitwise) + unsigned char *const buf = new unsigned char[siz]; + cimg::fread(buf,siz,nfile); + _uchar2bool(buf,siz,is_multiplexed); + delete[] buf; + } else { // Non-boolean data + if (siz && (!is_multiplexed || size_c==1)) { // Non-multiplexed + cimg::fread(_data,siz,nfile); + if (invert_endianness) cimg::invert_endianness(_data,siz); + } else if (siz) { // Multiplexed + CImg buf(1,1,1,_size_c); + cimg_forXYZ(*this,x,y,z) { + cimg::fread(buf._data,_size_c,nfile); + if (invert_endianness) cimg::invert_endianness(buf._data,_size_c); + set_vector_at(buf,x,y,z); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image sequence from a YUV file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the frames. + \param size_y Height of the frames. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param yuv2rgb Tells if the YUV to RGB transform must be applied. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + **/ + CImg& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load image sequence from a YUV file \overloading. + CImg& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load 3D object from a .OFF file. + /** + \param[out] primitives Primitives data of the 3D object. + \param[out] colors Colors data of the 3D object. + \param filename Filename, as a C-string. + **/ + template + CImg& load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return _load_off(primitives,colors,0,filename); + } + + //! Load 3D object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return CImg().load_off(primitives,colors,filename); + } + + //! Load 3D object from a .OFF file \overloading. + template + CImg& load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return _load_off(primitives,colors,file,0); + } + + //! Load 3D object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return CImg().load_off(primitives,colors,file); + } + + template + CImg& _load_off(CImgList& primitives, CImgList& colors, + std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_off(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + unsigned int nb_points = 0, nb_primitives = 0, nb_read = 0; + CImg line(256); *line = 0; + int err; + + // Skip comments, and read magic string OFF + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if (cimg::strncasecmp(line,"OFF",3) && cimg::strncasecmp(line,"COFF",4)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): OFF header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%u%u%*[^\n] ",&nb_points,&nb_primitives))!=2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Invalid number of vertices or primitives specified in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read points data + assign(nb_points,3); + float X = 0, Y = 0, Z = 0; + cimg_forX(*this,l) { + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%f%f%f%*[^\n] ",&X,&Y,&Z))!=3) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Failed to read vertex %u/%u in file '%s'.", + cimg_instance, + l + 1,nb_points,filename?filename:"(FILE*)"); + } + (*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z; + } + + // Read primitive data + primitives.assign(); + colors.assign(); + bool stop_flag = false; + while (!stop_flag) { + float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f; + unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0; + *line = 0; + if ((err = std::fscanf(nfile,"%u",&prim))!=1) stop_flag = true; + else { + ++nb_read; + switch (prim) { + case 1 : { + if ((err = std::fscanf(nfile,"%u%255[^\n] ",&i0,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 2 : { + if ((err = std::fscanf(nfile,"%u%u%255[^\n] ",&i0,&i1,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 3 : { + if ((err = std::fscanf(nfile,"%u%u%u%255[^\n] ",&i0,&i1,&i2,line._data))<3) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 4 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,line._data))<4) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 5 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,line._data))<5) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 6 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,line._data))<6) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 7 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i4,i3,i1).move_to(primitives); + CImg::vector(i0,i6,i5,i4).move_to(primitives); + CImg::vector(i3,i2,i1).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + case 8 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + CImg::vector(i0,i7,i6,i5).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + default : + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.", + cimg_instance, + nb_read,nb_primitives,prim,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } + } + } + if (!file) cimg::fclose(nfile); + if (primitives._width!=nb_primitives) + cimg::warn(_cimg_instance + "load_off(): Only %u/%u primitives read from file '%s'.", + cimg_instance, + primitives._width,nb_primitives,filename?filename:"(FILE*)"); + return *this; + } + + //! Load image sequence from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param axis Alignment axis. + \param align Appending alignment. + **/ + CImg& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return get_load_video(filename,first_frame,last_frame,step_frame,axis,align).move_to(*this); + } + + //! Load image sequence from a video file, using OpenCV library \newinstance. + static CImg get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame).get_append(axis,align); + } + + //! Load image sequence using custom's external tool 'custom'. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_custom_external(const char *const filename, const char axis='z', const float align=0) { + return get_load_custom_external(filename,axis,align).move_to(*this); + } + + //! Load image sequence using custom's external tool 'custom' \newinstance. + static CImg get_load_custom_external(const char *const filename, const char axis='z', const float align=0) { + return CImgList().load_custom_external(filename).get_append(axis,align); + } + + //! Load gif file, using Imagemagick or GraphicsMagicks's external tools. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return get_load_gif_external(filename,axis,align).move_to(*this); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tool 'convert' \newinstance. + static CImg get_load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return CImgList().load_gif_external(filename).get_append(axis,align); + } + + //! Load image from a HEIC file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_heif(const char *const filename) { + return _load_heif(filename); + } + + //! Load image from a HEIC file \newinstance. + static CImg get_load_heif(const char *const filename) { + return CImg().load_heif(filename); + } + + CImg& _load_heif(const char *const filename) { +#ifndef cimg_use_heif + return load_other(filename); +#else + try { + heif::Context ctx; + ctx.read_from_file(filename); + + heif::ImageHandle handle = ctx.get_primary_image_handle(); + const heif::Image image = + handle.decode_image(heif_colorspace_RGB,handle.has_alpha_channel()?heif_chroma_interleaved_RGBA: + heif_chroma_interleaved_RGB); + const int + W = image.get_width(heif_channel_interleaved), + H = image.get_height(heif_channel_interleaved), + S = handle.has_alpha_channel()?4:3; + assign(W,H,1,S); + + int stride; + const unsigned char *const buffer = image.get_plane(heif_channel_interleaved,&stride); + T *ptr_r = _data, *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = S>3?data(0,0,0,3):0; + cimg_forY(*this,y) { + const unsigned char *ptrs = buffer + y*stride; + if (ptr_a) cimg_forX(*this,x) { // RGBA + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + else cimg_forX(*this,x) { // RGB + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } catch (const heif::Error& e) { + throw CImgInstanceException(_cimg_instance + "load_heif(): Unable to decode image: %s", + cimg_instance, + e.get_message().c_str()); + } catch (...) { + throw; + } + return *this; +#endif + } + + //! Load image using GraphicsMagick's external tool 'gm'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_graphicsmagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + if (!cimg::system("which gm")) { + cimg_snprintf(command,command._width,"%s convert \"%s\" %s:-", + cimg::graphicsmagick_path(), + s_filename.data(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { +#ifdef cimg_use_png + load_png(file); +#else + load_pnm(file); +#endif + } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' " + "with external command 'gm'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(), + cimg_file_separator, + cimg::filenamerand(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" convert \"%s\" \"%s\"", + cimg::graphicsmagick_path(), + s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::graphicsmagick_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.", + cimg_instance, + filename); + + } else cimg::fclose(file); +#ifdef cimg_use_png + load_png(filename_tmp); +#else + load_pnm(filename_tmp); +#endif + std::remove(filename_tmp); + return *this; + } + + //! Load image using GraphicsMagick's external tool 'gm' \newinstance. + static CImg get_load_graphicsmagick_external(const char *const filename) { + return CImg().load_graphicsmagick_external(filename); + } + + //! Load gzipped image file, using external tool 'gunzip'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimg_instance + "load_gzip_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + const char + *const ext = cimg::split_filename(filename,body), + *const ext2 = cimg::split_filename(body,0); + + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_gzip_external(): Failed to load file '%s' with external command 'gunzip'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load gzipped image file, using external tool 'gunzip' \newinstance. + static CImg get_load_gzip_external(const char *const filename) { + return CImg().load_gzip_external(filename); + } + + //! Load image using ImageMagick's external tool 'convert'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_imagemagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_imagemagick_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + if (!cimg::system("which convert")) { + cimg_snprintf(command,command._width,"%s%s \"%s\" %s:-", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { +#ifdef cimg_use_png + load_png(file); +#else + load_pnm(file); +#endif + } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(), + cimg_file_separator, + cimg::filenamerand(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\"%s \"%s\" \"%s\"", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::imagemagick_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + + } else cimg::fclose(file); +#ifdef cimg_use_png + load_png(filename_tmp); +#else + load_pnm(filename_tmp); +#endif + std::remove(filename_tmp); + return *this; + } + + //! Load image using ImageMagick's external tool 'convert' \newinstance. + static CImg get_load_imagemagick_external(const char *const filename) { + return CImg().load_imagemagick_external(filename); + } + + //! Load image from a DICOM file, using Medcon's external tool 'medcon'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_medcon_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_medcon_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + cimg::fclose(cimg::fopen(filename,"r")); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -w -c anlz -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::medcon_path()); + cimg::split_filename(filename_tmp,body); + + cimg_snprintf(command,command._width,"%s.hdr",body._data); + file = cimg::std_fopen(command,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s.hdr",body._data); + file = cimg::std_fopen(command,"rb"); + if (!file) { + throw CImgIOException(_cimg_instance + "load_medcon_external(): Failed to load file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + load_analyze(command); + std::remove(command); + cimg::split_filename(command,body); + cimg_snprintf(command,command._width,"%s.img",body._data); + std::remove(command); + return *this; + } + + //! Load image from a DICOM file, using Medcon's external tool 'medcon' \newinstance. + static CImg get_load_medcon_external(const char *const filename) { + return CImg().load_medcon_external(filename); + } + + //! Load image from a .pdf file. + /** + \param filename Filename, as a C-string. + \param resolution Image resolution. + **/ + CImg& load_pdf_external(const char *const filename, const unsigned int resolution=400) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_pdf_external(): Specified filename is (null).", + cimg_instance); + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o - -r%u \"%s\"", + resolution,s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_pdf_external(): Failed to load file '%s' with external command 'gs'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o \"%s\" -r%u \"%s\"", + CImg::string(filename_tmp)._system_strescape().data(),resolution,s_filename.data()); + cimg::system(command,"gs"); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_pdf_external(): Failed to load file '%s' with external command 'gs'.", + cimg_instance, + filename); + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a .pdf file \newinstance. + static CImg get_load_pdf_external(const char *const filename, const unsigned int resolution=400) { + return CImg().load_pdf_external(filename,resolution); + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_dcraw_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_dcraw_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"%s -w -4 -c \"%s\"", + cimg::dcraw_path(),s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -w -4 -c \"%s\" > \"%s\"", + cimg::dcraw_path(),s_filename.data(),CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::dcraw_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw' \newinstance. + static CImg get_load_dcraw_external(const char *const filename) { + return CImg().load_dcraw_external(filename); + } + +#ifdef cimg_use_opencv + + // Convert a continuous cv::Mat to a CImg. + static CImg _cvmat2cimg(const cv::Mat &src) { + if (src.channels()==1) return CImg(src.ptr(),src.cols,src.rows,1,1); + else if (src.channels()==3) { // BGR + CImg res(src.cols,src.rows,1,src.channels()); + const unsigned char *ptrs = src.ptr(); + unsigned char *pR = res.data(), *pG = res.data(0,0,0,1), *pB = res.data(0,0,0,2); + cimg_forXY(res,x,y) { *(pB++) = *(ptrs++); *(pG++) = *(ptrs++); *(pR++) = *(ptrs++); } + return res; + } + return CImg(src.ptr(),src.channels(),src.cols,src.rows,1,true).get_permute_axes("yzcx"); + } + + // Convert a CImg to a cv::Mat. + cv::Mat _cimg2cvmat() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Instance image is empty.", + cimg_instance); + if (_spectrum==2) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Invalid number of channels (should be '1' or '3+').", + cimg_instance); + if (_depth!=1) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Invalid number of slices (should be '1').", + cimg_instance); + int mat_type = -1; + if (pixel_type()==cimg::type::string()) mat_type = CV_8UC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_8SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_16UC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_16SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_32SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_32FC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_64FC1; + if (mat_type<0) + throw CImgInstanceException(_cimg_instance + "_cvmat2cimg() : pixel type '%s' is not supported.", + cimg_instance,pixel_type()); + cv::Mat res; + std::vector channels(_spectrum); + if (_spectrum>1) { + cimg_forC(*this,c) + channels[c] = cv::Mat(_height,_width,mat_type,_data + _width*_height*(_spectrum - 1 - c)); + cv::merge(channels,res); + } else res = cv::Mat(_height,_width,mat_type,_data).clone(); + return res; + } + +#endif + + //! Load image from a camera stream, using OpenCV. + /** + \param index Index of the camera to capture images from (from 0 to 63). + \param capture_width Width of the desired image ('0' stands for default value). + \param capture_height Height of the desired image ('0' stands for default value). + \param skip_frames Number of frames to skip before the capture. + \param release_camera Tells if the camera resource must be released at the end of the method. + **/ + CImg& load_camera(const unsigned int camera_index=0, + const unsigned int capture_width=0, const unsigned int capture_height=0, + const unsigned int skip_frames=0, const bool release_camera=true) { +#ifdef cimg_use_opencv + if (camera_index>=64) + throw CImgArgumentException(_cimg_instance + "load_camera(): Invalid request for camera #%u " + "(no more than 100 cameras can be managed simultaneously).", + cimg_instance, + camera_index); + static cv::VideoCapture *captures[64] = { 0 }; + static unsigned int captures_w[64], captures_h[64]; + if (release_camera) { + cimg::mutex(9); + if (captures[camera_index]) captures[camera_index]->release(); + delete captures[camera_index]; + captures[camera_index] = 0; + captures_w[camera_index] = captures_h[camera_index] = 0; + cimg::mutex(9,0); + return *this; + } + if (!captures[camera_index]) { + cimg::mutex(9); + captures[camera_index] = new cv::VideoCapture(camera_index); + captures_w[camera_index] = captures_h[camera_index] = 0; + if (!captures[camera_index]->isOpened()) { + delete captures[camera_index]; + captures[camera_index] = 0; + cimg::mutex(9,0); + throw CImgIOException(_cimg_instance + "load_camera(): Failed to initialize camera #%u.", + cimg_instance, + camera_index); + } + cimg::mutex(9,0); + } + cimg::mutex(9); + if (capture_width!=captures_w[camera_index]) { + captures[camera_index]->set(_cimg_cap_prop_frame_width,capture_width); + captures_w[camera_index] = capture_width; + } + if (capture_height!=captures_h[camera_index]) { + captures[camera_index]->set(_cimg_cap_prop_frame_height,capture_height); + captures_h[camera_index] = capture_height; + } + for (unsigned int i = 0; igrab(); + cv::Mat cvimg; + captures[camera_index]->read(cvimg); + if (cvimg.empty()) assign(); else _cvmat2cimg(cvimg).move_to(*this); + cimg::mutex(9,0); + return *this; +#else + cimg::unused(camera_index,skip_frames,release_camera,capture_width,capture_height); + throw CImgIOException(_cimg_instance + "load_camera(): This function requires features from the OpenCV library " + "('-Dcimg_use_opencv' must be defined).", + cimg_instance); +#endif + } + + //! Load image from a camera stream, using OpenCV \newinstance. + static CImg get_load_camera(const unsigned int camera_index=0, + const unsigned int capture_width=0, const unsigned int capture_height=0, + const unsigned int skip_frames=0, const bool release_camera=true) { + return CImg().load_camera(camera_index,capture_width,capture_height,skip_frames,release_camera); + } + + //! Load image using various non-native ways. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_other(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_other(): Specified filename is (null).", + cimg_instance); + + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_magick(filename); } + catch (CImgException&) { + try { load_imagemagick_external(filename); } + catch (CImgException&) { + try { load_graphicsmagick_external(filename); } + catch (CImgException&) { + try { load_cimg(filename); } + catch (CImgException&) { + try { + cimg::fclose(cimg::fopen(filename,"rb")); + } catch (CImgException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to open file '%s'.", + cimg_instance, + filename); + } + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image using various non-native ways \newinstance. + static CImg get_load_other(const char *const filename) { + return CImg().load_other(filename); + } + + //@} + //--------------------------- + // + //! \name Data Output + //@{ + //--------------------------- + + //! Display information about the image data. + /** + \param title Name for the considered image. + \param display_stats Tells to compute and display image statistics. + **/ + const CImg& print(const char *const title=0, const bool display_stats=true) const { + + int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0; + CImg st; + if (!is_empty() && display_stats) { + st = get_stats(); + xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7]; + xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11]; + } + + const ulongT siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1, + mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U, width1 = _width - 1; + + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImg<%s>",pixel_type()); + + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p", + cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal, + cimg::t_bold,cimg::t_normal,(void*)this, + cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum, + (unsigned long)(mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20))), + mdisp==0?"b":(mdisp==1?"Kio":"Mio"), + cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin()); + if (_data) + std::fprintf(cimg::output(),"..%p (%s) = [ ",(void*)((char*)end() - 1),_is_shared?"shared":"non-shared"); + else std::fprintf(cimg::output()," (%s) = [ ",_is_shared?"shared":"non-shared"); + + if (!is_empty()) cimg_foroff(*this,off) { + std::fprintf(cimg::output(),"%g",(double)_data[off]); + if (off!=siz1) std::fprintf(cimg::output(),"%s",off%_width==width1?" ; ":" "); + if (off==7 && siz>16) { off = siz1 - 8; std::fprintf(cimg::output(),"... "); } + } + if (!is_empty() && display_stats) + std::fprintf(cimg::output(), + " ], %smin%s = %g, %smax%s = %g, %smean%s = %g, %sstd%s = %g, %scoords_min%s = (%u,%u,%u,%u), " + "%scoords_max%s = (%u,%u,%u,%u).\n", + cimg::t_bold,cimg::t_normal,st[0], + cimg::t_bold,cimg::t_normal,st[1], + cimg::t_bold,cimg::t_normal,st[2], + cimg::t_bold,cimg::t_normal,std::sqrt(st[3]), + cimg::t_bold,cimg::t_normal,xm,ym,zm,vm, + cimg::t_bold,cimg::t_normal,xM,yM,zM,vM); + else std::fprintf(cimg::output(),"%s].\n",is_empty()?"":" "); + std::fflush(cimg::output()); + return *this; + } + + //! Display image into a CImgDisplay window. + /** + \param disp Display window. + **/ + const CImg& display(CImgDisplay& disp) const { + disp.display(*this); + return *this; + } + + //! Display image into a CImgDisplay window, in an interactive way. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + return _display(disp,0,display_info,XYZ,exit_on_anykey,false); + } + + //! Display image into an interactive window. + /** + \param title Window title + \param display_info Tells if image information are displayed on the standard output. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display(disp,title,display_info,XYZ,exit_on_anykey,false); + } + + const CImg& _display(CImgDisplay &disp, const char *const title, const bool display_info, + unsigned int *const XYZ, const bool exit_on_anykey, + const bool exit_on_singleclick) const { + unsigned int oldw = 0, oldh = 0, _XYZ[3] = { 0 }, key = 0; + int x0 = 0, y0 = 0, z0 = 0, x1 = width() - 1, y1 = height() - 1, z1 = depth() - 1, + old_mouse_x = -1, old_mouse_y = -1; + + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + else disp.set_title("%s",title); + } else if (title) disp.set_title("%s",title); + disp.show().flush(); + + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(dtitle); + + CImg zoom; + for (bool reset_view = true, resize_disp = false, is_first_select = true; !key && !disp.is_closed(); ) { + if (reset_view) { + if (XYZ) { _XYZ[0] = XYZ[0]; _XYZ[1] = XYZ[1]; _XYZ[2] = XYZ[2]; } + else { + _XYZ[0] = (unsigned int)(x0 + x1 + 1)/2; + _XYZ[1] = (unsigned int)(y0 + y1 + 1)/2; + _XYZ[2] = (unsigned int)(z0 + z1 + 1)/2; + } + x0 = 0; y0 = 0; z0 = 0; x1 = width() - 1; y1 = height() - 1; z1 = depth() - 1; + disp.resize(cimg_fitscreen(_width,_height,_depth),false); + oldw = disp._width; oldh = disp._height; + resize_disp = true; + reset_view = false; + } + if (!x0 && !y0 && !z0 && x1==width() - 1 && y1==height() - 1 && z1==depth() - 1) { + if (is_empty()) zoom.assign(1,1,1,1,(T)0); else zoom.assign(); + } else zoom = get_crop(x0,y0,z0,x1,y1,z1); + + const CImg& visu = zoom?zoom:*this; + const unsigned int + dx = 1U + x1 - x0, dy = 1U + y1 - y0, dz = 1U + z1 - z0, + tw = dx + (dz>1?dz:0U), th = dy + (dz>1?dz:0U); + if (!is_empty() && !disp.is_fullscreen() && resize_disp) { + const float + ttw = (float)tw*disp.width()/oldw, tth = (float)th*disp.height()/oldh, + dM = std::max(ttw,tth), diM = (float)std::max(disp.width(),disp.height()); + const unsigned int + imgw = (unsigned int)(ttw*diM/dM), imgh = (unsigned int)(tth*diM/dM); + disp.set_fullscreen(false).resize(cimg_fitscreen(imgw,imgh,1),false); + resize_disp = false; + } + oldw = tw; oldh = th; + + bool + go_up = false, go_down = false, go_left = false, go_right = false, + go_inc = false, go_dec = false, go_in = false, go_out = false, + go_in_center = false; + + disp.set_title("%s",dtitle._data); + if (_width>1 && visu._width==1) disp.set_title("%s | x=%u",disp._title,x0); + if (_height>1 && visu._height==1) disp.set_title("%s | y=%u",disp._title,y0); + if (_depth>1 && visu._depth==1) disp.set_title("%s | z=%u",disp._title,z0); + + disp._mouse_x = old_mouse_x; disp._mouse_y = old_mouse_y; + CImg selection = visu._select(disp,0,2,_XYZ,x0,y0,z0,true,is_first_select,_depth>1,true); + old_mouse_x = disp._mouse_x; old_mouse_y = disp._mouse_y; + is_first_select = false; + + if (disp.wheel()) { + if ((disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) && + (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT())) { + go_left = !(go_right = disp.wheel()>0); + } else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) { + go_down = !(go_up = disp.wheel()>0); + } else if (depth()==1 || disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + go_out = !(go_in = disp.wheel()>0); go_in_center = false; + } + disp.set_wheel(); + } + + const int + sx0 = selection(0), sy0 = selection(1), sz0 = selection(2), + sx1 = selection(3), sy1 = selection(4), sz1 = selection(5); + if (sx0>=0 && sy0>=0 && sz0>=0 && sx1>=0 && sy1>=0 && sz1>=0) { + x1 = x0 + sx1; y1 = y0 + sy1; z1 = z0 + sz1; + x0+=sx0; y0+=sy0; z0+=sz0; + if ((sx0==sx1 && sy0==sy1) || (_depth>1 && sx0==sx1 && sz0==sz1) || (_depth>1 && sy0==sy1 && sz0==sz1)) { + if (exit_on_singleclick && (!zoom || is_empty())) break; else reset_view = true; + } + resize_disp = true; + } else switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : key = 0; break; + case cimg::keyP : if (visu._depth>1 && (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT())) { + // Special mode: play stack of frames + const unsigned int + w1 = visu._width*disp.width()/(visu._width + (visu._depth>1?visu._depth:0)), + h1 = visu._height*disp.height()/(visu._height + (visu._depth>1?visu._depth:0)); + float frame_timing = 5; + bool is_stopped = false; + disp.set_key(key,false).set_wheel().resize(cimg_fitscreen(w1,h1,1),false); key = 0; + for (unsigned int timer = 0; !key && !disp.is_closed() && !disp.button(); ) { + if (disp.is_resized()) disp.resize(false); + if (!timer) { + visu.get_slice((int)_XYZ[2]).display(disp.set_title("%s | z=%d",dtitle.data(),_XYZ[2])); + (++_XYZ[2])%=visu._depth; + } + if (!is_stopped) { if (++timer>(unsigned int)frame_timing) timer = 0; } else timer = ~0U; + if (disp.wheel()) { frame_timing-=disp.wheel()/3.f; disp.set_wheel(); } + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : frame_timing-=0.3f; key = 0; break; + case cimg::keyPAGEDOWN : frame_timing+=0.3f; key = 0; break; + case cimg::keySPACE : is_stopped = !is_stopped; disp.set_key(key,false); key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyARROWUP : is_stopped = true; timer = 0; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyARROWDOWN : is_stopped = true; + (_XYZ[2]+=visu._depth - 2)%=visu._depth; timer = 0; key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false).set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(_width,_height,_depth),false).set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false). + toggle_fullscreen().set_key(key,false); key = 0; + } break; + } + frame_timing = frame_timing<1?1:(frame_timing>39?39:frame_timing); + disp.wait(20); + } + const unsigned int + w2 = (visu._width + (visu._depth>1?visu._depth:0))*disp.width()/visu._width, + h2 = (visu._height + (visu._depth>1?visu._depth:0))*disp.height()/visu._height; + disp.resize(cimg_fitscreen(w2,h2,1),false).set_title(dtitle.data()).set_key().set_button().set_wheel(); + key = 0; + } break; + case cimg::keyHOME : reset_view = resize_disp = true; key = 0; break; + case cimg::keyPADADD : go_in = true; go_in_center = true; key = 0; break; + case cimg::keyPADSUB : go_out = true; key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyPAD4: go_left = true; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6: go_right = true; key = 0; break; + case cimg::keyARROWUP : case cimg::keyPAD8: go_up = true; key = 0; break; + case cimg::keyARROWDOWN : case cimg::keyPAD2: go_down = true; key = 0; break; + case cimg::keyPAD7 : go_up = go_left = true; key = 0; break; + case cimg::keyPAD9 : go_up = go_right = true; key = 0; break; + case cimg::keyPAD1 : go_down = go_left = true; key = 0; break; + case cimg::keyPAD3 : go_down = go_right = true; key = 0; break; + case cimg::keyPAGEUP : go_inc = true; key = 0; break; + case cimg::keyPAGEDOWN : go_dec = true; key = 0; break; + } + if (go_in) { + const int + mx = go_in_center?disp.width()/2:disp.mouse_x(), + my = go_in_center?disp.height()/2:disp.mouse_y(), + mX = mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my*(height() + (depth()>1?depth():0))/disp.height(); + int X = (int)_XYZ[0], Y = (int)_XYZ[1], Z = (int)_XYZ[2]; + if (mX=height()) { + X = x0 + mX*(1 + x1 - x0)/width(); Z = z0 + (mY - height())*(1 + z1 - z0)/depth(); + } + if (mX>=width() && mY4) { x0 = X - 3*(X - x0)/4; x1 = X + 3*(x1 - X)/4; } + if (y1 - y0>4) { y0 = Y - 3*(Y - y0)/4; y1 = Y + 3*(y1 - Y)/4; } + if (z1 - z0>4) { z0 = Z - 3*(Z - z0)/4; z1 = Z + 3*(z1 - Z)/4; } + } + if (go_out) { + const int + delta_x = (x1 - x0)/8, delta_y = (y1 - y0)/8, delta_z = (z1 - z0)/8, + ndelta_x = delta_x?delta_x:(_width>1), + ndelta_y = delta_y?delta_y:(_height>1), + ndelta_z = delta_z?delta_z:(_depth>1); + x0-=ndelta_x; y0-=ndelta_y; z0-=ndelta_z; + x1+=ndelta_x; y1+=ndelta_y; z1+=ndelta_z; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=width()) x1 = width() - 1; } + if (y0<0) { y1-=y0; y0 = 0; if (y1>=height()) y1 = height() - 1; } + if (z0<0) { z1-=z0; z0 = 0; if (z1>=depth()) z1 = depth() - 1; } + if (x1>=width()) { x0-=(x1 - width() + 1); x1 = width() - 1; if (x0<0) x0 = 0; } + if (y1>=height()) { y0-=(y1 - height() + 1); y1 = height() - 1; if (y0<0) y0 = 0; } + if (z1>=depth()) { z0-=(z1 - depth() + 1); z1 = depth() - 1; if (z0<0) z0 = 0; } + const float + ratio = (float)(x1-x0)/(y1-y0), + ratiow = (float)disp._width/disp._height, + sub = std::min(cimg::abs(ratio - ratiow),cimg::abs(1/ratio-1/ratiow)); + if (sub>0.01) resize_disp = true; + } + if (go_left) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + } + if (go_right) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x1+ndelta1); + if (y0 - ndelta>=0) { y0-=ndelta; y1-=ndelta; } + else { y1-=y0; y0 = 0; } + } + if (go_down) { + const int delta = (y1 - y0)/4, ndelta = delta?delta:(_height>1); + if (y1+ndelta1); + if (z0 - ndelta>=0) { z0-=ndelta; z1-=ndelta; } + else { z1-=z0; z0 = 0; } + } + if (go_dec) { + const int delta = (z1 - z0)/4, ndelta = delta?delta:(_depth>1); + if (z1+ndelta + const CImg& display_object3d(CImgDisplay& disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return _display_object3d(disp,0,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + template + const CImg& _display_object3d(CImgDisplay& disp, const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering, + const int render_static, const int render_motion, + const bool is_double_sided, const float focale, + const float light_x, const float light_y, const float light_z, + const float specular_lightness, const float specular_shininess, + const bool display_axes, float *const pose_matrix, + const bool exit_on_anykey) const { + typedef typename cimg::superset::type tpfloat; + + // Check input arguments + if (is_empty()) { + CImg background; + if (colors && colors[0].size()==1) background.assign(1,2,1,1,64,128); + else background.assign(1,2,1,3,32,64,32,116,64,96); + if (disp) background.resize(disp.width(),disp.height(),1,-100,3); + else background.resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),1,-100,3); + return background._display_object3d(disp,title,vertices,primitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } else { if (disp) disp.resize(*this,false); } + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgArgumentException(_cimg_instance + "display_object3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); + if (vertices._width && !primitives) { + CImgList nprimitives(vertices._width,1,1,1,1); + cimglist_for(nprimitives,l) nprimitives(l,0) = (tf)l; + return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3); + if (!title) disp.set_title("CImg<%s> (%u vertices, %u primitives)", + pixel_type(),vertices._width,primitives._width); + } else if (title) disp.set_title("%s",title); + + // Init 3D objects and compute object statistics + CImg + pose, + rotated_vertices(vertices._width,3), + bbox_vertices, rotated_bbox_vertices, + axes_vertices, rotated_axes_vertices, + bbox_opacities, axes_opacities; + CImgList bbox_primitives, axes_primitives; + CImgList reverse_primitives; + CImgList bbox_colors, bbox_colors2, axes_colors; + unsigned int ns_width = 0, ns_height = 0; + int _is_double_sided = (int)is_double_sided; + bool ndisplay_axes = display_axes; + const CImg + background_color(1,1,1,_spectrum,0), + foreground_color(1,1,1,_spectrum,(T)std::min((int)cimg::type::max(),255)); + float + Xoff = 0, Yoff = 0, Zoff = 0, sprite_scale = 1, + xm = 0, xM = vertices?vertices.get_shared_row(0).max_min(xm):0, + ym = 0, yM = vertices?vertices.get_shared_row(1).max_min(ym):0, + zm = 0, zM = vertices?vertices.get_shared_row(2).max_min(zm):0; + const float delta = cimg::max(xM - xm,yM - ym,zM - zm); + + rotated_bbox_vertices = bbox_vertices.assign(8,3,1,1, + xm,xM,xM,xm,xm,xM,xM,xm, + ym,ym,yM,yM,ym,ym,yM,yM, + zm,zm,zm,zm,zM,zM,zM,zM); + bbox_primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 1,2,6,5, 0,4,7,3, 0,1,5,4, 2,3,7,6); + bbox_colors.assign(6,_spectrum,1,1,1,background_color[0]); + bbox_colors2.assign(6,_spectrum,1,1,1,foreground_color[0]); + bbox_opacities.assign(bbox_colors._width,1,1,1,0.3f); + + rotated_axes_vertices = axes_vertices.assign(7,3,1,1, + 0,20,0,0,22,-6,-6, + 0,0,20,0,-6,22,-6, + 0,0,0,20,0,0,22); + axes_opacities.assign(3,1,1,1,1); + axes_colors.assign(3,_spectrum,1,1,1,foreground_color[0]); + axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3); + + // Begin user interaction loop + CImg visu0(*this,false), visu; + CImg zbuffer(visu0.width(),visu0.height(),1,1,0); + bool init_pose = true, clicked = false, redraw = true; + unsigned int key = 0, font_size = 32; + int + x0 = 0, y0 = 0, x1 = 0, y1 = 0, + nrender_static = render_static, + nrender_motion = render_motion; + disp.show().flush(); + + while (!disp.is_closed() && !key) { + + // Init object pose + if (init_pose) { + const float + ratio = delta>0?(2.f*std::min(disp.width(),disp.height())/(3.f*delta)):1, + dx = (xM + xm)/2, dy = (yM + ym)/2, dz = (zM + zm)/2; + if (centering) + CImg(4,3,1,1, ratio,0.,0.,-ratio*dx, 0.,ratio,0.,-ratio*dy, 0.,0.,ratio,-ratio*dz).move_to(pose); + else CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose); + if (pose_matrix) { + CImg pose0(pose_matrix,4,3,1,1,false); + pose0.resize(4,4,1,1,0); pose.resize(4,4,1,1,0); + pose0(3,3) = pose(3,3) = 1; + (pose0*pose).get_crop(0,0,3,2).move_to(pose); + Xoff = pose_matrix[12]; Yoff = pose_matrix[13]; Zoff = pose_matrix[14]; sprite_scale = pose_matrix[15]; + } else { Xoff = Yoff = Zoff = 0; sprite_scale = 1; } + init_pose = false; + redraw = true; + } + + // Rotate and draw 3D object + if (redraw) { + const float + r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0), + r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1), + r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2); + if ((clicked && nrender_motion>=0) || (!clicked && nrender_static>=0)) { + const tp *const pv0 = vertices.data(), *const pv1 = vertices.data(0,1), *const pv2 = vertices.data(0,2); + float + *const prv0 = rotated_vertices.data(), + *const prv1 = rotated_vertices.data(0,1), + *const prv2 = rotated_vertices.data(0,2); + cimg_pragma_openmp(parallel for cimg_openmp_if(vertices.width()>(cimg_openmp_sizefactor)*1024)) + cimg_forX(vertices,l) { + const float x = (float)pv0[l], y = (float)pv1[l], z = (float)pv2[l]; + prv0[l] = r00*x + r10*y + r20*z + r30; + prv1[l] = r01*x + r11*y + r21*z + r31; + prv2[l] = r02*x + r12*y + r22*z + r32; + } + } + else cimg_forX(bbox_vertices,l) { + const float x = bbox_vertices(l,0), y = bbox_vertices(l,1), z = bbox_vertices(l,2); + rotated_bbox_vertices(l,0) = r00*x + r10*y + r20*z + r30; + rotated_bbox_vertices(l,1) = r01*x + r11*y + r21*z + r31; + rotated_bbox_vertices(l,2) = r02*x + r12*y + r22*z + r32; + } + + // Draw objects + const bool render_with_zbuffer = !clicked && nrender_static>0; + visu = visu0; + if ((clicked && nrender_motion<0) || (!clicked && nrender_static<0)) + visu.draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors,bbox_opacities,2,false,focale). + draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors2,1,false,focale); + else visu._draw_object3d((void*)0,render_with_zbuffer?zbuffer.fill(0):CImg::empty(), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static,_is_double_sided==1,focale, + width()/2.f + light_x,height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1,sprite_scale); + // Draw axes + if (ndisplay_axes) { + const float + n = 1e-8f + cimg::hypot(r00,r01,r02), + _r00 = r00/n, _r10 = r10/n, _r20 = r20/n, + _r01 = r01/n, _r11 = r11/n, _r21 = r21/n, + _r02 = r01/n, _r12 = r12/n, _r22 = r22/n, + Xaxes = 25, Yaxes = visu._height - 38.f; + cimg_forX(axes_vertices,l) { + const float + x = axes_vertices(l,0), + y = axes_vertices(l,1), + z = axes_vertices(l,2); + rotated_axes_vertices(l,0) = _r00*x + _r10*y + _r20*z; + rotated_axes_vertices(l,1) = _r01*x + _r11*y + _r21*z; + rotated_axes_vertices(l,2) = _r02*x + _r12*y + _r22*z; + } + axes_opacities(0,0) = (rotated_axes_vertices(1,2)>0)?0.5f:1.f; + axes_opacities(1,0) = (rotated_axes_vertices(2,2)>0)?0.5f:1.f; + axes_opacities(2,0) = (rotated_axes_vertices(3,2)>0)?0.5f:1.f; + visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_vertices,axes_primitives, + axes_colors,axes_opacities,1,false,focale). + draw_text((int)(Xaxes + rotated_axes_vertices(4,0)), + (int)(Yaxes + rotated_axes_vertices(4,1)), + "X",axes_colors[0]._data,0,axes_opacities(0,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(5,0)), + (int)(Yaxes + rotated_axes_vertices(5,1)), + "Y",axes_colors[1]._data,0,axes_opacities(1,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(6,0)), + (int)(Yaxes + rotated_axes_vertices(6,1)), + "Z",axes_colors[2]._data,0,axes_opacities(2,0),13); + } + visu.display(disp); + if (!clicked || nrender_motion==nrender_static) redraw = false; + } + + // Handle user interaction + if (!redraw) disp.wait(); + if ((disp.button() || disp.wheel()) && disp.mouse_x()>=0 && disp.mouse_y()>=0) { + redraw = true; + if (!clicked) { x0 = x1 = disp.mouse_x(); y0 = y1 = disp.mouse_y(); if (!disp.wheel()) clicked = true; } + else { x1 = disp.mouse_x(); y1 = disp.mouse_y(); } + const bool is_keyCTRL = disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT(); + if (disp.button()&1 && !is_keyCTRL) { + const float + R = 0.45f*std::min(disp.width(),disp.height()), + R2 = R*R, + u0 = (float)(x0 - disp.width()/2), + v0 = (float)(y0 - disp.height()/2), + u1 = (float)(x1 - disp.width()/2), + v1 = (float)(y1 - disp.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + (CImg::rotation_matrix(u,v,w,-alpha)*pose).move_to(pose); + x0 = x1; y0 = y1; + } + if (disp.button()&2 && !is_keyCTRL) { + if (focale>0) Zoff-=(y0 - y1)*focale/400; + else { const float s = std::exp((y0 - y1)/400.f); pose*=s; sprite_scale*=s; } + x0 = x1; y0 = y1; + } + if (disp.wheel()) { + if (focale>0) Zoff-=disp.wheel()*focale/20; + else { const float s = std::exp(disp.wheel()/20.f); pose*=s; sprite_scale*=s; } + disp.set_wheel(); + } + if (disp.button()&4 || (disp.button()&1 && is_keyCTRL)) { + Xoff+=(x1 - x0); Yoff+=(y1 - y0); x0 = x1; y0 = y1; + } + if ((disp.button()&1) && (disp.button()&2) && !is_keyCTRL) { + init_pose = true; disp.set_button(); x0 = x1; y0 = y1; + pose = CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0); + } + } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; } + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD: if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + if (!ns_width || !ns_height || + ns_width>(unsigned int)disp.screen_width() || ns_height>(unsigned int)disp.screen_height()) { + ns_width = disp.screen_width()*3U/4; + ns_height = disp.screen_height()*3U/4; + } + if (disp.is_fullscreen()) disp.resize(ns_width,ns_height,false); + else { + ns_width = disp._width; ns_height = disp._height; + disp.resize(disp.screen_width(),disp.screen_height(),false); + } + disp.toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyT : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Switch single/double-sided primitives. + if (--_is_double_sided==-2) _is_double_sided = 1; + if (_is_double_sided>=0) reverse_primitives.assign(); + else primitives.get_reverse_object3d().move_to(reverse_primitives); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyZ : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Enable/disable Z-buffer + if (zbuffer) zbuffer.assign(); + else zbuffer.assign(visu0.width(),visu0.height(),1,1,0); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Show/hide 3D axes + ndisplay_axes = !ndisplay_axes; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF1 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to points + nrender_motion = (nrender_static==0 && nrender_motion!=0)?0:-1; nrender_static = 0; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF2 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to lines + nrender_motion = (nrender_static==1 && nrender_motion!=1)?1:-1; nrender_static = 1; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF3 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat + nrender_motion = (nrender_static==2 && nrender_motion!=2)?2:-1; nrender_static = 2; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF4 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat-shaded + nrender_motion = (nrender_static==3 && nrender_motion!=3)?3:-1; nrender_static = 3; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF5 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Set rendering mode to gouraud-shaded. + nrender_motion = (nrender_static==4 && nrender_motion!=4)?4:-1; nrender_static = 4; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF6 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to phong-shaded + nrender_motion = (nrender_static==5 && nrender_motion!=5)?5:-1; nrender_static = 5; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save snapshot + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving snapshot... ",font_size,0).display(disp); + visu.save(filename); + (+visu).__draw_text(" Snapshot '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyG : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .off file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.off",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving object... ",font_size,0).display(disp); + vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .cimg file + static unsigned int snap_number = 0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving object... ",font_size,0).display(disp); + vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities). + save(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + +#ifdef cimg_use_board + case cimg::keyP : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .EPS file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.eps",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving EPS snapshot... ",font_size,0).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1, + sprite_scale); + board.saveEPS(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .SVG file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.svg",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving SVG snapshot... ",font_size,0).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1, + sprite_scale); + board.saveSVG(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; +#endif + } + if (disp.is_resized()) { + disp.resize(false); visu0 = get_resize(disp,1); + if (zbuffer) zbuffer.assign(disp.width(),disp.height()); + redraw = true; + } + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + if (pose_matrix) { + std::memcpy(pose_matrix,pose._data,12*sizeof(float)); + pose_matrix[12] = Xoff; pose_matrix[13] = Yoff; pose_matrix[14] = Zoff; pose_matrix[15] = sprite_scale; + } + disp.set_button().set_key(key); + return *this; + } + + //! Display 1D graph in an interactive window. + /** + \param disp Display window. + \param plot_type Plot type. Can be { 0=points | 1=segments | 2=splines | 3=bars }. + \param vertex_type Vertex type. + \param labelx Title for the horizontal axis, as a C-string. + \param xmin Minimum value along the X-axis. + \param xmax Maximum value along the X-axis. + \param labely Title for the vertical axis, as a C-string. + \param ymin Minimum value along the X-axis. + \param ymax Maximum value along the X-axis. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + //! Display 1D graph in an interactive window \overloading. + const CImg& display_graph(const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + const CImg& _display_graph(CImgDisplay &disp, const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "display_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title(title?"%s":"CImg<%s>",title?title:pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth, siz1 = std::max((ulongT)1,siz - 1); + const unsigned int old_normalization = disp.normalization(); + disp.show().flush()._normalization = 0; + + double y0 = ymin, y1 = ymax, nxmin = xmin, nxmax = xmax; + if (nxmin==nxmax) { nxmin = 0; nxmax = siz1; } + int x0 = 0, x1 = width()*height()*depth() - 1, key = 0; + + for (bool reset_view = true; !key && !disp.is_closed(); ) { + if (reset_view) { x0 = 0; x1 = width()*height()*depth() - 1; y0 = ymin; y1 = ymax; reset_view = false; } + CImg zoom(x1 - x0 + 1,1,1,spectrum()); + cimg_forC(*this,c) zoom.get_shared_channel(c) = CImg(data(x0,0,0,c),x1 - x0 + 1,1,1,1,true); + if (y0==y1) { y0 = zoom.min_max(y1); const double dy = y1 - y0; y0-=dy/20; y1+=dy/20; } + if (y0==y1) { --y0; ++y1; } + + const CImg selection = zoom.get_select_graph(disp,plot_type,vertex_type, + labelx, + nxmin + x0*(nxmax - nxmin)/siz1, + nxmin + x1*(nxmax - nxmin)/siz1, + labely,y0,y1,true); + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + if (selection[0]>=0) { + if (selection[2]<0) reset_view = true; + else { + x1 = x0 + selection[2]; x0+=selection[0]; + if (selection[1]>=0 && selection[3]>=0) { + y0 = y1 - selection[3]*(y1 - y0)/(disp.height() - 32); + y1-=selection[1]*(y1 - y0)/(disp.height() - 32); + } + } + } else { + bool go_in = false, go_out = false, go_left = false, go_right = false, go_up = false, go_down = false; + switch (key = (int)disp.key()) { + case cimg::keyHOME : reset_view = true; key = 0; disp.set_key(); break; + case cimg::keyPADADD : go_in = true; go_out = false; key = 0; disp.set_key(); break; + case cimg::keyPADSUB : go_out = true; go_in = false; key = 0; disp.set_key(); break; + case cimg::keyARROWLEFT : case cimg::keyPAD4 : go_left = true; go_right = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6 : go_right = true; go_left = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWUP : case cimg::keyPAD8 : go_up = true; go_down = false; key = 0; disp.set_key(); break; + case cimg::keyARROWDOWN : case cimg::keyPAD2 : go_down = true; go_up = false; key = 0; disp.set_key(); break; + case cimg::keyPAD7 : go_left = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD9 : go_right = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD1 : go_left = true; go_down = true; key = 0; disp.set_key(); break; + case cimg::keyPAD3 : go_right = true; go_down = true; key = 0; disp.set_key(); break; + } + if (disp.wheel()) { + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_up = !(go_down = disp.wheel()<0); + else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) go_left = !(go_right = disp.wheel()>0); + else go_out = !(go_in = disp.wheel()>0); + key = 0; + } + + if (go_in) { + const int + xsiz = x1 - x0, + mx = (mouse_x - 16)*xsiz/(disp.width() - 32), + cx = x0 + cimg::cut(mx,0,xsiz); + if (x1 - x0>4) { + x0 = cx - 7*(cx - x0)/8; x1 = cx + 7*(x1 - cx)/8; + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + const double + ysiz = y1 - y0, + my = (mouse_y - 16)*ysiz/(disp.height() - 32), + cy = y1 - cimg::cut(my,0.,ysiz); + y0 = cy - 7*(cy - y0)/8; y1 = cy + 7*(y1 - cy)/8; + } else y0 = y1 = 0; + } + } + if (go_out) { + if (x0>0 || x1<(int)siz1) { + const int delta_x = (x1 - x0)/8, ndelta_x = delta_x?delta_x:(siz>1); + const double ndelta_y = (y1 - y0)/8; + x0-=ndelta_x; x1+=ndelta_x; + y0-=ndelta_y; y1+=ndelta_y; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=(int)siz) x1 = (int)siz1; } + if (x1>=(int)siz) { x0-=(x1 - siz1); x1 = (int)siz1; if (x0<0) x0 = 0; } + } + } + if (go_left) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + go_left = false; + } + if (go_right) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x1 + ndelta<(int)siz) { x0+=ndelta; x1+=ndelta; } + else { x0+=(siz1 - x1); x1 = (int)siz1; } + go_right = false; + } + if (go_up) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0+=ndelta; y1+=ndelta; + go_up = false; + } + if (go_down) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0-=ndelta; y1-=ndelta; + go_down = false; + } + } + if (!exit_on_anykey && key && key!=(int)cimg::keyESC && + (key!=(int)cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + key = 0; + } + } + disp._normalization = old_normalization; + return *this; + } + + //! Save image as a file. + /** + \param filename Filename, as a C-string. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + \note + - The used file format is defined by the file extension in the filename \p filename. + - Parameter \p number can be used to add a 6-digit number to the filename before saving. + + **/ + const CImg& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save(): Specified filename is (null).", + cimg_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:(number>=0)?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimg_save_plugin + cimg_save_plugin(fn); +#endif +#ifdef cimg_save_plugin1 + cimg_save_plugin1(fn); +#endif +#ifdef cimg_save_plugin2 + cimg_save_plugin2(fn); +#endif +#ifdef cimg_save_plugin3 + cimg_save_plugin3(fn); +#endif +#ifdef cimg_save_plugin4 + cimg_save_plugin4(fn); +#endif +#ifdef cimg_save_plugin5 + cimg_save_plugin5(fn); +#endif +#ifdef cimg_save_plugin6 + cimg_save_plugin6(fn); +#endif +#ifdef cimg_save_plugin7 + cimg_save_plugin7(fn); +#endif +#ifdef cimg_save_plugin8 + cimg_save_plugin8(fn); +#endif + // Text formats + if (!cimg::strcasecmp(ext,"asc")) return save_ascii(fn); + else if (!cimg::strcasecmp(ext,"csv") || + !cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) return save_dlm(fn); + else if (!cimg::strcasecmp(ext,"cpp") || + !cimg::strcasecmp(ext,"hpp") || + !cimg::strcasecmp(ext,"h") || + !cimg::strcasecmp(ext,"c")) return save_cpp(fn); + + // 2D binary formats + else if (!cimg::strcasecmp(ext,"bmp")) return save_bmp(fn); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) return save_jpeg(fn); + else if (!cimg::strcasecmp(ext,"rgb")) return save_rgb(fn); + else if (!cimg::strcasecmp(ext,"rgba")) return save_rgba(fn); + else if (!cimg::strcasecmp(ext,"png")) return save_png(fn); + else if (!cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pnm")) return save_pnm(fn); + else if (!cimg::strcasecmp(ext,"pnk")) return save_pnk(fn); + else if (!cimg::strcasecmp(ext,"pfm")) return save_pfm(fn); + else if (!cimg::strcasecmp(ext,"exr")) return save_exr(fn); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); + + // 3D binary formats + else if (!*ext) { +#ifdef cimg_use_zlib + return save_cimg(fn,true); +#else + return save_cimg(fn,false); +#endif + } else if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg")) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"dcm")) return save_medcon_external(fn); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) return save_analyze(fn); + else if (!cimg::strcasecmp(ext,"inr")) return save_inr(fn); + else if (!cimg::strcasecmp(ext,"mnc")) return save_minc2(fn); + else if (!cimg::strcasecmp(ext,"pan")) return save_pandore(fn); + else if (!cimg::strcasecmp(ext,"raw")) return save_raw(fn); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + + // Image sequences + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,444,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); + return save_other(fn); + } + + //! Save image as an ascii file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_ascii(const char *const filename) const { + return _save_ascii(0,filename); + } + + //! Save image as an Ascii file \overloading. + const CImg& save_ascii(std::FILE *const file) const { + return _save_ascii(file,0); + } + + const CImg& _save_ascii(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_ascii(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + std::fprintf(nfile,"%u %u %u %u\n",_width,_height,_depth,_spectrum); + const T* ptrs = _data; + cimg_forYZC(*this,y,z,c) { + cimg_forX(*this,x) std::fprintf(nfile,"%.17g ",(double)*(ptrs++)); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a .cpp source file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_cpp(const char *const filename) const { + return _save_cpp(0,filename); + } + + //! Save image as a .cpp source file \overloading. + const CImg& save_cpp(std::FILE *const file) const { + return _save_cpp(file,0); + } + + const CImg& _save_cpp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_cpp(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + CImg varname(1024); *varname = 0; + if (filename) cimg_sscanf(cimg::basename(filename),"%1023[a-zA-Z0-9_]",varname._data); + if (!*varname) cimg_snprintf(varname,varname._width,"unnamed"); + std::fprintf(nfile, + "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n" + "%s data_%s[] = { %s\n ", + varname._data,_width,_height,_depth,_spectrum,pixel_type(),pixel_type(),varname._data, + is_empty()?"};":""); + if (!is_empty()) for (ulongT off = 0, siz = size() - 1; off<=siz; ++off) { + std::fprintf(nfile,cimg::type::format(),cimg::type::format((*this)[off])); + if (off==siz) std::fprintf(nfile," };\n"); + else if (!((off + 1)%16)) std::fprintf(nfile,",\n "); + else std::fprintf(nfile,", "); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a DLM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_dlm(const char *const filename) const { + return _save_dlm(0,filename); + } + + //! Save image as a DLM file \overloading. + const CImg& save_dlm(std::FILE *const file) const { + return _save_dlm(file,0); + } + + const CImg& _save_dlm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_dlm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is volumetric, values along Z will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + const T* ptrs = _data; + cimg_forYZC(*this,y,z,c) { + cimg_forX(*this,x) std::fprintf(nfile,"%.17g%s",(double)*(ptrs++),(x==width() - 1)?"":","); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a BMP file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_bmp(const char *const filename) const { + return _save_bmp(0,filename); + } + + //! Save image as a BMP file \overloading. + const CImg& save_bmp(std::FILE *const file) const { + return _save_bmp(file,0); + } + + const CImg& _save_bmp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_bmp(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_bmp(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_bmp(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(54,1,1,1,0); + unsigned char align_buf[4] = { 0 }; + const unsigned int + align = (4 - (3*_width)%4)%4, + buf_size = (3*_width + align)*height(), + file_size = 54 + buf_size; + header[0] = 'B'; header[1] = 'M'; + header[0x02] = file_size&0xFF; + header[0x03] = (file_size>>8)&0xFF; + header[0x04] = (file_size>>16)&0xFF; + header[0x05] = (file_size>>24)&0xFF; + header[0x0A] = 0x36; + header[0x0E] = 0x28; + header[0x12] = _width&0xFF; + header[0x13] = (_width>>8)&0xFF; + header[0x14] = (_width>>16)&0xFF; + header[0x15] = (_width>>24)&0xFF; + header[0x16] = _height&0xFF; + header[0x17] = (_height>>8)&0xFF; + header[0x18] = (_height>>16)&0xFF; + header[0x19] = (_height>>24)&0xFF; + header[0x1A] = 1; + header[0x1B] = 0; + header[0x1C] = 24; + header[0x1D] = 0; + header[0x22] = buf_size&0xFF; + header[0x23] = (buf_size>>8)&0xFF; + header[0x24] = (buf_size>>16)&0xFF; + header[0x25] = (buf_size>>24)&0xFF; + header[0x27] = 0x1; + header[0x2B] = 0x1; + cimg::fwrite(header._data,54,nfile); + + const T + *ptr_r = data(0,_height - 1,0,0), + *ptr_g = (_spectrum>=2)?data(0,_height - 1,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,_height - 1,0,2):0; + + switch (_spectrum) { + case 1 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + const unsigned char val = (unsigned char)*(ptr_r++); + std::fputc(val,nfile); std::fputc(val,nfile); std::fputc(val,nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; + } + } break; + case 2 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc(0,nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; + } + } break; + default : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc((unsigned char)(*(ptr_b++)),nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; ptr_b-=2*_width; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a JPEG file. + /** + \param filename Filename, as a C-string. + \param quality Image quality (in %) + **/ + const CImg& save_jpeg(const char *const filename, const unsigned int quality=100) const { + return _save_jpeg(0,filename,quality); + } + + //! Save image as a JPEG file \overloading. + const CImg& save_jpeg(std::FILE *const file, const unsigned int quality=100) const { + return _save_jpeg(file,0,quality); + } + + const CImg& _save_jpeg(std::FILE *const file, const char *const filename, const unsigned int quality) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_jpeg(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + +#ifndef cimg_use_jpeg + if (!file) return save_other(filename,quality); + else throw CImgIOException(_cimg_instance + "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.", + cimg_instance); +#else + unsigned int dimbuf = 0; + J_COLOR_SPACE colortype = JCS_RGB; + + switch (_spectrum) { + case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE; break; + case 2 : dimbuf = 3; colortype = JCS_RGB; break; + case 3 : dimbuf = 3; colortype = JCS_RGB; break; + default : dimbuf = 4; colortype = JCS_CMYK; break; + } + + // Call libjpeg functions + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + jpeg_stdio_dest(&cinfo,nfile); + cinfo.image_width = _width; + cinfo.image_height = _height; + cinfo.input_components = dimbuf; + cinfo.in_color_space = colortype; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE); + jpeg_start_compress(&cinfo,TRUE); + + JSAMPROW row_pointer[1]; + CImg buffer(_width*dimbuf); + + while (cinfo.next_scanline& save_magick(const char *const filename, const unsigned int bytes_per_pixel=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_magick(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_magick + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_magick(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_magick(): Instance is multispectral, only the three first channels will be " + "saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_magick(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + Magick::Image image(Magick::Geometry(_width,_height),"black"); + image.type(Magick::TrueColorType); + image.depth(bytes_per_pixel?(8*bytes_per_pixel):(stmax>=256?16:8)); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = _spectrum>1?data(0,0,0,1):0, + *ptr_b = _spectrum>2?data(0,0,0,2):0; + Magick::PixelPacket *pixels = image.getPixels(0,0,_width,_height); + switch (_spectrum) { + case 1 : // Scalar images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = pixels->green = pixels->blue = (Magick::Quantum)*(ptr_r++); + ++pixels; + } + break; + case 2 : // RG images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = 0; ++pixels; + } + break; + default : // RGB images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = (Magick::Quantum)*(ptr_b++); + ++pixels; + } + } + image.syncPixels(); + image.write(filename); + return *this; +#else + cimg::unused(bytes_per_pixel); + throw CImgIOException(_cimg_instance + "save_magick(): Unable to save file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Save image as a PNG file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving, when possible. + **/ + const CImg& save_png(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_png(0,filename,bytes_per_pixel); + } + + //! Save image as a PNG file \overloading. + const CImg& save_png(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_png(file,0,bytes_per_pixel); + } + + const CImg& _save_png(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_png(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + +#ifndef cimg_use_png + cimg::unused(bytes_per_pixel); + if (!file) return save_other(filename); + else throw CImgIOException(_cimg_instance + "save_png(): Unable to save data in '(*FILE)' unless libpng is enabled.", + cimg_instance); +#else + +#if defined __GNUC__ + const char *volatile nfilename = filename; // Use 'volatile' to avoid (wrong) g++ warning + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"wb"); + volatile double stmin, stmax = (double)max_min(stmin); +#else + const char *nfilename = filename; + std::FILE *nfile = file?file:cimg::fopen(nfilename,"wb"); + double stmin, stmax = (double)max_min(stmin); +#endif + + if (_depth>1) + cimg::warn(_cimg_instance + "save_png(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>4) + cimg::warn(_cimg_instance + "save_png(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_png(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + // Setup PNG structures for write + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,user_error_ptr, user_error_fn, + user_warning_fn); + if (!png_ptr){ + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'png_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)0); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'info_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + + const int bit_depth = bytes_per_pixel?(bytes_per_pixel*8):(stmax>=256?16:8); + + int color_type; + switch (spectrum()) { + case 1 : color_type = PNG_COLOR_TYPE_GRAY; break; + case 2 : color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; + case 3 : color_type = PNG_COLOR_TYPE_RGB; break; + default : color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + const int interlace_type = PNG_INTERLACE_NONE; + const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT; + const int filter_method = PNG_FILTER_TYPE_DEFAULT; + png_set_IHDR(png_ptr,info_ptr,_width,_height,bit_depth,color_type,interlace_type,compression_type,filter_method); + png_write_info(png_ptr,info_ptr); + const int byte_depth = bit_depth>>3; + const int numChan = spectrum()>4?4:spectrum(); + const int pixel_bit_depth_flag = numChan * (bit_depth - 1); + + // Allocate Memory for Image Save and Fill pixel data + png_bytep *const imgData = new png_byte*[_height]; + for (unsigned int row = 0; row<_height; ++row) imgData[row] = new png_byte[byte_depth*numChan*_width]; + const T *pC0 = data(0,0,0,0); + switch (pixel_bit_depth_flag) { + case 7 : { // Gray 8-bit + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) *(ptrd++) = (unsigned char)*(pC0++); + } + } break; + case 14 : { // Gray w/ Alpha 8-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + } + } + } break; + case 21 : { // RGB 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + } + } + } break; + case 28 : { // RGB x/ Alpha 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y){ + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x){ + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + *(ptrd++) = (unsigned char)*(pC3++); + } + } + } break; + case 15 : { // Gray 16-bit + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) *(ptrd++) = (unsigned short)*(pC0++); + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],_width); + } + } break; + case 30 : { // Gray w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],2*_width); + } + } break; + case 45 : { // RGB 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],3*_width); + } + } break; + case 60 : { // RGB w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + *(ptrd++) = (unsigned short)*(pC3++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],4*_width); + } + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_write_image(png_ptr,imgData); + png_write_end(png_ptr,info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + // Deallocate Image Write Memory + cimg_forY(*this,n) delete[] imgData[n]; + delete[] imgData; + + if (!file) cimg::fclose(nfile); + return *this; +#endif + } + + //! Save image as a PNM file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving. + **/ + const CImg& save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(0,filename,bytes_per_pixel); + } + + //! Save image as a PNM file \overloading. + const CImg& save_pnm(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(file,0,bytes_per_pixel); + } + + const CImg& _save_pnm(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_pnm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pnm(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_pnm(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + stmin,stmax,filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const ulongT buf_size = std::min((ulongT)(1024*1024),(ulongT)(_width*_height*(_spectrum==1?1UL:3UL))); + + std::fprintf(nfile,"P%c\n%u %u\n%u\n", + (_spectrum==1?'5':'6'),_width,_height,stmax<256?255:(stmax<4096?4095:65535)); + + switch (_spectrum) { + case 1 : { // Scalar image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PGM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr_r++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Binary PGM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned short)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + } break; + case 2 : { // RG image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = 0; + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } break; + default : { // RGB image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = (unsigned char)*(ptr_b++); + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = (unsigned short)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PNK file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pnk(const char *const filename) const { + return _save_pnk(0,filename); + } + + //! Save image as a PNK file \overloading. + const CImg& save_pnk(std::FILE *const file) const { + return _save_pnk(file,0); + } + + const CImg& _save_pnk(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnk(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + const ulongT buf_size = std::min((ulongT)1024*1024,(ulongT)_width*_height*_depth); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T *ptr = data(0,0,0,0); + + if (!cimg::type::is_float() && sizeof(T)==1 && _depth<2) // Can be saved as regular PNM file + _save_pnm(file,filename,0); + else if (!cimg::type::is_float() && sizeof(T)==1) { // Save as extended P5 file: Binary byte-valued 3D + std::fprintf(nfile,"P5\n%u %u %u\n255\n",_width,_height,_depth); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else if (!cimg::type::is_float()) { // Save as P8: Binary int32-valued 3D + if (_depth>1) std::fprintf(nfile,"P8\n%u %u %u\n%d\n",_width,_height,_depth,(int)max()); + else std::fprintf(nfile,"P8\n%u %u\n%d\n",_width,_height,(int)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + int *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (int)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Save as P9: Binary float-valued 3D + if (_depth>1) std::fprintf(nfile,"P9\n%u %u %u\n%g\n",_width,_height,_depth,(double)max()); + else std::fprintf(nfile,"P9\n%u %u\n%g\n",_width,_height,(double)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PFM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pfm(const char *const filename) const { + get_mirror('y')._save_pfm(0,filename); + return *this; + } + + //! Save image as a PFM file \overloading. + const CImg& save_pfm(std::FILE *const file) const { + get_mirror('y')._save_pfm(file,0); + return *this; + } + + const CImg& _save_pfm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pfm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pfm(): image instance is multispectral, only the three first channels will be saved " + "in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const unsigned int buf_size = std::min(1024*1024U,_width*_height*(_spectrum==1?1:3)); + + std::fprintf(nfile,"P%c\n%u %u\n1.0\n", + (_spectrum==1?'f':'F'),_width,_height); + + switch (_spectrum) { + case 1 : { // Scalar image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,(ulongT)buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } break; + case 2 : { // RG image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } break; + default : { // RGB image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = (float)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a RGB file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_rgb(const char *const filename) const { + return _save_rgb(0,filename); + } + + //! Save image as a RGB file \overloading. + const CImg& save_rgb(std::FILE *const file) const { + return _save_rgb(file,0); + } + + const CImg& _save_rgb(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgb(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=3) + cimg::warn(_cimg_instance + "save_rgb(): image instance has not exactly 3 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0; + switch (_spectrum) { + case 1 : { // Scalar image + for (ulongT k = 0; k& save_rgba(const char *const filename) const { + return _save_rgba(0,filename); + } + + //! Save image as a RGBA file \overloading. + const CImg& save_rgba(std::FILE *const file) const { + return _save_rgba(file,0); + } + + const CImg& _save_rgba(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgba(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=4) + cimg::warn(_cimg_instance + "save_rgba(): image instance has not exactly 4 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[4*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0, + *ptr4 = _spectrum>3?data(0,0,0,3):0; + switch (_spectrum) { + case 1 : { // Scalar images + for (ulongT k = 0; k{ 0=None | 1=LZW | 2=JPEG }. + \param[out] voxel_size Voxel size, to be stored in the filename. + \param[out] description Description, to be stored in the filename. + \param use_bigtiff Allow to save big tiff files (>4Gb). + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tiff is not defined at compile time the + function uses CImg&save_other(const char*). + **/ + const CImg& save_tiff(const char *const filename, const unsigned int compression_type=0, + + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_tiff(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_tiff + const bool + _use_bigtiff = use_bigtiff && sizeof(ulongT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "save_tiff(): Failed to open file '%s' for writing.", + cimg_instance, + filename); + return *this; +#else + cimg::unused(compression_type,voxel_size,description,use_bigtiff); + return save_other(filename); +#endif + } + +#ifdef cimg_use_tiff + +#define _cimg_save_tiff(types,typed,compression_type) if (!std::strcmp(types,pixel_type())) { \ + const typed foo = (typed)0; return _save_tiff(tif,directory,z,foo,compression_type,voxel_size,description); } + + // [internal] Save a plane into a tiff file + template + const CImg& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, const t& pixel_t, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + if (is_empty() || !tif || pixel_t) return *this; + const char *const filename = TIFFFileName(tif); + uint32 rowsperstrip = (uint32)-1; + uint16 spp = _spectrum, bpp = sizeof(t)*8, photometric; + if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB; + else photometric = PHOTOMETRIC_MINISBLACK; + TIFFSetDirectory(tif,directory); + TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,_width); + TIFFSetField(tif,TIFFTAG_IMAGELENGTH,_height); + if (voxel_size) { + const float vx = voxel_size[0], vy = voxel_size[1], vz = voxel_size[2]; + TIFFSetField(tif,TIFFTAG_RESOLUTIONUNIT,RESUNIT_NONE); + TIFFSetField(tif,TIFFTAG_XRESOLUTION,1.f/vx); + TIFFSetField(tif,TIFFTAG_YRESOLUTION,1.f/vy); + CImg s_description(256); + cimg_snprintf(s_description,s_description._width,"VX=%g VY=%g VZ=%g spacing=%g",vx,vy,vz,vz); + TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,s_description.data()); + } + if (description) TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,description); + TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); + TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp); + if (cimg::type::is_float()) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,3); + else if (cimg::type::min()==0) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,1); + else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2); + double valm, valM = max_min(valm); + TIFFSetField(tif,TIFFTAG_SMINSAMPLEVALUE,valm); + TIFFSetField(tif,TIFFTAG_SMAXSAMPLEVALUE,valM); + TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp); + TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); + TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric); + TIFFSetField(tif,TIFFTAG_COMPRESSION,compression_type==2?COMPRESSION_JPEG: + compression_type==1?COMPRESSION_LZW:COMPRESSION_NONE); + rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip); + TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip); + TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB); + TIFFSetField(tif,TIFFTAG_SOFTWARE,"CImg"); + + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + for (unsigned int row = 0; row<_height; row+=rowsperstrip) { + uint32 nrow = (row + rowsperstrip>_height?_height - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif,row,0); + tsize_t i = 0; + for (unsigned int rr = 0; rr& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + _cimg_save_tiff("bool",unsigned char,compression_type); + _cimg_save_tiff("unsigned char",unsigned char,compression_type); + _cimg_save_tiff("char",char,compression_type); + _cimg_save_tiff("unsigned short",unsigned short,compression_type); + _cimg_save_tiff("short",short,compression_type); + _cimg_save_tiff("unsigned int",unsigned int,compression_type); + _cimg_save_tiff("int",int,compression_type); + _cimg_save_tiff("unsigned int64",unsigned int,compression_type); + _cimg_save_tiff("int64",int,compression_type); + _cimg_save_tiff("float",float,compression_type); + _cimg_save_tiff("double",float,compression_type); + const char *const filename = TIFFFileName(tif); + throw CImgInstanceException(_cimg_instance + "save_tiff(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + return *this; + } +#endif + + //! Save image as a MINC2 file. + /** + \param filename Filename, as a C-string. + \param imitate_file If non-zero, reference filename, as a C-string, to borrow header from. + **/ + const CImg& save_minc2(const char *const filename, + const char *const imitate_file=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_minc2(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_minc2 + cimg::unused(imitate_file); + return save_other(filename); +#else + minc::minc_1_writer wtr; + if (imitate_file) + wtr.open(filename, imitate_file); + else { + minc::minc_info di; + if (width()) di.push_back(minc::dim_info(width(),width()*0.5,-1,minc::dim_info::DIM_X)); + if (height()) di.push_back(minc::dim_info(height(),height()*0.5,-1,minc::dim_info::DIM_Y)); + if (depth()) di.push_back(minc::dim_info(depth(),depth()*0.5,-1,minc::dim_info::DIM_Z)); + if (spectrum()) di.push_back(minc::dim_info(spectrum(),spectrum()*0.5,-1,minc::dim_info::DIM_TIME)); + wtr.open(filename,di,1,NC_FLOAT,0); + } + if (pixel_type()==cimg::type::string()) + wtr.setup_write_byte(); + else if (pixel_type()==cimg::type::string()) + wtr.setup_write_int(); + else if (pixel_type()==cimg::type::string()) + wtr.setup_write_double(); + else + wtr.setup_write_float(); + minc::save_standard_volume(wtr, this->_data); + return *this; +#endif + } + + //! Save image as an ANALYZE7.5 or NIFTI file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 consecutive values that tell about the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_analyze(const char *const filename, const float *const voxel_size=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_analyze(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + std::FILE *file; + CImg hname(1024), iname(1024); + const char *const ext = cimg::split_filename(filename); + short datatype = -1; + if (!*ext) { + cimg_snprintf(hname,hname._width,"%s.hdr",filename); + cimg_snprintf(iname,iname._width,"%s.img",filename); + } + if (!cimg::strncasecmp(ext,"hdr",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(iname._data + std::strlen(iname) - 3,"img"); + } + if (!cimg::strncasecmp(ext,"img",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(hname._data + std::strlen(iname) - 3,"hdr"); + } + if (!cimg::strncasecmp(ext,"nii",3)) { + std::strncpy(hname,filename,hname._width - 1); *iname = 0; + } + + CImg header(*iname?348:352,1,1,1,0); + int *const iheader = (int*)header._data; + *iheader = 348; + std::strcpy(header._data + 4,"CImg"); + std::strcpy(header._data + 14," "); + ((short*)&(header[36]))[0] = 4096; + ((char*)&(header[38]))[0] = 114; + ((short*)&(header[40]))[0] = 4; + ((short*)&(header[40]))[1] = (short)_width; + ((short*)&(header[40]))[2] = (short)_height; + ((short*)&(header[40]))[3] = (short)_depth; + ((short*)&(header[40]))[4] = (short)_spectrum; + if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"unsigned int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16; + if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64; + if (datatype<0) + throw CImgIOException(_cimg_instance + "save_analyze(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename); + + ((short*)&(header[70]))[0] = datatype; + ((short*)&(header[72]))[0] = sizeof(T); + ((float*)&(header[108]))[0] = (float)(*iname?0:header.width()); + ((float*)&(header[112]))[0] = 1; + ((float*)&(header[76]))[0] = 0; + if (voxel_size) { + ((float*)&(header[76]))[1] = voxel_size[0]; + ((float*)&(header[76]))[2] = voxel_size[1]; + ((float*)&(header[76]))[3] = voxel_size[2]; + } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1; + file = cimg::fopen(hname,"wb"); + cimg::fwrite(header._data,header.width(),file); + if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); } + cimg::fwrite(_data,size(),file); + cimg::fclose(file); + return *this; + } + + //! Save image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param is_compressed Tells if the file contains compressed image data. + **/ + const CImg& save_cimg(const char *const filename, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(filename,is_compressed); + return *this; + } + + //! Save image as a .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(file,is_compressed); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Index of the image inside the file. + \param x0 X-coordinate of the sub-image location. + \param y0 Y-coordinate of the sub-image location. + \param z0 Z-coordinate of the sub-image location. + \param c0 C-coordinate of the sub-image location. + **/ + const CImg& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(filename,n0,x0,y0,z0,c0); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(file,n0,x0,y0,z0,c0); + return *this; + } + + //! Save blank image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param dx Width of the image. + \param dy Height of the image. + \param dz Depth of the image. + \param dc Number of channels of the image. + \note + - All pixel values of the saved image are set to \c 0. + - Use this method to save large images without having to instantiate and allocate them. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(filename,1,dx,dy,dz,dc); + } + + //! Save blank image as a .cimg file \overloading. + /** + Same as save_empty_cimg(const char *,unsigned int,unsigned int,unsigned int,unsigned int) + with a file stream argument instead of a filename string. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(file,1,dx,dy,dz,dc); + } + + //! Save image as an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 values specifying the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_inr(const char *const filename, const float *const voxel_size=0) const { + return _save_inr(0,filename,voxel_size); + } + + //! Save image as an INRIMAGE-4 file \overloading. + const CImg& save_inr(std::FILE *const file, const float *const voxel_size=0) const { + return _save_inr(file,0,voxel_size); + } + + const CImg& _save_inr(std::FILE *const file, const char *const filename, const float *const voxel_size) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_inr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + int inrpixsize = -1; + const char *inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) { + inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"char")) { + inrtype = "fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) { + inrtype = "unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"short")) { + inrtype = "fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) { + inrtype = "unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"int")) { + inrtype = "fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"float")) { + inrtype = "float\nPIXSIZE=32 bits"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"double")) { + inrtype = "float\nPIXSIZE=64 bits"; inrpixsize = 8; + } + if (inrpixsize<=0) + throw CImgIOException(_cimg_instance + "save_inr(): Unsupported pixel type '%s' for file '%s'", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(257); + int err = cimg_snprintf(header,header._width,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n", + _width,_height,_depth,_spectrum); + if (voxel_size) err+=cimg_sprintf(header._data + err,"VX=%g\nVY=%g\nVZ=%g\n", + voxel_size[0],voxel_size[1],voxel_size[2]); + err+=cimg_sprintf(header._data + err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm"); + std::memset(header._data + err,'\n',252 - err); + std::memcpy(header._data + 252,"##}\n",4); + cimg::fwrite(header._data,256,nfile); + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as an OpenEXR file. + /** + \param filename Filename, as a C-string. + \note The OpenEXR file format is described here. + **/ + const CImg& save_exr(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_exr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_exr(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + +#ifndef cimg_use_openexr + return save_other(filename); +#else + Imf::Rgba *const ptrd0 = new Imf::Rgba[(size_t)_width*_height], *ptrd = ptrd0, rgba; + switch (_spectrum) { + case 1 : { // Grayscale image + for (const T *ptr_r = data(), *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_rPandore file specifications + for more information). + **/ + const CImg& save_pandore(const char *const filename, const unsigned int colorspace=0) const { + return _save_pandore(0,filename,colorspace); + } + + //! Save image as a Pandore-5 file \overloading. + /** + Same as save_pandore(const char *,unsigned int) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_pandore(std::FILE *const file, const unsigned int colorspace=0) const { + return _save_pandore(file,0,colorspace); + } + + unsigned int _save_pandore_header_length(unsigned int id, unsigned int *dims, const unsigned int colorspace) const { + unsigned int nbdims = 0; + if (id==2 || id==3 || id==4) { + dims[0] = 1; dims[1] = _width; nbdims = 2; + } + if (id==5 || id==6 || id==7) { + dims[0] = 1; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==8 || id==9 || id==10) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + if (id==16 || id==17 || id==18) { + dims[0] = 3; dims[1] = _height; dims[2] = _width; dims[3] = colorspace; nbdims = 4; + } + if (id==19 || id==20 || id==21) { + dims[0] = 3; dims[1] = _depth; dims[2] = _height; dims[3] = _width; dims[4] = colorspace; nbdims = 5; + } + if (id==22 || id==23 || id==25) { + dims[0] = _spectrum; dims[1] = _width; nbdims = 2; + } + if (id==26 || id==27 || id==29) { + dims[0] = _spectrum; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==30 || id==31 || id==33) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + return nbdims; + } + + const CImg& _save_pandore(std::FILE *const file, const char *const filename, + const unsigned int colorspace) const { + +#define __cimg_save_pandore_case(dtype) \ + dtype *buffer = new dtype[size()]; \ + const T *ptrs = _data; \ + cimg_foroff(*this,off) *(buffer++) = (dtype)(*(ptrs++)); \ + buffer-=size(); \ + cimg::fwrite(buffer,size(),nfile); \ + delete[] buffer + +#define _cimg_save_pandore_case(sy,sz,sv,stype,id) \ + if (!saved && (sy?(sy==_height):true) && (sz?(sz==_depth):true) && \ + (sv?(sv==_spectrum):true) && !std::strcmp(stype,pixel_type())) { \ + unsigned int *iheader = (unsigned int*)(header + 12); \ + nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \ + cimg::fwrite(header,36,nfile); \ + if (sizeof(unsigned long)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned long)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned int)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned int)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned short)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned short)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \ + __cimg_save_pandore_case(unsigned char); \ + } else if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \ + if (sizeof(unsigned long)==4) { __cimg_save_pandore_case(unsigned long); } \ + else if (sizeof(unsigned int)==4) { __cimg_save_pandore_case(unsigned int); } \ + else if (sizeof(unsigned short)==4) { __cimg_save_pandore_case(unsigned short); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \ + if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \ + else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pandore(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0, + 0,0,0,0,'C','I','m','g',0,0,0,0,0, + 'N','o',' ','d','a','t','e',0,0,0,0 }; + unsigned int nbdims, dims[5] = { 0 }; + bool saved = false; + _cimg_save_pandore_case(1,1,1,"unsigned char",2); + _cimg_save_pandore_case(1,1,1,"char",3); + _cimg_save_pandore_case(1,1,1,"unsigned short",3); + _cimg_save_pandore_case(1,1,1,"short",3); + _cimg_save_pandore_case(1,1,1,"unsigned int",3); + _cimg_save_pandore_case(1,1,1,"int",3); + _cimg_save_pandore_case(1,1,1,"unsigned int64",3); + _cimg_save_pandore_case(1,1,1,"int64",3); + _cimg_save_pandore_case(1,1,1,"float",4); + _cimg_save_pandore_case(1,1,1,"double",4); + + _cimg_save_pandore_case(0,1,1,"unsigned char",5); + _cimg_save_pandore_case(0,1,1,"char",6); + _cimg_save_pandore_case(0,1,1,"unsigned short",6); + _cimg_save_pandore_case(0,1,1,"short",6); + _cimg_save_pandore_case(0,1,1,"unsigned int",6); + _cimg_save_pandore_case(0,1,1,"int",6); + _cimg_save_pandore_case(0,1,1,"unsigned int64",6); + _cimg_save_pandore_case(0,1,1,"int64",6); + _cimg_save_pandore_case(0,1,1,"float",7); + _cimg_save_pandore_case(0,1,1,"double",7); + + _cimg_save_pandore_case(0,0,1,"unsigned char",8); + _cimg_save_pandore_case(0,0,1,"char",9); + _cimg_save_pandore_case(0,0,1,"unsigned short",9); + _cimg_save_pandore_case(0,0,1,"short",9); + _cimg_save_pandore_case(0,0,1,"unsigned int",9); + _cimg_save_pandore_case(0,0,1,"int",9); + _cimg_save_pandore_case(0,0,1,"unsigned int64",9); + _cimg_save_pandore_case(0,0,1,"int64",9); + _cimg_save_pandore_case(0,0,1,"float",10); + _cimg_save_pandore_case(0,0,1,"double",10); + + _cimg_save_pandore_case(0,1,3,"unsigned char",16); + _cimg_save_pandore_case(0,1,3,"char",17); + _cimg_save_pandore_case(0,1,3,"unsigned short",17); + _cimg_save_pandore_case(0,1,3,"short",17); + _cimg_save_pandore_case(0,1,3,"unsigned int",17); + _cimg_save_pandore_case(0,1,3,"int",17); + _cimg_save_pandore_case(0,1,3,"unsigned int64",17); + _cimg_save_pandore_case(0,1,3,"int64",17); + _cimg_save_pandore_case(0,1,3,"float",18); + _cimg_save_pandore_case(0,1,3,"double",18); + + _cimg_save_pandore_case(0,0,3,"unsigned char",19); + _cimg_save_pandore_case(0,0,3,"char",20); + _cimg_save_pandore_case(0,0,3,"unsigned short",20); + _cimg_save_pandore_case(0,0,3,"short",20); + _cimg_save_pandore_case(0,0,3,"unsigned int",20); + _cimg_save_pandore_case(0,0,3,"int",20); + _cimg_save_pandore_case(0,0,3,"unsigned int64",20); + _cimg_save_pandore_case(0,0,3,"int64",20); + _cimg_save_pandore_case(0,0,3,"float",21); + _cimg_save_pandore_case(0,0,3,"double",21); + + _cimg_save_pandore_case(1,1,0,"unsigned char",22); + _cimg_save_pandore_case(1,1,0,"char",23); + _cimg_save_pandore_case(1,1,0,"unsigned short",23); + _cimg_save_pandore_case(1,1,0,"short",23); + _cimg_save_pandore_case(1,1,0,"unsigned int",23); + _cimg_save_pandore_case(1,1,0,"int",23); + _cimg_save_pandore_case(1,1,0,"unsigned int64",23); + _cimg_save_pandore_case(1,1,0,"int64",23); + _cimg_save_pandore_case(1,1,0,"float",25); + _cimg_save_pandore_case(1,1,0,"double",25); + + _cimg_save_pandore_case(0,1,0,"unsigned char",26); + _cimg_save_pandore_case(0,1,0,"char",27); + _cimg_save_pandore_case(0,1,0,"unsigned short",27); + _cimg_save_pandore_case(0,1,0,"short",27); + _cimg_save_pandore_case(0,1,0,"unsigned int",27); + _cimg_save_pandore_case(0,1,0,"int",27); + _cimg_save_pandore_case(0,1,0,"unsigned int64",27); + _cimg_save_pandore_case(0,1,0,"int64",27); + _cimg_save_pandore_case(0,1,0,"float",29); + _cimg_save_pandore_case(0,1,0,"double",29); + + _cimg_save_pandore_case(0,0,0,"unsigned char",30); + _cimg_save_pandore_case(0,0,0,"char",31); + _cimg_save_pandore_case(0,0,0,"unsigned short",31); + _cimg_save_pandore_case(0,0,0,"short",31); + _cimg_save_pandore_case(0,0,0,"unsigned int",31); + _cimg_save_pandore_case(0,0,0,"int",31); + _cimg_save_pandore_case(0,0,0,"unsigned int64",31); + _cimg_save_pandore_case(0,0,0,"int64",31); + _cimg_save_pandore_case(0,0,0,"float",33); + _cimg_save_pandore_case(0,0,0,"double",33); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a raw data file. + /** + \param filename Filename, as a C-string. + \param is_multiplexed Tells if the image channels are stored in a multiplexed way (\c true) or not (\c false). + \note The .raw format does not store the image dimensions in the output file, + so you have to keep track of them somewhere to be able to read the file correctly afterwards. + **/ + const CImg& save_raw(const char *const filename, const bool is_multiplexed=false) const { + return _save_raw(0,filename,is_multiplexed); + } + + //! Save image as a raw data file \overloading. + /** + Same as save_raw(const char *,bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_raw(std::FILE *const file, const bool is_multiplexed=false) const { + return _save_raw(file,0,is_multiplexed); + } + + const CImg& _save_raw(std::FILE *const file, const char *const filename, const bool is_multiplexed) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_raw(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (pixel_type()==cimg::type::string()) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = _bool2uchar(siz,is_multiplexed); + cimg::fwrite(buf,siz,nfile); + delete[] buf; + } else { // Non boolean data + if (!is_multiplexed || _spectrum==1) cimg::fwrite(_data,size(),nfile); // Non-multiplexed + else { // Multiplexed + CImg buf(_spectrum); + cimg_forXYZ(*this,x,y,z) { + cimg_forC(*this,c) buf[c] = (*this)(x,y,z,c); + cimg::fwrite(buf._data,_spectrum,nfile); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + // Return unsigned char buffer that encodes data of a CImg instance bitwise. + // (buffer needs to be deallocated afterwards, with delete[]). + const unsigned char *_bool2uchar(ulongT &siz, const bool is_multiplexed) const { + const ulongT _siz = size(); + siz = _siz/8 + (_siz%8?1:0); + unsigned char *const buf = new unsigned char[siz], *ptrd = buf, val = 0, bit = 0; + + if (!is_multiplexed || _spectrum==1) // Non-multiplexed + cimg_for(*this,ptrs,T) { (val<<=1)|=(*ptrs?1:0); if (++bit==8) { *(ptrd++) = val; val = bit = 0; }} + else // Multiplexed + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) { + (val<<=1)|=((*this)(x,y,z,c)?1:0); if (++bit==8) { *(ptrd++) = val; val = bit = 0; } + } + if (bit) *ptrd = val; + return buf; + } + + // Fill CImg instance from bitwise data encoded in an unsigned char buffer. + void _uchar2bool(const unsigned char *buf, const ulongT siz, const bool is_multiplexed) { + const ulongT S = std::min(siz*8,size()); + const unsigned char *ptrs = buf; + unsigned char val = 0, mask = 0; + T *ptrd = _data; + if (S && (!is_multiplexed || _spectrum==1)) // Non-multiplexed + for (ulongT off = 0; off>=1)) { val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?1:0); + } + else if (S) { // Multiplexed + ulongT off = 0; + for (int z = 0; z>=1)) { val = *(ptrs++); ++off; mask = 128; } + (*this)(x,y,z,c) = (T)((val&mask)?1:0); + } + } + } + + //! Save image as a .yuv video file. + /** + \param filename Filename, as a C-string. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if pixel values of the instance image are RGB-coded (\c true) or YUV-coded (\c false). + \note Each slice of the instance image is considered to be a single frame of the output video file. + **/ + const CImg& save_yuv(const char *const filename, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + CImgList(*this,true).save_yuv(filename,chroma_subsampling,is_rgb); + return *this; + } + + //! Save image as a .yuv video file \overloading. + /** + Same as save_yuv(const char*,const unsigned int,const bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_yuv(std::FILE *const file, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + CImgList(*this,true).save_yuv(file,chroma_subsampling,is_rgb); + return *this; + } + + //! Save 3D object as an Object File Format (.off) file. + /** + \param filename Filename, as a C-string. + \param primitives List of 3D object primitives. + \param colors List of 3D object colors. + \note + - Instance image contains the vertices data of the 3D object. + - Textured, transparent or sphere-shaped primitives cannot be managed by the .off file format. + Such primitives will be lost or simplified during file saving. + - The .off file format is described here. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + const char *const filename) const { + return _save_off(primitives,colors,0,filename); + } + + //! Save 3D object as an Object File Format (.off) file \overloading. + /** + Same as save_off(const CImgList&,const CImgList&,const char*) const + with a file stream argument instead of a filename string. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file) const { + return _save_off(primitives,colors,file,0); + } + + template + const CImg& _save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_off(): Specified filename is (null).", + cimg_instance); + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "save_off(): Empty instance, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + CImgList opacities; + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgInstanceException(_cimg_instance + "save_off(): Invalid specified 3D object, for file '%s' (%s).", + cimg_instance, + filename?filename:"(FILE*)",error_message.data()); + + const CImg default_color(1,3,1,1,(tc)std::min((int)cimg::type::max(),200)); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + unsigned int supported_primitives = 0; + cimglist_for(primitives,l) if (primitives[l].size()!=5) ++supported_primitives; + std::fprintf(nfile,"OFF\n%u %u %u\n",_width,supported_primitives,3*primitives._width); + cimg_forX(*this,i) std::fprintf(nfile,"%f %f %f\n", + (float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2))); + cimglist_for(primitives,l) { + const CImg& color = l1?color[1]:r)/255.f, b = (csiz>2?color[2]:g)/255.f; + switch (psiz) { + case 1 : std::fprintf(nfile,"1 %u %f %f %f\n", + (unsigned int)primitives(l,0),r,g,b); break; + case 2 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 3 : std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),r,g,b); break; + case 4 : std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),r,g,b); break; + case 5 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 6 : { + const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 9 : { + const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 12 : { + const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save volumetric image as a video (using the OpenCV library when available). + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImg& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { + if (is_empty()) { CImgList().save_video(filename,fps,codec,keep_open); return *this; } + CImgList list; + get_split('z').move_to(list); + list.save_video(filename,fps,codec,keep_open); + return *this; + } + + //! Save volumetric image as a video, using custom external binary. + /** + \param filename Filename, as a C-string. + \param fps Video framerate. + \param codec Video codec, as a C-string. + \param bitrate Video bitrate. + \note + - Each slice of the instance image is considered to be a single frame of the output video file. + - This method uses \c custom, an external executable binary provided by + custom. + It must be installed for the method to succeed. + **/ + const CImg& save_custom_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_custom_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImgList list; + get_split('z').move_to(list); + list.save_custom_external(filename,fps,codec,bitrate); + return *this; + } + + //! Save image using gzip external binary. + /** + \param filename Filename, as a C-string. + \note This method uses \c gzip, an external executable binary provided by + gzip. + It must be installed for the method to succeed. + **/ + const CImg& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_gzip_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::gzip_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimg_instance, + filename); + + else cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using GraphicsMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c gm, an external executable binary provided by + GraphicsMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + +#ifdef cimg_use_png +#define _cimg_sge_extension1 "png" +#define _cimg_sge_extension2 "png" +#else +#define _cimg_sge_extension1 "pgm" +#define _cimg_sge_extension2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(), + _spectrum==1?_cimg_sge_extension1:_cimg_sge_extension2); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"\"%s\" convert -quality %u \"%s\" \"%s\"", + cimg::graphicsmagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::graphicsmagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_graphicsmagick_external(): Failed to save file '%s' with external command 'gm'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using ImageMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c convert, an external executable binary provided by + ImageMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_imagemagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_imagemagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick only writes the first image slice.", + cimg_instance,filename); +#ifdef cimg_use_png +#define _cimg_sie_extension1 "png" +#define _cimg_sie_extension2 "png" +#else +#define _cimg_sie_extension1 "pgm" +#define _cimg_sie_extension2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",cimg::temporary_path(), + cimg_file_separator,cimg::filenamerand(),_spectrum==1?_cimg_sie_extension1:_cimg_sie_extension2); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"\"%s\" -quality %u \"%s\" \"%s\"", + cimg::imagemagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::imagemagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_imagemagick_external(): Failed to save file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image as a Dicom file. + /** + \param filename Filename, as a C-string. + \note This method uses \c medcon, an external executable binary provided by + (X)Medcon. + It must be installed for the method to succeed. + **/ + const CImg& save_medcon_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_medcon_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save_analyze(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -w -c dicom -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::medcon_path()); + std::remove(filename_tmp); + cimg::split_filename(filename_tmp,body); + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.img",body._data); + std::remove(filename_tmp); + + file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s",filename); + file = cimg::std_fopen(command,"rb"); + if (!file) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "save_medcon_external(): Failed to save file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + std::rename(command,filename); + return *this; + } + + // Save image for non natively supported formats. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note + - The filename extension tells about the desired file format. + - This method tries to save the instance image as a file, using external tools from + ImageMagick or + GraphicsMagick. + At least one of these tool must be installed for the method to succeed. + - It is recommended to use the generic method save(const char*, int) const instead, + as it can handle some file formats natively. + **/ + const CImg& save_other(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_other(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick or GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + + const unsigned int omode = cimg::exception_mode(); + bool is_saved = true; + cimg::exception_mode(0); + try { save_magick(filename); } + catch (CImgException&) { + try { save_imagemagick_external(filename,quality); } + catch (CImgException&) { + try { save_graphicsmagick_external(filename,quality); } + catch (CImgException&) { + is_saved = false; + } + } + } + cimg::exception_mode(omode); + if (!is_saved) + throw CImgIOException(_cimg_instance + "save_other(): Failed to save file '%s'. Format is not natively supported, " + "and no external commands succeeded.", + cimg_instance, + filename); + return *this; + } + + //! Serialize a CImg instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { + return CImgList(*this,true).get_serialize(is_compressed); + } + + // [internal] Return a 40x38 color logo of a 'danger' item. + static CImg _logo40x38() { + CImg res(40,38,1,3); + const unsigned char *ptrs = cimg::logo40x38; + T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2); + for (ulongT off = 0; off<(ulongT)res._width*res._height;) { + const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++); + for (unsigned int l = 0; l structure + # + # + # + #------------------------------------------ + */ + //! Represent a list of images CImg. + template + struct CImgList { + unsigned int _width, _allocated_width; + CImg *_data; + + //! Simple iterator type, to loop through each image of a list. + /** + \note + - The \c CImgList::iterator type is defined as a CImg*. + - You may use it like this: + \code + CImgList<> list; // Assuming this image list is not empty + for (CImgList<>::iterator it = list.begin(); it* iterator; + + //! Simple const iterator type, to loop through each image of a \c const list instance. + /** + \note + - The \c CImgList::const_iterator type is defined to be a const CImg*. + - Similar to CImgList::iterator, but for constant list instances. + **/ + typedef const CImg* const_iterator; + + //! Pixel value type. + /** + Refer to the pixels value type of the images in the list. + \note + - The \c CImgList::value_type type of a \c CImgList is defined to be a \c T. + It is then similar to CImg::value_type. + - \c CImgList::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimglist_plugin +#include cimglist_plugin +#endif +#ifdef cimglist_plugin1 +#include cimglist_plugin1 +#endif +#ifdef cimglist_plugin2 +#include cimglist_plugin2 +#endif +#ifdef cimglist_plugin3 +#include cimglist_plugin3 +#endif +#ifdef cimglist_plugin4 +#include cimglist_plugin4 +#endif +#ifdef cimglist_plugin5 +#include cimglist_plugin5 +#endif +#ifdef cimglist_plugin6 +#include cimglist_plugin6 +#endif +#ifdef cimglist_plugin7 +#include cimglist_plugin7 +#endif +#ifdef cimglist_plugin8 +#include cimglist_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + Destroy current list instance. + \note + - Any allocated buffer is deallocated. + - Destroying an empty list does nothing actually. + **/ + ~CImgList() { + delete[] _data; + } + + //! Default constructor. + /** + Construct a new empty list instance. + \note + - An empty list has no pixel data and its dimension width() is set to \c 0, as well as its + image buffer pointer data(). + - An empty list may be reassigned afterwards, with the family of the assign() methods. + In all cases, the type of pixels stays \c T. + **/ + CImgList(): + _width(0),_allocated_width(0),_data(0) {} + + //! Construct list containing empty images. + /** + \param n Number of empty images. + \note Useful when you know by advance the number of images you want to manage, as + it will allocate the right amount of memory for the list, without needs for reallocation + (that may occur when starting from an empty list and inserting several images in it). + **/ + explicit CImgList(const unsigned int n):_width(n) { + if (n) _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + else { _allocated_width = 0; _data = 0; } + } + + //! Construct list containing images of specified size. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \note Pixel values are not initialized and may probably contain garbage. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + } + + //! Construct list containing images of specified size, and initialize pixel values. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val Initialization value for images pixels. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + } + + //! Construct list containing images of specified size, and initialize pixel values from a sequence of integers. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val0 First value of the initializing integers sequence. + \param val1 Second value of the initializing integers sequence. + \warning You must specify at least width*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...): + _width(0),_allocated_width(0),_data(0) { +#define _CImgList_stdarg(t) { \ + assign(n,width,height,depth,spectrum); \ + const ulongT siz = (ulongT)width*height*depth*spectrum, nsiz = siz*n; \ + T *ptrd = _data->_data; \ + va_list ap; \ + va_start(ap,val1); \ + for (ulongT l = 0, s = 0, i = 0; iwidth*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const double val0, const double val1, ...): + _width(0),_allocated_width(0),_data(0) { + _CImgList_stdarg(double); + } + + //! Construct list containing copies of an input image. + /** + \param n Number of images. + \param img Input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of \c img. + **/ + template + CImgList(const unsigned int n, const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + } + + //! Construct list from one image. + /** + \param img Input image to copy in the constructed list. + \param is_shared Tells if the element of the list is a shared or non-shared copy of \c img. + **/ + template + explicit CImgList(const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(1); + _data[0].assign(img,is_shared); + } + + //! Construct list from two images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + } + + //! Construct list from three images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + } + + //! Construct list from four images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + } + + //! Construct list from five images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + } + + //! Construct list from six images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + } + + //! Construct list from seven images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + } + + //! Construct list from eight images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param img8 Eighth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + } + + //! Construct list copy. + /** + \param list Input list to copy. + \note The shared state of each element of the constructed list is kept the same as in \c list. + **/ + template + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + } + + //! Construct list copy \specialization. + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],list[l]._is_shared); + } + + //! Construct list copy, and force the shared state of the list elements. + /** + \param list Input list to copy. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImgList& list, const bool is_shared):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],is_shared); + } + + //! Construct list by reading the content of a file. + /** + \param filename Filename, as a C-string. + **/ + explicit CImgList(const char *const filename):_width(0),_allocated_width(0),_data(0) { + assign(filename); + } + + //! Construct list from the content of a display window. + /** + \param disp Display window to get content from. + \note Constructed list contains a single image only. + **/ + explicit CImgList(const CImgDisplay& disp):_width(0),_allocated_width(0),_data(0) { + assign(disp); + } + + //! Return a list with elements being shared copies of images in the list instance. + /** + \note list2 = list1.get_shared() is equivalent to list2.assign(list1,true). + **/ + CImgList get_shared() { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Return a list with elements being shared copies of images in the list instance \const. + const CImgList get_shared() const { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Destructor \inplace. + /** + \see CImgList(). + **/ + CImgList& assign() { + delete[] _data; + _width = _allocated_width = 0; + _data = 0; + return *this; + } + + //! Destructor \inplace. + /** + Equivalent to assign(). + \note Only here for compatibility with STL naming conventions. + **/ + CImgList& clear() { + return assign(); + } + + //! Construct list containing empty images \inplace. + /** + \see CImgList(unsigned int). + **/ + CImgList& assign(const unsigned int n) { + if (!n) return assign(); + if (_allocated_width(n<<2)) { + delete[] _data; + _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + } + _width = n; + return *this; + } + + //! Construct list containing images of specified size \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + return *this; + } + + //! Construct list containing images of specified size, and initialize pixel values \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const T). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of integers \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const int, const int, ...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...) { + _CImgList_stdarg(int); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of doubles \inplace. + /** + \see CImgList(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,const double,const double,...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, + const double val0, const double val1, ...) { + _CImgList_stdarg(double); + return *this; + } + + //! Construct list containing copies of an input image \inplace. + /** + \see CImgList(unsigned int, const CImg&, bool). + **/ + template + CImgList& assign(const unsigned int n, const CImg& img, const bool is_shared=false) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + return *this; + } + + //! Construct list from one image \inplace. + /** + \see CImgList(const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img, const bool is_shared=false) { + assign(1); + _data[0].assign(img,is_shared); + return *this; + } + + //! Construct list from two images \inplace. + /** + \see CImgList(const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const bool is_shared=false) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + return *this; + } + + //! Construct list from three images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + return *this; + } + + //! Construct list from four images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + return *this; + } + + //! Construct list from five images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + return *this; + } + + //! Construct list from six images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + return *this; + } + + //! Construct list from seven images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, + const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + return *this; + } + + //! Construct list from eight images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, + const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + return *this; + } + + //! Construct list as a copy of an existing list and force the shared state of the list elements \inplace. + /** + \see CImgList(const CImgList&, bool is_shared). + **/ + template + CImgList& assign(const CImgList& list, const bool is_shared=false) { + cimg::unused(is_shared); + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + return *this; + } + + //! Construct list as a copy of an existing list and force shared state of elements \inplace \specialization. + CImgList& assign(const CImgList& list, const bool is_shared=false) { + if (this==&list) return *this; + CImgList res(list._width); + cimglist_for(res,l) res[l].assign(list[l],is_shared); + return res.move_to(*this); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& assign(const char *const filename) { + return load(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& assign(const CImgDisplay &disp) { + return assign(CImg(disp)); + } + + //! Transfer the content of the list instance to another list. + /** + \param list Destination list. + \note When returning, the current list instance is empty and the initial content of \c list is destroyed. + **/ + template + CImgList& move_to(CImgList& list) { + list.assign(_width); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[l]); + assign(); + return list; + } + + //! Transfer the content of the list instance at a specified position in another list. + /** + \param list Destination list. + \param pos Index of the insertion in the list. + \note When returning, the list instance is empty and the initial content of \c list is preserved + (only images indexes may be modified). + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos) { + if (is_empty()) return list; + const unsigned int npos = pos>list._width?list._width:pos; + list.insert(_width,npos); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[npos + l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[npos + l]); + assign(); + return list; + } + + //! Swap all fields between two list instances. + /** + \param list List to swap fields with. + \note Can be used to exchange the content of two lists in a fast way. + **/ + CImgList& swap(CImgList& list) { + cimg::swap(_width,list._width,_allocated_width,list._allocated_width); + cimg::swap(_data,list._data); + return list; + } + + //! Return a reference to an empty list. + /** + \note Can be used to define default values in a function taking a CImgList as an argument. + \code + void f(const CImgList& list=CImgList::empty()); + \endcode + **/ + static CImgList& empty() { + static CImgList _empty; + return _empty.assign(); + } + + //! Return a reference to an empty list \const. + static const CImgList& const_empty() { + static const CImgList _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Return a reference to one image element of the list. + /** + \param pos Index of the image element. + **/ + CImg& operator()(const unsigned int pos) { +#if cimg_verbosity>=3 + if (pos>=_width) { + cimg::warn(_cimglist_instance + "operator(): Invalid image request, at position [%u].", + cimglist_instance, + pos); + return *_data; + } +#endif + return _data[pos]; + } + + //! Return a reference to one image of the list. + /** + \param pos Index of the image element. + **/ + const CImg& operator()(const unsigned int pos) const { + return const_cast*>(this)->operator()(pos); + } + + //! Return a reference to one pixel value of one image of the list. + /** + \param pos Index of the image element. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list(n,x,y,z,c) is equivalent to list[n](x,y,z,c). + **/ + T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + return (*this)[pos](x,y,z,c); + } + + //! Return a reference to one pixel value of one image of the list \const. + const T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return (*this)[pos](x,y,z,c); + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + operator CImg*() { + return _data; + } + + //! Return pointer to the first image of the list \const. + operator const CImg*() const { + return _data; + } + + //! Construct list from one image \inplace. + /** + \param img Input image to copy in the constructed list. + \note list = img; is equivalent to list.assign(img);. + **/ + template + CImgList& operator=(const CImg& img) { + return assign(img); + } + + //! Construct list from another list. + /** + \param list Input list to copy. + \note list1 = list2 is equivalent to list1.assign(list2);. + **/ + template + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list from another list \specialization. + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& operator=(const char *const filename) { + return assign(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return a non-shared copy of a list. + /** + \note +list is equivalent to CImgList(list,false). + It forces the copy to have non-shared elements. + **/ + CImgList operator+() const { + return CImgList(*this,false); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end. + /** + \param img Image inserted at the end of the instance copy. + \note Define a convenient way to create temporary lists of images, as in the following code: + \code + (img1,img2,img3,img4).display("My four images"); + \endcode + **/ + template + CImgList& operator,(const CImg& img) { + return insert(img); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end \const. + template + CImgList operator,(const CImg& img) const { + return (+*this).insert(img); + } + + //! Return a copy of the list instance, where all elements of input list \c list have been inserted at the end. + /** + \param list List inserted at the end of the instance copy. + **/ + template + CImgList& operator,(const CImgList& list) { + return insert(list); + } + + //! Return a copy of the list instance, where all elements of input \c list have been inserted at the end \const. + template + CImgList& operator,(const CImgList& list) const { + return (+*this).insert(list); + } + + //! Return image corresponding to the appending of all images of the instance list along specified axis. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \note list>'x' is equivalent to list.get_append('x'). + **/ + CImg operator>(const char axis) const { + return get_append(axis,0); + } + + //! Return list corresponding to the splitting of all images of the instance list along specified axis. + /** + \param axis Axis used for image splitting. + \note list<'x' is equivalent to list.get_split('x'). + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to size() but returns result as a (signed) integer. + **/ + int width() const { + return (int)_width; + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to width() but returns result as an unsigned integer. + **/ + unsigned int size() const { + return _width; + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + CImg *data() { + return _data; + } + + //! Return pointer to the first image of the list \const. + const CImg *data() const { + return _data; + } + + //! Return pointer to the pos-th image of the list. + /** + \param pos Index of the image element to access. + \note list.data(n); is equivalent to list.data + n;. + **/ +#if cimg_verbosity>=3 + CImg *data(const unsigned int pos) { + if (pos>=size()) + cimg::warn(_cimglist_instance + "data(): Invalid pointer request, at position [%u].", + cimglist_instance, + pos); + return _data + pos; + } + + const CImg *data(const unsigned int l) const { + return const_cast*>(this)->data(l); + } +#else + CImg *data(const unsigned int l) { + return _data + l; + } + + //! Return pointer to the pos-th image of the list \const. + const CImg *data(const unsigned int l) const { + return _data + l; + } +#endif + + //! Return iterator to the first image of the list. + /** + **/ + iterator begin() { + return _data; + } + + //! Return iterator to the first image of the list \const. + const_iterator begin() const { + return _data; + } + + //! Return iterator to one position after the last image of the list. + /** + **/ + iterator end() { + return _data + _width; + } + + //! Return iterator to one position after the last image of the list \const. + const_iterator end() const { + return _data + _width; + } + + //! Return reference to the first image of the list. + /** + **/ + CImg& front() { + return *_data; + } + + //! Return reference to the first image of the list \const. + const CImg& front() const { + return *_data; + } + + //! Return a reference to the last image of the list. + /** + **/ + const CImg& back() const { + return *(_data + _width - 1); + } + + //! Return a reference to the last image of the list \const. + CImg& back() { + return *(_data + _width - 1); + } + + //! Return pos-th image of the list. + /** + \param pos Index of the image element to access. + **/ + CImg& at(const int pos) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "at(): Empty instance.", + cimglist_instance); + + return _data[cimg::cut(pos,0,width() - 1)]; + } + + //! Access to pixel value with Dirichlet boundary conditions. + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions. + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + T& _atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + T _atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + T& _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + T _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 coordinates (\c pos, \c x,\c y). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + T& _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + T _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 coordinates (\c pos,\c x). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 coordinates (\c pos,\c x) \const. + T atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x) \const. + T atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + T& _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + T _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the coordinate (\c pos). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):(*this)(pos,x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the coordinate (\c pos) \const. + T atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:(*this)(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos) \const. + T atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + T& _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + T _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Return \c true if list is empty. + /** + **/ + bool is_empty() const { + return (!_data || !_width); + } + + //! Test if number of image elements is equal to specified value. + /** + \param size_n Number of image elements to test. + **/ + bool is_sameN(const unsigned int size_n) const { + return _width==size_n; + } + + //! Test if number of image elements is equal between two images lists. + /** + \param list Input list to compare with. + **/ + template + bool is_sameN(const CImgList& list) const { + return is_sameN(list._width); + } + + // Define useful functions to check list dimensions. + // (cannot be documented because macro-generated). +#define _cimglist_def_is_same1(axis) \ + bool is_same##axis(const unsigned int val) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(val); \ + return res; \ + } \ + bool is_sameN##axis(const unsigned int n, const unsigned int val) const { \ + return is_sameN(n) && is_same##axis(val); \ + } \ + +#define _cimglist_def_is_same2(axis1,axis2) \ + bool is_same##axis1##axis2(const unsigned int val1, const unsigned int val2) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2(val1,val2); \ + return res; \ + } \ + bool is_sameN##axis1##axis2(const unsigned int n, const unsigned int val1, const unsigned int val2) const { \ + return is_sameN(n) && is_same##axis1##axis2(val1,val2); \ + } \ + +#define _cimglist_def_is_same3(axis1,axis2,axis3) \ + bool is_same##axis1##axis2##axis3(const unsigned int val1, const unsigned int val2, \ + const unsigned int val3) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2##axis3(val1,val2,val3); \ + return res; \ + } \ + bool is_sameN##axis1##axis2##axis3(const unsigned int n, const unsigned int val1, \ + const unsigned int val2, const unsigned int val3) const { \ + return is_sameN(n) && is_same##axis1##axis2##axis3(val1,val2,val3); \ + } \ + +#define _cimglist_def_is_same(axis) \ + template bool is_same##axis(const CImg& img) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(img); \ + return res; \ + } \ + template bool is_same##axis(const CImgList& list) const { \ + const unsigned int lmin = std::min(_width,list._width); \ + bool res = true; \ + for (unsigned int l = 0; l bool is_sameN##axis(const unsigned int n, const CImg& img) const { \ + return (is_sameN(n) && is_same##axis(img)); \ + } \ + template bool is_sameN##axis(const CImgList& list) const { \ + return (is_sameN(list) && is_same##axis(list)); \ + } + + _cimglist_def_is_same(XY) + _cimglist_def_is_same(XZ) + _cimglist_def_is_same(XC) + _cimglist_def_is_same(YZ) + _cimglist_def_is_same(YC) + _cimglist_def_is_same(XYZ) + _cimglist_def_is_same(XYC) + _cimglist_def_is_same(YZC) + _cimglist_def_is_same(XYZC) + _cimglist_def_is_same1(X) + _cimglist_def_is_same1(Y) + _cimglist_def_is_same1(Z) + _cimglist_def_is_same1(C) + _cimglist_def_is_same2(X,Y) + _cimglist_def_is_same2(X,Z) + _cimglist_def_is_same2(X,C) + _cimglist_def_is_same2(Y,Z) + _cimglist_def_is_same2(Y,C) + _cimglist_def_is_same2(Z,C) + _cimglist_def_is_same3(X,Y,Z) + _cimglist_def_is_same3(X,Y,C) + _cimglist_def_is_same3(X,Z,C) + _cimglist_def_is_same3(Y,Z,C) + + //! Test if dimensions of each image of the list match specified arguments. + /** + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameXYZC(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + bool res = true; + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_sameXYZC(dx,dy,dz,dc); + return res; + } + + //! Test if list dimensions match specified arguments. + /** + \param n Number of images in the list. + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameNXYZC(const unsigned int n, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + return is_sameN(n) && is_sameXYZC(dx,dy,dz,dc); + } + + //! Test if list contains one particular pixel location. + /** + \param n Index of the image whom checked pixel value belong to. + \param x X-coordinate of the checked pixel value. + \param y Y-coordinate of the checked pixel value. + \param z Z-coordinate of the checked pixel value. + \param c C-coordinate of the checked pixel value. + **/ + bool containsNXYZC(const int n, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) return false; + return n>=0 && n=0 && x<_data[n].width() && y>=0 && y<_data[n].height() && + z>=0 && z<_data[n].depth() && c>=0 && c<_data[n].spectrum(); + } + + //! Test if list contains image with specified index. + /** + \param n Index of the checked image. + **/ + bool containsN(const int n) const { + if (is_empty()) return false; + return n>=0 && n + bool contains(const T& pixel, t& n, t& x, t&y, t& z, t& c) const { + if (is_empty()) return false; + cimglist_for(*this,l) if (_data[l].contains(pixel,x,y,z,c)) { n = (t)l; return true; } + return false; + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \param[out] z Z-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y,z). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y, t& z) const { + t c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y) const { + t z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x). + **/ + template + bool contains(const T& pixel, t& n, t& x) const { + t y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \note If true, set coordinates (n). + **/ + template + bool contains(const T& pixel, t& n) const { + t x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + **/ + bool contains(const T& pixel) const { + unsigned int n, x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if the list contains the image 'img'. + /** + \param img Reference to image to test. + \param[out] n Index of image in the list, if test succeeds. + \note If true, returns the position (n) of the image in the list. + **/ + template + bool contains(const CImg& img, t& n) const { + if (is_empty()) return false; + const CImg *const ptr = &img; + cimglist_for(*this,i) if (_data + i==ptr) { n = (t)i; return true; } + return false; + } + + //! Test if the list contains the image img. + /** + \param img Reference to image to test. + **/ + bool contains(const CImg& img) const { + unsigned int n; + return contains(img,n); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + //! Return a reference to the minimum pixel value of the instance list. + /** + **/ + T& min() { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the maximum pixel value of the instance list \const. + const T& max() const { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T max_value = *ptr_max; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + T& min_max(t& max_val) { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min_max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well \const. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + const T& min_max(t& max_val) const { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min_max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the minimum value as well. + /** + \param[out] min_val Value of the minimum value found. + **/ + template + T& max_min(t& min_val) { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max_min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max_min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + if (is_shared) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified shared image " + "CImg<%s>(%u,%u,%u,%u,%p) at position %u (pixel types are different).", + cimglist_instance, + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data,npos); + + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list + _data = new_data; + *_data = img; + } else { + if (new_data) { // Insert with re-allocation + if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos); + if (npos!=_width - 1) + std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + std::memset((void*)_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else if (npos!=_width - 1) // Insert without re-allocation + std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \specialization. + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list + _data = new_data; + if (is_shared && img) { + _data->_width = img._width; + _data->_height = img._height; + _data->_depth = img._depth; + _data->_spectrum = img._spectrum; + _data->_is_shared = true; + _data->_data = img._data; + } else *_data = img; + } + else { + if (new_data) { // Insert with re-allocation + if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos); + if (npos!=_width - 1) + std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + new_data[npos]._width = img._width; + new_data[npos]._height = img._height; + new_data[npos]._depth = img._depth; + new_data[npos]._spectrum = img._spectrum; + new_data[npos]._is_shared = true; + new_data[npos]._data = img._data; + } else { + new_data[npos]._width = new_data[npos]._height = new_data[npos]._depth = new_data[npos]._spectrum = 0; + new_data[npos]._data = 0; + new_data[npos] = img; + } + std::memset((void*)_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else { // Insert without re-allocation + if (npos!=_width - 1) + std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + _data[npos]._width = img._width; + _data[npos]._height = img._height; + _data[npos]._depth = img._depth; + _data[npos]._spectrum = img._spectrum; + _data[npos]._is_shared = true; + _data[npos]._data = img._data; + } else { + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + } + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \newinstance. + template + CImgList get_insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(img,pos,is_shared); + } + + //! Insert n empty images img into the current image list, at position \p pos. + /** + \param n Number of empty images to insert. + \param pos Index of the insertion. + **/ + CImgList& insert(const unsigned int n, const unsigned int pos=~0U) { + CImg empty; + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i get_insert(const unsigned int n, const unsigned int pos=~0U) const { + return (+*this).insert(n,pos); + } + + //! Insert \c n copies of the image \c img into the current image list, at position \c pos. + /** + \param n Number of image copies to insert. + \param img Image to insert by copy. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of \c img or not. + **/ + template + CImgList& insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + insert(img,npos,is_shared); + for (unsigned int i = 1; i + CImgList get_insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,img,pos,is_shared); + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos. + /** + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if ((void*)this!=(void*)&list) cimglist_for(list,l) insert(list[l],npos + l,is_shared); + else insert(CImgList(list),npos,is_shared); + return *this; + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos \newinstance. + template + CImgList get_insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(list,pos,is_shared); + } + + //! Insert n copies of the list \c list at position \c pos of the current list. + /** + \param n Number of list copies to insert. + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i + CImgList get_insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,list,pos,is_shared); + } + + //! Remove all images between from indexes. + /** + \param pos1 Starting index of the removal. + \param pos2 Ending index of the removal. + **/ + CImgList& remove(const unsigned int pos1, const unsigned int pos2) { + const unsigned int + npos1 = pos1=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + else { + if (tpos2>=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + + for (unsigned int k = npos1; k<=npos2; ++k) _data[k].assign(); + const unsigned int nb = 1 + npos2 - npos1; + if (!(_width-=nb)) return assign(); + if (_width>(_allocated_width>>4) || _allocated_width<=16) { // Removing items without reallocation + if (npos1!=_width) + std::memmove((void*)(_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg)*(_width - npos1)); + std::memset((void*)(_data + _width),0,sizeof(CImg)*nb); + } else { // Removing items with reallocation + _allocated_width>>=4; + while (_allocated_width>16 && _width<(_allocated_width>>1)) _allocated_width>>=1; + CImg *const new_data = new CImg[_allocated_width]; + if (npos1) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos1); + if (npos1!=_width) + std::memcpy((void*)(new_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg)*(_width - npos1)); + if (_width!=_allocated_width) + std::memset((void*)(new_data + _width),0,sizeof(CImg)*(_allocated_width - _width)); + std::memset((void*)_data,0,sizeof(CImg)*(_width + nb)); + delete[] _data; + _data = new_data; + } + } + return *this; + } + + //! Remove all images between from indexes \newinstance. + CImgList get_remove(const unsigned int pos1, const unsigned int pos2) const { + return (+*this).remove(pos1,pos2); + } + + //! Remove image at index \c pos from the image list. + /** + \param pos Index of the image to remove. + **/ + CImgList& remove(const unsigned int pos) { + return remove(pos,pos); + } + + //! Remove image at index \c pos from the image list \newinstance. + CImgList get_remove(const unsigned int pos) const { + return (+*this).remove(pos); + } + + //! Remove last image. + /** + **/ + CImgList& remove() { + return remove(_width - 1); + } + + //! Remove last image \newinstance. + CImgList get_remove() const { + return (+*this).remove(); + } + + //! Reverse list order. + CImgList& reverse() { + for (unsigned int l = 0; l<_width/2; ++l) (*this)[l].swap((*this)[_width - 1 - l]); + return *this; + } + + //! Reverse list order \newinstance. + CImgList get_reverse() const { + return (+*this).reverse(); + } + + //! Return a sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList& images(const unsigned int pos0, const unsigned int pos1) { + return get_images(pos0,pos1).move_to(*this); + } + + //! Return a sublist \newinstance. + CImgList get_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l]); + return res; + } + + //! Return a shared sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a shared sublist \newinstance. + const CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a single image which is the appending of all images of the current CImgList instance. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg get_append(const char axis, const float align=0) const { + if (is_empty()) return CImg(); + if (_width==1) return +((*this)[0]); + unsigned int dx = 0, dy = 0, dz = 0, dc = 0, pos = 0; + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { // Along the X-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx+=img._width; + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._height==1 && img._depth==1 && img._spectrum==1 && + res._height==1 && res._depth==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._width); + else + res.draw_image(pos, + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._width; + } + } break; + case 'y' : { // Along the Y-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy+=img._height; + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._depth==1 && img._spectrum==1 && + res._width==1 && res._depth==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._height); + else + res.draw_image((int)(align*(dx - img._width)), + pos, + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._height; + } + } break; + case 'z' : { // Along the Z-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz+=img._depth; + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._height==1 && img._spectrum==1 && + res._width==1 && res._height==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._depth); + else + res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + pos, + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._depth; + } + } break; + default : { // Along the C-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc+=img._spectrum; + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._height==1 && img._depth==1 && + res._width==1 && res._height==1 && res._depth==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._spectrum); + else + res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + pos, + img); + } + pos+=img._spectrum; + } + } + } + return res; + } + + //! Return a list where each image has been split along the specified axis. + /** + \param axis Axis to split images along. + \param nb Number of split parts for each image. + **/ + CImgList& split(const char axis, const int nb=-1) { + return get_split(axis,nb).move_to(*this); + } + + //! Return a list where each image has been split along the specified axis \newinstance. + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + cimglist_for(*this,l) _data[l].get_split(axis,nb).move_to(res,~0U); + return res; + } + + //! Insert image at the end of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_back(const CImg& img) { + return insert(img); + } + + //! Insert image at the front of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_front(const CImg& img) { + return insert(img,0); + } + + //! Insert list at the end of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_back(const CImgList& list) { + return insert(list); + } + + //! Insert list at the front of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_front(const CImgList& list) { + return insert(list,0); + } + + //! Remove last image. + /** + **/ + CImgList& pop_back() { + return remove(_width - 1); + } + + //! Remove first image. + /** + **/ + CImgList& pop_front() { + return remove(0); + } + + //! Remove image pointed by iterator. + /** + \param iter Iterator pointing to the image to remove. + **/ + CImgList& erase(const iterator iter) { + return remove(iter - _data); + } + + //@} + //---------------------------------- + // + //! \name Data Input + //@{ + //---------------------------------- + + //! Display a simple interactive interface to select images or sublists. + /** + \param disp Window instance to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \param exit_on_anykey Exit function when any key is pressed. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(CImgDisplay &disp, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + return _select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + //! Display a simple interactive interface to select images or sublists. + /** + \param title Title of a new window used to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \param exit_on_anykey Exit function when any key is pressed. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(const char *const title, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + CImg _select(CImgDisplay &disp, const char *const title, const bool feature_type, + const char axis, const float align, const bool exit_on_anykey, + const unsigned int orig, const bool resize_disp, + const bool exit_on_rightbutton, const bool exit_on_wheel) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "select(): Empty instance.", + cimglist_instance); + + // Create image correspondence table and get list dimensions for visualization. + CImgList _indices; + unsigned int max_width = 0, max_height = 0, sum_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + if (h>max_height) max_height = h; + sum_width+=w; sum_height+=h; + if (axis=='x') CImg(w,1,1,1,(unsigned int)l).move_to(_indices); + else CImg(h,1,1,1,(unsigned int)l).move_to(_indices); + } + const CImg indices0 = _indices>'x'; + + // Create display window. + if (!disp) { + if (axis=='x') disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1); + else disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1); + if (!title) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else { + if (title) disp.set_title("%s",title); + disp.move_inside_screen(); + } + if (resize_disp) { + if (axis=='x') disp.resize(cimg_fitscreen(sum_width,max_height,1),false); + else disp.resize(cimg_fitscreen(max_width,sum_height,1),false); + } + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).show_mouse(); + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + + // Enter event loop. + CImg visu0, visu; + CImg indices; + CImg positions(_width,4,1,1,-1); + int oindex0 = -1, oindex1 = -1, index0 = -1, index1 = -1; + bool is_clicked = false, is_selected = false, text_down = false, update_display = true; + unsigned int key = 0, font_size = 32; + + while (!is_selected && !disp.is_closed() && !key) { + + // Create background image. + if (!visu0) { + visu0.assign(disp._width,disp._height,1,3,0); visu.assign(); + (indices0.get_resize(axis=='x'?visu0._width:visu0._height,1)).move_to(indices); + unsigned int _ind = 0; + const CImg onexone(1,1,1,1,(T)0); + if (axis=='x') + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4)) + cimglist_for(*this,ind) { + unsigned int x0 = 0; + while (x0 &src = _data[ind]?_data[ind]:onexone; + CImg res; + src._get_select(disp,old_normalization,src._width/2,src._height/2,src._depth/2). + move_to(res); + const unsigned int h = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,true); + res.resize(x1 - x0,std::max(32U,h*disp._height/max_height),1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)x0; + positions(ind,1) = positions(ind,3) = (int)(align*(visu0.height() - res.height())); + positions(ind,2)+=res._width; + positions(ind,3)+=res._height - 1; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4)) + cimglist_for(*this,ind) { + unsigned int y0 = 0; + while (y0 &src = _data[ind]?_data[ind]:onexone; + CImg res; + src._get_select(disp,old_normalization,(src._width - 1)/2,(src._height - 1)/2,(src._depth - 1)/2). + move_to(res); + const unsigned int w = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,false); + res.resize(std::max(32U,w*disp._width/max_width),y1 - y0,1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)(align*(visu0.width() - res.width())); + positions(ind,1) = positions(ind,3) = (int)y0; + positions(ind,2)+=res._width - 1; + positions(ind,3)+=res._height; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + if (axis=='x') --positions(_ind,2); else --positions(_ind,3); + update_display = true; + } + + if (!visu || oindex0!=index0 || oindex1!=index1) { + if (index0>=0 && index1>=0) { + visu.assign(visu0,false); + const int indm = std::min(index0,index1), indM = std::max(index0,index1); + for (int ind = indm; ind<=indM; ++ind) if (positions(ind,0)>=0) { + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + background_color,0.2f); + if ((axis=='x' && positions(ind,2) - positions(ind,0)>=8) || + (axis!='x' && positions(ind,3) - positions(ind,1)>=8)) + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + foreground_color,0.9f,0xAAAAAAAA); + } + if (is_clicked) visu.__draw_text(" Images #%u - #%u, Size = %u ",font_size,(int)text_down, + orig + indm,orig + indM,indM - indm + 1); + else visu.__draw_text(" Image #%u (%u,%u,%u,%u) ",font_size,(int)text_down, + orig + index0, + _data[index0]._width, + _data[index0]._height, + _data[index0]._depth, + _data[index0]._spectrum); + update_display = true; + } else visu.assign(); + } + if (!visu) { visu.assign(visu0,true); update_display = true; } + if (update_display) { visu.display(disp); update_display = false; } + disp.wait(); + + // Manage user events. + const int xm = disp.mouse_x(), ym = disp.mouse_y(); + int index = -1; + + if (xm>=0) { + index = (int)indices(axis=='x'?xm:ym); + if (disp.button()&1) { + if (!is_clicked) { is_clicked = true; oindex0 = index0; index0 = index; } + oindex1 = index1; index1 = index; + if (!feature_type) is_selected = true; + } else { + if (!is_clicked) { oindex0 = oindex1 = index0; index0 = index1 = index; } + else is_selected = true; + } + } else { + if (is_clicked) { + if (!(disp.button()&1)) { is_clicked = is_selected = false; index0 = index1 = -1; } + else index1 = -1; + } else index0 = index1 = -1; + } + + if (disp.button()&4) { is_clicked = is_selected = false; index0 = index1 = -1; } + if (disp.button()&2 && exit_on_rightbutton) { is_selected = true; index1 = index0 = -1; } + if (disp.wheel() && exit_on_wheel) is_selected = true; + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(axis=='x'?sum_width:max_width,axis=='x'?max_height:sum_height,1),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).__draw_text(" Saving snapshot... ",font_size,(int)text_down).display(disp); + visu0.save(filename); + (+visu0).__draw_text(" Snapshot '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + } + disp.set_key(key,false).wait(); key = 0; + } break; + case cimg::keyO : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).__draw_text(" Saving instance... ",font_size,(int)text_down).display(disp); + save(filename); + (+visu0).__draw_text(" Instance '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + disp.set_key(key,false).wait(); key = 0; + } break; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (ym>=0 && ym<13) { if (!text_down) { visu.assign(); text_down = true; }} + else if (ym>=visu.height() - 13) { if (text_down) { visu.assign(); text_down = false; }} + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + CImg res(1,2,1,1,-1); + if (is_selected) { + if (feature_type) res.fill(std::min(index0,index1),std::max(index0,index1)); + else res.fill(index0); + } + if (!(disp.button()&2)) disp.set_button(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + disp.set_key(key); + return res; + } + + //! Load a list from a file. + /** + \param filename Filename to read data from. + **/ + CImgList& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load(): Specified filename is (null).", + cimglist_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const bool is_stdin = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimglist_load_plugin + cimglist_load_plugin(filename); +#endif +#ifdef cimglist_load_plugin1 + cimglist_load_plugin1(filename); +#endif +#ifdef cimglist_load_plugin2 + cimglist_load_plugin2(filename); +#endif +#ifdef cimglist_load_plugin3 + cimglist_load_plugin3(filename); +#endif +#ifdef cimglist_load_plugin4 + cimglist_load_plugin4(filename); +#endif +#ifdef cimglist_load_plugin5 + cimglist_load_plugin5(filename); +#endif +#ifdef cimglist_load_plugin6 + cimglist_load_plugin6(filename); +#endif +#ifdef cimglist_load_plugin7 + cimglist_load_plugin7(filename); +#endif +#ifdef cimglist_load_plugin8 + cimglist_load_plugin8(filename); +#endif + if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) load_cimg(filename); + else if (!cimg::strcasecmp(ext,"rec") || + !cimg::strcasecmp(ext,"par")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded && !is_stdin) { + std::FILE *const file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to open file '%s'.", + cimglist_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + cimg::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file as a single image. + if (!is_loaded) { + assign(1); + try { + _data->load(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to recognize format of file '%s'.", + cimglist_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load a list from a file \newinstance. + static CImgList get_load(const char *const filename) { + return CImgList().load(filename); + } + + //! Load a list from a .cimg file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_cimg(const char *const filename) { + return _load_cimg(0,filename); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename) { + return CImgList().load_cimg(filename); + } + + //! Load a list from a .cimg file. + /** + \param file File to read data from. + **/ + CImgList& load_cimg(std::FILE *const file) { + return _load_cimg(file,0); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file) { + return CImgList().load_cimg(file); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename) { +#ifdef cimg_use_zlib +#define _cimgz_load_cimg_case(Tss) { \ + Bytef *const cbuf = new Bytef[csiz]; \ + cimg::fread(cbuf,(size_t)csiz,nfile); \ + if (is_bool) { \ + CImg raw(W*H*D*C/8); \ + uLongf destlen = (uLongf)raw.size(); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,(uLong)csiz); \ + img.assign(W,H,D,C); \ + img._uchar2bool(raw,raw.size(),false); \ + } else { \ + CImg raw(W,H,D,C); \ + uLongf destlen = (uLongf)(raw.size()*sizeof(Tss)); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,(uLong)csiz); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } \ + delete[] cbuf; \ +} +#else +#define _cimgz_load_cimg_case(Tss) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Unable to load compressed data from file '%s' unless zlib is enabled.", \ + cimglist_instance, \ + filename?filename:"(FILE*)"); +#endif + +#define _cimg_load_cimg_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + const bool is_bool = cimg::type::string()==cimg::type::string(); \ + for (unsigned int l = 0; l=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; csiz = 0; \ + if ((err = cimg_sscanf(tmp,"%u %u %u %u #" cimg_fuint64,&W,&H,&D,&C,&csiz))<4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'.", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:("(FILE*)")); \ + if (W*H*D*C>0) { \ + CImg &img = _data[l]; \ + if (err==5) _cimgz_load_cimg_case(Tss) \ + else { \ + img.assign(W,H,D,C); \ + T *ptrd = img._data; \ + if (is_bool) { \ + CImg raw; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + CImg(ptrd,std::min(8*raw._width,(unsigned int)(img.end() - ptrd)),1,1,1,true).\ + _uchar2bool(raw,raw._width,false); \ + to_read-=raw._width; \ + } \ + } else { \ + CImg raw; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + const Tss *ptrs = raw._data; \ + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + to_read-=raw._width; \ + } \ + } \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + + const ulongT cimg_iobuffer = (ulongT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + cimg_uint64 csiz; + int i, err; + do { + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; + } while (*tmp=='#' && i>=0); + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + assign(N); + _cimg_load_cimg_case("bool",bool); + _cimg_load_cimg_case("unsigned_char",unsigned char); + _cimg_load_cimg_case("uchar",unsigned char); + _cimg_load_cimg_case("char",char); + _cimg_load_cimg_case("unsigned_short",unsigned short); + _cimg_load_cimg_case("ushort",unsigned short); + _cimg_load_cimg_case("short",short); + _cimg_load_cimg_case("unsigned_int",unsigned int); + _cimg_load_cimg_case("uint",unsigned int); + _cimg_load_cimg_case("int",int); + _cimg_load_cimg_case("unsigned_long",ulongT); + _cimg_load_cimg_case("ulong",ulongT); + _cimg_load_cimg_case("long",longT); + _cimg_load_cimg_case("unsigned_int64",uint64T); + _cimg_load_cimg_case("uint64",uint64T); + _cimg_load_cimg_case("int64",int64T); + _cimg_load_cimg_case("float",float); + _cimg_load_cimg_case("double",double); + + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a sublist list from a (non compressed) .cimg file. + /** + \param filename Filename to read data from. + \param n0 Starting index of images to read (~0U for max). + \param n1 Ending index of images to read (~0U for max). + \param x0 Starting X-coordinates of image regions to read. + \param y0 Starting Y-coordinates of image regions to read. + \param z0 Starting Z-coordinates of image regions to read. + \param c0 Starting C-coordinates of image regions to read. + \param x1 Ending X-coordinates of image regions to read (~0U for max). + \param y1 Ending Y-coordinates of image regions to read (~0U for max). + \param z1 Ending Z-coordinates of image regions to read (~0U for max). + \param c1 Ending C-coordinates of image regions to read (~0U for max). + **/ + CImgList& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(0,filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sublist list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \overloading. + CImgList& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(file,0,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { +#define _cimg_load_cimg_case2(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l<=nn1; ++l) { \ + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; \ + if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:"(FILE*)"); \ + if (W*H*D*C>0) { \ + if (l=W || ny0>=H || nz0>=D || nc0>=C) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const unsigned int \ + _nx1 = nx1==~0U?W - 1:nx1, \ + _ny1 = ny1==~0U?H - 1:ny1, \ + _nz1 = nz1==~0U?D - 1:nz1, \ + _nc1 = nc1==~0U?C - 1:nc1; \ + if (_nx1>=W || _ny1>=H || _nz1>=D || _nc1>=C) \ + throw CImgArgumentException(_cimglist_instance \ + "load_cimg(): Invalid specified coordinates " \ + "[%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " \ + "because image [%u] in file '%s' has size (%u,%u,%u,%u).", \ + cimglist_instance, \ + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,l,filename?filename:"(FILE*)",W,H,D,C); \ + CImg raw(1 + _nx1 - nx0); \ + CImg &img = _data[l - nn0]; \ + img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \ + T *ptrd = img._data; \ + ulongT skipvb = nc0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \ + const ulongT skipzb = nz0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \ + const ulongT skipyb = ny0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \ + const ulongT skipxb = nx0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \ + const Tss *ptrs = raw._data; \ + for (unsigned int off = raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + const ulongT skipxe = (W - 1 - _nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const ulongT skipye = (H - 1 - _ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const ulongT skipze = (D - 1 - _nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const ulongT skipve = (C - 1 - _nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + unsigned int + nn0 = std::min(n0,n1), nn1 = std::max(n0,n1), + nx0 = std::min(x0,x1), nx1 = std::max(x0,x1), + ny0 = std::min(y0,y1), ny1 = std::max(y0,y1), + nz0 = std::min(z0,z1), nz1 = std::max(z0,z1), + nc0 = std::min(c0,c1), nc1 = std::max(c0,c1); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + nn1 = n1==~0U?N - 1:n1; + if (nn1>=N) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " + "because file '%s' contains only %u images.", + cimglist_instance, + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,filename?filename:"(FILE*)",N); + assign(1 + nn1 - n0); + _cimg_load_cimg_case2("bool",bool); + _cimg_load_cimg_case2("unsigned_char",unsigned char); + _cimg_load_cimg_case2("uchar",unsigned char); + _cimg_load_cimg_case2("char",char); + _cimg_load_cimg_case2("unsigned_short",unsigned short); + _cimg_load_cimg_case2("ushort",unsigned short); + _cimg_load_cimg_case2("short",short); + _cimg_load_cimg_case2("unsigned_int",unsigned int); + _cimg_load_cimg_case2("uint",unsigned int); + _cimg_load_cimg_case2("int",int); + _cimg_load_cimg_case2("unsigned_long",ulongT); + _cimg_load_cimg_case2("ulong",ulongT); + _cimg_load_cimg_case2("long",longT); + _cimg_load_cimg_case2("unsigned_int64",uint64T); + _cimg_load_cimg_case2("uint64",uint64T); + _cimg_load_cimg_case2("int64",int64T); + _cimg_load_cimg_case2("float",float); + _cimg_load_cimg_case2("double",double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_parrec(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_parrec(): Specified filename is (null).", + cimglist_instance); + + CImg body(1024), filenamepar(1024), filenamerec(1024); + *body = *filenamepar = *filenamerec = 0; + const char *const ext = cimg::split_filename(filename,body); + if (!std::strcmp(ext,"par")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.rec",body._data); + } + if (!std::strcmp(ext,"PAR")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.REC",body._data); + } + if (!std::strcmp(ext,"rec")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.par",body._data); + } + if (!std::strcmp(ext,"REC")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.PAR",body._data); + } + std::FILE *file = cimg::fopen(filenamepar,"r"); + + // Parse header file + CImgList st_slices; + CImgList st_global; + CImg line(256); *line = 0; + int err; + do { err = std::fscanf(file,"%255[^\n]%*c",line._data); } while (err!=EOF && (*line=='#' || *line=='.')); + do { + unsigned int sn,size_x,size_y,pixsize; + float rs,ri,ss; + err = std::fscanf(file,"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&size_x,&size_y,&ri,&rs,&ss); + if (err==7) { + CImg::vector((float)sn,(float)pixsize,(float)size_x,(float)size_y,ri,rs,ss,0).move_to(st_slices); + unsigned int i; for (i = 0; i::vector(size_x,size_y,sn).move_to(st_global); + else { + CImg &vec = st_global[i]; + if (size_x>vec[0]) vec[0] = size_x; + if (size_y>vec[1]) vec[1] = size_y; + vec[2] = sn; + } + st_slices[st_slices._width - 1][7] = (float)i; + } + } while (err==7); + + // Read data + std::FILE *file2 = cimg::fopen(filenamerec,"rb"); + cimglist_for(st_global,l) { + const CImg& vec = st_global[l]; + CImg(vec[0],vec[1],vec[2]).move_to(*this); + } + + cimglist_for(st_slices,l) { + const CImg& vec = st_slices[l]; + const unsigned int + sn = (unsigned int)vec[0] - 1, + pixsize = (unsigned int)vec[1], + size_x = (unsigned int)vec[2], + size_y = (unsigned int)vec[3], + imn = (unsigned int)vec[7]; + const float ri = vec[4], rs = vec[5], ss = vec[6]; + switch (pixsize) { + case 8 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 16 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 32 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + default : + cimg::fclose(file); + cimg::fclose(file2); + throw CImgIOException(_cimglist_instance + "load_parrec(): Unsupported %d-bits pixel type for file '%s'.", + cimglist_instance, + pixsize,filename); + } + } + cimg::fclose(file); + cimg::fclose(file2); + if (!_width) + throw CImgIOException(_cimglist_instance + "load_parrec(): Failed to recognize valid PAR-REC data in file '%s'.", + cimglist_instance, + filename); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file \newinstance. + static CImgList get_load_parrec(const char *const filename) { + return CImgList().load_parrec(filename); + } + + //! Load a list from a YUV image sequence file. + /** + \param filename Filename to read data from. + \param size_x Width of the images. + \param size_y Height of the images. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param yuv2rgb Apply YUV to RGB transformation during reading. + **/ + CImgList& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(0,filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from a YUV image sequence file \newinstance. + static CImgList get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \overloading. + CImgList& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(file,0,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \newinstance. + static CImgList get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + CImgList& _load_yuv(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling, + const unsigned int first_frame, const unsigned int last_frame, + const unsigned int step_frame, const bool yuv2rgb) { + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified filename is (null).", + cimglist_instance); + if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified chroma subsampling '%u' is invalid, for file '%s'.", + cimglist_instance, + chroma_subsampling,filename?filename:"(FILE*)"); + const unsigned int + cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1, + cfy = chroma_subsampling==420?2:1, + nfirst_frame = first_frame YUV(size_x,size_y,1,3), UV(size_x/cfx,size_y/cfy,1,2); + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool stop_flag = false; + int err; + if (nfirst_frame) { + err = cimg::fseek(nfile,(uint64T)nfirst_frame*(YUV._width*YUV._height + 2*UV._width*UV._height),SEEK_CUR); + if (err) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_yuv(): File '%s' doesn't contain frame number %u.", + cimglist_instance, + filename?filename:"(FILE*)",nfirst_frame); + } + } + unsigned int frame; + for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) { + YUV.get_shared_channel(0).fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(YUV._data),1,(size_t)YUV._width*YUV._height,nfile); + if (err!=(int)(YUV._width*YUV._height)) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + UV.fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(UV._data),1,(size_t)UV.size(),nfile); + if (err!=(int)(UV.size())) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + const ucharT *ptrs1 = UV._data, *ptrs2 = UV.data(0,0,0,1); + ucharT *ptrd1 = YUV.data(0,0,0,1), *ptrd2 = YUV.data(0,0,0,2); + const unsigned int wd = YUV._width; + switch (chroma_subsampling) { + case 420 : + cimg_forY(UV,y) { + cimg_forX(UV,x) { + const ucharT U = *(ptrs1++), V = *(ptrs2++); + ptrd1[wd] = U; *(ptrd1)++ = U; + ptrd1[wd] = U; *(ptrd1)++ = U; + ptrd2[wd] = V; *(ptrd2)++ = V; + ptrd2[wd] = V; *(ptrd2)++ = V; + } + ptrd1+=wd; ptrd2+=wd; + } + break; + case 422 : + cimg_forXY(UV,x,y) { + const ucharT U = *(ptrs1++), V = *(ptrs2++); + *(ptrd1++) = U; *(ptrd1++) = U; + *(ptrd2++) = V; *(ptrd2++) = V; + } + break; + default : + YUV.draw_image(0,0,0,1,UV); + } + if (yuv2rgb) YUV.YCbCrtoRGB(); + insert(YUV); + if (nstep_frame>1) cimg::fseek(nfile,(uint64T)(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR); + } + } + } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_yuv() : Missing data in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + if (stop_flag && nlast_frame!=~0U && frame!=nlast_frame) + cimg::warn(_cimglist_instance + "load_yuv(): Frame %d not reached since only %u frames were found in file '%s'.", + cimglist_instance, + nlast_frame,frame - 1,filename?filename:"(FILE*)"); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load an image from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read (can be higher than the actual number of frames, e.g. '~0U'). + \param step_frame Step value for frame reading. + \note If step_frame==0, the current video stream is forced to be released (without any frames read). + **/ + CImgList& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { +#ifndef cimg_use_opencv + if (first_frame || last_frame!=~0U || step_frame>1) + throw CImgArgumentException(_cimglist_instance + "load_video() : File '%s', arguments 'first_frame', 'last_frame' " + "and 'step_frame' requires features from the OpenCV library " + "('-Dcimg_use_opencv' must be defined).", + cimglist_instance,filename); + return load_custom_external(filename); +#else + static cv::VideoCapture *captures[32] = { 0 }; + static CImgList filenames(32); + static CImg positions(32,1,1,1,0); + static int last_used_index = -1; + + // Detect if a video capture already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Release stream if needed. + if (!step_frame || (index>=0 && positions[index]>first_frame)) { + if (index>=0) { + cimg::mutex(9); + captures[index]->release(); + delete captures[index]; + captures[index] = 0; + positions[index] = 0; + filenames[index].assign(); + if (last_used_index==index) last_used_index = -1; + index = -1; + cimg::mutex(9,0); + } else + if (filename) + cimg::warn(_cimglist_instance + "load_video() : File '%s', no opened video stream associated with filename found.", + cimglist_instance,filename); + else + cimg::warn(_cimglist_instance + "load_video() : No opened video stream found.", + cimglist_instance,filename); + if (!step_frame) return *this; + } + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_video(): No already open video reader found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', no video reader slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + cimg::mutex(9); + captures[index] = new cv::VideoCapture(filename); + positions[index] = 0; + if (!captures[index]->isOpened()) { + delete captures[index]; + captures[index] = 0; + cimg::mutex(9,0); + cimg::fclose(cimg::fopen(filename,"rb")); // Check file availability + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to detect format of video file.", + cimglist_instance,filename); + } + CImg::string(filename).move_to(filenames[index]); + cimg::mutex(9,0); + } + + cimg::mutex(9); + const unsigned int nb_frames = (unsigned int)std::max(0.,captures[index]->get(_cimg_cap_prop_frame_count)); + cimg::mutex(9,0); + assign(); + + // Skip frames if requested. + bool go_on = true; + unsigned int &pos = positions[index]; + while (posgrab()) { cimg::mutex(9,0); go_on = false; break; } + cimg::mutex(9,0); + ++pos; + } + + // Read and convert frames. + const unsigned int _last_frame = std::min(nb_frames?nb_frames - 1:~0U,last_frame); + while (go_on && pos<=_last_frame) { + cv::Mat cvimg; + cimg::mutex(9); + if (captures[index]->read(cvimg)) { CImg::_cvmat2cimg(cvimg).move_to(*this); ++pos; } + else go_on = false; + cimg::mutex(9,0); + if (go_on) + for (unsigned int i = 1; go_on && igrab()) go_on = false; + cimg::mutex(9,0); + } + } + + if (!go_on || (nb_frames && pos>=nb_frames)) { // Close video stream when necessary + cimg::mutex(9); + captures[index]->release(); + delete captures[index]; + captures[index] = 0; + filenames[index].assign(); + positions[index] = 0; + index = -1; + cimg::mutex(9,0); + } + + cimg::mutex(9); + last_used_index = index; + cimg::mutex(9,0); + + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to locate frame %u.", + cimglist_instance,filename,first_frame); + return *this; +#endif + } + + //! Load an image from a video file, using OpenCV library \newinstance. + static CImgList get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame); + } + + //! Load an image from a video file using the external tool 'custom'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_custom_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_custom_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%%6d.ppm",filename_tmp._data); + cimg_snprintf(command,command._width,"\"%s\" -v -8 -i \"%s\" \"%s\"", + cimg::custom_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp2)._system_strescape().data()); + cimg::system(command, cimg::custom_path()); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + unsigned int i = 1; + for (bool stop_flag = false; !stop_flag; ++i) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,i); + CImg img; + try { img.load_pnm(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + cimg::exception_mode(omode); + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_custom_external(): Failed to open file '%s' with external command 'custom'.", + cimglist_instance, + filename); + return *this; + } + + //! Load an image from a video file using the external tool 'custom' \newinstance. + static CImgList get_load_custom_external(const char *const filename) { + return CImgList().load_custom_external(filename); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gif_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_gif_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + if (!_load_gif_external(filename,false)) + if (!_load_gif_external(filename,true)) + try { assign(CImg().load_other(filename)); } catch (CImgException&) { assign(); } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_gif_external(): Failed to open file '%s'.", + cimglist_instance,filename); + return *this; + } + + CImgList& _load_gif_external(const char *const filename, const bool use_graphicsmagick=false) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.0",filename_tmp._data); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-0.png",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + if (use_graphicsmagick) cimg_snprintf(command,command._width,"%s convert \"%s\" \"%s.png\"", + cimg::graphicsmagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + else cimg_snprintf(command,command._width,"\"%s\" -coalesce \"%s\" \"%s.png\"", + cimg::imagemagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::imagemagick_path()); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + + // Try to read a single frame gif. + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png",filename_tmp._data); + CImg img; + try { img.load_png(filename_tmp2); } + catch (CImgException&) { } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + else { // Try to read animated gif + unsigned int i = 0; + for (bool stop_flag = false; !stop_flag; ++i) { + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.%u",filename_tmp._data,i); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-%u.png",filename_tmp._data,i); + try { img.load_png(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools \newinstance. + static CImgList get_load_gif_external(const char *const filename) { + return CImgList().load_gif_external(filename); + } + + //! Load a gzipped list, using external tool 'gunzip'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::gunzip_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Failed to open file '%s'.", + cimglist_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load a gzipped list, using external tool 'gunzip' \newinstance. + static CImgList get_load_gzip_external(const char *const filename) { + return CImgList().load_gzip_external(filename); + } + + //! Load images from a TIFF file. + /** + \param filename Filename to read data from. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + \param[out] voxel_size Voxel size, as stored in the filename. + \param[out] description Description, as stored in the filename. + **/ + CImgList& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + const unsigned int + nfirst_frame = first_frame::get_load_tiff(filename)); +#else +#if cimg_verbosity<3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimglist_instance + "load_tiff(): Invalid specified frame range is [%u,%u] (step %u) since " + "file '%s' contains %u image(s).", + cimglist_instance, + nfirst_frame,nlast_frame,nstep_frame,filename,nb_images); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + assign(1 + (nlast_frame - nfirst_frame)/nstep_frame); + TIFFSetDirectory(tif,0); + cimglist_for(*this,l) + _data[l]._load_tiff(tif,nfirst_frame + l*nstep_frame,bits_per_value,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimglist_instance + "load_tiff(): Failed to open file '%s'.", + cimglist_instance, + filename); + return *this; +#endif + } + + //! Load a multi-page TIFF file \newinstance. + static CImgList get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + return CImgList().load_tiff(filename,first_frame,last_frame,step_frame,bits_per_value,voxel_size,description); + } + + //@} + //---------------------------------- + // + //! \name Data Output + //@{ + //---------------------------------- + + //! Print information about the list on the standard output. + /** + \param title Label set to the information displayed. + \param display_stats Tells if image statistics must be computed and displayed. + **/ + const CImgList& print(const char *const title=0, const bool display_stats=true) const { + unsigned int msiz = 0; + cimglist_for(*this,l) msiz+=_data[l].size(); + msiz*=sizeof(T); + const unsigned int mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U; + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImgList<%s>",pixel_type()); + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%s>*)%p", + cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal, + cimg::t_bold,cimg::t_normal,(void*)this, + cimg::t_bold,cimg::t_normal,_width,_allocated_width, + mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)), + mdisp==0?"b":(mdisp==1?"Kio":"Mio"), + cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin()); + if (_data) std::fprintf(cimg::output(),"..%p.\n",(void*)((char*)end() - 1)); + else std::fprintf(cimg::output(),".\n"); + + char tmp[16] = { 0 }; + cimglist_for(*this,ll) { + cimg_snprintf(tmp,sizeof(tmp),"[%d]",ll); + std::fprintf(cimg::output()," "); + _data[ll].print(tmp,display_stats); + if (ll==3 && width()>8) { ll = width() - 5; std::fprintf(cimg::output()," ...\n"); } + } + std::fflush(cimg::output()); + return *this; + } + + //! Display the current CImgList instance in an existing CImgDisplay window (by reference). + /** + \param disp Reference to an existing CImgDisplay instance, where the current image list will be displayed. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + \note This function displays the list images of the current CImgList instance into an existing + CImgDisplay window. + Images of the list are appended in a single temporary image for visualization purposes. + The function returns immediately. + **/ + const CImgList& display(CImgDisplay &disp, const char axis='x', const float align=0) const { + disp.display(*this,axis,align); + return *this; + } + + //! Display the current CImgList instance in a new display window. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param axis Alignment axis for images viewing. + \param align Appending alignment. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + \note This function opens a new window with a specific title and displays the list images of the + current CImgList instance into it. + Images of the list are appended in a single temporary image for visualization purposes. + The function returns when a key is pressed or the display window is closed by the user. + **/ + const CImgList& display(CImgDisplay &disp, const bool display_info, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + bool is_exit = false; + return _display(disp,0,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + //! Display the current CImgList instance in a new display window. + /** + \param title Title of the opening display window. + \param display_info Tells if list information must be written on standard output. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImgList& display(const char *const title=0, const bool display_info=true, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + CImgDisplay disp; + bool is_exit = false; + return _display(disp,title,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + const CImgList& _display(CImgDisplay &disp, const char *const title, const CImgList *const titles, + const bool display_info, const char axis, const float align, unsigned int *const XYZ, + const bool exit_on_anykey, const unsigned int orig, const bool is_first_call, + bool &is_exit) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "display(): Empty instance.", + cimglist_instance); + if (!disp) { + if (axis=='x') { + unsigned int sum_width = 0, max_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + sum_width+=w; + if (h>max_height) max_height = h; + } + disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:titles?titles->__display()._data:0,1); + } else { + unsigned int max_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + sum_height+=h; + } + disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:titles?titles->__display()._data:0,1); + } + if (!title && !titles) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else if (title) disp.set_title("%s",title); + else if (titles) disp.set_title("%s",titles->__display()._data); + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(disp.title()); + disp.show().flush(); + + if (_width==1) { + const unsigned int dw = disp._width, dh = disp._height; + if (!is_first_call) + disp.resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),false); + disp.set_title("%s (%ux%ux%ux%u)", + dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum); + _data[0]._display(disp,0,false,XYZ,exit_on_anykey,!is_first_call); + if (disp.key()) is_exit = true; + disp.resize(cimg_fitscreen(dw,dh,1),false).set_title("%s",dtitle.data()); + } else { + bool disp_resize = !is_first_call; + while (!disp.is_closed() && !is_exit) { + const CImg s = _select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true); + disp_resize = true; + if (s[0]<0 && !disp.wheel()) { // No selections done + if (disp.button()&2) { disp.flush(); break; } + is_exit = true; + } else if (disp.wheel()) { // Zoom in/out + const int wheel = disp.wheel(); + disp.set_wheel(); + if (!is_first_call && wheel<0) break; + if (wheel>0 && _width>=4) { + const unsigned int + delta = std::max(1U,(unsigned int)cimg::round(0.3*_width)), + ind0 = (unsigned int)std::max(0,s[0] - (int)delta), + ind1 = (unsigned int)std::min(width() - 1,s[0] + (int)delta); + if ((ind0!=0 || ind1!=_width - 1) && ind1 - ind0>=3) { + const CImgList sublist = get_shared_images(ind0,ind1); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(ind0,ind1); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + ind0,false,is_exit); + } + } + } else if (s[0]!=0 || s[1]!=width() - 1) { + const CImgList sublist = get_shared_images(s[0],s[1]); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(s[0],s[1]); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + s[0],false,is_exit); + } + disp.set_title("%s",dtitle.data()); + } + } + return *this; + } + + // [internal] Return string to describe display title. + CImg __display() const { + CImg res, str; + cimglist_for(*this,l) { + CImg::string((char*)_data[l]).move_to(str); + if (l!=width() - 1) { + str.resize(str._width + 1,1,1,1,0); + str[str._width - 2] = ','; + str[str._width - 1] = ' '; + } + res.append(str,'x'); + } + if (!res) return CImg(1,1,1,1,0).move_to(res); + cimg::strellipsize(res,128,false); + if (_width>1) { + const unsigned int l = (unsigned int)std::strlen(res); + if (res._width<=l + 16) res.resize(l + 16,1,1,1,0); + cimg_snprintf(res._data + l,16," (#%u)",_width); + } + return res; + } + + //! Save list into a file. + /** + \param filename Filename to write data to. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + **/ + const CImgList& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save(): Specified filename is (null).", + cimglist_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:number>=0?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimglist_save_plugin + cimglist_save_plugin(fn); +#endif +#ifdef cimglist_save_plugin1 + cimglist_save_plugin1(fn); +#endif +#ifdef cimglist_save_plugin2 + cimglist_save_plugin2(fn); +#endif +#ifdef cimglist_save_plugin3 + cimglist_save_plugin3(fn); +#endif +#ifdef cimglist_save_plugin4 + cimglist_save_plugin4(fn); +#endif +#ifdef cimglist_save_plugin5 + cimglist_save_plugin5(fn); +#endif +#ifdef cimglist_save_plugin6 + cimglist_save_plugin6(fn); +#endif +#ifdef cimglist_save_plugin7 + cimglist_save_plugin7(fn); +#endif +#ifdef cimglist_save_plugin8 + cimglist_save_plugin8(fn); +#endif + if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg") || !*ext) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,444,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); +#ifdef cimg_use_tiff + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); +#endif + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + else { + if (_width==1) _data[0].save(fn,-1); + else cimglist_for(*this,l) { _data[l].save(fn,is_stdout?-1:l); if (is_stdout) std::fputc(EOF,cimg::_stdout()); } + } + return *this; + } + + //! Tell if an image list can be saved as one single file. + /** + \param filename Filename, as a C-string. + \return \c true if the file format supports multiple images, \c false otherwise. + **/ + static bool is_saveable(const char *const filename) { + const char *const ext = cimg::split_filename(filename); + if (!cimg::strcasecmp(ext,"cimgz") || +#ifdef cimg_use_tiff + !cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff") || +#endif + !cimg::strcasecmp(ext,"yuv") || + !cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return true; + return false; + } + + //! Save image sequence as a GIF animated file. + /** + \param filename Filename to write data to. + \param fps Number of desired frames per second. + \param nb_loops Number of loops (\c 0 for infinite looping). + **/ + const CImgList& save_gif_external(const char *const filename, const float fps=25, + const unsigned int nb_loops=0) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + +#ifdef cimg_use_png +#define _cimg_save_gif_extension "png" +#else +#define _cimg_save_gif_extension "ppm" +#endif + + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001." _cimg_save_gif_extension,filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u." _cimg_save_gif_extension,filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save(filename_tmp2); + else _data[l].save(filename_tmp2); + } + cimg_snprintf(command,command._width,"\"%s\" -delay %u -loop %u", + cimg::imagemagick_path(),(unsigned int)std::max(0.f,cimg::round(100/fps)),nb_loops); + CImg::string(command).move_to(filenames,0); + cimg_snprintf(command,command._width,"\"%s\"", + CImg::string(filename)._system_strescape().data()); + CImg::string(command).move_to(filenames); + CImg _command = filenames>'x'; + cimg_for(_command,p,char) if (!*p) *p = ' '; + _command.back() = 0; + + cimg::system(_command, cimg::imagemagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for_in(*this,1,filenames._width - 1,l) std::remove(filenames[l]); + return *this; + } + + //! Save list as a YUV image sequence file. + /** + \param filename Filename to write data to. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(const char *const filename=0, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + return _save_yuv(0,filename,chroma_subsampling,is_rgb); + } + + //! Save image sequence into a YUV file. + /** + \param file File to write data to. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(std::FILE *const file, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + return _save_yuv(file,0,chroma_subsampling,is_rgb); + } + + const CImgList& _save_yuv(std::FILE *const file, const char *const filename, + const unsigned int chroma_subsampling, + const bool is_rgb) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified filename is (null).", + cimglist_instance); + if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified chroma subsampling %u is invalid, for file '%s'.", + cimglist_instance, + chroma_subsampling,filename?filename:"(FILE*)"); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + const unsigned int + cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1, + cfy = chroma_subsampling==420?2:1, + w0 = (*this)[0]._width, h0 = (*this)[0]._height, + width0 = w0 + (w0%cfx), height0 = h0 + (h0%cfy); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + cimglist_for(*this,l) { + const CImg &frame = (*this)[l]; + cimg_forZ(frame,z) { + CImg YUV; + if (sizeof(T)==1 && !is_rgb && + frame._width==width0 && frame._height==height0 && frame._depth==1 && frame._spectrum==3) + YUV.assign((unsigned char*)frame._data,width0,height0,1,3,true); + else { + YUV = frame.get_slice(z); + if (YUV._width!=width0 || YUV._height!=height0) YUV.resize(width0,height0,1,-100,0); + if (YUV._spectrum!=3) YUV.resize(-100,-100,1,3,YUV._spectrum==1?1:0); + if (is_rgb) YUV.RGBtoYCbCr(); + } + if (chroma_subsampling==444) + cimg::fwrite(YUV._data,(size_t)YUV._width*YUV._height*3,nfile); + else { + cimg::fwrite(YUV._data,(size_t)YUV._width*YUV._height,nfile); + CImg UV = YUV.get_channels(1,2); + UV.resize(UV._width/cfx,UV._height/cfy,1,2,2); + cimg::fwrite(UV._data,(size_t)UV._width*UV._height*2,nfile); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param filename Filename to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(const char *const filename, const bool is_compressed=false) const { + return _save_cimg(0,filename,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, const bool is_compressed) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "save_cimg(): Unable to save compressed data in file '%s' unless zlib is enabled, " + "saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); +#endif + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const bool is_bool = ptype==cimg::type::string(); + if (!is_bool && std::strstr(ptype,"unsigned")==ptype) + std::fprintf(nfile,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + std::fprintf(nfile,"%u %s %s_endian\n",_width,ptype,etype); + + cimglist_for(*this,l) { + const CImg& img = _data[l]; + std::fprintf(nfile,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + Bytef *cbuf = 0; + uLongf csiz = 0; + + if (is_bool) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = ref._bool2uchar(siz,false); + csiz = siz + siz/100 + 16; + cbuf = new Bytef[csiz]; + failed_to_compress = (bool)compress(cbuf,&csiz,(Bytef*)buf,siz); + if (!failed_to_compress) { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + } + delete[] buf; + } else { // Non-boolean data + const ulongT siz = sizeof(T)*ref.size(); + csiz = siz + siz/100 + 16; + cbuf = new Bytef[csiz]; + failed_to_compress = (bool)compress(cbuf,&csiz,(Bytef*)ref._data,siz); + if (!failed_to_compress) { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + } + } + if (failed_to_compress) + cimg::warn(_cimglist_instance + "save_cimg(): Failed to save compressed data for file '%s', saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); + delete[] cbuf; +#endif + } + if (failed_to_compress) { // Write non-compressed + std::fputc('\n',nfile); + if (is_bool) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = ref._bool2uchar(siz,false); + cimg::fwrite(buf,siz,nfile); + delete[] buf; + } else cimg::fwrite(ref._data,ref.size(),nfile); // Non-boolean data + } + } else std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param file File to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(std::FILE *file, const bool is_compressed=false) const { + return _save_cimg(file,0,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { +#define _cimg_save_cimg_case(Ts,Tss) \ + if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l0) { \ + if (l=W || y0>=H || z0>=D || c0>=D) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const CImg& img = (*this)[l - n0]; \ + const T *ptrs = img._data; \ + const unsigned int \ + x1 = x0 + img._width - 1, \ + y1 = y0 + img._height - 1, \ + z1 = z0 + img._depth - 1, \ + c1 = c0 + img._spectrum - 1, \ + nx1 = x1>=W?W - 1:x1, \ + ny1 = y1>=H?H - 1:y1, \ + nz1 = z1>=D?D - 1:z1, \ + nc1 = c1>=C?C - 1:c1; \ + CImg raw(1 + nx1 - x0); \ + const unsigned int skipvb = c0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int v = 1 + nc1 - c0; v; --v) { \ + const unsigned int skipzb = z0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + nz1 - z0; z; --z) { \ + const unsigned int skipyb = y0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + ny1 - y0; y; --y) { \ + const unsigned int skipxb = x0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + raw.assign(ptrs, raw._width); \ + ptrs+=img._width; \ + if (endian) cimg::invert_endianness(raw._data,raw._width); \ + cimg::fwrite(raw._data,raw._width,nfile); \ + const unsigned int skipxe = (W - 1 - nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const unsigned int skipye = (H - 1 - ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const unsigned int skipze = (D - 1 - nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const unsigned int skipve = (C - 1 - nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_cimg(): Empty instance, for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb+"); + bool saved = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + const unsigned int lmax = std::min(N,n0 + _width); + _cimg_save_cimg_case("bool",bool); + _cimg_save_cimg_case("unsigned_char",unsigned char); + _cimg_save_cimg_case("uchar",unsigned char); + _cimg_save_cimg_case("char",char); + _cimg_save_cimg_case("unsigned_short",unsigned short); + _cimg_save_cimg_case("ushort",unsigned short); + _cimg_save_cimg_case("short",short); + _cimg_save_cimg_case("unsigned_int",unsigned int); + _cimg_save_cimg_case("uint",unsigned int); + _cimg_save_cimg_case("int",int); + _cimg_save_cimg_case("unsigned_int64",uint64T); + _cimg_save_cimg_case("uint64",uint64T); + _cimg_save_cimg_case("int64",int64T); + _cimg_save_cimg_case("float",float); + _cimg_save_cimg_case("double",double); + if (!saved) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): Unsupported data type '%s' for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)",str_pixeltype._data); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param filename Filename to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(0,filename,n0,x0,y0,z0,c0); + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param file File to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(file,0,n0,x0,y0,z0,c0); + } + + static void _save_empty_cimg(std::FILE *const file, const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT siz = (ulongT)dx*dy*dz*dc*sizeof(T); + std::fprintf(nfile,"%u %s\n",nb,pixel_type()); + for (unsigned int i=nb; i; --i) { + std::fprintf(nfile,"%u %u %u %u\n",dx,dy,dz,dc); + for (ulongT off = siz; off; --off) std::fputc(0,nfile); + } + if (!file) cimg::fclose(nfile); + } + + //! Save empty (non-compressed) .cimg file with specified dimensions. + /** + \param filename Filename to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(0,filename,nb,dx,dy,dz,dc); + } + + //! Save empty .cimg file with specified dimensions. + /** + \param file File to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(file,0,nb,dx,dy,dz,dc); + } + + //! Save list as a TIFF file. + /** + \param filename Filename to write data to. + \param compression_type Compression mode used to write data. + \param voxel_size Voxel size, to be stored in the filename. + \param description Description, to be stored in the filename. + \param use_bigtiff Allow to save big tiff files (>4Gb). + **/ + const CImgList& save_tiff(const char *const filename, const unsigned int compression_type=0, + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_tiff(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_tiff + if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,use_bigtiff); + else cimglist_for(*this,l) { + CImg nfilename(1024); + cimg::number_filename(filename,l,6,nfilename); + _data[l].save_tiff(nfilename,compression_type,voxel_size,description,use_bigtiff); + } +#else + ulongT siz = 0; + cimglist_for(*this,l) siz+=_data[l].size(); + const bool _use_bigtiff = use_bigtiff && sizeof(siz)>=8 && siz*sizeof(T)>=1UL<<31; // No bigtiff for small images + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + for (unsigned int dir = 0, l = 0; l<_width; ++l) { + const CImg& img = (*this)[l]; + cimg_forZ(img,z) img._save_tiff(tif,dir++,z,compression_type,voxel_size,description); + } + TIFFClose(tif); + } else + throw CImgIOException(_cimglist_instance + "save_tiff(): Failed to open stream for file '%s'.", + cimglist_instance, + filename); +#endif + return *this; + } + + //! Save list as a gzipped file, using external tool 'gzip'. + /** + \param filename Filename to write data to. + **/ + const CImgList& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Specified filename is (null).", + cimglist_instance); + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + + if (is_saveable(body)) { + save(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::gzip_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimglist_instance, + filename); + else cimg::fclose(file); + std::remove(filename_tmp); + } else { + CImg nfilename(1024); + cimglist_for(*this,l) { + cimg::number_filename(body,l,6,nfilename); + if (*ext) cimg_sprintf(nfilename._data + std::strlen(nfilename),".%s",ext); + _data[l].save_gzip_external(nfilename); + } + } + return *this; + } + + //! Save image sequence (using the OpenCV library when available). + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImgList& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { +#ifndef cimg_use_opencv + cimg::unused(codec,keep_open); + return save_custom_external(filename,fps); +#else + try { + static cv::VideoWriter *writers[32] = { 0 }; + static CImgList filenames(32); + static CImg sizes(32,2,1,1,0); + static int last_used_index = -1; + + // Detect if a video writer already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_video(): No already open video writer found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', no video writer slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_video(): Instance list is empty.", + cimglist_instance); + const unsigned int W = _data?_data[0]._width:0, H = _data?_data[0]._height:0; + if (!W || !H) + throw CImgInstanceException(_cimglist_instance + "save_video(): Frame [0] is an empty image.", + cimglist_instance); + const char + *const _codec = codec && *codec?codec:"h264", + codec0 = cimg::uppercase(_codec[0]), + codec1 = _codec[0]?cimg::uppercase(_codec[1]):0, + codec2 = _codec[1]?cimg::uppercase(_codec[2]):0, + codec3 = _codec[2]?cimg::uppercase(_codec[3]):0; + cimg::mutex(9); + writers[index] = new cv::VideoWriter(filename,_cimg_fourcc(codec0,codec1,codec2,codec3),fps,cv::Size(W,H)); + if (!writers[index]->isOpened()) { + delete writers[index]; + writers[index] = 0; + cimg::mutex(9,0); + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', unable to initialize video writer with codec '%c%c%c%c'.", + cimglist_instance,filename, + codec0,codec1,codec2,codec3); + } + CImg::string(filename).move_to(filenames[index]); + sizes(index,0) = W; + sizes(index,1) = H; + cimg::mutex(9,0); + } + + if (!is_empty()) { + const unsigned int W = sizes(index,0), H = sizes(index,1); + cimg::mutex(9); + cimglist_for(*this,l) { + CImg &src = _data[l]; + if (src.is_empty()) + cimg::warn(_cimglist_instance + "save_video(): Skip empty frame %d for file '%s'.", + cimglist_instance,l,filename); + if (src._depth>1 || src._spectrum>3) + cimg::warn(_cimglist_instance + "save_video(): Frame %u has incompatible dimension (%u,%u,%u,%u). " + "Some image data may be ignored when writing frame into video file '%s'.", + cimglist_instance,l,src._width,src._height,src._depth,src._spectrum,filename); + if (src._width==W && src._height==H && src._spectrum==3) + writers[index]->write(CImg(src)._cimg2cvmat()); + else { + CImg _src(src,false); + _src.channels(0,std::min(_src._spectrum - 1,2U)).resize(W,H); + _src.resize(W,H,1,3,_src._spectrum==1); + writers[index]->write(_src._cimg2cvmat()); + } + } + cimg::mutex(9,0); + } + + cimg::mutex(9); + if (!keep_open) { + delete writers[index]; + writers[index] = 0; + filenames[index].assign(); + sizes(index,0) = sizes(index,1) = 0; + last_used_index = -1; + } else last_used_index = index; + cimg::mutex(9,0); + } catch (CImgIOException &e) { + if (!keep_open) return save_custom_external(filename,fps); + throw e; + } + return *this; +#endif + } + + //! Save image sequence, using the external tool 'custom'. + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression. + \param bitrate Output bitrate + **/ + const CImgList& save_custom_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_custom_external(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + const char + *const ext = cimg::split_filename(filename), + *const _codec = codec?codec: + !cimg::strcasecmp(ext,"flv")?"flv": + !cimg::strcasecmp(ext,"mp4")?"h264":"mpeg2video"; + + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + cimglist_for(*this,l) if (!_data[l].is_sameXYZ(_data[0])) + throw CImgInstanceException(_cimglist_instance + "save_custom_external(): Invalid instance dimensions for file '%s'.", + cimglist_instance, + filename); + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + CImg tmp = _data[l].get_shared(); + if (tmp._width%2 || tmp._height%2) // Force output to have an even number of columns and rows + tmp.assign(tmp.get_resize(tmp._width + (tmp._width%2),tmp._height + (tmp._height%2),1,-100,0),false); + if (tmp._depth>1 || tmp._spectrum!=3) // Force output to be one slice, in color + tmp.assign(tmp.get_resize(-100,-100,1,3),false); + tmp.save_pnm(filename_tmp2); + } + cimg_snprintf(command,command._width, + "\"%s\" -v -8 -y -i \"%s_%%6d.ppm\" -pix_fmt yuv420p -vcodec %s -b %uk -r %u \"%s\"", + cimg::custom_path(), + CImg::string(filename_tmp)._system_strescape().data(), + _codec,bitrate,fps, + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::custom_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_custom_external(): Failed to save file '%s' with external command 'custom'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for(*this,l) std::remove(filenames[l]); + return *this; + } + + //! Serialize a CImgList instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "get_serialize(): Unable to compress data unless zlib is enabled, " + "storing them uncompressed.", + cimglist_instance); +#endif + CImgList stream; + CImg tmpstr(128); + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + if (std::strstr(ptype,"unsigned")==ptype) + cimg_snprintf(tmpstr,tmpstr._width,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + cimg_snprintf(tmpstr,tmpstr._width,"%u %s %s_endian\n",_width,ptype,etype); + CImg::string(tmpstr,false).move_to(stream); + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_snprintf(tmpstr,tmpstr._width,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + CImg::string(tmpstr,false).move_to(stream); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + const ulongT siz = sizeof(T)*ref.size(); + uLongf csiz = (ulongT)compressBound(siz); + Bytef *const cbuf = new Bytef[csiz]; + if (compress(cbuf,&csiz,(Bytef*)ref._data,siz)) + cimg::warn(_cimglist_instance + "get_serialize(): Failed to save compressed data, saving them uncompressed.", + cimglist_instance); + else { + cimg_snprintf(tmpstr,tmpstr._width," #%lu\n",csiz); + CImg::string(tmpstr,false).move_to(stream); + CImg(cbuf,csiz).move_to(stream); + delete[] cbuf; + failed_to_compress = false; + } +#endif + } + if (failed_to_compress) { // Write in a non-compressed way + CImg::string("\n",false).move_to(stream); + stream.insert(1); + stream.back().assign((unsigned char*)ref._data,ref.size()*sizeof(T),1,1,1,true); + } + } else CImg::string("\n",false).move_to(stream); + } + cimglist_apply(stream,unroll)('y'); + return stream>'y'; + } + + //! Unserialize a CImg serialized buffer into a CImgList list. + template + static CImgList get_unserialize(const CImg& buffer) { +#ifdef cimg_use_zlib +#define _cimgz_unserialize_case(Tss) { \ + Bytef *cbuf = 0; \ + if (sizeof(t)!=1 || buffer.pixel_type()==cimg::type::string()) { \ + cbuf = new Bytef[csiz]; Bytef *_cbuf = cbuf; \ + for (ulongT k = 0; k::get_unserialize(): Unable to unserialize compressed data " \ + "unless zlib is enabled.", \ + pixel_type()); +#endif + +#define _cimg_unserialize_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l::unserialize(): Invalid specified size (%u,%u,%u,%u) for " \ + "image #%u in serialized buffer.", \ + pixel_type(),W,H,D,C,l); \ + if (W*H*D*C>0) { \ + CImg raw; \ + CImg &img = res._data[l]; \ + if (err==5) _cimgz_unserialize_case(Tss) \ + else { \ + raw.assign(W,H,D,C); \ + CImg _raw((unsigned char*)raw._data,W*sizeof(Tss),H,D,C,true); \ + if (sizeof(t)==1) { std::memcpy(_raw,stream,_raw.size()); stream+=_raw.size(); } \ + else cimg_for(_raw,p,unsigned char) *p = (unsigned char)*(stream++); \ + } \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } \ + } \ + loaded = true; \ + } + + if (buffer.is_empty()) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Specified serialized buffer is (null).", + pixel_type()); + CImgList res; + const t *stream = buffer._data, *const estream = buffer._data + buffer.size(); + bool loaded = false, endian = cimg::endianness(), is_bytef = false; + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + uint64T csiz; + int i, err; + cimg::unused(is_bytef); + do { + j = 0; while ((i=(int)*stream)!='\n' && stream::get_unserialize(): CImg header not found in serialized buffer.", + pixel_type()); + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + res.assign(N); + _cimg_unserialize_case("bool",bool); + _cimg_unserialize_case("unsigned_char",unsigned char); + _cimg_unserialize_case("uchar",unsigned char); + _cimg_unserialize_case("char",char); + _cimg_unserialize_case("unsigned_short",unsigned short); + _cimg_unserialize_case("ushort",unsigned short); + _cimg_unserialize_case("short",short); + _cimg_unserialize_case("unsigned_int",unsigned int); + _cimg_unserialize_case("uint",unsigned int); + _cimg_unserialize_case("int",int); + _cimg_unserialize_case("unsigned_int64",uint64T); + _cimg_unserialize_case("uint64",uint64T); + _cimg_unserialize_case("int64",int64T); + _cimg_unserialize_case("float",float); + _cimg_unserialize_case("double",double); + if (!loaded) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Unsupported pixel type '%s' defined " + "in serialized buffer.", + pixel_type(),str_pixeltype._data); + return res; + } + + //@} + //---------------------------------- + // + //! \name Others + //@{ + //---------------------------------- + + //! Return a CImg pre-defined font with requested height. + /** + \param font_height Height of the desired font (exact match for 13,23,53,103). + \param is_variable_width Decide if the font has a variable (\c true) or fixed (\c false) width. + **/ + static const CImgList& font(const unsigned int requested_height, const bool is_variable_width=true) { + if (!requested_height) return CImgList::const_empty(); + cimg::mutex(11); + static const unsigned char font_resizemap[] = { + 0, 4, 7, 9, 11, 13, 15, 17, 19, 21, 22, 24, 26, 27, 29, 30, + 32, 33, 35, 36, 38, 39, 41, 42, 43, 45, 46, 47, 49, 50, 51, 52, + 54, 55, 56, 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 162, 163, 164, 164, 165, + 166, 167, 168, 169, 170, 170, 171, 172, 173, 174, 175, 176, 176, 177, 178, 179, + 180, 181, 181, 182, 183, 184, 185, 186, 186, 187, 188, 189, 190, 191, 191, 192, + 193, 194, 195, 196, 196, 197, 198, 199, 200, 200, 201, 202, 203, 204, 205, 205, + 206, 207, 208, 209, 209, 210, 211, 212, 213, 213, 214, 215, 216, 216, 217, 218, + 219, 220, 220, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 231, + 231, 232, 233, 234, 234, 235, 236, 237, 238, 238, 239, 240, 241, 241, 242, 243, + 244, 244, 245, 246, 247, 247, 248, 249, 250, 250, 251, 252, 253, 253, 254, 255 }; + static const char *const *font_data[] = { + cimg::data_font_small, + cimg::data_font_normal, + cimg::data_font_large, + cimg::data_font_huge }; + static const unsigned int + font_width[] = { 10,26,52,104 }, + font_height[] = { 13,32,64,128 }, + font_M[] = { 86,91,91,47 }, + font_chunk[] = { sizeof(cimg::data_font_small)/sizeof(char*), + sizeof(cimg::data_font_normal)/sizeof(char*), + sizeof(cimg::data_font_large)/sizeof(char*), + sizeof(cimg::data_font_huge)/sizeof(char*) }; + static const unsigned char font_is_binary[] = { 1,0,0,1 }; + static CImg font_base[4]; + + unsigned int ind = + requested_height<=font_height[0]?0U: + requested_height<=font_height[1]?1U: + requested_height<=font_height[2]?2U:3U; + + // Decompress nearest base font data if needed. + CImg &basef = font_base[ind]; + if (!basef) { + basef.assign(256*font_width[ind],font_height[ind]); + + unsigned char *ptrd = basef; + const unsigned char *const ptrde = basef.end(); + + // Recompose font data from several chunks, to deal with MS compiler limit with big strings (64 Kb). + CImg dataf; + for (unsigned int k = 0; k::string(font_data[ind][k],k==font_chunk[ind] - 1,true),'x'); + + // Uncompress font data (decode RLE). + const unsigned int M = font_M[ind]; + if (font_is_binary[ind]) + for (const char *ptrs = dataf; *ptrs; ++ptrs) { + const int _n = (int)(*ptrs - M - 32), v = _n>=0?255:0, n = _n>=0?_n:-_n; + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + else + for (const char *ptrs = dataf; *ptrs; ++ptrs) { + int n = (int)*ptrs - M - 32, v = 0; + if (n>=0) { v = 85*n; n = 1; } + else { + n = -n; + v = (int)*(++ptrs) - M - 32; + if (v<0) { v = 0; --ptrs; } else v*=85; + } + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + } + + // Find optimal font cache location to return. + static CImgList fonts[16]; + static bool is_variable_widths[16] = { 0 }; + ind = ~0U; + for (int i = 0; i<16; ++i) + if (!fonts[i] || (is_variable_widths[i]==is_variable_width && requested_height==fonts[i][0]._height)) { + ind = (unsigned int)i; break; // Found empty slot or cached font + } + if (ind==~0U) { // No empty slots nor existing font in cache + fonts->assign(); + std::memmove((void*)fonts,(void*)(fonts + 1),15*sizeof(CImgList)); + std::memmove(is_variable_widths,is_variable_widths + 1,15*sizeof(bool)); + std::memset((void*)(fonts + (ind=15)),0,sizeof(CImgList)); // Free a slot in cache for new font + } + CImgList &font = fonts[ind]; + + // Render requested font. + if (!font) { + is_variable_widths[ind] = is_variable_width; + basef.get_split('x',256).move_to(font); + +// cimg::tic(); + + if (requested_height!=font[0]._height) + cimglist_for(font,l) { + font[l].resize(std::max(1U,font[l]._width*requested_height/font[l]._height),requested_height,-100,-100,5); + cimg_for(font[l],ptr,ucharT) *ptr = font_resizemap[*ptr]; + } + +// cimg::toc(); +// std::exit(0); + + if (is_variable_width) { // Crop font + cimglist_for(font,l) { + CImg& letter = font[l]; + int xmin = letter.width(), xmax = 0; + cimg_forX(letter,x) { // Find xmin + cimg_forY(letter,y) if (letter(x,y)) { xmin = x; break; } + if (xmin!=letter.width()) break; + } + cimg_rofX(letter,x) { // Find xmax + cimg_forY(letter,y) if (letter(x,y)) { xmax = x; break; } + if (xmax) break; + } + if (xmin<=xmax) letter.crop(xmin,0,xmax,letter._height - 1); + } + font[(int)' '].resize(font[(int)'f']._width,-100,-100,-100,0); + if (' ' + 256& FFT(const char axis, const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + CImg::FFT(_data[0],_data[1],axis,invert); + return *this; + } + + //! Compute a 1-D Fast Fourier Transform, along specified axis \newinstance. + CImgList get_FFT(const char axis, const bool invert=false) const { + return CImgList(*this,false).FFT(axis,invert); + } + + //! Compute n-D Fast Fourier Transform. + /** + \param invert Tells if the direct (\c false) or inverse transform (\c true) is computed. + **/ + CImgList& FFT(const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + + CImg::FFT(_data[0],_data[1],invert); + return *this; + } + + //! Compute n-D Fast Fourier Transform \newinstance. + CImgList get_FFT(const bool invert=false) const { + return CImgList(*this,false).FFT(invert); + } + + //! Reverse primitives orientations of a 3D object. + /** + **/ + CImgList& reverse_object3d() { + cimglist_for(*this,l) { + CImg& p = _data[l]; + switch (p.size()) { + case 2 : case 3: cimg::swap(p[0],p[1]); break; + case 6 : cimg::swap(p[0],p[1],p[2],p[4],p[3],p[5]); break; + case 9 : cimg::swap(p[0],p[1],p[3],p[5],p[4],p[6]); break; + case 4 : cimg::swap(p[0],p[1],p[2],p[3]); break; + case 12 : cimg::swap(p[0],p[1],p[2],p[3],p[4],p[6],p[5],p[7],p[8],p[10],p[9],p[11]); break; + } + } + return *this; + } + + //! Reverse primitives orientations of a 3D object \newinstance. + CImgList get_reverse_object3d() const { + return (+*this).reverse_object3d(); + } + + //@} + }; // struct CImgList { ... + + // Completion of previously declared functions + //-------------------------------------------- + namespace cimg { + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + // (throw a CImgIOException when macro 'cimg_use_r' is defined). + inline FILE* _stdin(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stdin; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stdin(): Reference to 'stdin' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + inline FILE* _stdout(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stdout; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stdout(): Reference to 'stdout' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + inline FILE* _stderr(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stderr; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stderr(): Reference to 'stderr' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + // Open a file (similar to std:: fopen(), but with wide character support on Windows). + inline std::FILE *std_fopen(const char *const path, const char *const mode) { + std::FILE *const res = std::fopen(path,mode); + if (res) return res; +#if cimg_OS==2 + // Try alternative method, with wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (err) { + CImg wpath((unsigned int)err); + err = MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err); + if (err) { // Convert 'mode' to a wide-character string + err = MultiByteToWideChar(CP_UTF8,0,mode,-1,0,0); + if (err) { + CImg wmode((unsigned int)err); + if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wmode,err)) + return _wfopen(wpath,wmode); + } + } + } +#endif + return 0; + } + + //! Search path of an executable (Windows only). +#if cimg_OS==2 + inline bool win_searchpath(const char *const exec_name, char *const res, const unsigned int size_res) { + char *ptr = 0; + DWORD err = SearchPathA(0,exec_name,0,size_res,res,&ptr); + return err!=0; + } +#endif + + //! Get the file or directory attributes with support for UTF-8 paths (Windows only). +#if cimg_OS==2 + inline DWORD win_getfileattributes(const char *const path) { + DWORD res = GetFileAttributesA(path); + if (res==INVALID_FILE_ATTRIBUTES) { + // Try alternative method, with wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (err) { + CImg wpath((unsigned int)err); + if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err)) res = GetFileAttributesW(wpath); + } + } + return res; + } +#endif + + //! Get/set path to the Program Files/ directory (Windows only). + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the program files. + **/ +#if cimg_OS==2 + inline const char* win_programfiles_path(const char *const user_path=0, const bool reinit_path=false) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(MAX_PATH); + *s_path = 0; + // Note: in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler). +#if !defined(__INTEL_COMPILER) + if (!SHGetSpecialFolderPathA(0,s_path,0x0026,false)) { + const char *const pfPath = std::getenv("PROGRAMFILES"); + if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH - 1); + else std::strcpy(s_path,"C:\\PROGRA~1"); + } +#else + std::strcpy(s_path,"C:\\PROGRA~1"); +#endif + } + cimg::mutex(7,0); + return s_path; + } +#endif + + //! Get/set path to the \c curl binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c curl binary. + **/ + inline const char *curl_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("curl.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\curl.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./curl"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c dcraw binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c dcraw binary. + **/ + inline const char *dcraw_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("dcraw.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\dcraw.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./dcraw"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the custom's \c custom binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c custom binary. + **/ + inline const char *custom_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("custom.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\custom.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"custom.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./custom"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"custom"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the GraphicsMagick's \c gm binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gm binary. + **/ + inline const char* graphicsmagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gm.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\gm.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gm"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gunzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gunzip binary. + **/ + inline const char *gunzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gunzip.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\gunzip.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gunzip"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gzip binary. + **/ + inline const char *gzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gzip.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\gzip.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gzip"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the ImageMagick's \c convert binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c convert binary. + **/ + inline const char* imagemagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("magick.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + for (int l = 0; l<2 && !path_found; ++l) { + const char *const s_exe = l?"convert":"magick"; + cimg_snprintf(s_path,s_path._width,".\\%s.exe",s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) cimg_snprintf(s_path,s_path._width,"%s.exe",s_exe); + } +#else + std::strcpy(s_path,"./magick"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + if (!path_found) { + std::strcpy(s_path,"./convert"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"convert"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the Medcon's \c medcon binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c medcon binary. + **/ + inline const char* medcon_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("medcon.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\medcon.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.bat",pf_path); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.exe",pf_path); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + std::strcpy(s_path,"C:\\XMedCon\\bin\\medcon.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./medcon"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to store temporary files. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path where temporary files can be saved. + **/ + inline const char* temporary_path(const char *const user_path, const bool reinit_path) { +#define _cimg_test_temporary_path(p) \ + if (!path_found) { \ + cimg_snprintf(s_path,s_path._width,"%s",p); \ + cimg_snprintf(tmp,tmp._width,"%s%c%s",s_path.data(),cimg_file_separator,filename_tmp._data); \ + if ((file=cimg::std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } \ + } + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + CImg tmp(1024), filename_tmp(256); + std::FILE *file = 0; + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.tmp",cimg::filenamerand()); + char *tmpPath = std::getenv("TMP"); + if (!tmpPath) { tmpPath = std::getenv("TEMP"); winformat_string(tmpPath); } + if (tmpPath) _cimg_test_temporary_path(tmpPath); +#if cimg_OS==2 + _cimg_test_temporary_path("C:\\WINNT\\Temp"); + _cimg_test_temporary_path("C:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("C:\\Temp"); + _cimg_test_temporary_path("C:"); + _cimg_test_temporary_path("D:\\WINNT\\Temp"); + _cimg_test_temporary_path("D:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("D:\\Temp"); + _cimg_test_temporary_path("D:"); +#else + _cimg_test_temporary_path("/tmp"); + _cimg_test_temporary_path("/var/tmp"); +#endif + if (!path_found) { + *s_path = 0; + std::strncpy(tmp,filename_tmp,tmp._width - 1); + if ((file=cimg::std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } + } + if (!path_found) { + cimg::mutex(7,0); + throw CImgIOException("cimg::temporary_path(): Failed to locate path for writing temporary files.\n"); + } + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c wget binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c wget binary. + **/ + inline const char *wget_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("wget.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\wget.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./wget"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + + // [internal] Sorting function, used by cimg::files(). + inline int _sort_files(const void* a, const void* b) { + const CImg &sa = *(CImg*)a, &sb = *(CImg*)b; + return std::strcmp(sa._data,sb._data); + } + + //! Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str) { + if (!filename) { if (str) *str = 0; return 0; } + const unsigned int siz = (unsigned int)std::strlen(filename); + CImg format(16), body(siz + 32); + const char *const ext = cimg::split_filename(filename,body); + if (*ext) cimg_snprintf(format,format._width,"%%s_%%.%ud.%%s",digits); + else cimg_snprintf(format,format._width,"%%s_%%.%ud",digits); + cimg_snprintf(str,1024,format._data,body._data,number,ext); + return str; + } + + //! Return list of files/directories in specified directory. + /** + \param path Path to the directory. Set to 0 for current directory. + \param is_pattern Tell if specified path has a matching pattern in it. + \param mode Output type, can be primary { 0=files only | 1=folders only | 2=files + folders }. + \param include_path Tell if \c path must be included in resulting filenames. + \return A list of filenames. + **/ + inline CImgList files(const char *const path, const bool is_pattern=false, + const unsigned int mode=2, const bool include_path=false) { + if (!path || !*path) return files("*",true,mode,include_path); + CImgList res; + + // If path is a valid folder name, ignore argument 'is_pattern'. + const bool _is_pattern = is_pattern && !cimg::is_directory(path); + bool is_root = false, is_current = false; + cimg::unused(is_root,is_current); + + // Clean format of input path. + CImg pattern, _path = CImg::string(path); +#if cimg_OS==2 + for (char *ps = _path; *ps; ++ps) if (*ps=='\\') *ps='/'; +#endif + char *pd = _path; + for (char *ps = pd; *ps; ++ps) { if (*ps!='/' || *ps!=*(ps+1)) *(pd++) = *ps; } + *pd = 0; + unsigned int lp = (unsigned int)std::strlen(_path); + if (!_is_pattern && lp && _path[lp - 1]=='/') { + _path[lp - 1] = 0; --lp; +#if cimg_OS!=2 + is_root = !*_path; +#endif + } + + // Separate folder path and matching pattern. + if (_is_pattern) { + const unsigned int bpos = (unsigned int)(cimg::basename(_path,'/') - _path.data()); + CImg::string(_path).move_to(pattern); + if (bpos) { + _path[bpos - 1] = 0; // End 'path' at last slash +#if cimg_OS!=2 + is_root = !*_path; +#endif + } else { // No path to folder specified, assuming current folder + is_current = true; *_path = 0; + } + lp = (unsigned int)std::strlen(_path); + } + + // Windows version. +#if cimg_OS==2 + if (!_is_pattern) { + pattern.assign(lp + 3); + std::memcpy(pattern,_path,lp); + pattern[lp] = '/'; pattern[lp + 1] = '*'; pattern[lp + 2] = 0; + } + WIN32_FIND_DATAA file_data; + const HANDLE dir = FindFirstFileA(pattern.data(),&file_data); + if (dir==INVALID_HANDLE_VALUE) return CImgList::const_empty(); + do { + const char *const filename = file_data.cFileName; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode>=2) { + if (include_path) { + CImg full_filename((lp?lp+1:0) + lf + 1); + if (lp) { std::memcpy(full_filename,_path,lp); full_filename[lp] = '/'; } + std::memcpy(full_filename._data + (lp?lp + 1:0),filename,lf + 1); + full_filename.move_to(res); + } else CImg(filename,lf + 1).move_to(res); + } + } + } while (FindNextFileA(dir,&file_data)); + FindClose(dir); + + // Unix version (posix). +#elif cimg_OS == 1 + DIR *const dir = opendir(is_root?"/":is_current?".":_path.data()); + if (!dir) return CImgList::const_empty(); + struct dirent *ent; + while ((ent=readdir(dir))!=0) { + const char *const filename = ent->d_name; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + CImg full_filename(lp + lf + 2); + + if (!is_current) { + full_filename.assign(lp + lf + 2); + if (lp) std::memcpy(full_filename,_path,lp); + full_filename[lp] = '/'; + std::memcpy(full_filename._data + lp + 1,filename,lf + 1); + } else full_filename.assign(filename,lf + 1); + + struct stat st; + if (stat(full_filename,&st)==-1) continue; + const bool is_directory = (st.st_mode & S_IFDIR)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode==2) { + if (include_path) { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + full_filename.move_to(res); + } else { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + CImg(filename,lf + 1).move_to(res); + } + } + } + } + closedir(dir); +#endif + + // Sort resulting list by lexicographic order. + if (res._width>=2) std::qsort(res._data,res._width,sizeof(CImg),_sort_files); + + return res; + } + + //! Try to guess format from an image file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + \return C-string containing the guessed file format, or \c 0 if nothing has been guessed. + **/ + inline const char *ftype(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::ftype(): Specified filename is (null)."); + static const char + *const _pnm = "pnm", + *const _pfm = "pfm", + *const _bmp = "bmp", + *const _gif = "gif", + *const _jpg = "jpg", + *const _off = "off", + *const _pan = "pan", + *const _png = "png", + *const _tif = "tif", + *const _inr = "inr", + *const _dcm = "dcm"; + const char *f_type = 0; + CImg header; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + header._load_raw(file,filename,512,1,1,1,false,false,0); + const unsigned char *const uheader = (unsigned char*)header._data; + if (!std::strncmp(header,"OFF\n",4)) f_type = _off; // OFF + else if (!std::strncmp(header,"#INRIMAGE",9)) // INRIMAGE + f_type = _inr; + else if (!std::strncmp(header,"PANDORE",7)) // PANDORE + f_type = _pan; + else if (!std::strncmp(header.data() + 128,"DICM",4)) // DICOM + f_type = _dcm; + else if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) // JPEG + f_type = _jpg; + else if (header[0]=='B' && header[1]=='M') // BMP + f_type = _bmp; + else if (header[0]=='G' && header[1]=='I' && header[2]=='F' && header[3]=='8' && header[5]=='a' && + (header[4]=='7' || header[4]=='9')) // GIF + f_type = _gif; + else if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 && + uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) // PNG + f_type = _png; + else if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) // TIFF + f_type = _tif; + else { // PNM or PFM + CImgList _header = header.get_split(CImg::vector('\n'),0,false); + cimglist_for(_header,l) { + if (_header(l,0)=='#') continue; + if (_header[l]._width==2 && _header(l,0)=='P') { + const char c = _header(l,1); + if (c=='f' || c=='F') { f_type = _pfm; break; } + if (c>='1' && c<='9') { f_type = _pnm; break; } + } + f_type = 0; break; + } + } + } catch (CImgIOException&) { } + cimg::exception_mode(omode); + return f_type; + } + + //! Load file from network as a local temporary file. + /** + \param url URL of the filename, as a C-string. + \param[out] filename_local C-string containing the path to a local copy of \c filename. + \param timeout Maximum time (in seconds) authorized for downloading the file from the URL. + \param try_fallback When using libcurl, tells using system calls as fallbacks in case of libcurl failure. + \param referer Referer used, as a C-string. + \return Value of \c filename_local. + \note Use the \c libcurl library, or the external binaries \c wget or \c curl to perform the download. + **/ + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout, const bool try_fallback, + const char *const referer) { + if (!url) + throw CImgArgumentException("cimg::load_network(): Specified URL is (null)."); + if (!filename_local) + throw CImgArgumentException("cimg::load_network(): Specified destination string is (null)."); + if (!network_mode()) + throw CImgIOException("cimg::load_network(): Loading files from network is disabled."); + + const char *const __ext = cimg::split_filename(url), *const _ext = (*__ext && __ext>url)?__ext - 1:__ext; + CImg ext = CImg::string(_ext); + std::FILE *file = 0; + *filename_local = 0; + if (ext._width>16 || !cimg::strncasecmp(ext,"cgi",3)) *ext = 0; + else cimg::strwindows_reserved(ext); + do { + cimg_snprintf(filename_local,256,"%s%c%s%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext._data); + if ((file=cimg::std_fopen(filename_local,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_curl + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + CURL *curl = 0; + CURLcode res; + curl = curl_easy_init(); + if (curl) { + file = cimg::fopen(filename_local,"wb"); + curl_easy_setopt(curl,CURLOPT_URL,url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,0); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,file); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0L); + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L); + if (timeout) curl_easy_setopt(curl,CURLOPT_TIMEOUT,(long)timeout); + if (std::strchr(url,'?')) curl_easy_setopt(curl,CURLOPT_HTTPGET,1L); + if (referer) curl_easy_setopt(curl,CURLOPT_REFERER,referer); + res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + cimg::fseek(file,0,SEEK_END); // Check if file size is 0 + const cimg_ulong siz = cimg::ftell(file); + cimg::fclose(file); + if (siz>0 && res==CURLE_OK) { + cimg::exception_mode(omode); + return filename_local; + } else std::remove(filename_local); + } + } catch (...) { } + cimg::exception_mode(omode); + if (!try_fallback) throw CImgIOException("cimg::load_network(): Failed to load file '%s' with libcurl.",url); +#endif + + CImg command((unsigned int)std::strlen(url) + 64); + cimg::unused(try_fallback); + + // Try with 'curl' first. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" -e %s -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,timeout,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),timeout,filename_local, + CImg::string(url)._system_strescape().data()); + } else { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" -e %s -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),filename_local, + CImg::string(url)._system_strescape().data()); + } + cimg::system(command, cimg::curl_path()); + + if (!(file=cimg::std_fopen(filename_local,"rb"))) { + + // Try with 'wget' otherwise. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" --referer=%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,timeout,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),timeout,filename_local, + CImg::string(url)._system_strescape().data()); + } else { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" --referer=%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),filename_local, + CImg::string(url)._system_strescape().data()); + } + cimg::system(command, cimg::wget_path()); + + if (!(file=cimg::std_fopen(filename_local,"rb"))) + throw CImgIOException("cimg::load_network(): Failed to load file '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + + // Try gunzip it. + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(filename_local,command); + cimg_snprintf(command,command._width,"\"%s\" --quiet \"%s.gz\"", + gunzip_path(),filename_local); + cimg::system(command, gunzip_path()); + file = cimg::std_fopen(filename_local,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(command,filename_local); + file = cimg::std_fopen(filename_local,"rb"); + } + } + cimg::fseek(file,0,SEEK_END); // Check if file size is 0 + if (std::ftell(file)<=0) + throw CImgIOException("cimg::load_network(): Failed to load URL '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + return filename_local; + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_uint64 tictoc(const bool is_tic) { + cimg::mutex(2); + static CImg times(64); + static unsigned int pos = 0; + const cimg_uint64 t1 = cimg::time(); + if (is_tic) { + // Tic + times[pos++] = t1; + if (pos>=times._width) + throw CImgArgumentException("cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'."); + cimg::mutex(2,0); + return t1; + } + + // Toc + if (!pos) + throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made."); + const cimg_uint64 + t0 = times[--pos], + dt = t1>=t0?(t1 - t0):cimg::type::max(); + const unsigned int + edays = (unsigned int)(dt/86400000.), + ehours = (unsigned int)((dt - edays*86400000.)/3600000.), + emin = (unsigned int)((dt - edays*86400000. - ehours*3600000.)/60000.), + esec = (unsigned int)((dt - edays*86400000. - ehours*3600000. - emin*60000.)/1000.), + ems = (unsigned int)(dt - edays*86400000. - ehours*3600000. - emin*60000. - esec*1000.); + if (!edays && !ehours && !emin && !esec) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ems,cimg::t_normal); + else { + if (!edays && !ehours && !emin) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",esec,ems,cimg::t_normal); + else { + if (!edays && !ehours) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",emin,esec,ems,cimg::t_normal); + else{ + if (!edays) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ehours,emin,esec,ems,cimg::t_normal); + else{ + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u days %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",edays,ehours,emin,esec,ems,cimg::t_normal); + } + } + } + } + cimg::mutex(2,0); + return dt; + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size) { + static CImg res(256); + cimg::mutex(5); + if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",(unsigned long)size,size>1?"s":""); + else if (size<1024*1024LU) { const float nsize = size/1024.f; cimg_snprintf(res,res._width,"%.1f Kio",nsize); } + else if (size<1024*1024*1024LU) { + const float nsize = size/(1024*1024.f); cimg_snprintf(res,res._width,"%.1f Mio",nsize); + } else { const float nsize = size/(1024*1024*1024.f); cimg_snprintf(res,res._width,"%.1f Gio",nsize); } + cimg::mutex(5,0); + return res; + } + + //! Display a simple dialog box, and wait for the user's response. + /** + \param title Title of the dialog window. + \param msg Main message displayed inside the dialog window. + \param button1_label Label of the 1st button. + \param button2_label Label of the 2nd button (\c 0 to hide button). + \param button3_label Label of the 3rd button (\c 0 to hide button). + \param button4_label Label of the 4th button (\c 0 to hide button). + \param button5_label Label of the 5th button (\c 0 to hide button). + \param button6_label Label of the 6th button (\c 0 to hide button). + \param logo Image logo displayed at the left of the main message. + \param is_centered Tells if the dialog window must be centered on the screen. + \return Index of clicked button (from \c 0 to \c 5), or \c -1 if the dialog window has been closed by the user. + \note + - Up to 6 buttons can be defined in the dialog window. + - The function returns when a user clicked one of the button or closed the dialog window. + - If a button text is set to 0, the corresponding button (and the following) will not appear in the dialog box. + At least one button must be specified. + **/ + template + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const CImg& logo, const bool is_centered=false) { +#if cimg_display==0 + cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + logo._data,is_centered); + throw CImgIOException("cimg::dialog(): No display available."); +#else + static const unsigned char + black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 }; + + // Create buttons and canvas graphics + CImgList buttons, cbuttons, sbuttons; + if (button1_label) { + CImg().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons); + if (button2_label) { + CImg().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons); + if (button3_label) { + CImg().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons); + if (button4_label) { + CImg().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons); + if (button5_label) { + CImg().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons); + if (button6_label) { + CImg().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons); + }}}}}} + if (!buttons._width) + throw CImgArgumentException("cimg::dialog(): No buttons have been defined."); + cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3); + + unsigned int bw = 0, bh = 0; + cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); } + bw+=8; bh+=8; + if (bw<64) bw = 64; + if (bw>128) bw = 128; + if (bh<24) bh = 24; + if (bh>48) bh = 48; + + CImg button(bw,bh,1,3); + button.draw_rectangle(0,0,bw - 1,bh - 1,gray); + button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white); + button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black); + button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2); + CImg sbutton(bw,bh,1,3); + sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray); + sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black); + sbutton.draw_line(bw - 1,bh - 1,0,bh - 1,black).draw_line(0,bh - 1,0,0,black); + sbutton.draw_line(1,1,bw - 2,1,white).draw_line(1,bh - 2,1,1,white); + sbutton.draw_line(bw - 2,1,bw - 2,bh - 2,black).draw_line(bw - 2,bh - 2,1,bh - 2,black); + sbutton.draw_line(2,bh - 3,bw - 3,bh - 3,gray2).draw_line(bw - 3,bh - 3,bw - 3,2,gray2); + sbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true). + draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + sbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false). + draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + CImg cbutton(bw,bh,1,3); + cbutton.draw_rectangle(0,0,bw - 1,bh - 1,black).draw_rectangle(1,1,bw - 2,bh - 2,gray2). + draw_rectangle(2,2,bw - 3,bh - 3,gray); + cbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true). + draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + cbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false). + draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + + cimglist_for(buttons,ll) { + CImg(cbutton). + draw_image(1 + (bw -buttons[ll].width())/2,1 + (bh - buttons[ll].height())/2,buttons[ll]). + move_to(cbuttons); + CImg(sbutton). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(sbuttons); + CImg(button). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(buttons[ll]); + } + + CImg canvas; + if (msg) + ((CImg().draw_text(0,0,"%s",gray,0,1,13,msg)*=-1)+=200).resize(-100,-100,1,3).move_to(canvas); + + const unsigned int + bwall = (buttons._width - 1)*(12 + bw) + bw, + w = cimg::max(196U,36 + logo._width + canvas._width,24 + bwall), + h = cimg::max(96U,36 + canvas._height + bh,36 + logo._height + bh), + lx = 12 + (canvas._data?0:((w - 24 - logo._width)/2)), + ly = (h - 12 - bh - logo._height)/2, + tx = lx + logo._width + 12, + ty = (h - 12 - bh - canvas._height)/2, + bx = (w - bwall)/2, + by = h - 12 - bh; + + if (canvas._data) + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black). + draw_image(tx,ty,canvas); + else + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black); + if (logo._data) canvas.draw_image(lx,ly,logo); + + unsigned int xbuttons[6] = { 0 }; + cimglist_for(buttons,lll) { + xbuttons[lll] = bx + (bw + 12)*lll; + canvas.draw_image(xbuttons[lll],by,buttons[lll]); + } + + // Open window and enter events loop + CImgDisplay disp(canvas,title?title:" ",0,false,is_centered?true:false); + if (is_centered) disp.move((CImgDisplay::screen_width() - disp.width())/2, + (CImgDisplay::screen_height() - disp.height())/2); + bool stop_flag = false, refresh = false; + int oselected = -1, oclicked = -1, selected = -1, clicked = -1; + while (!disp.is_closed() && !stop_flag) { + if (refresh) { + if (clicked>=0) + CImg(canvas).draw_image(xbuttons[clicked],by,cbuttons[clicked]).display(disp); + else { + if (selected>=0) + CImg(canvas).draw_image(xbuttons[selected],by,sbuttons[selected]).display(disp); + else canvas.display(disp); + } + refresh = false; + } + disp.wait(15); + if (disp.is_resized()) disp.resize(disp,false); + + if (disp.button()&1) { + oclicked = clicked; + clicked = -1; + cimglist_for(buttons,l) + if (disp.mouse_y()>=(int)by && disp.mouse_y()<(int)(by + bh) && + disp.mouse_x()>=(int)xbuttons[l] && disp.mouse_x()<(int)(xbuttons[l] + bw)) { + clicked = selected = l; + refresh = true; + } + if (clicked!=oclicked) refresh = true; + } else if (clicked>=0) stop_flag = true; + + if (disp.key()) { + oselected = selected; + switch (disp.key()) { + case cimg::keyESC : selected = -1; stop_flag = true; break; + case cimg::keyENTER : if (selected<0) selected = 0; stop_flag = true; break; + case cimg::keyTAB : + case cimg::keyARROWRIGHT : + case cimg::keyARROWDOWN : selected = (selected + 1)%buttons.width(); break; + case cimg::keyARROWLEFT : + case cimg::keyARROWUP : selected = (selected + buttons.width() - 1)%buttons.width(); break; + } + disp.set_key(); + if (selected!=oselected) refresh = true; + } + } + if (!disp) selected = -1; + return selected; +#endif + } + + //! Display a simple dialog box, and wait for the user's response \specialization. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const bool is_centered) { + return dialog(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + CImg::_logo40x38(),is_centered); + } + + //! Evaluate math expression. + /** + \param expression C-string describing the formula to evaluate. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \return Result of the formula evaluation. + \note Set \c expression to \c 0 to keep evaluating the last specified \c expression. + \par Example + \code + const double + res1 = cimg::eval("cos(x)^2 + sin(y)^2",2,2), // will return '1' + res2 = cimg::eval(0,1,1); // will return '1' too + \endcode + **/ + inline double eval(const char *const expression, const double x, const double y, const double z, const double c) { + static const CImg empty; + return empty.eval(expression,x,y,z,c); + } + + template + inline CImg::type> eval(const char *const expression, const CImg& xyzc) { + static const CImg empty; + return empty.eval(expression,xyzc); + } + + } // namespace cimg { ... +} // namespace cimg_library { ... + +//! Short alias name. +namespace cil = cimg_library_suffixed; + +#ifdef _cimg_redefine_False +#define False 0 +#endif +#ifdef _cimg_redefine_True +#define True 1 +#endif +#ifdef _cimg_redefine_Status +#define Status int +#endif +#ifdef _cimg_redefine_Success +#define Success 0 +#endif +#ifdef _cimg_redefine_min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_PI +#define PI 3.141592653589793238462643383 +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif + +// Local Variables: +// mode: c++ +// End: diff --git a/rknn_yolo_demo/libs/common/cnpy/cnpy.cpp b/rknn_yolo_demo/libs/common/cnpy/cnpy.cpp new file mode 100644 index 0000000..ef021fe --- /dev/null +++ b/rknn_yolo_demo/libs/common/cnpy/cnpy.cpp @@ -0,0 +1,401 @@ +// Copyright (C) 2011 Carl Rogers +// Released under MIT License +// license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php + +#include "cnpy.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +char cnpy::BigEndianTest(int size) +{ + if (size == 1) + return '|'; + int x = 1; + return (((char*)&x)[0]) ? '<' : '>'; +} + +char cnpy::map_type(const std::type_info& t) +{ + if (t == typeid(float)) + return 'f'; + if (t == typeid(double)) + return 'f'; + if (t == typeid(long double)) + return 'f'; + + if (t == typeid(int)) + return 'i'; + if (t == typeid(char)) + return 'i'; + if (t == typeid(signed char)) + return 'i'; + if (t == typeid(short)) + return 'i'; + if (t == typeid(long)) + return 'i'; + if (t == typeid(long long)) + return 'i'; + + if (t == typeid(unsigned char)) + return 'u'; + if (t == typeid(unsigned short)) + return 'u'; + if (t == typeid(unsigned long)) + return 'u'; + if (t == typeid(unsigned long long)) + return 'u'; + if (t == typeid(unsigned int)) + return 'u'; + + if (t == typeid(bool)) + return 'b'; + + if (t == typeid(std::complex)) + return 'c'; + if (t == typeid(std::complex)) + return 'c'; + if (t == typeid(std::complex)) + return 'c'; + + else + return '?'; +} + +template <> +std::vector& cnpy::operator+=(std::vector& lhs, const std::string rhs) +{ + lhs.insert(lhs.end(), rhs.begin(), rhs.end()); + return lhs; +} + +template <> +std::vector& cnpy::operator+=(std::vector& lhs, const char* rhs) +{ + // write in little endian + size_t len = strlen(rhs); + lhs.reserve(len); + for (size_t byte = 0; byte < len; byte++) { + lhs.push_back(rhs[byte]); + } + return lhs; +} + +void cnpy::parse_npy_header(unsigned char* buffer, size_t& word_size, std::vector& shape, bool& fortran_order, + std::string& typeName) +{ + // std::string magic_string(buffer,6); + uint8_t major_version = *reinterpret_cast(buffer + 6); + uint8_t minor_version = *reinterpret_cast(buffer + 7); + uint16_t header_len = *reinterpret_cast(buffer + 8); + std::string header(reinterpret_cast(buffer + 9), header_len); + + size_t loc1, loc2; + + // fortran order + loc1 = header.find("fortran_order") + 16; + fortran_order = (header.substr(loc1, 4) == "True" ? true : false); + if (fortran_order) + throw std::runtime_error("npy input file: 'fortran_order' must be false, use: arr2 = np.ascontiguousarray(arr1)"); + + // shape + loc1 = header.find("("); + loc2 = header.find(")"); + + std::regex num_regex("[0-9][0-9]*"); + std::smatch sm; + shape.clear(); + + std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1); + while (std::regex_search(str_shape, sm, num_regex)) { + shape.push_back(std::stoi(sm[0].str())); + str_shape = sm.suffix().str(); + } + + // endian, word size, data type + // byte order code | stands for not applicable. + // not sure when this applies except for byte array + loc1 = header.find("descr") + 9; + bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false); + assert(littleEndian); + + // char type = header[loc1+1]; + // assert(type == map_type(T)); + + std::string str_ws = header.substr(loc1 + 2); + loc2 = str_ws.find("'"); + word_size = atoi(str_ws.substr(0, loc2).c_str()); + if (header.substr(loc1 + 1, 1) == "i") { + typeName = "int"; + } else if (header.substr(loc1 + 1, 1) == "u") { + typeName = "uint"; + } else if (header.substr(loc1 + 1, 1) == "f") { + typeName = "float"; + } + typeName = typeName + std::to_string(word_size * 8); +} + +void cnpy::parse_npy_header(FILE* fp, size_t& word_size, std::vector& shape, bool& fortran_order, + std::string& typeName) +{ + char buffer[256]; + size_t res = fread(buffer, sizeof(char), 11, fp); + if (res != 11) + throw std::runtime_error("parse_npy_header: failed fread"); + std::string header = fgets(buffer, 256, fp); + assert(header[header.size() - 1] == '\n'); + + size_t loc1, loc2; + + // fortran order + loc1 = header.find("fortran_order"); + if (loc1 == std::string::npos) + throw std::runtime_error("parse_npy_header: failed to find header keyword: 'fortran_order'"); + loc1 += 16; + fortran_order = (header.substr(loc1, 4) == "True" ? true : false); + if (fortran_order) + throw std::runtime_error("npy input file: 'fortran_order' must be false, use: arr2 = np.ascontiguousarray(arr1)"); + + // shape + loc1 = header.find("("); + loc2 = header.find(")"); + if (loc1 == std::string::npos || loc2 == std::string::npos) + throw std::runtime_error("parse_npy_header: failed to find header keyword: '(' or ')'"); + + std::regex num_regex("[0-9][0-9]*"); + std::smatch sm; + shape.clear(); + + std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1); + while (std::regex_search(str_shape, sm, num_regex)) { + shape.push_back(std::stoi(sm[0].str())); + str_shape = sm.suffix().str(); + } + + // endian, word size, data type + // byte order code | stands for not applicable. + // not sure when this applies except for byte array + loc1 = header.find("descr"); + if (loc1 == std::string::npos) + throw std::runtime_error("parse_npy_header: failed to find header keyword: 'descr'"); + loc1 += 9; + bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false); + assert(littleEndian); + + // char type = header[loc1+1]; + // assert(type == map_type(T)); + + std::string str_ws = header.substr(loc1 + 2); + loc2 = str_ws.find("'"); + word_size = atoi(str_ws.substr(0, loc2).c_str()); + if (header.substr(loc1 + 1, 1) == "i") { + typeName = "int"; + } else if (header.substr(loc1 + 1, 1) == "u") { + typeName = "uint"; + } else if (header.substr(loc1 + 1, 1) == "f") { + typeName = "float"; + } + typeName = typeName + std::to_string(word_size * 8); +} + +void cnpy::parse_zip_footer(FILE* fp, uint16_t& nrecs, size_t& global_header_size, size_t& global_header_offset) +{ + std::vector footer(22); + fseek(fp, -22, SEEK_END); + size_t res = fread(&footer[0], sizeof(char), 22, fp); + if (res != 22) + throw std::runtime_error("parse_zip_footer: failed fread"); + + uint16_t disk_no, disk_start, nrecs_on_disk, comment_len; + disk_no = *(uint16_t*)&footer[4]; + disk_start = *(uint16_t*)&footer[6]; + nrecs_on_disk = *(uint16_t*)&footer[8]; + nrecs = *(uint16_t*)&footer[10]; + global_header_size = *(uint32_t*)&footer[12]; + global_header_offset = *(uint32_t*)&footer[16]; + comment_len = *(uint16_t*)&footer[20]; + + assert(disk_no == 0); + assert(disk_start == 0); + assert(nrecs_on_disk == nrecs); + assert(comment_len == 0); +} + +cnpy::NpyArray load_the_npy_file(FILE* fp) +{ + std::vector shape; + size_t word_size; + std::string typeName; + bool fortran_order; + cnpy::parse_npy_header(fp, word_size, shape, fortran_order, typeName); + + cnpy::NpyArray arr(shape, word_size, fortran_order, typeName); + size_t nread = fread(arr.data(), 1, arr.num_bytes(), fp); + if (nread != arr.num_bytes()) + throw std::runtime_error("load_the_npy_file: failed fread"); + return arr; +} + +cnpy::NpyArray load_the_npz_array(FILE* fp, uint32_t compr_bytes, uint32_t uncompr_bytes) +{ + std::vector buffer_compr(compr_bytes); + std::vector buffer_uncompr(uncompr_bytes); + size_t nread = fread(&buffer_compr[0], 1, compr_bytes, fp); + if (nread != compr_bytes) + throw std::runtime_error("load_the_npy_file: failed fread"); + + int err; + z_stream d_stream; + + d_stream.zalloc = Z_NULL; + d_stream.zfree = Z_NULL; + d_stream.opaque = Z_NULL; + d_stream.avail_in = 0; + d_stream.next_in = Z_NULL; + err = inflateInit2(&d_stream, -MAX_WBITS); + + d_stream.avail_in = compr_bytes; + d_stream.next_in = &buffer_compr[0]; + d_stream.avail_out = uncompr_bytes; + d_stream.next_out = &buffer_uncompr[0]; + + err = inflate(&d_stream, Z_FINISH); + err = inflateEnd(&d_stream); + + std::vector shape; + size_t word_size; + bool fortran_order; + std::string typeName; + cnpy::parse_npy_header(&buffer_uncompr[0], word_size, shape, fortran_order, typeName); + + cnpy::NpyArray array(shape, word_size, fortran_order, typeName); + + size_t offset = uncompr_bytes - array.num_bytes(); + memcpy(array.data(), &buffer_uncompr[0] + offset, array.num_bytes()); + + return array; +} + +cnpy::npz_t cnpy::npz_load(std::string fname) +{ + FILE* fp = fopen(fname.c_str(), "rb"); + + if (!fp) { + throw std::runtime_error("npz_load: Error! Unable to open file " + fname + "!"); + } + + cnpy::npz_t arrays; + + while (1) { + std::vector local_header(30); + size_t headerres = fread(&local_header[0], sizeof(char), 30, fp); + if (headerres != 30) + throw std::runtime_error("npz_load: failed fread"); + + // if we've reached the global header, stop reading + if (local_header[2] != 0x03 || local_header[3] != 0x04) + break; + + // read in the variable name + uint16_t name_len = *(uint16_t*)&local_header[26]; + std::string varname(name_len, ' '); + size_t vname_res = fread(&varname[0], sizeof(char), name_len, fp); + if (vname_res != name_len) + throw std::runtime_error("npz_load: failed fread"); + + // erase the lagging .npy + varname.erase(varname.end() - 4, varname.end()); + + // read in the extra field + uint16_t extra_field_len = *(uint16_t*)&local_header[28]; + if (extra_field_len > 0) { + std::vector buff(extra_field_len); + size_t efield_res = fread(&buff[0], sizeof(char), extra_field_len, fp); + if (efield_res != extra_field_len) + throw std::runtime_error("npz_load: failed fread"); + } + + uint16_t compr_method = *reinterpret_cast(&local_header[0] + 8); + uint32_t compr_bytes = *reinterpret_cast(&local_header[0] + 18); + uint32_t uncompr_bytes = *reinterpret_cast(&local_header[0] + 22); + + if (compr_method == 0) { + arrays[varname] = load_the_npy_file(fp); + } else { + arrays[varname] = load_the_npz_array(fp, compr_bytes, uncompr_bytes); + } + } + + fclose(fp); + return arrays; +} + +cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) +{ + FILE* fp = fopen(fname.c_str(), "rb"); + + if (!fp) + throw std::runtime_error("npz_load: Unable to open file " + fname); + + while (1) { + std::vector local_header(30); + size_t header_res = fread(&local_header[0], sizeof(char), 30, fp); + if (header_res != 30) + throw std::runtime_error("npz_load: failed fread"); + + // if we've reached the global header, stop reading + if (local_header[2] != 0x03 || local_header[3] != 0x04) + break; + + // read in the variable name + uint16_t name_len = *(uint16_t*)&local_header[26]; + std::string vname(name_len, ' '); + size_t vname_res = fread(&vname[0], sizeof(char), name_len, fp); + if (vname_res != name_len) + throw std::runtime_error("npz_load: failed fread"); + vname.erase(vname.end() - 4, vname.end()); // erase the lagging .npy + + // read in the extra field + uint16_t extra_field_len = *(uint16_t*)&local_header[28]; + fseek(fp, extra_field_len, SEEK_CUR); // skip past the extra field + + uint16_t compr_method = *reinterpret_cast(&local_header[0] + 8); + uint32_t compr_bytes = *reinterpret_cast(&local_header[0] + 18); + uint32_t uncompr_bytes = *reinterpret_cast(&local_header[0] + 22); + + if (vname == varname) { + NpyArray array = (compr_method == 0) ? load_the_npy_file(fp) : load_the_npz_array(fp, compr_bytes, uncompr_bytes); + fclose(fp); + return array; + } else { + // skip past the data + uint32_t size = *(uint32_t*)&local_header[22]; + fseek(fp, size, SEEK_CUR); + } + } + + fclose(fp); + + // if we get here, we haven't found the variable in the file + throw std::runtime_error("npz_load: Variable name " + varname + " not found in " + fname); +} + +cnpy::NpyArray cnpy::npy_load(std::string fname) +{ + FILE* fp = fopen(fname.c_str(), "rb"); + + if (!fp) + throw std::runtime_error("npy_load: Unable to open file " + fname); + + NpyArray arr = load_the_npy_file(fp); + + fclose(fp); + return arr; +} diff --git a/rknn_yolo_demo/libs/common/cnpy/cnpy.h b/rknn_yolo_demo/libs/common/cnpy/cnpy.h new file mode 100644 index 0000000..4dbc48a --- /dev/null +++ b/rknn_yolo_demo/libs/common/cnpy/cnpy.h @@ -0,0 +1,316 @@ +// Copyright (C) 2011 Carl Rogers +// Released under MIT License +// license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php + +#ifndef LIBCNPY_H_ +#define LIBCNPY_H_ + +// #include "Logging.h" +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cnpy { + +struct NpyArray +{ + NpyArray(const std::vector& _shape, size_t _word_size, bool _fortran_order, std::string _typeName) + : shape(_shape) + , word_size(_word_size) + , fortran_order(_fortran_order) + , typeName(_typeName) + { + num_vals = 1; + for (size_t i = 0; i < shape.size(); i++) + num_vals *= shape[i]; + data_holder = std::shared_ptr>(new std::vector(num_vals * word_size)); + } + + NpyArray() + : shape(0) + , word_size(0) + , fortran_order(0) + , num_vals(0) + {} + + template + T* data() + { + return reinterpret_cast(&(*data_holder)[0]); + } + + template + const T* data() const + { + return reinterpret_cast(&(*data_holder)[0]); + } + + template + std::vector as_vec() const + { + const T* p = data(); + return std::vector(p, p + num_vals); + } + + size_t num_bytes() const { return data_holder->size(); } + + std::shared_ptr> data_holder; + std::vector shape; + size_t word_size; + bool fortran_order; + size_t num_vals; + std::string typeName; +}; + +using npz_t = std::map; + +char BigEndianTest(int size); +char map_type(const std::type_info& t); +template +std::vector create_npy_header(const std::vector& shape); +void parse_npy_header(FILE* fp, size_t& word_size, std::vector& shape, bool& fortran_order, + std::string& typeName); +void parse_npy_header(unsigned char* buffer, size_t& word_size, std::vector& shape, bool& fortran_order, + std::string& typeName); +void parse_zip_footer(FILE* fp, uint16_t& nrecs, size_t& global_header_size, size_t& global_header_offset); +npz_t npz_load(std::string fname); +NpyArray npz_load(std::string fname, std::string varname); +NpyArray npy_load(std::string fname); + +template +std::vector& operator+=(std::vector& lhs, const T rhs) +{ + // write in little endian + for (size_t byte = 0; byte < sizeof(T); byte++) { + char val = *((char*)&rhs + byte); + lhs.push_back(val); + } + return lhs; +} + +template <> +std::vector& operator+=(std::vector& lhs, const std::string rhs); +template <> +std::vector& operator+=(std::vector& lhs, const char* rhs); + +template +int npy_save(std::string fname, const T* data, const std::vector shape, std::string mode = "w") +{ + std::ofstream ofs(fname, std::ios::out); + if (!ofs.is_open()) { + return -1; + } + ofs.close(); + FILE* fp = NULL; + std::vector true_data_shape; // if appending, the shape of existing + new data + + if (mode == "a") + fp = fopen(fname.c_str(), "r+b"); + + if (fp) { + // file exists. we need to append to it. read the header, modify the array size + size_t word_size; + bool fortran_order; + std::string typeName; + parse_npy_header(fp, word_size, true_data_shape, fortran_order, typeName); + assert(!fortran_order); + + if (word_size != sizeof(T)) { + std::cout << "libnpy error: " << fname << " has word size " << word_size << " but npy_save appending data sized " + << sizeof(T) << "\n"; + assert(word_size == sizeof(T)); + } + if (true_data_shape.size() != shape.size()) { + std::cout << "libnpy error: npy_save attempting to append misdimensioned data to " << fname << "\n"; + assert(true_data_shape.size() != shape.size()); + } + + for (size_t i = 1; i < shape.size(); i++) { + if (shape[i] != true_data_shape[i]) { + std::cout << "libnpy error: npy_save attempting to append misshaped data to " << fname << "\n"; + assert(shape[i] == true_data_shape[i]); + } + } + true_data_shape[0] += shape[0]; + } else { + fp = fopen(fname.c_str(), "wb"); + true_data_shape = shape; + } + + std::vector header = create_npy_header(true_data_shape); + size_t nels = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies()); + + fseek(fp, 0, SEEK_SET); + fwrite(&header[0], sizeof(char), header.size(), fp); + fseek(fp, 0, SEEK_END); + fwrite(data, sizeof(T), nels, fp); + fclose(fp); + return 0; +} + +template +void npz_save(std::string zipname, std::string fname, const T* data, const std::vector& shape, + std::string mode = "w") +{ + // first, append a .npy to the fname + fname += ".npy"; + + // now, on with the show + FILE* fp = NULL; + uint16_t nrecs = 0; + size_t global_header_offset = 0; + std::vector global_header; + + if (mode == "a") + fp = fopen(zipname.c_str(), "r+b"); + + if (fp) { + // zip file exists. we need to add a new npy file to it. + // first read the footer. this gives us the offset and size of the global header + // then read and store the global header. + // below, we will write the the new data at the start of the global header then append the global header and footer + // below it + size_t global_header_size; + parse_zip_footer(fp, nrecs, global_header_size, global_header_offset); + fseek(fp, global_header_offset, SEEK_SET); + global_header.resize(global_header_size); + size_t res = fread(&global_header[0], sizeof(char), global_header_size, fp); + if (res != global_header_size) { + throw std::runtime_error("npz_save: header read error while adding to existing zip"); + } + fseek(fp, global_header_offset, SEEK_SET); + } else { + fp = fopen(zipname.c_str(), "wb"); + } + + std::vector npy_header = create_npy_header(shape); + + size_t nels = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies()); + size_t nbytes = nels * sizeof(T) + npy_header.size(); + + // get the CRC of the data to be added + uint32_t crc = crc32(0L, (uint8_t*)&npy_header[0], npy_header.size()); + crc = crc32(crc, (uint8_t*)data, nels * sizeof(T)); + + // build the local header + std::vector local_header; + local_header += "PK"; // first part of sig + local_header += (uint16_t)0x0403; // second part of sig + local_header += (uint16_t)20; // min version to extract + local_header += (uint16_t)0; // general purpose bit flag + local_header += (uint16_t)0; // compression method + local_header += (uint16_t)0; // file last mod time + local_header += (uint16_t)0; // file last mod date + local_header += (uint32_t)crc; // crc + local_header += (uint32_t)nbytes; // compressed size + local_header += (uint32_t)nbytes; // uncompressed size + local_header += (uint16_t)fname.size(); // fname length + local_header += (uint16_t)0; // extra field length + local_header += fname; + + // build global header + global_header += "PK"; // first part of sig + global_header += (uint16_t)0x0201; // second part of sig + global_header += (uint16_t)20; // version made by + global_header.insert(global_header.end(), local_header.begin() + 4, local_header.begin() + 30); + global_header += (uint16_t)0; // file comment length + global_header += (uint16_t)0; // disk number where file starts + global_header += (uint16_t)0; // internal file attributes + global_header += (uint32_t)0; // external file attributes + global_header += (uint32_t) + global_header_offset; // relative offset of local file header, since it begins where the global header used to begin + global_header += fname; + + // build footer + std::vector footer; + footer += "PK"; // first part of sig + footer += (uint16_t)0x0605; // second part of sig + footer += (uint16_t)0; // number of this disk + footer += (uint16_t)0; // disk where footer starts + footer += (uint16_t)(nrecs + 1); // number of records on this disk + footer += (uint16_t)(nrecs + 1); // total number of records + footer += (uint32_t)global_header.size(); // nbytes of global headers + footer += + (uint32_t)(global_header_offset + nbytes + local_header.size()); // offset of start of global headers, since global + // header now starts after newly written array + footer += (uint16_t)0; // zip file comment length + + // write everything + fwrite(&local_header[0], sizeof(char), local_header.size(), fp); + fwrite(&npy_header[0], sizeof(char), npy_header.size(), fp); + fwrite(data, sizeof(T), nels, fp); + fwrite(&global_header[0], sizeof(char), global_header.size(), fp); + fwrite(&footer[0], sizeof(char), footer.size(), fp); + fclose(fp); +} + +template +void npy_save(std::string fname, const std::vector data, std::string mode = "w") +{ + std::vector shape; + shape.push_back(data.size()); + npy_save(fname, &data[0], shape, mode); +} + +template +void npz_save(std::string zipname, std::string fname, const std::vector data, std::string mode = "w") +{ + std::vector shape; + shape.push_back(data.size()); + npz_save(zipname, fname, &data[0], shape, mode); +} + +template +std::vector create_npy_header(const std::vector& shape) +{ + const char* tpye_name = typeid(T).name(); + std::vector dict; + dict += "{'descr': '"; + dict += BigEndianTest(sizeof(T)); + if (std::string(tpye_name) == "N4rknn7float16E") { + dict += "f"; + } else { + dict += map_type(typeid(T)); + } + dict += std::to_string(sizeof(T)); + dict += "', 'fortran_order': False, 'shape': ("; + dict += std::to_string(shape[0]); + for (size_t i = 1; i < shape.size(); i++) { + dict += ", "; + dict += std::to_string(shape[i]); + } + if (shape.size() == 1) + dict += ","; + dict += "), }"; + // pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 bytes. dict needs to end with \n + int remainder = 16 - (10 + dict.size()) % 16; + dict.insert(dict.end(), remainder, ' '); + dict.back() = '\n'; + + std::vector header; + header += (char)0x93; + header += "NUMPY"; + header += (char)0x01; // major version of numpy format + header += (char)0x00; // minor version of numpy format + header += (uint16_t)dict.size(); + header.insert(header.end(), dict.begin(), dict.end()); + + return header; +} + +} // namespace cnpy + +#endif diff --git a/rknn_yolo_demo/libs/common/cnpy/logging.h b/rknn_yolo_demo/libs/common/cnpy/logging.h new file mode 100644 index 0000000..4cd247e --- /dev/null +++ b/rknn_yolo_demo/libs/common/cnpy/logging.h @@ -0,0 +1,1662 @@ +// Copyright (c) 1999, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Ray Sidney +// +// This file contains #include information about logging-related stuff. +// Pretty much everybody needs to #include this file so that they can +// log various happenings. +// +#ifndef _LOGGING_H_ +#define _LOGGING_H_ + +#include +#include +#include +#include +#include +#include +#include +#if 1 +# include +#endif +#include + +#if defined(_MSC_VER) +#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \ + __pragma(warning(disable:n)) +#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop)) +#else +#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) +#define GLOG_MSVC_POP_WARNING() +#endif + +// Annoying stuff for windows -- makes sure clients can import these functions +#ifndef GOOGLE_GLOG_DLL_DECL +# if defined(_WIN32) && !defined(__CYGWIN__) +# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport) +# else +# define GOOGLE_GLOG_DLL_DECL +# endif +#endif + +// We care a lot about number of bits things take up. Unfortunately, +// systems define their bit-specific ints in a lot of different ways. +// We use our own way, and have a typedef to get there. +// Note: these commands below may look like "#if 1" or "#if 0", but +// that's because they were constructed that way at ./configure time. +// Look at logging.h.in to see how they're calculated (based on your config). +#if 1 +#include // the normal place uint16_t is defined +#endif +#if 1 +#include // the normal place u_int16_t is defined +#endif +#if 1 +#include // a third place for uint16_t or u_int16_t +#endif + +#if 0 +#include +#endif + +namespace google { + +#if 1 // the C99 format +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +#elif 1 // the BSD format +typedef int32_t int32; +typedef u_int32_t uint32; +typedef int64_t int64; +typedef u_int64_t uint64; +#elif 0 // the windows (vc7) format +typedef __int32 int32; +typedef unsigned __int32 uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; +#else +#error Do not know how to define a 32-bit integer quantity on your system +#endif + +} + +// The global value of GOOGLE_STRIP_LOG. All the messages logged to +// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed. +// If it can be determined at compile time that the message will not be +// printed, the statement will be compiled out. +// +// Example: to strip out all INFO and WARNING messages, use the value +// of 2 below. To make an exception for WARNING messages from a single +// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including +// base/logging.h +#ifndef GOOGLE_STRIP_LOG +#define GOOGLE_STRIP_LOG 0 +#endif + +// GCC can be told that a certain branch is not likely to be taken (for +// instance, a CHECK failure), and use that information in static analysis. +// Giving it this information can help it optimize for the common case in +// the absence of better information (ie. -fprofile-arcs). +// +#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN +#if 1 +#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0)) +#else +#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x +#endif +#endif + +#ifndef GOOGLE_PREDICT_FALSE +#if 1 +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#else +#define GOOGLE_PREDICT_FALSE(x) x +#endif +#endif + +#ifndef GOOGLE_PREDICT_TRUE +#if 1 +#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) +#else +#define GOOGLE_PREDICT_TRUE(x) x +#endif +#endif + + +// Make a bunch of macros for logging. The way to log things is to stream +// things to LOG(). E.g., +// +// LOG(INFO) << "Found " << num_cookies << " cookies"; +// +// You can capture log messages in a string, rather than reporting them +// immediately: +// +// vector errors; +// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num; +// +// This pushes back the new error onto 'errors'; if given a NULL pointer, +// it reports the error via LOG(ERROR). +// +// You can also do conditional logging: +// +// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; +// +// You can also do occasional logging (log every n'th occurrence of an +// event): +// +// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie"; +// +// The above will cause log messages to be output on the 1st, 11th, 21st, ... +// times it is executed. Note that the special google::COUNTER value is used +// to identify which repetition is happening. +// +// You can also do occasional conditional logging (log every n'th +// occurrence of an event, when condition is satisfied): +// +// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER +// << "th big cookie"; +// +// You can log messages the first N times your code executes a line. E.g. +// +// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie"; +// +// Outputs log messages for the first 20 times it is executed. +// +// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available. +// These log to syslog as well as to the normal logs. If you use these at +// all, you need to be aware that syslog can drastically reduce performance, +// especially if it is configured for remote logging! Don't use these +// unless you fully understand this and have a concrete need to use them. +// Even then, try to minimize your use of them. +// +// There are also "debug mode" logging macros like the ones above: +// +// DLOG(INFO) << "Found cookies"; +// +// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; +// +// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie"; +// +// All "debug mode" logging is compiled away to nothing for non-debug mode +// compiles. +// +// We also have +// +// LOG_ASSERT(assertion); +// DLOG_ASSERT(assertion); +// +// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion; +// +// There are "verbose level" logging macros. They look like +// +// VLOG(1) << "I'm printed when you run the program with --v=1 or more"; +// VLOG(2) << "I'm printed when you run the program with --v=2 or more"; +// +// These always log at the INFO log level (when they log at all). +// The verbose logging can also be turned on module-by-module. For instance, +// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0 +// will cause: +// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc} +// b. VLOG(1) and lower messages to be printed from file.{h,cc} +// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs" +// d. VLOG(0) and lower messages to be printed from elsewhere +// +// The wildcarding functionality shown by (c) supports both '*' (match +// 0 or more characters) and '?' (match any single character) wildcards. +// +// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as +// +// if (VLOG_IS_ON(2)) { +// // do some logging preparation and logging +// // that can't be accomplished with just VLOG(2) << ...; +// } +// +// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level" +// condition macros for sample cases, when some extra computation and +// preparation for logs is not needed. +// VLOG_IF(1, (size > 1024)) +// << "I'm printed when size is more than 1024 and when you run the " +// "program with --v=1 or more"; +// VLOG_EVERY_N(1, 10) +// << "I'm printed every 10th occurrence, and when you run the program " +// "with --v=1 or more. Present occurence is " << google::COUNTER; +// VLOG_IF_EVERY_N(1, (size > 1024), 10) +// << "I'm printed on every 10th occurence of case when size is more " +// " than 1024, when you run the program with --v=1 or more. "; +// "Present occurence is " << google::COUNTER; +// +// The supported severity levels for macros that allow you to specify one +// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL. +// Note that messages of a given severity are logged not only in the +// logfile for that severity, but also in all logfiles of lower severity. +// E.g., a message of severity FATAL will be logged to the logfiles of +// severity FATAL, ERROR, WARNING, and INFO. +// +// There is also the special severity of DFATAL, which logs FATAL in +// debug mode, ERROR in normal mode. +// +// Very important: logging a message at the FATAL severity level causes +// the program to terminate (after the message is logged). +// +// Unless otherwise specified, logs will be written to the filename +// "...log..", followed +// by the date, time, and pid (you can't prevent the date, time, and pid +// from being in the filename). +// +// The logging code takes two flags: +// --v=# set the verbose level +// --logtostderr log all the messages to stderr instead of to logfiles + +// LOG LINE PREFIX FORMAT +// +// Log lines have this form: +// +// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... +// +// where the fields are defined as follows: +// +// L A single character, representing the log level +// (eg 'I' for INFO) +// mm The month (zero padded; ie May is '05') +// dd The day (zero padded) +// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds +// threadid The space-padded thread ID as returned by GetTID() +// (this matches the PID on Linux) +// file The file name +// line The line number +// msg The user-supplied message +// +// Example: +// +// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog +// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395 +// +// NOTE: although the microseconds are useful for comparing events on +// a single machine, clocks on different machines may not be well +// synchronized. Hence, use caution when comparing the low bits of +// timestamps from different machines. + +#ifndef DECLARE_VARIABLE +#define MUST_UNDEF_GFLAGS_DECLARE_MACROS +#define DECLARE_VARIABLE(type, shorttype, name, tn) \ + namespace fL##shorttype { \ + extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \ + } \ + using fL##shorttype::FLAGS_##name + +// bool specialization +#define DECLARE_bool(name) \ + DECLARE_VARIABLE(bool, B, name, bool) + +// int32 specialization +#define DECLARE_int32(name) \ + DECLARE_VARIABLE(google::int32, I, name, int32) + +// Special case for string, because we have to specify the namespace +// std::string, which doesn't play nicely with our FLAG__namespace hackery. +#define DECLARE_string(name) \ + namespace fLS { \ + extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \ + } \ + using fLS::FLAGS_##name +#endif + +// Set whether log messages go to stderr instead of logfiles +DECLARE_bool(logtostderr); + +// Set whether log messages go to stderr in addition to logfiles. +DECLARE_bool(alsologtostderr); + +// Set color messages logged to stderr (if supported by terminal). +DECLARE_bool(colorlogtostderr); + +// Log messages at a level >= this flag are automatically sent to +// stderr in addition to log files. +DECLARE_int32(stderrthreshold); + +// Set whether the log prefix should be prepended to each line of output. +DECLARE_bool(log_prefix); + +// Log messages at a level <= this flag are buffered. +// Log messages at a higher level are flushed immediately. +DECLARE_int32(logbuflevel); + +// Sets the maximum number of seconds which logs may be buffered for. +DECLARE_int32(logbufsecs); + +// Log suppression level: messages logged at a lower level than this +// are suppressed. +DECLARE_int32(minloglevel); + +// If specified, logfiles are written into this directory instead of the +// default logging directory. +DECLARE_string(log_dir); + +// Set the log file mode. +DECLARE_int32(logfile_mode); + +// Sets the path of the directory into which to put additional links +// to the log files. +DECLARE_string(log_link); + +DECLARE_int32(v); // in vlog_is_on.cc + +// Sets the maximum log file size (in MB). +DECLARE_int32(max_log_size); + +// Sets whether to avoid logging to the disk if the disk is full. +DECLARE_bool(stop_logging_if_full_disk); + +#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS +#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS +#undef DECLARE_VARIABLE +#undef DECLARE_bool +#undef DECLARE_int32 +#undef DECLARE_string +#endif + +// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for +// security reasons. See LOG(severtiy) below. + +// A few definitions of macros that don't generate much code. Since +// LOG(INFO) and its ilk are used all over our code, it's +// better to have compact code for these operations. + +#if GOOGLE_STRIP_LOG == 0 +#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \ + __FILE__, __LINE__) +#define LOG_TO_STRING_INFO(message) google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_INFO, message) +#else +#define COMPACT_GOOGLE_LOG_INFO google::NullStream() +#define LOG_TO_STRING_INFO(message) google::NullStream() +#endif + +#if GOOGLE_STRIP_LOG <= 1 +#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_WARNING) +#define LOG_TO_STRING_WARNING(message) google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_WARNING, message) +#else +#define COMPACT_GOOGLE_LOG_WARNING google::NullStream() +#define LOG_TO_STRING_WARNING(message) google::NullStream() +#endif + +#if GOOGLE_STRIP_LOG <= 2 +#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_ERROR) +#define LOG_TO_STRING_ERROR(message) google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_ERROR, message) +#else +#define COMPACT_GOOGLE_LOG_ERROR google::NullStream() +#define LOG_TO_STRING_ERROR(message) google::NullStream() +#endif + +#if GOOGLE_STRIP_LOG <= 3 +#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \ + __FILE__, __LINE__) +#define LOG_TO_STRING_FATAL(message) google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_FATAL, message) +#else +#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal() +#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal() +#endif + +#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) +#define DCHECK_IS_ON() 0 +#else +#define DCHECK_IS_ON() 1 +#endif + +// For DFATAL, we want to use LogMessage (as opposed to +// LogMessageFatal), to be consistent with the original behavior. +#if !DCHECK_IS_ON() +#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR +#elif GOOGLE_STRIP_LOG <= 3 +#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_FATAL) +#else +#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal() +#endif + +#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog) +#define SYSLOG_INFO(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \ + &google::LogMessage::SendToSyslogAndLog) +#define GOOGLE_LOG_WARNING(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \ + &google::LogMessage::SendToLog) +#define SYSLOG_WARNING(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \ + &google::LogMessage::SendToSyslogAndLog) +#define GOOGLE_LOG_ERROR(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \ + &google::LogMessage::SendToLog) +#define SYSLOG_ERROR(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \ + &google::LogMessage::SendToSyslogAndLog) +#define GOOGLE_LOG_FATAL(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \ + &google::LogMessage::SendToLog) +#define SYSLOG_FATAL(counter) \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \ + &google::LogMessage::SendToSyslogAndLog) +#define GOOGLE_LOG_DFATAL(counter) \ + google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \ + &google::LogMessage::SendToLog) +#define SYSLOG_DFATAL(counter) \ + google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \ + &google::LogMessage::SendToSyslogAndLog) + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__) +// A very useful logging macro to log windows errors: +#define LOG_SYSRESULT(result) \ + if (FAILED(HRESULT_FROM_WIN32(result))) { \ + LPSTR message = NULL; \ + LPSTR msg = reinterpret_cast(&message); \ + DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \ + FORMAT_MESSAGE_FROM_SYSTEM, \ + 0, result, 0, msg, 100, NULL); \ + if (message_length > 0) { \ + google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \ + &google::LogMessage::SendToLog).stream() \ + << reinterpret_cast(message); \ + LocalFree(message); \ + } \ + } +#endif + +// We use the preprocessor's merging operator, "##", so that, e.g., +// LOG(INFO) becomes the token GOOGLE_LOG_INFO. There's some funny +// subtle difference between ostream member streaming functions (e.g., +// ostream::operator<<(int) and ostream non-member streaming functions +// (e.g., ::operator<<(ostream&, string&): it turns out that it's +// impossible to stream something like a string directly to an unnamed +// ostream. We employ a neat hack by calling the stream() member +// function of LogMessage which seems to avoid the problem. +#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream() +#define SYSLOG(severity) SYSLOG_ ## severity(0).stream() + +namespace google { + +// They need the definitions of integer types. +#include "glog/log_severity.h" +#include "glog/vlog_is_on.h" + +// Initialize google's logging library. You will see the program name +// specified by argv0 in log outputs. +GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0); + +// Shutdown google's logging library. +GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging(); + +// Install a function which will be called after LOG(FATAL). +GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)()); + +class LogSink; // defined below + +// If a non-NULL sink pointer is given, we push this message to that sink. +// For LOG_TO_SINK we then do normal LOG(severity) logging as well. +// This is useful for capturing messages and passing/storing them +// somewhere more specific than the global log of the process. +// Argument types: +// LogSink* sink; +// LogSeverity severity; +// The cast is to disambiguate NULL arguments. +#define LOG_TO_SINK(sink, severity) \ + google::LogMessage( \ + __FILE__, __LINE__, \ + google::GLOG_ ## severity, \ + static_cast(sink), true).stream() +#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \ + google::LogMessage( \ + __FILE__, __LINE__, \ + google::GLOG_ ## severity, \ + static_cast(sink), false).stream() + +// If a non-NULL string pointer is given, we write this message to that string. +// We then do normal LOG(severity) logging as well. +// This is useful for capturing messages and storing them somewhere more +// specific than the global log of the process. +// Argument types: +// string* message; +// LogSeverity severity; +// The cast is to disambiguate NULL arguments. +// NOTE: LOG(severity) expands to LogMessage().stream() for the specified +// severity. +#define LOG_TO_STRING(severity, message) \ + LOG_TO_STRING_##severity(static_cast(message)).stream() + +// If a non-NULL pointer is given, we push the message onto the end +// of a vector of strings; otherwise, we report it with LOG(severity). +// This is handy for capturing messages and perhaps passing them back +// to the caller, rather than reporting them immediately. +// Argument types: +// LogSeverity severity; +// vector *outvec; +// The cast is to disambiguate NULL arguments. +#define LOG_STRING(severity, outvec) \ + LOG_TO_STRING_##severity(static_cast*>(outvec)).stream() + +#define LOG_IF(severity, condition) \ + static_cast(0), \ + !(condition) ? (void) 0 : google::LogMessageVoidify() & LOG(severity) +#define SYSLOG_IF(severity, condition) \ + static_cast(0), \ + !(condition) ? (void) 0 : google::LogMessageVoidify() & SYSLOG(severity) + +#define LOG_ASSERT(condition) \ + LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition +#define SYSLOG_ASSERT(condition) \ + SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition + +// CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by DCHECK_IS_ON(), so the check will be executed regardless of +// compilation mode. Therefore, it is safe to do things like: +// CHECK(fp->Write(x) == 4) +#define CHECK(condition) \ + LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \ + << "Check failed: " #condition " " + +// A container for a string pointer which can be evaluated to a bool - +// true iff the pointer is NULL. +struct CheckOpString { + CheckOpString(std::string* str) : str_(str) { } + // No destructor: if str_ is non-NULL, we're about to LOG(FATAL), + // so there's no point in cleaning up str_. + operator bool() const { + return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL); + } + std::string* str_; +}; + +// Function is overloaded for integral types to allow static const +// integrals declared in classes and not defined to be used as arguments to +// CHECK* macros. It's not encouraged though. +template +inline const T& GetReferenceableValue(const T& t) { return t; } +inline char GetReferenceableValue(char t) { return t; } +inline unsigned char GetReferenceableValue(unsigned char t) { return t; } +inline signed char GetReferenceableValue(signed char t) { return t; } +inline short GetReferenceableValue(short t) { return t; } +inline unsigned short GetReferenceableValue(unsigned short t) { return t; } +inline int GetReferenceableValue(int t) { return t; } +inline unsigned int GetReferenceableValue(unsigned int t) { return t; } +inline long GetReferenceableValue(long t) { return t; } +inline unsigned long GetReferenceableValue(unsigned long t) { return t; } +inline long long GetReferenceableValue(long long t) { return t; } +inline unsigned long long GetReferenceableValue(unsigned long long t) { + return t; +} + +// This is a dummy class to define the following operator. +struct DummyClassToDefineOperator {}; + +} + +// Define global operator<< to declare using ::operator<<. +// This declaration will allow use to use CHECK macros for user +// defined classes which have operator<< (e.g., stl_logging.h). +inline std::ostream& operator<<( + std::ostream& out, const google::DummyClassToDefineOperator&) { + return out; +} + +namespace google { + +// This formats a value for a failing CHECK_XX statement. Ordinarily, +// it uses the definition for operator<<, with a few special cases below. +template +inline void MakeCheckOpValueString(std::ostream* os, const T& v) { + (*os) << v; +} + +// Overrides for char types provide readable values for unprintable +// characters. +template <> GOOGLE_GLOG_DLL_DECL +void MakeCheckOpValueString(std::ostream* os, const char& v); +template <> GOOGLE_GLOG_DLL_DECL +void MakeCheckOpValueString(std::ostream* os, const signed char& v); +template <> GOOGLE_GLOG_DLL_DECL +void MakeCheckOpValueString(std::ostream* os, const unsigned char& v); + +// Build the error message string. Specify no inlining for code size. +template +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) + __attribute__((noinline)); + +namespace base { +namespace internal { + +// If "s" is less than base_logging::INFO, returns base_logging::INFO. +// If "s" is greater than base_logging::FATAL, returns +// base_logging::ERROR. Otherwise, returns "s". +LogSeverity NormalizeSeverity(LogSeverity s); + +} // namespace internal + +// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX +// statement. See MakeCheckOpString for sample usage. Other +// approaches were considered: use of a template method (e.g., +// base::BuildCheckOpString(exprtext, base::Print, &v1, +// base::Print, &v2), however this approach has complications +// related to volatile arguments and function-pointer arguments). +class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder { + public: + // Inserts "exprtext" and " (" to the stream. + explicit CheckOpMessageBuilder(const char *exprtext); + // Deletes "stream_". + ~CheckOpMessageBuilder(); + // For inserting the first variable. + std::ostream* ForVar1() { return stream_; } + // For inserting the second variable (adds an intermediate " vs. "). + std::ostream* ForVar2(); + // Get the result (inserts the closing ")"). + std::string* NewString(); + + private: + std::ostringstream *stream_; +}; + +} // namespace base + +template +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) { + base::CheckOpMessageBuilder comb(exprtext); + MakeCheckOpValueString(comb.ForVar1(), v1); + MakeCheckOpValueString(comb.ForVar2(), v2); + return comb.NewString(); +} + +// Helper functions for CHECK_OP macro. +// The (int, int) specialization works around the issue that the compiler +// will not instantiate the template version of the function on values of +// unnamed enum type - see comment below. +#define DEFINE_CHECK_OP_IMPL(name, op) \ + template \ + inline std::string* name##Impl(const T1& v1, const T2& v2, \ + const char* exprtext) { \ + if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \ + else return MakeCheckOpString(v1, v2, exprtext); \ + } \ + inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \ + return name##Impl(v1, v2, exprtext); \ + } + +// We use the full name Check_EQ, Check_NE, etc. in case the file including +// base/logging.h provides its own #defines for the simpler names EQ, NE, etc. +// This happens if, for example, those are used as token names in a +// yacc grammar. +DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)? +DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead. +DEFINE_CHECK_OP_IMPL(Check_LE, <=) +DEFINE_CHECK_OP_IMPL(Check_LT, < ) +DEFINE_CHECK_OP_IMPL(Check_GE, >=) +DEFINE_CHECK_OP_IMPL(Check_GT, > ) +#undef DEFINE_CHECK_OP_IMPL + +// Helper macro for binary operators. +// Don't use this macro directly in your code, use CHECK_EQ et al below. + +#if defined(STATIC_ANALYSIS) +// Only for static analysis tool to know that it is equivalent to assert +#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2)) +#elif DCHECK_IS_ON() +// In debug mode, avoid constructing CheckOpStrings if possible, +// to reduce the overhead of CHECK statments by 2x. +// Real DCHECK-heavy tests have seen 1.5x speedups. + +// The meaning of "string" might be different between now and +// when this macro gets invoked (e.g., if someone is experimenting +// with other string implementations that get defined after this +// file is included). Save the current meaning now and use it +// in the macro. +typedef std::string _Check_string; +#define CHECK_OP_LOG(name, op, val1, val2, log) \ + while (google::_Check_string* _result = \ + google::Check##name##Impl( \ + google::GetReferenceableValue(val1), \ + google::GetReferenceableValue(val2), \ + #val1 " " #op " " #val2)) \ + log(__FILE__, __LINE__, \ + google::CheckOpString(_result)).stream() +#else +// In optimized mode, use CheckOpString to hint to compiler that +// the while condition is unlikely. +#define CHECK_OP_LOG(name, op, val1, val2, log) \ + while (google::CheckOpString _result = \ + google::Check##name##Impl( \ + google::GetReferenceableValue(val1), \ + google::GetReferenceableValue(val2), \ + #val1 " " #op " " #val2)) \ + log(__FILE__, __LINE__, _result).stream() +#endif // STATIC_ANALYSIS, DCHECK_IS_ON() + +#if GOOGLE_STRIP_LOG <= 3 +#define CHECK_OP(name, op, val1, val2) \ + CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal) +#else +#define CHECK_OP(name, op, val1, val2) \ + CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal) +#endif // STRIP_LOG <= 3 + +// Equality/Inequality checks - compare two values, and log a FATAL message +// including the two values when the result is not as expected. The values +// must have operator<<(ostream, ...) defined. +// +// You may append to the error message like so: +// CHECK_NE(1, 2) << ": The world must be ending!"; +// +// We are very careful to ensure that each argument is evaluated exactly +// once, and that anything which is legal to pass as a function argument is +// legal here. In particular, the arguments may be temporary expressions +// which will end up being destroyed at the end of the apparent statement, +// for example: +// CHECK_EQ(string("abc")[1], 'b'); +// +// WARNING: These don't compile correctly if one of the arguments is a pointer +// and the other is NULL. To work around this, simply static_cast NULL to the +// type of the desired pointer. + +#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2) +#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2) +#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2) +#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2) +#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2) +#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2) + +// Check that the input is non NULL. This very useful in constructor +// initializer lists. + +#define CHECK_NOTNULL(val) \ + google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val)) + +// Helper functions for string comparisons. +// To avoid bloat, the definitions are in logging.cc. +#define DECLARE_CHECK_STROP_IMPL(func, expected) \ + GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \ + const char* s1, const char* s2, const char* names); +DECLARE_CHECK_STROP_IMPL(strcmp, true) +DECLARE_CHECK_STROP_IMPL(strcmp, false) +DECLARE_CHECK_STROP_IMPL(strcasecmp, true) +DECLARE_CHECK_STROP_IMPL(strcasecmp, false) +#undef DECLARE_CHECK_STROP_IMPL + +// Helper macro for string comparisons. +// Don't use this macro directly in your code, use CHECK_STREQ et al below. +#define CHECK_STROP(func, op, expected, s1, s2) \ + while (google::CheckOpString _result = \ + google::Check##func##expected##Impl((s1), (s2), \ + #s1 " " #op " " #s2)) \ + LOG(FATAL) << *_result.str_ + + +// String (char*) equality/inequality checks. +// CASE versions are case-insensitive. +// +// Note that "s1" and "s2" may be temporary strings which are destroyed +// by the compiler at the end of the current "full expression" +// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())). + +#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2) +#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2) +#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2) +#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2) + +#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0]))) +#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0]))) + +#define CHECK_DOUBLE_EQ(val1, val2) \ + do { \ + CHECK_LE((val1), (val2)+0.000000000000001L); \ + CHECK_GE((val1), (val2)-0.000000000000001L); \ + } while (0) + +#define CHECK_NEAR(val1, val2, margin) \ + do { \ + CHECK_LE((val1), (val2)+(margin)); \ + CHECK_GE((val1), (val2)-(margin)); \ + } while (0) + +// perror()..googly style! +// +// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and +// CHECK equivalents with the addition that they postpend a description +// of the current state of errno to their output lines. + +#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream() + +#define GOOGLE_PLOG(severity, counter) \ + google::ErrnoLogMessage( \ + __FILE__, __LINE__, google::GLOG_ ## severity, counter, \ + &google::LogMessage::SendToLog) + +#define PLOG_IF(severity, condition) \ + static_cast(0), \ + !(condition) ? (void) 0 : google::LogMessageVoidify() & PLOG(severity) + +// A CHECK() macro that postpends errno if the condition is false. E.g. +// +// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... } +#define PCHECK(condition) \ + PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \ + << "Check failed: " #condition " " + +// A CHECK() macro that lets you assert the success of a function that +// returns -1 and sets errno in case of an error. E.g. +// +// CHECK_ERR(mkdir(path, 0700)); +// +// or +// +// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename; +#define CHECK_ERR(invocation) \ +PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \ + << #invocation + +// Use macro expansion to create, for each use of LOG_EVERY_N(), static +// variables with the __LINE__ expansion as part of the variable name. +#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line) +#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line + +#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__) +#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__) + +#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \ + static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \ + ++LOG_OCCURRENCES; \ + if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \ + if (LOG_OCCURRENCES_MOD_N == 1) \ + google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \ + &what_to_do).stream() + +#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \ + static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \ + ++LOG_OCCURRENCES; \ + if (condition && \ + ((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \ + google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \ + &what_to_do).stream() + +#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \ + static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \ + ++LOG_OCCURRENCES; \ + if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \ + if (LOG_OCCURRENCES_MOD_N == 1) \ + google::ErrnoLogMessage( \ + __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \ + &what_to_do).stream() + +#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \ + static int LOG_OCCURRENCES = 0; \ + if (LOG_OCCURRENCES <= n) \ + ++LOG_OCCURRENCES; \ + if (LOG_OCCURRENCES <= n) \ + google::LogMessage( \ + __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \ + &what_to_do).stream() + +namespace glog_internal_namespace_ { +template +struct CompileAssert { +}; +struct CrashReason; + +// Returns true if FailureSignalHandler is installed. +// Needs to be exported since it's used by the signalhandler_unittest. +GOOGLE_GLOG_DLL_DECL bool IsFailureSignalHandlerInstalled(); +} // namespace glog_internal_namespace_ + +#define LOG_EVERY_N(severity, n) \ + SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog) + +#define SYSLOG_EVERY_N(severity, n) \ + SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToSyslogAndLog) + +#define PLOG_EVERY_N(severity, n) \ + SOME_KIND_OF_PLOG_EVERY_N(severity, (n), google::LogMessage::SendToLog) + +#define LOG_FIRST_N(severity, n) \ + SOME_KIND_OF_LOG_FIRST_N(severity, (n), google::LogMessage::SendToLog) + +#define LOG_IF_EVERY_N(severity, condition, n) \ + SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), google::LogMessage::SendToLog) + +// We want the special COUNTER value available for LOG_EVERY_X()'ed messages +enum PRIVATE_Counter {COUNTER}; + +#ifdef GLOG_NO_ABBREVIATED_SEVERITIES +// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets +// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us +// to keep using this syntax, we define this macro to do the same thing +// as COMPACT_GOOGLE_LOG_ERROR. +#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR +#define SYSLOG_0 SYSLOG_ERROR +#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR +// Needed for LOG_IS_ON(ERROR). +const LogSeverity GLOG_0 = GLOG_ERROR; +#else +// Users may include windows.h after logging.h without +// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN. +// For this case, we cannot detect if ERROR is defined before users +// actually use ERROR. Let's make an undefined symbol to warn users. +# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail +# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG +# define SYSLOG_0 GLOG_ERROR_MSG +# define LOG_TO_STRING_0 GLOG_ERROR_MSG +# define GLOG_0 GLOG_ERROR_MSG +#endif + +// Plus some debug-logging macros that get compiled to nothing for production + +#if DCHECK_IS_ON() + +#define DLOG(severity) LOG(severity) +#define DVLOG(verboselevel) VLOG(verboselevel) +#define DLOG_IF(severity, condition) LOG_IF(severity, condition) +#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n) +#define DLOG_IF_EVERY_N(severity, condition, n) \ + LOG_IF_EVERY_N(severity, condition, n) +#define DLOG_ASSERT(condition) LOG_ASSERT(condition) + +// debug-only checking. executed if DCHECK_IS_ON(). +#define DCHECK(condition) CHECK(condition) +#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) +#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) +#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) +#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) +#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) +#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) +#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val) +#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2) +#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2) +#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2) +#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2) + +#else // !DCHECK_IS_ON() + +#define DLOG(severity) \ + static_cast(0), \ + true ? (void) 0 : google::LogMessageVoidify() & LOG(severity) + +#define DVLOG(verboselevel) \ + static_cast(0), \ + (true || !VLOG_IS_ON(verboselevel)) ? \ + (void) 0 : google::LogMessageVoidify() & LOG(INFO) + +#define DLOG_IF(severity, condition) \ + static_cast(0), \ + (true || !(condition)) ? (void) 0 : google::LogMessageVoidify() & LOG(severity) + +#define DLOG_EVERY_N(severity, n) \ + static_cast(0), \ + true ? (void) 0 : google::LogMessageVoidify() & LOG(severity) + +#define DLOG_IF_EVERY_N(severity, condition, n) \ + static_cast(0), \ + (true || !(condition))? (void) 0 : google::LogMessageVoidify() & LOG(severity) + +#define DLOG_ASSERT(condition) \ + static_cast(0), \ + true ? (void) 0 : LOG_ASSERT(condition) + +// MSVC warning C4127: conditional expression is constant +#define DCHECK(condition) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK(condition) + +#define DCHECK_EQ(val1, val2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2) + +#define DCHECK_NE(val1, val2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2) + +#define DCHECK_LE(val1, val2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2) + +#define DCHECK_LT(val1, val2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2) + +#define DCHECK_GE(val1, val2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2) + +#define DCHECK_GT(val1, val2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2) + +// You may see warnings in release mode if you don't use the return +// value of DCHECK_NOTNULL. Please just use DCHECK for such cases. +#define DCHECK_NOTNULL(val) (val) + +#define DCHECK_STREQ(str1, str2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2) + +#define DCHECK_STRCASEEQ(str1, str2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2) + +#define DCHECK_STRNE(str1, str2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2) + +#define DCHECK_STRCASENE(str1, str2) \ + GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ + while (false) \ + GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2) + +#endif // DCHECK_IS_ON() + +// Log only in verbose mode. + +#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel)) + +#define VLOG_IF(verboselevel, condition) \ + LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel)) + +#define VLOG_EVERY_N(verboselevel, n) \ + LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n) + +#define VLOG_IF_EVERY_N(verboselevel, condition, n) \ + LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n) + +namespace base_logging { + +// LogMessage::LogStream is a std::ostream backed by this streambuf. +// This class ignores overflow and leaves two bytes at the end of the +// buffer to allow for a '\n' and '\0'. +class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf { + public: + // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\0'. + LogStreamBuf(char *buf, int len) { + setp(buf, buf + len - 2); + } + + // This effectively ignores overflow. + virtual int_type overflow(int_type ch) { + return ch; + } + + // Legacy public ostrstream method. + size_t pcount() const { return pptr() - pbase(); } + char* pbase() const { return std::streambuf::pbase(); } +}; + +} // namespace base_logging + +// +// This class more or less represents a particular log message. You +// create an instance of LogMessage and then stream stuff to it. +// When you finish streaming to it, ~LogMessage is called and the +// full message gets streamed to the appropriate destination. +// +// You shouldn't actually use LogMessage's constructor to log things, +// though. You should use the LOG() macro (and variants thereof) +// above. +class GOOGLE_GLOG_DLL_DECL LogMessage { +public: + enum { + // Passing kNoLogPrefix for the line number disables the + // log-message prefix. Useful for using the LogMessage + // infrastructure as a printing utility. See also the --log_prefix + // flag for controlling the log-message prefix on an + // application-wide basis. + kNoLogPrefix = -1 + }; + + // LogStream inherit from non-DLL-exported class (std::ostrstream) + // and VC++ produces a warning for this situation. + // However, MSDN says "C4275 can be ignored in Microsoft Visual C++ + // 2005 if you are deriving from a type in the Standard C++ Library" + // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx + // Let's just ignore the warning. +GLOG_MSVC_PUSH_DISABLE_WARNING(4275) + class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream { +GLOG_MSVC_POP_WARNING() + public: + LogStream(char *buf, int len, int ctr) + : std::ostream(NULL), + streambuf_(buf, len), + ctr_(ctr), + self_(this) { + rdbuf(&streambuf_); + } + + int ctr() const { return ctr_; } + void set_ctr(int ctr) { ctr_ = ctr; } + LogStream* self() const { return self_; } + + // Legacy std::streambuf methods. + size_t pcount() const { return streambuf_.pcount(); } + char* pbase() const { return streambuf_.pbase(); } + char* str() const { return pbase(); } + + private: + LogStream(const LogStream&); + LogStream& operator=(const LogStream&); + base_logging::LogStreamBuf streambuf_; + int ctr_; // Counter hack (for the LOG_EVERY_X() macro) + LogStream *self_; // Consistency check hack + }; + +public: + // icc 8 requires this typedef to avoid an internal compiler error. + typedef void (LogMessage::*SendMethod)(); + + LogMessage(const char* file, int line, LogSeverity severity, int ctr, + SendMethod send_method); + + // Two special constructors that generate reduced amounts of code at + // LOG call sites for common cases. + + // Used for LOG(INFO): Implied are: + // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog. + // + // Using this constructor instead of the more complex constructor above + // saves 19 bytes per call site. + LogMessage(const char* file, int line); + + // Used for LOG(severity) where severity != INFO. Implied + // are: ctr = 0, send_method = &LogMessage::SendToLog + // + // Using this constructor instead of the more complex constructor above + // saves 17 bytes per call site. + LogMessage(const char* file, int line, LogSeverity severity); + + // Constructor to log this message to a specified sink (if not NULL). + // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if + // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise. + LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink, + bool also_send_to_log); + + // Constructor where we also give a vector pointer + // for storing the messages (if the pointer is not NULL). + // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog. + LogMessage(const char* file, int line, LogSeverity severity, + std::vector* outvec); + + // Constructor where we also give a string pointer for storing the + // message (if the pointer is not NULL). Implied are: ctr = 0, + // send_method = &LogMessage::WriteToStringAndLog. + LogMessage(const char* file, int line, LogSeverity severity, + std::string* message); + + // A special constructor used for check failures + LogMessage(const char* file, int line, const CheckOpString& result); + + ~LogMessage(); + + // Flush a buffered message to the sink set in the constructor. Always + // called by the destructor, it may also be called from elsewhere if + // needed. Only the first call is actioned; any later ones are ignored. + void Flush(); + + // An arbitrary limit on the length of a single log message. This + // is so that streaming can be done more efficiently. + static const size_t kMaxLogMessageLen; + + // Theses should not be called directly outside of logging.*, + // only passed as SendMethod arguments to other LogMessage methods: + void SendToLog(); // Actually dispatch to the logs + void SendToSyslogAndLog(); // Actually dispatch to syslog and the logs + + // Call abort() or similar to perform LOG(FATAL) crash. + static void __attribute__((noreturn)) Fail(); + + std::ostream& stream(); + + int preserved_errno() const; + + // Must be called without the log_mutex held. (L < log_mutex) + static int64 num_messages(int severity); + + struct LogMessageData; + +private: + // Fully internal SendMethod cases: + void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs + void SendToSink(); // Send to sink if provided, do nothing otherwise. + + // Write to string if provided and dispatch to the logs. + void WriteToStringAndLog(); + + void SaveOrSendToLog(); // Save to stringvec if provided, else to logs + + void Init(const char* file, int line, LogSeverity severity, + void (LogMessage::*send_method)()); + + // Used to fill in crash information during LOG(FATAL) failures. + void RecordCrashReason(glog_internal_namespace_::CrashReason* reason); + + // Counts of messages sent at each priority: + static int64 num_messages_[NUM_SEVERITIES]; // under log_mutex + + // We keep the data in a separate struct so that each instance of + // LogMessage uses less stack space. + LogMessageData* allocated_; + LogMessageData* data_; + + friend class LogDestination; + + LogMessage(const LogMessage&); + void operator=(const LogMessage&); +}; + +// This class happens to be thread-hostile because all instances share +// a single data buffer, but since it can only be created just before +// the process dies, we don't worry so much. +class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage { + public: + LogMessageFatal(const char* file, int line); + LogMessageFatal(const char* file, int line, const CheckOpString& result); + __attribute__((noreturn)) ~LogMessageFatal(); +}; + +// A non-macro interface to the log facility; (useful +// when the logging level is not a compile-time constant). +inline void LogAtLevel(int const severity, std::string const &msg) { + LogMessage(__FILE__, __LINE__, severity).stream() << msg; +} + +// A macro alternative of LogAtLevel. New code may want to use this +// version since there are two advantages: 1. this version outputs the +// file name and the line number where this macro is put like other +// LOG macros, 2. this macro can be used as C++ stream. +#define LOG_AT_LEVEL(severity) google::LogMessage(__FILE__, __LINE__, severity).stream() + +// Check if it's compiled in C++11 mode. +// +// GXX_EXPERIMENTAL_CXX0X is defined by gcc and clang up to at least +// gcc-4.7 and clang-3.1 (2011-12-13). __cplusplus was defined to 1 +// in gcc before 4.7 (Crosstool 16) and clang before 3.1, but is +// defined according to the language version in effect thereafter. +// Microsoft Visual Studio 14 (2015) sets __cplusplus==199711 despite +// reasonably good C++11 support, so we set LANG_CXX for it and +// newer versions (_MSC_VER >= 1900). +#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +// Helper for CHECK_NOTNULL(). +// +// In C++11, all cases can be handled by a single function. Since the value +// category of the argument is preserved (also for rvalue references), +// member initializer lists like the one below will compile correctly: +// +// Foo() +// : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {} +template +T CheckNotNull(const char* file, int line, const char* names, T&& t) { + if (t == nullptr) { + LogMessageFatal(file, line, new std::string(names)); + } + return std::forward(t); +} + +#else + +// A small helper for CHECK_NOTNULL(). +template +T* CheckNotNull(const char *file, int line, const char *names, T* t) { + if (t == NULL) { + LogMessageFatal(file, line, new std::string(names)); + } + return t; +} +#endif + +// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This +// only works if ostream is a LogStream. If the ostream is not a +// LogStream you'll get an assert saying as much at runtime. +GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os, + const PRIVATE_Counter&); + + +// Derived class for PLOG*() above. +class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage { + public: + + ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr, + void (LogMessage::*send_method)()); + + // Postpends ": strerror(errno) [errno]". + ~ErrnoLogMessage(); + + private: + ErrnoLogMessage(const ErrnoLogMessage&); + void operator=(const ErrnoLogMessage&); +}; + + +// This class is used to explicitly ignore values in the conditional +// logging macros. This avoids compiler warnings like "value computed +// is not used" and "statement has no effect". + +class GOOGLE_GLOG_DLL_DECL LogMessageVoidify { + public: + LogMessageVoidify() { } + // This has to be an operator with a precedence lower than << but + // higher than ?: + void operator&(std::ostream&) { } +}; + + +// Flushes all log files that contains messages that are at least of +// the specified severity level. Thread-safe. +GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity); + +// Flushes all log files that contains messages that are at least of +// the specified severity level. Thread-hostile because it ignores +// locking -- used for catastrophic failures. +GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity); + +// +// Set the destination to which a particular severity level of log +// messages is sent. If base_filename is "", it means "don't log this +// severity". Thread-safe. +// +GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity, + const char* base_filename); + +// +// Set the basename of the symlink to the latest log file at a given +// severity. If symlink_basename is empty, do not make a symlink. If +// you don't call this function, the symlink basename is the +// invocation name of the program. Thread-safe. +// +GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity, + const char* symlink_basename); + +// +// Used to send logs to some other kind of destination +// Users should subclass LogSink and override send to do whatever they want. +// Implementations must be thread-safe because a shared instance will +// be called from whichever thread ran the LOG(XXX) line. +class GOOGLE_GLOG_DLL_DECL LogSink { + public: + virtual ~LogSink(); + + // Sink's logging logic (message_len is such as to exclude '\n' at the end). + // This method can't use LOG() or CHECK() as logging system mutex(s) are held + // during this call. + virtual void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, + const struct ::tm* tm_time, + const char* message, size_t message_len) = 0; + + // Redefine this to implement waiting for + // the sink's logging logic to complete. + // It will be called after each send() returns, + // but before that LogMessage exits or crashes. + // By default this function does nothing. + // Using this function one can implement complex logic for send() + // that itself involves logging; and do all this w/o causing deadlocks and + // inconsistent rearrangement of log messages. + // E.g. if a LogSink has thread-specific actions, the send() method + // can simply add the message to a queue and wake up another thread that + // handles real logging while itself making some LOG() calls; + // WaitTillSent() can be implemented to wait for that logic to complete. + // See our unittest for an example. + virtual void WaitTillSent(); + + // Returns the normal text output of the log message. + // Can be useful to implement send(). + static std::string ToString(LogSeverity severity, const char* file, int line, + const struct ::tm* tm_time, + const char* message, size_t message_len); +}; + +// Add or remove a LogSink as a consumer of logging data. Thread-safe. +GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination); +GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination); + +// +// Specify an "extension" added to the filename specified via +// SetLogDestination. This applies to all severity levels. It's +// often used to append the port we're listening on to the logfile +// name. Thread-safe. +// +GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension( + const char* filename_extension); + +// +// Make it so that all log messages of at least a particular severity +// are logged to stderr (in addition to logging to the usual log +// file(s)). Thread-safe. +// +GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity); + +// +// Make it so that all log messages go only to stderr. Thread-safe. +// +GOOGLE_GLOG_DLL_DECL void LogToStderr(); + +// +// Make it so that all log messages of at least a particular severity are +// logged via email to a list of addresses (in addition to logging to the +// usual log file(s)). The list of addresses is just a string containing +// the email addresses to send to (separated by spaces, say). Thread-safe. +// +GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity, + const char* addresses); + +// A simple function that sends email. dest is a commma-separated +// list of addressess. Thread-safe. +GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest, + const char *subject, const char *body); + +GOOGLE_GLOG_DLL_DECL const std::vector& GetLoggingDirectories(); + +// For tests only: Clear the internal [cached] list of logging directories to +// force a refresh the next time GetLoggingDirectories is called. +// Thread-hostile. +void TestOnly_ClearLoggingDirectoriesList(); + +// Returns a set of existing temporary directories, which will be a +// subset of the directories returned by GetLogginDirectories(). +// Thread-safe. +GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories( + std::vector* list); + +// Print any fatal message again -- useful to call from signal handler +// so that the last thing in the output is the fatal message. +// Thread-hostile, but a race is unlikely. +GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage(); + +// Truncate a log file that may be the append-only output of multiple +// processes and hence can't simply be renamed/reopened (typically a +// stdout/stderr). If the file "path" is > "limit" bytes, copy the +// last "keep" bytes to offset 0 and truncate the rest. Since we could +// be racing with other writers, this approach has the potential to +// lose very small amounts of data. For security, only follow symlinks +// if the path is /proc/self/fd/* +GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path, + int64 limit, int64 keep); + +// Truncate stdout and stderr if they are over the value specified by +// --max_log_size; keep the final 1MB. This function has the same +// race condition as TruncateLogFile. +GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr(); + +// Return the string representation of the provided LogSeverity level. +// Thread-safe. +GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity); + +// --------------------------------------------------------------------- +// Implementation details that are not useful to most clients +// --------------------------------------------------------------------- + +// A Logger is the interface used by logging modules to emit entries +// to a log. A typical implementation will dump formatted data to a +// sequence of files. We also provide interfaces that will forward +// the data to another thread so that the invoker never blocks. +// Implementations should be thread-safe since the logging system +// will write to them from multiple threads. + +namespace base { + +class GOOGLE_GLOG_DLL_DECL Logger { + public: + virtual ~Logger(); + + // Writes "message[0,message_len-1]" corresponding to an event that + // occurred at "timestamp". If "force_flush" is true, the log file + // is flushed immediately. + // + // The input message has already been formatted as deemed + // appropriate by the higher level logging facility. For example, + // textual log messages already contain timestamps, and the + // file:linenumber header. + virtual void Write(bool force_flush, + time_t timestamp, + const char* message, + int message_len) = 0; + + // Flush any buffered messages + virtual void Flush() = 0; + + // Get the current LOG file size. + // The returned value is approximate since some + // logged data may not have been flushed to disk yet. + virtual uint32 LogSize() = 0; +}; + +// Get the logger for the specified severity level. The logger +// remains the property of the logging module and should not be +// deleted by the caller. Thread-safe. +extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level); + +// Set the logger for the specified severity level. The logger +// becomes the property of the logging module and should not +// be deleted by the caller. Thread-safe. +extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger); + +} + +// glibc has traditionally implemented two incompatible versions of +// strerror_r(). There is a poorly defined convention for picking the +// version that we want, but it is not clear whether it even works with +// all versions of glibc. +// So, instead, we provide this wrapper that automatically detects the +// version that is in use, and then implements POSIX semantics. +// N.B. In addition to what POSIX says, we also guarantee that "buf" will +// be set to an empty string, if this function failed. This means, in most +// cases, you do not need to check the error code and you can directly +// use the value of "buf". It will never have an undefined value. +// DEPRECATED: Use StrError(int) instead. +GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len); + +// A thread-safe replacement for strerror(). Returns a string describing the +// given POSIX error code. +GOOGLE_GLOG_DLL_DECL std::string StrError(int err); + +// A class for which we define operator<<, which does nothing. +class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream { + public: + // Initialize the LogStream so the messages can be written somewhere + // (they'll never be actually displayed). This will be needed if a + // NullStream& is implicitly converted to LogStream&, in which case + // the overloaded NullStream::operator<< will not be invoked. + NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { } + NullStream(const char* /*file*/, int /*line*/, + const CheckOpString& /*result*/) : + LogMessage::LogStream(message_buffer_, 1, 0) { } + NullStream &stream() { return *this; } + private: + // A very short buffer for messages (which we discard anyway). This + // will be needed if NullStream& converted to LogStream& (e.g. as a + // result of a conditional expression). + char message_buffer_[2]; +}; + +// Do nothing. This operator is inline, allowing the message to be +// compiled away. The message will not be compiled away if we do +// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when +// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly +// converted to LogStream and the message will be computed and then +// quietly discarded. +template +inline NullStream& operator<<(NullStream &str, const T &) { return str; } + +// Similar to NullStream, but aborts the program (without stack +// trace), like LogMessageFatal. +class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream { + public: + NullStreamFatal() { } + NullStreamFatal(const char* file, int line, const CheckOpString& result) : + NullStream(file, line, result) { } + __attribute__((noreturn)) ~NullStreamFatal() throw () { _exit(1); } +}; + +// Install a signal handler that will dump signal information and a stack +// trace when the program crashes on certain signals. We'll install the +// signal handler for the following signals. +// +// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM. +// +// By default, the signal handler will write the failure dump to the +// standard error. You can customize the destination by installing your +// own writer function by InstallFailureWriter() below. +// +// Note on threading: +// +// The function should be called before threads are created, if you want +// to use the failure signal handler for all threads. The stack trace +// will be shown only for the thread that receives the signal. In other +// words, stack traces of other threads won't be shown. +GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler(); + +// Installs a function that is used for writing the failure dump. "data" +// is the pointer to the beginning of a message to be written, and "size" +// is the size of the message. You should not expect the data is +// terminated with '\0'. +GOOGLE_GLOG_DLL_DECL void InstallFailureWriter( + void (*writer)(const char* data, int size)); + +} + +#endif // _LOGGING_H_ diff --git a/rknn_yolo_demo/libs/common/drm/include/demo.h b/rknn_yolo_demo/libs/common/drm/include/demo.h new file mode 100644 index 0000000..0aafc91 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/demo.h @@ -0,0 +1,136 @@ +/* + + */ + +#ifndef DEMO_H_ +#define DEMO_H_ +//ڴ˴ͷļ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" +#include "math.h" + +#include "demo_define.h" +#include "tool.h" +#include "inital_alg_params_ynr.h" +#include "inital_alg_params_gic.h" +#include "inital_alg_params_lsc.h" +#include "inital_alg_params_lsc2.h" +#include "inital_alg_params_rk_shapren_HW.h" +#include "inital_alg_params_rk_edgefilter.h" + +#include "initial_alg_params_bayernr.h" + +#include "inital_alg_params_rkuvnr.h" +#include "inital_alg_params_rk_cnr.h" + +#include "inital_alg_params_mfnr.h" +#include "rk_aiq_awb_algo_v200.h" +#define FILE_RAW_EXT ".raw" +#define FILE_YUV_EXT ".yuv" +#define FILE_DAT_EXT ".dat" + +typedef enum YUV_FILE_FMT +{ + F_YUV_420SP = 0x00, + F_YUV_420P = 0x01, + F_YUV_422I = 0x02, + F_YUV_422SP = 0x03, + F_YUV_422P = 0x04, + F_YUV_444I = 0x05, + + F_YUV_MAX = 0x10, +}YUV_FILE_FMT_t; + +typedef enum INPUT_FILE_FMT +{ + F_IN_FMT_RAW = 0x00, + F_IN_FMT_YUV, + + + F_IN_FMT_MAX = 0x10, +}INPUT_FILE_FMT_t; + + + +//˴ +typedef struct tag_config_com +{ + int exp_info_en ; + int framenum ; + int rawwid ; + int rawhgt ; + int rawbit ; + int bayerfmt ; + int yuvbit ; + int yuvfmt ; +}tag_config_com; + +typedef struct tag_config_txt +{ + tag_config_com config_com; + + int framecnt ; + int iso ; + int exptime[3] ; + int expgain[3] ; + int rgain ; + int bgain ; + int grgain ; + int gbgain ; + int dGain ; + int lux ; +}tag_config_txt; + +typedef struct tag_ST_DEMO_INPUT_PARAMS +{ + int width; //rawͼ + int height; //rawͼ + int bayerPattern; //bayer patternʽ:0--BGGR,1--GBRG,2--GRBG,3--RGGB + int yuvFmt; //yuv file ʽ: YUV_FILE_FMT_t + int bitValue; //rawλ + int hdr_framenum; + float expGain[MAX_HDR_FRM_NUM]; // + float expTime[MAX_HDR_FRM_NUM]; //عʱ + int rGain; //wb rgain + int bGain; //wb bgain + int grGain; //wb grgain + int gbGain; //wb gbgain + int dGain; //wb gbgain + int fileFmt; //input file format:INPUT_FILE_FMT_t + int width_full; //rawͼ + int height_full; //rawͼ + int crop_width; + int crop_height; + int crop_xoffset; + int crop_yoffset; + + char pathFileCfg[256];//configļ· + char pathRawData[256];//rawͼ· + char nameRawData[256];//rawͼ + char pathExpInfo[256];//exp_infoļ· + char pathReslut[256];//ļ· + char suffix[256]; // ļ׺ַ + char pathRtlin[256]; //rtl in path + int skip_num; + int frame_end; + + int hdr_proc_mode; + int out_mode; + + + char dbgFlg[1024]; // must > ISP_CAP_MAX + int config_full; + + int exp_info_en; + int file_info_en; + FILE *fp_exp_info; +}ST_DEMO_INPUT_PARAMS; + + + +//˴ + + + +#endif // DEMO_H_ diff --git a/rknn_yolo_demo/libs/common/drm/include/demo_define.h b/rknn_yolo_demo/libs/common/drm/include/demo_define.h new file mode 100644 index 0000000..da7d26e --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/demo_define.h @@ -0,0 +1,44 @@ +/* + + */ + +#ifndef DEFINE_H_ +#define DEFINE_H_ +//ڴ˴ͷļ + + + +#define S7_EDGE 1 +#define GZ 2 +#define DVR 3 +/* +#define ISP_BAYER_NR 1 +#define ISP_DPC 2 +#define ISP_BLC 3 +#define ISP_STAT_3A 4 +#define ISP_LSC 5 +#define ISP_AWBG 6 +#define ISP_VHDM 7 +#define ISP_GAMMA 8 +#define ISP_CSM 9 +#define ISP_DRC 10 +#define ISP_RGB2YUV 11 +#define ISP_LCE 12 +#define ISP_Y_NR 13 +#define ISP_SHARPEN 14 +#define ISP_SCALING 15 +#define ISP_GIC 16 +#define ISP_UV_NR 17 +#define ISP_HDR_MERGE 18 +#define ISP_HDR_TMO 19 +#define ISP_DPN 20 +#define ISP_CTK 21 +#define ISP_WDR 22 +*/ +#define SAVE_RESULT 1 + + +//#define GET_LSC_CALIBRATION_DATA //ȡlens shadingУ궨 + + +#endif // DEFINE_H_ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/amdgpu_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/amdgpu_drm.h new file mode 100644 index 0000000..4fe35d6 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/amdgpu_drm.h @@ -0,0 +1,1067 @@ +/* amdgpu_drm.h -- Public header for the amdgpu driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#ifndef __AMDGPU_DRM_H__ +#define __AMDGPU_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_AMDGPU_GEM_CREATE 0x00 +#define DRM_AMDGPU_GEM_MMAP 0x01 +#define DRM_AMDGPU_CTX 0x02 +#define DRM_AMDGPU_BO_LIST 0x03 +#define DRM_AMDGPU_CS 0x04 +#define DRM_AMDGPU_INFO 0x05 +#define DRM_AMDGPU_GEM_METADATA 0x06 +#define DRM_AMDGPU_GEM_WAIT_IDLE 0x07 +#define DRM_AMDGPU_GEM_VA 0x08 +#define DRM_AMDGPU_WAIT_CS 0x09 +#define DRM_AMDGPU_GEM_OP 0x10 +#define DRM_AMDGPU_GEM_USERPTR 0x11 +#define DRM_AMDGPU_WAIT_FENCES 0x12 +#define DRM_AMDGPU_VM 0x13 +#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14 +#define DRM_AMDGPU_SCHED 0x15 + +#define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) +#define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) +#define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx) +#define DRM_IOCTL_AMDGPU_BO_LIST DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_BO_LIST, union drm_amdgpu_bo_list) +#define DRM_IOCTL_AMDGPU_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CS, union drm_amdgpu_cs) +#define DRM_IOCTL_AMDGPU_INFO DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_INFO, struct drm_amdgpu_info) +#define DRM_IOCTL_AMDGPU_GEM_METADATA DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, struct drm_amdgpu_gem_metadata) +#define DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_WAIT_IDLE, union drm_amdgpu_gem_wait_idle) +#define DRM_IOCTL_AMDGPU_GEM_VA DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_VA, struct drm_amdgpu_gem_va) +#define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs) +#define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op) +#define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) +#define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences) +#define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm) +#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle) +#define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched) + +/** + * DOC: memory domains + * + * %AMDGPU_GEM_DOMAIN_CPU System memory that is not GPU accessible. + * Memory in this pool could be swapped out to disk if there is pressure. + * + * %AMDGPU_GEM_DOMAIN_GTT GPU accessible system memory, mapped into the + * GPU's virtual address space via gart. Gart memory linearizes non-contiguous + * pages of system memory, allows GPU access system memory in a linezrized + * fashion. + * + * %AMDGPU_GEM_DOMAIN_VRAM Local video memory. For APUs, it is memory + * carved out by the BIOS. + * + * %AMDGPU_GEM_DOMAIN_GDS Global on-chip data storage used to share data + * across shader threads. + * + * %AMDGPU_GEM_DOMAIN_GWS Global wave sync, used to synchronize the + * execution of all the waves on a device. + * + * %AMDGPU_GEM_DOMAIN_OA Ordered append, used by 3D or Compute engines + * for appending data. + */ +#define AMDGPU_GEM_DOMAIN_CPU 0x1 +#define AMDGPU_GEM_DOMAIN_GTT 0x2 +#define AMDGPU_GEM_DOMAIN_VRAM 0x4 +#define AMDGPU_GEM_DOMAIN_GDS 0x8 +#define AMDGPU_GEM_DOMAIN_GWS 0x10 +#define AMDGPU_GEM_DOMAIN_OA 0x20 +#define AMDGPU_GEM_DOMAIN_MASK (AMDGPU_GEM_DOMAIN_CPU | \ + AMDGPU_GEM_DOMAIN_GTT | \ + AMDGPU_GEM_DOMAIN_VRAM | \ + AMDGPU_GEM_DOMAIN_GDS | \ + AMDGPU_GEM_DOMAIN_GWS | \ + AMDGPU_GEM_DOMAIN_OA) + +/* Flag that CPU access will be required for the case of VRAM domain */ +#define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0) +/* Flag that CPU access will not work, this VRAM domain is invisible */ +#define AMDGPU_GEM_CREATE_NO_CPU_ACCESS (1 << 1) +/* Flag that USWC attributes should be used for GTT */ +#define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2) +/* Flag that the memory should be in VRAM and cleared */ +#define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3) +/* Flag that create shadow bo(GTT) while allocating vram bo */ +#define AMDGPU_GEM_CREATE_SHADOW (1 << 4) +/* Flag that allocating the BO should use linear VRAM */ +#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5) +/* Flag that BO is always valid in this VM */ +#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6) +/* Flag that BO sharing will be explicitly synchronized */ +#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7) +/* Flag that indicates allocating MQD gart on GFX9, where the mtype + * for the second page onward should be set to NC. + */ +#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8) +/* Flag that BO may contain sensitive data that must be wiped before + * releasing the memory + */ +#define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE (1 << 9) + +struct drm_amdgpu_gem_create_in { + /** the requested memory size */ + __u64 bo_size; + /** physical start_addr alignment in bytes for some HW requirements */ + __u64 alignment; + /** the requested memory domains */ + __u64 domains; + /** allocation flags */ + __u64 domain_flags; +}; + +struct drm_amdgpu_gem_create_out { + /** returned GEM object handle */ + __u32 handle; + __u32 _pad; +}; + +union drm_amdgpu_gem_create { + struct drm_amdgpu_gem_create_in in; + struct drm_amdgpu_gem_create_out out; +}; + +/** Opcode to create new residency list. */ +#define AMDGPU_BO_LIST_OP_CREATE 0 +/** Opcode to destroy previously created residency list */ +#define AMDGPU_BO_LIST_OP_DESTROY 1 +/** Opcode to update resource information in the list */ +#define AMDGPU_BO_LIST_OP_UPDATE 2 + +struct drm_amdgpu_bo_list_in { + /** Type of operation */ + __u32 operation; + /** Handle of list or 0 if we want to create one */ + __u32 list_handle; + /** Number of BOs in list */ + __u32 bo_number; + /** Size of each element describing BO */ + __u32 bo_info_size; + /** Pointer to array describing BOs */ + __u64 bo_info_ptr; +}; + +struct drm_amdgpu_bo_list_entry { + /** Handle of BO */ + __u32 bo_handle; + /** New (if specified) BO priority to be used during migration */ + __u32 bo_priority; +}; + +struct drm_amdgpu_bo_list_out { + /** Handle of resource list */ + __u32 list_handle; + __u32 _pad; +}; + +union drm_amdgpu_bo_list { + struct drm_amdgpu_bo_list_in in; + struct drm_amdgpu_bo_list_out out; +}; + +/* context related */ +#define AMDGPU_CTX_OP_ALLOC_CTX 1 +#define AMDGPU_CTX_OP_FREE_CTX 2 +#define AMDGPU_CTX_OP_QUERY_STATE 3 +#define AMDGPU_CTX_OP_QUERY_STATE2 4 + +/* GPU reset status */ +#define AMDGPU_CTX_NO_RESET 0 +/* this the context caused it */ +#define AMDGPU_CTX_GUILTY_RESET 1 +/* some other context caused it */ +#define AMDGPU_CTX_INNOCENT_RESET 2 +/* unknown cause */ +#define AMDGPU_CTX_UNKNOWN_RESET 3 + +/* indicate gpu reset occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_RESET (1<<0) +/* indicate vram lost occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1) +/* indicate some job from this context once cause gpu hang */ +#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY (1<<2) +/* indicate some errors are detected by RAS */ +#define AMDGPU_CTX_QUERY2_FLAGS_RAS_CE (1<<3) +#define AMDGPU_CTX_QUERY2_FLAGS_RAS_UE (1<<4) + +/* Context priority level */ +#define AMDGPU_CTX_PRIORITY_UNSET -2048 +#define AMDGPU_CTX_PRIORITY_VERY_LOW -1023 +#define AMDGPU_CTX_PRIORITY_LOW -512 +#define AMDGPU_CTX_PRIORITY_NORMAL 0 +/* + * When used in struct drm_amdgpu_ctx_in, a priority above NORMAL requires + * CAP_SYS_NICE or DRM_MASTER +*/ +#define AMDGPU_CTX_PRIORITY_HIGH 512 +#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023 + +struct drm_amdgpu_ctx_in { + /** AMDGPU_CTX_OP_* */ + __u32 op; + /** For future use, no flags defined so far */ + __u32 flags; + __u32 ctx_id; + /** AMDGPU_CTX_PRIORITY_* */ + __s32 priority; +}; + +union drm_amdgpu_ctx_out { + struct { + __u32 ctx_id; + __u32 _pad; + } alloc; + + struct { + /** For future use, no flags defined so far */ + __u64 flags; + /** Number of resets caused by this context so far. */ + __u32 hangs; + /** Reset status since the last call of the ioctl. */ + __u32 reset_status; + } state; +}; + +union drm_amdgpu_ctx { + struct drm_amdgpu_ctx_in in; + union drm_amdgpu_ctx_out out; +}; + +/* vm ioctl */ +#define AMDGPU_VM_OP_RESERVE_VMID 1 +#define AMDGPU_VM_OP_UNRESERVE_VMID 2 + +struct drm_amdgpu_vm_in { + /** AMDGPU_VM_OP_* */ + __u32 op; + __u32 flags; +}; + +struct drm_amdgpu_vm_out { + /** For future use, no flags defined so far */ + __u64 flags; +}; + +union drm_amdgpu_vm { + struct drm_amdgpu_vm_in in; + struct drm_amdgpu_vm_out out; +}; + +/* sched ioctl */ +#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE 1 +#define AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE 2 + +struct drm_amdgpu_sched_in { + /* AMDGPU_SCHED_OP_* */ + __u32 op; + __u32 fd; + /** AMDGPU_CTX_PRIORITY_* */ + __s32 priority; + __u32 ctx_id; +}; + +union drm_amdgpu_sched { + struct drm_amdgpu_sched_in in; +}; + +/* + * This is not a reliable API and you should expect it to fail for any + * number of reasons and have fallback path that do not use userptr to + * perform any operation. + */ +#define AMDGPU_GEM_USERPTR_READONLY (1 << 0) +#define AMDGPU_GEM_USERPTR_ANONONLY (1 << 1) +#define AMDGPU_GEM_USERPTR_VALIDATE (1 << 2) +#define AMDGPU_GEM_USERPTR_REGISTER (1 << 3) + +struct drm_amdgpu_gem_userptr { + __u64 addr; + __u64 size; + /* AMDGPU_GEM_USERPTR_* */ + __u32 flags; + /* Resulting GEM handle */ + __u32 handle; +}; + +/* SI-CI-VI: */ +/* same meaning as the GB_TILE_MODE and GL_MACRO_TILE_MODE fields */ +#define AMDGPU_TILING_ARRAY_MODE_SHIFT 0 +#define AMDGPU_TILING_ARRAY_MODE_MASK 0xf +#define AMDGPU_TILING_PIPE_CONFIG_SHIFT 4 +#define AMDGPU_TILING_PIPE_CONFIG_MASK 0x1f +#define AMDGPU_TILING_TILE_SPLIT_SHIFT 9 +#define AMDGPU_TILING_TILE_SPLIT_MASK 0x7 +#define AMDGPU_TILING_MICRO_TILE_MODE_SHIFT 12 +#define AMDGPU_TILING_MICRO_TILE_MODE_MASK 0x7 +#define AMDGPU_TILING_BANK_WIDTH_SHIFT 15 +#define AMDGPU_TILING_BANK_WIDTH_MASK 0x3 +#define AMDGPU_TILING_BANK_HEIGHT_SHIFT 17 +#define AMDGPU_TILING_BANK_HEIGHT_MASK 0x3 +#define AMDGPU_TILING_MACRO_TILE_ASPECT_SHIFT 19 +#define AMDGPU_TILING_MACRO_TILE_ASPECT_MASK 0x3 +#define AMDGPU_TILING_NUM_BANKS_SHIFT 21 +#define AMDGPU_TILING_NUM_BANKS_MASK 0x3 + +/* GFX9 and later: */ +#define AMDGPU_TILING_SWIZZLE_MODE_SHIFT 0 +#define AMDGPU_TILING_SWIZZLE_MODE_MASK 0x1f +#define AMDGPU_TILING_DCC_OFFSET_256B_SHIFT 5 +#define AMDGPU_TILING_DCC_OFFSET_256B_MASK 0xFFFFFF +#define AMDGPU_TILING_DCC_PITCH_MAX_SHIFT 29 +#define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43 +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1 + +/* Set/Get helpers for tiling flags. */ +#define AMDGPU_TILING_SET(field, value) \ + (((__u64)(value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT) +#define AMDGPU_TILING_GET(value, field) \ + (((__u64)(value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK) + +#define AMDGPU_GEM_METADATA_OP_SET_METADATA 1 +#define AMDGPU_GEM_METADATA_OP_GET_METADATA 2 + +/** The same structure is shared for input/output */ +struct drm_amdgpu_gem_metadata { + /** GEM Object handle */ + __u32 handle; + /** Do we want get or set metadata */ + __u32 op; + struct { + /** For future use, no flags defined so far */ + __u64 flags; + /** family specific tiling info */ + __u64 tiling_info; + __u32 data_size_bytes; + __u32 data[64]; + } data; +}; + +struct drm_amdgpu_gem_mmap_in { + /** the GEM object handle */ + __u32 handle; + __u32 _pad; +}; + +struct drm_amdgpu_gem_mmap_out { + /** mmap offset from the vma offset manager */ + __u64 addr_ptr; +}; + +union drm_amdgpu_gem_mmap { + struct drm_amdgpu_gem_mmap_in in; + struct drm_amdgpu_gem_mmap_out out; +}; + +struct drm_amdgpu_gem_wait_idle_in { + /** GEM object handle */ + __u32 handle; + /** For future use, no flags defined so far */ + __u32 flags; + /** Absolute timeout to wait */ + __u64 timeout; +}; + +struct drm_amdgpu_gem_wait_idle_out { + /** BO status: 0 - BO is idle, 1 - BO is busy */ + __u32 status; + /** Returned current memory domain */ + __u32 domain; +}; + +union drm_amdgpu_gem_wait_idle { + struct drm_amdgpu_gem_wait_idle_in in; + struct drm_amdgpu_gem_wait_idle_out out; +}; + +struct drm_amdgpu_wait_cs_in { + /* Command submission handle + * handle equals 0 means none to wait for + * handle equals ~0ull means wait for the latest sequence number + */ + __u64 handle; + /** Absolute timeout to wait */ + __u64 timeout; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; +}; + +struct drm_amdgpu_wait_cs_out { + /** CS status: 0 - CS completed, 1 - CS still busy */ + __u64 status; +}; + +union drm_amdgpu_wait_cs { + struct drm_amdgpu_wait_cs_in in; + struct drm_amdgpu_wait_cs_out out; +}; + +struct drm_amdgpu_fence { + __u32 ctx_id; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u64 seq_no; +}; + +struct drm_amdgpu_wait_fences_in { + /** This points to uint64_t * which points to fences */ + __u64 fences; + __u32 fence_count; + __u32 wait_all; + __u64 timeout_ns; +}; + +struct drm_amdgpu_wait_fences_out { + __u32 status; + __u32 first_signaled; +}; + +union drm_amdgpu_wait_fences { + struct drm_amdgpu_wait_fences_in in; + struct drm_amdgpu_wait_fences_out out; +}; + +#define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0 +#define AMDGPU_GEM_OP_SET_PLACEMENT 1 + +/* Sets or returns a value associated with a buffer. */ +struct drm_amdgpu_gem_op { + /** GEM object handle */ + __u32 handle; + /** AMDGPU_GEM_OP_* */ + __u32 op; + /** Input or return value */ + __u64 value; +}; + +#define AMDGPU_VA_OP_MAP 1 +#define AMDGPU_VA_OP_UNMAP 2 +#define AMDGPU_VA_OP_CLEAR 3 +#define AMDGPU_VA_OP_REPLACE 4 + +/* Delay the page table update till the next CS */ +#define AMDGPU_VM_DELAY_UPDATE (1 << 0) + +/* Mapping flags */ +/* readable mapping */ +#define AMDGPU_VM_PAGE_READABLE (1 << 1) +/* writable mapping */ +#define AMDGPU_VM_PAGE_WRITEABLE (1 << 2) +/* executable mapping, new for VI */ +#define AMDGPU_VM_PAGE_EXECUTABLE (1 << 3) +/* partially resident texture */ +#define AMDGPU_VM_PAGE_PRT (1 << 4) +/* MTYPE flags use bit 5 to 8 */ +#define AMDGPU_VM_MTYPE_MASK (0xf << 5) +/* Default MTYPE. Pre-AI must use this. Recommended for newer ASICs. */ +#define AMDGPU_VM_MTYPE_DEFAULT (0 << 5) +/* Use NC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_NC (1 << 5) +/* Use WC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_WC (2 << 5) +/* Use CC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_CC (3 << 5) +/* Use UC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_UC (4 << 5) + +struct drm_amdgpu_gem_va { + /** GEM object handle */ + __u32 handle; + __u32 _pad; + /** AMDGPU_VA_OP_* */ + __u32 operation; + /** AMDGPU_VM_PAGE_* */ + __u32 flags; + /** va address to assign . Must be correctly aligned.*/ + __u64 va_address; + /** Specify offset inside of BO to assign. Must be correctly aligned.*/ + __u64 offset_in_bo; + /** Specify mapping size. Must be correctly aligned. */ + __u64 map_size; +}; + +#define AMDGPU_HW_IP_GFX 0 +#define AMDGPU_HW_IP_COMPUTE 1 +#define AMDGPU_HW_IP_DMA 2 +#define AMDGPU_HW_IP_UVD 3 +#define AMDGPU_HW_IP_VCE 4 +#define AMDGPU_HW_IP_UVD_ENC 5 +#define AMDGPU_HW_IP_VCN_DEC 6 +#define AMDGPU_HW_IP_VCN_ENC 7 +#define AMDGPU_HW_IP_VCN_JPEG 8 +#define AMDGPU_HW_IP_NUM 9 + +#define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1 + +#define AMDGPU_CHUNK_ID_IB 0x01 +#define AMDGPU_CHUNK_ID_FENCE 0x02 +#define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03 +#define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04 +#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05 +#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06 +#define AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES 0x07 +#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT 0x08 +#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL 0x09 + +struct drm_amdgpu_cs_chunk { + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; +}; + +struct drm_amdgpu_cs_in { + /** Rendering context id */ + __u32 ctx_id; + /** Handle of resource list associated with CS */ + __u32 bo_list_handle; + __u32 num_chunks; + __u32 _pad; + /** this points to __u64 * which point to cs chunks */ + __u64 chunks; +}; + +struct drm_amdgpu_cs_out { + __u64 handle; +}; + +union drm_amdgpu_cs { + struct drm_amdgpu_cs_in in; + struct drm_amdgpu_cs_out out; +}; + +/* Specify flags to be used for IB */ + +/* This IB should be submitted to CE */ +#define AMDGPU_IB_FLAG_CE (1<<0) + +/* Preamble flag, which means the IB could be dropped if no context switch */ +#define AMDGPU_IB_FLAG_PREAMBLE (1<<1) + +/* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */ +#define AMDGPU_IB_FLAG_PREEMPT (1<<2) + +/* The IB fence should do the L2 writeback but not invalidate any shader + * caches (L2/vL1/sL1/I$). */ +#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3) + +/* Set GDS_COMPUTE_MAX_WAVE_ID = DEFAULT before PACKET3_INDIRECT_BUFFER. + * This will reset wave ID counters for the IB. + */ +#define AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID (1 << 4) + +struct drm_amdgpu_cs_chunk_ib { + __u32 _pad; + /** AMDGPU_IB_FLAG_* */ + __u32 flags; + /** Virtual address to begin IB execution */ + __u64 va_start; + /** Size of submission */ + __u32 ib_bytes; + /** HW IP to submit to */ + __u32 ip_type; + /** HW IP index of the same type to submit to */ + __u32 ip_instance; + /** Ring index to submit to */ + __u32 ring; +}; + +struct drm_amdgpu_cs_chunk_dep { + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; + __u64 handle; +}; + +struct drm_amdgpu_cs_chunk_fence { + __u32 handle; + __u32 offset; +}; + +struct drm_amdgpu_cs_chunk_sem { + __u32 handle; +}; + +struct drm_amdgpu_cs_chunk_syncobj { + __u32 handle; + __u32 flags; + __u64 point; +}; + +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2 + +union drm_amdgpu_fence_to_handle { + struct { + struct drm_amdgpu_fence fence; + __u32 what; + __u32 pad; + } in; + struct { + __u32 handle; + } out; +}; + +struct drm_amdgpu_cs_chunk_data { + union { + struct drm_amdgpu_cs_chunk_ib ib_data; + struct drm_amdgpu_cs_chunk_fence fence_data; + }; +}; + +/** + * Query h/w info: Flag that this is integrated (a.h.a. fusion) GPU + * + */ +#define AMDGPU_IDS_FLAGS_FUSION 0x1 +#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 + +/* indicate if acceleration can be working */ +#define AMDGPU_INFO_ACCEL_WORKING 0x00 +/* get the crtc_id from the mode object id? */ +#define AMDGPU_INFO_CRTC_FROM_ID 0x01 +/* query hw IP info */ +#define AMDGPU_INFO_HW_IP_INFO 0x02 +/* query hw IP instance count for the specified type */ +#define AMDGPU_INFO_HW_IP_COUNT 0x03 +/* timestamp for GL_ARB_timer_query */ +#define AMDGPU_INFO_TIMESTAMP 0x05 +/* Query the firmware version */ +#define AMDGPU_INFO_FW_VERSION 0x0e + /* Subquery id: Query VCE firmware version */ + #define AMDGPU_INFO_FW_VCE 0x1 + /* Subquery id: Query UVD firmware version */ + #define AMDGPU_INFO_FW_UVD 0x2 + /* Subquery id: Query GMC firmware version */ + #define AMDGPU_INFO_FW_GMC 0x03 + /* Subquery id: Query GFX ME firmware version */ + #define AMDGPU_INFO_FW_GFX_ME 0x04 + /* Subquery id: Query GFX PFP firmware version */ + #define AMDGPU_INFO_FW_GFX_PFP 0x05 + /* Subquery id: Query GFX CE firmware version */ + #define AMDGPU_INFO_FW_GFX_CE 0x06 + /* Subquery id: Query GFX RLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC 0x07 + /* Subquery id: Query GFX MEC firmware version */ + #define AMDGPU_INFO_FW_GFX_MEC 0x08 + /* Subquery id: Query SMC firmware version */ + #define AMDGPU_INFO_FW_SMC 0x0a + /* Subquery id: Query SDMA firmware version */ + #define AMDGPU_INFO_FW_SDMA 0x0b + /* Subquery id: Query PSP SOS firmware version */ + #define AMDGPU_INFO_FW_SOS 0x0c + /* Subquery id: Query PSP ASD firmware version */ + #define AMDGPU_INFO_FW_ASD 0x0d + /* Subquery id: Query VCN firmware version */ + #define AMDGPU_INFO_FW_VCN 0x0e + /* Subquery id: Query GFX RLC SRLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f + /* Subquery id: Query GFX RLC SRLG firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10 + /* Subquery id: Query GFX RLC SRLS firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11 + /* Subquery id: Query DMCU firmware version */ + #define AMDGPU_INFO_FW_DMCU 0x12 + #define AMDGPU_INFO_FW_TA 0x13 +/* number of bytes moved for TTM migration */ +#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f +/* the used VRAM size */ +#define AMDGPU_INFO_VRAM_USAGE 0x10 +/* the used GTT size */ +#define AMDGPU_INFO_GTT_USAGE 0x11 +/* Information about GDS, etc. resource configuration */ +#define AMDGPU_INFO_GDS_CONFIG 0x13 +/* Query information about VRAM and GTT domains */ +#define AMDGPU_INFO_VRAM_GTT 0x14 +/* Query information about register in MMR address space*/ +#define AMDGPU_INFO_READ_MMR_REG 0x15 +/* Query information about device: rev id, family, etc. */ +#define AMDGPU_INFO_DEV_INFO 0x16 +/* visible vram usage */ +#define AMDGPU_INFO_VIS_VRAM_USAGE 0x17 +/* number of TTM buffer evictions */ +#define AMDGPU_INFO_NUM_EVICTIONS 0x18 +/* Query memory about VRAM and GTT domains */ +#define AMDGPU_INFO_MEMORY 0x19 +/* Query vce clock table */ +#define AMDGPU_INFO_VCE_CLOCK_TABLE 0x1A +/* Query vbios related information */ +#define AMDGPU_INFO_VBIOS 0x1B + /* Subquery id: Query vbios size */ + #define AMDGPU_INFO_VBIOS_SIZE 0x1 + /* Subquery id: Query vbios image */ + #define AMDGPU_INFO_VBIOS_IMAGE 0x2 +/* Query UVD handles */ +#define AMDGPU_INFO_NUM_HANDLES 0x1C +/* Query sensor related information */ +#define AMDGPU_INFO_SENSOR 0x1D + /* Subquery id: Query GPU shader clock */ + #define AMDGPU_INFO_SENSOR_GFX_SCLK 0x1 + /* Subquery id: Query GPU memory clock */ + #define AMDGPU_INFO_SENSOR_GFX_MCLK 0x2 + /* Subquery id: Query GPU temperature */ + #define AMDGPU_INFO_SENSOR_GPU_TEMP 0x3 + /* Subquery id: Query GPU load */ + #define AMDGPU_INFO_SENSOR_GPU_LOAD 0x4 + /* Subquery id: Query average GPU power */ + #define AMDGPU_INFO_SENSOR_GPU_AVG_POWER 0x5 + /* Subquery id: Query northbridge voltage */ + #define AMDGPU_INFO_SENSOR_VDDNB 0x6 + /* Subquery id: Query graphics voltage */ + #define AMDGPU_INFO_SENSOR_VDDGFX 0x7 + /* Subquery id: Query GPU stable pstate shader clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK 0x8 + /* Subquery id: Query GPU stable pstate memory clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK 0x9 +/* Number of VRAM page faults on CPU access. */ +#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E +#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F +/* query ras mask of enabled features*/ +#define AMDGPU_INFO_RAS_ENABLED_FEATURES 0x20 + +/* RAS MASK: UMC (VRAM) */ +#define AMDGPU_INFO_RAS_ENABLED_UMC (1 << 0) +/* RAS MASK: SDMA */ +#define AMDGPU_INFO_RAS_ENABLED_SDMA (1 << 1) +/* RAS MASK: GFX */ +#define AMDGPU_INFO_RAS_ENABLED_GFX (1 << 2) +/* RAS MASK: MMHUB */ +#define AMDGPU_INFO_RAS_ENABLED_MMHUB (1 << 3) +/* RAS MASK: ATHUB */ +#define AMDGPU_INFO_RAS_ENABLED_ATHUB (1 << 4) +/* RAS MASK: PCIE */ +#define AMDGPU_INFO_RAS_ENABLED_PCIE (1 << 5) +/* RAS MASK: HDP */ +#define AMDGPU_INFO_RAS_ENABLED_HDP (1 << 6) +/* RAS MASK: XGMI */ +#define AMDGPU_INFO_RAS_ENABLED_XGMI (1 << 7) +/* RAS MASK: DF */ +#define AMDGPU_INFO_RAS_ENABLED_DF (1 << 8) +/* RAS MASK: SMN */ +#define AMDGPU_INFO_RAS_ENABLED_SMN (1 << 9) +/* RAS MASK: SEM */ +#define AMDGPU_INFO_RAS_ENABLED_SEM (1 << 10) +/* RAS MASK: MP0 */ +#define AMDGPU_INFO_RAS_ENABLED_MP0 (1 << 11) +/* RAS MASK: MP1 */ +#define AMDGPU_INFO_RAS_ENABLED_MP1 (1 << 12) +/* RAS MASK: FUSE */ +#define AMDGPU_INFO_RAS_ENABLED_FUSE (1 << 13) + +#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 +#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff +#define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8 +#define AMDGPU_INFO_MMR_SH_INDEX_MASK 0xff + +struct drm_amdgpu_query_fw { + /** AMDGPU_INFO_FW_* */ + __u32 fw_type; + /** + * Index of the IP if there are more IPs of + * the same type. + */ + __u32 ip_instance; + /** + * Index of the engine. Whether this is used depends + * on the firmware type. (e.g. MEC, SDMA) + */ + __u32 index; + __u32 _pad; +}; + +/* Input structure for the INFO ioctl */ +struct drm_amdgpu_info { + /* Where the return value will be stored */ + __u64 return_pointer; + /* The size of the return value. Just like "size" in "snprintf", + * it limits how many bytes the kernel can write. */ + __u32 return_size; + /* The query request id. */ + __u32 query; + + union { + struct { + __u32 id; + __u32 _pad; + } mode_crtc; + + struct { + /** AMDGPU_HW_IP_* */ + __u32 type; + /** + * Index of the IP if there are more IPs of the same + * type. Ignored by AMDGPU_INFO_HW_IP_COUNT. + */ + __u32 ip_instance; + } query_hw_ip; + + struct { + __u32 dword_offset; + /** number of registers to read */ + __u32 count; + __u32 instance; + /** For future use, no flags defined so far */ + __u32 flags; + } read_mmr_reg; + + struct drm_amdgpu_query_fw query_fw; + + struct { + __u32 type; + __u32 offset; + } vbios_info; + + struct { + __u32 type; + } sensor_info; + }; +}; + +struct drm_amdgpu_info_gds { + /** GDS GFX partition size */ + __u32 gds_gfx_partition_size; + /** GDS compute partition size */ + __u32 compute_partition_size; + /** total GDS memory size */ + __u32 gds_total_size; + /** GWS size per GFX partition */ + __u32 gws_per_gfx_partition; + /** GSW size per compute partition */ + __u32 gws_per_compute_partition; + /** OA size per GFX partition */ + __u32 oa_per_gfx_partition; + /** OA size per compute partition */ + __u32 oa_per_compute_partition; + __u32 _pad; +}; + +struct drm_amdgpu_info_vram_gtt { + __u64 vram_size; + __u64 vram_cpu_accessible_size; + __u64 gtt_size; +}; + +struct drm_amdgpu_heap_info { + /** max. physical memory */ + __u64 total_heap_size; + + /** Theoretical max. available memory in the given heap */ + __u64 usable_heap_size; + + /** + * Number of bytes allocated in the heap. This includes all processes + * and private allocations in the kernel. It changes when new buffers + * are allocated, freed, and moved. It cannot be larger than + * heap_size. + */ + __u64 heap_usage; + + /** + * Theoretical possible max. size of buffer which + * could be allocated in the given heap + */ + __u64 max_allocation; +}; + +struct drm_amdgpu_memory_info { + struct drm_amdgpu_heap_info vram; + struct drm_amdgpu_heap_info cpu_accessible_vram; + struct drm_amdgpu_heap_info gtt; +}; + +struct drm_amdgpu_info_firmware { + __u32 ver; + __u32 feature; +}; + +#define AMDGPU_VRAM_TYPE_UNKNOWN 0 +#define AMDGPU_VRAM_TYPE_GDDR1 1 +#define AMDGPU_VRAM_TYPE_DDR2 2 +#define AMDGPU_VRAM_TYPE_GDDR3 3 +#define AMDGPU_VRAM_TYPE_GDDR4 4 +#define AMDGPU_VRAM_TYPE_GDDR5 5 +#define AMDGPU_VRAM_TYPE_HBM 6 +#define AMDGPU_VRAM_TYPE_DDR3 7 +#define AMDGPU_VRAM_TYPE_DDR4 8 +#define AMDGPU_VRAM_TYPE_GDDR6 9 + +struct drm_amdgpu_info_device { + /** PCI Device ID */ + __u32 device_id; + /** Internal chip revision: A0, A1, etc.) */ + __u32 chip_rev; + __u32 external_rev; + /** Revision id in PCI Config space */ + __u32 pci_rev; + __u32 family; + __u32 num_shader_engines; + __u32 num_shader_arrays_per_engine; + /* in KHz */ + __u32 gpu_counter_freq; + __u64 max_engine_clock; + __u64 max_memory_clock; + /* cu information */ + __u32 cu_active_number; + /* NOTE: cu_ao_mask is INVALID, DON'T use it */ + __u32 cu_ao_mask; + __u32 cu_bitmap[4][4]; + /** Render backend pipe mask. One render backend is CB+DB. */ + __u32 enabled_rb_pipes_mask; + __u32 num_rb_pipes; + __u32 num_hw_gfx_contexts; + __u32 _pad; + __u64 ids_flags; + /** Starting virtual address for UMDs. */ + __u64 virtual_address_offset; + /** The maximum virtual address */ + __u64 virtual_address_max; + /** Required alignment of virtual addresses. */ + __u32 virtual_address_alignment; + /** Page table entry - fragment size */ + __u32 pte_fragment_size; + __u32 gart_page_size; + /** constant engine ram size*/ + __u32 ce_ram_size; + /** video memory type info*/ + __u32 vram_type; + /** video memory bit width*/ + __u32 vram_bit_width; + /* vce harvesting instance */ + __u32 vce_harvest_config; + /* gfx double offchip LDS buffers */ + __u32 gc_double_offchip_lds_buf; + /* NGG Primitive Buffer */ + __u64 prim_buf_gpu_addr; + /* NGG Position Buffer */ + __u64 pos_buf_gpu_addr; + /* NGG Control Sideband */ + __u64 cntl_sb_buf_gpu_addr; + /* NGG Parameter Cache */ + __u64 param_buf_gpu_addr; + __u32 prim_buf_size; + __u32 pos_buf_size; + __u32 cntl_sb_buf_size; + __u32 param_buf_size; + /* wavefront size*/ + __u32 wave_front_size; + /* shader visible vgprs*/ + __u32 num_shader_visible_vgprs; + /* CU per shader array*/ + __u32 num_cu_per_sh; + /* number of tcc blocks*/ + __u32 num_tcc_blocks; + /* gs vgt table depth*/ + __u32 gs_vgt_table_depth; + /* gs primitive buffer depth*/ + __u32 gs_prim_buffer_depth; + /* max gs wavefront per vgt*/ + __u32 max_gs_waves_per_vgt; + __u32 _pad1; + /* always on cu bitmap */ + __u32 cu_ao_bitmap[4][4]; + /** Starting high virtual address for UMDs. */ + __u64 high_va_offset; + /** The maximum high virtual address */ + __u64 high_va_max; + /* gfx10 pa_sc_tile_steering_override */ + __u32 pa_sc_tile_steering_override; + /* disabled TCCs */ + __u64 tcc_disabled_mask; +}; + +struct drm_amdgpu_info_hw_ip { + /** Version of h/w IP */ + __u32 hw_ip_version_major; + __u32 hw_ip_version_minor; + /** Capabilities */ + __u64 capabilities_flags; + /** command buffer address start alignment*/ + __u32 ib_start_alignment; + /** command buffer size alignment*/ + __u32 ib_size_alignment; + /** Bitmask of available rings. Bit 0 means ring 0, etc. */ + __u32 available_rings; + __u32 _pad; +}; + +struct drm_amdgpu_info_num_handles { + /** Max handles as supported by firmware for UVD */ + __u32 uvd_max_handles; + /** Handles currently in use for UVD */ + __u32 uvd_used_handles; +}; + +#define AMDGPU_VCE_CLOCK_TABLE_ENTRIES 6 + +struct drm_amdgpu_info_vce_clock_table_entry { + /** System clock */ + __u32 sclk; + /** Memory clock */ + __u32 mclk; + /** VCE clock */ + __u32 eclk; + __u32 pad; +}; + +struct drm_amdgpu_info_vce_clock_table { + struct drm_amdgpu_info_vce_clock_table_entry entries[AMDGPU_VCE_CLOCK_TABLE_ENTRIES]; + __u32 num_valid_entries; + __u32 pad; +}; + +/* + * Supported GPU families + */ +#define AMDGPU_FAMILY_UNKNOWN 0 +#define AMDGPU_FAMILY_SI 110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */ +#define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */ +#define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */ +#define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */ +#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */ +#define AMDGPU_FAMILY_AI 141 /* Vega10 */ +#define AMDGPU_FAMILY_RV 142 /* Raven */ +#define AMDGPU_FAMILY_NV 143 /* Navi10 */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h new file mode 100644 index 0000000..438abde --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm.h @@ -0,0 +1,1042 @@ +/** + * \file drm.h + * Header for the Direct Rendering Manager + * + * \author Rickard E. (Rik) Faith + * + * \par Acknowledgments: + * Dec 1999, Richard Henderson , move to generic \c cmpxchg. + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_H_ +#define _DRM_H_ + +#if defined(__linux__) + +#include +#include +typedef unsigned int drm_handle_t; + +#else /* One of the BSDs */ + +#include +#include +#include +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; +typedef size_t __kernel_size_t; +typedef unsigned long drm_handle_t; + +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ +#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ +#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ +#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ + +#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ +#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) +#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) +#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) + +typedef unsigned int drm_context_t; +typedef unsigned int drm_drawable_t; +typedef unsigned int drm_magic_t; + +/** + * Cliprect. + * + * \warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well + * + * \note KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ +struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +}; + +/** + * Drawable information. + */ +struct drm_drawable_info { + unsigned int num_rects; + struct drm_clip_rect *rects; +}; + +/** + * Texture region, + */ +struct drm_tex_region { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; + unsigned int age; +}; + +/** + * Hardware lock. + * + * The lock structure is a simple cache-line aligned integer. To avoid + * processor bus contention on a multiprocessor system, there should not be any + * other data stored in the same cache line. + */ +struct drm_hw_lock { + __volatile__ unsigned int lock; /**< lock variable */ + char padding[60]; /**< Pad to cache line */ +}; + +/** + * DRM_IOCTL_VERSION ioctl argument type. + * + * \sa drmGetVersion(). + */ +struct drm_version { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + __kernel_size_t name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + __kernel_size_t date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + __kernel_size_t desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +}; + +/** + * DRM_IOCTL_GET_UNIQUE ioctl argument type. + * + * \sa drmGetBusid() and drmSetBusId(). + */ +struct drm_unique { + __kernel_size_t unique_len; /**< Length of unique */ + char *unique; /**< Unique name for driver instantiation */ +}; + +struct drm_list { + int count; /**< Length of user-space structures */ + struct drm_version *version; +}; + +struct drm_block { + int unused; +}; + +/** + * DRM_IOCTL_CONTROL ioctl argument type. + * + * \sa drmCtlInstHandler() and drmCtlUninstHandler(). + */ +struct drm_control { + enum { + DRM_ADD_COMMAND, + DRM_RM_COMMAND, + DRM_INST_HANDLER, + DRM_UNINST_HANDLER + } func; + int irq; +}; + +/** + * Type of memory to map. + */ +enum drm_map_type { + _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ + _DRM_REGISTERS = 1, /**< no caching, no core dump */ + _DRM_SHM = 2, /**< shared, cached */ + _DRM_AGP = 3, /**< AGP/GART */ + _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ + _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ +}; + +/** + * Memory mapping flags. + */ +enum drm_map_flags { + _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ + _DRM_READ_ONLY = 0x02, + _DRM_LOCKED = 0x04, /**< shared, cached, locked */ + _DRM_KERNEL = 0x08, /**< kernel requires access */ + _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ + _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ + _DRM_REMOVABLE = 0x40, /**< Removable mapping */ + _DRM_DRIVER = 0x80 /**< Managed by driver */ +}; + +struct drm_ctx_priv_map { + unsigned int ctx_id; /**< Context requesting private mapping */ + void *handle; /**< Handle of map */ +}; + +/** + * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls + * argument type. + * + * \sa drmAddMap(). + */ +struct drm_map { + unsigned long offset; /**< Requested physical address (0 for SAREA)*/ + unsigned long size; /**< Requested physical size (bytes) */ + enum drm_map_type type; /**< Type of memory to map */ + enum drm_map_flags flags; /**< Flags */ + void *handle; /**< User-space: "Handle" to pass to mmap() */ + /**< Kernel-space: kernel-virtual address */ + int mtrr; /**< MTRR slot used */ + /* Private data */ +}; + +/** + * DRM_IOCTL_GET_CLIENT ioctl argument type. + */ +struct drm_client { + int idx; /**< Which client desired? */ + int auth; /**< Is client authenticated? */ + unsigned long pid; /**< Process ID */ + unsigned long uid; /**< User ID */ + unsigned long magic; /**< Magic */ + unsigned long iocs; /**< Ioctl count */ +}; + +enum drm_stat_type { + _DRM_STAT_LOCK, + _DRM_STAT_OPENS, + _DRM_STAT_CLOSES, + _DRM_STAT_IOCTLS, + _DRM_STAT_LOCKS, + _DRM_STAT_UNLOCKS, + _DRM_STAT_VALUE, /**< Generic value */ + _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ + _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ + + _DRM_STAT_IRQ, /**< IRQ */ + _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ + _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ + _DRM_STAT_DMA, /**< DMA */ + _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ + _DRM_STAT_MISSED /**< Missed DMA opportunity */ + /* Add to the *END* of the list */ +}; + +/** + * DRM_IOCTL_GET_STATS ioctl argument type. + */ +struct drm_stats { + unsigned long count; + struct { + unsigned long value; + enum drm_stat_type type; + } data[15]; +}; + +/** + * Hardware locking flags. + */ +enum drm_lock_flags { + _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +}; + +/** + * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. + * + * \sa drmGetLock() and drmUnlock(). + */ +struct drm_lock { + int context; + enum drm_lock_flags flags; +}; + +/** + * DMA flags + * + * \warning + * These values \e must match xf86drm.h. + * + * \sa drm_dma. + */ +enum drm_dma_flags { + /* Flags for DMA buffer dispatch */ + _DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note The buffer may not yet have + * been processed by the hardware -- + * getting a hardware lock with the + * hardware quiescent will ensure + * that the buffer has been + * processed. + */ + _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + + /* Flags for DMA buffer request */ + _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ +}; + +/** + * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. + * + * \sa drmAddBufs(). + */ +struct drm_buf_desc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ + enum { + _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ + _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ + _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ + _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ + } flags; + unsigned long agp_start; /**< + * Start address of where the AGP buffers are + * in the AGP aperture + */ +}; + +/** + * DRM_IOCTL_INFO_BUFS ioctl argument type. + */ +struct drm_buf_info { + int count; /**< Entries in list */ + struct drm_buf_desc *list; +}; + +/** + * DRM_IOCTL_FREE_BUFS ioctl argument type. + */ +struct drm_buf_free { + int count; + int *list; +}; + +/** + * Buffer information + * + * \sa drm_buf_map. + */ +struct drm_buf_pub { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + void *address; /**< Address of buffer */ +}; + +/** + * DRM_IOCTL_MAP_BUFS ioctl argument type. + */ +struct drm_buf_map { + int count; /**< Length of the buffer list */ +#ifdef __cplusplus + void *virt; +#else + void *virtual; /**< Mmap'd area in user-virtual */ +#endif + struct drm_buf_pub *list; /**< Buffer information */ +}; + +/** + * DRM_IOCTL_DMA ioctl argument type. + * + * Indices here refer to the offset into the buffer list in drm_buf_get. + * + * \sa drmDMA(). + */ +struct drm_dma { + int context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_indices; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send */ + enum drm_dma_flags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size for buffers */ + int *request_indices; /**< Buffer information */ + int *request_sizes; + int granted_count; /**< Number of buffers granted */ +}; + +enum drm_ctx_flags { + _DRM_CONTEXT_PRESERVED = 0x01, + _DRM_CONTEXT_2DONLY = 0x02 +}; + +/** + * DRM_IOCTL_ADD_CTX ioctl argument type. + * + * \sa drmCreateContext() and drmDestroyContext(). + */ +struct drm_ctx { + drm_context_t handle; + enum drm_ctx_flags flags; +}; + +/** + * DRM_IOCTL_RES_CTX ioctl argument type. + */ +struct drm_ctx_res { + int count; + struct drm_ctx *contexts; +}; + +/** + * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. + */ +struct drm_draw { + drm_drawable_t handle; +}; + +/** + * DRM_IOCTL_UPDATE_DRAW ioctl argument type. + */ +typedef enum { + DRM_DRAWABLE_CLIPRECTS +} drm_drawable_info_type_t; + +struct drm_update_draw { + drm_drawable_t handle; + unsigned int type; + unsigned int num; + unsigned long long data; +}; + +/** + * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. + */ +struct drm_auth { + drm_magic_t magic; +}; + +/** + * DRM_IOCTL_IRQ_BUSID ioctl argument type. + * + * \sa drmGetInterruptFromBusID(). + */ +struct drm_irq_busid { + int irq; /**< IRQ number */ + int busnum; /**< bus number */ + int devnum; /**< device number */ + int funcnum; /**< function number */ +}; + +enum drm_vblank_seq_type { + _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + _DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ +}; +#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) + +struct drm_wait_vblank_request { + enum drm_vblank_seq_type type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + enum drm_vblank_seq_type type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +/** + * DRM_IOCTL_WAIT_VBLANK ioctl argument type. + * + * \sa drmWaitVBlank(). + */ +union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +}; + +#define _DRM_PRE_MODESET 1 +#define _DRM_POST_MODESET 2 + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + __u32 crtc; + __u32 cmd; +}; + +/** + * DRM_IOCTL_AGP_ENABLE ioctl argument type. + * + * \sa drmAgpEnable(). + */ +struct drm_agp_mode { + unsigned long mode; /**< AGP mode */ +}; + +/** + * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. + * + * \sa drmAgpAlloc() and drmAgpFree(). + */ +struct drm_agp_buffer { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for binding / unbinding */ + unsigned long type; /**< Type of memory to allocate */ + unsigned long physical; /**< Physical used by i810 */ +}; + +/** + * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. + * + * \sa drmAgpBind() and drmAgpUnbind(). + */ +struct drm_agp_binding { + unsigned long handle; /**< From drm_agp_buffer */ + unsigned long offset; /**< In bytes -- will round to page boundary */ +}; + +/** + * DRM_IOCTL_AGP_INFO ioctl argument type. + * + * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), + * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), + * drmAgpVendorId() and drmAgpDeviceId(). + */ +struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +}; + +/** + * DRM_IOCTL_SG_ALLOC ioctl argument type. + */ +struct drm_scatter_gather { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for mapping / unmapping */ +}; + +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +}; + +/** DRM_IOCTL_GEM_CLOSE ioctl argument type */ +struct drm_gem_close { + /** Handle of the object to be closed. */ + __u32 handle; + __u32 pad; +}; + +/** DRM_IOCTL_GEM_FLINK ioctl argument type */ +struct drm_gem_flink { + /** Handle for the object being named */ + __u32 handle; + + /** Returned global name */ + __u32 name; +}; + +/** DRM_IOCTL_GEM_OPEN ioctl argument type */ +struct drm_gem_open { + /** Name of object being opened */ + __u32 name; + + /** Returned handle for the object */ + __u32 handle; + + /** Returned size of the object */ + __u64 size; +}; + +#define DRM_CAP_DUMB_BUFFER 0x1 +#define DRM_CAP_VBLANK_HIGH_CRTC 0x2 +#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 +#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 +#define DRM_CAP_PRIME 0x5 +#define DRM_PRIME_CAP_IMPORT 0x1 +#define DRM_PRIME_CAP_EXPORT 0x2 +#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 +#define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +/* + * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight + * combination for the hardware cursor. The intention is that a hardware + * agnostic userspace can query a cursor plane size to use. + * + * Note that the cross-driver contract is to merely return a valid size; + * drivers are free to attach another meaning on top, eg. i915 returns the + * maximum plane size. + */ +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#define DRM_CAP_ADDFB2_MODIFIERS 0x10 +#define DRM_CAP_PAGE_FLIP_TARGET 0x11 +#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 +#define DRM_CAP_SYNCOBJ 0x13 +#define DRM_CAP_SYNCOBJ_TIMELINE 0x14 + +/** DRM_IOCTL_GET_CAP ioctl argument type */ +struct drm_get_cap { + __u64 capability; + __u64 value; +}; + +/** + * DRM_CLIENT_CAP_STEREO_3D + * + * if set to 1, the DRM core will expose the stereo 3D capabilities of the + * monitor by advertising the supported 3D layouts in the flags of struct + * drm_mode_modeinfo. + */ +#define DRM_CLIENT_CAP_STEREO_3D 1 + +/** + * DRM_CLIENT_CAP_UNIVERSAL_PLANES + * + * If set to 1, the DRM core will expose all planes (overlay, primary, and + * cursor) to userspace. + */ +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 + +/** + * DRM_CLIENT_CAP_ATOMIC + * + * If set to 1, the DRM core will expose atomic properties to userspace + */ +#define DRM_CLIENT_CAP_ATOMIC 3 + +/** + * DRM_CLIENT_CAP_ASPECT_RATIO + * + * If set to 1, the DRM core will provide aspect ratio information in modes. + */ +#define DRM_CLIENT_CAP_ASPECT_RATIO 4 + +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 + +/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ +struct drm_set_client_cap { + __u64 capability; + __u64 value; +}; + +#define DRM_RDWR O_RDWR +#define DRM_CLOEXEC O_CLOEXEC +struct drm_prime_handle { + __u32 handle; + + /** Flags.. only applicable for handle->fd */ + __u32 flags; + + /** Returned dmabuf file descriptor */ + __s32 fd; +}; + +struct drm_syncobj_create { + __u32 handle; +#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) + __u32 flags; +}; + +struct drm_syncobj_destroy { + __u32 handle; + __u32 pad; +}; + +#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) +#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) +struct drm_syncobj_handle { + __u32 handle; + __u32 flags; + + __s32 fd; + __u32 pad; +}; + +struct drm_syncobj_transfer { + __u32 src_handle; + __u32 dst_handle; + __u64 src_point; + __u64 dst_point; + __u32 flags; + __u32 pad; +}; + +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ +struct drm_syncobj_wait { + __u64 handles; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + +struct drm_syncobj_timeline_wait { + __u64 handles; + /* wait on specific timeline point for every handles*/ + __u64 points; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + + +struct drm_syncobj_array { + __u64 handles; + __u32 count_handles; + __u32 pad; +}; + +struct drm_syncobj_timeline_array { + __u64 handles; + __u64 points; + __u32 count_handles; + __u32 pad; +}; + + +/* Query current scanout sequence number */ +struct drm_crtc_get_sequence { + __u32 crtc_id; /* requested crtc_id */ + __u32 active; /* return: crtc output is active */ + __u64 sequence; /* return: most recent vblank sequence */ + __s64 sequence_ns; /* return: most recent time of first pixel out */ +}; + +/* Queue event to be delivered at specified sequence. Time stamp marks + * when the first pixel of the refresh cycle leaves the display engine + * for the display + */ +#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ +#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ + +struct drm_crtc_queue_sequence { + __u32 crtc_id; + __u32 flags; + __u64 sequence; /* on input, target sequence. on output, actual sequence */ + __u64 user_data; /* user data passed to event */ +}; + +#if defined(__cplusplus) +} +#endif + +#include "drm_mode.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_IOCTL_BASE 'd' +#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) +#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) + +#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) +#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) +#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) +#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) +#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) +#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) +#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) +#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap) + +#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) +#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) +#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) +#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) +#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) +#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) +#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) +#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) +#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) +#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) +#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) + +#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) + +#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) +#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) + +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + +#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) +#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) +#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) +#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) +#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) +#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) +#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) +#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) +#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) +#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) +#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) +#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) +#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) + +#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) +#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) + +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) + +#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) +#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) + +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) + +#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) +#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) + +#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) + +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) +#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) +#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */ +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */ + +#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) +#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) +#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) +#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) + +#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) +#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) +#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) +#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) +#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) +#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) +#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) +#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) +#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) +#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) +#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) +#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) + +#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) +#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) +#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait) +#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array) +#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array) + +#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease) +#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees) +#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) +#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) + +#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) +#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array) +#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) +#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) + +/** + * Device specific ioctls should only be in their respective headers + * The device specific ioctl range is from 0x40 to 0x9f. + * Generic IOCTLS restart at 0xA0. + * + * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and + * drmCommandReadWrite(). + */ +#define DRM_COMMAND_BASE 0x40 +#define DRM_COMMAND_END 0xA0 + +/** + * Header for events written back to userspace on the drm fd. The + * type defines the type of event, the length specifies the total + * length of the event (including the header), and user_data is + * typically a 64 bit value passed with the ioctl that triggered the + * event. A read on the drm fd will always only return complete + * events, that is, if for example the read buffer is 100 bytes, and + * there are two 64 byte events pending, only one will be returned. + * + * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and + * up are chipset specific. + */ +struct drm_event { + __u32 type; + __u32 length; +}; + +#define DRM_EVENT_VBLANK 0x01 +#define DRM_EVENT_FLIP_COMPLETE 0x02 +#define DRM_EVENT_CRTC_SEQUENCE 0x03 + +struct drm_event_vblank { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 crtc_id; /* 0 on older kernels that do not support this */ +}; + +/* Event delivered at sequence. Time stamp marks when the first pixel + * of the refresh cycle leaves the display engine for the display + */ +struct drm_event_crtc_sequence { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; +}; + +/* typedef area */ +typedef struct drm_clip_rect drm_clip_rect_t; +typedef struct drm_drawable_info drm_drawable_info_t; +typedef struct drm_tex_region drm_tex_region_t; +typedef struct drm_hw_lock drm_hw_lock_t; +typedef struct drm_version drm_version_t; +typedef struct drm_unique drm_unique_t; +typedef struct drm_list drm_list_t; +typedef struct drm_block drm_block_t; +typedef struct drm_control drm_control_t; +typedef enum drm_map_type drm_map_type_t; +typedef enum drm_map_flags drm_map_flags_t; +typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; +typedef struct drm_map drm_map_t; +typedef struct drm_client drm_client_t; +typedef enum drm_stat_type drm_stat_type_t; +typedef struct drm_stats drm_stats_t; +typedef enum drm_lock_flags drm_lock_flags_t; +typedef struct drm_lock drm_lock_t; +typedef enum drm_dma_flags drm_dma_flags_t; +typedef struct drm_buf_desc drm_buf_desc_t; +typedef struct drm_buf_info drm_buf_info_t; +typedef struct drm_buf_free drm_buf_free_t; +typedef struct drm_buf_pub drm_buf_pub_t; +typedef struct drm_buf_map drm_buf_map_t; +typedef struct drm_dma drm_dma_t; +typedef union drm_wait_vblank drm_wait_vblank_t; +typedef struct drm_agp_mode drm_agp_mode_t; +typedef enum drm_ctx_flags drm_ctx_flags_t; +typedef struct drm_ctx drm_ctx_t; +typedef struct drm_ctx_res drm_ctx_res_t; +typedef struct drm_draw drm_draw_t; +typedef struct drm_update_draw drm_update_draw_t; +typedef struct drm_auth drm_auth_t; +typedef struct drm_irq_busid drm_irq_busid_t; +typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; + +typedef struct drm_agp_buffer drm_agp_buffer_t; +typedef struct drm_agp_binding drm_agp_binding_t; +typedef struct drm_agp_info drm_agp_info_t; +typedef struct drm_scatter_gather drm_scatter_gather_t; +typedef struct drm_set_version drm_set_version_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h new file mode 100644 index 0000000..5c69090 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_fourcc.h @@ -0,0 +1,763 @@ +/* + * Copyright 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DRM_FOURCC_H +#define DRM_FOURCC_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * DOC: overview + * + * In the DRM subsystem, framebuffer pixel formats are described using the + * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the + * fourcc code, a Format Modifier may optionally be provided, in order to + * further describe the buffer's format - for example tiling or compression. + * + * Format Modifiers + * ---------------- + * + * Format modifiers are used in conjunction with a fourcc code, forming a + * unique fourcc:modifier pair. This format:modifier pair must fully define the + * format and data layout of the buffer, and should be the only way to describe + * that particular buffer. + * + * Having multiple fourcc:modifier pairs which describe the same layout should + * be avoided, as such aliases run the risk of different drivers exposing + * different names for the same data format, forcing userspace to understand + * that they are aliases. + * + * Format modifiers may change any property of the buffer, including the number + * of planes and/or the required allocation size. Format modifiers are + * vendor-namespaced, and as such the relationship between a fourcc code and a + * modifier is specific to the modifer being used. For example, some modifiers + * may preserve meaning - such as number of planes - from the fourcc code, + * whereas others may not. + * + * Vendors should document their modifier usage in as much detail as + * possible, to ensure maximum compatibility across devices, drivers and + * applications. + * + * The authoritative list of format modifier codes is found in + * `include/uapi/drm/drm_fourcc.h` + */ + +#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ + ((__u32)(c) << 16) | ((__u32)(d) << 24)) + +#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ + +/* Reserve 0 for the invalid format specifier */ +#define DRM_FORMAT_INVALID 0 + +/* color index */ +#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ + +/* 8 bpp Red */ +#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ + +/* 16 bpp Red */ +#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ + +/* 16 bpp RG */ +#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */ +#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ + +/* 32 bpp RG */ +#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */ +#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ + +/* 8 bpp RGB */ +#define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ +#define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ + +/* 16 bpp RGB */ +#define DRM_FORMAT_XRGB4444 fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ +#define DRM_FORMAT_XBGR4444 fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ +#define DRM_FORMAT_RGBX4444 fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ +#define DRM_FORMAT_BGRX4444 fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ + +#define DRM_FORMAT_ARGB4444 fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ +#define DRM_FORMAT_ABGR4444 fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ +#define DRM_FORMAT_RGBA4444 fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ +#define DRM_FORMAT_BGRA4444 fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ + +#define DRM_FORMAT_XRGB1555 fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ +#define DRM_FORMAT_XBGR1555 fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ +#define DRM_FORMAT_RGBX5551 fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ +#define DRM_FORMAT_BGRX5551 fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ + +#define DRM_FORMAT_ARGB1555 fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ +#define DRM_FORMAT_ABGR1555 fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ +#define DRM_FORMAT_RGBA5551 fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ +#define DRM_FORMAT_BGRA5551 fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ + +#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ +#define DRM_FORMAT_BGR565 fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ + +/* 24 bpp RGB */ +#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ +#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ + +/* 32 bpp RGB */ +#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ +#define DRM_FORMAT_RGBX8888 fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ +#define DRM_FORMAT_BGRX8888 fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ + +#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ +#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ +#define DRM_FORMAT_BGRA8888 fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ + +#define DRM_FORMAT_XRGB2101010 fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ +#define DRM_FORMAT_XBGR2101010 fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ +#define DRM_FORMAT_RGBX1010102 fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ +#define DRM_FORMAT_BGRX1010102 fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ + +#define DRM_FORMAT_ARGB2101010 fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ +#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ +#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ +#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ + +/* + * Floating point 64bpp RGB + * IEEE 754-2008 binary16 half-precision float + * [15:0] sign:exponent:mantissa 1:5:10 + */ +#define DRM_FORMAT_XRGB16161616F fourcc_code('X', 'R', '4', 'H') /* [63:0] x:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ + +#define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H') /* [63:0] A:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ + +/* packed YCbCr */ +#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ +#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ + +#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */ +#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */ + +/* + * packed Y2xx indicate for each component, xx valid data occupy msb + * 16-xx padding occupy lsb + */ +#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels */ +#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels */ +#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels */ + +/* + * packed Y4xx indicate for each component, xx valid data occupy msb + * 16-xx padding occupy lsb except Y410 + */ +#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */ +#define DRM_FORMAT_Y412 fourcc_code('Y', '4', '1', '2') /* [63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ +#define DRM_FORMAT_Y416 fourcc_code('Y', '4', '1', '6') /* [63:0] A:Cr:Y:Cb 16:16:16:16 little endian */ + +#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */ +#define DRM_FORMAT_XVYU12_16161616 fourcc_code('X', 'V', '3', '6') /* [63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ +#define DRM_FORMAT_XVYU16161616 fourcc_code('X', 'V', '4', '8') /* [63:0] X:Cr:Y:Cb 16:16:16:16 little endian */ + +/* + * packed YCbCr420 2x2 tiled formats + * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile + */ +/* [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ +#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0') +/* [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ +#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0') + +/* [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ +#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2') +/* [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ +#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2') + +/* + * 1-plane YUV 4:2:0 + * In these formats, the component ordering is specified (Y, followed by U + * then V), but the exact Linear layout is undefined. + * These formats can only be used with a non-Linear modifier. + */ +#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8') +#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0') + +/* + * 2 plane RGB + A + * index 0 = RGB plane, same format as the corresponding non _A8 format has + * index 1 = A plane, [7:0] A + */ +#define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8') +#define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8') +#define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8') +#define DRM_FORMAT_BGRX8888_A8 fourcc_code('B', 'X', 'A', '8') +#define DRM_FORMAT_RGB888_A8 fourcc_code('R', '8', 'A', '8') +#define DRM_FORMAT_BGR888_A8 fourcc_code('B', '8', 'A', '8') +#define DRM_FORMAT_RGB565_A8 fourcc_code('R', '5', 'A', '8') +#define DRM_FORMAT_BGR565_A8 fourcc_code('B', '5', 'A', '8') + +/* + * 2 plane YCbCr + * index 0 = Y plane, [7:0] Y + * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian + * or + * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian + */ +#define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + */ +#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0') /* 2x1 subsampled Cr:Cb plane, 10 bit per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + */ +#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [12:4] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian + */ +#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane 12 bits per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y little endian + * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian + */ +#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + +/* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y + * index 1: Cb plane, [7:0] Cb + * index 2: Cr plane, [7:0] Cr + * or + * index 1: Cr plane, [7:0] Cr + * index 2: Cb plane, [7:0] Cb + */ +#define DRM_FORMAT_YUV410 fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU410 fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU411 fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV420 fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU420 fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV422 fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU422 fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ + + +/* + * Format Modifiers: + * + * Format modifiers describe, typically, a re-ordering or modification + * of the data in a plane of an FB. This can be used to express tiled/ + * swizzled formats, or compression, or a combination of the two. + * + * The upper 8 bits of the format modifier are a vendor-id as assigned + * below. The lower 56 bits are assigned as vendor sees fit. + */ + +/* Vendor Ids: */ +#define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 +#define DRM_FORMAT_MOD_VENDOR_AMD 0x02 +#define DRM_FORMAT_MOD_VENDOR_NVIDIA 0x03 +#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 +#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 +#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06 +#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 +#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 +#define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 + +/* add more to the end as needed */ + +#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) + +#define fourcc_mod_code(vendor, val) \ + ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL)) + +/* + * Format Modifier tokens: + * + * When adding a new token please document the layout with a code comment, + * similar to the fourcc codes above. drm_fourcc.h is considered the + * authoritative source for all of these. + */ + +/* + * Invalid Modifier + * + * This modifier can be used as a sentinel to terminate the format modifiers + * list, or to initialize a variable with an invalid modifier. It might also be + * used to report an error back to userspace for certain APIs. + */ +#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) + +/* + * Linear Layout + * + * Just plain linear layout. Note that this is different from no specifying any + * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl), + * which tells the driver to also take driver-internal information into account + * and so might actually result in a tiled framebuffer. + */ +#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) + +/* Intel framebuffer modifiers */ + +/* + * Intel X-tiling layout + * + * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) + * in row-major layout. Within the tile bytes are laid out row-major, with + * a platform-dependent stride. On top of that the memory can apply + * platform-depending swizzling of some higher address bits into bit6. + * + * This format is highly platforms specific and not useful for cross-driver + * sharing. It exists since on a given platform it does uniquely identify the + * layout in a simple way for i915-specific userspace. + */ +#define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1) + +/* + * Intel Y-tiling layout + * + * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) + * in row-major layout. Within the tile bytes are laid out in OWORD (16 bytes) + * chunks column-major, with a platform-dependent height. On top of that the + * memory can apply platform-depending swizzling of some higher address bits + * into bit6. + * + * This format is highly platforms specific and not useful for cross-driver + * sharing. It exists since on a given platform it does uniquely identify the + * layout in a simple way for i915-specific userspace. + */ +#define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2) + +/* + * Intel Yf-tiling layout + * + * This is a tiled layout using 4Kb tiles in row-major layout. + * Within the tile pixels are laid out in 16 256 byte units / sub-tiles which + * are arranged in four groups (two wide, two high) with column-major layout. + * Each group therefore consists out of four 256 byte units, which are also laid + * out as 2x2 column-major. + * 256 byte units are made out of four 64 byte blocks of pixels, producing + * either a square block or a 2:1 unit. + * 64 byte blocks of pixels contain four pixel rows of 16 bytes, where the width + * in pixel depends on the pixel depth. + */ +#define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3) + +/* + * Intel color control surface (CCS) for render compression + * + * The framebuffer format must be one of the 8:8:8:8 RGB formats. + * The main surface will be plane index 0 and must be Y/Yf-tiled, + * the CCS will be plane index 1. + * + * Each CCS tile matches a 1024x512 pixel area of the main surface. + * To match certain aspects of the 3D hardware the CCS is + * considered to be made up of normal 128Bx32 Y tiles, Thus + * the CCS pitch must be specified in multiples of 128 bytes. + * + * In reality the CCS tile appears to be a 64Bx64 Y tile, composed + * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks. + * But that fact is not relevant unless the memory is accessed + * directly. + */ +#define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) +#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) + +/* + * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks + * + * Macroblocks are laid in a Z-shape, and each pixel data is following the + * standard NV12 style. + * As for NV12, an image is the result of two frame buffers: one for Y, + * one for the interleaved Cb/Cr components (1/2 the height of the Y buffer). + * Alignment requirements are (for each buffer): + * - multiple of 128 pixels for the width + * - multiple of 32 pixels for the height + * + * For more information: see https://linuxtv.org/downloads/v4l-dvb-apis/re32.html + */ +#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) + +/* + * Tiled, 16 (pixels) x 16 (lines) - sized macroblocks + * + * This is a simple tiled layout using tiles of 16x16 pixels in a row-major + * layout. For YCbCr formats Cb/Cr components are taken in such a way that + * they correspond to their 16x16 luma block. + */ +#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2) + +/* + * Qualcomm Compressed Format + * + * Refers to a compressed variant of the base format that is compressed. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + +/* Vivante framebuffer modifiers */ + +/* + * Vivante 4x4 tiling layout + * + * This is a simple tiled layout using tiles of 4x4 pixels in a row-major + * layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1) + +/* + * Vivante 64x64 super-tiling layout + * + * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile + * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row- + * major layout. + * + * For more information: see + * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling + */ +#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2) + +/* + * Vivante 4x4 tiling layout for dual-pipe + * + * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a + * different base address. Offsets from the base addresses are therefore halved + * compared to the non-split tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3) + +/* + * Vivante 64x64 super-tiling layout for dual-pipe + * + * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile + * starts at a different base address. Offsets from the base addresses are + * therefore halved compared to the non-split super-tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4) + +/* NVIDIA frame buffer modifiers */ + +/* + * Tegra Tiled Layout, used by Tegra 2, 3 and 4. + * + * Pixels are arranged in simple tiles of 16 x 16 bytes. + */ +#define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1) + +/* + * 16Bx2 Block Linear layout, used by desktop GPUs, and Tegra K1 and later + * + * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked + * vertically by a power of 2 (1 to 32 GOBs) to form a block. + * + * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape. + * + * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically. + * Valid values are: + * + * 0 == ONE_GOB + * 1 == TWO_GOBS + * 2 == FOUR_GOBS + * 3 == EIGHT_GOBS + * 4 == SIXTEEN_GOBS + * 5 == THIRTYTWO_GOBS + * + * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format + * in full detail. + */ +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \ + fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf)) + +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \ + fourcc_mod_code(NVIDIA, 0x10) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \ + fourcc_mod_code(NVIDIA, 0x11) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \ + fourcc_mod_code(NVIDIA, 0x12) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \ + fourcc_mod_code(NVIDIA, 0x13) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \ + fourcc_mod_code(NVIDIA, 0x14) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ + fourcc_mod_code(NVIDIA, 0x15) + +/* + * Some Broadcom modifiers take parameters, for example the number of + * vertical lines in the image. Reserve the lower 32 bits for modifier + * type, and the next 24 bits for parameters. Top 8 bits are the + * vendor code. + */ +#define __fourcc_mod_broadcom_param_shift 8 +#define __fourcc_mod_broadcom_param_bits 48 +#define fourcc_mod_broadcom_code(val, params) \ + fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val)) +#define fourcc_mod_broadcom_param(m) \ + ((int)(((m) >> __fourcc_mod_broadcom_param_shift) & \ + ((1ULL << __fourcc_mod_broadcom_param_bits) - 1))) +#define fourcc_mod_broadcom_mod(m) \ + ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << \ + __fourcc_mod_broadcom_param_shift)) + +/* + * Broadcom VC4 "T" format + * + * This is the primary layout that the V3D GPU can texture from (it + * can't do linear). The T format has: + * + * - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4 + * pixels at 32 bit depth. + * + * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually + * 16x16 pixels). + * + * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On + * even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows + * they're (TR, BR, BL, TL), where bottom left is start of memory. + * + * - an image made of 4k tiles in rows either left-to-right (even rows of 4k + * tiles) or right-to-left (odd rows of 4k tiles). + */ +#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1) + +/* + * Broadcom SAND format + * + * This is the native format that the H.264 codec block uses. For VC4 + * HVS, it is only valid for H.264 (NV12/21) and RGBA modes. + * + * The image can be considered to be split into columns, and the + * columns are placed consecutively into memory. The width of those + * columns can be either 32, 64, 128, or 256 pixels, but in practice + * only 128 pixel columns are used. + * + * The pitch between the start of each column is set to optimally + * switch between SDRAM banks. This is passed as the number of lines + * of column width in the modifier (we can't use the stride value due + * to various core checks that look at it , so you should set the + * stride to width*cpp). + * + * Note that the column height for this format modifier is the same + * for all of the planes, assuming that each column contains both Y + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. + */ + +#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(2, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(3, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(4, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(5, v) + +#define DRM_FORMAT_MOD_BROADCOM_SAND32 \ + DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND64 \ + DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND128 \ + DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND256 \ + DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) + +/* Broadcom UIF format + * + * This is the common format for the current Broadcom multimedia + * blocks, including V3D 3.x and newer, newer video codecs, and + * displays. + * + * The image consists of utiles (64b blocks), UIF blocks (2x2 utiles), + * and macroblocks (4x4 UIF blocks). Those 4x4 UIF block groups are + * stored in columns, with padding between the columns to ensure that + * moving from one column to the next doesn't hit the same SDRAM page + * bank. + * + * To calculate the padding, it is assumed that each hardware block + * and the software driving it knows the platform's SDRAM page size, + * number of banks, and XOR address, and that it's identical between + * all blocks using the format. This tiling modifier will use XOR as + * necessary to reduce the padding. If a hardware block can't do XOR, + * the assumption is that a no-XOR tiling modifier will be created. + */ +#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) + +/* + * Arm Framebuffer Compression (AFBC) modifiers + * + * AFBC is a proprietary lossless image compression protocol and format. + * It provides fine-grained random access and minimizes the amount of data + * transferred between IP blocks. + * + * AFBC has several features which may be supported and/or used, which are + * represented using bits in the modifier. Not all combinations are valid, + * and different devices or use-cases may support different combinations. + * + * Further information on the use of AFBC modifiers can be found in + * Documentation/gpu/afbc.rst + */ +#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) + +/* + * AFBC superblock size + * + * Indicates the superblock size(s) used for the AFBC buffer. The buffer + * size (in pixels) must be aligned to a multiple of the superblock size. + * Four lowest significant bits(LSBs) are reserved for block size. + * + * Where one superblock size is specified, it applies to all planes of the + * buffer (e.g. 16x16, 32x8). When multiple superblock sizes are specified, + * the first applies to the Luma plane and the second applies to the Chroma + * plane(s). e.g. (32x8_64x4 means 32x8 Luma, with 64x4 Chroma). + * Multiple superblock sizes are only valid for multi-plane YCbCr formats. + */ +#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf +#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 (3ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 (4ULL) + +/* + * AFBC lossless colorspace transform + * + * Indicates that the buffer makes use of the AFBC lossless colorspace + * transform. + */ +#define AFBC_FORMAT_MOD_YTR (1ULL << 4) + +/* + * AFBC block-split + * + * Indicates that the payload of each superblock is split. The second + * half of the payload is positioned at a predefined offset from the start + * of the superblock payload. + */ +#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5) + +/* + * AFBC sparse layout + * + * This flag indicates that the payload of each superblock must be stored at a + * predefined position relative to the other superblocks in the same AFBC + * buffer. This order is the same order used by the header buffer. In this mode + * each superblock is given the same amount of space as an uncompressed + * superblock of the particular format would require, rounding up to the next + * multiple of 128 bytes in size. + */ +#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6) + +/* + * AFBC copy-block restrict + * + * Buffers with this flag must obey the copy-block restriction. The restriction + * is such that there are no copy-blocks referring across the border of 8x8 + * blocks. For the subsampled data the 8x8 limitation is also subsampled. + */ +#define AFBC_FORMAT_MOD_CBR (1ULL << 7) + +/* + * AFBC tiled layout + * + * The tiled layout groups superblocks in 8x8 or 4x4 tiles, where all + * superblocks inside a tile are stored together in memory. 8x8 tiles are used + * for pixel formats up to and including 32 bpp while 4x4 tiles are used for + * larger bpp formats. The order between the tiles is scan line. + * When the tiled layout is used, the buffer size (in pixels) must be aligned + * to the tile size. + */ +#define AFBC_FORMAT_MOD_TILED (1ULL << 8) + +/* + * AFBC solid color blocks + * + * Indicates that the buffer makes use of solid-color blocks, whereby bandwidth + * can be reduced if a whole superblock is a single color. + */ +#define AFBC_FORMAT_MOD_SC (1ULL << 9) + +/* + * AFBC double-buffer + * + * Indicates that the buffer is allocated in a layout safe for front-buffer + * rendering. + */ +#define AFBC_FORMAT_MOD_DB (1ULL << 10) + +/* + * AFBC buffer content hints + * + * Indicates that the buffer includes per-superblock content hints. + */ +#define AFBC_FORMAT_MOD_BCH (1ULL << 11) + +/* + * Allwinner tiled modifier + * + * This tiling mode is implemented by the VPU found on all Allwinner platforms, + * codenamed sunxi. It is associated with a YUV format that uses either 2 or 3 + * planes. + * + * With this tiling, the luminance samples are disposed in tiles representing + * 32x32 pixels and the chrominance samples in tiles representing 32x64 pixels. + * The pixel order in each tile is linear and the tiles are disposed linearly, + * both in row-major order. + */ +#define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) + +#if defined(__cplusplus) +} +#endif + +#endif /* DRM_FOURCC_H */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h new file mode 100644 index 0000000..5fe6c64 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_mode.h @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2007 Dave Airlie + * Copyright (c) 2007 Jakob Bornecrantz + * Copyright (c) 2008 Red Hat Inc. + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA + * Copyright (c) 2007-2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _DRM_MODE_H +#define _DRM_MODE_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */ +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) /* deprecated */ +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +#define DRM_MODE_TYPE_ALL (DRM_MODE_TYPE_PREFERRED | \ + DRM_MODE_TYPE_USERDEF | \ + DRM_MODE_TYPE_DRIVER) + +/* Video mode flags */ +/* bit compatible with the xrandr RR_ definitions (bits 0-13) + * + * ABI warning: Existing userspace really expects + * the mode flags to match the xrandr definitions. Any + * changes that don't match the xrandr definitions will + * likely need a new client cap or some other mechanism + * to avoid breaking existing userspace. This includes + * allocating new flags in the previously unused bits! + */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) /* deprecated */ +#define DRM_MODE_FLAG_PIXMUX (1<<11) /* deprecated */ +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) + /* + * When adding a new stereo mode don't forget to adjust DRM_MODE_FLAGS_3D_MAX + * (define not exposed to user space). + */ +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + +/* Picture aspect ratio options */ +#define DRM_MODE_PICTURE_ASPECT_NONE 0 +#define DRM_MODE_PICTURE_ASPECT_4_3 1 +#define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 + +/* Content type options */ +#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 +#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 +#define DRM_MODE_CONTENT_TYPE_PHOTO 2 +#define DRM_MODE_CONTENT_TYPE_CINEMA 3 +#define DRM_MODE_CONTENT_TYPE_GAME 4 + +/* Aspect ratio flag bitmask (4 bits 22:19) */ +#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) +#define DRM_MODE_FLAG_PIC_AR_NONE \ + (DRM_MODE_PICTURE_ASPECT_NONE<<19) +#define DRM_MODE_FLAG_PIC_AR_4_3 \ + (DRM_MODE_PICTURE_ASPECT_4_3<<19) +#define DRM_MODE_FLAG_PIC_AR_16_9 \ + (DRM_MODE_PICTURE_ASPECT_16_9<<19) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<19) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<19) + +#define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ + DRM_MODE_FLAG_NHSYNC | \ + DRM_MODE_FLAG_PVSYNC | \ + DRM_MODE_FLAG_NVSYNC | \ + DRM_MODE_FLAG_INTERLACE | \ + DRM_MODE_FLAG_DBLSCAN | \ + DRM_MODE_FLAG_CSYNC | \ + DRM_MODE_FLAG_PCSYNC | \ + DRM_MODE_FLAG_NCSYNC | \ + DRM_MODE_FLAG_HSKEW | \ + DRM_MODE_FLAG_DBLCLK | \ + DRM_MODE_FLAG_CLKDIV2 | \ + DRM_MODE_FLAG_3D_MASK) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NONE 0 /* Unmodified timing (display or + software can still scale) */ +#define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ +#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ +#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 +#define DRM_MODE_DITHERING_AUTO 2 + +/* Dirty info options */ +#define DRM_MODE_DIRTY_OFF 0 +#define DRM_MODE_DIRTY_ON 1 +#define DRM_MODE_DIRTY_ANNOTATE 2 + +/* Link Status options */ +#define DRM_MODE_LINK_STATUS_GOOD 0 +#define DRM_MODE_LINK_STATUS_BAD 1 + +/* + * DRM_MODE_ROTATE_ + * + * Signals that a drm plane is been rotated degrees in counter + * clockwise direction. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_ROTATE_0 (1<<0) +#define DRM_MODE_ROTATE_90 (1<<1) +#define DRM_MODE_ROTATE_180 (1<<2) +#define DRM_MODE_ROTATE_270 (1<<3) + +/* + * DRM_MODE_ROTATE_MASK + * + * Bitmask used to look for drm plane rotations. + */ +#define DRM_MODE_ROTATE_MASK (\ + DRM_MODE_ROTATE_0 | \ + DRM_MODE_ROTATE_90 | \ + DRM_MODE_ROTATE_180 | \ + DRM_MODE_ROTATE_270) + +/* + * DRM_MODE_REFLECT_ + * + * Signals that the contents of a drm plane is reflected along the axis, + * in the same way as mirroring. + * See kerneldoc chapter "Plane Composition Properties" for more details. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_REFLECT_X (1<<4) +#define DRM_MODE_REFLECT_Y (1<<5) + +/* + * DRM_MODE_REFLECT_MASK + * + * Bitmask used to look for drm plane reflections. + */ +#define DRM_MODE_REFLECT_MASK (\ + DRM_MODE_REFLECT_X | \ + DRM_MODE_REFLECT_Y) + +/* Content Protection Flags */ +#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED 0 +#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 +#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 + +struct drm_mode_modeinfo { + __u32 clock; + __u16 hdisplay; + __u16 hsync_start; + __u16 hsync_end; + __u16 htotal; + __u16 hskew; + __u16 vdisplay; + __u16 vsync_start; + __u16 vsync_end; + __u16 vtotal; + __u16 vscan; + + __u32 vrefresh; + + __u32 flags; + __u32 type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + __u64 fb_id_ptr; + __u64 crtc_id_ptr; + __u64 connector_id_ptr; + __u64 encoder_id_ptr; + __u32 count_fbs; + __u32 count_crtcs; + __u32 count_connectors; + __u32 count_encoders; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; +}; + +struct drm_mode_crtc { + __u64 set_connectors_ptr; + __u32 count_connectors; + + __u32 crtc_id; /**< Id */ + __u32 fb_id; /**< Id of framebuffer */ + + __u32 x; /**< x Position on the framebuffer */ + __u32 y; /**< y Position on the framebuffer */ + + __u32 gamma_size; + __u32 mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_PRESENT_TOP_FIELD (1<<0) +#define DRM_MODE_PRESENT_BOTTOM_FIELD (1<<1) + +/* Planes blend with or override other bits on the CRTC */ +struct drm_mode_set_plane { + __u32 plane_id; + __u32 crtc_id; + __u32 fb_id; /* fb object contains surface format type */ + __u32 flags; /* see above flags */ + + /* Signed dest location allows it to be partially off screen */ + __s32 crtc_x; + __s32 crtc_y; + __u32 crtc_w; + __u32 crtc_h; + + /* Source values are 16.16 fixed point */ + __u32 src_x; + __u32 src_y; + __u32 src_h; + __u32 src_w; +}; + +struct drm_mode_get_plane { + __u32 plane_id; + + __u32 crtc_id; + __u32 fb_id; + + __u32 possible_crtcs; + __u32 gamma_size; + + __u32 count_format_types; + __u64 format_type_ptr; +}; + +struct drm_mode_get_plane_res { + __u64 plane_id_ptr; + __u32 count_planes; +}; + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 + +struct drm_mode_get_encoder { + __u32 encoder_id; + __u32 encoder_type; + + __u32 crtc_id; /**< Id of crtc */ + + __u32 possible_crtcs; + __u32 possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +enum drm_mode_subconnector { + DRM_MODE_SUBCONNECTOR_Automatic = 0, + DRM_MODE_SUBCONNECTOR_Unknown = 0, + DRM_MODE_SUBCONNECTOR_DVID = 3, + DRM_MODE_SUBCONNECTOR_DVIA = 4, + DRM_MODE_SUBCONNECTOR_Composite = 5, + DRM_MODE_SUBCONNECTOR_SVIDEO = 6, + DRM_MODE_SUBCONNECTOR_Component = 8, + DRM_MODE_SUBCONNECTOR_SCART = 9, +}; + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 +#define DRM_MODE_CONNECTOR_WRITEBACK 18 + +struct drm_mode_get_connector { + + __u64 encoders_ptr; + __u64 modes_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + + __u32 count_modes; + __u32 count_props; + __u32 count_encoders; + + __u32 encoder_id; /**< Current Encoder */ + __u32 connector_id; /**< Id */ + __u32 connector_type; + __u32 connector_type_id; + + __u32 connection; + __u32 mm_width; /**< width in millimeters */ + __u32 mm_height; /**< height in millimeters */ + __u32 subpixel; + + __u32 pad; +}; + +#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) +#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ + +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, + * grab a chunk of the bits to use as integer type id. + */ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE(n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) + +/* the PROP_ATOMIC flag is used to hide properties from userspace that + * is not aware of atomic properties. This is mostly to work around + * older userspace (DDX drivers) that read/write each prop they find, + * without being aware that this could be triggering a lengthy modeset. + */ +#define DRM_MODE_PROP_ATOMIC 0x80000000 + +struct drm_mode_property_enum { + __u64 value; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + __u64 values_ptr; /* values and blob lengths */ + __u64 enum_blob_ptr; /* enum and blob id ptrs */ + + __u32 prop_id; + __u32 flags; + char name[DRM_PROP_NAME_LEN]; + + __u32 count_values; + /* This is only used to count enum values, not blobs. The _blobs is + * simply because of a historical reason, i.e. backwards compat. */ + __u32 count_enum_blobs; +}; + +struct drm_mode_connector_set_property { + __u64 value; + __u32 prop_id; + __u32 connector_id; +}; + +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee +#define DRM_MODE_OBJECT_ANY 0 + +struct drm_mode_obj_get_properties { + __u64 props_ptr; + __u64 prop_values_ptr; + __u32 count_props; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_obj_set_property { + __u64 value; + __u32 prop_id; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_get_blob { + __u32 blob_id; + __u32 length; + __u64 data; +}; + +struct drm_mode_fb_cmd { + __u32 fb_id; + __u32 width; + __u32 height; + __u32 pitch; + __u32 bpp; + __u32 depth; + /* driver specific handle */ + __u32 handle; +}; + +#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ +#define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[] */ + +struct drm_mode_fb_cmd2 { + __u32 fb_id; + __u32 width; + __u32 height; + __u32 pixel_format; /* fourcc code from drm_fourcc.h */ + __u32 flags; /* see above flags */ + + /* + * In case of planar formats, this ioctl allows up to 4 + * buffer objects with offsets and pitches per plane. + * The pitch and offset order is dictated by the fourcc, + * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: + * + * YUV 4:2:0 image with a plane of 8 bit Y samples + * followed by an interleaved U/V plane containing + * 8 bit 2x2 subsampled colour difference samples. + * + * So it would consist of Y as offsets[0] and UV as + * offsets[1]. Note that offsets[0] will generally + * be 0 (but this is not required). + * + * To accommodate tiled, compressed, etc formats, a + * modifier can be specified. The default value of zero + * indicates "native" format as specified by the fourcc. + * Vendor specific modifier token. Note that even though + * it looks like we have a modifier per-plane, we in fact + * do not. The modifier for each plane must be identical. + * Thus all combinations of different data layouts for + * multi plane formats must be enumerated as separate + * modifiers. + */ + __u32 handles[4]; + __u32 pitches[4]; /* pitch for each plane */ + __u32 offsets[4]; /* offset of each plane */ + __u64 modifier[4]; /* ie, tiling, compress */ +}; + +#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 +#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 +#define DRM_MODE_FB_DIRTY_FLAGS 0x03 + +#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256 + +/* + * Mark a region of a framebuffer as dirty. + * + * Some hardware does not automatically update display contents + * as a hardware or software draw to a framebuffer. This ioctl + * allows userspace to tell the kernel and the hardware what + * regions of the framebuffer have changed. + * + * The kernel or hardware is free to update more then just the + * region specified by the clip rects. The kernel or hardware + * may also delay and/or coalesce several calls to dirty into a + * single update. + * + * Userspace may annotate the updates, the annotates are a + * promise made by the caller that the change is either a copy + * of pixels or a fill of a single color in the region specified. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then + * the number of updated regions are half of num_clips given, + * where the clip rects are paired in src and dst. The width and + * height of each one of the pairs must match. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller + * promises that the region specified of the clip rects is filled + * completely with a single color as given in the color argument. + */ + +struct drm_mode_fb_dirty_cmd { + __u32 fb_id; + __u32 flags; + __u32 color; + __u32 num_clips; + __u64 clips_ptr; +}; + +struct drm_mode_mode_cmd { + __u32 connector_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 + +/* + * depending on the value in flags different members are used. + * + * CURSOR_BO uses + * crtc_id + * width + * height + * handle - if 0 turns the cursor off + * + * CURSOR_MOVE uses + * crtc_id + * x + * y + */ +struct drm_mode_cursor { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; +}; + +struct drm_mode_cursor2 { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; + __s32 hot_x; + __s32 hot_y; +}; + +struct drm_mode_crtc_lut { + __u32 crtc_id; + __u32 gamma_size; + + /* pointers to arrays */ + __u64 red; + __u64 green; + __u64 blue; +}; + +struct drm_color_ctm { + /* + * Conversion matrix in S31.32 sign-magnitude + * (not two's complement!) format. + */ + __u64 matrix[9]; +}; + +struct drm_color_lut { + /* + * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and + * 0xffff == 1.0. + */ + __u16 red; + __u16 green; + __u16 blue; + __u16 reserved; +}; + +#define DRM_MODE_PAGE_FLIP_EVENT 0x01 +#define DRM_MODE_PAGE_FLIP_ASYNC 0x02 +#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 +#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8 +#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \ + DRM_MODE_PAGE_FLIP_TARGET_RELATIVE) +#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \ + DRM_MODE_PAGE_FLIP_ASYNC | \ + DRM_MODE_PAGE_FLIP_TARGET) + +/* + * Request a page flip on the specified crtc. + * + * This ioctl will ask KMS to schedule a page flip for the specified + * crtc. Once any pending rendering targeting the specified fb (as of + * ioctl time) has completed, the crtc will be reprogrammed to display + * that fb after the next vertical refresh. The ioctl returns + * immediately, but subsequent rendering to the current fb will block + * in the execbuffer ioctl until the page flip happens. If a page + * flip is already pending as the ioctl is called, EBUSY will be + * returned. + * + * Flag DRM_MODE_PAGE_FLIP_EVENT requests that drm sends back a vblank + * event (see drm.h: struct drm_event_vblank) when the page flip is + * done. The user_data field passed in with this ioctl will be + * returned as the user_data field in the vblank event struct. + * + * Flag DRM_MODE_PAGE_FLIP_ASYNC requests that the flip happen + * 'as soon as possible', meaning that it not delay waiting for vblank. + * This may cause tearing on the screen. + * + * The reserved field must be zero. + */ + +struct drm_mode_crtc_page_flip { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 reserved; + __u64 user_data; +}; + +/* + * Request a page flip on the specified crtc. + * + * Same as struct drm_mode_crtc_page_flip, but supports new flags and + * re-purposes the reserved field: + * + * The sequence field must be zero unless either of the + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When + * the ABSOLUTE flag is specified, the sequence field denotes the absolute + * vblank sequence when the flip should take effect. When the RELATIVE + * flag is specified, the sequence field denotes the relative (to the + * current one when the ioctl is called) vblank sequence when the flip + * should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to + * make sure the vblank sequence before the target one has passed before + * calling this ioctl. The purpose of the + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify + * the target for when code dealing with a page flip runs during a + * vertical blank period. + */ + +struct drm_mode_crtc_page_flip_target { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 sequence; + __u64 user_data; +}; + +/* create a dumb scanout buffer */ +struct drm_mode_create_dumb { + __u32 height; + __u32 width; + __u32 bpp; + __u32 flags; + /* handle, pitch, size will be returned */ + __u32 handle; + __u32 pitch; + __u64 size; +}; + +/* set up for mmap of a dumb scanout buffer */ +struct drm_mode_map_dumb { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_mode_destroy_dumb { + __u32 handle; +}; + +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + +struct drm_format_modifier_blob { +#define FORMAT_BLOB_CURRENT 1 + /* Version of this blob format */ + __u32 version; + + /* Flags */ + __u32 flags; + + /* Number of fourcc formats supported */ + __u32 count_formats; + + /* Where in this blob the formats exist (in bytes) */ + __u32 formats_offset; + + /* Number of drm_format_modifiers */ + __u32 count_modifiers; + + /* Where in this blob the modifiers exist (in bytes) */ + __u32 modifiers_offset; + + /* __u32 formats[] */ + /* struct drm_format_modifier modifiers[] */ +}; + +struct drm_format_modifier { + /* Bitmask of formats in get_plane format list this info applies to. The + * offset allows a sliding window of which 64 formats (bits). + * + * Some examples: + * In today's world with < 65 formats, and formats 0, and 2 are + * supported + * 0x0000000000000005 + * ^-offset = 0, formats = 5 + * + * If the number formats grew to 128, and formats 98-102 are + * supported with the modifier: + * + * 0x0000007c00000000 0000000000000000 + * ^ + * |__offset = 64, formats = 0x7c00000000 + * + */ + __u64 formats; + __u32 offset; + __u32 pad; + + /* The modifier that applies to the >get_plane format list bitmask. */ + __u64 modifier; +}; + +/** + * Create a new 'blob' data property, copying length bytes from data pointer, + * and returning new blob ID. + */ +struct drm_mode_create_blob { + /** Pointer to data to copy. */ + __u64 data; + /** Length of data to copy. */ + __u32 length; + /** Return: new property ID. */ + __u32 blob_id; +}; + +/** + * Destroy a user-created blob property. + */ +struct drm_mode_destroy_blob { + __u32 blob_id; +}; + +/** + * Lease mode resources, creating another drm_master. + */ +struct drm_mode_create_lease { + /** Pointer to array of object ids (__u32) */ + __u64 object_ids; + /** Number of object ids */ + __u32 object_count; + /** flags for new FD (O_CLOEXEC, etc) */ + __u32 flags; + + /** Return: unique identifier for lessee. */ + __u32 lessee_id; + /** Return: file descriptor to new drm_master file */ + __u32 fd; +}; + +/** + * List lesses from a drm_master + */ +struct drm_mode_list_lessees { + /** Number of lessees. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_lessees; + __u32 pad; + + /** Pointer to lessees. + * pointer to __u64 array of lessee ids + */ + __u64 lessees_ptr; +}; + +/** + * Get leased objects + */ +struct drm_mode_get_lease { + /** Number of leased objects. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_objects; + __u32 pad; + + /** Pointer to objects. + * pointer to __u32 array of object ids + */ + __u64 objects_ptr; +}; + +/** + * Revoke lease + */ +struct drm_mode_revoke_lease { + /** Unique ID of lessee + */ + __u32 lessee_id; +}; + +/** + * struct drm_mode_rect - Two dimensional rectangle. + * @x1: Horizontal starting coordinate (inclusive). + * @y1: Vertical starting coordinate (inclusive). + * @x2: Horizontal ending coordinate (exclusive). + * @y2: Vertical ending coordinate (exclusive). + * + * With drm subsystem using struct drm_rect to manage rectangular area this + * export it to user-space. + * + * Currently used by drm_mode_atomic blob property FB_DAMAGE_CLIPS. + */ +struct drm_mode_rect { + __s32 x1; + __s32 y1; + __s32 x2; + __s32 y2; +}; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_sarea.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_sarea.h new file mode 100644 index 0000000..93025be --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/drm_sarea.h @@ -0,0 +1,92 @@ +/** + * \file drm_sarea.h + * \brief SAREA definitions + * + * \author Michel Dänzer + */ + +/* + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* SAREA area needs to be at least a page */ +#if defined(__alpha__) +#define SAREA_MAX 0x2000U +#elif defined(__mips__) +#define SAREA_MAX 0x4000U +#elif defined(__ia64__) +#define SAREA_MAX 0x10000U /* 64kB */ +#else +/* Intel 830M driver needs at least 8k SAREA */ +#define SAREA_MAX 0x2000U +#endif + +/** Maximum number of drawables in the SAREA */ +#define SAREA_MAX_DRAWABLES 256 + +#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000 + +/** SAREA drawable */ +struct drm_sarea_drawable { + unsigned int stamp; + unsigned int flags; +}; + +/** SAREA frame */ +struct drm_sarea_frame { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +}; + +/** SAREA */ +struct drm_sarea { + /** first thing is always the DRM locking structure */ + struct drm_hw_lock lock; + /** \todo Use readers/writer lock for drm_sarea::drawable_lock */ + struct drm_hw_lock drawable_lock; + struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */ + struct drm_sarea_frame frame; /**< frame */ + drm_context_t dummy_context; +}; + +typedef struct drm_sarea_drawable drm_sarea_drawable_t; +typedef struct drm_sarea_frame drm_sarea_frame_t; +typedef struct drm_sarea drm_sarea_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* _DRM_SAREA_H_ */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/i915_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/i915_drm.h new file mode 100644 index 0000000..72afd94 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/i915_drm.h @@ -0,0 +1,1915 @@ +/* + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _I915_DRM_H_ +#define _I915_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +/** + * DOC: uevents generated by i915 on it's device node + * + * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch + * event from the gpu l3 cache. Additional information supplied is ROW, + * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep + * track of these events and if a specific cache-line seems to have a + * persistent error remap it with the l3 remapping tool supplied in + * intel-gpu-tools. The value supplied with the event is always 1. + * + * I915_ERROR_UEVENT - Generated upon error detection, currently only via + * hangcheck. The error detection event is a good indicator of when things + * began to go badly. The value supplied with the event is a 1 upon error + * detection, and a 0 upon reset completion, signifying no more error + * exists. NOTE: Disabling hangcheck or reset via module parameter will + * cause the related events to not be seen. + * + * I915_RESET_UEVENT - Event is generated just before an attempt to reset the + * the GPU. The value supplied with the event is always 1. NOTE: Disable + * reset via module parameter will cause this event to not be seen. + */ +#define I915_L3_PARITY_UEVENT "L3_PARITY_ERROR" +#define I915_ERROR_UEVENT "ERROR" +#define I915_RESET_UEVENT "RESET" + +/* + * i915_user_extension: Base class for defining a chain of extensions + * + * Many interfaces need to grow over time. In most cases we can simply + * extend the struct and have userspace pass in more data. Another option, + * as demonstrated by Vulkan's approach to providing extensions for forward + * and backward compatibility, is to use a list of optional structs to + * provide those extra details. + * + * The key advantage to using an extension chain is that it allows us to + * redefine the interface more easily than an ever growing struct of + * increasing complexity, and for large parts of that interface to be + * entirely optional. The downside is more pointer chasing; chasing across + * the boundary with pointers encapsulated inside u64. + */ +struct i915_user_extension { + __u64 next_extension; + __u32 name; + __u32 flags; /* All undefined bits must be zero. */ + __u32 rsvd[4]; /* Reserved for future use; must be zero. */ +}; + +/* + * MOCS indexes used for GPU surfaces, defining the cacheability of the + * surface data and the coherency for this data wrt. CPU vs. GPU accesses. + */ +enum i915_mocs_table_index { + /* + * Not cached anywhere, coherency between CPU and GPU accesses is + * guaranteed. + */ + I915_MOCS_UNCACHED, + /* + * Cacheability and coherency controlled by the kernel automatically + * based on the DRM_I915_GEM_SET_CACHING IOCTL setting and the current + * usage of the surface (used for display scanout or not). + */ + I915_MOCS_PTE, + /* + * Cached in all GPU caches available on the platform. + * Coherency between CPU and GPU accesses to the surface is not + * guaranteed without extra synchronization. + */ + I915_MOCS_CACHED, +}; + +/* + * Different engines serve different roles, and there may be more than one + * engine serving each role. enum drm_i915_gem_engine_class provides a + * classification of the role of the engine, which may be used when requesting + * operations to be performed on a certain subset of engines, or for providing + * information about that group. + */ +enum drm_i915_gem_engine_class { + I915_ENGINE_CLASS_RENDER = 0, + I915_ENGINE_CLASS_COPY = 1, + I915_ENGINE_CLASS_VIDEO = 2, + I915_ENGINE_CLASS_VIDEO_ENHANCE = 3, + + /* should be kept compact */ + + I915_ENGINE_CLASS_INVALID = -1 +}; + +/** + * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915 + * + */ + +enum drm_i915_pmu_engine_sample { + I915_SAMPLE_BUSY = 0, + I915_SAMPLE_WAIT = 1, + I915_SAMPLE_SEMA = 2 +}; + +#define I915_PMU_SAMPLE_BITS (4) +#define I915_PMU_SAMPLE_MASK (0xf) +#define I915_PMU_SAMPLE_INSTANCE_BITS (8) +#define I915_PMU_CLASS_SHIFT \ + (I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS) + +#define __I915_PMU_ENGINE(class, instance, sample) \ + ((class) << I915_PMU_CLASS_SHIFT | \ + (instance) << I915_PMU_SAMPLE_BITS | \ + (sample)) + +#define I915_PMU_ENGINE_BUSY(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY) + +#define I915_PMU_ENGINE_WAIT(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT) + +#define I915_PMU_ENGINE_SEMA(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA) + +#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x)) + +#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0) +#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1) +#define I915_PMU_INTERRUPTS __I915_PMU_OTHER(2) +#define I915_PMU_RC6_RESIDENCY __I915_PMU_OTHER(3) + +#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY + +/* Each region is a minimum of 16k, and there are at most 255 of them. + */ +#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use + * of chars for next/prev indices */ +#define I915_LOG_MIN_TEX_REGION_SIZE 14 + +typedef struct _drm_i915_init { + enum { + I915_INIT_DMA = 0x01, + I915_CLEANUP_DMA = 0x02, + I915_RESUME_DMA = 0x03 + } func; + unsigned int mmio_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; + unsigned int chipset; +} drm_i915_init_t; + +typedef struct _drm_i915_sarea { + struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; + + int pipeA_x; + int pipeA_y; + int pipeA_w; + int pipeA_h; + int pipeB_x; + int pipeB_y; + int pipeB_w; + int pipeB_h; + + /* fill out some space for old userspace triple buffer */ + drm_handle_t unused_handle; + __u32 unused1, unused2, unused3; + + /* buffer object handles for static buffers. May change + * over the lifetime of the client. + */ + __u32 front_bo_handle; + __u32 back_bo_handle; + __u32 unused_bo_handle; + __u32 depth_bo_handle; + +} drm_i915_sarea_t; + +/* due to userspace building against these headers we need some compat here */ +#define planeA_x pipeA_x +#define planeA_y pipeA_y +#define planeA_w pipeA_w +#define planeA_h pipeA_h +#define planeB_x pipeB_x +#define planeB_y pipeB_y +#define planeB_w pipeB_w +#define planeB_h pipeB_h + +/* Flags for perf_boxes + */ +#define I915_BOX_RING_EMPTY 0x1 +#define I915_BOX_FLIP 0x2 +#define I915_BOX_WAIT 0x4 +#define I915_BOX_TEXTURE_LOAD 0x8 +#define I915_BOX_LOST_CONTEXT 0x10 + +/* + * i915 specific ioctls. + * + * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie + * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset + * against DRM_COMMAND_BASE and should be between [0x0, 0x60). + */ +#define DRM_I915_INIT 0x00 +#define DRM_I915_FLUSH 0x01 +#define DRM_I915_FLIP 0x02 +#define DRM_I915_BATCHBUFFER 0x03 +#define DRM_I915_IRQ_EMIT 0x04 +#define DRM_I915_IRQ_WAIT 0x05 +#define DRM_I915_GETPARAM 0x06 +#define DRM_I915_SETPARAM 0x07 +#define DRM_I915_ALLOC 0x08 +#define DRM_I915_FREE 0x09 +#define DRM_I915_INIT_HEAP 0x0a +#define DRM_I915_CMDBUFFER 0x0b +#define DRM_I915_DESTROY_HEAP 0x0c +#define DRM_I915_SET_VBLANK_PIPE 0x0d +#define DRM_I915_GET_VBLANK_PIPE 0x0e +#define DRM_I915_VBLANK_SWAP 0x0f +#define DRM_I915_HWS_ADDR 0x11 +#define DRM_I915_GEM_INIT 0x13 +#define DRM_I915_GEM_EXECBUFFER 0x14 +#define DRM_I915_GEM_PIN 0x15 +#define DRM_I915_GEM_UNPIN 0x16 +#define DRM_I915_GEM_BUSY 0x17 +#define DRM_I915_GEM_THROTTLE 0x18 +#define DRM_I915_GEM_ENTERVT 0x19 +#define DRM_I915_GEM_LEAVEVT 0x1a +#define DRM_I915_GEM_CREATE 0x1b +#define DRM_I915_GEM_PREAD 0x1c +#define DRM_I915_GEM_PWRITE 0x1d +#define DRM_I915_GEM_MMAP 0x1e +#define DRM_I915_GEM_SET_DOMAIN 0x1f +#define DRM_I915_GEM_SW_FINISH 0x20 +#define DRM_I915_GEM_SET_TILING 0x21 +#define DRM_I915_GEM_GET_TILING 0x22 +#define DRM_I915_GEM_GET_APERTURE 0x23 +#define DRM_I915_GEM_MMAP_GTT 0x24 +#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25 +#define DRM_I915_GEM_MADVISE 0x26 +#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 +#define DRM_I915_OVERLAY_ATTRS 0x28 +#define DRM_I915_GEM_EXECBUFFER2 0x29 +#define DRM_I915_GEM_EXECBUFFER2_WR DRM_I915_GEM_EXECBUFFER2 +#define DRM_I915_GET_SPRITE_COLORKEY 0x2a +#define DRM_I915_SET_SPRITE_COLORKEY 0x2b +#define DRM_I915_GEM_WAIT 0x2c +#define DRM_I915_GEM_CONTEXT_CREATE 0x2d +#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e +#define DRM_I915_GEM_SET_CACHING 0x2f +#define DRM_I915_GEM_GET_CACHING 0x30 +#define DRM_I915_REG_READ 0x31 +#define DRM_I915_GET_RESET_STATS 0x32 +#define DRM_I915_GEM_USERPTR 0x33 +#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 +#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 +#define DRM_I915_PERF_OPEN 0x36 +#define DRM_I915_PERF_ADD_CONFIG 0x37 +#define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_QUERY 0x39 +/* Must be kept compact -- no holes */ + +#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) +#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) +#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP) +#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) +#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) +#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) +#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) +#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t) +#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t) +#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) +#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) +#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) +#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) +#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_HWS_ADDR DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) +#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2) +#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2) +#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) +#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) +#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) +#define DRM_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHING, struct drm_i915_gem_caching) +#define DRM_IOCTL_I915_GEM_GET_CACHING DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHING, struct drm_i915_gem_caching) +#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) +#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) +#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) +#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) +#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) +#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) +#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) +#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) +#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) +#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) +#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) +#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture) +#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id) +#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) +#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) +#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) +#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext) +#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) +#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read) +#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats) +#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr) +#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) +#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) +#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) + +/* Allow drivers to submit batchbuffers directly to hardware, relying + * on the security mechanisms provided by hardware. + */ +typedef struct drm_i915_batchbuffer { + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_batchbuffer_t; + +/* As above, but pass a pointer to userspace buffer which can be + * validated by the kernel prior to sending to hardware. + */ +typedef struct _drm_i915_cmdbuffer { + char *buf; /* pointer to userspace command buffer */ + int sz; /* nr bytes in buf */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_cmdbuffer_t; + +/* Userspace can request & wait on irq's: + */ +typedef struct drm_i915_irq_emit { + int *irq_seq; +} drm_i915_irq_emit_t; + +typedef struct drm_i915_irq_wait { + int irq_seq; +} drm_i915_irq_wait_t; + +/* + * Different modes of per-process Graphics Translation Table, + * see I915_PARAM_HAS_ALIASING_PPGTT + */ +#define I915_GEM_PPGTT_NONE 0 +#define I915_GEM_PPGTT_ALIASING 1 +#define I915_GEM_PPGTT_FULL 2 + +/* Ioctl to query kernel params: + */ +#define I915_PARAM_IRQ_ACTIVE 1 +#define I915_PARAM_ALLOW_BATCHBUFFER 2 +#define I915_PARAM_LAST_DISPATCH 3 +#define I915_PARAM_CHIPSET_ID 4 +#define I915_PARAM_HAS_GEM 5 +#define I915_PARAM_NUM_FENCES_AVAIL 6 +#define I915_PARAM_HAS_OVERLAY 7 +#define I915_PARAM_HAS_PAGEFLIPPING 8 +#define I915_PARAM_HAS_EXECBUF2 9 +#define I915_PARAM_HAS_BSD 10 +#define I915_PARAM_HAS_BLT 11 +#define I915_PARAM_HAS_RELAXED_FENCING 12 +#define I915_PARAM_HAS_COHERENT_RINGS 13 +#define I915_PARAM_HAS_EXEC_CONSTANTS 14 +#define I915_PARAM_HAS_RELAXED_DELTA 15 +#define I915_PARAM_HAS_GEN7_SOL_RESET 16 +#define I915_PARAM_HAS_LLC 17 +#define I915_PARAM_HAS_ALIASING_PPGTT 18 +#define I915_PARAM_HAS_WAIT_TIMEOUT 19 +#define I915_PARAM_HAS_SEMAPHORES 20 +#define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21 +#define I915_PARAM_HAS_VEBOX 22 +#define I915_PARAM_HAS_SECURE_BATCHES 23 +#define I915_PARAM_HAS_PINNED_BATCHES 24 +#define I915_PARAM_HAS_EXEC_NO_RELOC 25 +#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26 +#define I915_PARAM_HAS_WT 27 +#define I915_PARAM_CMD_PARSER_VERSION 28 +#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29 +#define I915_PARAM_MMAP_VERSION 30 +#define I915_PARAM_HAS_BSD2 31 +#define I915_PARAM_REVISION 32 +#define I915_PARAM_SUBSLICE_TOTAL 33 +#define I915_PARAM_EU_TOTAL 34 +#define I915_PARAM_HAS_GPU_RESET 35 +#define I915_PARAM_HAS_RESOURCE_STREAMER 36 +#define I915_PARAM_HAS_EXEC_SOFTPIN 37 +#define I915_PARAM_HAS_POOLED_EU 38 +#define I915_PARAM_MIN_EU_IN_POOL 39 +#define I915_PARAM_MMAP_GTT_VERSION 40 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution + * priorities and the driver will attempt to execute batches in priority order. + * The param returns a capability bitmask, nonzero implies that the scheduler + * is enabled, with different features present according to the mask. + * + * The initial priority for each batch is supplied by the context and is + * controlled via I915_CONTEXT_PARAM_PRIORITY. + */ +#define I915_PARAM_HAS_SCHEDULER 41 +#define I915_SCHEDULER_CAP_ENABLED (1ul << 0) +#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1) +#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2) +#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3) + +#define I915_PARAM_HUC_STATUS 42 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of + * synchronisation with implicit fencing on individual objects. + * See EXEC_OBJECT_ASYNC. + */ +#define I915_PARAM_HAS_EXEC_ASYNC 43 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support - + * both being able to pass in a sync_file fd to wait upon before executing, + * and being able to return a new sync_file fd that is signaled when the + * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT. + */ +#define I915_PARAM_HAS_EXEC_FENCE 44 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture + * user specified buffers for post-mortem debugging of GPU hangs. See + * EXEC_OBJECT_CAPTURE. + */ +#define I915_PARAM_HAS_EXEC_CAPTURE 45 + +#define I915_PARAM_SLICE_MASK 46 + +/* Assuming it's uniform for each slice, this queries the mask of subslices + * per-slice for this system. + */ +#define I915_PARAM_SUBSLICE_MASK 47 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer + * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST. + */ +#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of + * drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY. + */ +#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49 + +/* + * Query whether every context (both per-file default and user created) is + * isolated (insofar as HW supports). If this parameter is not true, then + * freshly created contexts may inherit values from an existing context, + * rather than default HW values. If true, it also ensures (insofar as HW + * supports) that all state set by this context will not leak to any other + * context. + * + * As not every engine across every gen support contexts, the returned + * value reports the support of context isolation for individual engines by + * returning a bitmask of each engine class set to true if that class supports + * isolation. + */ +#define I915_PARAM_HAS_CONTEXT_ISOLATION 50 + +/* Frequency of the command streamer timestamps given by the *_TIMESTAMP + * registers. This used to be fixed per platform but from CNL onwards, this + * might vary depending on the parts. + */ +#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51 + +/* + * Once upon a time we supposed that writes through the GGTT would be + * immediately in physical memory (once flushed out of the CPU path). However, + * on a few different processors and chipsets, this is not necessarily the case + * as the writes appear to be buffered internally. Thus a read of the backing + * storage (physical memory) via a different path (with different physical tags + * to the indirect write via the GGTT) will see stale values from before + * the GGTT write. Inside the kernel, we can for the most part keep track of + * the different read/write domains in use (e.g. set-domain), but the assumption + * of coherency is baked into the ABI, hence reporting its true state in this + * parameter. + * + * Reports true when writes via mmap_gtt are immediately visible following an + * lfence to flush the WCB. + * + * Reports false when writes via mmap_gtt are indeterminately delayed in an in + * internal buffer and are _not_ immediately visible to third parties accessing + * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC + * communications channel when reporting false is strongly disadvised. + */ +#define I915_PARAM_MMAP_GTT_COHERENT 52 + +/* Must be kept compact -- no holes and well documented */ + +typedef struct drm_i915_getparam { + __s32 param; + /* + * WARNING: Using pointers instead of fixed-size u64 means we need to write + * compat32 code. Don't repeat this mistake. + */ + int *value; +} drm_i915_getparam_t; + +/* Ioctl to set kernel params: + */ +#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 +#define I915_SETPARAM_ALLOW_BATCHBUFFER 3 +#define I915_SETPARAM_NUM_USED_FENCES 4 +/* Must be kept compact -- no holes */ + +typedef struct drm_i915_setparam { + int param; + int value; +} drm_i915_setparam_t; + +/* A memory manager for regions of shared memory: + */ +#define I915_MEM_REGION_AGP 1 + +typedef struct drm_i915_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drm_i915_mem_alloc_t; + +typedef struct drm_i915_mem_free { + int region; + int region_offset; +} drm_i915_mem_free_t; + +typedef struct drm_i915_mem_init_heap { + int region; + int size; + int start; +} drm_i915_mem_init_heap_t; + +/* Allow memory manager to be torn down and re-initialized (eg on + * rotate): + */ +typedef struct drm_i915_mem_destroy_heap { + int region; +} drm_i915_mem_destroy_heap_t; + +/* Allow X server to configure which pipes to monitor for vblank signals + */ +#define DRM_I915_VBLANK_PIPE_A 1 +#define DRM_I915_VBLANK_PIPE_B 2 + +typedef struct drm_i915_vblank_pipe { + int pipe; +} drm_i915_vblank_pipe_t; + +/* Schedule buffer swap at given vertical blank: + */ +typedef struct drm_i915_vblank_swap { + drm_drawable_t drawable; + enum drm_vblank_seq_type seqtype; + unsigned int sequence; +} drm_i915_vblank_swap_t; + +typedef struct drm_i915_hws_addr { + __u64 addr; +} drm_i915_hws_addr_t; + +struct drm_i915_gem_init { + /** + * Beginning offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_start; + /** + * Ending offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_end; +}; + +struct drm_i915_gem_create { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + __u64 size; + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** + * Pointer to write the data into. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** + * Pointer to read the data from. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_mmap { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** Offset in the object to map. */ + __u64 offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + __u64 size; + /** + * Returned pointer the data was mapped at. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 addr_ptr; + + /** + * Flags for extended behaviour. + * + * Added in version 2. + */ + __u64 flags; +#define I915_MMAP_WC 0x1 +}; + +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_i915_gem_set_domain { + /** Handle for the object */ + __u32 handle; + + /** New read domains */ + __u32 read_domains; + + /** New write domain */ + __u32 write_domain; +}; + +struct drm_i915_gem_sw_finish { + /** Handle for the object */ + __u32 handle; +}; + +struct drm_i915_gem_relocation_entry { + /** + * Handle of the buffer being pointed to by this relocation entry. + * + * It's appealing to make this be an index into the mm_validate_entry + * list to refer to the buffer, but this allows the driver to create + * a relocation list for state buffers and not re-write it per + * exec using the buffer. + */ + __u32 target_handle; + + /** + * Value to be added to the offset of the target buffer to make up + * the relocation entry. + */ + __u32 delta; + + /** Offset in the buffer the relocation entry will be written into */ + __u64 offset; + + /** + * Offset value of the target buffer that the relocation entry was last + * written as. + * + * If the buffer has the same offset as last time, we can skip syncing + * and writing the relocation. This value is written back out by + * the execbuffer ioctl when the relocation is written. + */ + __u64 presumed_offset; + + /** + * Target memory domains read by this operation. + */ + __u32 read_domains; + + /** + * Target memory domains written by this operation. + * + * Note that only one domain may be written by the whole + * execbuffer operation, so that where there are conflicts, + * the application will get -EINVAL back. + */ + __u32 write_domain; +}; + +/** @{ + * Intel memory domains + * + * Most of these just align with the various caches in + * the system and are used to flush and invalidate as + * objects end up cached in different domains. + */ +/** CPU cache */ +#define I915_GEM_DOMAIN_CPU 0x00000001 +/** Render cache, used by 2D and 3D drawing */ +#define I915_GEM_DOMAIN_RENDER 0x00000002 +/** Sampler cache, used by texture engine */ +#define I915_GEM_DOMAIN_SAMPLER 0x00000004 +/** Command queue, used to load batch buffers */ +#define I915_GEM_DOMAIN_COMMAND 0x00000008 +/** Instruction cache, used by shader programs */ +#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 +/** Vertex address cache */ +#define I915_GEM_DOMAIN_VERTEX 0x00000020 +/** GTT domain - aperture and scanout */ +#define I915_GEM_DOMAIN_GTT 0x00000040 +/** WC domain - uncached access */ +#define I915_GEM_DOMAIN_WC 0x00000080 +/** @} */ + +struct drm_i915_gem_exec_object { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * Returned value of the updated offset of the object, for future + * presumed_offset writes. + */ + __u64 offset; +}; + +struct drm_i915_gem_execbuffer { + /** + * List of buffers to be validated with their relocations to be + * performend on them. + * + * This is a pointer to an array of struct drm_i915_gem_validate_entry. + * + * These buffers must be listed in an order such that all relocations + * a buffer is performing refer to buffers that have already appeared + * in the validate list. + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** This is a struct drm_clip_rect *cliprects */ + __u64 cliprects_ptr; +}; + +struct drm_i915_gem_exec_object2 { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * When the EXEC_OBJECT_PINNED flag is specified this is populated by + * the user with the GTT offset at which this object will be pinned. + * When the I915_EXEC_NO_RELOC flag is specified this must contain the + * presumed_offset of the object. + * During execbuffer2 the kernel populates it with the value of the + * current GTT offset of the object, for future presumed_offset writes. + */ + __u64 offset; + +#define EXEC_OBJECT_NEEDS_FENCE (1<<0) +#define EXEC_OBJECT_NEEDS_GTT (1<<1) +#define EXEC_OBJECT_WRITE (1<<2) +#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3) +#define EXEC_OBJECT_PINNED (1<<4) +#define EXEC_OBJECT_PAD_TO_SIZE (1<<5) +/* The kernel implicitly tracks GPU activity on all GEM objects, and + * synchronises operations with outstanding rendering. This includes + * rendering on other devices if exported via dma-buf. However, sometimes + * this tracking is too coarse and the user knows better. For example, + * if the object is split into non-overlapping ranges shared between different + * clients or engines (i.e. suballocating objects), the implicit tracking + * by kernel assumes that each operation affects the whole object rather + * than an individual range, causing needless synchronisation between clients. + * The kernel will also forgo any CPU cache flushes prior to rendering from + * the object as the client is expected to be also handling such domain + * tracking. + * + * The kernel maintains the implicit tracking in order to manage resources + * used by the GPU - this flag only disables the synchronisation prior to + * rendering with this object in this execbuf. + * + * Opting out of implicit synhronisation requires the user to do its own + * explicit tracking to avoid rendering corruption. See, for example, + * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously. + */ +#define EXEC_OBJECT_ASYNC (1<<6) +/* Request that the contents of this execobject be copied into the error + * state upon a GPU hang involving this batch for post-mortem debugging. + * These buffers are recorded in no particular order as "user" in + * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see + * if the kernel supports this flag. + */ +#define EXEC_OBJECT_CAPTURE (1<<7) +/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */ +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1) + __u64 flags; + + union { + __u64 rsvd1; + __u64 pad_to_size; + }; + __u64 rsvd2; +}; + +struct drm_i915_gem_exec_fence { + /** + * User's handle for a drm_syncobj to wait on or signal. + */ + __u32 handle; + +#define I915_EXEC_FENCE_WAIT (1<<0) +#define I915_EXEC_FENCE_SIGNAL (1<<1) +#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1)) + __u32 flags; +}; + +struct drm_i915_gem_execbuffer2 { + /** + * List of gem_exec_object2 structs + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** + * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY + * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a + * struct drm_i915_gem_exec_fence *fences. + */ + __u64 cliprects_ptr; +#define I915_EXEC_RING_MASK (0x3f) +#define I915_EXEC_DEFAULT (0<<0) +#define I915_EXEC_RENDER (1<<0) +#define I915_EXEC_BSD (2<<0) +#define I915_EXEC_BLT (3<<0) +#define I915_EXEC_VEBOX (4<<0) + +/* Used for switching the constants addressing mode on gen4+ RENDER ring. + * Gen6+ only supports relative addressing to dynamic state (default) and + * absolute addressing. + * + * These flags are ignored for the BSD and BLT rings. + */ +#define I915_EXEC_CONSTANTS_MASK (3<<6) +#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */ +#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) +#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ + __u64 flags; + __u64 rsvd1; /* now used for context info */ + __u64 rsvd2; +}; + +/** Resets the SO write offset registers for transform feedback on gen7. */ +#define I915_EXEC_GEN7_SOL_RESET (1<<8) + +/** Request a privileged ("secure") batch buffer. Note only available for + * DRM_ROOT_ONLY | DRM_MASTER processes. + */ +#define I915_EXEC_SECURE (1<<9) + +/** Inform the kernel that the batch is and will always be pinned. This + * negates the requirement for a workaround to be performed to avoid + * an incoherent CS (such as can be found on 830/845). If this flag is + * not passed, the kernel will endeavour to make sure the batch is + * coherent with the CS before execution. If this flag is passed, + * userspace assumes the responsibility for ensuring the same. + */ +#define I915_EXEC_IS_PINNED (1<<10) + +/** Provide a hint to the kernel that the command stream and auxiliary + * state buffers already holds the correct presumed addresses and so the + * relocation process may be skipped if no buffers need to be moved in + * preparation for the execbuffer. + */ +#define I915_EXEC_NO_RELOC (1<<11) + +/** Use the reloc.handle as an index into the exec object array rather + * than as the per-file handle. + */ +#define I915_EXEC_HANDLE_LUT (1<<12) + +/** Used for switching BSD rings on the platforms with two BSD rings */ +#define I915_EXEC_BSD_SHIFT (13) +#define I915_EXEC_BSD_MASK (3 << I915_EXEC_BSD_SHIFT) +/* default ping-pong mode */ +#define I915_EXEC_BSD_DEFAULT (0 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING1 (1 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING2 (2 << I915_EXEC_BSD_SHIFT) + +/** Tell the kernel that the batchbuffer is processed by + * the resource streamer. + */ +#define I915_EXEC_RESOURCE_STREAMER (1<<15) + +/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent + * a sync_file fd to wait upon (in a nonblocking manner) prior to executing + * the batch. + * + * Returns -EINVAL if the sync_file fd cannot be found. + */ +#define I915_EXEC_FENCE_IN (1<<16) + +/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd + * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given + * to the caller, and it should be close() after use. (The fd is a regular + * file descriptor and will be cleaned up on process termination. It holds + * a reference to the request, but nothing else.) + * + * The sync_file fd can be combined with other sync_file and passed either + * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip + * will only occur after this request completes), or to other devices. + * + * Using I915_EXEC_FENCE_OUT requires use of + * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written + * back to userspace. Failure to do so will cause the out-fence to always + * be reported as zero, and the real fence fd to be leaked. + */ +#define I915_EXEC_FENCE_OUT (1<<17) + +/* + * Traditionally the execbuf ioctl has only considered the final element in + * the execobject[] to be the executable batch. Often though, the client + * will known the batch object prior to construction and being able to place + * it into the execobject[] array first can simplify the relocation tracking. + * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the + * execobject[] as the * batch instead (the default is to use the last + * element). + */ +#define I915_EXEC_BATCH_FIRST (1<<18) + +/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr + * define an array of i915_gem_exec_fence structures which specify a set of + * dma fences to wait upon or signal. + */ +#define I915_EXEC_FENCE_ARRAY (1<<19) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1)) + +#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) +#define i915_execbuffer2_set_context_id(eb2, context) \ + (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK +#define i915_execbuffer2_get_context_id(eb2) \ + ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) + +struct drm_i915_gem_pin { + /** Handle of the buffer to be pinned. */ + __u32 handle; + __u32 pad; + + /** alignment required within the aperture */ + __u64 alignment; + + /** Returned GTT offset of the buffer. */ + __u64 offset; +}; + +struct drm_i915_gem_unpin { + /** Handle of the buffer to be unpinned. */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_busy { + /** Handle of the buffer to check for busy */ + __u32 handle; + + /** Return busy status + * + * A return of 0 implies that the object is idle (after + * having flushed any pending activity), and a non-zero return that + * the object is still in-flight on the GPU. (The GPU has not yet + * signaled completion for all pending requests that reference the + * object.) An object is guaranteed to become idle eventually (so + * long as no new GPU commands are executed upon it). Due to the + * asynchronous nature of the hardware, an object reported + * as busy may become idle before the ioctl is completed. + * + * Furthermore, if the object is busy, which engine is busy is only + * provided as a guide and only indirectly by reporting its class + * (there may be more than one engine in each class). There are race + * conditions which prevent the report of which engines are busy from + * being always accurate. However, the converse is not true. If the + * object is idle, the result of the ioctl, that all engines are idle, + * is accurate. + * + * The returned dword is split into two fields to indicate both + * the engine classess on which the object is being read, and the + * engine class on which it is currently being written (if any). + * + * The low word (bits 0:15) indicate if the object is being written + * to by any engine (there can only be one, as the GEM implicit + * synchronisation rules force writes to be serialised). Only the + * engine class (offset by 1, I915_ENGINE_CLASS_RENDER is reported as + * 1 not 0 etc) for the last write is reported. + * + * The high word (bits 16:31) are a bitmask of which engines classes + * are currently reading from the object. Multiple engines may be + * reading from the object simultaneously. + * + * The value of each engine class is the same as specified in the + * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e. + * I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc. + * reported as active itself. Some hardware may have parallel + * execution engines, e.g. multiple media engines, which are + * mapped to the same class identifier and so are not separately + * reported for busyness. + * + * Caveat emptor: + * Only the boolean result of this query is reliable; that is whether + * the object is idle or busy. The report of which engines are busy + * should be only used as a heuristic. + */ + __u32 busy; +}; + +/** + * I915_CACHING_NONE + * + * GPU access is not coherent with cpu caches. Default for machines without an + * LLC. + */ +#define I915_CACHING_NONE 0 +/** + * I915_CACHING_CACHED + * + * GPU access is coherent with cpu caches and furthermore the data is cached in + * last-level caches shared between cpu cores and the gpu GT. Default on + * machines with HAS_LLC. + */ +#define I915_CACHING_CACHED 1 +/** + * I915_CACHING_DISPLAY + * + * Special GPU caching mode which is coherent with the scanout engines. + * Transparently falls back to I915_CACHING_NONE on platforms where no special + * cache mode (like write-through or gfdt flushing) is available. The kernel + * automatically sets this mode when using a buffer as a scanout target. + * Userspace can manually set this mode to avoid a costly stall and clflush in + * the hotpath of drawing the first frame. + */ +#define I915_CACHING_DISPLAY 2 + +struct drm_i915_gem_caching { + /** + * Handle of the buffer to set/get the caching level of. */ + __u32 handle; + + /** + * Caching level to apply or return value + * + * bits0-15 are for generic caching control (i.e. the above defined + * values). bits16-31 are reserved for platform-specific variations + * (e.g. l3$ caching on gen7). */ + __u32 caching; +}; + +#define I915_TILING_NONE 0 +#define I915_TILING_X 1 +#define I915_TILING_Y 2 +#define I915_TILING_LAST I915_TILING_Y + +#define I915_BIT_6_SWIZZLE_NONE 0 +#define I915_BIT_6_SWIZZLE_9 1 +#define I915_BIT_6_SWIZZLE_9_10 2 +#define I915_BIT_6_SWIZZLE_9_11 3 +#define I915_BIT_6_SWIZZLE_9_10_11 4 +/* Not seen by userland */ +#define I915_BIT_6_SWIZZLE_UNKNOWN 5 +/* Seen by userland. */ +#define I915_BIT_6_SWIZZLE_9_17 6 +#define I915_BIT_6_SWIZZLE_9_10_17 7 + +struct drm_i915_gem_set_tiling { + /** Handle of the buffer to have its tiling state updated */ + __u32 handle; + + /** + * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + * + * This value is to be set on request, and will be updated by the + * kernel on successful return with the actual chosen tiling layout. + * + * The tiling mode may be demoted to I915_TILING_NONE when the system + * has bit 6 swizzling that can't be managed correctly by GEM. + * + * Buffer contents become undefined when changing tiling_mode. + */ + __u32 tiling_mode; + + /** + * Stride in bytes for the object when in I915_TILING_X or + * I915_TILING_Y. + */ + __u32 stride; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; +}; + +struct drm_i915_gem_get_tiling { + /** Handle of the buffer to get tiling state for. */ + __u32 handle; + + /** + * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + */ + __u32 tiling_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping whilst bound. + */ + __u32 phys_swizzle_mode; +}; + +struct drm_i915_gem_get_aperture { + /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ + __u64 aper_size; + + /** + * Available space in the aperture used by i915_gem_execbuffer, in + * bytes + */ + __u64 aper_available_size; +}; + +struct drm_i915_get_pipe_from_crtc_id { + /** ID of CRTC being requested **/ + __u32 crtc_id; + + /** pipe of requested CRTC **/ + __u32 pipe; +}; + +#define I915_MADV_WILLNEED 0 +#define I915_MADV_DONTNEED 1 +#define __I915_MADV_PURGED 2 /* internal state */ + +struct drm_i915_gem_madvise { + /** Handle of the buffer to change the backing store advice */ + __u32 handle; + + /* Advice: either the buffer will be needed again in the near future, + * or wont be and could be discarded under memory pressure. + */ + __u32 madv; + + /** Whether the backing store still exists. */ + __u32 retained; +}; + +/* flags */ +#define I915_OVERLAY_TYPE_MASK 0xff +#define I915_OVERLAY_YUV_PLANAR 0x01 +#define I915_OVERLAY_YUV_PACKED 0x02 +#define I915_OVERLAY_RGB 0x03 + +#define I915_OVERLAY_DEPTH_MASK 0xff00 +#define I915_OVERLAY_RGB24 0x1000 +#define I915_OVERLAY_RGB16 0x2000 +#define I915_OVERLAY_RGB15 0x3000 +#define I915_OVERLAY_YUV422 0x0100 +#define I915_OVERLAY_YUV411 0x0200 +#define I915_OVERLAY_YUV420 0x0300 +#define I915_OVERLAY_YUV410 0x0400 + +#define I915_OVERLAY_SWAP_MASK 0xff0000 +#define I915_OVERLAY_NO_SWAP 0x000000 +#define I915_OVERLAY_UV_SWAP 0x010000 +#define I915_OVERLAY_Y_SWAP 0x020000 +#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000 + +#define I915_OVERLAY_FLAGS_MASK 0xff000000 +#define I915_OVERLAY_ENABLE 0x01000000 + +struct drm_intel_overlay_put_image { + /* various flags and src format description */ + __u32 flags; + /* source picture description */ + __u32 bo_handle; + /* stride values and offsets are in bytes, buffer relative */ + __u16 stride_Y; /* stride for packed formats */ + __u16 stride_UV; + __u32 offset_Y; /* offset for packet formats */ + __u32 offset_U; + __u32 offset_V; + /* in pixels */ + __u16 src_width; + __u16 src_height; + /* to compensate the scaling factors for partially covered surfaces */ + __u16 src_scan_width; + __u16 src_scan_height; + /* output crtc description */ + __u32 crtc_id; + __u16 dst_x; + __u16 dst_y; + __u16 dst_width; + __u16 dst_height; +}; + +/* flags */ +#define I915_OVERLAY_UPDATE_ATTRS (1<<0) +#define I915_OVERLAY_UPDATE_GAMMA (1<<1) +#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2) +struct drm_intel_overlay_attrs { + __u32 flags; + __u32 color_key; + __s32 brightness; + __u32 contrast; + __u32 saturation; + __u32 gamma0; + __u32 gamma1; + __u32 gamma2; + __u32 gamma3; + __u32 gamma4; + __u32 gamma5; +}; + +/* + * Intel sprite handling + * + * Color keying works with a min/mask/max tuple. Both source and destination + * color keying is allowed. + * + * Source keying: + * Sprite pixels within the min & max values, masked against the color channels + * specified in the mask field, will be transparent. All other pixels will + * be displayed on top of the primary plane. For RGB surfaces, only the min + * and mask fields will be used; ranged compares are not allowed. + * + * Destination keying: + * Primary plane pixels that match the min value, masked against the color + * channels specified in the mask field, will be replaced by corresponding + * pixels from the sprite plane. + * + * Note that source & destination keying are exclusive; only one can be + * active on a given plane. + */ + +#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set + * flags==0 to disable colorkeying. + */ +#define I915_SET_COLORKEY_DESTINATION (1<<1) +#define I915_SET_COLORKEY_SOURCE (1<<2) +struct drm_intel_sprite_colorkey { + __u32 plane_id; + __u32 min_value; + __u32 channel_mask; + __u32 max_value; + __u32 flags; +}; + +struct drm_i915_gem_wait { + /** Handle of BO we shall wait on */ + __u32 bo_handle; + __u32 flags; + /** Number of nanoseconds to wait, Returns time remaining. */ + __s64 timeout_ns; +}; + +struct drm_i915_gem_context_create { + __u32 ctx_id; /* output: id of new context*/ + __u32 pad; +}; + +struct drm_i915_gem_context_create_ext { + __u32 ctx_id; /* output: id of new context*/ + __u32 flags; +#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0) +#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \ + (-(I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS << 1)) + __u64 extensions; +}; + +struct drm_i915_gem_context_param { + __u32 ctx_id; + __u32 size; + __u64 param; +#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1 +#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2 +#define I915_CONTEXT_PARAM_GTT_SIZE 0x3 +#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4 +#define I915_CONTEXT_PARAM_BANNABLE 0x5 +#define I915_CONTEXT_PARAM_PRIORITY 0x6 +#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */ +#define I915_CONTEXT_DEFAULT_PRIORITY 0 +#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */ + /* + * When using the following param, value should be a pointer to + * drm_i915_gem_context_param_sseu. + */ +#define I915_CONTEXT_PARAM_SSEU 0x7 + +/* + * Not all clients may want to attempt automatic recover of a context after + * a hang (for example, some clients may only submit very small incremental + * batches relying on known logical state of previous batches which will never + * recover correctly and each attempt will hang), and so would prefer that + * the context is forever banned instead. + * + * If set to false (0), after a reset, subsequent (and in flight) rendering + * from this context is discarded, and the client will need to create a new + * context to use instead. + * + * If set to true (1), the kernel will automatically attempt to recover the + * context by skipping the hanging batch and executing the next batch starting + * from the default context state (discarding the incomplete logical context + * state lost due to the reset). + * + * On creation, all new contexts are marked as recoverable. + */ +#define I915_CONTEXT_PARAM_RECOVERABLE 0x8 +/* Must be kept compact -- no holes and well documented */ + + __u64 value; +}; + +/** + * Context SSEU programming + * + * It may be necessary for either functional or performance reason to configure + * a context to run with a reduced number of SSEU (where SSEU stands for Slice/ + * Sub-slice/EU). + * + * This is done by configuring SSEU configuration using the below + * @struct drm_i915_gem_context_param_sseu for every supported engine which + * userspace intends to use. + * + * Not all GPUs or engines support this functionality in which case an error + * code -ENODEV will be returned. + * + * Also, flexibility of possible SSEU configuration permutations varies between + * GPU generations and software imposed limitations. Requesting such a + * combination will return an error code of -EINVAL. + * + * NOTE: When perf/OA is active the context's SSEU configuration is ignored in + * favour of a single global setting. + */ +struct drm_i915_gem_context_param_sseu { + /* + * Engine class & instance to be configured or queried. + */ + __u16 engine_class; + __u16 engine_instance; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Mask of slices to enable for the context. Valid values are a subset + * of the bitmask value returned for I915_PARAM_SLICE_MASK. + */ + __u64 slice_mask; + + /* + * Mask of subslices to enable for the context. Valid values are a + * subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK. + */ + __u64 subslice_mask; + + /* + * Minimum/Maximum number of EUs to enable per subslice for the + * context. min_eus_per_subslice must be inferior or equal to + * max_eus_per_subslice. + */ + __u16 min_eus_per_subslice; + __u16 max_eus_per_subslice; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 rsvd; +}; + +struct drm_i915_gem_context_create_ext_setparam { +#define I915_CONTEXT_CREATE_EXT_SETPARAM 0 + struct i915_user_extension base; + struct drm_i915_gem_context_param param; +}; + +struct drm_i915_gem_context_destroy { + __u32 ctx_id; + __u32 pad; +}; + +/* + * DRM_I915_GEM_VM_CREATE - + * + * Create a new virtual memory address space (ppGTT) for use within a context + * on the same file. Extensions can be provided to configure exactly how the + * address space is setup upon creation. + * + * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is + * returned in the outparam @id. + * + * No flags are defined, with all bits reserved and must be zero. + * + * An extension chain maybe provided, starting with @extensions, and terminated + * by the @next_extension being 0. Currently, no extensions are defined. + * + * DRM_I915_GEM_VM_DESTROY - + * + * Destroys a previously created VM id, specified in @id. + * + * No extensions or flags are allowed currently, and so must be zero. + */ +struct drm_i915_gem_vm_control { + __u64 extensions; + __u32 flags; + __u32 vm_id; +}; + +struct drm_i915_reg_read { + /* + * Register offset. + * For 64bit wide registers where the upper 32bits don't immediately + * follow the lower 32bits, the offset of the lower 32bits must + * be specified + */ + __u64 offset; +#define I915_REG_READ_8B_WA (1ul << 0) + + __u64 val; /* Return value */ +}; + +/* Known registers: + * + * Render engine timestamp - 0x2358 + 64bit - gen7+ + * - Note this register returns an invalid value if using the default + * single instruction 8byte read, in order to workaround that pass + * flag I915_REG_READ_8B_WA in offset field. + * + */ + +struct drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + + /* All resets since boot/module reload, for all contexts */ + __u32 reset_count; + + /* Number of batches lost when active in GPU, for this context */ + __u32 batch_active; + + /* Number of batches lost pending for execution, for this context */ + __u32 batch_pending; + + __u32 pad; +}; + +struct drm_i915_gem_userptr { + __u64 user_ptr; + __u64 user_size; + __u32 flags; +#define I915_USERPTR_READ_ONLY 0x1 +#define I915_USERPTR_UNSYNCHRONIZED 0x80000000 + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; +}; + +enum drm_i915_oa_format { + I915_OA_FORMAT_A13 = 1, /* HSW only */ + I915_OA_FORMAT_A29, /* HSW only */ + I915_OA_FORMAT_A13_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8, /* HSW only */ + I915_OA_FORMAT_A45_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8_A16, /* HSW only */ + I915_OA_FORMAT_C4_B8, /* HSW+ */ + + /* Gen8+ */ + I915_OA_FORMAT_A12, + I915_OA_FORMAT_A12_B8_C8, + I915_OA_FORMAT_A32u40_A4u32_B8_C8, + + I915_OA_FORMAT_MAX /* non-ABI */ +}; + +enum drm_i915_perf_property_id { + /** + * Open the stream for a specific context handle (as used with + * execbuffer2). A stream opened for a specific context this way + * won't typically require root privileges. + */ + DRM_I915_PERF_PROP_CTX_HANDLE = 1, + + /** + * A value of 1 requests the inclusion of raw OA unit reports as + * part of stream samples. + */ + DRM_I915_PERF_PROP_SAMPLE_OA, + + /** + * The value specifies which set of OA unit metrics should be + * be configured, defining the contents of any OA unit reports. + */ + DRM_I915_PERF_PROP_OA_METRICS_SET, + + /** + * The value specifies the size and layout of OA unit reports. + */ + DRM_I915_PERF_PROP_OA_FORMAT, + + /** + * Specifying this property implicitly requests periodic OA unit + * sampling and (at least on Haswell) the sampling frequency is derived + * from this exponent as follows: + * + * 80ns * 2^(period_exponent + 1) + */ + DRM_I915_PERF_PROP_OA_EXPONENT, + + DRM_I915_PERF_PROP_MAX /* non-ABI */ +}; + +struct drm_i915_perf_open_param { + __u32 flags; +#define I915_PERF_FLAG_FD_CLOEXEC (1<<0) +#define I915_PERF_FLAG_FD_NONBLOCK (1<<1) +#define I915_PERF_FLAG_DISABLED (1<<2) + + /** The number of u64 (id, value) pairs */ + __u32 num_properties; + + /** + * Pointer to array of u64 (id, value) pairs configuring the stream + * to open. + */ + __u64 properties_ptr; +}; + +/** + * Enable data capture for a stream that was either opened in a disabled state + * via I915_PERF_FLAG_DISABLED or was later disabled via + * I915_PERF_IOCTL_DISABLE. + * + * It is intended to be cheaper to disable and enable a stream than it may be + * to close and re-open a stream with the same configuration. + * + * It's undefined whether any pending data for the stream will be lost. + */ +#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0) + +/** + * Disable data capture for a stream. + * + * It is an error to try and read a stream that is disabled. + */ +#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1) + +/** + * Common to all i915 perf records + */ +struct drm_i915_perf_record_header { + __u32 type; + __u16 pad; + __u16 size; +}; + +enum drm_i915_perf_record_type { + + /** + * Samples are the work horse record type whose contents are extensible + * and defined when opening an i915 perf stream based on the given + * properties. + * + * Boolean properties following the naming convention + * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in + * every sample. + * + * The order of these sample properties given by userspace has no + * affect on the ordering of data within a sample. The order is + * documented here. + * + * struct { + * struct drm_i915_perf_record_header header; + * + * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA + * }; + */ + DRM_I915_PERF_RECORD_SAMPLE = 1, + + /* + * Indicates that one or more OA reports were not written by the + * hardware. This can happen for example if an MI_REPORT_PERF_COUNT + * command collides with periodic sampling - which would be more likely + * at higher sampling frequencies. + */ + DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2, + + /** + * An error occurred that resulted in all pending OA reports being lost. + */ + DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3, + + DRM_I915_PERF_RECORD_MAX /* non-ABI */ +}; + +/** + * Structure to upload perf dynamic configuration into the kernel. + */ +struct drm_i915_perf_oa_config { + /** String formatted like "%08x-%04x-%04x-%04x-%012x" */ + char uuid[36]; + + __u32 n_mux_regs; + __u32 n_boolean_regs; + __u32 n_flex_regs; + + /* + * These fields are pointers to tuples of u32 values (register address, + * value). For example the expected length of the buffer pointed by + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). + */ + __u64 mux_regs_ptr; + __u64 boolean_regs_ptr; + __u64 flex_regs_ptr; +}; + +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_TOPOLOGY_INFO 1 +/* Must be kept compact -- no holes and well documented */ + + /* + * When set to zero by userspace, this is filled with the size of the + * data to be written at the data_ptr pointer. The kernel sets this + * value to a negative value to signal an error on a particular query + * item. + */ + __s32 length; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Data will be written at the location pointed by data_ptr when the + * value of length matches the length of the data to be written by the + * kernel. + */ + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * This points to an array of num_items drm_i915_query_item structures. + */ + __u64 items_ptr; +}; + +/* + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : + * + * data: contains the 3 pieces of information : + * + * - the slice mask with one bit per slice telling whether a slice is + * available. The availability of slice X can be queried with the following + * formula : + * + * (data[X / 8] >> (X % 8)) & 1 + * + * - the subslice mask for each slice with one bit per subslice telling + * whether a subslice is available. The availability of subslice Y in slice + * X can be queried with the following formula : + * + * (data[subslice_offset + + * X * subslice_stride + + * Y / 8] >> (Y % 8)) & 1 + * + * - the EU mask for each subslice in each slice with one bit per EU telling + * whether an EU is available. The availability of EU Z in subslice Y in + * slice X can be queried with the following formula : + * + * (data[eu_offset + + * (X * max_subslices + Y) * eu_stride + + * Z / 8] >> (Z % 8)) & 1 + */ +struct drm_i915_query_topology_info { + /* + * Unused for now. Must be cleared to zero. + */ + __u16 flags; + + __u16 max_slices; + __u16 max_subslices; + __u16 max_eus_per_subslice; + + /* + * Offset in data[] at which the subslice masks are stored. + */ + __u16 subslice_offset; + + /* + * Stride at which each of the subslice masks for each slice are + * stored. + */ + __u16 subslice_stride; + + /* + * Offset in data[] at which the EU masks are stored. + */ + __u16 eu_offset; + + /* + * Stride at which each of the EU masks for each subslice are stored. + */ + __u16 eu_stride; + + __u8 data[]; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _I915_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/mach64_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/mach64_drm.h new file mode 100644 index 0000000..1f5fd84 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/mach64_drm.h @@ -0,0 +1,256 @@ +/* mach64_drm.h -- Public header for the mach64 driver -*- linux-c -*- + * Created: Thu Nov 30 20:04:32 2000 by gareth@valinux.com + */ +/* + * Copyright 2000 Gareth Hughes + * Copyright 2002 Frank C. Earl + * Copyright 2002-2003 Leif Delgass + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Frank C. Earl + * Leif Delgass + */ + +#ifndef __MACH64_DRM_H__ +#define __MACH64_DRM_H__ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mach64_sarea.h) + */ +#ifndef __MACH64_SAREA_DEFINES__ +#define __MACH64_SAREA_DEFINES__ + +/* What needs to be changed for the current vertex buffer? + * GH: We're going to be pedantic about this. We want the card to do as + * little as possible, so let's avoid having it fetch a whole bunch of + * register values that don't change all that often, if at all. + */ +#define MACH64_UPLOAD_DST_OFF_PITCH 0x0001 +#define MACH64_UPLOAD_Z_OFF_PITCH 0x0002 +#define MACH64_UPLOAD_Z_ALPHA_CNTL 0x0004 +#define MACH64_UPLOAD_SCALE_3D_CNTL 0x0008 +#define MACH64_UPLOAD_DP_FOG_CLR 0x0010 +#define MACH64_UPLOAD_DP_WRITE_MASK 0x0020 +#define MACH64_UPLOAD_DP_PIX_WIDTH 0x0040 +#define MACH64_UPLOAD_SETUP_CNTL 0x0080 +#define MACH64_UPLOAD_MISC 0x0100 +#define MACH64_UPLOAD_TEXTURE 0x0200 +#define MACH64_UPLOAD_TEX0IMAGE 0x0400 +#define MACH64_UPLOAD_TEX1IMAGE 0x0800 +#define MACH64_UPLOAD_CLIPRECTS 0x1000 /* handled client-side */ +#define MACH64_UPLOAD_CONTEXT 0x00ff +#define MACH64_UPLOAD_ALL 0x1fff + +/* DMA buffer size + */ +#define MACH64_BUFFER_SIZE 16384 + +/* Max number of swaps allowed on the ring + * before the client must wait + */ +#define MACH64_MAX_QUEUED_FRAMES 3U + +/* Byte offsets for host blit buffer data + */ +#define MACH64_HOSTDATA_BLIT_OFFSET 104 + +/* Keep these small for testing. + */ +#define MACH64_NR_SAREA_CLIPRECTS 8 + +#define MACH64_CARD_HEAP 0 +#define MACH64_AGP_HEAP 1 +#define MACH64_NR_TEX_HEAPS 2 +#define MACH64_NR_TEX_REGIONS 64 +#define MACH64_LOG_TEX_GRANULARITY 16 + +#define MACH64_TEX_MAXLEVELS 1 + +#define MACH64_NR_CONTEXT_REGS 15 +#define MACH64_NR_TEXTURE_REGS 4 + +#endif /* __MACH64_SAREA_DEFINES__ */ + +typedef struct { + unsigned int dst_off_pitch; + + unsigned int z_off_pitch; + unsigned int z_cntl; + unsigned int alpha_tst_cntl; + + unsigned int scale_3d_cntl; + + unsigned int sc_left_right; + unsigned int sc_top_bottom; + + unsigned int dp_fog_clr; + unsigned int dp_write_mask; + unsigned int dp_pix_width; + unsigned int dp_mix; + unsigned int dp_src; + + unsigned int clr_cmp_cntl; + unsigned int gui_traj_cntl; + + unsigned int setup_cntl; + + unsigned int tex_size_pitch; + unsigned int tex_cntl; + unsigned int secondary_tex_off; + unsigned int tex_offset; +} drm_mach64_context_regs_t; + +typedef struct drm_mach64_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + drm_mach64_context_regs_t context_state; + unsigned int dirty; + unsigned int vertsize; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[MACH64_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int frames_queued; + + /* Texture memory LRU. + */ + struct drm_tex_region tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[MACH64_NR_TEX_HEAPS]; + int ctx_owner; +} drm_mach64_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mach64_common.h) + */ + +/* Mach64 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ + +#define DRM_MACH64_INIT 0x00 +#define DRM_MACH64_IDLE 0x01 +#define DRM_MACH64_RESET 0x02 +#define DRM_MACH64_SWAP 0x03 +#define DRM_MACH64_CLEAR 0x04 +#define DRM_MACH64_VERTEX 0x05 +#define DRM_MACH64_BLIT 0x06 +#define DRM_MACH64_FLUSH 0x07 +#define DRM_MACH64_GETPARAM 0x08 + +#define DRM_IOCTL_MACH64_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_INIT, drm_mach64_init_t) +#define DRM_IOCTL_MACH64_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_IDLE ) +#define DRM_IOCTL_MACH64_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_RESET ) +#define DRM_IOCTL_MACH64_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_SWAP ) +#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_CLEAR, drm_mach64_clear_t) +#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_VERTEX, drm_mach64_vertex_t) +#define DRM_IOCTL_MACH64_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_BLIT, drm_mach64_blit_t) +#define DRM_IOCTL_MACH64_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_FLUSH ) +#define DRM_IOCTL_MACH64_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_MACH64_GETPARAM, drm_mach64_getparam_t) + +/* Buffer flags for clears + */ +#define MACH64_FRONT 0x1 +#define MACH64_BACK 0x2 +#define MACH64_DEPTH 0x4 + +/* Primitive types for vertex buffers + */ +#define MACH64_PRIM_POINTS 0x00000000 +#define MACH64_PRIM_LINES 0x00000001 +#define MACH64_PRIM_LINE_LOOP 0x00000002 +#define MACH64_PRIM_LINE_STRIP 0x00000003 +#define MACH64_PRIM_TRIANGLES 0x00000004 +#define MACH64_PRIM_TRIANGLE_STRIP 0x00000005 +#define MACH64_PRIM_TRIANGLE_FAN 0x00000006 +#define MACH64_PRIM_QUADS 0x00000007 +#define MACH64_PRIM_QUAD_STRIP 0x00000008 +#define MACH64_PRIM_POLYGON 0x00000009 + +typedef enum _drm_mach64_dma_mode_t { + MACH64_MODE_DMA_ASYNC, + MACH64_MODE_DMA_SYNC, + MACH64_MODE_MMIO +} drm_mach64_dma_mode_t; + +typedef struct drm_mach64_init { + enum { + DRM_MACH64_INIT_DMA = 0x01, + DRM_MACH64_CLEANUP_DMA = 0x02 + } func; + + unsigned long sarea_priv_offset; + int is_pci; + drm_mach64_dma_mode_t dma_mode; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drm_mach64_init_t; + +typedef struct drm_mach64_clear { + unsigned int flags; + int x, y, w, h; + unsigned int clear_color; + unsigned int clear_depth; +} drm_mach64_clear_t; + +typedef struct drm_mach64_vertex { + int prim; + void *buf; /* Address of vertex buffer */ + unsigned long used; /* Number of bytes in buffer */ + int discard; /* Client finished with buffer? */ +} drm_mach64_vertex_t; + +typedef struct drm_mach64_blit { + void *buf; + int pitch; + int offset; + int format; + unsigned short x, y; + unsigned short width, height; +} drm_mach64_blit_t; + +typedef struct drm_mach64_getparam { + enum { + MACH64_PARAM_FRAMES_QUEUED = 0x01, + MACH64_PARAM_IRQ_NR = 0x02 + } param; + void *value; +} drm_mach64_getparam_t; + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/mga_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/mga_drm.h new file mode 100644 index 0000000..7930011 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/mga_drm.h @@ -0,0 +1,427 @@ +/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- + * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jeff Hartmann + * Keith Whitwell + * + * Rewritten by: + * Gareth Hughes + */ + +#ifndef __MGA_DRM_H__ +#define __MGA_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mga_sarea.h) + */ + +#ifndef __MGA_SAREA_DEFINES__ +#define __MGA_SAREA_DEFINES__ + +/* WARP pipe flags + */ +#define MGA_F 0x1 /* fog */ +#define MGA_A 0x2 /* alpha */ +#define MGA_S 0x4 /* specular */ +#define MGA_T2 0x8 /* multitexture */ + +#define MGA_WARP_TGZ 0 +#define MGA_WARP_TGZF (MGA_F) +#define MGA_WARP_TGZA (MGA_A) +#define MGA_WARP_TGZAF (MGA_F|MGA_A) +#define MGA_WARP_TGZS (MGA_S) +#define MGA_WARP_TGZSF (MGA_S|MGA_F) +#define MGA_WARP_TGZSA (MGA_S|MGA_A) +#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) +#define MGA_WARP_T2GZ (MGA_T2) +#define MGA_WARP_T2GZF (MGA_T2|MGA_F) +#define MGA_WARP_T2GZA (MGA_T2|MGA_A) +#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) +#define MGA_WARP_T2GZS (MGA_T2|MGA_S) +#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) +#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) +#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) + +#define MGA_MAX_G200_PIPES 8 /* no multitex */ +#define MGA_MAX_G400_PIPES 16 +#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES +#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ + +#define MGA_CARD_TYPE_G200 1 +#define MGA_CARD_TYPE_G400 2 +#define MGA_CARD_TYPE_G450 3 /* not currently used */ +#define MGA_CARD_TYPE_G550 4 + +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define MGA_UPLOAD_CONTEXT 0x1 +#define MGA_UPLOAD_TEX0 0x2 +#define MGA_UPLOAD_TEX1 0x4 +#define MGA_UPLOAD_PIPE 0x8 +#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ +#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ +#define MGA_UPLOAD_2D 0x40 +#define MGA_WAIT_AGE 0x80 /* handled client-side */ +#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +#if 0 +#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock + quiescent */ +#endif + +/* 32 buffers of 64k each, total 2 meg. + */ +#define MGA_BUFFER_SIZE (1 << 16) +#define MGA_NUM_BUFFERS 128 + +/* Keep these small for testing. + */ +#define MGA_NR_SAREA_CLIPRECTS 8 + +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define MGA_CARD_HEAP 0 +#define MGA_AGP_HEAP 1 +#define MGA_NR_TEX_HEAPS 2 +#define MGA_NR_TEX_REGIONS 16 +#define MGA_LOG_MIN_TEX_REGION_SIZE 16 + +#define DRM_MGA_IDLE_RETRY 2048 + +#endif /* __MGA_SAREA_DEFINES__ */ + +/* Setup registers for 3D context + */ +typedef struct { + unsigned int dstorg; + unsigned int maccess; + unsigned int plnwt; + unsigned int dwgctl; + unsigned int alphactrl; + unsigned int fogcolor; + unsigned int wflag; + unsigned int tdualstage0; + unsigned int tdualstage1; + unsigned int fcol; + unsigned int stencil; + unsigned int stencilctl; +} drm_mga_context_regs_t; + +/* Setup registers for 2D, X server + */ +typedef struct { + unsigned int pitch; +} drm_mga_server_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int texctl; + unsigned int texctl2; + unsigned int texfilter; + unsigned int texbordercol; + unsigned int texorg; + unsigned int texwidth; + unsigned int texheight; + unsigned int texorg1; + unsigned int texorg2; + unsigned int texorg3; + unsigned int texorg4; +} drm_mga_texture_regs_t; + +/* General aging mechanism + */ +typedef struct { + unsigned int head; /* Position of head pointer */ + unsigned int wrap; /* Primary DMA wrap count */ +} drm_mga_age_t; + +typedef struct _drm_mga_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + drm_mga_context_regs_t context_state; + drm_mga_server_regs_t server_state; + drm_mga_texture_regs_t tex_state[2]; + unsigned int warp_pipe; + unsigned int dirty; + unsigned int vertsize; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Information about the most recently used 3d drawable. The + * client fills in the req_* fields, the server fills in the + * exported_ fields and puts the cliprects into boxes, above. + * + * The client clears the exported_drawable field before + * clobbering the boxes data. + */ + unsigned int req_drawable; /* the X drawable id */ + unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ + + unsigned int exported_drawable; + unsigned int exported_index; + unsigned int exported_stamp; + unsigned int exported_buffers; + unsigned int exported_nfront; + unsigned int exported_nback; + int exported_back_x, exported_front_x, exported_w; + int exported_back_y, exported_front_y, exported_h; + struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS]; + + /* Counters for aging textures and for client-side throttling. + */ + unsigned int status[4]; + unsigned int last_wrap; + + drm_mga_age_t last_frame; + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ + + /* LRU lists for texture memory in agp space and on the card. + */ + struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; + unsigned int texAge[MGA_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_mga_sarea_t; + +/* MGA specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_MGA_INIT 0x00 +#define DRM_MGA_FLUSH 0x01 +#define DRM_MGA_RESET 0x02 +#define DRM_MGA_SWAP 0x03 +#define DRM_MGA_CLEAR 0x04 +#define DRM_MGA_VERTEX 0x05 +#define DRM_MGA_INDICES 0x06 +#define DRM_MGA_ILOAD 0x07 +#define DRM_MGA_BLIT 0x08 +#define DRM_MGA_GETPARAM 0x09 + +/* 3.2: + * ioctls for operating on fences. + */ +#define DRM_MGA_SET_FENCE 0x0a +#define DRM_MGA_WAIT_FENCE 0x0b +#define DRM_MGA_DMA_BOOTSTRAP 0x0c + +#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) +#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) +#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) +#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) +#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) +#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) +#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) + +typedef struct _drm_mga_warp_index { + int installed; + unsigned long phys_addr; + int size; +} drm_mga_warp_index_t; + +typedef struct drm_mga_init { + enum { + MGA_INIT_DMA = 0x01, + MGA_CLEANUP_DMA = 0x02 + } func; + + unsigned long sarea_priv_offset; + + int chipset; + int sgram; + + unsigned int maccess; + + unsigned int fb_cpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_cpp; + unsigned int depth_offset, depth_pitch; + + unsigned int texture_offset[MGA_NR_TEX_HEAPS]; + unsigned int texture_size[MGA_NR_TEX_HEAPS]; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long status_offset; + unsigned long warp_offset; + unsigned long primary_offset; + unsigned long buffers_offset; +} drm_mga_init_t; + +typedef struct drm_mga_dma_bootstrap { + /** + * \name AGP texture region + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will + * be filled in with the actual AGP texture settings. + * + * \warning + * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode + * is zero, it means that PCI memory (most likely through the use of + * an IOMMU) is being used for "AGP" textures. + */ + /*@{ */ + unsigned long texture_handle; /**< Handle used to map AGP textures. */ + __u32 texture_size; /**< Size of the AGP texture region. */ + /*@} */ + + /** + * Requested size of the primary DMA region. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + */ + __u32 primary_size; + + /** + * Requested number of secondary DMA buffers. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual number of secondary DMA buffers + * allocated. Particularly when PCI DMA is used, this may be + * (subtantially) less than the number requested. + */ + __u32 secondary_bin_count; + + /** + * Requested size of each secondary DMA buffer. + * + * While the kernel \b is free to reduce + * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed + * to reduce dma_mga_dma_bootstrap::secondary_bin_size. + */ + __u32 secondary_bin_size; + + /** + * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, + * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is + * zero, it means that PCI DMA should be used, even if AGP is + * possible. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + * (i.e., PCI DMA was used), this value will be zero. + */ + __u32 agp_mode; + + /** + * Desired AGP GART size, measured in megabytes. + */ + __u8 agp_size; +} drm_mga_dma_bootstrap_t; + +typedef struct drm_mga_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_mga_clear_t; + +typedef struct drm_mga_vertex { + int idx; /* buffer to queue */ + int used; /* bytes in use */ + int discard; /* client finished with buffer? */ +} drm_mga_vertex_t; + +typedef struct drm_mga_indices { + int idx; /* buffer to queue */ + unsigned int start; + unsigned int end; + int discard; /* client finished with buffer? */ +} drm_mga_indices_t; + +typedef struct drm_mga_iload { + int idx; + unsigned int dstorg; + unsigned int length; +} drm_mga_iload_t; + +typedef struct _drm_mga_blit { + unsigned int planemask; + unsigned int srcorg; + unsigned int dstorg; + int src_pitch, dst_pitch; + int delta_sx, delta_sy; + int delta_dx, delta_dy; + int height, ydir; /* flip image vertically */ + int source_pitch, dest_pitch; +} drm_mga_blit_t; + +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +/* 3.2: Query the actual card type. The DDX only distinguishes between + * G200 chips and non-G200 chips, which it calls G400. It turns out that + * there are some very sublte differences between the G4x0 chips and the G550 + * chips. Using this parameter query, a client-side driver can detect the + * difference between a G4x0 and a G550. + */ +#define MGA_PARAM_CARD_TYPE 2 + +typedef struct drm_mga_getparam { + int param; + void *value; +} drm_mga_getparam_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/nouveau_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/nouveau_drm.h new file mode 100644 index 0000000..d42105c --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/nouveau_drm.h @@ -0,0 +1,221 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NOUVEAU_DRM_H__ +#define __NOUVEAU_DRM_H__ + +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16 + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +struct drm_nouveau_channel_alloc { + uint32_t fb_ctxdma_handle; + uint32_t tt_ctxdma_handle; + + int channel; + uint32_t pushbuf_domains; + + /* Notifier memory */ + uint32_t notifier_handle; + + /* DRM-enforced subchannel assignments */ + struct { + uint32_t handle; + uint32_t grclass; + } subchan[8]; + uint32_t nr_subchan; +}; + +struct drm_nouveau_channel_free { + int channel; +}; + +struct drm_nouveau_grobj_alloc { + int channel; + uint32_t handle; + int class; +}; + +struct drm_nouveau_notifierobj_alloc { + uint32_t channel; + uint32_t handle; + uint32_t size; + uint32_t offset; +}; + +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + +/* FIXME : maybe unify {GET,SET}PARAMs */ +#define NOUVEAU_GETPARAM_PCI_VENDOR 3 +#define NOUVEAU_GETPARAM_PCI_DEVICE 4 +#define NOUVEAU_GETPARAM_BUS_TYPE 5 +#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 +#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 +#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 +#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 +#define NOUVEAU_GETPARAM_GRAPH_UNITS 13 +#define NOUVEAU_GETPARAM_PTIMER_TIME 14 +#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 +#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 +struct drm_nouveau_getparam { + uint64_t param; + uint64_t value; +}; + +struct drm_nouveau_setparam { + uint64_t param; + uint64_t value; +}; + +#define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) +#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) +#define NOUVEAU_GEM_DOMAIN_GART (1 << 2) +#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) +#define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4) + +#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ +#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 +#define NOUVEAU_GEM_TILE_16BPP 0x00000001 +#define NOUVEAU_GEM_TILE_32BPP 0x00000002 +#define NOUVEAU_GEM_TILE_ZETA 0x00000004 +#define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 + +struct drm_nouveau_gem_info { + __u32 handle; + __u32 domain; + __u64 size; + __u64 offset; + __u64 map_handle; + __u32 tile_mode; + __u32 tile_flags; +}; + +struct drm_nouveau_gem_new { + struct drm_nouveau_gem_info info; + __u32 channel_hint; + __u32 align; +}; + +#define NOUVEAU_GEM_MAX_BUFFERS 1024 +struct drm_nouveau_gem_pushbuf_bo_presumed { + __u32 valid; + __u32 domain; + __u64 offset; +}; + +struct drm_nouveau_gem_pushbuf_bo { + __u64 user_priv; + __u32 handle; + __u32 read_domains; + __u32 write_domains; + __u32 valid_domains; + struct drm_nouveau_gem_pushbuf_bo_presumed presumed; +}; + +#define NOUVEAU_GEM_RELOC_LOW (1 << 0) +#define NOUVEAU_GEM_RELOC_HIGH (1 << 1) +#define NOUVEAU_GEM_RELOC_OR (1 << 2) +#define NOUVEAU_GEM_MAX_RELOCS 1024 +struct drm_nouveau_gem_pushbuf_reloc { + __u32 reloc_bo_index; + __u32 reloc_bo_offset; + __u32 bo_index; + __u32 flags; + __u32 data; + __u32 vor; + __u32 tor; +}; + +#define NOUVEAU_GEM_MAX_PUSH 512 +struct drm_nouveau_gem_pushbuf_push { + __u32 bo_index; + __u32 pad; + __u64 offset; + __u64 length; +}; + +struct drm_nouveau_gem_pushbuf { + __u32 channel; + __u32 nr_buffers; + __u64 buffers; + __u32 nr_relocs; + __u32 nr_push; + __u64 relocs; + __u64 push; + __u32 suffix0; + __u32 suffix1; + __u64 vram_available; + __u64 gart_available; +}; + +#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 +#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 +#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 +struct drm_nouveau_gem_cpu_prep { + __u32 handle; + __u32 flags; +}; + +struct drm_nouveau_gem_cpu_fini { + __u32 handle; +}; + +enum nouveau_bus_type { + NV_AGP = 0, + NV_PCI = 1, + NV_PCIE = 2, +}; + +struct drm_nouveau_sarea { +}; + +#define DRM_NOUVEAU_GETPARAM 0x00 +#define DRM_NOUVEAU_SETPARAM 0x01 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 +#define DRM_NOUVEAU_CHANNEL_FREE 0x03 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x04 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x06 +#define DRM_NOUVEAU_NVIF 0x07 +#define DRM_NOUVEAU_GEM_NEW 0x40 +#define DRM_NOUVEAU_GEM_PUSHBUF 0x41 +#define DRM_NOUVEAU_GEM_CPU_PREP 0x42 +#define DRM_NOUVEAU_GEM_CPU_FINI 0x43 +#define DRM_NOUVEAU_GEM_INFO 0x44 + +#if defined(__cplusplus) +} +#endif + +#endif /* __NOUVEAU_DRM_H__ */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/qxl_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/qxl_drm.h new file mode 100644 index 0000000..880999d --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/qxl_drm.h @@ -0,0 +1,158 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef QXL_DRM_H +#define QXL_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define QXL_GEM_DOMAIN_CPU 0 +#define QXL_GEM_DOMAIN_VRAM 1 +#define QXL_GEM_DOMAIN_SURFACE 2 + +#define DRM_QXL_ALLOC 0x00 +#define DRM_QXL_MAP 0x01 +#define DRM_QXL_EXECBUFFER 0x02 +#define DRM_QXL_UPDATE_AREA 0x03 +#define DRM_QXL_GETPARAM 0x04 +#define DRM_QXL_CLIENTCAP 0x05 + +#define DRM_QXL_ALLOC_SURF 0x06 + +struct drm_qxl_alloc { + __u32 size; + __u32 handle; /* 0 is an invalid handle */ +}; + +struct drm_qxl_map { + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; +}; + +/* + * dest is the bo we are writing the relocation into + * src is bo we are relocating. + * *(dest_handle.base_addr + dest_offset) = physical_address(src_handle.addr + + * src_offset) + */ +#define QXL_RELOC_TYPE_BO 1 +#define QXL_RELOC_TYPE_SURF 2 + +struct drm_qxl_reloc { + __u64 src_offset; /* offset into src_handle or src buffer */ + __u64 dst_offset; /* offset in dest handle */ + __u32 src_handle; /* dest handle to compute address from */ + __u32 dst_handle; /* 0 if to command buffer */ + __u32 reloc_type; + __u32 pad; +}; + +struct drm_qxl_command { + __u64 command; /* void* */ + __u64 relocs; /* struct drm_qxl_reloc* */ + __u32 type; + __u32 command_size; + __u32 relocs_num; + __u32 pad; +}; + +struct drm_qxl_execbuffer { + __u32 flags; /* for future use */ + __u32 commands_num; + __u64 commands; /* struct drm_qxl_command* */ +}; + +struct drm_qxl_update_area { + __u32 handle; + __u32 top; + __u32 left; + __u32 bottom; + __u32 right; + __u32 pad; +}; + +#define QXL_PARAM_NUM_SURFACES 1 /* rom->n_surfaces */ +#define QXL_PARAM_MAX_RELOCS 2 +struct drm_qxl_getparam { + __u64 param; + __u64 value; +}; + +/* these are one bit values */ +struct drm_qxl_clientcap { + __u32 index; + __u32 pad; +}; + +struct drm_qxl_alloc_surf { + __u32 format; + __u32 width; + __u32 height; + __s32 stride; + __u32 handle; + __u32 pad; +}; + +#define DRM_IOCTL_QXL_ALLOC \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC, struct drm_qxl_alloc) + +#define DRM_IOCTL_QXL_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_MAP, struct drm_qxl_map) + +#define DRM_IOCTL_QXL_EXECBUFFER \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_EXECBUFFER,\ + struct drm_qxl_execbuffer) + +#define DRM_IOCTL_QXL_UPDATE_AREA \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_UPDATE_AREA,\ + struct drm_qxl_update_area) + +#define DRM_IOCTL_QXL_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_GETPARAM,\ + struct drm_qxl_getparam) + +#define DRM_IOCTL_QXL_CLIENTCAP \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_CLIENTCAP,\ + struct drm_qxl_clientcap) + +#define DRM_IOCTL_QXL_ALLOC_SURF \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC_SURF,\ + struct drm_qxl_alloc_surf) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/r128_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/r128_drm.h new file mode 100644 index 0000000..bf431a0 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/r128_drm.h @@ -0,0 +1,336 @@ +/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + */ +/* + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Kevin E. Martin + */ + +#ifndef __R128_DRM_H__ +#define __R128_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (r128_sarea.h) + */ +#ifndef __R128_SAREA_DEFINES__ +#define __R128_SAREA_DEFINES__ + +/* What needs to be changed for the current vertex buffer? + */ +#define R128_UPLOAD_CONTEXT 0x001 +#define R128_UPLOAD_SETUP 0x002 +#define R128_UPLOAD_TEX0 0x004 +#define R128_UPLOAD_TEX1 0x008 +#define R128_UPLOAD_TEX0IMAGES 0x010 +#define R128_UPLOAD_TEX1IMAGES 0x020 +#define R128_UPLOAD_CORE 0x040 +#define R128_UPLOAD_MASKS 0x080 +#define R128_UPLOAD_WINDOW 0x100 +#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */ +#define R128_REQUIRE_QUIESCENCE 0x400 +#define R128_UPLOAD_ALL 0x7ff + +#define R128_FRONT 0x1 +#define R128_BACK 0x2 +#define R128_DEPTH 0x4 + +/* Primitive types + */ +#define R128_POINTS 0x1 +#define R128_LINES 0x2 +#define R128_LINE_STRIP 0x3 +#define R128_TRIANGLES 0x4 +#define R128_TRIANGLE_FAN 0x5 +#define R128_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define R128_BUFFER_SIZE 16384 + +/* Byte offsets for indirect buffer data + */ +#define R128_INDEX_PRIM_OFFSET 20 +#define R128_HOSTDATA_BLIT_OFFSET 32 + +/* Keep these small for testing. + */ +#define R128_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/AGP). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +#define R128_NR_CONTEXT_REGS 12 + +#define R128_MAX_TEXTURE_LEVELS 11 +#define R128_MAX_TEXTURE_UNITS 2 + +#endif /* __R128_SAREA_DEFINES__ */ + +typedef struct { + /* Context state - can be written in one large chunk */ + unsigned int dst_pitch_offset_c; + unsigned int dp_gui_master_cntl_c; + unsigned int sc_top_left_c; + unsigned int sc_bottom_right_c; + unsigned int z_offset_c; + unsigned int z_pitch_c; + unsigned int z_sten_cntl_c; + unsigned int tex_cntl_c; + unsigned int misc_3d_state_cntl_reg; + unsigned int texture_clr_cmp_clr_c; + unsigned int texture_clr_cmp_msk_c; + unsigned int fog_color_c; + + /* Texture state */ + unsigned int tex_size_pitch_c; + unsigned int constant_color_c; + + /* Setup state */ + unsigned int pm4_vc_fpu_setup; + unsigned int setup_cntl; + + /* Mask state */ + unsigned int dp_write_mask; + unsigned int sten_ref_mask_c; + unsigned int plane_3d_mask_c; + + /* Window state */ + unsigned int window_xy_offset; + + /* Core state */ + unsigned int scale_3d_cntl; +} drm_r128_context_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int tex_cntl; + unsigned int tex_combine_cntl; + unsigned int tex_size_pitch; + unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS]; + unsigned int tex_border_color; +} drm_r128_texture_regs_t; + +typedef struct drm_r128_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex buffer. + */ + drm_r128_context_regs_t context_state; + drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + + struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1]; + unsigned int tex_age[R128_NR_TEX_HEAPS]; + int ctx_owner; + int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */ + int pfCurrentPage; /* which buffer is being displayed? */ +} drm_r128_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmR128.h) + */ + +/* Rage 128 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_R128_INIT 0x00 +#define DRM_R128_CCE_START 0x01 +#define DRM_R128_CCE_STOP 0x02 +#define DRM_R128_CCE_RESET 0x03 +#define DRM_R128_CCE_IDLE 0x04 +/* 0x05 not used */ +#define DRM_R128_RESET 0x06 +#define DRM_R128_SWAP 0x07 +#define DRM_R128_CLEAR 0x08 +#define DRM_R128_VERTEX 0x09 +#define DRM_R128_INDICES 0x0a +#define DRM_R128_BLIT 0x0b +#define DRM_R128_DEPTH 0x0c +#define DRM_R128_STIPPLE 0x0d +/* 0x0e not used */ +#define DRM_R128_INDIRECT 0x0f +#define DRM_R128_FULLSCREEN 0x10 +#define DRM_R128_CLEAR2 0x11 +#define DRM_R128_GETPARAM 0x12 +#define DRM_R128_FLIP 0x13 + +#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE) +/* 0x05 not used */ +#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET) +#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t) +/* 0x0e not used */ +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) +#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP) + +typedef struct drm_r128_init { + enum { + R128_INIT_CCE = 0x01, + R128_CLEANUP_CCE = 0x02 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_secure; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + unsigned int span_offset; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drm_r128_init_t; + +typedef struct drm_r128_cce_stop { + int flush; + int idle; +} drm_r128_cce_stop_t; + +typedef struct drm_r128_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_r128_clear_t; + +typedef struct drm_r128_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_r128_vertex_t; + +typedef struct drm_r128_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_r128_indices_t; + +typedef struct drm_r128_blit { + int idx; + int pitch; + int offset; + int format; + unsigned short x, y; + unsigned short width, height; +} drm_r128_blit_t; + +typedef struct drm_r128_depth { + enum { + R128_WRITE_SPAN = 0x01, + R128_WRITE_PIXELS = 0x02, + R128_READ_SPAN = 0x03, + R128_READ_PIXELS = 0x04 + } func; + int n; + int *x; + int *y; + unsigned int *buffer; + unsigned char *mask; +} drm_r128_depth_t; + +typedef struct drm_r128_stipple { + unsigned int *mask; +} drm_r128_stipple_t; + +typedef struct drm_r128_indirect { + int idx; + int start; + int end; + int discard; +} drm_r128_indirect_t; + +typedef struct drm_r128_fullscreen { + enum { + R128_INIT_FULLSCREEN = 0x01, + R128_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_r128_fullscreen_t; + +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + void *value; +} drm_r128_getparam_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/radeon_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/radeon_drm.h new file mode 100644 index 0000000..a1e385d --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/radeon_drm.h @@ -0,0 +1,1079 @@ +/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#ifndef __RADEON_DRM_H__ +#define __RADEON_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (radeon_sarea.h) + */ +#ifndef __RADEON_SAREA_DEFINES__ +#define __RADEON_SAREA_DEFINES__ + +/* Old style state flags, required for sarea interface (1.1 and 1.2 + * clears) and 1.2 drm_vertex2 ioctl. + */ +#define RADEON_UPLOAD_CONTEXT 0x00000001 +#define RADEON_UPLOAD_VERTFMT 0x00000002 +#define RADEON_UPLOAD_LINE 0x00000004 +#define RADEON_UPLOAD_BUMPMAP 0x00000008 +#define RADEON_UPLOAD_MASKS 0x00000010 +#define RADEON_UPLOAD_VIEWPORT 0x00000020 +#define RADEON_UPLOAD_SETUP 0x00000040 +#define RADEON_UPLOAD_TCL 0x00000080 +#define RADEON_UPLOAD_MISC 0x00000100 +#define RADEON_UPLOAD_TEX0 0x00000200 +#define RADEON_UPLOAD_TEX1 0x00000400 +#define RADEON_UPLOAD_TEX2 0x00000800 +#define RADEON_UPLOAD_TEX0IMAGES 0x00001000 +#define RADEON_UPLOAD_TEX1IMAGES 0x00002000 +#define RADEON_UPLOAD_TEX2IMAGES 0x00004000 +#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */ +#define RADEON_REQUIRE_QUIESCENCE 0x00010000 +#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ +#define RADEON_UPLOAD_ALL 0x003effff +#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff + +/* New style per-packet identifiers for use in cmd_buffer ioctl with + * the RADEON_EMIT_PACKET command. Comments relate new packets to old + * state bits and the packet size: + */ +#define RADEON_EMIT_PP_MISC 0 /* context/7 */ +#define RADEON_EMIT_PP_CNTL 1 /* context/3 */ +#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ +#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ +#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ +#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ +#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ +#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ +#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ +#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ +#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ +#define RADEON_EMIT_RE_MISC 11 /* misc/1 */ +#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ +#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ +#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ +#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ +#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ +#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ +#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ +#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ +#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ +#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ +#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ +#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ +#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ +#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ +#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ +#define R200_EMIT_TFACTOR_0 30 /* tf/7 */ +#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ +#define R200_EMIT_VAP_CTL 32 /* vap/1 */ +#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ +#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ +#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ +#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ +#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ +#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ +#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ +#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ +#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ +#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ +#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ +#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ +#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ +#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ +#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ +#define R200_EMIT_VTE_CNTL 48 /* vte/1 */ +#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ +#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ +#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ +#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ +#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ +#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ +#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ +#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ +#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ +#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_EMIT_PP_TEX_SIZE_0 73 +#define RADEON_EMIT_PP_TEX_SIZE_1 74 +#define RADEON_EMIT_PP_TEX_SIZE_2 75 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77 +#define RADEON_EMIT_PP_CUBIC_FACES_0 78 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79 +#define RADEON_EMIT_PP_CUBIC_FACES_1 80 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81 +#define RADEON_EMIT_PP_CUBIC_FACES_2 82 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83 +#define R200_EMIT_PP_TRI_PERF_CNTL 84 +#define R200_EMIT_PP_AFS_0 85 +#define R200_EMIT_PP_AFS_1 86 +#define R200_EMIT_ATF_TFACTOR 87 +#define R200_EMIT_PP_TXCTLALL_0 88 +#define R200_EMIT_PP_TXCTLALL_1 89 +#define R200_EMIT_PP_TXCTLALL_2 90 +#define R200_EMIT_PP_TXCTLALL_3 91 +#define R200_EMIT_PP_TXCTLALL_4 92 +#define R200_EMIT_PP_TXCTLALL_5 93 +#define R200_EMIT_VAP_PVS_CNTL 94 +#define RADEON_MAX_STATE_PACKETS 95 + +/* Commands understood by cmd_buffer ioctl. More can be added but + * obviously these can't be removed or changed: + */ +#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ +#define RADEON_CMD_SCALARS 2 /* emit scalar data */ +#define RADEON_CMD_VECTORS 3 /* emit vector data */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ +#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ +#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: + * doesn't make the cpu wait, just + * the graphics hardware */ +#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */ + +typedef union { + int i; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, packet_id, pad0, pad1; + } packet; + struct { + unsigned char cmd_type, offset, stride, count; + } scalars; + struct { + unsigned char cmd_type, offset, stride, count; + } vectors; + struct { + unsigned char cmd_type, addr_lo, addr_hi, count; + } veclinear; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; +} drm_radeon_cmd_header_t; + +#define RADEON_WAIT_2D 0x1 +#define RADEON_WAIT_3D 0x2 + +/* Allowed parameters for R300_CMD_PACKET3 + */ +#define R300_CMD_PACKET3_CLEAR 0 +#define R300_CMD_PACKET3_RAW 1 + +/* Commands understood by cmd_buffer ioctl for R300. + * The interface has not been stabilized, so some of these may be removed + * and eventually reordered before stabilization. + */ +#define R300_CMD_PACKET0 1 +#define R300_CMD_VPU 2 /* emit vertex program upload */ +#define R300_CMD_PACKET3 3 /* emit a packet3 */ +#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */ +#define R300_CMD_CP_DELAY 5 +#define R300_CMD_DMA_DISCARD 6 +#define R300_CMD_WAIT 7 +# define R300_WAIT_2D 0x1 +# define R300_WAIT_3D 0x2 +/* these two defines are DOING IT WRONG - however + * we have userspace which relies on using these. + * The wait interface is backwards compat new + * code should use the NEW_WAIT defines below + * THESE ARE NOT BIT FIELDS + */ +# define R300_WAIT_2D_CLEAN 0x3 +# define R300_WAIT_3D_CLEAN 0x4 + +# define R300_NEW_WAIT_2D_3D 0x3 +# define R300_NEW_WAIT_2D_2D_CLEAN 0x4 +# define R300_NEW_WAIT_3D_3D_CLEAN 0x6 +# define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN 0x8 + +#define R300_CMD_SCRATCH 8 +#define R300_CMD_R500FP 9 + +typedef union { + unsigned int u; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, count, reglo, reghi; + } packet0; + struct { + unsigned char cmd_type, count, adrlo, adrhi; + } vpu; + struct { + unsigned char cmd_type, packet, pad0, pad1; + } packet3; + struct { + unsigned char cmd_type, packet; + unsigned short count; /* amount of packet2 to emit */ + } delay; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; + struct { + unsigned char cmd_type, count, adrlo, adrhi_flags; + } r500fp; +} drm_r300_cmd_header_t; + +#define RADEON_FRONT 0x1 +#define RADEON_BACK 0x2 +#define RADEON_DEPTH 0x4 +#define RADEON_STENCIL 0x8 +#define RADEON_CLEAR_FASTZ 0x80000000 +#define RADEON_USE_HIERZ 0x40000000 +#define RADEON_USE_COMP_ZBUF 0x20000000 + +#define R500FP_CONSTANT_TYPE (1 << 1) +#define R500FP_CONSTANT_CLAMP (1 << 2) + +/* Primitive types + */ +#define RADEON_POINTS 0x1 +#define RADEON_LINES 0x2 +#define RADEON_LINE_STRIP 0x3 +#define RADEON_TRIANGLES 0x4 +#define RADEON_TRIANGLE_FAN 0x5 +#define RADEON_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define RADEON_BUFFER_SIZE 65536 + +/* Byte offsets for indirect buffer data + */ +#define RADEON_INDEX_PRIM_OFFSET 20 + +#define RADEON_SCRATCH_REG_OFFSET 32 + +#define R600_SCRATCH_REG_OFFSET 256 + +#define RADEON_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/GART). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define RADEON_LOCAL_TEX_HEAP 0 +#define RADEON_GART_TEX_HEAP 1 +#define RADEON_NR_TEX_HEAPS 2 +#define RADEON_NR_TEX_REGIONS 64 +#define RADEON_LOG_TEX_GRANULARITY 16 + +#define RADEON_MAX_TEXTURE_LEVELS 12 +#define RADEON_MAX_TEXTURE_UNITS 3 + +#define RADEON_MAX_SURFACES 8 + +/* Blits have strict offset rules. All blit offset must be aligned on + * a 1K-byte boundary. + */ +#define RADEON_OFFSET_SHIFT 10 +#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT) +#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1) + +#endif /* __RADEON_SAREA_DEFINES__ */ + +typedef struct { + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int alpha; +} radeon_color_regs_t; + +typedef struct { + /* Context state */ + unsigned int pp_misc; /* 0x1c14 */ + unsigned int pp_fog_color; + unsigned int re_solid_color; + unsigned int rb3d_blendcntl; + unsigned int rb3d_depthoffset; + unsigned int rb3d_depthpitch; + unsigned int rb3d_zstencilcntl; + + unsigned int pp_cntl; /* 0x1c38 */ + unsigned int rb3d_cntl; + unsigned int rb3d_coloroffset; + unsigned int re_width_height; + unsigned int rb3d_colorpitch; + unsigned int se_cntl; + + /* Vertex format state */ + unsigned int se_coord_fmt; /* 0x1c50 */ + + /* Line state */ + unsigned int re_line_pattern; /* 0x1cd0 */ + unsigned int re_line_state; + + unsigned int se_line_width; /* 0x1db8 */ + + /* Bumpmap state */ + unsigned int pp_lum_matrix; /* 0x1d00 */ + + unsigned int pp_rot_matrix_0; /* 0x1d58 */ + unsigned int pp_rot_matrix_1; + + /* Mask state */ + unsigned int rb3d_stencilrefmask; /* 0x1d7c */ + unsigned int rb3d_ropcntl; + unsigned int rb3d_planemask; + + /* Viewport state */ + unsigned int se_vport_xscale; /* 0x1d98 */ + unsigned int se_vport_xoffset; + unsigned int se_vport_yscale; + unsigned int se_vport_yoffset; + unsigned int se_vport_zscale; + unsigned int se_vport_zoffset; + + /* Setup state */ + unsigned int se_cntl_status; /* 0x2140 */ + + /* Misc state */ + unsigned int re_top_left; /* 0x26c0 */ + unsigned int re_misc; +} drm_radeon_context_regs_t; + +typedef struct { + /* Zbias state */ + unsigned int se_zbias_factor; /* 0x1dac */ + unsigned int se_zbias_constant; +} drm_radeon_context2_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int pp_txfilter; + unsigned int pp_txformat; + unsigned int pp_txoffset; + unsigned int pp_txcblend; + unsigned int pp_txablend; + unsigned int pp_tfactor; + unsigned int pp_border_color; +} drm_radeon_texture_regs_t; + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim:8; + unsigned int stateidx:8; + unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ + unsigned int vc_format; /* vertex format */ +} drm_radeon_prim_t; + +typedef struct { + drm_radeon_context_regs_t context; + drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; + drm_radeon_context2_regs_t context2; + unsigned int dirty; +} drm_radeon_state_t; + +typedef struct { + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. + */ + drm_radeon_context_regs_t context_state; + drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + unsigned int last_clear; + + struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[RADEON_NR_TEX_HEAPS]; + int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ + int tiling_enabled; /* set by drm, read by 2d + 3d clients */ +} drm_radeon_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmRadeon.h) + * + * KW: actually it's illegal to change any of this (backwards compatibility). + */ + +/* Radeon specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_RADEON_CP_INIT 0x00 +#define DRM_RADEON_CP_START 0x01 +#define DRM_RADEON_CP_STOP 0x02 +#define DRM_RADEON_CP_RESET 0x03 +#define DRM_RADEON_CP_IDLE 0x04 +#define DRM_RADEON_RESET 0x05 +#define DRM_RADEON_FULLSCREEN 0x06 +#define DRM_RADEON_SWAP 0x07 +#define DRM_RADEON_CLEAR 0x08 +#define DRM_RADEON_VERTEX 0x09 +#define DRM_RADEON_INDICES 0x0A +#define DRM_RADEON_NOT_USED +#define DRM_RADEON_STIPPLE 0x0C +#define DRM_RADEON_INDIRECT 0x0D +#define DRM_RADEON_TEXTURE 0x0E +#define DRM_RADEON_VERTEX2 0x0F +#define DRM_RADEON_CMDBUF 0x10 +#define DRM_RADEON_GETPARAM 0x11 +#define DRM_RADEON_FLIP 0x12 +#define DRM_RADEON_ALLOC 0x13 +#define DRM_RADEON_FREE 0x14 +#define DRM_RADEON_INIT_HEAP 0x15 +#define DRM_RADEON_IRQ_EMIT 0x16 +#define DRM_RADEON_IRQ_WAIT 0x17 +#define DRM_RADEON_CP_RESUME 0x18 +#define DRM_RADEON_SETPARAM 0x19 +#define DRM_RADEON_SURF_ALLOC 0x1a +#define DRM_RADEON_SURF_FREE 0x1b +/* KMS ioctl */ +#define DRM_RADEON_GEM_INFO 0x1c +#define DRM_RADEON_GEM_CREATE 0x1d +#define DRM_RADEON_GEM_MMAP 0x1e +#define DRM_RADEON_GEM_PREAD 0x21 +#define DRM_RADEON_GEM_PWRITE 0x22 +#define DRM_RADEON_GEM_SET_DOMAIN 0x23 +#define DRM_RADEON_GEM_WAIT_IDLE 0x24 +#define DRM_RADEON_CS 0x26 +#define DRM_RADEON_INFO 0x27 +#define DRM_RADEON_GEM_SET_TILING 0x28 +#define DRM_RADEON_GEM_GET_TILING 0x29 +#define DRM_RADEON_GEM_BUSY 0x2a +#define DRM_RADEON_GEM_VA 0x2b +#define DRM_RADEON_GEM_OP 0x2c +#define DRM_RADEON_GEM_USERPTR 0x2d + +#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) +#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) +#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) +#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET) +#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE) +#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t) +#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP) +#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t) +#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t) +#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME) +#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) +#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) +#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) +/* KMS */ +#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info) +#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create) +#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap) +#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) +#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) +#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) +#define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) +#define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) +#define DRM_IOCTL_RADEON_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling) +#define DRM_IOCTL_RADEON_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling) +#define DRM_IOCTL_RADEON_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy) +#define DRM_IOCTL_RADEON_GEM_VA DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_VA, struct drm_radeon_gem_va) +#define DRM_IOCTL_RADEON_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_OP, struct drm_radeon_gem_op) +#define DRM_IOCTL_RADEON_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_USERPTR, struct drm_radeon_gem_userptr) + +typedef struct drm_radeon_init { + enum { + RADEON_INIT_CP = 0x01, + RADEON_CLEANUP_CP = 0x02, + RADEON_INIT_R200_CP = 0x03, + RADEON_INIT_R300_CP = 0x04, + RADEON_INIT_R600_CP = 0x05 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cp_mode; + int gart_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long gart_textures_offset; +} drm_radeon_init_t; + +typedef struct drm_radeon_cp_stop { + int flush; + int idle; +} drm_radeon_cp_stop_t; + +typedef struct drm_radeon_fullscreen { + enum { + RADEON_INIT_FULLSCREEN = 0x01, + RADEON_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_radeon_fullscreen_t; + +#define CLEAR_X1 0 +#define CLEAR_Y1 1 +#define CLEAR_X2 2 +#define CLEAR_Y2 3 +#define CLEAR_DEPTH 4 + +typedef union drm_radeon_clear_rect { + float f[5]; + unsigned int ui[5]; +} drm_radeon_clear_rect_t; + +typedef struct drm_radeon_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ + drm_radeon_clear_rect_t *depth_boxes; +} drm_radeon_clear_t; + +typedef struct drm_radeon_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_radeon_vertex_t; + +typedef struct drm_radeon_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_radeon_indices_t; + +/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices + * - allows multiple primitives and state changes in a single ioctl + * - supports driver change to emit native primitives + */ +typedef struct drm_radeon_vertex2 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t *state; + int nr_prims; + drm_radeon_prim_t *prim; +} drm_radeon_vertex2_t; + +/* v1.3 - obsoletes drm_radeon_vertex2 + * - allows arbitrarily large cliprect list + * - allows updating of tcl packet, vector and scalar state + * - allows memory-efficient description of state updates + * - allows state to be emitted without a primitive + * (for clears, ctx switches) + * - allows more than one dma buffer to be referenced per ioctl + * - supports tcl driver + * - may be extended in future versions with new cmd types, packets + */ +typedef struct drm_radeon_cmd_buffer { + int bufsz; + char *buf; + int nbox; + struct drm_clip_rect *boxes; +} drm_radeon_cmd_buffer_t; + +typedef struct drm_radeon_tex_image { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + const void *data; +} drm_radeon_tex_image_t; + +typedef struct drm_radeon_texture { + unsigned int offset; + int pitch; + int format; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t *image; +} drm_radeon_texture_t; + +typedef struct drm_radeon_stipple { + unsigned int *mask; +} drm_radeon_stipple_t; + +typedef struct drm_radeon_indirect { + int idx; + int start; + int end; + int discard; +} drm_radeon_indirect_t; + +/* enum for card type parameters */ +#define RADEON_CARD_PCI 0 +#define RADEON_CARD_AGP 1 +#define RADEON_CARD_PCIE 2 + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +/* Added with DRM version 1.6. */ +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ +/* Added with DRM version 1.8. */ +#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ +#define RADEON_PARAM_STATUS_HANDLE 8 +#define RADEON_PARAM_SAREA_HANDLE 9 +#define RADEON_PARAM_GART_TEX_HANDLE 10 +#define RADEON_PARAM_SCRATCH_OFFSET 11 +#define RADEON_PARAM_CARD_TYPE 12 +#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ +#define RADEON_PARAM_FB_LOCATION 14 /* FB location */ +#define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ +#define RADEON_PARAM_DEVICE_ID 16 +#define RADEON_PARAM_NUM_Z_PIPES 17 /* num Z pipes */ + +typedef struct drm_radeon_getparam { + int param; + void *value; +} drm_radeon_getparam_t; + +/* 1.6: Set up a memory manager for regions of shared memory: + */ +#define RADEON_MEM_REGION_GART 1 +#define RADEON_MEM_REGION_FB 2 + +typedef struct drm_radeon_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or GART */ +} drm_radeon_mem_alloc_t; + +typedef struct drm_radeon_mem_free { + int region; + int region_offset; +} drm_radeon_mem_free_t; + +typedef struct drm_radeon_mem_init_heap { + int region; + int size; + int start; +} drm_radeon_mem_init_heap_t; + +/* 1.6: Userspace can request & wait on irq's: + */ +typedef struct drm_radeon_irq_emit { + int *irq_seq; +} drm_radeon_irq_emit_t; + +typedef struct drm_radeon_irq_wait { + int irq_seq; +} drm_radeon_irq_wait_t; + +/* 1.10: Clients tell the DRM where they think the framebuffer is located in + * the card's address space, via a new generic ioctl to set parameters + */ + +typedef struct drm_radeon_setparam { + unsigned int param; + __s64 value; +} drm_radeon_setparam_t; + +#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ +#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ +#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ +#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ +/* 1.14: Clients can allocate/free a surface + */ +typedef struct drm_radeon_surface_alloc { + unsigned int address; + unsigned int size; + unsigned int flags; +} drm_radeon_surface_alloc_t; + +typedef struct drm_radeon_surface_free { + unsigned int address; +} drm_radeon_surface_free_t; + +#define DRM_RADEON_VBLANK_CRTC1 1 +#define DRM_RADEON_VBLANK_CRTC2 2 + +/* + * Kernel modesetting world below. + */ +#define RADEON_GEM_DOMAIN_CPU 0x1 +#define RADEON_GEM_DOMAIN_GTT 0x2 +#define RADEON_GEM_DOMAIN_VRAM 0x4 + +struct drm_radeon_gem_info { + __u64 gart_size; + __u64 vram_size; + __u64 vram_visible; +}; + +#define RADEON_GEM_NO_BACKING_STORE (1 << 0) +#define RADEON_GEM_GTT_UC (1 << 1) +#define RADEON_GEM_GTT_WC (1 << 2) +/* BO is expected to be accessed by the CPU */ +#define RADEON_GEM_CPU_ACCESS (1 << 3) +/* CPU access is not expected to work for this BO */ +#define RADEON_GEM_NO_CPU_ACCESS (1 << 4) + +struct drm_radeon_gem_create { + __u64 size; + __u64 alignment; + __u32 handle; + __u32 initial_domain; + __u32 flags; +}; + +/* + * This is not a reliable API and you should expect it to fail for any + * number of reasons and have fallback path that do not use userptr to + * perform any operation. + */ +#define RADEON_GEM_USERPTR_READONLY (1 << 0) +#define RADEON_GEM_USERPTR_ANONONLY (1 << 1) +#define RADEON_GEM_USERPTR_VALIDATE (1 << 2) +#define RADEON_GEM_USERPTR_REGISTER (1 << 3) + +struct drm_radeon_gem_userptr { + __u64 addr; + __u64 size; + __u32 flags; + __u32 handle; +}; + +#define RADEON_TILING_MACRO 0x1 +#define RADEON_TILING_MICRO 0x2 +#define RADEON_TILING_SWAP_16BIT 0x4 +#define RADEON_TILING_R600_NO_SCANOUT RADEON_TILING_SWAP_16BIT +#define RADEON_TILING_SWAP_32BIT 0x8 +/* this object requires a surface when mapped - i.e. front buffer */ +#define RADEON_TILING_SURFACE 0x10 +#define RADEON_TILING_MICRO_SQUARE 0x20 +#define RADEON_TILING_EG_BANKW_SHIFT 8 +#define RADEON_TILING_EG_BANKW_MASK 0xf +#define RADEON_TILING_EG_BANKH_SHIFT 12 +#define RADEON_TILING_EG_BANKH_MASK 0xf +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT 16 +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK 0xf +#define RADEON_TILING_EG_TILE_SPLIT_SHIFT 24 +#define RADEON_TILING_EG_TILE_SPLIT_MASK 0xf +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT 28 +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf + +struct drm_radeon_gem_set_tiling { + __u32 handle; + __u32 tiling_flags; + __u32 pitch; +}; + +struct drm_radeon_gem_get_tiling { + __u32 handle; + __u32 tiling_flags; + __u32 pitch; +}; + +struct drm_radeon_gem_mmap { + __u32 handle; + __u32 pad; + __u64 offset; + __u64 size; + __u64 addr_ptr; +}; + +struct drm_radeon_gem_set_domain { + __u32 handle; + __u32 read_domains; + __u32 write_domain; +}; + +struct drm_radeon_gem_wait_idle { + __u32 handle; + __u32 pad; +}; + +struct drm_radeon_gem_busy { + __u32 handle; + __u32 domain; +}; + +struct drm_radeon_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** Pointer to write the data into. */ + /* void *, but pointers are not 32/64 compatible */ + __u64 data_ptr; +}; + +struct drm_radeon_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** Pointer to read the data from. */ + /* void *, but pointers are not 32/64 compatible */ + __u64 data_ptr; +}; + +/* Sets or returns a value associated with a buffer. */ +struct drm_radeon_gem_op { + __u32 handle; /* buffer */ + __u32 op; /* RADEON_GEM_OP_* */ + __u64 value; /* input or return value */ +}; + +#define RADEON_GEM_OP_GET_INITIAL_DOMAIN 0 +#define RADEON_GEM_OP_SET_INITIAL_DOMAIN 1 + +#define RADEON_VA_MAP 1 +#define RADEON_VA_UNMAP 2 + +#define RADEON_VA_RESULT_OK 0 +#define RADEON_VA_RESULT_ERROR 1 +#define RADEON_VA_RESULT_VA_EXIST 2 + +#define RADEON_VM_PAGE_VALID (1 << 0) +#define RADEON_VM_PAGE_READABLE (1 << 1) +#define RADEON_VM_PAGE_WRITEABLE (1 << 2) +#define RADEON_VM_PAGE_SYSTEM (1 << 3) +#define RADEON_VM_PAGE_SNOOPED (1 << 4) + +struct drm_radeon_gem_va { + __u32 handle; + __u32 operation; + __u32 vm_id; + __u32 flags; + __u64 offset; +}; + +#define RADEON_CHUNK_ID_RELOCS 0x01 +#define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_FLAGS 0x03 +#define RADEON_CHUNK_ID_CONST_IB 0x04 + +/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ +#define RADEON_CS_KEEP_TILING_FLAGS 0x01 +#define RADEON_CS_USE_VM 0x02 +#define RADEON_CS_END_OF_FRAME 0x04 /* a hint from userspace which CS is the last one */ +/* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */ +#define RADEON_CS_RING_GFX 0 +#define RADEON_CS_RING_COMPUTE 1 +#define RADEON_CS_RING_DMA 2 +#define RADEON_CS_RING_UVD 3 +#define RADEON_CS_RING_VCE 4 +/* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ +/* 0 = normal, + = higher priority, - = lower priority */ + +struct drm_radeon_cs_chunk { + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; +}; + +/* drm_radeon_cs_reloc.flags */ +#define RADEON_RELOC_PRIO_MASK (0xf << 0) + +struct drm_radeon_cs_reloc { + __u32 handle; + __u32 read_domains; + __u32 write_domain; + __u32 flags; +}; + +struct drm_radeon_cs { + __u32 num_chunks; + __u32 cs_id; + /* this points to __u64 * which point to cs chunks */ + __u64 chunks; + /* updates to the limits after this CS ioctl */ + __u64 gart_limit; + __u64 vram_limit; +}; + +#define RADEON_INFO_DEVICE_ID 0x00 +#define RADEON_INFO_NUM_GB_PIPES 0x01 +#define RADEON_INFO_NUM_Z_PIPES 0x02 +#define RADEON_INFO_ACCEL_WORKING 0x03 +#define RADEON_INFO_CRTC_FROM_ID 0x04 +#define RADEON_INFO_ACCEL_WORKING2 0x05 +#define RADEON_INFO_TILING_CONFIG 0x06 +#define RADEON_INFO_WANT_HYPERZ 0x07 +#define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ +#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ +#define RADEON_INFO_NUM_BACKENDS 0x0a /* DB/backends for r600+ - need for OQ */ +#define RADEON_INFO_NUM_TILE_PIPES 0x0b /* tile pipes for r600+ */ +#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ +#define RADEON_INFO_BACKEND_MAP 0x0d /* pipe to backend map, needed by mesa */ +/* virtual address start, va < start are reserved by the kernel */ +#define RADEON_INFO_VA_START 0x0e +/* maximum size of ib using the virtual memory cs */ +#define RADEON_INFO_IB_VM_MAX_SIZE 0x0f +/* max pipes - needed for compute shaders */ +#define RADEON_INFO_MAX_PIPES 0x10 +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ +#define RADEON_INFO_TIMESTAMP 0x11 +/* max shader engines (SE) - needed for geometry shaders, etc. */ +#define RADEON_INFO_MAX_SE 0x12 +/* max SH per SE */ +#define RADEON_INFO_MAX_SH_PER_SE 0x13 +/* fast fb access is enabled */ +#define RADEON_INFO_FASTFB_WORKING 0x14 +/* query if a RADEON_CS_RING_* submission is supported */ +#define RADEON_INFO_RING_WORKING 0x15 +/* SI tile mode array */ +#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16 +/* query if CP DMA is supported on the compute ring */ +#define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17 +/* CIK macrotile mode array */ +#define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY 0x18 +/* query the number of render backends */ +#define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19 +/* max engine clock - needed for OpenCL */ +#define RADEON_INFO_MAX_SCLK 0x1a +/* version of VCE firmware */ +#define RADEON_INFO_VCE_FW_VERSION 0x1b +/* version of VCE feedback */ +#define RADEON_INFO_VCE_FB_VERSION 0x1c +#define RADEON_INFO_NUM_BYTES_MOVED 0x1d +#define RADEON_INFO_VRAM_USAGE 0x1e +#define RADEON_INFO_GTT_USAGE 0x1f +#define RADEON_INFO_ACTIVE_CU_COUNT 0x20 +#define RADEON_INFO_CURRENT_GPU_TEMP 0x21 +#define RADEON_INFO_CURRENT_GPU_SCLK 0x22 +#define RADEON_INFO_CURRENT_GPU_MCLK 0x23 +#define RADEON_INFO_READ_REG 0x24 +#define RADEON_INFO_VA_UNMAP_WORKING 0x25 +#define RADEON_INFO_GPU_RESET_COUNTER 0x26 + +struct drm_radeon_info { + __u32 request; + __u32 pad; + __u64 value; +}; + +/* Those correspond to the tile index to use, this is to explicitly state + * the API that is implicitly defined by the tile mode array. + */ +#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8 +#define SI_TILE_MODE_COLOR_1D 13 +#define SI_TILE_MODE_COLOR_1D_SCANOUT 9 +#define SI_TILE_MODE_COLOR_2D_8BPP 14 +#define SI_TILE_MODE_COLOR_2D_16BPP 15 +#define SI_TILE_MODE_COLOR_2D_32BPP 16 +#define SI_TILE_MODE_COLOR_2D_64BPP 17 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12 +#define SI_TILE_MODE_DEPTH_STENCIL_1D 4 +#define SI_TILE_MODE_DEPTH_STENCIL_2D 0 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2 + +#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5 + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/savage_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/savage_drm.h new file mode 100644 index 0000000..1a91234 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/savage_drm.h @@ -0,0 +1,220 @@ +/* savage_drm.h -- Public header for the savage driver + * + * Copyright 2004 Felix Kuehling + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SAVAGE_DRM_H__ +#define __SAVAGE_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef __SAVAGE_SAREA_DEFINES__ +#define __SAVAGE_SAREA_DEFINES__ + +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define SAVAGE_CARD_HEAP 0 +#define SAVAGE_AGP_HEAP 1 +#define SAVAGE_NR_TEX_HEAPS 2 +#define SAVAGE_NR_TEX_REGIONS 16 +#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16 + +#endif /* __SAVAGE_SAREA_DEFINES__ */ + +typedef struct _drm_savage_sarea { + /* LRU lists for texture memory in agp space and on the card. + */ + struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS + + 1]; + unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_savage_sarea_t, *drm_savage_sarea_ptr; + +/* Savage-specific ioctls + */ +#define DRM_SAVAGE_BCI_INIT 0x00 +#define DRM_SAVAGE_BCI_CMDBUF 0x01 +#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 +#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 + +#define DRM_IOCTL_SAVAGE_BCI_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) +#define DRM_IOCTL_SAVAGE_BCI_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) + +#define SAVAGE_DMA_PCI 1 +#define SAVAGE_DMA_AGP 3 +typedef struct drm_savage_init { + enum { + SAVAGE_INIT_BCI = 1, + SAVAGE_CLEANUP_BCI = 2 + } func; + unsigned int sarea_priv_offset; + + /* some parameters */ + unsigned int cob_size; + unsigned int bci_threshold_lo, bci_threshold_hi; + unsigned int dma_type; + + /* frame buffer layout */ + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + /* local textures */ + unsigned int texture_offset; + unsigned int texture_size; + + /* physical locations of non-permanent maps */ + unsigned long status_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; + unsigned long cmd_dma_offset; +} drm_savage_init_t; + +typedef union drm_savage_cmd_header drm_savage_cmd_header_t; +typedef struct drm_savage_cmdbuf { + /* command buffer in client's address space */ + drm_savage_cmd_header_t *cmd_addr; + unsigned int size; /* size of the command buffer in 64bit units */ + + unsigned int dma_idx; /* DMA buffer index to use */ + int discard; /* discard DMA buffer when done */ + /* vertex buffer in client's address space */ + unsigned int *vb_addr; + unsigned int vb_size; /* size of client vertex buffer in bytes */ + unsigned int vb_stride; /* stride of vertices in 32bit words */ + /* boxes in client's address space */ + struct drm_clip_rect *box_addr; + unsigned int nbox; /* number of clipping boxes */ +} drm_savage_cmdbuf_t; + +#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */ +#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */ +#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */ +typedef struct drm_savage_event { + unsigned int count; + unsigned int flags; +} drm_savage_event_emit_t, drm_savage_event_wait_t; + +/* Commands for the cmdbuf ioctl + */ +#define SAVAGE_CMD_STATE 0 /* a range of state registers */ +#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */ +#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */ +#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */ +#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */ +#define SAVAGE_CMD_CLEAR 5 /* clear buffers */ +#define SAVAGE_CMD_SWAP 6 /* swap buffers */ + +/* Primitive types +*/ +#define SAVAGE_PRIM_TRILIST 0 /* triangle list */ +#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */ +#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */ +#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat + * shading on s3d */ + +/* Skip flags (vertex format) + */ +#define SAVAGE_SKIP_Z 0x01 +#define SAVAGE_SKIP_W 0x02 +#define SAVAGE_SKIP_C0 0x04 +#define SAVAGE_SKIP_C1 0x08 +#define SAVAGE_SKIP_S0 0x10 +#define SAVAGE_SKIP_T0 0x20 +#define SAVAGE_SKIP_ST0 0x30 +#define SAVAGE_SKIP_S1 0x40 +#define SAVAGE_SKIP_T1 0x80 +#define SAVAGE_SKIP_ST1 0xc0 +#define SAVAGE_SKIP_ALL_S3D 0x3f +#define SAVAGE_SKIP_ALL_S4 0xff + +/* Buffer names for clear command + */ +#define SAVAGE_FRONT 0x1 +#define SAVAGE_BACK 0x2 +#define SAVAGE_DEPTH 0x4 + +/* 64-bit command header + */ +union drm_savage_cmd_header { + struct { + unsigned char cmd; /* command */ + unsigned char pad0; + unsigned short pad1; + unsigned short pad2; + unsigned short pad3; + } cmd; /* generic */ + struct { + unsigned char cmd; + unsigned char global; /* need idle engine? */ + unsigned short count; /* number of consecutive registers */ + unsigned short start; /* first register */ + unsigned short pad3; + } state; /* SAVAGE_CMD_STATE */ + struct { + unsigned char cmd; + unsigned char prim; /* primitive type */ + unsigned short skip; /* vertex format (skip flags) */ + unsigned short count; /* number of vertices */ + unsigned short start; /* first vertex in DMA/vertex buffer */ + } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */ + struct { + unsigned char cmd; + unsigned char prim; + unsigned short skip; + unsigned short count; /* number of indices that follow */ + unsigned short pad3; + } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */ + struct { + unsigned char cmd; + unsigned char pad0; + unsigned short pad1; + unsigned int flags; + } clear0; /* SAVAGE_CMD_CLEAR */ + struct { + unsigned int mask; + unsigned int value; + } clear1; /* SAVAGE_CMD_CLEAR data */ +}; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/sis_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/sis_drm.h new file mode 100644 index 0000000..8e51bb9 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/sis_drm.h @@ -0,0 +1,77 @@ +/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ +/* + * Copyright 2005 Eric Anholt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __SIS_DRM_H__ +#define __SIS_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* SiS specific ioctls */ +#define NOT_USED_0_3 +#define DRM_SIS_FB_ALLOC 0x04 +#define DRM_SIS_FB_FREE 0x05 +#define NOT_USED_6_12 +#define DRM_SIS_AGP_INIT 0x13 +#define DRM_SIS_AGP_ALLOC 0x14 +#define DRM_SIS_AGP_FREE 0x15 +#define DRM_SIS_FB_INIT 0x16 + +#define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t) +#define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t) +/* +#define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t) +#define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49) +#define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50) +*/ + +typedef struct { + int context; + unsigned int offset; + unsigned int size; + unsigned long free; +} drm_sis_mem_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_agp_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_fb_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* __SIS_DRM_H__ */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/tegra_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/tegra_drm.h new file mode 100644 index 0000000..6c07919 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/tegra_drm.h @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) +#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) + +/** + * struct drm_tegra_gem_create - parameters for the GEM object creation IOCTL + */ +struct drm_tegra_gem_create { + /** + * @size: + * + * The size, in bytes, of the buffer object to be created. + */ + __u64 size; + + /** + * @flags: + * + * A bitmask of flags that influence the creation of GEM objects: + * + * DRM_TEGRA_GEM_CREATE_TILED + * Use the 16x16 tiling format for this buffer. + * + * DRM_TEGRA_GEM_CREATE_BOTTOM_UP + * The buffer has a bottom-up layout. + */ + __u32 flags; + + /** + * @handle: + * + * The handle of the created GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u32 handle; +}; + +/** + * struct drm_tegra_gem_mmap - parameters for the GEM mmap IOCTL + */ +struct drm_tegra_gem_mmap { + /** + * @handle: + * + * Handle of the GEM object to obtain an mmap offset for. + */ + __u32 handle; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; + + /** + * @offset: + * + * The mmap offset for the given GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u64 offset; +}; + +/** + * struct drm_tegra_syncpt_read - parameters for the read syncpoint IOCTL + */ +struct drm_tegra_syncpt_read { + /** + * @id: + * + * ID of the syncpoint to read the current value from. + */ + __u32 id; + + /** + * @value: + * + * The current syncpoint value. Set by the kernel upon successful + * completion of the IOCTL. + */ + __u32 value; +}; + +/** + * struct drm_tegra_syncpt_incr - parameters for the increment syncpoint IOCTL + */ +struct drm_tegra_syncpt_incr { + /** + * @id: + * + * ID of the syncpoint to increment. + */ + __u32 id; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_syncpt_wait - parameters for the wait syncpoint IOCTL + */ +struct drm_tegra_syncpt_wait { + /** + * @id: + * + * ID of the syncpoint to wait on. + */ + __u32 id; + + /** + * @thresh: + * + * Threshold value for which to wait. + */ + __u32 thresh; + + /** + * @timeout: + * + * Timeout, in milliseconds, to wait. + */ + __u32 timeout; + + /** + * @value: + * + * The new syncpoint value after the wait. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u32 value; +}; + +#define DRM_TEGRA_NO_TIMEOUT (0xffffffff) + +/** + * struct drm_tegra_open_channel - parameters for the open channel IOCTL + */ +struct drm_tegra_open_channel { + /** + * @client: + * + * The client ID for this channel. + */ + __u32 client; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; + + /** + * @context: + * + * The application context of this channel. Set by the kernel upon + * successful completion of the IOCTL. This context needs to be passed + * to the DRM_TEGRA_CHANNEL_CLOSE or the DRM_TEGRA_SUBMIT IOCTLs. + */ + __u64 context; +}; + +/** + * struct drm_tegra_close_channel - parameters for the close channel IOCTL + */ +struct drm_tegra_close_channel { + /** + * @context: + * + * The application context of this channel. This is obtained from the + * DRM_TEGRA_OPEN_CHANNEL IOCTL. + */ + __u64 context; +}; + +/** + * struct drm_tegra_get_syncpt - parameters for the get syncpoint IOCTL + */ +struct drm_tegra_get_syncpt { + /** + * @context: + * + * The application context identifying the channel for which to obtain + * the syncpoint ID. + */ + __u64 context; + + /** + * @index: + * + * Index of the client syncpoint for which to obtain the ID. + */ + __u32 index; + + /** + * @id: + * + * The ID of the given syncpoint. Set by the kernel upon successful + * completion of the IOCTL. + */ + __u32 id; +}; + +/** + * struct drm_tegra_get_syncpt_base - parameters for the get wait base IOCTL + */ +struct drm_tegra_get_syncpt_base { + /** + * @context: + * + * The application context identifying for which channel to obtain the + * wait base. + */ + __u64 context; + + /** + * @syncpt: + * + * ID of the syncpoint for which to obtain the wait base. + */ + __u32 syncpt; + + /** + * @id: + * + * The ID of the wait base corresponding to the client syncpoint. Set + * by the kernel upon successful completion of the IOCTL. + */ + __u32 id; +}; + +/** + * struct drm_tegra_syncpt - syncpoint increment operation + */ +struct drm_tegra_syncpt { + /** + * @id: + * + * ID of the syncpoint to operate on. + */ + __u32 id; + + /** + * @incrs: + * + * Number of increments to perform for the syncpoint. + */ + __u32 incrs; +}; + +/** + * struct drm_tegra_cmdbuf - structure describing a command buffer + */ +struct drm_tegra_cmdbuf { + /** + * @handle: + * + * Handle to a GEM object containing the command buffer. + */ + __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, into the GEM object identified by @handle at + * which the command buffer starts. + */ + __u32 offset; + + /** + * @words: + * + * Number of 32-bit words in this command buffer. + */ + __u32 words; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_reloc - GEM object relocation structure + */ +struct drm_tegra_reloc { + struct { + /** + * @cmdbuf.handle: + * + * Handle to the GEM object containing the command buffer for + * which to perform this GEM object relocation. + */ + __u32 handle; + + /** + * @cmdbuf.offset: + * + * Offset, in bytes, into the command buffer at which to + * insert the relocated address. + */ + __u32 offset; + } cmdbuf; + struct { + /** + * @target.handle: + * + * Handle to the GEM object to be relocated. + */ + __u32 handle; + + /** + * @target.offset: + * + * Offset, in bytes, into the target GEM object at which the + * relocated data starts. + */ + __u32 offset; + } target; + + /** + * @shift: + * + * The number of bits by which to shift relocated addresses. + */ + __u32 shift; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_waitchk - wait check structure + */ +struct drm_tegra_waitchk { + /** + * @handle: + * + * Handle to the GEM object containing a command stream on which to + * perform the wait check. + */ + __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, of the location in the command stream to perform + * the wait check on. + */ + __u32 offset; + + /** + * @syncpt: + * + * ID of the syncpoint to wait check. + */ + __u32 syncpt; + + /** + * @thresh: + * + * Threshold value for which to check. + */ + __u32 thresh; +}; + +/** + * struct drm_tegra_submit - job submission structure + */ +struct drm_tegra_submit { + /** + * @context: + * + * The application context identifying the channel to use for the + * execution of this job. + */ + __u64 context; + + /** + * @num_syncpts: + * + * The number of syncpoints operated on by this job. This defines the + * length of the array pointed to by @syncpts. + */ + __u32 num_syncpts; + + /** + * @num_cmdbufs: + * + * The number of command buffers to execute as part of this job. This + * defines the length of the array pointed to by @cmdbufs. + */ + __u32 num_cmdbufs; + + /** + * @num_relocs: + * + * The number of relocations to perform before executing this job. + * This defines the length of the array pointed to by @relocs. + */ + __u32 num_relocs; + + /** + * @num_waitchks: + * + * The number of wait checks to perform as part of this job. This + * defines the length of the array pointed to by @waitchks. + */ + __u32 num_waitchks; + + /** + * @waitchk_mask: + * + * Bitmask of valid wait checks. + */ + __u32 waitchk_mask; + + /** + * @timeout: + * + * Timeout, in milliseconds, before this job is cancelled. + */ + __u32 timeout; + + /** + * @syncpts: + * + * A pointer to an array of &struct drm_tegra_syncpt structures that + * specify the syncpoint operations performed as part of this job. + * The number of elements in the array must be equal to the value + * given by @num_syncpts. + */ + __u64 syncpts; + + /** + * @cmdbufs: + * + * A pointer to an array of &struct drm_tegra_cmdbuf structures that + * define the command buffers to execute as part of this job. The + * number of elements in the array must be equal to the value given + * by @num_syncpts. + */ + __u64 cmdbufs; + + /** + * @relocs: + * + * A pointer to an array of &struct drm_tegra_reloc structures that + * specify the relocations that need to be performed before executing + * this job. The number of elements in the array must be equal to the + * value given by @num_relocs. + */ + __u64 relocs; + + /** + * @waitchks: + * + * A pointer to an array of &struct drm_tegra_waitchk structures that + * specify the wait checks to be performed while executing this job. + * The number of elements in the array must be equal to the value + * given by @num_waitchks. + */ + __u64 waitchks; + + /** + * @fence: + * + * The threshold of the syncpoint associated with this job after it + * has been completed. Set by the kernel upon successful completion of + * the IOCTL. This can be used with the DRM_TEGRA_SYNCPT_WAIT IOCTL to + * wait for this job to be finished. + */ + __u32 fence; + + /** + * @reserved: + * + * This field is reserved for future use. Must be 0. + */ + __u32 reserved[5]; +}; + +#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 +#define DRM_TEGRA_GEM_TILING_MODE_TILED 1 +#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 + +/** + * struct drm_tegra_gem_set_tiling - parameters for the set tiling IOCTL + */ +struct drm_tegra_gem_set_tiling { + /** + * @handle: + * + * Handle to the GEM object for which to set the tiling parameters. + */ + __u32 handle; + + /** + * @mode: + * + * The tiling mode to set. Must be one of: + * + * DRM_TEGRA_GEM_TILING_MODE_PITCH + * pitch linear format + * + * DRM_TEGRA_GEM_TILING_MODE_TILED + * 16x16 tiling format + * + * DRM_TEGRA_GEM_TILING_MODE_BLOCK + * 16Bx2 tiling format + */ + __u32 mode; + + /** + * @value: + * + * The value to set for the tiling mode parameter. + */ + __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_gem_get_tiling - parameters for the get tiling IOCTL + */ +struct drm_tegra_gem_get_tiling { + /** + * @handle: + * + * Handle to the GEM object for which to query the tiling parameters. + */ + __u32 handle; + + /** + * @mode: + * + * The tiling mode currently associated with the GEM object. Set by + * the kernel upon successful completion of the IOCTL. + */ + __u32 mode; + + /** + * @value: + * + * The tiling mode parameter currently associated with the GEM object. + * Set by the kernel upon successful completion of the IOCTL. + */ + __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) +#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) + +/** + * struct drm_tegra_gem_set_flags - parameters for the set flags IOCTL + */ +struct drm_tegra_gem_set_flags { + /** + * @handle: + * + * Handle to the GEM object for which to set the flags. + */ + __u32 handle; + + /** + * @flags: + * + * The flags to set for the GEM object. + */ + __u32 flags; +}; + +/** + * struct drm_tegra_gem_get_flags - parameters for the get flags IOCTL + */ +struct drm_tegra_gem_get_flags { + /** + * @handle: + * + * Handle to the GEM object for which to query the flags. + */ + __u32 handle; + + /** + * @flags: + * + * The flags currently associated with the GEM object. Set by the + * kernel upon successful completion of the IOCTL. + */ + __u32 flags; +}; + +#define DRM_TEGRA_GEM_CREATE 0x00 +#define DRM_TEGRA_GEM_MMAP 0x01 +#define DRM_TEGRA_SYNCPT_READ 0x02 +#define DRM_TEGRA_SYNCPT_INCR 0x03 +#define DRM_TEGRA_SYNCPT_WAIT 0x04 +#define DRM_TEGRA_OPEN_CHANNEL 0x05 +#define DRM_TEGRA_CLOSE_CHANNEL 0x06 +#define DRM_TEGRA_GET_SYNCPT 0x07 +#define DRM_TEGRA_SUBMIT 0x08 +#define DRM_TEGRA_GET_SYNCPT_BASE 0x09 +#define DRM_TEGRA_GEM_SET_TILING 0x0a +#define DRM_TEGRA_GEM_GET_TILING 0x0b +#define DRM_TEGRA_GEM_SET_FLAGS 0x0c +#define DRM_TEGRA_GEM_GET_FLAGS 0x0d + +#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) +#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) +#define DRM_IOCTL_TEGRA_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_READ, struct drm_tegra_syncpt_read) +#define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr) +#define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait) +#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel) +#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) +#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) +#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) +#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) +#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) +#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) +#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/vc4_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/vc4_drm.h new file mode 100644 index 0000000..31f50de --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/vc4_drm.h @@ -0,0 +1,442 @@ +/* + * Copyright © 2014-2015 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _VC4_DRM_H_ +#define _VC4_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_VC4_SUBMIT_CL 0x00 +#define DRM_VC4_WAIT_SEQNO 0x01 +#define DRM_VC4_WAIT_BO 0x02 +#define DRM_VC4_CREATE_BO 0x03 +#define DRM_VC4_MMAP_BO 0x04 +#define DRM_VC4_CREATE_SHADER_BO 0x05 +#define DRM_VC4_GET_HANG_STATE 0x06 +#define DRM_VC4_GET_PARAM 0x07 +#define DRM_VC4_SET_TILING 0x08 +#define DRM_VC4_GET_TILING 0x09 +#define DRM_VC4_LABEL_BO 0x0a +#define DRM_VC4_GEM_MADVISE 0x0b +#define DRM_VC4_PERFMON_CREATE 0x0c +#define DRM_VC4_PERFMON_DESTROY 0x0d +#define DRM_VC4_PERFMON_GET_VALUES 0x0e + +#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) +#define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) +#define DRM_IOCTL_VC4_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_BO, struct drm_vc4_wait_bo) +#define DRM_IOCTL_VC4_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_BO, struct drm_vc4_create_bo) +#define DRM_IOCTL_VC4_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_MMAP_BO, struct drm_vc4_mmap_bo) +#define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo) +#define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state) +#define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param) +#define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling) +#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling) +#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo) +#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise) +#define DRM_IOCTL_VC4_PERFMON_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_CREATE, struct drm_vc4_perfmon_create) +#define DRM_IOCTL_VC4_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_DESTROY, struct drm_vc4_perfmon_destroy) +#define DRM_IOCTL_VC4_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_GET_VALUES, struct drm_vc4_perfmon_get_values) + +struct drm_vc4_submit_rcl_surface { + __u32 hindex; /* Handle index, or ~0 if not present. */ + __u32 offset; /* Offset to start of buffer. */ + /* + * Bits for either render config (color_write) or load/store packet. + * Bits should all be 0 for MSAA load/stores. + */ + __u16 bits; + +#define VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES (1 << 0) + __u16 flags; +}; + +/** + * struct drm_vc4_submit_cl - ioctl argument for submitting commands to the 3D + * engine. + * + * Drivers typically use GPU BOs to store batchbuffers / command lists and + * their associated state. However, because the VC4 lacks an MMU, we have to + * do validation of memory accesses by the GPU commands. If we were to store + * our commands in BOs, we'd need to do uncached readback from them to do the + * validation process, which is too expensive. Instead, userspace accumulates + * commands and associated state in plain memory, then the kernel copies the + * data to its own address space, and then validates and stores it in a GPU + * BO. + */ +struct drm_vc4_submit_cl { + /* Pointer to the binner command list. + * + * This is the first set of commands executed, which runs the + * coordinate shader to determine where primitives land on the screen, + * then writes out the state updates and draw calls necessary per tile + * to the tile allocation BO. + */ + __u64 bin_cl; + + /* Pointer to the shader records. + * + * Shader records are the structures read by the hardware that contain + * pointers to uniforms, shaders, and vertex attributes. The + * reference to the shader record has enough information to determine + * how many pointers are necessary (fixed number for shaders/uniforms, + * and an attribute count), so those BO indices into bo_handles are + * just stored as __u32s before each shader record passed in. + */ + __u64 shader_rec; + + /* Pointer to uniform data and texture handles for the textures + * referenced by the shader. + * + * For each shader state record, there is a set of uniform data in the + * order referenced by the record (FS, VS, then CS). Each set of + * uniform data has a __u32 index into bo_handles per texture + * sample operation, in the order the QPU_W_TMUn_S writes appear in + * the program. Following the texture BO handle indices is the actual + * uniform data. + * + * The individual uniform state blocks don't have sizes passed in, + * because the kernel has to determine the sizes anyway during shader + * code validation. + */ + __u64 uniforms; + __u64 bo_handles; + + /* Size in bytes of the binner command list. */ + __u32 bin_cl_size; + /* Size in bytes of the set of shader records. */ + __u32 shader_rec_size; + /* Number of shader records. + * + * This could just be computed from the contents of shader_records and + * the address bits of references to them from the bin CL, but it + * keeps the kernel from having to resize some allocations it makes. + */ + __u32 shader_rec_count; + /* Size in bytes of the uniform state. */ + __u32 uniforms_size; + + /* Number of BO handles passed in (size is that times 4). */ + __u32 bo_handle_count; + + /* RCL setup: */ + __u16 width; + __u16 height; + __u8 min_x_tile; + __u8 min_y_tile; + __u8 max_x_tile; + __u8 max_y_tile; + struct drm_vc4_submit_rcl_surface color_read; + struct drm_vc4_submit_rcl_surface color_write; + struct drm_vc4_submit_rcl_surface zs_read; + struct drm_vc4_submit_rcl_surface zs_write; + struct drm_vc4_submit_rcl_surface msaa_color_write; + struct drm_vc4_submit_rcl_surface msaa_zs_write; + __u32 clear_color[2]; + __u32 clear_z; + __u8 clear_s; + + __u32 pad:24; + +#define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0) +/* By default, the kernel gets to choose the order that the tiles are + * rendered in. If this is set, then the tiles will be rendered in a + * raster order, with the right-to-left vs left-to-right and + * top-to-bottom vs bottom-to-top dictated by + * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*. This allows overlapping + * blits to be implemented using the 3D engine. + */ +#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3) + __u32 flags; + + /* Returned value of the seqno of this render job (for the + * wait ioctl). + */ + __u64 seqno; + + /* ID of the perfmon to attach to this job. 0 means no perfmon. */ + __u32 perfmonid; + + /* Syncobj handle to wait on. If set, processing of this render job + * will not start until the syncobj is signaled. 0 means ignore. + */ + __u32 in_sync; + + /* Syncobj handle to export fence to. If set, the fence in the syncobj + * will be replaced with a fence that signals upon completion of this + * render job. 0 means ignore. + */ + __u32 out_sync; + + __u32 pad2; +}; + +/** + * struct drm_vc4_wait_seqno - ioctl argument for waiting for + * DRM_VC4_SUBMIT_CL completion using its returned seqno. + * + * timeout_ns is the timeout in nanoseconds, where "0" means "don't + * block, just return the status." + */ +struct drm_vc4_wait_seqno { + __u64 seqno; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_wait_bo - ioctl argument for waiting for + * completion of the last DRM_VC4_SUBMIT_CL on a BO. + * + * This is useful for cases where multiple processes might be + * rendering to a BO and you want to wait for all rendering to be + * completed. + */ +struct drm_vc4_wait_bo { + __u32 handle; + __u32 pad; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_create_bo - ioctl argument for creating VC4 BOs. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_create_bo { + __u32 size; + __u32 flags; + /** Returned GEM handle for the BO. */ + __u32 handle; + __u32 pad; +}; + +/** + * struct drm_vc4_mmap_bo - ioctl argument for mapping VC4 BOs. + * + * This doesn't actually perform an mmap. Instead, it returns the + * offset you need to use in an mmap on the DRM device node. This + * means that tools like valgrind end up knowing about the mapped + * memory. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_mmap_bo { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 flags; + /** offset into the drm node to use for subsequent mmap call. */ + __u64 offset; +}; + +/** + * struct drm_vc4_create_shader_bo - ioctl argument for creating VC4 + * shader BOs. + * + * Since allowing a shader to be overwritten while it's also being + * executed from would allow privlege escalation, shaders must be + * created using this ioctl, and they can't be mmapped later. + */ +struct drm_vc4_create_shader_bo { + /* Size of the data argument. */ + __u32 size; + /* Flags, currently must be 0. */ + __u32 flags; + + /* Pointer to the data. */ + __u64 data; + + /** Returned GEM handle for the BO. */ + __u32 handle; + /* Pad, must be 0. */ + __u32 pad; +}; + +struct drm_vc4_get_hang_state_bo { + __u32 handle; + __u32 paddr; + __u32 size; + __u32 pad; +}; + +/** + * struct drm_vc4_hang_state - ioctl argument for collecting state + * from a GPU hang for analysis. +*/ +struct drm_vc4_get_hang_state { + /** Pointer to array of struct drm_vc4_get_hang_state_bo. */ + __u64 bo; + /** + * On input, the size of the bo array. Output is the number + * of bos to be returned. + */ + __u32 bo_count; + + __u32 start_bin, start_render; + + __u32 ct0ca, ct0ea; + __u32 ct1ca, ct1ea; + __u32 ct0cs, ct1cs; + __u32 ct0ra0, ct1ra0; + + __u32 bpca, bpcs; + __u32 bpoa, bpos; + + __u32 vpmbase; + + __u32 dbge; + __u32 fdbgo; + __u32 fdbgb; + __u32 fdbgr; + __u32 fdbgs; + __u32 errstat; + + /* Pad that we may save more registers into in the future. */ + __u32 pad[16]; +}; + +#define DRM_VC4_PARAM_V3D_IDENT0 0 +#define DRM_VC4_PARAM_V3D_IDENT1 1 +#define DRM_VC4_PARAM_V3D_IDENT2 2 +#define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 +#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 +#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 +#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6 +#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7 +#define DRM_VC4_PARAM_SUPPORTS_PERFMON 8 + +struct drm_vc4_get_param { + __u32 param; + __u32 pad; + __u64 value; +}; + +struct drm_vc4_get_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +struct drm_vc4_set_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +/** + * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes. + */ +struct drm_vc4_label_bo { + __u32 handle; + __u32 len; + __u64 name; +}; + +/* + * States prefixed with '__' are internal states and cannot be passed to the + * DRM_IOCTL_VC4_GEM_MADVISE ioctl. + */ +#define VC4_MADV_WILLNEED 0 +#define VC4_MADV_DONTNEED 1 +#define __VC4_MADV_PURGED 2 +#define __VC4_MADV_NOTSUPP 3 + +struct drm_vc4_gem_madvise { + __u32 handle; + __u32 madv; + __u32 retained; + __u32 pad; +}; + +enum { + VC4_PERFCNT_FEP_VALID_PRIMS_NO_RENDER, + VC4_PERFCNT_FEP_VALID_PRIMS_RENDER, + VC4_PERFCNT_FEP_CLIPPED_QUADS, + VC4_PERFCNT_FEP_VALID_QUADS, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_STENCIL, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_NON_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_WRITTEN_TO_COLOR_BUF, + VC4_PERFCNT_PLB_PRIMS_OUTSIDE_VIEWPORT, + VC4_PERFCNT_PLB_PRIMS_NEED_CLIPPING, + VC4_PERFCNT_PSE_PRIMS_REVERSED, + VC4_PERFCNT_QPU_TOTAL_IDLE_CYCLES, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_VERTEX_COORD_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_FRAGMENT_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_EXEC_VALID_INST, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_TMUS, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_SCOREBOARD, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_VARYINGS, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_MISS, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_MISS, + VC4_PERFCNT_TMU_TOTAL_TEXT_QUADS_PROCESSED, + VC4_PERFCNT_TMU_TOTAL_TEXT_CACHE_MISS, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VDW_STALLED, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VCD_STALLED, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_HIT, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_MISS, + VC4_PERFCNT_NUM_EVENTS, +}; + +#define DRM_VC4_MAX_PERF_COUNTERS 16 + +struct drm_vc4_perfmon_create { + __u32 id; + __u32 ncounters; + __u8 events[DRM_VC4_MAX_PERF_COUNTERS]; +}; + +struct drm_vc4_perfmon_destroy { + __u32 id; +}; + +/* + * Returns the values of the performance counters tracked by this + * perfmon (as an array of ncounters u64 values). + * + * No implicit synchronization is performed, so the user has to + * guarantee that any jobs using this perfmon have already been + * completed (probably by blocking on the seqno returned by the + * last exec that used the perfmon). + */ +struct drm_vc4_perfmon_get_values { + __u32 id; + __u64 values_ptr; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _VC4_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/via_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/via_drm.h new file mode 100644 index 0000000..8b69e81 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/via_drm.h @@ -0,0 +1,283 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_DRM_H_ +#define _VIA_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_DEFINES_ +#define _VIA_DEFINES_ + +#include "via_drmclient.h" + +#define VIA_NR_SAREA_CLIPRECTS 8 +#define VIA_NR_XVMC_PORTS 10 +#define VIA_NR_XVMC_LOCKS 5 +#define VIA_MAX_CACHELINE_SIZE 64 +#define XVMCLOCKPTR(saPriv,lockNo) \ + ((__volatile__ struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ + (VIA_MAX_CACHELINE_SIZE - 1)) & \ + ~(VIA_MAX_CACHELINE_SIZE - 1)) + \ + VIA_MAX_CACHELINE_SIZE*(lockNo))) + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_NR_TEX_REGIONS 64 +#define VIA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_UPLOAD_CTX 0x4 +#define VIA_UPLOAD_BUFFERS 0x8 +#define VIA_UPLOAD_TEX0 0x10 +#define VIA_UPLOAD_TEX1 0x20 +#define VIA_UPLOAD_CLIPRECTS 0x40 +#define VIA_UPLOAD_ALL 0xff + +/* VIA specific ioctls */ +#define DRM_VIA_ALLOCMEM 0x00 +#define DRM_VIA_FREEMEM 0x01 +#define DRM_VIA_AGP_INIT 0x02 +#define DRM_VIA_FB_INIT 0x03 +#define DRM_VIA_MAP_INIT 0x04 +#define DRM_VIA_DEC_FUTEX 0x05 +#define NOT_USED +#define DRM_VIA_DMA_INIT 0x07 +#define DRM_VIA_CMDBUFFER 0x08 +#define DRM_VIA_FLUSH 0x09 +#define DRM_VIA_PCICMD 0x0a +#define DRM_VIA_CMDBUF_SIZE 0x0b +#define NOT_USED +#define DRM_VIA_WAIT_IRQ 0x0d +#define DRM_VIA_DMA_BLIT 0x0e +#define DRM_VIA_BLIT_SYNC 0x0f + +#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t) +#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t) +#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t) +#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t) +#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t) +#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t) +#define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t) +#define DRM_IOCTL_VIA_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t) +#define DRM_IOCTL_VIA_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_VIA_FLUSH) +#define DRM_IOCTL_VIA_PCICMD DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t) +#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \ + drm_via_cmdbuf_size_t) +#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t) +#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t) +#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t) + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_FRONT 0x1 +#define VIA_BACK 0x2 +#define VIA_DEPTH 0x4 +#define VIA_STENCIL 0x8 +#define VIA_MEM_VIDEO 0 /* matches drm constant */ +#define VIA_MEM_AGP 1 /* matches drm constant */ +#define VIA_MEM_SYSTEM 2 +#define VIA_MEM_MIXED 3 +#define VIA_MEM_UNKNOWN 4 + +typedef struct { + __u32 offset; + __u32 size; +} drm_via_agp_t; + +typedef struct { + __u32 offset; + __u32 size; +} drm_via_fb_t; + +typedef struct { + __u32 context; + __u32 type; + __u32 size; + unsigned long index; + unsigned long offset; +} drm_via_mem_t; + +typedef struct _drm_via_init { + enum { + VIA_INIT_MAP = 0x01, + VIA_CLEANUP_MAP = 0x02 + } func; + + unsigned long sarea_priv_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long agpAddr; +} drm_via_init_t; + +typedef struct _drm_via_futex { + enum { + VIA_FUTEX_WAIT = 0x00, + VIA_FUTEX_WAKE = 0X01 + } func; + __u32 ms; + __u32 lock; + __u32 val; +} drm_via_futex_t; + +typedef struct _drm_via_dma_init { + enum { + VIA_INIT_DMA = 0x01, + VIA_CLEANUP_DMA = 0x02, + VIA_DMA_INITIALIZED = 0x03 + } func; + + unsigned long offset; + unsigned long size; + unsigned long reg_pause_addr; +} drm_via_dma_init_t; + +typedef struct _drm_via_cmdbuffer { + char *buf; + unsigned long size; +} drm_via_cmdbuffer_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_via_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_via_tex_region_t; + +typedef struct _drm_via_sarea { + unsigned int dirty; + unsigned int nbox; + struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS]; + drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1]; + int texAge; /* last time texture was uploaded */ + int ctxOwner; /* last context to upload state */ + int vertexPrim; + + /* + * Below is for XvMC. + * We want the lock integers alone on, and aligned to, a cache line. + * Therefore this somewhat strange construct. + */ + + char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)]; + + unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS]; + unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS]; + unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ + + /* Used by the 3d driver only at this point, for pageflipping: + */ + unsigned int pfCurrentOffset; +} drm_via_sarea_t; + +typedef struct _drm_via_cmdbuf_size { + enum { + VIA_CMDBUF_SPACE = 0x01, + VIA_CMDBUF_LAG = 0x02 + } func; + int wait; + __u32 size; +} drm_via_cmdbuf_size_t; + +typedef enum { + VIA_IRQ_ABSOLUTE = 0x0, + VIA_IRQ_RELATIVE = 0x1, + VIA_IRQ_SIGNAL = 0x10000000, + VIA_IRQ_FORCE_SEQUENCE = 0x20000000 +} via_irq_seq_type_t; + +#define VIA_IRQ_FLAGS_MASK 0xF0000000 + +enum drm_via_irqs { + drm_via_irq_hqv0 = 0, + drm_via_irq_hqv1, + drm_via_irq_dma0_dd, + drm_via_irq_dma0_td, + drm_via_irq_dma1_dd, + drm_via_irq_dma1_td, + drm_via_irq_num +}; + +struct drm_via_wait_irq_request { + unsigned irq; + via_irq_seq_type_t type; + __u32 sequence; + __u32 signal; +}; + +typedef union drm_via_irqwait { + struct drm_via_wait_irq_request request; + struct drm_wait_vblank_reply reply; +} drm_via_irqwait_t; + +typedef struct drm_via_blitsync { + __u32 sync_handle; + unsigned engine; +} drm_via_blitsync_t; + +/* - * Below,"flags" is currently unused but will be used for possible future + * extensions like kernel space bounce buffers for bad alignments and + * blit engine busy-wait polling for better latency in the absence of + * interrupts. + */ + +typedef struct drm_via_dmablit { + __u32 num_lines; + __u32 line_length; + + __u32 fb_addr; + __u32 fb_stride; + + unsigned char *mem_addr; + __u32 mem_stride; + + __u32 flags; + int to_fb; + + drm_via_blitsync_t sync; +} drm_via_dmablit_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* _VIA_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/common/drm/include/libdrm/virtgpu_drm.h b/rknn_yolo_demo/libs/common/drm/include/libdrm/virtgpu_drm.h new file mode 100644 index 0000000..f06a789 --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/libdrm/virtgpu_drm.h @@ -0,0 +1,182 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRTGPU_DRM_H +#define VIRTGPU_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define DRM_VIRTGPU_MAP 0x01 +#define DRM_VIRTGPU_EXECBUFFER 0x02 +#define DRM_VIRTGPU_GETPARAM 0x03 +#define DRM_VIRTGPU_RESOURCE_CREATE 0x04 +#define DRM_VIRTGPU_RESOURCE_INFO 0x05 +#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06 +#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07 +#define DRM_VIRTGPU_WAIT 0x08 +#define DRM_VIRTGPU_GET_CAPS 0x09 + +#define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01 +#define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02 +#define VIRTGPU_EXECBUF_FLAGS (\ + VIRTGPU_EXECBUF_FENCE_FD_IN |\ + VIRTGPU_EXECBUF_FENCE_FD_OUT |\ + 0) + +struct drm_virtgpu_map { + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; +}; + +struct drm_virtgpu_execbuffer { + __u32 flags; + __u32 size; + __u64 command; /* void* */ + __u64 bo_handles; + __u32 num_bo_handles; + __s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */ +}; + +#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ +#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */ + +struct drm_virtgpu_getparam { + __u64 param; + __u64 value; +}; + +/* NO_BO flags? NO resource flag? */ +/* resource flag for y_0_top */ +struct drm_virtgpu_resource_create { + __u32 target; + __u32 format; + __u32 bind; + __u32 width; + __u32 height; + __u32 depth; + __u32 array_size; + __u32 last_level; + __u32 nr_samples; + __u32 flags; + __u32 bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ + __u32 res_handle; /* returned by kernel */ + __u32 size; /* validate transfer in the host */ + __u32 stride; /* validate transfer in the host */ +}; + +struct drm_virtgpu_resource_info { + __u32 bo_handle; + __u32 res_handle; + __u32 size; + __u32 stride; +}; + +struct drm_virtgpu_3d_box { + __u32 x; + __u32 y; + __u32 z; + __u32 w; + __u32 h; + __u32 d; +}; + +struct drm_virtgpu_3d_transfer_to_host { + __u32 bo_handle; + struct drm_virtgpu_3d_box box; + __u32 level; + __u32 offset; +}; + +struct drm_virtgpu_3d_transfer_from_host { + __u32 bo_handle; + struct drm_virtgpu_3d_box box; + __u32 level; + __u32 offset; +}; + +#define VIRTGPU_WAIT_NOWAIT 1 /* like it */ +struct drm_virtgpu_3d_wait { + __u32 handle; /* 0 is an invalid handle */ + __u32 flags; +}; + +struct drm_virtgpu_get_caps { + __u32 cap_set_id; + __u32 cap_set_ver; + __u64 addr; + __u32 size; + __u32 pad; +}; + +#define DRM_IOCTL_VIRTGPU_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) + +#define DRM_IOCTL_VIRTGPU_EXECBUFFER \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\ + struct drm_virtgpu_execbuffer) + +#define DRM_IOCTL_VIRTGPU_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\ + struct drm_virtgpu_getparam) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, \ + struct drm_virtgpu_resource_create) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \ + struct drm_virtgpu_resource_info) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST, \ + struct drm_virtgpu_3d_transfer_from_host) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST, \ + struct drm_virtgpu_3d_transfer_to_host) + +#define DRM_IOCTL_VIRTGPU_WAIT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT, \ + struct drm_virtgpu_3d_wait) + +#define DRM_IOCTL_VIRTGPU_GET_CAPS \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ + struct drm_virtgpu_get_caps) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/tool.h b/rknn_yolo_demo/libs/common/drm/include/tool.h new file mode 100644 index 0000000..c7b334d --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/tool.h @@ -0,0 +1,145 @@ +/* + + */ + +#ifndef TOOL_H_ +#define TOOL_H_ +//ڴ˴ͷļ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define YUV420 0 +#define YUV422 YUV420 + 1 +#define YUV444 YUV422 + 1 +/************************************************************* +Function: ReadBmpFile +Description: ȡbmpͼڴ +Input: pFilePathbmp· + pDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgrrgbֵΪ8bit + widthͼ + heightͼ +Output: +*************************************************************/ +extern void ReadBmpFile(char *pFilePath, unsigned char *pData, int & width, int & height); +/************************************************************* +Function: SaveBmpFile +Description: rgbͼݱΪbmp +Input: pFilePathbmp· + pDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgrrgbֵΪ8bit + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveBmpFile(char *pFilePath, unsigned char *pData, int width, int height); +/************************************************************* +Function: SaveRaw +Description: rawͼ +Input: pSavePathraw· + pDataraw + widthrawͼ + heightrawͼ +Output: +*************************************************************/ +extern void SaveRaw(char *pSavePath, short *pRawData, int width, int height); + +extern void SaveRaw32bit(char *pSavePath, long *pRawData, int width, int height); + +/************************************************************* +Function: SaveBmpFile2 +Description: λ8bitbmpͼ +Input: pFilePathbmp· + widthͼ + heightͼ + bitValueͼλ + pRGBDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgr +Output: +*************************************************************/ +extern void SaveBmpFile2(char *pFilePath, int width, int height, int bitValue, short *pRGBData); + +/************************************************************* +Function: SaveYUVData +Description: 8bit YUVͼ +Input: pSavePath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData(char *pSavePath, unsigned char *pData, int width, int height); + + + +/************************************************************* +Function: SaveYUVData2 +Description: λ8bitYUVͼ +Input: pSavePath· + pDatayuvݣλ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData2(char *pSavePath, short *pData, int width, int height, int bitValue); +/************************************************************* +Function: SaveYUVData1 +Description: 8bit YUV420ͼ +Input: pSavePath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData1(char *pSavePath, unsigned char *pData, int width, int height, int fmt); +/************************************************************* +Function: ReadYUVData1 +Description: ȡ8bit YUV420ͼ +Input: pReadPath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void ReadYUVData1(char *pReadPath, unsigned char *pData, int width, int height, int fmt); +/************************************************************* +Function: Yuvfmtconv +Description: yuv fmt conversion.444 420 422 to 444 420 422 +Input: pDatain 뻺 + pDataout + width + height + fmt_in ʽ + fmt_out ʽ +Output: +*************************************************************/ +extern void Yuvfmtconv(void *pDatain, void *pDataout, int width, int height, int fmt_in, int fmt_out, int size); +/************************************************************* +Function: Yuvbitstochar +Description: save yuv to 8 bitdepth +Input: pDatain 뻺 + pDataout + size yuv + height λ +Output: +*************************************************************/ +extern void Yuvbitstochar(short *pDatain, unsigned char *pDataout, int size, int bitdepth); + +/************************************************************* +Function: SaveCfaBmp +Description: rawcfaͼ +Input: pRawDatarawͼ + widthrawͼ + heightrawͼߣ + bayerPatternbayer patternʽȡֵΧ[03] + bitValuerawλ +Output: +*************************************************************/ +extern void SaveCfaBmp(char *pFilePath, short *pRawData, int width, int height, int bayerPattern, int bitValue); + +#ifdef __cplusplus +} +#endif + +#endif // TOOL_H_ diff --git a/rknn_yolo_demo/libs/common/drm/include/xf86drm.h b/rknn_yolo_demo/libs/common/drm/include/xf86drm.h new file mode 100644 index 0000000..d86428a --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/xf86drm.h @@ -0,0 +1,930 @@ +/** + * \file xf86drm.h + * OS-independent header for DRM user-level library interface. + * + * \author Rickard E. (Rik) Faith + */ + +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _XF86DRM_H_ +#define _XF86DRM_H_ + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef DRM_MAX_MINOR +#define DRM_MAX_MINOR 16 +#endif + +#if defined(__linux__) + +#define DRM_IOCTL_NR(n) _IOC_NR(n) +#define DRM_IOC_VOID _IOC_NONE +#define DRM_IOC_READ _IOC_READ +#define DRM_IOC_WRITE _IOC_WRITE +#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) + +#else /* One of the *BSDs */ + +#include +#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define DRM_IOC_VOID IOC_VOID +#define DRM_IOC_READ IOC_OUT +#define DRM_IOC_WRITE IOC_IN +#define DRM_IOC_READWRITE IOC_INOUT +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) + +#endif + + /* Defaults, if nothing set in xf86config */ +#define DRM_DEV_UID 0 +#define DRM_DEV_GID 0 +/* Default /dev/dri directory permissions 0755 */ +#define DRM_DEV_DIRMODE \ + (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) +#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + +#ifdef __OpenBSD__ +#define DRM_DIR_NAME "/dev" +#define DRM_PRIMARY_MINOR_NAME "drm" +#define DRM_CONTROL_MINOR_NAME "drmC" +#define DRM_RENDER_MINOR_NAME "drmR" +#else +#define DRM_DIR_NAME "/dev/dri" +#define DRM_PRIMARY_MINOR_NAME "card" +#define DRM_CONTROL_MINOR_NAME "controlD" +#define DRM_RENDER_MINOR_NAME "renderD" +#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ +#endif + +#define DRM_DEV_NAME "%s/" DRM_PRIMARY_MINOR_NAME "%d" +#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d" +#define DRM_RENDER_DEV_NAME "%s/" DRM_RENDER_MINOR_NAME "%d" + +#define DRM_NODE_NAME_MAX \ + (sizeof(DRM_DIR_NAME) + 1 /* slash */ \ + + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \ + sizeof(DRM_CONTROL_MINOR_NAME), \ + sizeof(DRM_RENDER_MINOR_NAME)) \ + + sizeof("144") /* highest possible node number */ \ + + 1) /* NULL-terminator */ + +#define DRM_ERR_NO_DEVICE (-1001) +#define DRM_ERR_NO_ACCESS (-1002) +#define DRM_ERR_NOT_ROOT (-1003) +#define DRM_ERR_INVALID (-1004) +#define DRM_ERR_NO_FD (-1005) + +#define DRM_AGP_NO_HANDLE 0 + +typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ +typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ + +#if (__GNUC__ >= 3) +#define DRM_PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) +#else +#define DRM_PRINTFLIKE(f, a) +#endif + +typedef struct _drmServerInfo { + int (*debug_print)(const char *format, va_list ap) DRM_PRINTFLIKE(1,0); + int (*load_module)(const char *name); + void (*get_perms)(gid_t *, mode_t *); +} drmServerInfo, *drmServerInfoPtr; + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +extern int drmIoctl(int fd, unsigned long request, void *arg); +extern void *drmGetHashTable(void); +extern drmHashEntry *drmGetEntry(int fd); + +/** + * Driver version information. + * + * \sa drmGetVersion() and drmSetVersion(). + */ +typedef struct _drmVersion { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + int name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + int date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + int desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +} drmVersion, *drmVersionPtr; + +typedef struct _drmStats { + unsigned long count; /**< Number of data */ + struct { + unsigned long value; /**< Value from kernel */ + const char *long_format; /**< Suggested format for long_name */ + const char *long_name; /**< Long name for value */ + const char *rate_format; /**< Suggested format for rate_name */ + const char *rate_name; /**< Short name for value per second */ + int isvalue; /**< True if value (vs. counter) */ + const char *mult_names; /**< Multiplier names (e.g., "KGM") */ + int mult; /**< Multiplier value (e.g., 1024) */ + int verbose; /**< Suggest only in verbose output */ + } data[15]; +} drmStatsT; + + + /* All of these enums *MUST* match with the + kernel implementation -- so do *NOT* + change them! (The drmlib implementation + will just copy the flags instead of + translating them.) */ +typedef enum { + DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */ + DRM_REGISTERS = 1, /**< no caching, no core dump */ + DRM_SHM = 2, /**< shared, cached */ + DRM_AGP = 3, /**< AGP/GART */ + DRM_SCATTER_GATHER = 4, /**< PCI scatter/gather */ + DRM_CONSISTENT = 5 /**< PCI consistent */ +} drmMapType; + +typedef enum { + DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */ + DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */ + DRM_LOCKED = 0x0004, /**< Physical pages locked */ + DRM_KERNEL = 0x0008, /**< Kernel requires access */ + DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */ + DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */ + DRM_REMOVABLE = 0x0040 /**< Removable mapping */ +} drmMapFlags; + +/** + * \warning These values *MUST* match drm.h + */ +typedef enum { + /** \name Flags for DMA buffer dispatch */ + /*@{*/ + DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note the buffer may not yet have been + * processed by the hardware -- getting a + * hardware lock with the hardware quiescent + * will ensure that the buffer has been + * processed. + */ + DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + /*@}*/ + + /** \name Flags for DMA buffer request */ + /*@{*/ + DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ + /*@}*/ +} drmDMAFlags; + +typedef enum { + DRM_PAGE_ALIGN = 0x01, + DRM_AGP_BUFFER = 0x02, + DRM_SG_BUFFER = 0x04, + DRM_FB_BUFFER = 0x08, + DRM_PCI_BUFFER_RO = 0x10 +} drmBufDescFlags; + +typedef enum { + DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +} drmLockFlags; + +typedef enum { + DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and + never swapped. */ + DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */ +} drm_context_tFlags, *drm_context_tFlagsPtr; + +typedef struct _drmBufDesc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ +} drmBufDesc, *drmBufDescPtr; + +typedef struct _drmBufInfo { + int count; /**< Number of buffers described in list */ + drmBufDescPtr list; /**< List of buffer descriptions */ +} drmBufInfo, *drmBufInfoPtr; + +typedef struct _drmBuf { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + drmAddress address; /**< Address */ +} drmBuf, *drmBufPtr; + +/** + * Buffer mapping information. + * + * Used by drmMapBufs() and drmUnmapBufs() to store information about the + * mapped buffers. + */ +typedef struct _drmBufMap { + int count; /**< Number of buffers mapped */ + drmBufPtr list; /**< Buffers */ +} drmBufMap, *drmBufMapPtr; + +typedef struct _drmLock { + volatile unsigned int lock; + char padding[60]; + /* This is big enough for most current (and future?) architectures: + DEC Alpha: 32 bytes + Intel Merced: ? + Intel P5/PPro/PII/PIII: 32 bytes + Intel StrongARM: 32 bytes + Intel i386/i486: 16 bytes + MIPS: 32 bytes (?) + Motorola 68k: 16 bytes + Motorola PowerPC: 32 bytes + Sun SPARC: 32 bytes + */ +} drmLock, *drmLockPtr; + +/** + * Indices here refer to the offset into + * list in drmBufInfo + */ +typedef struct _drmDMAReq { + drm_context_t context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_list; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send, in bytes */ + drmDMAFlags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size of buffers requested */ + int *request_list; /**< Buffer information */ + int *request_sizes; /**< Minimum acceptable sizes */ + int granted_count; /**< Number of buffers granted at this size */ +} drmDMAReq, *drmDMAReqPtr; + +typedef struct _drmRegion { + drm_handle_t handle; + unsigned int offset; + drmSize size; + drmAddress map; +} drmRegion, *drmRegionPtr; + +typedef struct _drmTextureRegion { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; /**< Explicitly pad this out */ + unsigned int age; +} drmTextureRegion, *drmTextureRegionPtr; + + +typedef enum { + DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drmVBlankSeqType; +#define DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +typedef struct _drmVBlankReq { + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq, *drmVBlankReqPtr; + +typedef struct _drmVBlankReply { + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec; + long tval_usec; +} drmVBlankReply, *drmVBlankReplyPtr; + +typedef union _drmVBlank { + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank, *drmVBlankPtr; + +typedef struct _drmSetVersion { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drmSetVersion, *drmSetVersionPtr; + +#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) + +#define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ + +#if defined(__GNUC__) && (__GNUC__ >= 2) +# if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__) + /* Reflect changes here to drmP.h */ +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + int __dummy; /* Can't mark eax as clobbered */ \ + __asm__ __volatile__( \ + "lock ; cmpxchg %4,%1\n\t" \ + "setnz %0" \ + : "=d" (__ret), \ + "=m" (__drm_dummy_lock(lock)), \ + "=a" (__dummy) \ + : "2" (old), \ + "r" (new)); \ + } while (0) + +#elif defined(__alpha__) + +#define DRM_CAS(lock, old, new, ret) \ + do { \ + int tmp, old32; \ + __asm__ __volatile__( \ + " addl $31, %5, %3\n" \ + "1: ldl_l %0, %2\n" \ + " cmpeq %0, %3, %1\n" \ + " beq %1, 2f\n" \ + " mov %4, %0\n" \ + " stl_c %0, %2\n" \ + " beq %0, 3f\n" \ + " mb\n" \ + "2: cmpeq %1, 0, %1\n" \ + ".subsection 2\n" \ + "3: br 1b\n" \ + ".previous" \ + : "=&r"(tmp), "=&r"(ret), \ + "=m"(__drm_dummy_lock(lock)), \ + "=&r"(old32) \ + : "r"(new), "r"(old) \ + : "memory"); \ + } while (0) + +#elif defined(__sparc__) + +#define DRM_CAS(lock,old,new,__ret) \ +do { register unsigned int __old __asm("o0"); \ + register unsigned int __new __asm("o1"); \ + register volatile unsigned int *__lock __asm("o2"); \ + __old = old; \ + __new = new; \ + __lock = (volatile unsigned int *)lock; \ + __asm__ __volatile__( \ + /*"cas [%2], %3, %0"*/ \ + ".word 0xd3e29008\n\t" \ + /*"membar #StoreStore | #StoreLoad"*/ \ + ".word 0x8143e00a" \ + : "=&r" (__new) \ + : "0" (__new), \ + "r" (__lock), \ + "r" (__old) \ + : "memory"); \ + __ret = (__new != __old); \ +} while(0) + +#elif defined(__ia64__) + +#ifdef __INTEL_COMPILER +/* this currently generates bad code (missing stop bits)... */ +#include + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned long __result, __old = (old) & 0xffffffff; \ + __mf(); \ + __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\ + __ret = (__result) != (__old); \ +/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ + (old), (new)) \ + != (old)); */\ + } while (0) + +#else +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned int __result, __old = (old); \ + __asm__ __volatile__( \ + "mf\n" \ + "mov ar.ccv=%2\n" \ + ";;\n" \ + "cmpxchg4.acq %0=%1,%3,ar.ccv" \ + : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ + : "r" ((unsigned long)__old), "r" (new) \ + : "memory"); \ + __ret = (__result) != (__old); \ + } while (0) + +#endif + +#elif defined(__powerpc__) + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__( \ + "sync;" \ + "0: lwarx %0,0,%1;" \ + " xor. %0,%3,%0;" \ + " bne 1f;" \ + " stwcx. %2,0,%1;" \ + " bne- 0b;" \ + "1: " \ + "sync;" \ + : "=&r"(__ret) \ + : "r"(lock), "r"(new), "r"(old) \ + : "cr0", "memory"); \ + } while (0) + +# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \ + || defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) + #undef DRM_DEV_MODE + #define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + + #define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__ ( \ + "1: ldrex %0, [%1]\n" \ + " teq %0, %2\n" \ + " ite eq\n" \ + " strexeq %0, %3, [%1]\n" \ + " movne %0, #1\n" \ + : "=&r" (__ret) \ + : "r" (lock), "r" (old), "r" (new) \ + : "cc","memory"); \ + } while (0) + +#endif /* architecture */ +#endif /* __GNUC__ >= 2 */ + +#ifndef DRM_CAS +#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ +#endif + +#if defined(__alpha__) +#define DRM_CAS_RESULT(_result) long _result +#elif defined(__powerpc__) +#define DRM_CAS_RESULT(_result) int _result +#else +#define DRM_CAS_RESULT(_result) char _result +#endif + +#define DRM_LIGHT_LOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + } while(0) + + /* This one counts fast locks -- for + benchmarking only. */ +#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + else ++count; \ + } while(0) + +#define DRM_LOCK(fd,lock,context,flags) \ + do { \ + if (flags) drmGetLock(fd,context,flags); \ + else DRM_LIGHT_LOCK(fd,lock,context); \ + } while(0) + +#define DRM_UNLOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \ + if (__ret) drmUnlock(fd,context); \ + } while(0) + + /* Simple spin locks */ +#define DRM_SPINLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + do { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) while ((spin)->lock); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_TAKE(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + int cur; \ + do { \ + cur = (*spin).lock; \ + DRM_CAS(spin,cur,val,__ret); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ + do { \ + int __i; \ + __ret = 1; \ + for (__i = 0; __ret && __i < count; __i++) { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) for (;__i < count && (spin)->lock; __i++); \ + } \ + } while(0) + +#define DRM_SPINUNLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + if ((*spin).lock == val) { /* else server stole lock */ \ + do { \ + DRM_CAS(spin,val,0,__ret); \ + } while (__ret); \ + } \ + } while(0) + + + +/* General user-level programmer's API: unprivileged */ +extern int drmAvailable(void); +extern int drmOpen(const char *name, const char *busid); + +#define DRM_NODE_PRIMARY 0 +#define DRM_NODE_CONTROL 1 +#define DRM_NODE_RENDER 2 +#define DRM_NODE_MAX 3 + +extern int drmOpenWithType(const char *name, const char *busid, + int type); + +extern int drmOpenControl(int minor); +extern int drmOpenRender(int minor); +extern int drmClose(int fd); +extern drmVersionPtr drmGetVersion(int fd); +extern drmVersionPtr drmGetLibVersion(int fd); +extern int drmGetCap(int fd, uint64_t capability, uint64_t *value); +extern void drmFreeVersion(drmVersionPtr); +extern int drmGetMagic(int fd, drm_magic_t * magic); +extern char *drmGetBusid(int fd); +extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum, + int funcnum); +extern int drmGetMap(int fd, int idx, drm_handle_t *offset, + drmSize *size, drmMapType *type, + drmMapFlags *flags, drm_handle_t *handle, + int *mtrr); +extern int drmGetClient(int fd, int idx, int *auth, int *pid, + int *uid, unsigned long *magic, + unsigned long *iocs); +extern int drmGetStats(int fd, drmStatsT *stats); +extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); +extern int drmCommandNone(int fd, unsigned long drmCommandIndex); +extern int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); + +/* General user-level programmer's API: X server (root) only */ +extern void drmFreeBusid(const char *busid); +extern int drmSetBusid(int fd, const char *busid); +extern int drmAuthMagic(int fd, drm_magic_t magic); +extern int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle); +extern int drmRmMap(int fd, drm_handle_t handle); +extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t handle); + +extern int drmAddBufs(int fd, int count, int size, + drmBufDescFlags flags, + int agp_offset); +extern int drmMarkBufs(int fd, double low, double high); +extern int drmCreateContext(int fd, drm_context_t * handle); +extern int drmSetContextFlags(int fd, drm_context_t context, + drm_context_tFlags flags); +extern int drmGetContextFlags(int fd, drm_context_t context, + drm_context_tFlagsPtr flags); +extern int drmAddContextTag(int fd, drm_context_t context, void *tag); +extern int drmDelContextTag(int fd, drm_context_t context); +extern void *drmGetContextTag(int fd, drm_context_t context); +extern drm_context_t * drmGetReservedContextList(int fd, int *count); +extern void drmFreeReservedContextList(drm_context_t *); +extern int drmSwitchToContext(int fd, drm_context_t context); +extern int drmDestroyContext(int fd, drm_context_t handle); +extern int drmCreateDrawable(int fd, drm_drawable_t * handle); +extern int drmDestroyDrawable(int fd, drm_drawable_t handle); +extern int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, + drm_drawable_info_type_t type, + unsigned int num, void *data); +extern int drmCtlInstHandler(int fd, int irq); +extern int drmCtlUninstHandler(int fd); +extern int drmSetClientCap(int fd, uint64_t capability, + uint64_t value); + +extern int drmCrtcGetSequence(int fd, uint32_t crtcId, + uint64_t *sequence, uint64_t *ns); +extern int drmCrtcQueueSequence(int fd, uint32_t crtcId, + uint32_t flags, uint64_t sequence, + uint64_t *sequence_queued, + uint64_t user_data); +/* General user-level programmer's API: authenticated client and/or X */ +extern int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address); +extern int drmUnmap(drmAddress address, drmSize size); +extern drmBufInfoPtr drmGetBufInfo(int fd); +extern drmBufMapPtr drmMapBufs(int fd); +extern int drmUnmapBufs(drmBufMapPtr bufs); +extern int drmDMA(int fd, drmDMAReqPtr request); +extern int drmFreeBufs(int fd, int count, int *list); +extern int drmGetLock(int fd, + drm_context_t context, + drmLockFlags flags); +extern int drmUnlock(int fd, drm_context_t context); +extern int drmFinish(int fd, int context, drmLockFlags flags); +extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t * handle); + +/* AGP/GART support: X server (root) only */ +extern int drmAgpAcquire(int fd); +extern int drmAgpRelease(int fd); +extern int drmAgpEnable(int fd, unsigned long mode); +extern int drmAgpAlloc(int fd, unsigned long size, + unsigned long type, unsigned long *address, + drm_handle_t *handle); +extern int drmAgpFree(int fd, drm_handle_t handle); +extern int drmAgpBind(int fd, drm_handle_t handle, + unsigned long offset); +extern int drmAgpUnbind(int fd, drm_handle_t handle); + +/* AGP/GART info: authenticated client and/or X */ +extern int drmAgpVersionMajor(int fd); +extern int drmAgpVersionMinor(int fd); +extern unsigned long drmAgpGetMode(int fd); +extern unsigned long drmAgpBase(int fd); /* Physical location */ +extern unsigned long drmAgpSize(int fd); /* Bytes */ +extern unsigned long drmAgpMemoryUsed(int fd); +extern unsigned long drmAgpMemoryAvail(int fd); +extern unsigned int drmAgpVendorId(int fd); +extern unsigned int drmAgpDeviceId(int fd); + +/* PCI scatter/gather support: X server (root) only */ +extern int drmScatterGatherAlloc(int fd, unsigned long size, + drm_handle_t *handle); +extern int drmScatterGatherFree(int fd, drm_handle_t handle); + +extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); + +/* Support routines */ +extern void drmSetServerInfo(drmServerInfoPtr info); +extern int drmError(int err, const char *label); +extern void *drmMalloc(int size); +extern void drmFree(void *pt); + +/* Hash table routines */ +extern void *drmHashCreate(void); +extern int drmHashDestroy(void *t); +extern int drmHashLookup(void *t, unsigned long key, void **value); +extern int drmHashInsert(void *t, unsigned long key, void *value); +extern int drmHashDelete(void *t, unsigned long key); +extern int drmHashFirst(void *t, unsigned long *key, void **value); +extern int drmHashNext(void *t, unsigned long *key, void **value); + +/* PRNG routines */ +extern void *drmRandomCreate(unsigned long seed); +extern int drmRandomDestroy(void *state); +extern unsigned long drmRandom(void *state); +extern double drmRandomDouble(void *state); + +/* Skip list routines */ + +extern void *drmSLCreate(void); +extern int drmSLDestroy(void *l); +extern int drmSLLookup(void *l, unsigned long key, void **value); +extern int drmSLInsert(void *l, unsigned long key, void *value); +extern int drmSLDelete(void *l, unsigned long key); +extern int drmSLNext(void *l, unsigned long *key, void **value); +extern int drmSLFirst(void *l, unsigned long *key, void **value); +extern void drmSLDump(void *l); +extern int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); + +extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened); +extern int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type); +extern void drmCloseOnce(int fd); +extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2); + +extern int drmSetMaster(int fd); +extern int drmDropMaster(int fd); +extern int drmIsMaster(int fd); + +#define DRM_EVENT_CONTEXT_VERSION 4 + +typedef struct _drmEventContext { + + /* This struct is versioned so we can add more pointers if we + * add more events. */ + int version; + + void (*vblank_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + + void (*page_flip_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + + void (*page_flip_handler2)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + unsigned int crtc_id, + void *user_data); + + void (*sequence_handler)(int fd, + uint64_t sequence, + uint64_t ns, + uint64_t user_data); +} drmEventContext, *drmEventContextPtr; + +extern int drmHandleEvent(int fd, drmEventContextPtr evctx); + +extern char *drmGetDeviceNameFromFd(int fd); + +/* Improved version of drmGetDeviceNameFromFd which attributes for any type of + * device/node - card, control or renderD. + */ +extern char *drmGetDeviceNameFromFd2(int fd); +extern int drmGetNodeTypeFromFd(int fd); + +extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd); +extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle); + +extern char *drmGetPrimaryDeviceNameFromFd(int fd); +extern char *drmGetRenderDeviceNameFromFd(int fd); + +#define DRM_BUS_PCI 0 +#define DRM_BUS_USB 1 +#define DRM_BUS_PLATFORM 2 +#define DRM_BUS_HOST1X 3 + +typedef struct _drmPciBusInfo { + uint16_t domain; + uint8_t bus; + uint8_t dev; + uint8_t func; +} drmPciBusInfo, *drmPciBusInfoPtr; + +typedef struct _drmPciDeviceInfo { + uint16_t vendor_id; + uint16_t device_id; + uint16_t subvendor_id; + uint16_t subdevice_id; + uint8_t revision_id; +} drmPciDeviceInfo, *drmPciDeviceInfoPtr; + +typedef struct _drmUsbBusInfo { + uint8_t bus; + uint8_t dev; +} drmUsbBusInfo, *drmUsbBusInfoPtr; + +typedef struct _drmUsbDeviceInfo { + uint16_t vendor; + uint16_t product; +} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr; + +#define DRM_PLATFORM_DEVICE_NAME_LEN 512 + +typedef struct _drmPlatformBusInfo { + char fullname[DRM_PLATFORM_DEVICE_NAME_LEN]; +} drmPlatformBusInfo, *drmPlatformBusInfoPtr; + +typedef struct _drmPlatformDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr; + +#define DRM_HOST1X_DEVICE_NAME_LEN 512 + +typedef struct _drmHost1xBusInfo { + char fullname[DRM_HOST1X_DEVICE_NAME_LEN]; +} drmHost1xBusInfo, *drmHost1xBusInfoPtr; + +typedef struct _drmHost1xDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; + +typedef struct _drmDevice { + char **nodes; /* DRM_NODE_MAX sized array */ + int available_nodes; /* DRM_NODE_* bitmask */ + int bustype; + union { + drmPciBusInfoPtr pci; + drmUsbBusInfoPtr usb; + drmPlatformBusInfoPtr platform; + drmHost1xBusInfoPtr host1x; + } businfo; + union { + drmPciDeviceInfoPtr pci; + drmUsbDeviceInfoPtr usb; + drmPlatformDeviceInfoPtr platform; + drmHost1xDeviceInfoPtr host1x; + } deviceinfo; +} drmDevice, *drmDevicePtr; + +extern int drmGetDevice(int fd, drmDevicePtr *device); +extern void drmFreeDevice(drmDevicePtr *device); + +extern int drmGetDevices(drmDevicePtr devices[], int max_devices); +extern void drmFreeDevices(drmDevicePtr devices[], int count); + +#define DRM_DEVICE_GET_PCI_REVISION (1 << 0) +extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device); +extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices); + +extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); + +extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); +extern int drmSyncobjDestroy(int fd, uint32_t handle); +extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd); +extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle); + +extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd); +extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd); +extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, + uint64_t *points, uint32_t handle_count); +extern int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, + unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points, + uint32_t handle_count); +extern int drmSyncobjTransfer(int fd, + uint32_t dst_handle, uint64_t dst_point, + uint32_t src_handle, uint64_t src_point, + uint32_t flags); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/drm/include/xf86drmMode.h b/rknn_yolo_demo/libs/common/drm/include/xf86drmMode.h new file mode 100644 index 0000000..a32902f --- /dev/null +++ b/rknn_yolo_demo/libs/common/drm/include/xf86drmMode.h @@ -0,0 +1,551 @@ +/* + * \file xf86drmMode.h + * Header for DRM modesetting interface. + * + * \author Jakob Bornecrantz + * + * \par Acknowledgements: + * Feb 2007, Dave Airlie + */ + +/* + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 2007-2008 Dave Airlie + * Copyright (c) 2007-2008 Jakob Bornecrantz + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _XF86DRMMODE_H_ +#define _XF86DRMMODE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include + +/* + * This is the interface for modesetting for drm. + * + * In order to use this interface you must include either or another + * header defining uint32_t, int32_t and uint16_t. + * + * It aims to provide a randr1.2 compatible interface for modesettings in the + * kernel, the interface is also meant to be used by libraries like EGL. + * + * More information can be found in randrproto.txt which can be found here: + * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git + * + * There are some major differences to be noted. Unlike the randr1.2 proto you + * need to create the memory object of the framebuffer yourself with the ttm + * buffer object interface. This object needs to be pinned. + */ + +/* + * If we pickup an old version of drm.h which doesn't include drm_mode.h + * we should redefine defines. This is so that builds doesn't breaks with + * new libdrm on old kernels. + */ +#ifndef _DRM_MODE_H + +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NON_GPU 0 +#define DRM_MODE_SCALE_FULLSCREEN 1 +#define DRM_MODE_SCALE_NO_SCALE 2 +#define DRM_MODE_SCALE_ASPECT 3 + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 + +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 +#define DRM_MODE_SUBCONNECTOR_SCART 9 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) + +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) + +#endif /* _DRM_MODE_H */ + + +/* + * Feature defines + * + * Just because these are defined doesn't mean that the kernel + * can do that feature, its just for new code vs old libdrm. + */ +#define DRM_MODE_FEATURE_KMS 1 +#define DRM_MODE_FEATURE_DIRTYFB 1 + + +typedef struct _drmModeRes { + + int count_fbs; + uint32_t *fbs; + + int count_crtcs; + uint32_t *crtcs; + + int count_connectors; + uint32_t *connectors; + + int count_encoders; + uint32_t *encoders; + + uint32_t min_width, max_width; + uint32_t min_height, max_height; +} drmModeRes, *drmModeResPtr; + +typedef struct _drmModeModeInfo { + uint32_t clock; + uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; + uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; + + uint32_t vrefresh; + + uint32_t flags; + uint32_t type; + char name[DRM_DISPLAY_MODE_LEN]; +} drmModeModeInfo, *drmModeModeInfoPtr; + +typedef struct _drmModeFB { + uint32_t fb_id; + uint32_t width, height; + uint32_t pitch; + uint32_t bpp; + uint32_t depth; + /* driver specific handle */ + uint32_t handle; +} drmModeFB, *drmModeFBPtr; + +typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr; + +typedef struct _drmModePropertyBlob { + uint32_t id; + uint32_t length; + void *data; +} drmModePropertyBlobRes, *drmModePropertyBlobPtr; + +typedef struct _drmModeProperty { + uint32_t prop_id; + uint32_t flags; + char name[DRM_PROP_NAME_LEN]; + int count_values; + uint64_t *values; /* store the blob lengths */ + int count_enums; + struct drm_mode_property_enum *enums; + int count_blobs; + uint32_t *blob_ids; /* store the blob IDs */ +} drmModePropertyRes, *drmModePropertyPtr; + +static __inline int drm_property_type_is(drmModePropertyPtr property, + uint32_t type) +{ + /* instanceof for props.. handles extended type vs original types: */ + if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) + return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type; + return property->flags & type; +} + +typedef struct _drmModeCrtc { + uint32_t crtc_id; + uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */ + + uint32_t x, y; /**< Position on the framebuffer */ + uint32_t width, height; + int mode_valid; + drmModeModeInfo mode; + + int gamma_size; /**< Number of gamma stops */ + +} drmModeCrtc, *drmModeCrtcPtr; + +typedef struct _drmModeEncoder { + uint32_t encoder_id; + uint32_t encoder_type; + uint32_t crtc_id; + uint32_t possible_crtcs; + uint32_t possible_clones; +} drmModeEncoder, *drmModeEncoderPtr; + +typedef enum { + DRM_MODE_CONNECTED = 1, + DRM_MODE_DISCONNECTED = 2, + DRM_MODE_UNKNOWNCONNECTION = 3 +} drmModeConnection; + +typedef enum { + DRM_MODE_SUBPIXEL_UNKNOWN = 1, + DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2, + DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3, + DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4, + DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5, + DRM_MODE_SUBPIXEL_NONE = 6 +} drmModeSubPixel; + +typedef struct _drmModeConnector { + uint32_t connector_id; + uint32_t encoder_id; /**< Encoder currently connected to */ + uint32_t connector_type; + uint32_t connector_type_id; + drmModeConnection connection; + uint32_t mmWidth, mmHeight; /**< HxW in millimeters */ + drmModeSubPixel subpixel; + + int count_modes; + drmModeModeInfoPtr modes; + + int count_props; + uint32_t *props; /**< List of property ids */ + uint64_t *prop_values; /**< List of property values */ + + int count_encoders; + uint32_t *encoders; /**< List of encoder ids */ +} drmModeConnector, *drmModeConnectorPtr; + +#define DRM_PLANE_TYPE_OVERLAY 0 +#define DRM_PLANE_TYPE_PRIMARY 1 +#define DRM_PLANE_TYPE_CURSOR 2 + +typedef struct _drmModeObjectProperties { + uint32_t count_props; + uint32_t *props; + uint64_t *prop_values; +} drmModeObjectProperties, *drmModeObjectPropertiesPtr; + +typedef struct _drmModePlane { + uint32_t count_formats; + uint32_t *formats; + uint32_t plane_id; + + uint32_t crtc_id; + uint32_t fb_id; + + uint32_t crtc_x, crtc_y; + uint32_t x, y; + + uint32_t possible_crtcs; + uint32_t gamma_size; +} drmModePlane, *drmModePlanePtr; + +typedef struct _drmModePlaneRes { + uint32_t count_planes; + uint32_t *planes; +} drmModePlaneRes, *drmModePlaneResPtr; + +extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr ); +extern void drmModeFreeResources( drmModeResPtr ptr ); +extern void drmModeFreeFB( drmModeFBPtr ptr ); +extern void drmModeFreeCrtc( drmModeCrtcPtr ptr ); +extern void drmModeFreeConnector( drmModeConnectorPtr ptr ); +extern void drmModeFreeEncoder( drmModeEncoderPtr ptr ); +extern void drmModeFreePlane( drmModePlanePtr ptr ); +extern void drmModeFreePlaneResources(drmModePlaneResPtr ptr); + +/** + * Retrieves all of the resources associated with a card. + */ +extern drmModeResPtr drmModeGetResources(int fd); + +/* + * FrameBuffer manipulation. + */ + +/** + * Retrieve information about framebuffer bufferId + */ +extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId); + +/** + * Creates a new framebuffer with an buffer object as its scanout buffer. + */ +extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint32_t *buf_id); +/* ...with a specific pixel format */ +extern int drmModeAddFB2(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + uint32_t *buf_id, uint32_t flags); + +/* ...with format modifiers */ +int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + const uint64_t modifier[4], uint32_t *buf_id, + uint32_t flags); + +/** + * Destroies the given framebuffer. + */ +extern int drmModeRmFB(int fd, uint32_t bufferId); + +/** + * Mark a region of a framebuffer as dirty. + */ +extern int drmModeDirtyFB(int fd, uint32_t bufferId, + drmModeClipPtr clips, uint32_t num_clips); + + +/* + * Crtc functions + */ + +/** + * Retrieve information about the ctrt crtcId + */ +extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId); + +/** + * Set the mode on a crtc crtcId with the given mode modeId. + */ +int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, + uint32_t x, uint32_t y, uint32_t *connectors, int count, + drmModeModeInfoPtr mode); + +/* + * Cursor functions + */ + +/** + * Set the cursor on crtc + */ +int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height); + +int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y); +/** + * Move the cursor on crtc + */ +int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y); + +/** + * Encoder functions + */ +drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id); + +/* + * Connector manipulation + */ + +/** + * Retrieve all information about the connector connectorId. This will do a + * forced probe on the connector to retrieve remote information such as EDIDs + * from the display device. + */ +extern drmModeConnectorPtr drmModeGetConnector(int fd, + uint32_t connectorId); + +/** + * Retrieve current information, i.e the currently active mode and encoder, + * about the connector connectorId. This will not do any probing on the + * connector or remote device, and only reports what is currently known. + * For the complete set of modes and encoders associated with the connector + * use drmModeGetConnector() which will do a probe to determine any display + * link changes first. + */ +extern drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, + uint32_t connector_id); + +/** + * Attaches the given mode to an connector. + */ +extern int drmModeAttachMode(int fd, uint32_t connectorId, drmModeModeInfoPtr mode_info); + +/** + * Detaches a mode from the connector + * must be unused, by the given mode. + */ +extern int drmModeDetachMode(int fd, uint32_t connectorId, drmModeModeInfoPtr mode_info); + +extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId); +extern void drmModeFreeProperty(drmModePropertyPtr ptr); + +extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id); +extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); +extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, + uint64_t value); +extern int drmCheckModesettingSupported(const char *busid); + +extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data); +extern int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data, + uint32_t target_vblank); + +extern drmModePlaneResPtr drmModeGetPlaneResources(int fd); +extern drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id); +extern int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, + uint32_t fb_id, uint32_t flags, + int32_t crtc_x, int32_t crtc_y, + uint32_t crtc_w, uint32_t crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); + +extern drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, + uint32_t object_id, + uint32_t object_type); +extern void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr); +extern int drmModeObjectSetProperty(int fd, uint32_t object_id, + uint32_t object_type, uint32_t property_id, + uint64_t value); + + +typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr; + +extern drmModeAtomicReqPtr drmModeAtomicAlloc(void); +extern drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr req); +extern int drmModeAtomicMerge(drmModeAtomicReqPtr base, + drmModeAtomicReqPtr augment); +extern void drmModeAtomicFree(drmModeAtomicReqPtr req); +extern int drmModeAtomicGetCursor(drmModeAtomicReqPtr req); +extern void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor); +extern int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, + uint32_t object_id, + uint32_t property_id, + uint64_t value); +extern int drmModeAtomicCommit(int fd, + drmModeAtomicReqPtr req, + uint32_t flags, + void *user_data); + +extern int drmModeCreatePropertyBlob(int fd, const void *data, size_t size, + uint32_t *id); +extern int drmModeDestroyPropertyBlob(int fd, uint32_t id); + +/* + * DRM mode lease APIs. These create and manage new drm_masters with + * access to a subset of the available DRM resources + */ + +extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id); + +typedef struct drmModeLesseeList { + uint32_t count; + uint32_t lessees[0]; +} drmModeLesseeListRes, *drmModeLesseeListPtr; + +extern drmModeLesseeListPtr drmModeListLessees(int fd); + +typedef struct drmModeObjectList { + uint32_t count; + uint32_t objects[0]; +} drmModeObjectListRes, *drmModeObjectListPtr; + +extern drmModeObjectListPtr drmModeGetLease(int fd); + +extern int drmModeRevokeLease(int fd, uint32_t lessee_id); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/common/stb/stb_image.h b/rknn_yolo_demo/libs/common/stb/stb_image.h new file mode 100644 index 0000000..196dfd5 --- /dev/null +++ b/rknn_yolo_demo/libs/common/stb/stb_image.h @@ -0,0 +1,7559 @@ +/* stb_image - v2.23 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt JR Smith github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/common/stb/stb_image_resize.h b/rknn_yolo_demo/libs/common/stb/stb_image_resize.h new file mode 100644 index 0000000..4f6ad35 --- /dev/null +++ b/rknn_yolo_demo/libs/common/stb/stb_image_resize.h @@ -0,0 +1,2630 @@ +/* stb_image_resize - v0.96 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/common/stb/stb_image_write.h b/rknn_yolo_demo/libs/common/stb/stb_image_write.h new file mode 100644 index 0000000..c117344 --- /dev/null +++ b/rknn_yolo_demo/libs/common/stb/stb_image_write.h @@ -0,0 +1,1619 @@ +/* stb_image_write - v1.13 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. + +USAGE: + + There are five functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +extern int stbi_write_tga_with_rle; +extern int stbi_write_png_compression_level; +extern int stbi_write_force_png_filter; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBI_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi__flip_vertically_on_write=0; +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi__flip_vertically_on_write=0; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a; arr[1] = b; arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +#ifdef __STDC_WANT_SECURE_LIB__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else + len = snprintf(buffer, 128, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +#endif +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + const unsigned char *imageData = (const unsigned char *)data; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + int x, y, pos; + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float YDU[64], UDU[64], VDU[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + float r, g, b; + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + + r = imageData[p+0]; + g = imageData[p+ofsG]; + b = imageData[p+ofsB]; + YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; + UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; + VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/cjpeg b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/cjpeg new file mode 100644 index 0000000..a717a38 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/cjpeg differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/djpeg b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/djpeg new file mode 100644 index 0000000..5c5e03c Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/djpeg differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/jpegtran b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/jpegtran new file mode 100644 index 0000000..06f1446 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/jpegtran differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/rdjpgcom b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/rdjpgcom new file mode 100644 index 0000000..94901a3 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/rdjpgcom differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/wrjpgcom b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/wrjpgcom new file mode 100644 index 0000000..72764d7 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/bin/wrjpgcom differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jconfig.h b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jconfig.h new file mode 100644 index 0000000..966b1d5 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jconfig.h @@ -0,0 +1,54 @@ +/* jconfig.h. Generated from jconfig.cfg by configure. */ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.txt for explanations */ + +#define HAVE_PROTOTYPES 1 +#define HAVE_UNSIGNED_CHAR 1 +#define HAVE_UNSIGNED_SHORT 1 +/* #undef void */ +/* #undef const */ +/* #undef CHAR_IS_UNSIGNED */ +#define HAVE_STDDEF_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_LOCALE_H 1 +/* #undef NEED_BSD_STRINGS */ +/* #undef NEED_SYS_TYPES_H */ +/* #undef NEED_FAR_POINTERS */ +/* #undef NEED_SHORT_EXTERNAL_NAMES */ +/* Define this if you get warnings about undefined structures. */ +/* #undef INCOMPLETE_TYPES_BROKEN */ + +/* Define "boolean" as unsigned char, not int, on Windows systems. */ +#ifdef _WIN32 +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + +#ifdef JPEG_INTERNALS + +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ +#define INLINE __inline__ +/* These are for configuring the JPEG memory manager. */ +/* #undef DEFAULT_MAX_MEM */ +/* #undef NO_MKTEMP */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +/* #undef RLE_SUPPORTED */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* #undef TWO_FILE_COMMANDLINE */ +/* #undef NEED_SIGNAL_CATCHER */ +/* #undef DONT_USE_B_MODE */ + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +/* #undef PROGRESS_REPORT */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jerror.h b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jerror.h new file mode 100644 index 0000000..1cfb2b1 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jmorecfg.h b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jmorecfg.h new file mode 100644 index 0000000..6c085c3 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jmorecfg.h @@ -0,0 +1,369 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jpeglib.h b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jpeglib.h new file mode 100644 index 0000000..1327cff --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/include/jpeglib.h @@ -0,0 +1,1160 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". + */ + +#define JPEG_LIB_VERSION 80 /* Compatibility version 8.0 */ +#define JPEG_LIB_VERSION_MAJOR 8 +#define JPEG_LIB_VERSION_MINOR 4 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.a b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.a new file mode 100644 index 0000000..1fbd0a9 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.la b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.la new file mode 100644 index 0000000..0b8f91c --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.la @@ -0,0 +1,41 @@ +# libjpeg.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libjpeg.so.8' + +# Names of this library. +library_names='libjpeg.so.8.4.0 libjpeg.so.8 libjpeg.so' + +# The name of the static archive. +old_library='libjpeg.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/xz/Documents/testing/compile_test/lpng1637/zlib/rk1808/lib' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libjpeg. +current=12 +age=4 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/xz/Documents/testing/compile_test/jpegsrc.v8d1/jpeg-8d1/rk1808/lib' diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so new file mode 100644 index 0000000..acff391 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so @@ -0,0 +1 @@ +libjpeg.so.8.4.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so.8 b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so.8 new file mode 100644 index 0000000..acff391 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so.8 @@ -0,0 +1 @@ +libjpeg.so.8.4.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so.8.4.0 b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so.8.4.0 new file mode 100644 index 0000000..f91df71 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libjpeg/lib/Linux/libjpeg.so.8.4.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/bin/libpng-config b/rknn_yolo_demo/libs/platform/RK1808/libpng/bin/libpng-config new file mode 100644 index 0000000..ae3d3d4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/bin/libpng-config @@ -0,0 +1 @@ +libpng16-config \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/bin/libpng16-config b/rknn_yolo_demo/libs/platform/RK1808/libpng/bin/libpng16-config new file mode 100644 index 0000000..923d561 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/bin/libpng16-config @@ -0,0 +1,127 @@ +#! /bin/sh + +# libpng-config +# provides configuration info for libpng. + +# Copyright (C) 2002, 2004, 2006, 2007 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Modeled after libxml-config. + +version="1.6.37" +prefix="//home/xz/Documents/testing/compile_test/lpng1637/rk1808" +exec_prefix="${prefix}" +libdir="${exec_prefix}/lib" +includedir="${prefix}/include/libpng16" +libs="-lpng16" +all_libs="-lpng16 -lm -lz -lm " +I_opts="-I${includedir}" +L_opts="-L${libdir}" +R_opts="" +cppflags="" +ccopts="" +ldopts="" + +usage() +{ + cat < + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.37" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 37 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10637 /* 1.6.37 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_37; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/include/libpng16/pngconf.h b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/libpng16/pngconf.h new file mode 100644 index 0000000..927a769 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/libpng16/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.37 + * + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/include/libpng16/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/libpng16/pnglibconf.h new file mode 100644 index 0000000..7f6a817 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/libpng16/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.37 */ + +/* Copyright (c) 2018-2019 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/include/png.h b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/png.h new file mode 100644 index 0000000..bbca0e8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/png.h @@ -0,0 +1 @@ +libpng16/png.h \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/include/pngconf.h b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/pngconf.h new file mode 100644 index 0000000..addd8a1 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/pngconf.h @@ -0,0 +1 @@ +libpng16/pngconf.h \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/include/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/pnglibconf.h new file mode 100644 index 0000000..64d182a --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/include/pnglibconf.h @@ -0,0 +1 @@ +libpng16/pnglibconf.h \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.a b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.a new file mode 100644 index 0000000..5671875 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.a @@ -0,0 +1 @@ +libpng16.a \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.la b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.la new file mode 100644 index 0000000..3a5dc32 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.la @@ -0,0 +1 @@ +libpng16.la \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.so b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.so new file mode 100644 index 0000000..e41f2c3 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng.so @@ -0,0 +1 @@ +libpng16.so \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.a b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.a new file mode 100644 index 0000000..eef42bb Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.la b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.la new file mode 100644 index 0000000..0156394 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.la @@ -0,0 +1,41 @@ +# libpng16.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libpng16.so.16' + +# Names of this library. +library_names='libpng16.so.16.37.0 libpng16.so.16 libpng16.so' + +# The name of the static archive. +old_library='libpng16.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/xz/Documents/testing/compile_test/lpng1637/zlib/rk1808/lib/ -lz -lm' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libpng16. +current=53 +age=37 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='//home/xz/Documents/testing/compile_test/lpng1637/rk1808/lib' diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so new file mode 100644 index 0000000..a5196c4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so @@ -0,0 +1 @@ +libpng16.so.16.37.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so.16 b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so.16 new file mode 100644 index 0000000..a5196c4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so.16 @@ -0,0 +1 @@ +libpng16.so.16.37.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so.16.37.0 b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so.16.37.0 new file mode 100644 index 0000000..35a39c8 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/libpng16.so.16.37.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/pkgconfig/libpng.pc b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/pkgconfig/libpng.pc new file mode 100644 index 0000000..02f0e64 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/pkgconfig/libpng.pc @@ -0,0 +1 @@ +libpng16.pc \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/pkgconfig/libpng16.pc b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/pkgconfig/libpng16.pc new file mode 100644 index 0000000..fa2b2de --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/lib/Linux/pkgconfig/libpng16.pc @@ -0,0 +1,12 @@ +prefix=//home/xz/Documents/testing/compile_test/lpng1637/rk1808 +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/libpng16 + +Name: libpng +Description: Loads and saves PNG files +Version: 1.6.37 +Requires: zlib +Libs: -L${libdir} -lpng16 +Libs.private: -lm -lz -lm +Cflags: -I${includedir} diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man3/libpng.3 b/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man3/libpng.3 new file mode 100644 index 0000000..f374235 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man3/libpng.3 @@ -0,0 +1,6052 @@ +.TH LIBPNG 3 "April 14, 2019" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.6.37 + +.SH SYNOPSIS +\fB#include \fP + +\fBpng_uint_32 png_access_version_number (void);\fP + +\fBvoid png_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP + +\fBpng_voidp png_calloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fBvoid png_chunk_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP + +\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP + +\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP + +\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fBpng_structp png_create_read_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fBpng_structp png_create_write_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask\fP\fB);\fP + +\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP + +\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fBvoid png_err (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_free_default (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP + +\fBpng_byte png_get_bit_depth (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_bKGD (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP + +\fBpng_byte png_get_channels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_cHRM (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP + +\fBpng_uint_32 png_get_cHRM_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP + +\fBpng_uint_32 png_get_cHRM_XYZ (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*red_X\fP\fB, double \fP\fI*red_Y\fP\fB, double \fP\fI*red_Z\fP\fB, double \fP\fI*green_X\fP\fB, double \fP\fI*green_Y\fP\fB, double \fP\fI*green_Z\fP\fB, double \fP\fI*blue_X\fP\fB, double \fP\fI*blue_Y\fP\fB, double \fI*blue_Z\fP\fB);\fP + +\fBpng_uint_32 png_get_cHRM_XYZ_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_fixed_point \fP\fI*int_red_X\fP\fB, png_fixed_point \fP\fI*int_red_Y\fP\fB, png_fixed_point \fP\fI*int_red_Z\fP\fB, png_fixed_point \fP\fI*int_green_X\fP\fB, png_fixed_point \fP\fI*int_green_Y\fP\fB, png_fixed_point \fP\fI*int_green_Z\fP\fB, png_fixed_point \fP\fI*int_blue_X\fP\fB, png_fixed_point \fP\fI*int_blue_Y\fP\fB, png_fixed_point \fI*int_blue_Z\fP\fB);\fP + +\fBpng_uint_32 png_get_chunk_cache_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_alloc_size_t png_get_chunk_malloc_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_byte png_get_color_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_compression_buffer_size (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_byte png_get_compression_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_byte png_get_copyright (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_current_row_number \fI(png_const_structp\fP\fB);\fP + +\fBpng_byte png_get_current_pass_number \fI(png_const_structp\fP\fB);\fP + +\fBpng_voidp png_get_error_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_byte png_get_filter_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_gAMA (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP + +\fBpng_uint_32 png_get_gAMA_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP + +\fBpng_byte png_get_header_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_byte png_get_header_version (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_eXIf (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fI*exif\fP\fB);\fP + +\fBpng_uint_32 png_get_eXIf_1 (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unit_32 \fP\fI*num_exif\fP\fB, png_bytep \fI*exif\fP\fB);\fP + +\fBpng_uint_32 png_get_hIST (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP + +\fBpng_uint_32 png_get_iCCP (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_bytepp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP + +\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP + +\fBpng_uint_32 png_get_image_height (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_image_width (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP + +\fBpng_byte png_get_interlace_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_io_chunk_type (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_io_state (png_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_byte png_get_libpng_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBint png_get_palette_max(png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_voidp png_get_mem_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_oFFs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fBpng_uint_32 png_get_pCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP + +\fBpng_uint_32 png_get_pHYs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fBfloat png_get_pixel_aspect_ratio (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_pHYs_dpi (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fBpng_fixed_point png_get_pixel_aspect_ratio_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_voidp png_get_progressive_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_PLTE (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP + +\fBpng_byte png_get_rgb_to_gray_status (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_rowbytes (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_bytepp png_get_rows (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_sBIT (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP + +\fBvoid png_get_sCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, double* \fP\fIwidth\fP\fB, double* \fIheight\fP\fB);\fP + +\fBvoid png_get_sCAL_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_fixed_pointp \fP\fIwidth\fP\fB, png_fixed_pointp \fIheight\fP\fB);\fP + +\fBvoid png_get_sCAL_s (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_charpp \fP\fIwidth\fP\fB, png_charpp \fIheight\fP\fB);\fP + +\fBpng_bytep png_get_signature (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_sPLT (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_sRGB (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int \fI*file_srgb_intent\fP\fB);\fP + +\fBpng_uint_32 png_get_text (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP + +\fBpng_uint_32 png_get_tIME (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP + +\fBpng_uint_32 png_get_tRNS (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans_alpha\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_color\fP\fB);\fP + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP + +\fBpng_uint_32 png_get_uint_31 (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIbuf\fP\fB);\fP + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP + +\fBpng_uint_32 png_get_unknown_chunks (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP + +\fBpng_voidp png_get_user_chunk_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_user_height_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_voidp png_get_user_transform_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_user_width_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_valid (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP + +\fBfloat png_get_x_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_fixed_point png_get_x_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_int_32 png_get_x_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_int_32 png_get_x_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_x_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_x_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBfloat png_get_y_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_fixed_point png_get_y_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_int_32 png_get_y_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_int_32 png_get_y_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_y_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBpng_uint_32 png_get_y_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP + +\fBint png_image_begin_read_from_file (png_imagep \fP\fIimage\fP\fB, const char \fI*file_name\fP\fB);\fP + +\fBint png_image_begin_read_from_stdio (png_imagep \fP\fIimage\fP\fB, FILE* \fIfile\fP\fB);\fP + +\fBint, png_image_begin_read_from_memory (png_imagep \fP\fIimage\fP\fB, png_const_voidp \fP\fImemory\fP\fB, size_t \fIsize\fP\fB);\fP + +\fBint png_image_finish_read (png_imagep \fP\fIimage\fP\fB, png_colorp \fP\fIbackground\fP\fB, void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP + +\fBvoid png_image_free (png_imagep \fIimage\fP\fB);\fP + +\fBint png_image_write_to_file (png_imagep \fP\fIimage\fP\fB, const char \fP\fI*file\fP\fB, int \fP\fIconvert_to_8bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP + +\fBint png_image_write_to_memory (png_imagep \fP\fIimage\fP\fB, void \fP\fI*memory\fP\fB, png_alloc_size_t * PNG_RESTRICT \fP\fImemory_bytes\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, const void \fI*colormap\fP\fB);\fP + +\fBint png_image_write_to_stdio (png_imagep \fP\fIimage\fP\fB, FILE \fP\fI*file\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP + +\fBvoid png_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, size_t \fIpng_info_struct_size\fP\fB);\fP + +\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP + +\fBvoid png_longjmp (png_structp \fP\fIpng_ptr\fP\fB, int \fIval\fP\fB);\fP + +\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fBpng_voidp png_malloc_default (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fBpng_voidp png_malloc_warn (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fBpng_uint_32 png_permit_mng_features (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fImng_features_permitted\fP\fB);\fP + +\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, size_t \fIbuffer_size\fP\fB);\fP + +\fBsize_t png_process_data_pause (png_structp \fP\fIpng_ptr\fP\fB, int \fIsave\fP\fB);\fP + +\fBpng_uint_32 png_process_data_skip (png_structp \fP\fIpng_ptr\fP\fB);\fP + +\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP + +\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP + +\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBint png_reset_zstream (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP + +\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP + +\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP + +\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fBvoid png_set_alpha_mode (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, double \fIoutput_gamma\fP\fB);\fP + +\fBvoid png_set_alpha_mode_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, png_fixed_point \fIoutput_gamma\fP\fB);\fP + +\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP + +\fBvoid png_set_background_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, png_uint_32 \fIbackground_gamma\fP\fB);\fP + +\fBvoid png_set_benign_errors (png_structp \fP\fIpng_ptr\fP\fB, int \fIallowed\fP\fB);\fP + +\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP + +\fBvoid png_set_check_for_invalid_index (png_structrp \fP\fIpng_ptr\fP\fB, int \fIallowed\fP\fB);\fP + +\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP + +\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP + +\fBvoid png_set_cHRM_XYZ (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIred_X\fP\fB, double \fP\fIred_Y\fP\fB, double \fP\fIred_Z\fP\fB, double \fP\fIgreen_X\fP\fB, double \fP\fIgreen_Y\fP\fB, double \fP\fIgreen_Z\fP\fB, double \fP\fIblue_X\fP\fB, double \fP\fIblue_Y\fP\fB, double \fIblue_Z\fP\fB);\fP + +\fBvoid png_set_cHRM_XYZ_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_fixed_point \fP\fIint_red_X\fP\fB, png_fixed_point \fP\fIint_red_Y\fP\fB, png_fixed_point \fP\fIint_red_Z\fP\fB, png_fixed_point \fP\fIint_green_X\fP\fB, png_fixed_point \fP\fIint_green_Y\fP\fB, png_fixed_point \fP\fIint_green_Z\fP\fB, png_fixed_point \fP\fIint_blue_X\fP\fB, png_fixed_point \fP\fIint_blue_Y\fP\fB, png_fixed_point \fIint_blue_Z\fP\fB);\fP + +\fBvoid png_set_chunk_cache_max (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIuser_chunk_cache_max\fP\fB);\fP + +\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP + +\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP + +\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP + +\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_expand_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_expand_gray_1_2_4_to_8 (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP + +\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP + +\fBvoid png_set_filter_heuristics_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_fixed_point_p \fP\fIfilter_weights\fP\fB, png_fixed_point_p \fIfilter_costs\fP\fB);\fP + +\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP + +\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP + +\fBvoid png_set_gamma_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIscreen_gamma\fP\fB, png_uint_32 \fIdefault_file_gamma\fP\fB);\fP + +\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP + +\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP + +\fBvoid png_set_gray_1_2_4_to_8 (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_eXIf (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fIexif\fP\fB);\fP + +\fBvoid png_set_eXIf_1 (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fInum_exif\fP\fB, png_bytep \fIexif\fP\fB);\fP + +\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP + +\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_const_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_const_bytep \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP + +\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP + +\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP + +\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP + +\fBjmp_buf* png_set_longjmp_fn (png_structp \fP\fIpng_ptr\fP\fB, png_longjmp_ptr \fP\fIlongjmp_fn\fP\fB, size_t \fIjmp_buf_size\fP\fB);\fP + +\fBvoid png_set_chunk_malloc_max (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIuser_chunk_cache_max\fP\fB);\fP + +\fBvoid png_set_compression_buffer_size (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fBvoid png_set_mem_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fBint png_set_option(png_structrp \fP\fIpng_ptr\fP\fB, int \fP\fIoption\fP\fB, int \fIonoff\fP\fB);\fP + +\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_palette_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP + +\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP + +\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP + +\fBvoid png_set_quantize (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_quantize\fP\fB);\fP + +\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP + +\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP + +\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP + +\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP + +\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP + +\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_uint_32 \fP\fIred\fP\fB, png_uint_32 \fIgreen\fP\fB);\fP + +\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP + +\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP + +\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fBvoid png_set_sCAL_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_fixed_point \fP\fIwidth\fP\fB, png_fixed_point \fIheight\fP\fB);\fP + +\fBvoid png_set_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP + +\fBvoid png_set_scale_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP + +\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP + +\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP + +\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIsrgb_intent\fP\fB);\fP + +\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIsrgb_intent\fP\fB);\fP + +\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_strip_error_numbers (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIstrip_mode\fP\fB);\fP + +\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP + +\fBvoid png_set_text_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fBvoid png_set_text_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fBvoid png_set_text_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fBvoid png_set_text_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fBvoid png_set_text_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP + +\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP + +\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans_alpha\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_color\fP\fB);\fP + +\fBvoid png_set_tRNS_to_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP + +\fBvoid png_set_unknown_chunk_location (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP + +\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP + +\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP + +\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP + +\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP + +\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP + +\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, size_t \fP\fIstart\fP\fB, size_t \fInum_to_check\fP\fB);\fP + +\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, size_t \fIlength\fP\fB);\fP + +\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, size_t \fIlength\fP\fB);\fP + +\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP + +\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP + +.SH DESCRIPTION +The +.I libpng +library supports encoding, decoding, and various manipulations of +the Portable Network Graphics (PNG) format image files. It uses the +.IR zlib(3) +compression library. +Following is a copy of the libpng-manual.txt file that accompanies libpng. + +.SH LIBPNG.TXT +libpng-manual.txt - A description on how to use and modify libpng + + Copyright (c) 2018-2019 Cosmin Truta + Copyright (c) 1998-2018 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng version 1.6.36, December 2018, through 1.6.37 - April 2019 + Updated and distributed by Cosmin Truta + Copyright (c) 2018-2019 Cosmin Truta + + libpng versions 0.97, January 1998, through 1.6.35 - July 2018 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2018 Glenn Randers-Pehrson + + libpng 1.0 beta 6 - version 0.96 - May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 - January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + + TABLE OF CONTENTS + + I. Introduction + II. Structures + III. Reading + IV. Writing + V. Simplified API + VI. Modifying/Customizing libpng + VII. MNG support + VIII. Changes to Libpng from version 0.88 + IX. Changes to Libpng from version 1.0.x to 1.2.x + X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + XI. Changes to Libpng from version 1.4.x to 1.5.x + XII. Changes to Libpng from version 1.5.x to 1.6.x + XIII. Detecting libpng + XIV. Source code repository + XV. Coding style + +.SH I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to configure and install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2004 (E)) at +. +The W3C and ISO documents have identical technical content. + +The PNG-1.2 specification is available at +. +It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available as RFC 2083 at + and as a +W3C Recommendation at . + +Some additional chunks are described in the special-purpose public chunks +documents at + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, . +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +.SH II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. Both are internal structures that are no longer exposed +in the libpng interface (as of libpng 1.5.0). + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed, and direct access to the png_info fields was +deprecated.. + +The png_struct structure is the object used by the library to decode a +single image. As of 1.5.0 this structure is also not exposed. + +Almost all libpng APIs require a pointer to a png_struct as the first argument. +Many (in particular the png_set and png_get APIs) also require a pointer +to png_info as the second argument. Some application visible macros +defined in png.h designed for basic data access (reading and writing +integers in the PNG format) don't take a png_info pointer, but it's almost +always safe to assume that a (png_struct*) has to be passed to call an API +function. + +You can have more than one png_info structure associated with an image, +as illustrated in pngtest.c, one for information valid prior to the +IDAT chunks and another (called "end_info" below) for things after them. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include + +and also (as of libpng-1.5.0) the zlib header file, if you need it: + +#include + +.SS Types + +The png.h header file defines a number of integral types used by the +APIs. Most of these are fairly obvious; for example types corresponding +to integers of particular sizes and types for passing color values. + +One exception is how non-integral numbers are handled. For application +convenience most APIs that take such numbers have C (double) arguments; +however, internally PNG, and libpng, use 32 bit signed integers and encode +the value by multiplying by 100,000. As of libpng 1.5.0 a convenience +macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) +which is simply (png_int_32). + +All APIs that take (double) arguments also have a matching API that +takes the corresponding fixed point integer arguments. The fixed point +API has the same name as the floating point one with "_fixed" appended. +The actual range of values permitted in the APIs is frequently less than +the full range of (png_fixed_point) (\-21474 to +21474). When APIs require +a non-negative argument the type is recorded as png_uint_32 above. Consult +the header file and the text below for more information. + +Special care must be take with sCAL chunk handling because the chunk itself +uses non-integral values encoded as strings containing decimal floating point +numbers. See the comments in the header file. + +.SS Configuration + +The main header file function declarations are frequently protected by C +preprocessing directives of the form: + + #ifdef PNG_feature_SUPPORTED + declare-function + #endif + ... + #ifdef PNG_feature_SUPPORTED + use-function + #endif + +The library can be built without support for these APIs, although a +standard build will have all implemented APIs. Application programs +should check the feature macros before using an API for maximum +portability. From libpng 1.5.0 the feature macros set during the build +of libpng are recorded in the header file "pnglibconf.h" and this file +is always included by png.h. + +If you don't need to change the library configuration from the default, skip to +the next section ("Reading"). + +Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all +of the build project files in the 'projects' directory simply copy +scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build +systems do not permit easy auto-configuration of the library - they only +support the default configuration. + +The easiest way to make minor changes to the libpng configuration when +auto-configuration is supported is to add definitions to the command line +using (typically) CPPFLAGS. For example: + +CPPFLAGS=\-DPNG_NO_FLOATING_ARITHMETIC + +will change the internal libpng math implementation for gamma correction and +other arithmetic calculations to fixed point, avoiding the need for fast +floating point support. The result can be seen in the generated pnglibconf.h - +make sure it contains the changed feature macro setting. + +If you need to make more extensive configuration changes - more than one or two +feature macro settings - you can either add \-DPNG_USER_CONFIG to the build +command line and put a list of feature macro settings in pngusr.h or you can set +DFA_XTRA (a makefile variable) to a file containing the same information in the +form of 'option' settings. + +A. Changing pnglibconf.h + +A variety of methods exist to build libpng. Not all of these support +reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be +rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. + +Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt to +pnglibconf.h and changing the lines defining the supported features, paying +very close attention to the 'option' information in scripts/pnglibconf.dfa +that describes those features and their requirements. This is easy to get +wrong. + +B. Configuration using DFA_XTRA + +Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later +variant such as 'nawk' or 'gawk', is available. The configure build will +automatically find an appropriate awk and build pnglibconf.h. +The scripts/pnglibconf.mak file contains a set of make rules for doing the +same thing if configure is not used, and many of the makefiles in the scripts +directory use this approach. + +When rebuilding simply write a new file containing changed options and set +DFA_XTRA to the name of this file. This causes the build to append the new file +to the end of scripts/pnglibconf.dfa. The pngusr.dfa file should contain lines +of the following forms: + +everything = off + +This turns all optional features off. Include it at the start of pngusr.dfa to +make it easier to build a minimal configuration. You will need to turn at least +some features on afterward to enable either reading or writing code, or both. + +option feature on +option feature off + +Enable or disable a single feature. This will automatically enable other +features required by a feature that is turned on or disable other features that +require a feature which is turned off. Conflicting settings will cause an error +message to be emitted by awk. + +setting feature default value + +Changes the default value of setting 'feature' to 'value'. There are a small +number of settings listed at the top of pnglibconf.h, they are documented in the +source code. Most of these values have performance implications for the library +but most of them have no visible effect on the API. Some can also be overridden +from the API. + +This method of building a customized pnglibconf.h is illustrated in +contrib/pngminim/*. See the "$(PNGCONF):" target in the makefile and +pngusr.dfa in these directories. + +C. Configuration using PNG_USER_CONFIG + +If \-DPNG_USER_CONFIG is added to the CPPFLAGS when pnglibconf.h is built, +the file pngusr.h will automatically be included before the options in +scripts/pnglibconf.dfa are processed. Your pngusr.h file should contain only +macro definitions turning features on or off or setting settings. + +Apart from the global setting "everything = off" all the options listed above +can be set using macros in pngusr.h: + +#define PNG_feature_SUPPORTED + +is equivalent to: + +option feature on + +#define PNG_NO_feature + +is equivalent to: + +option feature off + +#define PNG_feature value + +is equivalent to: + +setting feature default value + +Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the +pngusr file you supply override the contents of scripts/pnglibconf.dfa + +If confusing or incomprehensible behavior results it is possible to +examine the intermediate file pnglibconf.dfn to find the full set of +dependency information for each setting and option. Simply locate the +feature in the file and read the C comments that precede it. + +This method is also illustrated in the contrib/pngminim/* makefiles and +pngusr.h. + +.SH III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +.SS Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return ERROR; + } + + if (fread(header, 1, number, fp) != number) + { + return ERROR; + } + + is_png = !png_sig_cmp(header, 0, number); + if (!is_png) + { + return NOT_PNG; + } + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return ERROR; + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return ERROR; + } + +If you want to use your own memory allocation routines, +use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the longjmp buffer every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return ERROR; + } + +Pass (png_infopp)NULL instead of &end_info if you didn't create +an end_info structure. + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +If you want CRC errors to be handled in a different manner than +the default, use + + png_set_crc_action(png_ptr, crit_action, ancil_action); + +The values for png_set_crc_action() say how libpng is to handle CRC errors in +ancillary and critical chunks, and whether to use the data contained +therein. Starting with libpng-1.6.26, this also governs how an ADLER32 error +is handled while reading the IDAT chunk. Note that it is impossible to +"discard" data in a critical chunk. + +Choices for (int) crit_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Choices for (int) ancil_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_DISCARD 2 warn/discard data + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +When the setting for crit_action is PNG_CRC_QUIET_USE, the CRC and ADLER32 +checksums are not only ignored, but they are not evaluated. + +.SS Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_structp png_ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return \-n; /* chunk had an error */ + return 0; /* did not recognize */ + return n; /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks which the callback does not handle will be saved when read. You can +cause them to be discarded by returning '1' ("handled") instead of '0'. This +behavior will change in libpng 1.7 and the default handling set by the +png_set_keep_unknown_chunks() function, described below, will be used when the +callback returns 0. If you want the existing behavior you should set the global +default to PNG_HANDLE_CHUNK_IF_SAFE now; this is compatible with all current +versions of libpng and with 1.7. Libpng 1.6 issues a warning if you keep the +default, or PNG_HANDLE_CHUNK_NEVER, and the callback returns 0. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_structp png_ptr, + png_uint_32 row, int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +When this function is called the row has already been completely processed and +the 'row' and 'pass' refer to the next row to be handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass\-1'; if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + +.SS Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is positive; ignored if + numchunks <= 0). + + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If positive, + only the chunks in the list are affected, + and if negative all unknown chunks and + all known chunks except for the IHDR, + PLTE, tRNS, IDAT, and IEND chunks are + affected. + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. +If you know that your application will never make use of some particular +chunks, use PNG_HANDLE_CHUNK_NEVER (or 1) as demonstrated below. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks + * (use global setting "2" for libpng16 and earlier): + */ + png_set_keep_unknown_chunks(read_ptr, 2, NULL, 0); + + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)(sizeof unused_chunks)/5); + #endif + +.SS User limits + +The PNG specification allows the width and height of an image to be as +large as 2^(31\-1 (0x7fffffff), or about 2.147 billion rows and columns. +For safety, libpng imposes a default limit of 1 million rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to change these limits, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits (libpng may reject some very wide images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). + +When writing a PNG datastream, put this statement before calling +png_write_info() or png_write_png(). + +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. By default, libpng imposes a limit of +a total of 1000 sPLT, tEXt, iTXt, zTXt, and unknown chunks to be stored. +If you have set up both info_ptr and end_info_ptr, the limit applies +separately to each. You can change the limit on the total number of such +chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +Libpng imposes a limit of 8 Megabytes (8,000,000 bytes) on the amount of +memory that any chunk other than IDAT can occupy, originally or when +decompressed (prior to libpng-1.6.32 the limit was only applied to compressed +chunks after decompression). You can change this limit with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +.SS Information about your system + +If you intend to display the PNG or to incorporate it in other image data you +need to tell libpng information about your display or drawing surface so that +libpng can convert the values in the image to match the display. + +From libpng-1.5.4 this information can be set before reading the PNG file +header. In earlier versions png_set_gamma() existed but behaved incorrectly if +called before the PNG file header had been read and png_set_alpha_mode() did not +exist. + +If you need to support versions prior to libpng-1.5.4 test the version number +as illustrated below using "PNG_LIBPNG_VER >= 10504" and follow the procedures +described in the appropriate manual page. + +You give libpng the encoding expected by your system expressed as a 'gamma' +value. You can also specify a default encoding for the PNG file in +case the required information is missing from the file. By default libpng +assumes that the PNG data matches your system, to keep this default call: + + png_set_gamma(png_ptr, screen_gamma, output_gamma); + +or you can use the fixed point equivalent: + + png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, + PNG_FP_1*output_gamma); + +If you don't know the gamma for your system it is probably 2.2 - a good +approximation to the IEC standard for display systems (sRGB). If images are +too contrasty or washed out you got the value wrong - check your system +documentation! + +Many systems permit the system gamma to be changed via a lookup table in the +display driver, a few systems, including older Macs, change the response by +default. As of 1.5.4 three special values are available to handle common +situations: + + PNG_DEFAULT_sRGB: Indicates that the system conforms to the + IEC 61966-2-1 standard. This matches almost + all systems. + PNG_GAMMA_MAC_18: Indicates that the system is an older + (pre Mac OS 10.6) Apple Macintosh system with + the default settings. + PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates + that the system expects data with no gamma + encoding. + +You would use the linear (unencoded) value if you need to process the pixel +values further because this avoids the need to decode and re-encode each +component value whenever arithmetic is performed. A lot of graphics software +uses linear values for this reason, often with higher precision component values +to preserve overall accuracy. + + +The output_gamma value expresses how to decode the output values, not how +they are encoded. The values used correspond to the normal numbers used to +describe the overall gamma of a computer display system; for example 2.2 for +an sRGB conformant system. The values are scaled by 100000 in the _fixed +version of the API (so 220000 for sRGB.) + +The inverse of the value is always used to provide a default for the PNG file +encoding if it has no gAMA chunk and if png_set_gamma() has not been called +to override the PNG gamma information. + +When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode +opaque pixels however pixels with lower alpha values are not encoded, +regardless of the output gamma setting. + +When the standard Porter Duff handling is requested with mode 1 the output +encoding is set to be linear and the output_gamma value is only relevant +as a default for input data that has no gamma information. The linear output +encoding will be overridden if png_set_gamma() is called - the results may be +highly unexpected! + +The following numbers are derived from the sRGB standard and the research +behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of +0.45455 (1/2.2) for PNG. The value implicitly includes any viewing +correction required to take account of any differences in the color +environment of the original scene and the intended display environment; the +value expresses how to *decode* the image for display, not how the original +data was *encoded*. + +sRGB provides a peg for the PNG standard by defining a viewing environment. +sRGB itself, and earlier TV standards, actually use a more complex transform +(a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is +limited to simple power laws.) By saying that an image for direct display on +an sRGB conformant system should be stored with a gAMA chunk value of 45455 +(11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification +makes it possible to derive values for other display systems and +environments. + +The Mac value is deduced from the sRGB based on an assumption that the actual +extra viewing correction used in early Mac display systems was implemented as +a power 1.45 lookup table. + +Any system where a programmable lookup table is used or where the behavior of +the final display device characteristics can be changed requires system +specific code to obtain the current characteristic. However this can be +difficult and most PNG gamma correction only requires an approximate value. + +By default, if png_set_alpha_mode() is not called, libpng assumes that all +values are unencoded, linear, values and that the output device also has a +linear characteristic. This is only very rarely correct - it is invariably +better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the +default if you don't know what the right answer is! + +The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS +10.6) which used a correction table to implement a somewhat lower gamma on an +otherwise sRGB system. + +Both these values are reserved (not simple gamma values) in order to allow +more precise correction internally in the future. + +NOTE: the values can be passed to either the fixed or floating +point APIs, but the floating point API will also accept floating point +values. + +The second thing you may need to tell libpng about is how your system handles +alpha channel information. Some, but not all, PNG files contain an alpha +channel. To display these files correctly you need to compose the data onto a +suitable background, as described in the PNG specification. + +Libpng only supports composing onto a single color (using png_set_background; +see below). Otherwise you must do the composition yourself and, in this case, +you may need to call png_set_alpha_mode: + + #if PNG_LIBPNG_VER >= 10504 + png_set_alpha_mode(png_ptr, mode, screen_gamma); + #else + png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma); + #endif + +The screen_gamma value is the same as the argument to png_set_gamma; however, +how it affects the output depends on the mode. png_set_alpha_mode() sets the +file gamma default to 1/screen_gamma, so normally you don't need to call +png_set_gamma. If you need different defaults call png_set_gamma() before +png_set_alpha_mode() - if you call it after it will override the settings made +by png_set_alpha_mode(). + +The mode is as follows: + + PNG_ALPHA_PNG: The data is encoded according to the PNG +specification. Red, green and blue, or gray, components are +gamma encoded color values and are not premultiplied by the +alpha value. The alpha value is a linear measure of the +contribution of the pixel to the corresponding final output pixel. + +You should normally use this format if you intend to perform +color correction on the color values; most, maybe all, color +correction software has no handling for the alpha channel and, +anyway, the math to handle pre-multiplied component values is +unnecessarily complex. + +Before you do any arithmetic on the component values you need +to remove the gamma encoding and multiply out the alpha +channel. See the PNG specification for more detail. It is +important to note that when an image with an alpha channel is +scaled, linear encoded, pre-multiplied component values must +be used! + +The remaining modes assume you don't need to do any further color correction or +that if you do, your color correction software knows all about alpha (it +probably doesn't!). They 'associate' the alpha with the color information by +storing color channel values that have been scaled by the alpha. The +advantage is that the color channels can be resampled (the image can be +scaled) in this form. The disadvantage is that normal practice is to store +linear, not (gamma) encoded, values and this requires 16-bit channels for +still images rather than the 8-bit channels that are just about sufficient if +gamma encoding is used. In addition all non-transparent pixel values, +including completely opaque ones, must be gamma encoded to produce the final +image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes +described below (the latter being the two common names for associated alpha +color channels). Note that PNG files always contain non-associated color +channels; png_set_alpha_mode() with one of the modes causes the decoder to +convert the pixels to an associated form before returning them to your +application. + +Since it is not necessary to perform arithmetic on opaque color values so +long as they are not to be resampled and are in the final color space it is +possible to optimize the handling of alpha by storing the opaque pixels in +the PNG format (adjusted for the output color space) while storing partially +opaque pixels in the standard, linear, format. The accuracy required for +standard alpha composition is relatively low, because the pixels are +isolated, therefore typically the accuracy loss in storing 8-bit linear +values is acceptable. (This is not true if the alpha channel is used to +simulate transparency over large areas - use 16 bits or the PNG mode in +this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is +treated as opaque only if the alpha value is equal to the maximum value. + + PNG_ALPHA_STANDARD: The data libpng produces is encoded in the +standard way assumed by most correctly written graphics software. +The gamma encoding will be removed by libpng and the +linear component values will be pre-multiplied by the +alpha channel. + +With this format the final image must be re-encoded to +match the display gamma before the image is displayed. +If your system doesn't do that, yet still seems to +perform arithmetic on the pixels without decoding them, +it is broken - check out the modes below. + +With PNG_ALPHA_STANDARD libpng always produces linear +component values, whatever screen_gamma you supply. The +screen_gamma value is, however, used as a default for +the file gamma if the PNG file has no gamma information. + +If you call png_set_gamma() after png_set_alpha_mode() you +will override the linear encoding. Instead the +pre-multiplied pixel values will be gamma encoded but +the alpha channel will still be linear. This may +actually match the requirements of some broken software, +but it is unlikely. + +While linear 8-bit data is often used it has +insufficient precision for any image with a reasonable +dynamic range. To avoid problems, and if your software +supports it, use png_set_expand_16() to force all +components to 16 bits. + + PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD +except that completely opaque pixels are gamma encoded according to +the screen_gamma value. Pixels with alpha less than 1.0 +will still have linear components. + +Use this format if you have control over your +compositing software and so don't do other arithmetic +(such as scaling) on the data you get from libpng. Your +compositing software can simply copy opaque pixels to +the output but still has linear values for the +non-opaque pixels. + +In normal compositing, where the alpha channel encodes +partial pixel coverage (as opposed to broad area +translucency), the inaccuracies of the 8-bit +representation of non-opaque pixels are irrelevant. + +You can also try this format if your software is broken; +it might look better. + + PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; however, all component +values, including the alpha channel are gamma encoded. This is +broken because, in practice, no implementation that uses this choice +correctly undoes the encoding before handling alpha composition. Use this +choice only if other serious errors in the software or hardware you use +mandate it. In most cases of broken software or hardware the bug in the +final display manifests as a subtle halo around composited parts of the +image. You may not even perceive this as a halo; the composited part of +the image may simply appear separate from the background, as though it had +been cut out of paper and pasted on afterward. + +If you don't have to deal with bugs in software or hardware, or if you can fix +them, there are three recommended ways of using png_set_alpha_mode(): + + png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, + screen_gamma); + +You can do color correction on the result (libpng does not currently +support color correction internally). When you handle the alpha channel +you need to undo the gamma encoding and multiply out the alpha. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, + screen_gamma); + png_set_expand_16(png_ptr); + +If you are using the high level interface, don't call png_set_expand_16(); +instead pass PNG_TRANSFORM_EXPAND_16 to the interface. + +With this mode you can't do color correction, but you can do arithmetic, +including composition and scaling, on the data without further processing. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED, + screen_gamma); + +You can avoid the expansion to 16-bit components with this mode, but you +lose the ability to scale the image or perform other linear arithmetic. +All you can do is compose the result onto a matching output. Since this +mode is libpng-specific you also need to write your own composition +software. + +The following are examples of calls to png_set_alpha_mode to achieve the +required overall gamma correction and, where necessary, alpha +premultiplication. + + png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + +Choices for the alpha_mode are + + PNG_ALPHA_PNG 0 /* according to the PNG standard */ + PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ + PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ + PNG_ALPHA_PREMULTIPLIED 1 /* as above */ + PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ + PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_ALPHA_PNG is the default libpng handling of the alpha channel. It is not +pre-multiplied into the color components. In addition the call states +that the output is for a sRGB system and causes all PNG files without gAMA +chunks to be assumed to be encoded using sRGB. + + png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + +In this case the output is assumed to be something like an sRGB conformant +display preceded by a power-law lookup table of power 1.45. This is how +early Mac systems behaved. + + png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + +This is the classic Jim Blinn approach and will work in academic +environments where everything is done by the book. It has the shortcoming +of assuming that input PNG data with no gamma information is linear - this +is unlikely to be correct unless the PNG files were generated locally. +Most of the time the output precision will be so low as to show +significant banding in dark areas of the image. + + png_set_expand_16(pp); + png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + +This is a somewhat more realistic Jim Blinn inspired approach. PNG files +are assumed to have the sRGB encoding if not marked with a gamma value and +the output is always 16 bits per component. This permits accurate scaling +and processing of the data. If you know that your input PNG files were +generated locally you might need to replace PNG_DEFAULT_sRGB with the +correct value for your system. + + png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + +If you just need to composite the PNG image onto an existing background +and if you control the code that does this you can use the optimization +setting. In this case you just copy completely opaque pixels to the +output. For pixels that are not completely transparent (you just skip +those) you do the composition math using png_composite or png_composite_16 +below then encode the resultant 8-bit or 16-bit values to match the output +encoding. + + Other cases + +If neither the PNG nor the standard linear encoding work for you because +of the software or hardware you use then you have a big problem. The PNG +case will probably result in halos around the image. The linear encoding +will probably result in a washed out, too bright, image (it's actually too +contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably +substantially reduce the halos. Alternatively try: + + png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + +This option will also reduce the halos, but there will be slight dark +halos round the opaque parts of the image where the background is light. +In the OPTIMIZED mode the halos will be light halos where the background +is dark. Take your pick - the halos are unavoidable unless you can get +your hardware/software fixed! (The OPTIMIZED approach is slightly +faster.) + +When the default gamma of PNG files doesn't match the output gamma. +If you have PNG files with no gamma information png_set_alpha_mode allows +you to provide a default gamma, but it also sets the output gamma to the +matching value. If you know your PNG files have a gamma that doesn't +match the output you can take advantage of the fact that +png_set_alpha_mode always sets the output gamma but only sets the PNG +default if it is not already set: + + png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + +The first call sets both the default and the output gamma values, the +second call overrides the output gamma without changing the default. This +is easier than achieving the same effect with png_set_gamma. You must use +PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will +fire if more than one call to png_set_alpha_mode and png_set_background is +made in the same read operation, however multiple calls with PNG_ALPHA_PNG +are ignored. + +If you don't need, or can't handle, the alpha channel you can call +png_set_background() to remove it by compositing against a fixed color. Don't +call png_set_strip_alpha() to do this - it will leave spurious pixel values in +transparent parts of this image. + + png_set_background(png_ptr, &background_color, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1); + +The background_color is an RGB or grayscale value according to the data format +libpng will produce for you. Because you don't yet know the format of the PNG +file, if you call png_set_background at this point you must arrange for the +format produced by libpng to always have 8-bit or 16-bit components and then +store the color as an 8-bit or 16-bit color as appropriate. The color contains +separate gray and RGB component values, so you can let libpng produce gray or +RGB output according to the input format, but low bit depth grayscale images +must always be converted to at least 8-bit format. (Even though low bit depth +grayscale images can't have an alpha channel they can have a transparent +color!) + +You set the transforms you need later, either as flags to the high level +interface or libpng API calls for the low level interface. For reference the +settings and API calls required are: + +8-bit values: + PNG_TRANSFORM_SCALE_16 | PNG_EXPAND + png_set_expand(png_ptr); png_set_scale_16(png_ptr); + + If you must get exactly the same inaccurate results + produced by default in versions prior to libpng-1.5.4, + use PNG_TRANSFORM_STRIP_16 and png_set_strip_16(png_ptr) + instead. + +16-bit values: + PNG_TRANSFORM_EXPAND_16 + png_set_expand_16(png_ptr); + +In either case palette image data will be expanded to RGB. If you just want +color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr) +to the list. + +Calling png_set_background before the PNG file header is read will not work +prior to libpng-1.5.4. Because the failure may result in unexpected warnings or +errors it is therefore much safer to call png_set_background after the head has +been read. Unfortunately this means that prior to libpng-1.5.4 it cannot be +used with the high level interface. + +.SS The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_SCALE_16 Strip 16-bit samples to + 8-bit accurately + PNG_TRANSFORM_STRIP_16 Chop 16-bit samples to + 8-bit less accurately + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + PNG_TRANSFORM_EXPAND_16 Expand samples to 16 bits + +(This excludes setting a background color, doing gamma transformation, +quantizing, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/(sizeof (png_byte))) + png_error (png_ptr, + "Image is too tall to process in memory"); + + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + + row_pointers = png_malloc(png_ptr, + height*(sizeof (png_bytep))); + + for (int i=0; i PNG_SIZE_MAX/(width*pixel_size)) { + png_error(png_ptr,"image_data buffer would be too large"); + } + + png_bytep buffer=png_malloc(png_ptr,height*width*pixel_size); + + for (int i=0; i) and +png_get_(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_ are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + +The colorspace data from gAMA, cHRM, sRGB, iCCP, and sBIT chunks +is simply returned to give the application information about how the +image was encoded. Libpng itself only does transformations using the file +gamma when combining semitransparent pixels with the background color, and, +since libpng-1.6.0, when converting between 8-bit sRGB and 16-bit linear pixels +within the simplified API. Libpng also uses the file gamma when converting +RGB to gray, beginning with libpng-1.0.5, if the application calls +png_set_rgb_to_gray()). + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + + palette - the palette for the file + (array of png_color) + + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); + + file_gamma - the gamma at which the file is + written (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which the + file is written + + png_get_cHRM(png_ptr, info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y) + png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z, + &green_X, &green_Y, &green_Z, &blue_X, &blue_Y, + &blue_Z) + png_get_cHRM_fixed(png_ptr, info_ptr, &int_white_x, + &int_white_y, &int_red_x, &int_red_y, + &int_green_x, &int_green_y, &int_blue_x, + &int_blue_y) + png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &int_red_X, &int_red_Y, + &int_red_Z, &int_green_X, &int_green_Y, + &int_green_Z, &int_blue_X, &int_blue_Y, + &int_blue_Z) + + {white,red,green,blue}_{x,y} + A color space encoding specified using the + chromaticities of the end points and the + white point. (PNG_INFO_cHRM) + + {red,green,blue}_{X,Y,Z} + A color space encoding specified using the + encoding end points - the CIE tristimulus + specification of the intended color of the red, + green and blue channels in the PNG RGB data. + The white point is simply the sum of the three + end points. (PNG_INFO_cHRM) + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + + srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, + &num_trans, &trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_get_eXIf_1(png_ptr, info_ptr, &num_exif, &exif); + (PNG_INFO_eXIf) + + exif - Exif profile (array of png_byte) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + + background - background color (of type + png_color_16p) (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + + num_comments - number of comments + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + + text_ptr[i].text - text comments for current + keyword. Can be empty. + + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + + text_ptr[i].lang - language of comment (empty + string for unknown). + + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist when the + library is built with iTXt chunk support. Prior to + libpng-1.4.0 the library was built by default without + iTXt support. Also note that when iTXt is supported, + they contain NULL pointers when the "compression" + field contains PNG_TEXT_COMPRESSION_NONE or + PNG_TEXT_COMPRESSION_zTXt. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + + num_spalettes - number of sPLT chunks read. + + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + + offset_x - positive offset from the left edge + of the screen (can be negative) + + offset_y - positive offset from the top edge + of the screen (can be negative) + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + + res_x - pixels/unit physical resolution in + x direction + + res_y - pixels/unit physical resolution in + x direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + (expressed as a string) + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + + unknowns[i].name - name of unknown chunk + + unknowns[i].data - data of unknown chunk + + unknowns[i].size - size of unknown chunk's data + + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + + The value of "location" is a bitwise "or" of + + PNG_HAVE_IHDR (0x01) + PNG_HAVE_PLTE (0x02) + PNG_AFTER_IDAT (0x08) + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y + + Note that because of the way the resolutions are + stored internally, the inch conversions won't + come out to exactly even number. For example, + 72 dpi is stored as 0.28346 pixels/meter, and + when this is retrieved it is 71.9988 dpi, so + be sure to round the returned value appropriately + if you want to display a reasonable-looking result. + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel. The + remark about inexact inch conversions applies here + as well, because a value in inches can't always be + converted to microns and back without some loss + of precision. + +For more information, see the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +.SS Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. + +Transformations you request are ignored if they don't have any meaning for a +particular input data format. However some transformations can have an effect +as a result of a previous transformation. If you specify a contradictory set of +transformations, for example both adding and removing the alpha channel, you +cannot predict the final result. + +The color used for the transparency values should be supplied in the same +format/depth as the current image data. It is stored in the same format/depth +as the image data in a tRNS chunk, so this is what libpng expects for this data. + +The color used for the background value depends on the need_expand argument as +described below. + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the byte, +unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. + +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_scale_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler() or +png_set_add alpha() is called to insert two filler bytes, either before +or after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can +be modified with png_set_filler(), png_set_add_alpha(), png_set_strip_16(), +or png_set_scale_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + +The first two functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was +added. It expands the sample depth without changing tRNS to alpha. + +As of libpng version 1.5.2, png_set_expand_16() was added. It behaves as +png_set_expand(); however, the resultant channels have 16 bits rather than 8. +Use this when the output color or gray channels are made linear to avoid fairly +severe accuracy loss. + + if (bit_depth < 16) + png_set_expand_16(png_ptr); + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8-bit. + + if (bit_depth == 16) +#if PNG_LIBPNG_VER >= 10504 + png_set_scale_16(png_ptr); +#else + png_set_strip_16(png_ptr); +#endif + +(The more accurate "png_set_scale_16()" API became available in libpng version +1.5.4). + +If you need to process the alpha channel on the image separately from the image +data (for example if you convert it to a bitmap mask) it is possible to have +libpng strip the channel leaving just RGB or gray data: + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +If you strip the alpha channel you need to find some other way of dealing with +the information. If, instead, you want to convert the image to an opaque +version with no alpha channel use png_set_background; see below. + +As of libpng version 1.5.2, almost all useful expansions are supported, the +major ommissions are conversion of grayscale to indexed images (which can be +done trivially in the application) and conversion of indexed to grayscale (which +can be done by a trivial manipulation of the palette.) + +In the following table, the 01 means grayscale with depth<8, 31 means +indexed with depth<8, other numerals represent the color type, "T" means +the tRNS chunk is present, A means an alpha channel is present, and O +means tRNS or alpha is present but all pixels in the image are opaque. + + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + TO + 01 - [G] - - - - - - - - - - - - - + 31 [Q] Q [Q] [Q] [Q] Q Q Q Q Q Q [Q] [Q] Q Q + 0 1 G + . . G G G G G G B B GB GB + 0T lt Gt t + . Gt G G Gt G G Bt Bt GBt GBt + 0O lt Gt t . + Gt Gt G Gt Gt G Bt Bt GBt GBt + 2 C P C C C + . . C - - CB CB B B + 2T Ct - Ct C C t + t - - - CBt CBt Bt Bt + 2O Ct - Ct C C t t + - - - CBt CBt Bt Bt + 3 [Q] p [Q] [Q] [Q] Q Q Q + . . [Q] [Q] Q Q + 3T [Qt] p [Qt][Q] [Q] Qt Qt Qt t + t [Qt][Qt] Qt Qt + 3O [Qt] p [Qt][Q] [Q] Qt Qt Qt t t + [Qt][Qt] Qt Qt + 4A lA G A T T GA GT GT GA GT GT + BA G GBA + 4O lA GBA A T T GA GT GT GA GT GT BA + GBA G + 6A CA PA CA C C A T tT PA P P C CBA + BA + 6O CA PBA CA C C A tT T PA P P CBA C BA + + +Within the matrix, + "+" identifies entries where 'from' and 'to' are the same. + "-" means the transformation is not supported. + "." means nothing is necessary (a tRNS chunk can just be ignored). + "t" means the transformation is obtained by png_set_tRNS. + "A" means the transformation is obtained by png_set_add_alpha(). + "X" means the transformation is obtained by png_set_expand(). + "1" means the transformation is obtained by + png_set_expand_gray_1_2_4_to_8() (and by png_set_expand() + if there is no transparency in the original or the final + format). + "C" means the transformation is obtained by png_set_gray_to_rgb(). + "G" means the transformation is obtained by png_set_rgb_to_gray(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "p" means the transformation is obtained by png_set_packing(). + "Q" means the transformation is obtained by png_set_quantize(). + "T" means the transformation is obtained by + png_set_tRNS_to_alpha(). + "B" means the transformation is obtained by + png_set_background(), or png_strip_alpha(). + +When an entry has multiple transforms listed all are required to cause the +right overall transformation. When two transforms are separated by a comma +either will do the job. When transforms are enclosed in [] the transform should +do the job but this is currently unimplemented - a different format will result +if the suggested transformations are used. + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8-bit or 16-bit number to fill with, and the location +is either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. When filling an 8-bit pixel, +the least significant 8 bits of the number are used, if a 16-bit number is +supplied. This transformation does not affect images that already have full +alpha channels. To add an opaque alpha channel, use filler=0xffff and +PNG_FILLER_AFTER which will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +The png_set_add_alpha() function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray(png_ptr, error_action, + double red_weight, double green_weight); + + error_action = 1: silently do the conversion + + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component + + green_weight: weight of green component + If either weight is negative, default + weights are used. + +In the corresponding fixed point API the red_weight and green_weight values are +simply scaled by 100,000: + + png_set_rgb_to_gray(png_ptr, error_action, + png_fixed_point red_weight, + png_fixed_point green_weight); + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. Background and sBIT data +will be silently converted to grayscale, using the green channel +data for sBIT, regardless of the error_action setting. + +The default values come from the PNG file cHRM chunk if present; otherwise, the +defaults correspond to the ITU-R recommendation 709, and also the sRGB color +space, as recommended in the Charles Poynton's Colour FAQ, +Copyright (c) 2006-11-28 Charles Poynton, in section 9: + + + + Y = 0.2126 * R + 0.7152 * G + 0.0722 * B + +Previous versions of this document, 1998 through 2002, recommended a slightly +different formula: + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng uses an integer approximation: + + Y = (6968 * R + 23434 * G + 2366 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +can be determined. + +The png_set_background() function has been described already; it tells libpng to +composite images with alpha or simple transparency against the supplied +background color. For compatibility with versions of libpng earlier than +libpng-1.5.4 it is recommended that you call the function after reading the file +header, even if you don't want to use the color in a bKGD chunk, if one exists. + +If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng how the color is represented, both the format of the +component values in the color (the number of bits) and the gamma encoding of the +color. The function takes two arguments, background_gamma_mode and need_expand +to convey this information; however, only two combinations are likely to be +useful: + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1/*needs to be expanded*/, 1); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1); + +The second call was described above - my_background is in the format of the +final, display, output produced by libpng. Because you now know the format of +the PNG it is possible to avoid the need to choose either 8-bit or 16-bit +output and to retain palette images (the palette colors will be modified +appropriately and the tRNS chunk removed.) However, if you are doing this, +take great care not to ask for transformations without checking first that +they apply! + +In the first call the background color has the original bit depth and color type +of the PNG file. So, for palette images the color is supplied as a palette +index and for low bit greyscale images the color is a reduced bit value in +image_background->gray. + +If you didn't call png_set_gamma() before reading the file header, for example +if you need your code to remain compatible with older versions of libpng prior +to libpng-1.5.4, this is the place to call it. + +Do not call it if you called png_set_alpha_mode(); doing so will damage the +settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is +supported then you can certainly do png_set_gamma() before reading the PNG +header.) + +This API unconditionally sets the screen and file gamma values, so it will +override the value in the PNG file unless it is called before the PNG file +reading starts. For this reason you must always call it with the PNG file +value when you call it in this position: + + if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma(png_ptr, screen_gamma, file_gamma); + + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries than will fit on your screen, png_set_quantize() +will do that. Note that this is a simple match quantization that merely +finds the closest color available. This should work fairly well with +optimized palettes, but fairly badly with linear color cubes. If you +pass a palette that is larger than maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, libpng will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16-bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_structp png_ptr, png_row_infop + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. Take care with +interlaced images if you do the interlace yourself - the width of the row is the +width in 'row_info', not the overall image width. + +If supported, libpng provides two information routines that you can use to find +where you are in processing the image: + + png_get_current_pass_number(png_structp png_ptr); + png_get_current_row_number(png_structp png_ptr); + +Don't try using these outside a transform callback - firstly they are only +supported if user transforms are supported, secondly they may well return +unexpected results unless the row is actually being processed at the moment they +are called. + +With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. + + png_read_update_info(png_ptr, info_ptr); + +This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. You may +only call png_read_update_info() once with a particular info_ptr. + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Be sure that your platform can allocate the buffer that you'll need. +libpng internally checks for oversize width, but you'll need to +do your own check for number_of_rows*width*pixel_size if you are using +a multiple-row buffer: + + /* Guard against integer overflow */ + if (number_of_rows > PNG_SIZE_MAX/(width*pixel_size)) { + png_error(png_ptr,"image_data buffer would be too large"); + } + +Remember: Before you call png_read_update_info(), the png_get_*() +functions return the values corresponding to the original PNG image. +After you call png_read_update_info the values refer to the image +that libpng will output. Consequently you must call all the png_set_ +functions before you call png_read_update_info(). This is particularly +important for png_set_interlace_handling() - if you are going to call +png_read_update_info() you must call png_set_interlace_handling() before +it unless you want to receive interlaced output. + +.SS Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() (unless you call +png_read_update_info()) or call this function multiple times, or any +of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7); +a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. This number is defined (from libpng 1.5) as +PNG_INTERLACE_ADAM7_PASSES in png.h + +libpng can fill out those images or it can give them to you "as is". +It is almost always better to have libpng handle the interlacing for you. +If you want the images filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If, as is likely, you want libpng to expand the images, call this before +calling png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. This function can be +called even if the file is not interlaced, where it will return one pass. +You then need to read the whole image 'number_of_passes' times. Each time +will distribute the pixels from the current pass to the correct place in +the output image, so you need to supply the same rows to png_read_rows in +each pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_row() or +png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + or + png_read_row(png_ptr, row_pointers, NULL); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + or + png_read_row(png_ptr, NULL, row_pointers); + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. +Each of the images is a valid image by itself; however, you will almost +certainly need to distribute the pixels from each sub-image to the +correct place. This is where everything gets very tricky. + +If you want to retrieve the separate images you must pass the correct +number of rows to each successive call of png_read_rows(). The calculation +gets pretty complicated for small images, where some sub-images may +not even exist because either their width or height ends up zero. +libpng provides two macros to help you in 1.5 and later versions: + + png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); + png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); + +Respectively these tell you the width and height of the sub-image +corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - +this can be confusing because the specification refers to the same passes +as 1 to 7! Be careful, you must check both the width and height before +calling png_read_rows() and not call it for that pass if either is zero. + +You can, of course, read each sub-image row by row. If you want to +produce optimal code to make a pixel-by-pixel transformation of an +interlaced image this is the best approach; read each row of each pass, +transform it, and write it out to a new interlaced image. + +If you want to de-interlace the image yourself libpng provides further +macros to help that tell you where to place the pixels in the output image. +Because the interlacing scheme is rectangular - sub-image pixels are always +arranged on a rectangular grid - all you need to know for each pass is the +starting column and row in the output image of the first pixel plus the +spacing between each pixel. As of libpng 1.5 there are four macros to +retrieve this information: + + png_uint_32 x = PNG_PASS_START_COL(pass); + png_uint_32 y = PNG_PASS_START_ROW(pass); + png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); + png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); + +These allow you to write the obvious loop: + + png_uint_32 input_y = 0; + png_uint_32 output_y = PNG_PASS_START_ROW(pass); + + while (output_y < output_image_height) + { + png_uint_32 input_x = 0; + png_uint_32 output_x = PNG_PASS_START_COL(pass); + + while (output_x < output_image_width) + { + image[output_y][output_x] = + subimage[pass][input_y][input_x++]; + + output_x += xStep; + } + + ++input_y; + output_y += yStep; + } + +Notice that the steps between successive output rows and columns are +returned as shifts. This is possible because the pixels in the subimages +are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original +image. In practice you may need to directly calculate the output coordinate +given an input coordinate. libpng provides two further macros for this +purpose: + + png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); + png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); + +Finally a pair of macros are provided to tell you if a particular image +row or column appears in a given pass: + + int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); + int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); + +Bear in mind that you will probably also need to check the width and height +of the pass in addition to the above to be sure the pass even exists! + +With any luck you are convinced by now that you don't want to do your own +interlace handling. In reality normally the only good reason for doing this +is if you are processing PNG files on a pixel-by-pixel basis and don't want +to load the whole file into memory when it is interlaced. + +libpng includes a test program, pngvalid, that illustrates reading and +writing of interlaced images. If you can't get interlacing to work in your +code and don't want to leave it to libpng (the recommended approach), see +how pngvalid.c does it. + +.SS Finishing a sequential read + +After you are finished reading the image through the +low-level interface, you can finish reading the file. + +If you want to use a different crc action for handling CRC errors in +chunks after the image data, you can call png_set_crc_action() +again at this point. + +If you are interested in comments or time, which may be stored either +before or after the image data, you should pass the separate png_info +struct if you want to keep the comments from before and after the image +separate. + + png_infop end_info = png_create_info_struct(png_ptr); + + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return ERROR; + } + + png_read_end(png_ptr, end_info); + +If you are not interested, you should still call png_read_end() +but you can pass NULL, avoiding the need to create an end_info structure. +If you do this, libpng will not process any chunks after IDAT other than +skipping over them and perhaps (depending on whether you have called +png_set_crc_action) checking their CRCs while looking for the IEND chunk. + + png_read_end(png_ptr, (png_infop)NULL); + +If you don't call png_read_end(), then your file pointer will be +left pointing to the first chunk after the last IDAT, which is probably +not what you want if you expect to read something beyond the end of +the PNG datastream. + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +or, if you didn't create an end_info structure, + + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (\-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not \-1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_calloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_calloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_eXIf, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +.SS Reading PNG files progressively + +The progressive reader is slightly different from the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return ERROR; + + info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return ERROR; + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return ERROR; + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return ERROR; + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less than 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + + /* At this point you can call png_process_data_skip if + you want to handle data the library will skip yourself; + it simply returns the number of bytes to skip (and stops + libpng skipping that number of bytes on the next + png_process_data call). + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + + This is where you turn on interlace handling, + assuming you don't want to do it yourself. + + If you need to you can stop the processing of + your original input data at this point by calling + png_process_data_pause. This returns the number + of unprocessed bytes from the last png_process_data + call - it is up to you to ensure that the next call + sees these bytes again. If you don't want to bother + with this you can get libpng to cache the unread + bytes by setting the 'save' parameter (see png.h) but + then libpng will have to copy the data internally. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + If you did not turn on interlace handling then + the callback is called for each row of each + sub-image when the image is interlaced. In this + case 'row_num' is the row in the sub-image, not + the row in the output image as it is in all other + cases. + + For the non-NULL rows of interlaced images when + you have switched on libpng interlace handling, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases if you switch on interlace handling; + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + + You can also call png_process_data_pause in this + callback - see above. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +.SH IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +.SS Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + + if (!fp) + return ERROR; + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return ERROR; + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return ERROR; + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return ERROR; + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Checking for invalid palette index on write was added at libpng +1.5.10. If a pixel contains an invalid (out-of-range) index libpng issues +a benign error. This is enabled by default because this condition is an +error according to the PNG specification, Clause 11.3.2, but the error can +be ignored in each png_ptr with + + png_set_check_for_invalid_index(png_ptr, 0); + +If the error is ignored, or if png_benign_error() treats it as a warning, +any invalid pixels are written as-is by the encoder, resulting in an +invalid PNG datastream as output. In this case the application is +responsible for ensuring that the pixel indexes are in range when it writes +a PLTE chunk with fewer entries than the bit depth would allow. + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +.SS Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_structp png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +When this function is called the row has already been completely processed and +it has also been written out. The 'row' and 'pass' refer to the next row to be +handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass\-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. + */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS | PNG_FAST_FILTERS); + +If an application wants to start and stop using particular filters during +compression, it should start out with all of the filters (to ensure that +the previous row of pixels will be stored in case it's needed later), +and then add and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + #include zlib.h + + /* Set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* Set other zlib parameters for compressing IDAT */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + + /* Set zlib parameters for text compression + * If you don't call these, the parameters + * fall back on those defined for IDAT chunks + */ + png_set_text_compression_mem_level(png_ptr, 8); + png_set_text_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_text_compression_window_bits(png_ptr, 15); + png_set_text_compression_method(png_ptr, 8); + +.SS Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + + width - holds the width of the image + in pixels (up to 2^31). + + height - holds the height of the image + in pixels (up to 2^31). + + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + + png_set_gAMA(png_ptr, info_ptr, file_gamma); + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); + + file_gamma - the gamma at which the image was + created (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which + the image was created + + png_set_cHRM(png_ptr, info_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y) + png_set_cHRM_XYZ(png_ptr, info_ptr, red_X, red_Y, red_Z, green_X, + green_Y, green_Z, blue_X, blue_Y, blue_Z) + png_set_cHRM_fixed(png_ptr, info_ptr, int_white_x, int_white_y, + int_red_x, int_red_y, int_green_x, int_green_y, + int_blue_x, int_blue_y) + png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, int_red_X, int_red_Y, + int_red_Z, int_green_X, int_green_Y, int_green_Z, + int_blue_X, int_blue_Y, int_blue_Z) + + {white,red,green,blue}_{x,y} + A color space encoding specified using the chromaticities + of the end points and the white point. + + {red,green,blue}_{X,Y,Z} + A color space encoding specified using the encoding end + points - the CIE tristimulus specification of the intended + color of the red, green and blue channels in the PNG RGB + data. The white point is simply the sum of the three end + points. + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans_alpha, + num_trans, trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_set_eXIf_1(png_ptr, info_ptr, num_exif, exif); + + exif - Exif profile (array of + png_byte) (PNG_INFO_eXIf) + + png_set_hIST(png_ptr, info_ptr, hist); + + hist - histogram of palette (array of + png_uint_16) (PNG_INFO_hIST) + + png_set_tIME(png_ptr, info_ptr, mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + + background - background color (of type + png_color_16p) (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist when the + library is built with iTXt chunk support. Prior to + libpng-1.4.0 the library was built by default without + iTXt support. Also note that when iTXt is supported, + they contain NULL pointers when the "compression" + field contains PNG_TEXT_COMPRESSION_NONE or + PNG_TEXT_COMPRESSION_zTXt. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + + offset_x - positive offset from the left + edge of the screen + + offset_y - positive offset from the top + edge of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + + res_x - pixels/unit physical resolution + in x direction + + res_y - pixels/unit physical resolution + in y direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + expressed as a string + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around a few hundred bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct). + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + + Author Name of image's creator + + Description Description of image (possibly long) + + Copyright Copyright notice + + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + + Software Software used to create the image + + Disclaimer Legal disclaimer + + Warning Warning of nature of content + + Source Device used to create the image + + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123_buffer(buffer, png_timep) is provided to +convert from PNG time to an RFC 1123 format string. The caller must provide +a writeable buffer of at least 29 bytes. + +.SS Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up private chunks +for writing. You give it a chunk name, location, raw data, and a size. You +also must use png_set_keep_unknown_chunks() to ensure that libpng will +handle them. That's all there is to it. The chunks will be written by the +next following png_write_info_before_PLTE, png_write_info, or png_write_end +function, depending upon the specified location. Any chunks previously +read into the info structure's unknown-chunk list will also be written out +in a sequence that satisfies the PNG specification's ordering rules. + +Here is an example of writing two private chunks, prVt and miNE: + + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + /* Set unknown chunk data */ + png_unknown_chunk unk_chunk[2]; + strcpy((char *) unk_chunk[0].name, "prVt"; + unk_chunk[0].data = (unsigned char *) "PRIVATE DATA"; + unk_chunk[0].size = strlen(unk_chunk[0].data)+1; + unk_chunk[0].location = PNG_HAVE_IHDR; + strcpy((char *) unk_chunk[1].name, "miNE"; + unk_chunk[1].data = (unsigned char *) "MY CHUNK DATA"; + unk_chunk[1].size = strlen(unk_chunk[0].data)+1; + unk_chunk[1].location = PNG_AFTER_IDAT; + png_set_unknown_chunks(write_ptr, write_info_ptr, + unk_chunk, 2); + /* Needed because miNE is not safe-to-copy */ + png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, + (png_bytep) "miNE", 1); + # if PNG_LIBPNG_VER < 10600 + /* Deal with unknown chunk location bug in 1.5.x and earlier */ + png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_IHDR); + png_set_unknown_chunk_location(png, info, 1, PNG_AFTER_IDAT); + # endif + # if PNG_LIBPNG_VER < 10500 + /* PNG_AFTER_IDAT writes two copies of the chunk prior to libpng-1.5.0, + * one before IDAT and another after IDAT, so don't use it; only use + * PNG_HAVE_IHDR location. This call resets the location previously + * set by assignment and png_set_unknown_chunk_location() for chunk 1. + */ + png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_IHDR); + # endif + #endif + +.SS The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +.SS The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + + else + { + sig_bit.gray = true_bit_depth; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16-bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_structp png_ptr, png_row_infop + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. If supported +libpng also supplies an information routine that may be called from +your callback: + + png_get_current_row_number(png_ptr); + png_get_current_pass_number(png_ptr); + +This returns the current row passed to the transform. With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +.SS Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all the sub-images +(png_set_interlace_handling() returns the number of sub-images.) + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, number_of_rows); + +Think carefully before you write an interlaced image. Typically code that +reads such images reads all the image data into memory, uncompressed, before +doing any processing. Only code that can display an image on the fly can +take advantage of the interlacing and even then the image has to be exactly +the correct size for the output device, because scaling an image requires +adjacent pixels and these are not available until all the passes have been +read. + +If you do write an interlaced image you will hardly ever need to handle +the interlacing yourself. Call png_set_interlace_handling() and use the +approach described above. + +The only time it is conceivable that you will really need to write an +interlaced image pass-by-pass is when you have read one pass by pass and +made some pixel-by-pixel transformation to it, as described in the read +code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros +to determine the size of each sub-image in turn and simply write the rows +you obtained from the read code. + +.SS Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (\-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not \-1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_calloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_calloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +.SH V. Simplified API + +The simplified API, which became available in libpng-1.6.0, hides the details +of both libpng and the PNG file format itself. +It allows PNG files to be read into a very limited number of +in-memory bitmap formats or to be written from the same formats. If these +formats do not accommodate your needs then you can, and should, use the more +sophisticated APIs above - these support a wide variety of in-memory formats +and a wide variety of sophisticated transformations to those formats as well +as a wide variety of APIs to manipulate ancillary information. + +To read a PNG file using the simplified API: + + 1) Declare a 'png_image' structure (see below) on the stack, set the + version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + (this is REQUIRED, your program may crash if you don't do it.) + + 2) Call the appropriate png_image_begin_read... function. + + 3) Set the png_image 'format' member to the required sample format. + + 4) Allocate a buffer for the image and, if required, the color-map. + + 5) Call png_image_finish_read to read the image and, if required, the + color-map into your buffers. + +There are no restrictions on the format of the PNG input itself; all valid +color types, bit depths, and interlace methods are acceptable, and the +input image is transformed as necessary to the requested in-memory format +during the png_image_finish_read() step. The only caveat is that if you +request a color-mapped image from a PNG that is full-color or makes +complex use of an alpha channel the transformation is extremely lossy and the +result may look terrible. + +To write a PNG file using the simplified API: + + 1) Declare a 'png_image' structure on the stack and memset() + it to all zero. + + 2) Initialize the members of the structure that describe the + image, setting the 'format' member to the format of the + image samples. + + 3) Call the appropriate png_image_write... function with a + pointer to the image and, if necessary, the color-map to write + the PNG data. + +png_image is a structure that describes the in-memory format of an image +when it is being read or defines the in-memory format of an image that you +need to write. The "png_image" structure contains the following members: + + png_controlp opaque Initialize to NULL, free with png_image_free + png_uint_32 version Set to PNG_IMAGE_VERSION + png_uint_32 width Image width in pixels (columns) + png_uint_32 height Image height in pixels (rows) + png_uint_32 format Image format as defined below + png_uint_32 flags A bit mask containing informational flags + png_uint_32 colormap_entries; Number of entries in the color-map + png_uint_32 warning_or_error; + char message[64]; + +In the event of an error or warning the "warning_or_error" +field will be set to a non-zero value and the 'message' field will contain +a '\0' terminated string with the libpng error or warning message. If both +warnings and an error were encountered, only the error is recorded. If there +are multiple warnings, only the first one is recorded. + +The upper 30 bits of the "warning_or_error" value are reserved; the low two +bits contain a two bit code such that a value more than 1 indicates a failure +in the API just called: + + 0 - no warning or error + 1 - warning + 2 - error + 3 - error preceded by warning + +The pixels (samples) of the image have one to four channels whose components +have original values in the range 0 to 1.0: + + 1: A single gray or luminance channel (G). + 2: A gray/luminance channel and an alpha channel (GA). + 3: Three red, green, blue color channels (RGB). + 4: Three color channels and an alpha channel (RGBA). + +The channels are encoded in one of two ways: + + a) As a small integer, value 0..255, contained in a single byte. For the +alpha channel the original value is simply value/255. For the color or +luminance channels the value is encoded according to the sRGB specification +and matches the 8-bit format expected by typical display devices. + +The color/gray channels are not scaled (pre-multiplied) by the alpha +channel and are suitable for passing to color management software. + + b) As a value in the range 0..65535, contained in a 2-byte integer, in +the native byte order of the platform on which the application is running. +All channels can be converted to the original value by dividing by 65535; all +channels are linear. Color channels use the RGB encoding (RGB end-points) of +the sRGB specification. This encoding is identified by the +PNG_FORMAT_FLAG_LINEAR flag below. + +When the simplified API needs to convert between sRGB and linear colorspaces, +the actual sRGB transfer curve defined in the sRGB specification (see the +article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +approximation used elsewhere in libpng. + +When an alpha channel is present it is expected to denote pixel coverage +of the color or luminance channels and is returned as an associated alpha +channel: the color/gray channels are scaled (pre-multiplied) by the alpha +value. + +The samples are either contained directly in the image data, between 1 and 8 +bytes per pixel according to the encoding, or are held in a color-map indexed +by bytes in the image data. In the case of a color-map the color-map entries +are individual samples, encoded as above, and the image data has one byte per +pixel to select the relevant sample from the color-map. + +PNG_FORMAT_* + +The #defines to be used in png_image::format. Each #define identifies a +particular layout of channel data and, if present, alpha values. There are +separate defines for each of the two component encodings. + +A format is built up using single bit flag values. All combinations are +valid. Formats can be built up from the flag values or you can use one of +the predefined values below. When testing formats always use the FORMAT_FLAG +macros to test for individual features - future versions of the library may +add new flags. + +When reading or writing color-mapped images the format should be set to the +format of the entries in the color-map then png_image_{read,write}_colormap +called to read or write the color-map and set the format correctly for the +image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + +NOTE: libpng can be built with particular features disabled. If you see +compiler errors because the definition of one of the following flags has been +compiled out it is because libpng does not have the required support. It is +possible, however, for the libpng configuration to enable the format on just +read or just write; in that case you may see an error at run time. +You can guard against this by checking for the definition of the +appropriate "_SUPPORTED" macro, one of: + + PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + + PNG_FORMAT_FLAG_ALPHA format with an alpha channel + PNG_FORMAT_FLAG_COLOR color format: otherwise grayscale + PNG_FORMAT_FLAG_LINEAR 2-byte channels else 1-byte + PNG_FORMAT_FLAG_COLORMAP image data is color-mapped + PNG_FORMAT_FLAG_BGR BGR colors, else order is RGB + PNG_FORMAT_FLAG_AFIRST alpha channel comes first + +Supported formats are as follows. Future versions of libpng may support more +formats; for compatibility with older versions simply check if the format +macro is defined using #ifdef. These defines describe the in-memory layout +of the components of the pixels of the image. + +First the single byte (sRGB) formats: + + PNG_FORMAT_GRAY + PNG_FORMAT_GA + PNG_FORMAT_AG + PNG_FORMAT_RGB + PNG_FORMAT_BGR + PNG_FORMAT_RGBA + PNG_FORMAT_ARGB + PNG_FORMAT_BGRA + PNG_FORMAT_ABGR + +Then the linear 2-byte formats. When naming these "Y" is used to +indicate a luminance (gray) channel. The component order within the pixel +is always the same - there is no provision for swapping the order of the +components in the linear format. The components are 16-bit integers in +the native byte order for your platform, and there is no provision for +swapping the bytes to a different endian condition. + + PNG_FORMAT_LINEAR_Y + PNG_FORMAT_LINEAR_Y_ALPHA + PNG_FORMAT_LINEAR_RGB + PNG_FORMAT_LINEAR_RGB_ALPHA + +With color-mapped formats the image data is one byte for each pixel. The byte +is an index into the color-map which is formatted as above. To obtain a +color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP +to one of the above definitions, or you can use one of the definitions below. + + PNG_FORMAT_RGB_COLORMAP + PNG_FORMAT_BGR_COLORMAP + PNG_FORMAT_RGBA_COLORMAP + PNG_FORMAT_ARGB_COLORMAP + PNG_FORMAT_BGRA_COLORMAP + PNG_FORMAT_ABGR_COLORMAP + +PNG_IMAGE macros + +These are convenience macros to derive information from a png_image +structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the +actual image sample values - either the entries in the color-map or the +pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values +for the pixels and will always return 1 for color-mapped formats. The +remaining macros return information about the rows in the image and the +complete image. + +NOTE: All the macros that take a png_image::format parameter are compile time +constants if the format parameter is, itself, a constant. Therefore these +macros can be used in array declarations and case labels where required. +Similarly the macros are also pre-processor constants (sizeof is not used) so +they can be used in #if tests. + + PNG_IMAGE_SAMPLE_CHANNELS(fmt) + Returns the total number of channels in a given format: 1..4 + + PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt) + Returns the size in bytes of a single component of a pixel or color-map + entry (as appropriate) in the image: 1 or 2. + + PNG_IMAGE_SAMPLE_SIZE(fmt) + This is the size of the sample data for one sample. If the image is + color-mapped it is the size of one color-map entry (and image pixels are + one byte in size), otherwise it is the size of one image pixel. + + PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt) + The maximum size of the color-map required by the format expressed in a + count of components. This can be used to compile-time allocate a + color-map: + + png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + + png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + + Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + information from one of the png_image_begin_read_ APIs and dynamically + allocate the required memory. + + PNG_IMAGE_COLORMAP_SIZE(fmt) + The size of the color-map required by the format; this is the size of the + color-map buffer passed to the png_image_{read,write}_colormap APIs. It is + a fixed number determined by the format so can easily be allocated on the + stack if necessary. + +Corresponding information about the pixels + + PNG_IMAGE_PIXEL_CHANNELS(fmt) + The number of separate channels (components) in a pixel; 1 for a + color-mapped image. + + PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + The size, in bytes, of each component in a pixel; 1 for a color-mapped + image. + + PNG_IMAGE_PIXEL_SIZE(fmt) + The size, in bytes, of a complete pixel; 1 for a color-mapped image. + +Information about the whole row, or whole image + + PNG_IMAGE_ROW_STRIDE(image) + Returns the total number of components in a single row of the image; this + is the minimum 'row stride', the minimum count of components between each + row. For a color-mapped image this is the minimum number of bytes in a + row. + + If you need the stride measured in bytes, row_stride_bytes is + PNG_IMAGE_ROW_STRIDE(image) * PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt) + plus any padding bytes that your application might need, for example + to start the next row on a 4-byte boundary. + + PNG_IMAGE_BUFFER_SIZE(image, row_stride) + Return the size, in bytes, of an image buffer given a png_image and a row + stride - the number of components to leave space for in each row. + + PNG_IMAGE_SIZE(image) + Return the size, in bytes, of the image in memory given just a png_image; + the row stride is the minimum stride required for the image. + + PNG_IMAGE_COLORMAP_SIZE(image) + Return the size, in bytes, of the color-map of this image. If the image + format is not a color-map format this will return a size sufficient for + 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + you don't want to allocate a color-map in this case. + +PNG_IMAGE_FLAG_* + +Flags containing additional information about the image are held in +the 'flags' field of png_image. + + PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB == 0x01 + This indicates that the RGB values of the in-memory bitmap do not + correspond to the red, green and blue end-points defined by sRGB. + + PNG_IMAGE_FLAG_FAST == 0x02 + On write emphasise speed over compression; the resultant PNG file will be + larger but will be produced significantly faster, particular for large + images. Do not use this option for images which will be distributed, only + used it when producing intermediate files that will be read back in + repeatedly. For a typical 24-bit image the option will double the read + speed at the cost of increasing the image size by 25%, however for many + more compressible images the PNG file can be 10 times larger with only a + slight speed gain. + + PNG_IMAGE_FLAG_16BIT_sRGB == 0x04 + On read if the image is a 16-bit per component image and there is no gAMA + or sRGB chunk assume that the components are sRGB encoded. Notice that + images output by the simplified API always have gamma information; setting + this flag only affects the interpretation of 16-bit images from an + external source. It is recommended that the application expose this flag + to the user; the user can normally easily recognize the difference between + linear and sRGB encoding. This flag has no effect on write - the data + passed to the write APIs must have the correct encoding (as defined + above.) + + If the flag is not set (the default) input 16-bit per component data is + assumed to be linear. + + NOTE: the flag can only be set after the png_image_begin_read_ call, + because that call initializes the 'flags' field. + +READ APIs + + The png_image passed to the read APIs must have been initialized by setting + the png_controlp field 'opaque' to NULL (or, better, memset the whole thing.) + + int png_image_begin_read_from_file( png_imagep image, + const char *file_name) + + The named file is opened for read and the image header + is filled in from the PNG header in the file. + + int png_image_begin_read_from_stdio (png_imagep image, + FILE* file) + + The PNG header is read from the stdio FILE object. + + int png_image_begin_read_from_memory(png_imagep image, + png_const_voidp memory, size_t size) + + The PNG header is read from the given memory buffer. + + int png_image_finish_read(png_imagep image, + png_colorp background, void *buffer, + png_int_32 row_stride, void *colormap)); + + Finish reading the image into the supplied buffer and + clean up the png_image structure. + + row_stride is the step, in png_byte or png_uint_16 units + as appropriate, between adjacent rows. A positive stride + indicates that the top-most row is first in the buffer - + the normal top-down arrangement. A negative stride + indicates that the bottom-most row is first in the buffer. + + background need only be supplied if an alpha channel must + be removed from a png_byte format and the removal is to be + done by compositing on a solid color; otherwise it may be + NULL and any composition will be done directly onto the + buffer. The value is an sRGB color to use for the + background, for grayscale output the green channel is used. + + For linear output removing the alpha channel is always done + by compositing on black. + + void png_image_free(png_imagep image) + + Free any data allocated by libpng in image->opaque, + setting the pointer to NULL. May be called at any time + after the structure is initialized. + +When the simplified API needs to convert between sRGB and linear colorspaces, +the actual sRGB transfer curve defined in the sRGB specification (see the +article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +approximation used elsewhere in libpng. + +WRITE APIS + +For write you must initialize a png_image structure to describe the image to +be written: + + version: must be set to PNG_IMAGE_VERSION + opaque: must be initialized to NULL + width: image width in pixels + height: image height in rows + format: the format of the data you wish to write + flags: set to 0 unless one of the defined flags applies; set + PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images + where the RGB values do not correspond to the colors in sRGB. + colormap_entries: set to the number of entries in the color-map (0 to 256) + + int png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + + Write the image to the named file. + + int png_image_write_to_memory (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, + int convert_to_8_bit, const void *buffer, ptrdiff_t row_stride, + const void *colormap)); + + Write the image to memory. + + int png_image_write_to_stdio(png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, + png_int_32 row_stride, const void *colormap) + + Write the image to the given (FILE*). + +With all write APIs if image is in one of the linear formats with +(png_uint_16) data then setting convert_to_8_bit will cause the output to be +a (png_byte) PNG gamma encoded according to the sRGB specification, otherwise +a 16-bit linear encoded PNG file is written. + +With all APIs row_stride is handled as in the read APIs - it is the spacing +from one row to the next in component sized units (float) and if negative +indicates a bottom-up row layout in the buffer. If you pass zero, libpng will +calculate the row_stride for you from the width and number of channels. + +Note that the write API does not support interlacing, sub-8-bit pixels, +indexed (paletted) images, or most ancillary chunks. + +.SH VI. Modifying/Customizing libpng + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). The png_malloc() and png_free() functions currently just +call the standard C functions and png_calloc() calls png_malloc() and then +clears the newly allocated memory to zero; note that png_calloc(png_ptr, size) +is not the same as the calloc(number, size) function provided by stdlib.h. +There is limited support for certain systems with segmented memory +architectures and the types of pointers declared by png.h match this; you +will have to use appropriate pointers in your application. If you prefer +to use a different method of allocating and freeing data, you can use +png_create_read_struct_2() or png_create_write_struct_2() to register your +own functions as described above. These functions also provide a void +pointer that can be retrieved via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_alloc_size_t size); + + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, size_t length); + + void user_write_data(png_structp png_ptr, + png_bytep data, size_t length); + + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +Then, within your user_error_fn or user_warning_fn, you can retrieve +the error_ptr if you need it, by calling + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see https://cexcept.sourceforge.io/), +which is illustrated in pngvalid.c and in contrib/visupng. + +Beginning in libpng-1.4.0, the png_set_benign_errors() API became available. +You can use this to handle certain errors (normally handled as errors) +as warnings. + + png_set_benign_errors (png_ptr, int allowed); + + allowed: 0: treat png_benign_error() as an error. + 1: treat png_benign_error() as a warning. + +As of libpng-1.6.0, the default condition is to treat benign errors as +warnings while reading and as errors while writing. + +.SS Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle private or unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. This +is illustrated in pngtest.c, which uses a callback function to handle a +private "vpAg" chunk and the new "sTER" chunk, which are both unknown to +libpng. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +.SS Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +.SS Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + #include zlib.h + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + #include zlib.h + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + #include zlib.h + png_set_compression_strategy(png_ptr, + strategy); + + png_set_compression_window_bits(png_ptr, + window_bits); + + png_set_compression_method(png_ptr, method); + +This controls the size of the IDAT chunks (default 8192): + + png_set_compression_buffer_size(png_ptr, size); + +As of libpng version 1.5.4, additional APIs became +available to set these separately for non-IDAT +compressed chunks such as zTXt, iTXt, and iCCP: + + #include zlib.h + #if PNG_LIBPNG_VER >= 10504 + png_set_text_compression_level(png_ptr, level); + + png_set_text_compression_mem_level(png_ptr, level); + + png_set_text_compression_strategy(png_ptr, + strategy); + + png_set_text_compression_window_bits(png_ptr, + window_bits); + + png_set_text_compression_method(png_ptr, method); + #endif + +.SS Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS, PNG_NO_FILTERS, +or PNG_FAST_FILTERS to turn filtering on and off, or to turn on +just the fast-decoding subset of filters, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_NO_FILTERS; + filters = PNG_ALL_FILTERS; + filters = PNG_FAST_FILTERS; + + or + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB | + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +.SS Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d", foo); + +is expanded to + + if (PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\en", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +.SH VII. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +https://www.libmng.com/) instead. + +.SH VIII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 1.4.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Support for the sCAL, iCCP, iTXt, and sPLT chunks was added at libpng-1.0.6; +however, iTXt support was not enabled by default. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +Note that this function does not take a png_ptr, so you can call it +before you've created one. + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +.SH IX. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW + PNG_ASM_FLAG_MMX_READ_INTERLACE + PNG_ASM_FLAG_MMX_READ_FILTER_SUB + PNG_ASM_FLAG_MMX_READ_FILTER_UP + PNG_ASM_FLAG_MMX_READ_FILTER_AVG + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +.SH X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions png_get_mmx_flagmask(), +png_set_mmx_thresholds(), png_get_asm_flags(), +png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(), +png_set_asm_flags(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), +and memset(), respectively. + +The function png_set_gray_1_2_4_to_8() was removed. It has been +deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with +png_set_expand_gray_1_2_4_to_8() because the former function also +expanded any tRNS chunk to an alpha channel. + +Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 +were added and are used by default instead of the corresponding +functions. Unfortunately, +from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +The png_zalloc() function no longer zeroes out the memory that it +allocates. Applications that called png_zalloc(png_ptr, number, size) +can call png_calloc(png_ptr, number*size) instead, and can call +png_free() instead of png_zfree(). + +Support for dithering was disabled by default in libpng-1.4.0, because +it has not been well tested and doesn't actually "dither". +The code was not +removed, however, and could be enabled by building libpng with +PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support +was re-enabled, but the function was renamed png_set_quantize() to +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED +was renamed to PNG_READ_QUANTIZE_SUPPORTED. + +We removed the trailing '.' from the warning and error messages. + +.SH XI. Changes to Libpng from version 1.4.x to 1.5.x + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. +The incorrect macro was removed from libpng-1.4.5. + +Checking for invalid palette index on write was added at libpng +1.5.10. If a pixel contains an invalid (out-of-range) index libpng issues +a benign error. This is enabled by default because this condition is an +error according to the PNG specification, Clause 11.3.2, but the error can +be ignored in each png_ptr with + + png_set_check_for_invalid_index(png_ptr, allowed); + + allowed - one of + 0: disable benign error (accept the + invalid data without warning). + 1: enable benign error (treat the + invalid data as an error or a + warning). + +If the error is ignored, or if png_benign_error() treats it as a warning, +any invalid pixels are decoded as opaque black by the decoder and written +as-is by the encoder. + +Retrieving the maximum palette index found was added at libpng-1.5.15. +This statement must appear after png_read_png() or png_read_image() while +reading, and after png_write_png() or png_write_image() while writing. + + int max_palette = png_get_palette_max(png_ptr, info_ptr); + +This will return the maximum palette index found in the image, or "\-1" if +the palette was not checked, or "0" if no palette was found. Note that this +does not account for any palette index used by ancillary chunks such as the +bKGD chunk; you must check those separately to determine the maximum +palette index actually used. + +There are no substantial API changes between the non-deprecated parts of +the 1.4.5 API and the 1.5.0 API; however, the ability to directly access +members of the main libpng control structures, png_struct and png_info, +deprecated in earlier versions of libpng, has been completely removed from +libpng 1.5, and new private "pngstruct.h", "pnginfo.h", and "pngdebug.h" +header files were created. + +We no longer include zlib.h in png.h. The include statement has been moved +to pngstruct.h, where it is not accessible by applications. Applications that +need access to information in zlib.h will need to add the '#include "zlib.h"' +directive. It does not matter whether this is placed prior to or after +the '"#include png.h"' directive. + +The png_sprintf(), png_strcpy(), and png_strncpy() macros are no longer used +and were removed. + +We moved the png_strlen(), png_memcpy(), png_memset(), and png_memcmp() +macros into a private header file (pngpriv.h) that is not accessible to +applications. + +In png_get_iCCP, the type of "profile" was changed from png_charpp +to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. + +There are changes of form in png.h, including new and changed macros to +declare parts of the API. Some API functions with arguments that are +pointers to data not modified within the function have been corrected to +declare these arguments with const. + +Much of the internal use of C macros to control the library build has also +changed and some of this is visible in the exported header files, in +particular the use of macros to control data and API elements visible +during application compilation may require significant revision to +application code. (It is extremely rare for an application to do this.) + +Any program that compiled against libpng 1.4 and did not use deprecated +features or access internal library structures should compile and work +against libpng 1.5, except for the change in the prototype for +png_get_iCCP() and png_set_iCCP() API functions mentioned above. + +libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of +interlaced images. The macros return the number of rows and columns in +each pass and information that can be used to de-interlace and (if +absolutely necessary) interlace an image. + +libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls +the application-provided png_longjmp_ptr on the internal, but application +initialized, longjmp buffer. It is provided as a convenience to avoid +the need to use the png_jmpbuf macro, which had the unnecessary side +effect of resetting the internal png_longjmp_ptr value. + +libpng 1.5.0 includes a complete fixed point API. By default this is +present along with the corresponding floating point API. In general the +fixed point API is faster and smaller than the floating point one because +the PNG file format used fixed point, not floating point. This applies +even if the library uses floating point in internal calculations. A new +macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library +uses floating point arithmetic (the default) or fixed point arithmetic +internally for performance critical calculations such as gamma correction. +In some cases, the gamma calculations may produce slightly different +results. This has changed the results in png_rgb_to_gray and in alpha +composition (png_set_background for example). This applies even if the +original image was already linear (gamma == 1.0) and, therefore, it is +not necessary to linearize the image. This is because libpng has *not* +been changed to optimize that case correctly, yet. + +Fixed point support for the sCAL chunk comes with an important caveat; +the sCAL specification uses a decimal encoding of floating point values +and the accuracy of PNG fixed point values is insufficient for +representation of these values. Consequently a "string" API +(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading +arbitrary sCAL chunks in the absence of either the floating point API or +internal floating point calculations. Starting with libpng-1.5.0, both +of these functions are present when PNG_sCAL_SUPPORTED is defined. Prior +to libpng-1.5.0, their presence also depended upon PNG_FIXED_POINT_SUPPORTED +being defined and PNG_FLOATING_POINT_SUPPORTED not being defined. + +Applications no longer need to include the optional distribution header +file pngusr.h or define the corresponding macros during application +build in order to see the correct variant of the libpng API. From 1.5.0 +application code can check for the corresponding _SUPPORTED macro: + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED + /* code that uses the inch conversion APIs. */ +#endif + +This macro will only be defined if the inch conversion functions have been +compiled into libpng. The full set of macros, and whether or not support +has been compiled in, are available in the header file pnglibconf.h. +This header file is specific to the libpng build. Notice that prior to +1.5.0 the _SUPPORTED macros would always have the default definition unless +reset by pngusr.h or by explicit settings on the compiler command line. +These settings may produce compiler warnings or errors in 1.5.0 because +of macro redefinition. + +Applications can now choose whether to use these macros or to call the +corresponding function by defining PNG_USE_READ_MACROS or +PNG_NO_USE_READ_MACROS before including png.h. Notice that this is +only supported from 1.5.0; defining PNG_NO_USE_READ_MACROS prior to 1.5.0 +will lead to a link failure. + +Prior to libpng-1.5.4, the zlib compressor used the same set of parameters +when compressing the IDAT data and textual data such as zTXt and iCCP. +In libpng-1.5.4 we reinitialized the zlib stream for each type of data. +We added five png_set_text_*() functions for setting the parameters to +use with textual data. + +Prior to libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +option was off by default, and slightly inaccurate scaling occurred. +This option can no longer be turned off, and the choice of accurate +or inaccurate 16-to-8 scaling is by using the new png_set_scale_16_to_8() +API for accurate scaling or the old png_set_strip_16_to_8() API for simple +chopping. In libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +macro became PNG_READ_SCALE_16_TO_8_SUPPORTED, and the PNG_READ_16_TO_8 +macro became PNG_READ_STRIP_16_TO_8_SUPPORTED, to enable the two +png_set_*_16_to_8() functions separately. + +Prior to libpng-1.5.4, the png_set_user_limits() function could only be +used to reduce the width and height limits from the value of +PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said +that it could be used to override them. Now this function will reduce or +increase the limits. + +Starting in libpng-1.5.22, default user limits were established. These +can be overridden by application calls to png_set_user_limits(), +png_set_user_chunk_cache_max(), and/or png_set_user_malloc_max(). +The limits are now + max possible default + png_user_width_max 0x7fffffff 1,000,000 + png_user_height_max 0x7fffffff 1,000,000 + png_user_chunk_cache_max 0 (unlimited) 1000 + png_user_chunk_malloc_max 0 (unlimited) 8,000,000 + +The png_set_option() function (and the "options" member of the png struct) was +added to libpng-1.5.15, with option PNG_ARM_NEON. + +The library now supports a complete fixed point implementation and can +thus be used on systems that have no floating point support or very +limited or slow support. Previously gamma correction, an essential part +of complete PNG support, required reasonably fast floating point. + +As part of this the choice of internal implementation has been made +independent of the choice of fixed versus floating point APIs and all the +missing fixed point APIs have been implemented. + +The exact mechanism used to control attributes of API functions has +changed, as described in the INSTALL file. + +A new test program, pngvalid, is provided in addition to pngtest. +pngvalid validates the arithmetic accuracy of the gamma correction +calculations and includes a number of validations of the file format. +A subset of the full range of tests is run when "make check" is done +(in the 'configure' build.) pngvalid also allows total allocated memory +usage to be evaluated and performs additional memory overwrite validation. + +Many changes to individual feature macros have been made. The following +are the changes most likely to be noticed by library builders who +configure libpng: + +1) All feature macros now have consistent naming: + +#define PNG_NO_feature turns the feature off +#define PNG_feature_SUPPORTED turns the feature on + +pnglibconf.h contains one line for each feature macro which is either: + +#define PNG_feature_SUPPORTED + +if the feature is supported or: + +/*#undef PNG_feature_SUPPORTED*/ + +if it is not. Library code consistently checks for the 'SUPPORTED' macro. +It does not, and libpng applications should not, check for the 'NO' macro +which will not normally be defined even if the feature is not supported. +The 'NO' macros are only used internally for setting or not setting the +corresponding 'SUPPORTED' macros. + +Compatibility with the old names is provided as follows: + +PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED + +And the following definitions disable the corresponding feature: + +PNG_SETJMP_NOT_SUPPORTED disables SETJMP +PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS +PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV +PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS +PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS +PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS + +Library builders should remove use of the above, inconsistent, names. + +2) Warning and error message formatting was previously conditional on +the STDIO feature. The library has been changed to use the +CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled +the library no longer uses the printf(3) functions, even though the +default read/write implementations use (FILE) style stdio.h functions. + +3) Three feature macros now control the fixed/floating point decisions: + +PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs + +PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in +practice these are normally required internally anyway (because the PNG +file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT +merely stops the function from being exported. + +PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating +point implementation or the fixed point one. Typically the fixed point +implementation is larger and slower than the floating point implementation +on a system that supports floating point; however, it may be faster on a +system which lacks floating point hardware and therefore uses a software +emulation. + +4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the +functions to read and write ints to be disabled independently of +PNG_USE_READ_MACROS, which allows libpng to be built with the functions +even though the default is to use the macros - this allows applications +to choose at app buildtime whether or not to use macros (previously +impossible because the functions weren't in the default build.) + +.SH XII. Changes to Libpng from version 1.5.x to 1.6.x + +A "simplified API" has been added (see documentation in png.h and a simple +example in contrib/examples/pngtopng.c). The new publicly visible API +includes the following: + + macros: + PNG_FORMAT_* + PNG_IMAGE_* + structures: + png_control + png_image + read functions + png_image_begin_read_from_file() + png_image_begin_read_from_stdio() + png_image_begin_read_from_memory() + png_image_finish_read() + png_image_free() + write functions + png_image_write_to_file() + png_image_write_to_memory() + png_image_write_to_stdio() + +Starting with libpng-1.6.0, you can configure libpng to prefix all exported +symbols, using the PNG_PREFIX macro. + +We no longer include string.h in png.h. The include statement has been moved +to pngpriv.h, where it is not accessible by applications. Applications that +need access to information in string.h must add an '#include ' +directive. It does not matter whether this is placed prior to or after +the '#include "png.h"' directive. + +The following API are now DEPRECATED: + png_info_init_3() + png_convert_to_rfc1123() which has been replaced + with png_convert_to_rfc1123_buffer() + png_malloc_default() + png_free_default() + png_reset_zstream() + +The following have been removed: + png_get_io_chunk_name(), which has been replaced + with png_get_io_chunk_type(). The new + function returns a 32-bit integer instead of + a string. + The png_sizeof(), png_strlen(), png_memcpy(), png_memcmp(), and + png_memset() macros are no longer used in the libpng sources and + have been removed. These had already been made invisible to applications + (i.e., defined in the private pngpriv.h header file) since libpng-1.5.0. + +The signatures of many exported functions were changed, such that + png_structp became png_structrp or png_const_structrp + png_infop became png_inforp or png_const_inforp +where "rp" indicates a "restricted pointer". + +Dropped support for 16-bit platforms. The support for FAR/far types has +been eliminated and the definition of png_alloc_size_t is now controlled +by a flag so that 'small size_t' systems can select it if necessary. + +Error detection in some chunks has improved; in particular the iCCP chunk +reader now does pretty complete validation of the basic format. Some bad +profiles that were previously accepted are now accepted with a warning or +rejected, depending upon the png_set_benign_errors() setting, in particular +the very old broken Microsoft/HP 3144-byte sRGB profile. Starting with +libpng-1.6.11, recognizing and checking sRGB profiles can be avoided by +means of + + #if defined(PNG_SKIP_sRGB_CHECK_PROFILE) && \ + defined(PNG_SET_OPTION_SUPPORTED) + png_set_option(png_ptr, PNG_SKIP_sRGB_CHECK_PROFILE, + PNG_OPTION_ON); + #endif + +It's not a good idea to do this if you are using the "simplified API", +which needs to be able to recognize sRGB profiles conveyed via the iCCP +chunk. + +The PNG spec requirement that only grayscale profiles may appear in images +with color type 0 or 4 and that even if the image only contains gray pixels, +only RGB profiles may appear in images with color type 2, 3, or 6, is now +enforced. The sRGB chunk is allowed to appear in images with any color type +and is interpreted by libpng to convey a one-tracer-curve gray profile or a +three-tracer-curve RGB profile as appropriate. + +Libpng 1.5.x erroneously used /MD for Debug DLL builds; if you used the debug +builds in your app and you changed your app to use /MD you will need to +change it back to /MDd for libpng 1.6.x. + +Prior to libpng-1.6.0 a warning would be issued if the iTXt chunk contained +an empty language field or an empty translated keyword. Both of these +are allowed by the PNG specification, so these warnings are no longer issued. + +The library now issues an error if the application attempts to set a +transform after it calls png_read_update_info() or if it attempts to call +both png_read_update_info() and png_start_read_image() or to call either +of them more than once. + +The default condition for benign_errors is now to treat benign errors as +warnings while reading and as errors while writing. + +The library now issues a warning if both background processing and RGB to +gray are used when gamma correction happens. As with previous versions of +the library the results are numerically very incorrect in this case. + +There are some minor arithmetic changes in some transforms such as +png_set_background(), that might be detected by certain regression tests. + +Unknown chunk handling has been improved internally, without any API change. +This adds more correct option control of the unknown handling, corrects +a pre-existing bug where the per-chunk 'keep' setting is ignored, and makes +it possible to skip IDAT chunks in the sequential reader. + +The machine-generated configure files are no longer included in branches +libpng16 and later of the GIT repository. They continue to be included +in the tarball releases, however. + +Libpng-1.6.0 through 1.6.2 used the CMF bytes at the beginning of the IDAT +stream to set the size of the sliding window for reading instead of using the +default 32-kbyte sliding window size. It was discovered that there are +hundreds of PNG files in the wild that have incorrect CMF bytes that caused +zlib to issue the "invalid distance too far back" error and reject the file. +Libpng-1.6.3 and later calculate their own safe CMF from the image dimensions, +provide a way to revert to the libpng-1.5.x behavior (ignoring the CMF bytes +and using a 32-kbyte sliding window), by using + + png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, + PNG_OPTION_ON); + +and provide a tool (contrib/tools/pngfix) for rewriting a PNG file while +optimizing the CMF bytes in its IDAT chunk correctly. + +Libpng-1.6.0 and libpng-1.6.1 wrote uncompressed iTXt chunks with the wrong +length, which resulted in PNG files that cannot be read beyond the bad iTXt +chunk. This error was fixed in libpng-1.6.3, and a tool (called +contrib/tools/png-fix-itxt) has been added to the libpng distribution. + +Starting with libpng-1.6.17, the PNG_SAFE_LIMITS macro was eliminated +and safe limits are used by default (users who need larger limits +can still override them at compile time or run time, as described above). + +The new limits are + default spec limit + png_user_width_max 1,000,000 2,147,483,647 + png_user_height_max 1,000,000 2,147,483,647 + png_user_chunk_cache_max 128 unlimited + png_user_chunk_malloc_max 8,000,000 unlimited + +Starting with libpng-1.6.18, a PNG_RELEASE_BUILD macro was added, which allows +library builders to control compilation for an installed system (a release build). +It can be set for testing debug or beta builds to ensure that they will compile +when the build type is switched to RC or STABLE. In essence this overrides the +PNG_LIBPNG_BUILD_BASE_TYPE definition which is not directly user controllable. + +Starting with libpng-1.6.19, attempting to set an over-length PLTE chunk +is an error. Previously this requirement of the PNG specification was not +enforced, and the palette was always limited to 256 entries. An over-length +PLTE chunk found in an input PNG is silently truncated. + +Starting with libpng-1.6.31, the eXIf chunk is supported. Libpng does not +attempt to decode the Exif profile; it simply returns a byte array +containing the profile to the calling application which must do its own +decoding. + +.SH XIII. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +.SH XV. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + https://github.com/glennrp/libpng or + https://git.code.sf.net/p/libpng/code.git + +or you can browse it with a web browser at + + https://github.com/glennrp/libpng or + https://sourceforge.net/p/libpng/code/ci/libpng16/tree/ + +Patches can be sent to png-mng-implement at lists.sourceforge.net or +uploaded to the libpng bug tracker at + + https://libpng.sourceforge.io/ + +or as a "pull request" to + + https://github.com/glennrp/libpng/pulls + +We also accept patches built from the tar or zip distributions, and +simple verbal descriptions of bug fixes, reported either to the +SourceForge bug tracker, to the png-mng-implement at lists.sf.net +mailing list, as github issues. + +.SH XV. Coding style + +Our coding style is similar to the "Allman" style +(See https://en.wikipedia.org/wiki/Indent_style#Allman_style), with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return 0; + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programmers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The return type and decorations are placed on a separate line +ahead of the function name, as illustrated above. + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in pngpriv.h above the comment that says + + /* Maintainer: Put new private prototypes here ^ */ + +To avoid polluting the global namespace, the names of all exported +functions and variables begin with "png_", and all publicly visible C +preprocessor macros begin with "PNG". We request that applications that +use libpng *not* begin any of their own symbols with either of these strings. + +We put a space after the "sizeof" operator and we omit the +optional parentheses around its argument when the argument +is an expression, not a type name, and we always enclose the +sizeof operator, with its argument, in parentheses: + + (sizeof (png_uint_32)) + (sizeof array) + +Prior to libpng-1.6.0 we used a "png_sizeof()" macro, formatted as +though it were a function. + +Control keywords if, for, while, and switch are always followed by a space +to distinguish them from function calls, which have no trailing space. + +We put a space after each comma and after each semicolon +in "for" statements, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". We don't put a space between a typecast and the expression +being cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; \-\-i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and #if !defined() +when there is only one macro being tested. We always use parentheses +with "defined". + +We express integer constants that are used as bit masks in hex format, +with an even number of lower-case hex digits, and to make them unsigned +(e.g., 0x00U, 0xffU, 0x0100U) and long if they are greater than 0x7fff +(e.g., 0xffffUL). + +We prefer to use underscores rather than camelCase in names, except +for a few type names that we inherit from zlib.h. + +We prefer "if (something != 0)" and "if (something == 0)" over +"if (something)" and if "(!something)", respectively, and for pointers +we prefer "if (some_pointer != NULL)" or "if (some_pointer == NULL)". + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +.SH NOTE + +Note about libpng version numbers: + +Due to various miscommunications, unforeseen code incompatibilities +and occasional factors outside the authors' control, version numbering +on the library has not always been consistent and straightforward. +The following table summarizes matters since version 0.89c, which was +the first widely used release: + + source png.h png.h shared-lib + version string int version + ------- ------ ----- ---------- + 0.89c "1.0 beta 3" 0.89 89 1.0.89 + 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + 0.97c 0.97 97 2.0.97 + 0.98 0.98 98 2.0.98 + 0.99 0.99 98 2.0.99 + 0.99a-m 0.99 99 2.0.99 + 1.00 1.00 100 2.1.0 [100 should be 10000] + 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + 1.0.1 png.h string is 10001 2.1.0 + 1.0.1a-e identical to the 10002 from here on, the shared library + 1.0.2 source version) 10002 is 2.V where V is the source code + 1.0.2a-b 10003 version, except as noted. + 1.0.3 10003 + 1.0.3a-d 10004 + 1.0.4 10004 + 1.0.4a-f 10005 + 1.0.5 (+ 2 patches) 10005 + 1.0.5a-d 10006 + 1.0.5e-r 10100 (not source compatible) + 1.0.5s-v 10006 (not binary compatible) + 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + 1.0.6d-f 10007 (still binary incompatible) + 1.0.6g 10007 + 1.0.6h 10007 10.6h (testing xy.z so-numbering) + 1.0.6i 10007 10.6i + 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + 1.0.7 1 10007 (still compatible) + ... + 1.0.69 10 10069 10.so.0.69[.0] + ... + 1.2.59 13 10259 12.so.0.59[.0] + ... + 1.4.20 14 10420 14.so.0.20[.0] + ... + 1.5.30 15 10530 15.so.15.30[.0] + ... + 1.6.35 16 10635 16.so.16.35[.0] + +Henceforth the source version will match the shared-library minor and +patch numbers; the shared-library major version number will be used for +changes in backward compatibility, as it is intended. +The PNG_PNGLIB_VER macro, which is not used within libpng but is +available for applications, is an unsigned integer of the form XYYZZ +corresponding to the source version X.Y.Z (leading zeros in Y and Z). +Beta versions were given the previous public release number plus a +letter, until version 1.0.6j; from then on they were given the upcoming +public release number plus "betaNN" or "rcNN". + +.SH "SEE ALSO" +.IR libpngpf(3) ", " png(5) +.LP +.IR libpng : +.IP +https://libpng.sourceforge.io/ (follow the [DOWNLOAD] link) +http://www.libpng.org/pub/png + +.LP +.IR zlib : +.IP +(generally) at the same location as +.I libpng +or at +.br +https://zlib.net/ + +.LP +.IR PNG specification: RFC 2083 +.IP +(generally) at the same location as +.I libpng +or at +.br +https://www.ietf.org/rfc/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +https://www.w3.org/TR/REC-png.html + +.LP +In the case of any inconsistency between the PNG specification +and this library, the specification takes precedence. + +.SH AUTHORS +This man page: +Initially created by Glenn Randers-Pehrson. +Maintained by Cosmin Truta. + +The contributing authors would like to thank all those who helped +with testing, bug fixes, and patience. This wouldn't have been +possible without all of you. + +Thanks to Frank J. T. Wojcik for helping with the documentation. + +Libpng: +Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. +Maintained by Cosmin Truta. + +Supported by the PNG development group +.br +png-mng-implement at lists.sourceforge.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe). + +.\" end of man page diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man3/libpngpf.3 b/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man3/libpngpf.3 new file mode 100644 index 0000000..6909c70 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man3/libpngpf.3 @@ -0,0 +1,24 @@ +.TH LIBPNGPF 3 "April 14, 2019" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.6.37 +(private functions) + +.SH SYNOPSIS +\fB#include \fI"pngpriv.h" + +\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer +\fP\fImaintained\fP\fB, now that the private function prototypes are hidden in +\fP\fIpngpriv.h\fP\fB and not accessible to applications. Look in +\fP\fIpngpriv.h\fP\fB for the prototypes and a short description of each +function. + +.SH DESCRIPTION +The functions previously listed here are used privately by libpng and are not +available for use by applications. They are not "exported" to applications +using shared libraries. + +.SH "SEE ALSO" +.BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) + +.SH AUTHORS +Cosmin Truta, Glenn Randers-Pehrson diff --git a/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man5/png.5 b/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man5/png.5 new file mode 100644 index 0000000..c2da95c --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/libpng/share/man/man5/png.5 @@ -0,0 +1,84 @@ +.TH PNG 5 "April 14, 2019" +.SH NAME +png \- Portable Network Graphics (PNG) format + +.SH DESCRIPTION +PNG (Portable Network Graphics) is an extensible file format for the +lossless, portable, well-compressed storage of raster images. PNG +provides a patent-free replacement for GIF, and can also replace many +common uses of TIFF. Indexed-color, grayscale, and truecolor images are +supported, plus an optional alpha channel. Sample depths range from +1 to 16 bits. +.br +PNG is designed to work well in online viewing applications, such +as the World Wide Web, so it is fully streamable with a progressive +display option. PNG is robust, providing both full file integrity +checking and fast, simple detection of common transmission errors. +Also, PNG can store gamma and chromaticity data for improved color +matching on heterogeneous platforms. + +.SH "SEE ALSO" +.BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.LP +PNG Specification (Second Edition), November 2003: +.IP +.br +https://www.w3.org/TR/2003/REC-PNG-20031110/ +.LP +PNG 1.2 Specification, July 1999: +.IP +.br +https://png-mng.sourceforge.io/pub/png/spec/1.2/ +.LP +PNG 1.0 Specification, October 1996: +.IP +.br +RFC 2083 +.br +https://www.ietf.org/rfc/rfc2083.txt +.IP +.br +or W3C Recommendation +.br +https://www.w3.org/TR/REC-png-961001 + +.SH AUTHORS +This man page: Cosmin Truta, Glenn Randers-Pehrson +.LP +Portable Network Graphics (PNG) Specification (Second Edition) +Information technology - Computer graphics and image processing - +Portable Network Graphics (PNG): Functional specification. +ISO/IEC 15948:2003 (E) (November 10, 2003): David Duce and others. +.LP +Portable Network Graphics (PNG) Specification Version 1.2 (July 8, 1999): +Glenn Randers-Pehrson and others (png-list). +.LP +Portable Network Graphics (PNG) Specification Version 1.0 (October 1, 1996): +Thomas Boutell and others (png-list). + +.SH COPYRIGHT +.LP +This man page is +.br +Copyright (c) 2018-2019 Cosmin Truta. +.br +Copyright (c) 1998-2006 Glenn Randers-Pehrson. +.br +See png.h for conditions of use and distribution. +.LP +The PNG Specification (Second Edition) is +.br +Copyright (c) 2003 W3C. (MIT, ERCIM, Keio), All Rights Reserved. +.LP +The PNG-1.2 Specification is +.br +Copyright (c) 1999 Glenn Randers-Pehrson. +.br +See the specification for conditions of use and distribution. +.LP +The PNG-1.0 Specification is +.br +Copyright (c) 1996 Massachusetts Institute of Technology. +.br +See the specification for conditions of use and distribution. +.\" end of man page diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/include/zconf.h b/rknn_yolo_demo/libs/platform/RK1808/zlib/include/zconf.h new file mode 100644 index 0000000..77398c1 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/zlib/include/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/include/zlib.h b/rknn_yolo_demo/libs/platform/RK1808/zlib/include/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/zlib/include/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.a b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.a new file mode 100644 index 0000000..de8e5f8 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so.1 b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so.1 new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so.1 @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so.1.2.11 b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so.1.2.11 new file mode 100644 index 0000000..286b21a Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/libz.so.1.2.11 differ diff --git a/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/pkgconfig/zlib.pc b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/pkgconfig/zlib.pc new file mode 100644 index 0000000..5495a28 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK1808/zlib/lib/Linux/pkgconfig/zlib.pc @@ -0,0 +1,13 @@ +prefix=/home/xz/Documents/testing/compile_test/zlib1211/zlib-1.2.11/rk1808 +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib +Description: zlib compression library +Version: 1.2.11 + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/.gitignore b/rknn_yolo_demo/libs/platform/RK3399PRO/.gitignore new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/.gitignore @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jconfig.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jconfig.h new file mode 100644 index 0000000..cb09382 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jconfig.h @@ -0,0 +1,163 @@ +/* + * jconfig.txt + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * Modified 2009-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file documents the configuration options that are required to + * customize the JPEG software for a particular system. + * + * The actual configuration options for a particular installation are stored + * in jconfig.h. On many machines, jconfig.h can be generated automatically + * or copied from one of the "canned" jconfig files that we supply. But if + * you need to generate a jconfig.h file by hand, this file tells you how. + * + * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. + * EDIT A COPY NAMED JCONFIG.H. + */ + + +/* + * These symbols indicate the properties of your machine or compiler. + * #define the symbol if yes, #undef it if no. + */ + +/* Does your compiler support function prototypes? + * (If not, you also need to use ansi2knr, see install.txt) + */ +#define HAVE_PROTOTYPES + +/* Does your compiler support the declaration "unsigned char" ? + * How about "unsigned short" ? + */ +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT + +/* Define this if an ordinary "char" type is unsigned. + * If you're not sure, leaving it undefined will work at some cost in speed. + * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. + */ +/* #undef CHAR_IS_UNSIGNED */ + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV , + * but does have a BSD-style . + */ +/* #undef NEED_BSD_STRINGS */ + +/* Define this if your system does not provide typedef size_t in any of the + * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in + * instead. + */ +#define NEED_SYS_TYPES_H + +/* For 80x86 machines, you need to define NEED_FAR_POINTERS, + * unless you are using a large-data memory model or 80386 flat-memory mode. + * On less brain-damaged CPUs this symbol must not be defined. + * (Defining this symbol causes large data structures to be referenced through + * "far" pointers and to be allocated with a special version of malloc.) + */ +#undef NEED_FAR_POINTERS + +/* Define this if your linker needs global names to be unique in less + * than the first 15 characters. + */ +#undef NEED_SHORT_EXTERNAL_NAMES + +/* Although a real ANSI C compiler can deal perfectly well with pointers to + * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI + * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, + * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you + * actually get "missing structure definition" warnings or errors while + * compiling the JPEG code. + */ +#undef INCOMPLETE_TYPES_BROKEN + +/* Define "boolean" as unsigned char, not enum, on Windows systems. + */ +#ifdef _WIN32 +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + + +/* + * The following options affect code selection within the JPEG library, + * but they don't need to be visible to applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS has been defined. + */ + +#ifdef JPEG_INTERNALS + +/* Define this if your compiler implements ">>" on signed values as a logical + * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, + * which is the normal and rational definition. + */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + + +#endif /* JPEG_INTERNALS */ + + +/* + * The remaining options do not affect the JPEG library proper, + * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). + * Other applications can ignore these. + */ + +#ifdef JPEG_CJPEG_DJPEG + +/* These defines indicate which image (non-JPEG) file formats are allowed. */ + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* Define this if you want to name both input and output files on the command + * line, rather than using stdout and optionally stdin. You MUST do this if + * your system can't cope with binary I/O to stdin/stdout. See comments at + * head of cjpeg.c or djpeg.c. + */ +#undef TWO_FILE_COMMANDLINE + +/* #undef USE_SETMODE */ + +/* Define this if your system needs explicit cleanup of temporary files. + * This is crucial under MS-DOS, where the temporary "files" may be areas + * of extended memory; on most other systems it's not as important. + */ +#undef NEED_SIGNAL_CATCHER + +/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). + * This is necessary on systems that distinguish text files from binary files, + * and is harmless on most systems that don't. If you have one of the rare + * systems that complains about the "b" spec, define this symbol. + */ +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. + */ +#undef PROGRESS_REPORT + + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jerror.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jerror.h new file mode 100644 index 0000000..a4b661f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2012 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jmorecfg.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jmorecfg.h new file mode 100644 index 0000000..679d68b --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jmorecfg.h @@ -0,0 +1,446 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 9 for 9-bit sample values + * 10 for 10-bit sample values + * 11 for 11-bit sample values + * 12 for 12-bit sample values + * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for + * full-feature DCT processing. Further depths up to 16-bit may be added + * later for the lossless modes of operation. + * Run-time selection and conversion of data precision will be added later + * and are currently not supported, sorry. + * Exception: The transcoding part (jpegtran) supports all settings in a + * single instance, since it operates on the level of DCT coefficients and + * not sample values. The DCT coefficients are of the same type (16 bits) + * in all cases (see below). + */ + +#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 9 +/* JSAMPLE should be the smallest type that will hold the values 0..511. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 511 +#define CENTERJSAMPLE 256 + +#endif /* BITS_IN_JSAMPLE == 9 */ + + +#if BITS_IN_JSAMPLE == 10 +/* JSAMPLE should be the smallest type that will hold the values 0..1023. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 1023 +#define CENTERJSAMPLE 512 + +#endif /* BITS_IN_JSAMPLE == 10 */ + + +#if BITS_IN_JSAMPLE == 11 +/* JSAMPLE should be the smallest type that will hold the values 0..2047. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 2047 +#define CENTERJSAMPLE 1024 + +#endif /* BITS_IN_JSAMPLE == 11 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* The noreturn type identifier is used to declare functions + * which cannot return. + * Compilers can thus create more optimized code and perform + * better checks for warnings and errors. + * Static analyzer tools can make improved inferences about + * execution paths and are prevented from giving false alerts. + * + * Unfortunately, the proposed specifications of corresponding + * extensions in the Dec 2011 ISO C standard revision (C11), + * GCC, MSVC, etc. are not viable. + * Thus we introduce a user defined type to declare noreturn + * functions at least for clarity. A proper compiler would + * have a suitable noreturn type to match in place of void. + */ + +#ifndef HAVE_NORETURN_T +typedef void noreturn_t; +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +#if defined FALSE || defined TRUE || defined QGLOBAL_H +/* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ +typedef int boolean; +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#else +typedef enum { FALSE = 0, TRUE = 1 } boolean; +#endif +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected more than 8-bit data precision, it is dangerous to + * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only + * good for 8-bit precision, so arithmetic coding is recommended for higher + * precision. The Huffman encoder normally uses entropy optimization to + * compute usable tables for higher precision. Otherwise, you'll have to + * supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jpeglib.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jpeglib.h new file mode 100644 index 0000000..f4fbf23 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/include/jpeglib.h @@ -0,0 +1,1180 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 90". + */ + +#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ +#define JPEG_LIB_VERSION_MAJOR 9 +#define JPEG_LIB_VERSION_MINOR 1 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, + * so don't change them if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = + * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* For decompression, in cases where some of the components will be + * ignored (eg grayscale output from YCbCr image), we can skip most + * computations for the unused components. + * For compression, some of the components will need further quantization + * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). + * The field is first set TRUE for decompression, FALSE for compression + * in initial_setup, and then adapted in color conversion setup. + */ + boolean component_needed; + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ + JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ +} J_COLOR_SPACE; + +/* Supported color transforms. */ + +typedef enum { + JCT_NONE = 0, + JCT_SUBTRACT_GREEN = 1 +} J_COLOR_TRANSFORM; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier, writes LSE marker if nonzero */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier derived from LSE marker, otherwise zero */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Android/libjpeg.a b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Android/libjpeg.a new file mode 100644 index 0000000..5394bc1 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Android/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Android/libjpeg.so b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Android/libjpeg.so new file mode 100644 index 0000000..aeda23e Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Android/libjpeg.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.a b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.a new file mode 100644 index 0000000..1fbd0a9 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.la b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.la new file mode 100644 index 0000000..0b8f91c --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.la @@ -0,0 +1,41 @@ +# libjpeg.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libjpeg.so.8' + +# Names of this library. +library_names='libjpeg.so.8.4.0 libjpeg.so.8 libjpeg.so' + +# The name of the static archive. +old_library='libjpeg.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/xz/Documents/testing/compile_test/lpng1637/zlib/rk1808/lib' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libjpeg. +current=12 +age=4 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/xz/Documents/testing/compile_test/jpegsrc.v8d1/jpeg-8d1/rk1808/lib' diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so new file mode 100644 index 0000000..acff391 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so @@ -0,0 +1 @@ +libjpeg.so.8.4.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so.8 b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so.8 new file mode 100644 index 0000000..acff391 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so.8 @@ -0,0 +1 @@ +libjpeg.so.8.4.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so.8.4.0 b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so.8.4.0 new file mode 100644 index 0000000..f91df71 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libjpeg/lib/Linux/libjpeg.so.8.4.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/png.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/png.h new file mode 100644 index 0000000..5fb494f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.38 - September 14, 2022 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2022 The PNG Reference Library Authors. + * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.38 16 10638 16.so.16.38[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.38" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 38 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10638 /* 1.6.38 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_38; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explanation of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer calculations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/pngconf.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/pngconf.h new file mode 100644 index 0000000..89d28f8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.38 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/pnglibconf.h new file mode 100644 index 0000000..7a0e1fa --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/libpng16/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.38 */ + +/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/png.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/png.h new file mode 100644 index 0000000..5fb494f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.38 - September 14, 2022 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2022 The PNG Reference Library Authors. + * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.38 16 10638 16.so.16.38[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.38" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 38 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10638 /* 1.6.38 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_38; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explanation of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer calculations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/pngconf.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/pngconf.h new file mode 100644 index 0000000..89d28f8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.38 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/pnglibconf.h new file mode 100644 index 0000000..7a0e1fa --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/include/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.38 */ + +/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng.a b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng.a new file mode 100644 index 0000000..0ab8355 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng.a @@ -0,0 +1 @@ +./libpng16.a \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng.so b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng.so new file mode 100644 index 0000000..c6e48f5 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng.so @@ -0,0 +1 @@ +./libpng16.so \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng16.a b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng16.a new file mode 100644 index 0000000..90cb292 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng16.so b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng16.so new file mode 100644 index 0000000..1792a09 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Android/libpng16.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.a b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.a new file mode 100644 index 0000000..5671875 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.a @@ -0,0 +1 @@ +libpng16.a \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.la b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.la new file mode 100644 index 0000000..3a5dc32 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.la @@ -0,0 +1 @@ +libpng16.la \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.so b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.so new file mode 100644 index 0000000..e41f2c3 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng.so @@ -0,0 +1 @@ +libpng16.so \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.a b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.a new file mode 100644 index 0000000..eef42bb Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.la b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.la new file mode 100644 index 0000000..0156394 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.la @@ -0,0 +1,41 @@ +# libpng16.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libpng16.so.16' + +# Names of this library. +library_names='libpng16.so.16.37.0 libpng16.so.16 libpng16.so' + +# The name of the static archive. +old_library='libpng16.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/xz/Documents/testing/compile_test/lpng1637/zlib/rk1808/lib/ -lz -lm' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libpng16. +current=53 +age=37 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='//home/xz/Documents/testing/compile_test/lpng1637/rk1808/lib' diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so new file mode 100644 index 0000000..a5196c4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so @@ -0,0 +1 @@ +libpng16.so.16.37.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16 b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16 new file mode 100644 index 0000000..a5196c4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16 @@ -0,0 +1 @@ +libpng16.so.16.37.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16.37.0 b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16.37.0 new file mode 100644 index 0000000..35a39c8 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16.37.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16.38.0 b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16.38.0 new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/libpng16.so.16.38.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/pkgconfig/libpng.pc b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/pkgconfig/libpng.pc new file mode 100644 index 0000000..02f0e64 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/pkgconfig/libpng.pc @@ -0,0 +1 @@ +libpng16.pc \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/pkgconfig/libpng16.pc b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/pkgconfig/libpng16.pc new file mode 100644 index 0000000..fa2b2de --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/libpng/lib/Linux/pkgconfig/libpng16.pc @@ -0,0 +1,12 @@ +prefix=//home/xz/Documents/testing/compile_test/lpng1637/rk1808 +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/libpng16 + +Name: libpng +Description: Loads and saves PNG files +Version: 1.6.37 +Requires: zlib +Libs: -L${libdir} -lpng16 +Libs.private: -lm -lz -lm +Cflags: -I${includedir} diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/include/zconf.h b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/include/zconf.h new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/include/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/include/zlib.h b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/include/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/include/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Android/libz.a b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Android/libz.a new file mode 100644 index 0000000..81f55a6 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Android/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Android/libz.so b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Android/libz.so new file mode 100644 index 0000000..577172c Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Android/libz.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.a b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.a new file mode 100644 index 0000000..de8e5f8 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so.1 b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so.1 new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so.1 @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so.1.2.11 b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so.1.2.11 new file mode 100644 index 0000000..286b21a Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/libz.so.1.2.11 differ diff --git a/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/pkgconfig/zlib.pc b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/pkgconfig/zlib.pc new file mode 100644 index 0000000..5495a28 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3399PRO/zlib/lib/Linux/pkgconfig/zlib.pc @@ -0,0 +1,13 @@ +prefix=/home/xz/Documents/testing/compile_test/zlib1211/zlib-1.2.11/rk1808 +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib +Description: zlib compression library +Version: 1.2.11 + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/.gitignore b/rknn_yolo_demo/libs/platform/RK3566_3568/.gitignore new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/.gitignore @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jconfig.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jconfig.h new file mode 100644 index 0000000..cb09382 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jconfig.h @@ -0,0 +1,163 @@ +/* + * jconfig.txt + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * Modified 2009-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file documents the configuration options that are required to + * customize the JPEG software for a particular system. + * + * The actual configuration options for a particular installation are stored + * in jconfig.h. On many machines, jconfig.h can be generated automatically + * or copied from one of the "canned" jconfig files that we supply. But if + * you need to generate a jconfig.h file by hand, this file tells you how. + * + * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. + * EDIT A COPY NAMED JCONFIG.H. + */ + + +/* + * These symbols indicate the properties of your machine or compiler. + * #define the symbol if yes, #undef it if no. + */ + +/* Does your compiler support function prototypes? + * (If not, you also need to use ansi2knr, see install.txt) + */ +#define HAVE_PROTOTYPES + +/* Does your compiler support the declaration "unsigned char" ? + * How about "unsigned short" ? + */ +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT + +/* Define this if an ordinary "char" type is unsigned. + * If you're not sure, leaving it undefined will work at some cost in speed. + * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. + */ +/* #undef CHAR_IS_UNSIGNED */ + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV , + * but does have a BSD-style . + */ +/* #undef NEED_BSD_STRINGS */ + +/* Define this if your system does not provide typedef size_t in any of the + * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in + * instead. + */ +#define NEED_SYS_TYPES_H + +/* For 80x86 machines, you need to define NEED_FAR_POINTERS, + * unless you are using a large-data memory model or 80386 flat-memory mode. + * On less brain-damaged CPUs this symbol must not be defined. + * (Defining this symbol causes large data structures to be referenced through + * "far" pointers and to be allocated with a special version of malloc.) + */ +#undef NEED_FAR_POINTERS + +/* Define this if your linker needs global names to be unique in less + * than the first 15 characters. + */ +#undef NEED_SHORT_EXTERNAL_NAMES + +/* Although a real ANSI C compiler can deal perfectly well with pointers to + * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI + * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, + * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you + * actually get "missing structure definition" warnings or errors while + * compiling the JPEG code. + */ +#undef INCOMPLETE_TYPES_BROKEN + +/* Define "boolean" as unsigned char, not enum, on Windows systems. + */ +#ifdef _WIN32 +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + + +/* + * The following options affect code selection within the JPEG library, + * but they don't need to be visible to applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS has been defined. + */ + +#ifdef JPEG_INTERNALS + +/* Define this if your compiler implements ">>" on signed values as a logical + * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, + * which is the normal and rational definition. + */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + + +#endif /* JPEG_INTERNALS */ + + +/* + * The remaining options do not affect the JPEG library proper, + * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). + * Other applications can ignore these. + */ + +#ifdef JPEG_CJPEG_DJPEG + +/* These defines indicate which image (non-JPEG) file formats are allowed. */ + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* Define this if you want to name both input and output files on the command + * line, rather than using stdout and optionally stdin. You MUST do this if + * your system can't cope with binary I/O to stdin/stdout. See comments at + * head of cjpeg.c or djpeg.c. + */ +#undef TWO_FILE_COMMANDLINE + +/* #undef USE_SETMODE */ + +/* Define this if your system needs explicit cleanup of temporary files. + * This is crucial under MS-DOS, where the temporary "files" may be areas + * of extended memory; on most other systems it's not as important. + */ +#undef NEED_SIGNAL_CATCHER + +/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). + * This is necessary on systems that distinguish text files from binary files, + * and is harmless on most systems that don't. If you have one of the rare + * systems that complains about the "b" spec, define this symbol. + */ +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. + */ +#undef PROGRESS_REPORT + + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jerror.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jerror.h new file mode 100644 index 0000000..a4b661f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2012 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jmorecfg.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jmorecfg.h new file mode 100644 index 0000000..679d68b --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jmorecfg.h @@ -0,0 +1,446 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 9 for 9-bit sample values + * 10 for 10-bit sample values + * 11 for 11-bit sample values + * 12 for 12-bit sample values + * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for + * full-feature DCT processing. Further depths up to 16-bit may be added + * later for the lossless modes of operation. + * Run-time selection and conversion of data precision will be added later + * and are currently not supported, sorry. + * Exception: The transcoding part (jpegtran) supports all settings in a + * single instance, since it operates on the level of DCT coefficients and + * not sample values. The DCT coefficients are of the same type (16 bits) + * in all cases (see below). + */ + +#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 9 +/* JSAMPLE should be the smallest type that will hold the values 0..511. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 511 +#define CENTERJSAMPLE 256 + +#endif /* BITS_IN_JSAMPLE == 9 */ + + +#if BITS_IN_JSAMPLE == 10 +/* JSAMPLE should be the smallest type that will hold the values 0..1023. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 1023 +#define CENTERJSAMPLE 512 + +#endif /* BITS_IN_JSAMPLE == 10 */ + + +#if BITS_IN_JSAMPLE == 11 +/* JSAMPLE should be the smallest type that will hold the values 0..2047. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 2047 +#define CENTERJSAMPLE 1024 + +#endif /* BITS_IN_JSAMPLE == 11 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* The noreturn type identifier is used to declare functions + * which cannot return. + * Compilers can thus create more optimized code and perform + * better checks for warnings and errors. + * Static analyzer tools can make improved inferences about + * execution paths and are prevented from giving false alerts. + * + * Unfortunately, the proposed specifications of corresponding + * extensions in the Dec 2011 ISO C standard revision (C11), + * GCC, MSVC, etc. are not viable. + * Thus we introduce a user defined type to declare noreturn + * functions at least for clarity. A proper compiler would + * have a suitable noreturn type to match in place of void. + */ + +#ifndef HAVE_NORETURN_T +typedef void noreturn_t; +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +#if defined FALSE || defined TRUE || defined QGLOBAL_H +/* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ +typedef int boolean; +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#else +typedef enum { FALSE = 0, TRUE = 1 } boolean; +#endif +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected more than 8-bit data precision, it is dangerous to + * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only + * good for 8-bit precision, so arithmetic coding is recommended for higher + * precision. The Huffman encoder normally uses entropy optimization to + * compute usable tables for higher precision. Otherwise, you'll have to + * supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jpeglib.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jpeglib.h new file mode 100644 index 0000000..f4fbf23 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/include/jpeglib.h @@ -0,0 +1,1180 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 90". + */ + +#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ +#define JPEG_LIB_VERSION_MAJOR 9 +#define JPEG_LIB_VERSION_MINOR 1 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, + * so don't change them if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = + * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* For decompression, in cases where some of the components will be + * ignored (eg grayscale output from YCbCr image), we can skip most + * computations for the unused components. + * For compression, some of the components will need further quantization + * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). + * The field is first set TRUE for decompression, FALSE for compression + * in initial_setup, and then adapted in color conversion setup. + */ + boolean component_needed; + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ + JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ +} J_COLOR_SPACE; + +/* Supported color transforms. */ + +typedef enum { + JCT_NONE = 0, + JCT_SUBTRACT_GREEN = 1 +} J_COLOR_TRANSFORM; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier, writes LSE marker if nonzero */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier derived from LSE marker, otherwise zero */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Android/libjpeg.a b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Android/libjpeg.a new file mode 100644 index 0000000..5394bc1 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Android/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Android/libjpeg.so b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Android/libjpeg.so new file mode 100644 index 0000000..aeda23e Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Android/libjpeg.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Linux/libjpeg.a b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Linux/libjpeg.a new file mode 100644 index 0000000..03d6c00 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Linux/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Linux/libjpeg.so b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Linux/libjpeg.so new file mode 100644 index 0000000..ffc5282 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libjpeg/lib/Linux/libjpeg.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/png.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/png.h new file mode 100644 index 0000000..5fb494f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.38 - September 14, 2022 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2022 The PNG Reference Library Authors. + * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.38 16 10638 16.so.16.38[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.38" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 38 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10638 /* 1.6.38 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_38; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explanation of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer calculations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/pngconf.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/pngconf.h new file mode 100644 index 0000000..89d28f8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.38 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/pnglibconf.h new file mode 100644 index 0000000..7a0e1fa --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/libpng16/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.38 */ + +/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/png.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/png.h new file mode 100644 index 0000000..5fb494f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.38 - September 14, 2022 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2022 The PNG Reference Library Authors. + * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.38 16 10638 16.so.16.38[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.38" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 38 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10638 /* 1.6.38 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_38; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explanation of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer calculations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/pngconf.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/pngconf.h new file mode 100644 index 0000000..89d28f8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.38 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/pnglibconf.h new file mode 100644 index 0000000..7a0e1fa --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/include/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.38 */ + +/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Android/libpng16.a b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Android/libpng16.a new file mode 100644 index 0000000..90cb292 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Android/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Android/libpng16.so b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Android/libpng16.so new file mode 100644 index 0000000..1792a09 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Android/libpng16.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.a b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.a new file mode 100644 index 0000000..61b56ba Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so.16 b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so.16 new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so.16 differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so.16.38.0 b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so.16.38.0 new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/libpng/lib/Linux/libpng16.so.16.38.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/include/zconf.h b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/include/zconf.h new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/include/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/include/zlib.h b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/include/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/include/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Android/libz.a b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Android/libz.a new file mode 100644 index 0000000..81f55a6 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Android/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Android/libz.so b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Android/libz.so new file mode 100644 index 0000000..577172c Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Android/libz.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Linux/libz.a b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Linux/libz.a new file mode 100644 index 0000000..9a085c5 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Linux/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Linux/libz.so b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Linux/libz.so new file mode 100644 index 0000000..ef1d87c Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3566_3568/zlib/lib/Linux/libz.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/.gitignore b/rknn_yolo_demo/libs/platform/RK3588/.gitignore new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/.gitignore @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jconfig.h b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jconfig.h new file mode 100644 index 0000000..cb09382 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jconfig.h @@ -0,0 +1,163 @@ +/* + * jconfig.txt + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * Modified 2009-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file documents the configuration options that are required to + * customize the JPEG software for a particular system. + * + * The actual configuration options for a particular installation are stored + * in jconfig.h. On many machines, jconfig.h can be generated automatically + * or copied from one of the "canned" jconfig files that we supply. But if + * you need to generate a jconfig.h file by hand, this file tells you how. + * + * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. + * EDIT A COPY NAMED JCONFIG.H. + */ + + +/* + * These symbols indicate the properties of your machine or compiler. + * #define the symbol if yes, #undef it if no. + */ + +/* Does your compiler support function prototypes? + * (If not, you also need to use ansi2knr, see install.txt) + */ +#define HAVE_PROTOTYPES + +/* Does your compiler support the declaration "unsigned char" ? + * How about "unsigned short" ? + */ +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT + +/* Define this if an ordinary "char" type is unsigned. + * If you're not sure, leaving it undefined will work at some cost in speed. + * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. + */ +/* #undef CHAR_IS_UNSIGNED */ + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV , + * but does have a BSD-style . + */ +/* #undef NEED_BSD_STRINGS */ + +/* Define this if your system does not provide typedef size_t in any of the + * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in + * instead. + */ +#define NEED_SYS_TYPES_H + +/* For 80x86 machines, you need to define NEED_FAR_POINTERS, + * unless you are using a large-data memory model or 80386 flat-memory mode. + * On less brain-damaged CPUs this symbol must not be defined. + * (Defining this symbol causes large data structures to be referenced through + * "far" pointers and to be allocated with a special version of malloc.) + */ +#undef NEED_FAR_POINTERS + +/* Define this if your linker needs global names to be unique in less + * than the first 15 characters. + */ +#undef NEED_SHORT_EXTERNAL_NAMES + +/* Although a real ANSI C compiler can deal perfectly well with pointers to + * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI + * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, + * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you + * actually get "missing structure definition" warnings or errors while + * compiling the JPEG code. + */ +#undef INCOMPLETE_TYPES_BROKEN + +/* Define "boolean" as unsigned char, not enum, on Windows systems. + */ +#ifdef _WIN32 +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + + +/* + * The following options affect code selection within the JPEG library, + * but they don't need to be visible to applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS has been defined. + */ + +#ifdef JPEG_INTERNALS + +/* Define this if your compiler implements ">>" on signed values as a logical + * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, + * which is the normal and rational definition. + */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + + +#endif /* JPEG_INTERNALS */ + + +/* + * The remaining options do not affect the JPEG library proper, + * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). + * Other applications can ignore these. + */ + +#ifdef JPEG_CJPEG_DJPEG + +/* These defines indicate which image (non-JPEG) file formats are allowed. */ + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* Define this if you want to name both input and output files on the command + * line, rather than using stdout and optionally stdin. You MUST do this if + * your system can't cope with binary I/O to stdin/stdout. See comments at + * head of cjpeg.c or djpeg.c. + */ +#undef TWO_FILE_COMMANDLINE + +/* #undef USE_SETMODE */ + +/* Define this if your system needs explicit cleanup of temporary files. + * This is crucial under MS-DOS, where the temporary "files" may be areas + * of extended memory; on most other systems it's not as important. + */ +#undef NEED_SIGNAL_CATCHER + +/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). + * This is necessary on systems that distinguish text files from binary files, + * and is harmless on most systems that don't. If you have one of the rare + * systems that complains about the "b" spec, define this symbol. + */ +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. + */ +#undef PROGRESS_REPORT + + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jerror.h b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jerror.h new file mode 100644 index 0000000..a4b661f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2012 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jmorecfg.h b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jmorecfg.h new file mode 100644 index 0000000..679d68b --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jmorecfg.h @@ -0,0 +1,446 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 9 for 9-bit sample values + * 10 for 10-bit sample values + * 11 for 11-bit sample values + * 12 for 12-bit sample values + * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for + * full-feature DCT processing. Further depths up to 16-bit may be added + * later for the lossless modes of operation. + * Run-time selection and conversion of data precision will be added later + * and are currently not supported, sorry. + * Exception: The transcoding part (jpegtran) supports all settings in a + * single instance, since it operates on the level of DCT coefficients and + * not sample values. The DCT coefficients are of the same type (16 bits) + * in all cases (see below). + */ + +#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 9 +/* JSAMPLE should be the smallest type that will hold the values 0..511. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 511 +#define CENTERJSAMPLE 256 + +#endif /* BITS_IN_JSAMPLE == 9 */ + + +#if BITS_IN_JSAMPLE == 10 +/* JSAMPLE should be the smallest type that will hold the values 0..1023. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 1023 +#define CENTERJSAMPLE 512 + +#endif /* BITS_IN_JSAMPLE == 10 */ + + +#if BITS_IN_JSAMPLE == 11 +/* JSAMPLE should be the smallest type that will hold the values 0..2047. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 2047 +#define CENTERJSAMPLE 1024 + +#endif /* BITS_IN_JSAMPLE == 11 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* The noreturn type identifier is used to declare functions + * which cannot return. + * Compilers can thus create more optimized code and perform + * better checks for warnings and errors. + * Static analyzer tools can make improved inferences about + * execution paths and are prevented from giving false alerts. + * + * Unfortunately, the proposed specifications of corresponding + * extensions in the Dec 2011 ISO C standard revision (C11), + * GCC, MSVC, etc. are not viable. + * Thus we introduce a user defined type to declare noreturn + * functions at least for clarity. A proper compiler would + * have a suitable noreturn type to match in place of void. + */ + +#ifndef HAVE_NORETURN_T +typedef void noreturn_t; +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +#if defined FALSE || defined TRUE || defined QGLOBAL_H +/* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ +typedef int boolean; +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#else +typedef enum { FALSE = 0, TRUE = 1 } boolean; +#endif +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected more than 8-bit data precision, it is dangerous to + * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only + * good for 8-bit precision, so arithmetic coding is recommended for higher + * precision. The Huffman encoder normally uses entropy optimization to + * compute usable tables for higher precision. Otherwise, you'll have to + * supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jpeglib.h b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jpeglib.h new file mode 100644 index 0000000..f4fbf23 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/include/jpeglib.h @@ -0,0 +1,1180 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 90". + */ + +#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ +#define JPEG_LIB_VERSION_MAJOR 9 +#define JPEG_LIB_VERSION_MINOR 1 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, + * so don't change them if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = + * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* For decompression, in cases where some of the components will be + * ignored (eg grayscale output from YCbCr image), we can skip most + * computations for the unused components. + * For compression, some of the components will need further quantization + * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). + * The field is first set TRUE for decompression, FALSE for compression + * in initial_setup, and then adapted in color conversion setup. + */ + boolean component_needed; + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ + JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ +} J_COLOR_SPACE; + +/* Supported color transforms. */ + +typedef enum { + JCT_NONE = 0, + JCT_SUBTRACT_GREEN = 1 +} J_COLOR_TRANSFORM; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier, writes LSE marker if nonzero */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + J_COLOR_TRANSFORM color_transform; + /* Color transform identifier derived from LSE marker, otherwise zero */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Android/libjpeg.a b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Android/libjpeg.a new file mode 100644 index 0000000..5394bc1 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Android/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Android/libjpeg.so b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Android/libjpeg.so new file mode 100644 index 0000000..aeda23e Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Android/libjpeg.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Linux/libjpeg.a b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Linux/libjpeg.a new file mode 100644 index 0000000..03d6c00 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Linux/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Linux/libjpeg.so b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Linux/libjpeg.so new file mode 100644 index 0000000..ffc5282 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libjpeg/lib/Linux/libjpeg.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/png.h b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/png.h new file mode 100644 index 0000000..5fb494f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.38 - September 14, 2022 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2022 The PNG Reference Library Authors. + * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.38 16 10638 16.so.16.38[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.38" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 38 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10638 /* 1.6.38 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_38; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explanation of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer calculations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/pngconf.h b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/pngconf.h new file mode 100644 index 0000000..89d28f8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.38 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/pnglibconf.h new file mode 100644 index 0000000..7a0e1fa --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/libpng16/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.38 */ + +/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/include/png.h b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/png.h new file mode 100644 index 0000000..5fb494f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.38 - September 14, 2022 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2022 The PNG Reference Library Authors. + * * Copyright (c) 2018-2022 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.38 16 10638 16.so.16.38[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.38" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 38 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10638 /* 1.6.38 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_38; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explanation of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer calculations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/include/pngconf.h b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/pngconf.h new file mode 100644 index 0000000..89d28f8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.38 + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/include/pnglibconf.h b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/pnglibconf.h new file mode 100644 index 0000000..7a0e1fa --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/libpng/include/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.38 */ + +/* Copyright (c) 2018-2022 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Android/libpng16.a b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Android/libpng16.a new file mode 100644 index 0000000..90cb292 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Android/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Android/libpng16.so b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Android/libpng16.so new file mode 100644 index 0000000..1792a09 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Android/libpng16.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.a b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.a new file mode 100644 index 0000000..61b56ba Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so.16 b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so.16 new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so.16 differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so.16.38.0 b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so.16.38.0 new file mode 100644 index 0000000..4ad0176 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/libpng/lib/Linux/libpng16.so.16.38.0 differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/zlib/include/zconf.h b/rknn_yolo_demo/libs/platform/RK3588/zlib/include/zconf.h new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/zlib/include/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/zlib/include/zlib.h b/rknn_yolo_demo/libs/platform/RK3588/zlib/include/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RK3588/zlib/include/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Android/libz.a b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Android/libz.a new file mode 100644 index 0000000..81f55a6 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Android/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Android/libz.so b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Android/libz.so new file mode 100644 index 0000000..577172c Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Android/libz.so differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Linux/libz.a b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Linux/libz.a new file mode 100644 index 0000000..9a085c5 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Linux/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Linux/libz.so b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Linux/libz.so new file mode 100644 index 0000000..ef1d87c Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RK3588/zlib/lib/Linux/libz.so differ diff --git a/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/include/zconf.h b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/include/zconf.h new file mode 100644 index 0000000..995ad4f --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/include/zconf.h @@ -0,0 +1,536 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H +/* #undef Z_PREFIX */ +#define Z_HAVE_UNISTD_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/include/zlib.h b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/include/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/include/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.a b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.a new file mode 100644 index 0000000..d8bd0a5 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so new file mode 100644 index 0000000..35fdc8b --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so @@ -0,0 +1 @@ +libz.so.1 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so.1 b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so.1 new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so.1 @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so.1.2.11 b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so.1.2.11 new file mode 100644 index 0000000..621149b Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1106_1103/zlib/lib/libz.so.1.2.11 differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h new file mode 100644 index 0000000..966b1d5 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jconfig.h @@ -0,0 +1,54 @@ +/* jconfig.h. Generated from jconfig.cfg by configure. */ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.txt for explanations */ + +#define HAVE_PROTOTYPES 1 +#define HAVE_UNSIGNED_CHAR 1 +#define HAVE_UNSIGNED_SHORT 1 +/* #undef void */ +/* #undef const */ +/* #undef CHAR_IS_UNSIGNED */ +#define HAVE_STDDEF_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_LOCALE_H 1 +/* #undef NEED_BSD_STRINGS */ +/* #undef NEED_SYS_TYPES_H */ +/* #undef NEED_FAR_POINTERS */ +/* #undef NEED_SHORT_EXTERNAL_NAMES */ +/* Define this if you get warnings about undefined structures. */ +/* #undef INCOMPLETE_TYPES_BROKEN */ + +/* Define "boolean" as unsigned char, not int, on Windows systems. */ +#ifdef _WIN32 +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + +#ifdef JPEG_INTERNALS + +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ +#define INLINE __inline__ +/* These are for configuring the JPEG memory manager. */ +/* #undef DEFAULT_MAX_MEM */ +/* #undef NO_MKTEMP */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +/* #undef RLE_SUPPORTED */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* #undef TWO_FILE_COMMANDLINE */ +/* #undef NEED_SIGNAL_CATCHER */ +/* #undef DONT_USE_B_MODE */ + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +/* #undef PROGRESS_REPORT */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jerror.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jerror.h new file mode 100644 index 0000000..1cfb2b1 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h new file mode 100644 index 0000000..6c085c3 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jmorecfg.h @@ -0,0 +1,369 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h new file mode 100644 index 0000000..1327cff --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/include/jpeglib.h @@ -0,0 +1,1160 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". + */ + +#define JPEG_LIB_VERSION 80 /* Compatibility version 8.0 */ +#define JPEG_LIB_VERSION_MAJOR 8 +#define JPEG_LIB_VERSION_MINOR 4 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.a b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.a new file mode 100644 index 0000000..b49d26b Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.a differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.la b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.la new file mode 100644 index 0000000..27b9cc9 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.la @@ -0,0 +1,41 @@ +# libjpeg.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libjpeg.so.8' + +# Names of this library. +library_names='libjpeg.so.8.4.0 libjpeg.so.8 libjpeg.so' + +# The name of the static archive. +old_library='libjpeg.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs='' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libjpeg. +current=12 +age=4 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/xz/Documents/testing/compile_test/jpegsrc.v8d1/jpeg-8d1/_install/lib' diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so new file mode 100644 index 0000000..acff391 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so @@ -0,0 +1 @@ +libjpeg.so.8.4.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so.8 b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so.8 new file mode 100644 index 0000000..acff391 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so.8 @@ -0,0 +1 @@ +libjpeg.so.8.4.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so.8.4.0 b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so.8.4.0 new file mode 100644 index 0000000..fe8d5c8 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1109_1126/libjpeg/lib/Linux/libjpeg.so.8.4.0 differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/png.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/png.h new file mode 100644 index 0000000..139eb0d --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/png.h @@ -0,0 +1,3247 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.37 - April 14, 2019 + * + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. (See LICENSE, below.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.35, July 2018: + * Glenn Randers-Pehrson + * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019: + * Cosmin Truta + * See also "Contributing Authors", below. + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE + * ========================================= + * + * PNG Reference Library License version 2 + * --------------------------------------- + * + * * Copyright (c) 1995-2019 The PNG Reference Library Authors. + * * Copyright (c) 2018-2019 Cosmin Truta. + * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * * Copyright (c) 1996-1997 Andreas Dilger. + * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * The software is supplied "as is", without warranty of any kind, + * express or implied, including, without limitation, the warranties + * of merchantability, fitness for a particular purpose, title, and + * non-infringement. In no event shall the Copyright owners, or + * anyone distributing the software, be liable for any damages or + * other liability, whether in contract, tort or otherwise, arising + * from, out of, or in connection with the software, or the use or + * other dealings in the software, even if advised of the possibility + * of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute + * this software, or portions hereof, for any purpose, without fee, + * subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you + * use this software in a product, an acknowledgment in the product + * documentation would be appreciated, but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * + * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) + * ----------------------------------------------------------------------- + * + * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are + * derived from libpng-1.0.6, and are distributed according to the same + * disclaimer and license as libpng-1.0.6 with the following individuals + * added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. + * + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners, and + * are released under other open source licenses. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from + * libpng-0.96, and are distributed according to the same disclaimer and + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, + * and are distributed according to the same disclaimer and license as + * libpng-0.88, with the following individuals added to the list of + * Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * Some files in the "scripts" directory have other copyright owners, + * but are released under this license. + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * result from the use of the PNG Reference Library, even if advised of + * the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. + * + * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. + * + * TRADEMARK + * ========= + * + * The name "libpng" has not been registered by the Copyright owners + * as a trademark in any jurisdiction. However, because libpng has + * been distributed and maintained world-wide, continually since 1995, + * the Copyright owners claim "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s", png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * ... + * 1.0.69 10 10069 10.so.0.69[.0] + * ... + * 1.2.59 13 10259 12.so.0.59[.0] + * ... + * 1.4.20 14 10420 14.so.0.20[.0] + * ... + * 1.5.30 15 10530 15.so.15.30[.0] + * ... + * 1.6.37 16 10637 16.so.16.37[.0] + * + * Henceforth the source version will match the shared-library major and + * minor numbers; the shared-library major version number will be used for + * changes in backward compatibility, as it is intended. + * The PNG_LIBPNG_VER macro, which is not used within libpng but is + * available for applications, is an unsigned integer of the form XYYZZ + * corresponding to the source version X.Y.Z (leading zeros in Y and Z). + * Beta versions were given the previous public release number plus a + * letter, until version 1.0.6j; from then on they were given the upcoming + * public release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO/IEC Standard; see + * + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng-manual.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. If that + * file has been stripped from your copy of libpng, you can find it at + * + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.6.37" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n" + +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 37 + +/* This should be zero for a public release, or non-zero for a + * development version. [Deprecated] + */ +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that + * would be octal. We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here + * (only version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release + */ +#define PNG_LIBPNG_VER 10637 /* 1.6.37 */ + +/* Library configuration: these options cannot be changed after + * the library has been built. + */ +#ifndef PNGLCONF_H +/* If pnglibconf.h is missing, you can + * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h + */ +# include "pnglibconf.h" +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. [omitted] + * 2. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 3. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 4. Exported library functions. + * 5. Simplified API. + * 6. Implementation options. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ + +/* Section 1: [omitted] */ + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_6_37; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001U +#define PNG_INFO_sBIT 0x0002U +#define PNG_INFO_cHRM 0x0004U +#define PNG_INFO_PLTE 0x0008U +#define PNG_INFO_tRNS 0x0010U +#define PNG_INFO_bKGD 0x0020U +#define PNG_INFO_hIST 0x0040U +#define PNG_INFO_pHYs 0x0080U +#define PNG_INFO_oFFs 0x0100U +#define PNG_INFO_tIME 0x0200U +#define PNG_INFO_pCAL 0x0400U +#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* CONVERT_tIME */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and re-encode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the output gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* READ_FILLER || WRITE_FILLER */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +#ifdef PNG_WRITE_SUPPORTED +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); +#endif /* WRITE */ + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) +#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* WRITE_WEIGHTED_FILTER */ + +/* The following are no longer used and will be removed from libpng-1.7: */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_COMPRESSION */ + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +#endif /* WRITE */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PROGRESSIVE_READ */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008U +#define PNG_FREE_ICCP 0x0010U +#define PNG_FREE_SPLT 0x0020U +#define PNG_FREE_ROWS 0x0040U +#define PNG_FREE_PCAL 0x0080U +#define PNG_FREE_SCAL 0x0100U +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200U +#endif +/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000U +#define PNG_FREE_TRNS 0x2000U +#define PNG_FREE_TEXT 0x4000U +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU +#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* EASY_ACCESS */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *exif)); +PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep exif)); + +PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); +PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* sCAL */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WITH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); +#endif /* HANDLE_AS_UNKNOWN */ + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* pHYs */ +#endif /* INCH_CONVERSIONS */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* IO_STATE */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { \ + png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ + } + +# define png_composite_16(composite, fg, alpha, bg) \ + { \ + png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ + } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = \ + (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255)) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = \ + (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535)) +#endif /* READ_COMPOSITE_NODIV */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ + : (png_int_32)png_get_uint_32(buf))) + +/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accommodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two-bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at ) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled. If you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + * + * WARNING: this macro overflows for some images with more than one component + * and very large image widths. libpng will refuse to process an image where + * this macro would overflow. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + * + * WARNING: this macro overflows a 32-bit integer for some large PNG images, + * libpng will refuse to process an image where such an overflow would occur. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates that the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* STDIO */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* SIMPLIFIED_READ */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ + +/* With all write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. If row_stride is + * zero, libpng will calculate it for you from the image width and number of + * channels. + * + * Note that the write API does not support interlacing, sub-8-bit pixels or + * most ancillary chunks. If you need to write text chunks (e.g. for copyright + * notices) you need to use one of the other APIs. + */ + +PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, + png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, + const void *buffer, png_int_32 row_stride, const void *colormap)); + /* Write the image to the given memory buffer. The function both writes the + * whole PNG data stream to *memory and updates *memory_bytes with the count + * of bytes written. + * + * 'memory' may be NULL. In this case *memory_bytes is not read however on + * success the number of bytes which would have been written will still be + * stored in *memory_bytes. On failure *memory_bytes will contain 0. + * + * If 'memory' is not NULL it must point to memory[*memory_bytes] of + * writeable memory. + * + * If the function returns success memory[*memory_bytes] (if 'memory' is not + * NULL) contains the written PNG data. *memory_bytes will always be less + * than or equal to the original value. + * + * If the function returns false and *memory_bytes was not changed an error + * occurred during write. If *memory_bytes was changed, or is not 0 if + * 'memory' was NULL, the write would have succeeded but for the memory + * buffer being too small. *memory_bytes contains the required number of + * bytes and will be bigger that the original value. + */ + +#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ + row_stride, colormap)\ + png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ + row_stride, colormap) + /* Return the amount of memory in 'size' required to compress this image. + * The png_image structure 'image' must be filled in as in the above + * function and must not be changed before the actual write call, the buffer + * and all other parameters must also be identical to that in the final + * write call. The 'size' variable need not be initialized. + * + * NOTE: the macro returns true/false, if false is returned 'size' will be + * set to zero and the write failed and probably will fail if tried again. + */ + +/* You can pre-allocate the buffer by making sure it is of sufficient size + * regardless of the amount of compression achieved. The buffer size will + * always be bigger than the original image and it will never be filled. The + * following macros are provided to assist in allocating the buffer. + */ +#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) + /* The number of uncompressed bytes in the PNG byte encoding of the image; + * uncompressing the PNG IDAT data will give this number of bytes. + * + * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this + * macro can because of the extra bytes used in the PNG byte encoding. You + * need to avoid this macro if your image size approaches 2^30 in width or + * height. The same goes for the remainder of these macros; they all produce + * bigger numbers than the actual in-memory image size. + */ +#ifndef PNG_ZLIB_MAX_SIZE +# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) + /* An upper bound on the number of compressed bytes given 'b' uncompressed + * bytes. This is based on deflateBounds() in zlib; different + * implementations of zlib compression may conceivably produce more data so + * if your zlib implementation is not zlib itself redefine this macro + * appropriately. + */ +#endif + +#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ + PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) + /* An upper bound on the size of the data in the PNG IDAT chunks. */ + +#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ + ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ + (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ + 12U+3U*(image).colormap_entries/*PLTE data*/+\ + (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ + 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ + 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) + /* A helper for the following macro; if your compiler cannot handle the + * following macro use this one with the result of + * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most + * compilers should handle this just fine.) + */ + +#define PNG_IMAGE_PNG_SIZE_MAX(image)\ + PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) + /* An upper bound on the total length of the PNG data stream for 'image'. + * The result is of type png_alloc_size_t, on 32-bit systems this may + * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will + * run out of buffer space but return a corrected size which should work. + */ +#endif /* SIMPLIFIED_WRITE */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ +#endif /* SIMPLIFIED_{READ|WRITE} */ + +/******************************************************************************* + * Section 6: IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ +#ifdef PNG_MIPS_MSA_API_SUPPORTED +# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#endif +#define PNG_IGNORE_ADLER32 8 +#ifdef PNG_POWERPC_VSX_API_SUPPORTED +# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ +#endif +#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif /* SET_OPTION */ + +/******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(249); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/pngconf.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/pngconf.h new file mode 100644 index 0000000..927a769 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/pngconf.h @@ -0,0 +1,623 @@ + +/* pngconf.h - machine-configurable file for libpng + * + * libpng version 1.6.37 + * + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16-bit and 32-bit + * values from PNG files. It can be set on a per-app-file basis: it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows systems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ + +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args) \ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) && defined(__has_attribute) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif + +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8-bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16-bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16-bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32-bit (or more) type" +#endif + +#if UINT_MAX > 4294967294U + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294U + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32-bit (or more) type" +#endif + +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/pnglibconf.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/pnglibconf.h new file mode 100644 index 0000000..7f6a817 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/libpng16/pnglibconf.h @@ -0,0 +1,219 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.37 */ + +/* Copyright (c) 2018-2019 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0x12b0 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h new file mode 100644 index 0000000..bbca0e8 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/png.h @@ -0,0 +1 @@ +libpng16/png.h \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h new file mode 100644 index 0000000..addd8a1 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pngconf.h @@ -0,0 +1 @@ +libpng16/pngconf.h \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h new file mode 100644 index 0000000..64d182a --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/include/pnglibconf.h @@ -0,0 +1 @@ +libpng16/pnglibconf.h \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.a b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.a new file mode 100644 index 0000000..5671875 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.a @@ -0,0 +1 @@ +libpng16.a \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.la b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.la new file mode 100644 index 0000000..3a5dc32 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.la @@ -0,0 +1 @@ +libpng16.la \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.so b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.so new file mode 100644 index 0000000..e41f2c3 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng.so @@ -0,0 +1 @@ +libpng16.so \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.a b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.a new file mode 100644 index 0000000..eb43fc0 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.a differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.la b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.la new file mode 100644 index 0000000..26050e0 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.la @@ -0,0 +1,41 @@ +# libpng16.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libpng16.so.16' + +# Names of this library. +library_names='libpng16.so.16.37.0 libpng16.so.16 libpng16.so' + +# The name of the static archive. +old_library='libpng16.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/xz/Documents/testing/compile_test/lpng1637/zlib/rv1109/lib/ -lz -lm' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libpng16. +current=53 +age=37 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='///home/xz/Documents/testing/compile_test/lpng1637/build/lib' diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so new file mode 100644 index 0000000..a5196c4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so @@ -0,0 +1 @@ +libpng16.so.16.37.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so.16 b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so.16 new file mode 100644 index 0000000..a5196c4 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so.16 @@ -0,0 +1 @@ +libpng16.so.16.37.0 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so.16.37.0 b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so.16.37.0 new file mode 100644 index 0000000..56fbd19 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/libpng16.so.16.37.0 differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/pkgconfig/libpng.pc b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/pkgconfig/libpng.pc new file mode 100644 index 0000000..02f0e64 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/pkgconfig/libpng.pc @@ -0,0 +1 @@ +libpng16.pc \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/pkgconfig/libpng16.pc b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/pkgconfig/libpng16.pc new file mode 100644 index 0000000..5a33e37 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/libpng/lib/Linux/pkgconfig/libpng16.pc @@ -0,0 +1,12 @@ +prefix=///home/xz/Documents/testing/compile_test/lpng1637/build +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/libpng16 + +Name: libpng +Description: Loads and saves PNG files +Version: 1.6.37 +Requires: zlib +Libs: -L${libdir} -lpng16 +Libs.private: -lm -lz -lm +Cflags: -I${includedir} diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include/zconf.h b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include/zconf.h new file mode 100644 index 0000000..77398c1 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include/zlib.h b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/include/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.a b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.a new file mode 100644 index 0000000..b0497bd Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.a differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so.1 b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so.1 new file mode 100644 index 0000000..95e0ebd --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so.1 @@ -0,0 +1 @@ +libz.so.1.2.11 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so.1.2.11 b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so.1.2.11 new file mode 100644 index 0000000..a789b70 Binary files /dev/null and b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/libz.so.1.2.11 differ diff --git a/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/pkgconfig/zlib.pc b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/pkgconfig/zlib.pc new file mode 100644 index 0000000..d378ea2 --- /dev/null +++ b/rknn_yolo_demo/libs/platform/RV1109_1126/zlib/lib/Linux/pkgconfig/zlib.pc @@ -0,0 +1,13 @@ +prefix=/home/xz/Documents/testing/compile_test/zlib1211/zlib-1.2.11/build +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib +Description: zlib compression library +Version: 1.2.11 + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/rknn_yolo_demo/libs/rklibs/.gitignore b/rknn_yolo_demo/libs/rklibs/.gitignore new file mode 100644 index 0000000..70b84df --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/.gitignore @@ -0,0 +1 @@ +.gitreview diff --git a/rknn_yolo_demo/libs/rklibs/LICENSE b/rknn_yolo_demo/libs/rklibs/LICENSE new file mode 100644 index 0000000..0fbe7ec --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/LICENSE @@ -0,0 +1,28 @@ +// Copyright 2020 Rockchip Electronics Co.,Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. diff --git a/rknn_yolo_demo/libs/rklibs/README.md b/rknn_yolo_demo/libs/rklibs/README.md new file mode 100644 index 0000000..416a03c --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/README.md @@ -0,0 +1,18 @@ +## rklibs + +在 rknn_model_zoo/libs/rklibs 目录下,根据实际需要,下载以下依赖库 + +``` +# RK1808/RV1126/RV1109 NPU 依赖库 +git clone https://github.com/rockchip-linux/rknpu + +# RK3399pro NPU 依赖库 +git clone https://github.com/airockchip/RK3399Pro_npu + +# RK3566/RK3568/RK3588/RV1106/RV1103 NPU 依赖库 +git clone https://github.com/rockchip-linux/rknpu2 + +# RGA调用依赖库,不区分硬件平台 +git clone https://github.com/airockchip/librga +``` + diff --git a/rknn_yolo_demo/libs/rklibs/drivers/README b/rknn_yolo_demo/libs/rklibs/drivers/README new file mode 100644 index 0000000..221dc00 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/README @@ -0,0 +1,5 @@ +Mini driver (folder name contains mini) only support rknn models with precompiled mode. + +linux-aarch64: RK1808 +linux-arm: RK1806 +linux-armhf-puma: RV1109/RV1126 diff --git a/rknn_yolo_demo/libs/rklibs/drivers/common/etc/init.d/S05NPU_init b/rknn_yolo_demo/libs/rklibs/drivers/common/etc/init.d/S05NPU_init new file mode 100644 index 0000000..b9e97ab --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/common/etc/init.d/S05NPU_init @@ -0,0 +1,43 @@ +#!/bin/sh + +GetDDRBitWidth() +{ + bit=1 + a=1 + while [ 1 ];do + a=$((1<<$bit)) + if [ $a -ge $1 ];then + break + fi + let bit++ + done + return $(($bit<16?16:$bit)) +} + + + +case "$1" in + start) + printf "insmod NPU modules: " + cp /usr/lib/cl_*.h /tmp/ + DDR_SIZE=`cat /proc/meminfo|grep MemTotal|awk '{print $2}'` + GetDDRBitWidth $DDR_SIZE + bitWidth=$(($?+10)) + insmod /lib/modules/galcore.ko contiguousSize=0x400000 DDRBitWidth=$bitWidth + unset MAX_FREQ + read MAX_FREQ < /sys/class/devfreq/ffbc0000.npu/max_freq + echo $MAX_FREQ > /sys/class/devfreq/ffbc0000.npu/userspace/set_freq + [ $? = 0 ] && echo "OK" || echo "FAIL" +#start_rknn.sh & + ;; + stop) + ;; + restart|reload) + $0 stop + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 diff --git a/rknn_yolo_demo/libs/rklibs/drivers/common/etc/init.d/S60NPU_init b/rknn_yolo_demo/libs/rklibs/drivers/common/etc/init.d/S60NPU_init new file mode 100644 index 0000000..2b3e454 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/common/etc/init.d/S60NPU_init @@ -0,0 +1,43 @@ +#!/bin/sh -x + +GetDDRBitWidth() +{ + bit=1 + a=1 + while [ 1 ];do + a=$((1<<$bit)) + if [ $a -ge $1 ];then + break + fi + let bit++ + done + return $(($bit<16?16:$bit)) +} + + + +case "$1" in + start) + printf "insmod NPU modules: " + cp /usr/lib/cl_*.h /tmp/ + DDR_SIZE=`cat /proc/meminfo|grep MemTotal|awk '{print $2}'` + GetDDRBitWidth $DDR_SIZE + bitWidth=$(($?+10)) + insmod /lib/modules/galcore.ko contiguousSize=0x400000 DDRBitWidth=$bitWidth + unset MAX_FREQ + read MAX_FREQ < /sys/class/devfreq/ffbc0000.npu/max_freq + echo $MAX_FREQ > /sys/class/devfreq/ffbc0000.npu/userspace/set_freq + [ $? = 0 ] && echo "OK" || echo "FAIL" + start_rknn.sh & + ;; + stop) + ;; + restart|reload) + $0 stop + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 diff --git a/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/restart_rknn.sh b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/restart_rknn.sh new file mode 100644 index 0000000..a38bee3 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/restart_rknn.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +killall start_rknn.sh > /dev/null 2>&1 +killall rknn_server > /dev/null 2>&1 +start_rknn.sh & diff --git a/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/start_rknn.sh b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/start_rknn.sh new file mode 100644 index 0000000..4de64ac --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/start_rknn.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +export RKNN_SERVER_PLUGINS='/usr/lib/npu/rknn/plugins/' + +while true +do + sleep 1 + rknn_server #>/dev/null 2>&1 +done diff --git a/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/start_usb.sh b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/start_usb.sh new file mode 100644 index 0000000..0dc8ab4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/bin/start_usb.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +configfs_init() +{ + PID=$1 + CONFIG_STRING=$2 + mkdir -p /dev/usb-ffs -m 0770 + mkdir -p /dev/usb-ffs/$CONFIG_STRING -m 0770 + mount -t configfs none /sys/kernel/config + mkdir -p /sys/kernel/config/usb_gadget/rockchip -m 0770 + echo 0x2207 > /sys/kernel/config/usb_gadget/rockchip/idVendor + echo $PID > /sys/kernel/config/usb_gadget/rockchip/idProduct + mkdir -p /sys/kernel/config/usb_gadget/rockchip/strings/0x409 -m 0770 + echo "0123456789ABCDEF" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/serialnumber + echo "rockchip" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/manufacturer + echo "rk3xxx" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/product + mkdir -p /sys/kernel/config/usb_gadget/rockchip/configs/b.1 -m 0770 + mkdir -p /sys/kernel/config/usb_gadget/rockchip/configs/b.1/strings/0x409 -m 0770 + echo 500 > /sys/kernel/config/usb_gadget/rockchip/configs/b.1/MaxPower + echo \"$CONFIG_STRING\" > /sys/kernel/config/usb_gadget/rockchip/configs/b.1/strings/0x409/configuration +} + +function_init() +{ + CONFIG_STRING=$1 + mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/ffs.$CONFIG_STRING + rm -f /sys/kernel/config/usb_gadget/rockchip/configs/b.1/ffs.* + ln -s /sys/kernel/config/usb_gadget/rockchip/functions/ffs.$CONFIG_STRING /sys/kernel/config/usb_gadget/rockchip/configs/b.1/ffs.$CONFIG_STRING +} + +case "$1" in +adb) + killall adbd start_rknn.sh rknn_server > /dev/null 2>&1 + + echo "none" > /sys/kernel/config/usb_gadget/rockchip/UDC + + umount /sys/kernel/config + umount /dev/usb-ffs/ntb > /dev/null 2>&1 + rm -rf /dev/usb-ffs/ntb + + configfs_init 0x0006 adb + function_init adb + + # START_APP_BEFORE_UDC + mkdir -p /dev/usb-ffs/adb + mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb + export service_adb_tcp_port=5555 + adbd& + sleep 1 + + UDC=`ls /sys/class/udc/| awk '{print $1}'` + echo $UDC > /sys/kernel/config/usb_gadget/rockchip/UDC + # START_APP_AFTER_UDC + + start_rknn.sh & + + ;; +ntb) + killall adbd start_rknn.sh rknn_server > /dev/null 2>&1 + + echo "none" > /sys/kernel/config/usb_gadget/rockchip/UDC + + umount /sys/kernel/config + umount /dev/usb-ffs/adb > /dev/null 2>&1 + rm -rf /dev/usb-ffs/adb + + configfs_init 0x1808 ntb + function_init ntb + + # START_APP_BEFORE_UDC + mkdir -p /dev/usb-ffs/ntb + mount -o uid=2000,gid=2000 -t functionfs ntb /dev/usb-ffs/ntb + + start_rknn.sh & + + ;; +*) + echo "Usage: $0 {adb|ntb}" + exit 1 +esac + +exit 0 diff --git a/rknn_yolo_demo/libs/rklibs/drivers/common/usr/lib/cl_viv_vx_ext.h b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/lib/cl_viv_vx_ext.h new file mode 100644 index 0000000..a6ecd50 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/drivers/common/usr/lib/cl_viv_vx_ext.h @@ -0,0 +1,1456 @@ + + + +#ifndef _GC_VX_H +#define _GC_VX_H 1 + +#ifdef _VIV_VX_EXTENSION + +#pragma OPENCL EXTENSION CL_VIV_asm : enable + +#ifndef VX_VERSION +#define VX_VERSION 1 +#endif + +typedef enum _VXC_FilterMode +{ + VXC_FM_BOX = 0, + VXC_FM_Guassian = 1, + VXC_FM_SobelX = 2, + VXC_FM_SobelY = 3, + VXC_FM_ScharrX = 4, + VXC_FM_ScharrY = 5, + VXC_FM_Max = 8, + VXC_FM_Min = 9, + VXC_FM_Median = 10 +} vxc_filter_mode; + +typedef enum _VXC_RoundMode +{ + VXC_RM_Truncate = 0, + VXC_RM_TowardZero = 0, + VXC_RM_TowardInf = 1, + VXC_RM_ToNearestEven = 2 +} vxc_round_mode; + +typedef enum _VXC_ScatteredOffsetType +{ + VXC_OFFSET_UNSIGNED32 = 0, + VXC_OFFSET_SIGNED32 = 1, + VXC_OFFSET_UNSIGNED16 = 2, + VXC_OFFSET_SIGNED16 = 3, + VXC_OFFSET_UNSIGNED8 = 4, + VXC_OFFSET_SIGNED8 = 5, +} VXC_ScatteredOffsetType; + +typedef enum _VXC_AtomicOp +{ + VXC_ATOMIC_OP_ADD = 0, + VXC_ATOMIC_OP_MIN = 1, + VXC_ATOMIC_OP_MAX = 2, + VXC_ATOMIC_OP_OR = 3, + VXC_ATOMIC_OP_AND = 4, + VXC_ATOMIC_OP_XOR = 5, + VXC_ATOMIC_OP_XCHG = 6, +}VXC_AtomicOpType; + +#define VXC_CLAMP_BITMASK 0x00400000 +#define VXC_PREADJ_BITMASK 0x00200000 +#define VXC_RANGEPI_BITMASK 0x00100000 +#define VXC_FILTER_BITMASK 0x000F0000 +#define VXC_START_BIN_BITMASK 0x0000F000 +#define VXC_END_BIN_BITMASK 0x00000F00 +#define VXC_SOURCE_BIN_BITMASK 0x000000F0 +#define VXC_ROUNDING_MODE_BITMASK 0x0000000C +#define VXC_ENABLEBOOL_BITMASK 0x00000002 +#define VXC_SIGNEXT_BITMASK 0x00000001 + + +#define VXC_OFFSET_TYPE_BITMASK 0x00070000 +#define VXC_OFFSET_TYPE_SHIFT 16 + + +#define VXC_ATOM_OP_BITMASK 0x00380000 +#define VXC_ATOM_OP_SHIFT 19 + +#define VXC_MODIFIER(StartBin, EndBin, SourceBin, RoundingMode, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) | \ + ((RoundingMode << 2)&VXC_ROUNDING_MODE_BITMASK) \ + ) + +#define VXC_MODIFIER_SIGNEXT(StartBin, EndBin, SourceBin, SignExt, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + ((SignExt)&VXC_SIGNEXT_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_MAGPHASE(StartBin, EndBin, SourceBin, NoPreAdjust, RangePi) \ + ( \ + (VXC_CLAMP_BITMASK) | \ + (((RangePi) << 20)&VXC_RANGEPI_BITMASK) | \ + (((NoPreAdjust) << 21)&VXC_PREADJ_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_CLAMP(StartBin, EndBin, SourceBin, EnableBool) \ + ( \ + (((EnableBool) << 1)&VXC_ENABLEBOOL_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_FILTER(StartBin, EndBin, SourceBin, Filter, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + (((Filter) << 16)&VXC_FILTER_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_BIN(StartBin, EndBin, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_GATHER(StartBin, EndBin, SourceBin, OffsetType) \ + ( \ + (((OffsetType) << VXC_OFFSET_TYPE_SHIFT)&VXC_OFFSET_TYPE_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_SCATTER(StartBin, EndBin, SourceBin, OffsetType) \ + ( \ + (((OffsetType) << VXC_OFFSET_TYPE_SHIFT)&VXC_OFFSET_TYPE_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_ATOMIC_S(StartBin, EndBin, SourceBin, OffsetType, AtomOp) \ + ( \ + (((OffsetType) << VXC_OFFSET_TYPE_SHIFT)&VXC_OFFSET_TYPE_BITMASK) | \ + (((AtomOp) << VXC_ATOM_OP_SHIFT)&VXC_ATOM_OP_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + + +#define VXC_MODIFIER_SetDestClamp(VxModifier, Clamp) ((VxModifier) | (((Clamp) << 22)&VXC_CLAMP_BITMASK)) + +#define VXC_DEFAULT_MODIFIER (-1) + +typedef unsigned int vxc_modifier; + + +typedef _viv_char2_packed vxc_char2; +typedef _viv_char4_packed vxc_char4; +typedef _viv_char8_packed vxc_char8; +typedef _viv_char16_packed vxc_char16; +typedef struct _vxc_char32 +{ + vxc_char16 hi; + vxc_char16 lo; +} vxc_char32; + + +typedef _viv_uchar2_packed vxc_uchar2; +typedef _viv_uchar4_packed vxc_uchar4; +typedef _viv_uchar8_packed vxc_uchar8; +typedef _viv_uchar16_packed vxc_uchar16; +typedef struct _vxc_uchar32 +{ + vxc_uchar16 hi; + vxc_uchar16 lo; +} vxc_uchar32; + + +typedef _viv_short2_packed vxc_short2; +typedef _viv_short4_packed vxc_short4; +typedef _viv_short8_packed vxc_short8; +typedef struct _vxc_short16 +{ + vxc_short8 hi; + vxc_short8 lo; +} vxc_short16; + + +typedef _viv_ushort2_packed vxc_ushort2; +typedef _viv_ushort4_packed vxc_ushort4; +typedef _viv_ushort8_packed vxc_ushort8; +typedef struct _vxc_ushort16 +{ + vxc_ushort8 hi; + vxc_ushort8 lo; +} vxc_ushort16; + + +typedef int vxc_int; +typedef int2 vxc_int2; +typedef int4 vxc_int4; +typedef int8 vxc_int8; +typedef int16 vxc_int16; + + +typedef uint vxc_uint; +typedef uint2 vxc_uint2; +typedef uint4 vxc_uint4; +typedef uint8 vxc_uint8; +typedef uint16 vxc_uint16; + + +typedef float vxc_float; +typedef float2 vxc_float2; +typedef float4 vxc_float4; +typedef float8 vxc_float8; +typedef float16 vxc_float16; + + +typedef half vxc_half; +typedef _viv_half2_packed vxc_half2; +typedef _viv_half4_packed vxc_half4; +typedef _viv_half8_packed vxc_half8; +typedef struct _vxc_half16 +{ + vxc_half8 hi; + vxc_half8 lo; +} vxc_half16; + +typedef uint16 vxc_512bits; +typedef uint4 vxc_128bits; + +typedef vxc_512bits VXC_512Bits; +typedef vxc_128bits VXC_128Bits; +typedef vxc_modifier VXC_Modifier_t ; +typedef vxc_round_mode VXC_RoundMode; +typedef vxc_filter_mode VXC_FilterMode; + +#ifndef VX_USE_INTRINSIC +#define VX_USE_INTRINSIC 0 +#endif + +enum VXC_OP { + VXC_OP_abs_diff = 3, + VXC_OP_iadd, + VXC_OP_iacc_sq, + VXC_OP_lerp, + VXC_OP_filter, + VXC_OP_mag_phase, + VXC_OP_mul_shift, + VXC_OP_dp16x1, + VXC_OP_dp8x2, + VXC_OP_dp4x4, + VXC_OP_dp2x8, + VXC_OP_clamp, + VXC_OP_bi_linear, + VXC_OP_select_add, + VXC_OP_atomic_add, + VXC_OP_bit_extract, + VXC_OP_bit_replace, + VXC_OP_dp32x1, + VXC_OP_dp16x2, + VXC_OP_dp8x4, + VXC_OP_dp4x8, + VXC_OP_dp2x16, + VXC_OP_dp32x1_b, + VXC_OP_dp16x2_b, + VXC_OP_dp8x4_b, + VXC_OP_dp4x8_b, + VXC_OP_dp2x16_b, + VXC_OP_img_load, + VXC_OP_img_load_3d, + VXC_OP_img_store, + VXC_OP_img_store_3d, + VXC_OP_vload2, + VXC_OP_vload3, + VXC_OP_vload4, + VXC_OP_vload8, + VXC_OP_vload16, + VXC_OP_vstore2, + VXC_OP_vstore3, + VXC_OP_vstore4, + VXC_OP_vstore8, + VXC_OP_vstore16, + VXC_OP_index_add, + VXC_OP_vert_min3, + VXC_OP_vert_max3, + VXC_OP_vert_med3, + VXC_OP_horz_min3, + VXC_OP_horz_max3, + VXC_OP_horz_med3, + VXC_OP_error, + OP_bit_extract, + VXC_OP_dp16x1_b, + VXC_OP_dp8x2_b, + VXC_OP_dp4x4_b, + VXC_OP_dp2x8_b, + VXC_OP_gather, + VXC_OP_gather_b, + VXC_OP_scatter, + VXC_OP_scatter_b, + VXC_OP_atomic_s, + VXC_OP_atomic_s_b, +}; + +enum eVXC_ERROR +{ + ERROR_DP2x16_NOT_SUPPORTED, + ERROR_IADD_NOT_SUPPORTED, + ERROR_SELECTADD_NOT_SUPPORTED, + ERROR_BITREPLACE_NOT_SUPPORTED +}; + +#define VXC_OP1(Op, Dest, Src0) _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, Src0) + +#define VXC_OP2(Op, Dest, Src0, Src1) \ + do { \ + int _t1; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t1); \ + } while(0) + +#define VXC_OP3(Op, Dest, Src0, Src1, Src2) \ + do { \ + int _t1, _t2; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t2); \ + } while(0) + +#define VXC_OP3_NoDest(Op, Src0, Src1, Src2) \ + do { \ + int _t1, _t2, _t3; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(INTRINSIC_ST, _t3, VXC_OP_##Op, _t2); \ + } while(0) + + +#define VXC_OP4(Op, Dest, Src0, Src1, Src2, Src3) \ + do { \ + int _t1, _t2, _t3; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t3); \ + } while(0) + +#define VXC_OP4_NoDest(Op, Src0, Src1, Src2, Src3) \ + do { \ + int _t1, _t2, _t3, _t4; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(INTRINSIC_ST, _t4, VXC_OP_##Op, _t3); \ + } while(0) + +#define VXC_OP4_ST(Op, Dest, Src0, Src1, Src2, Src3) \ + do { \ + int _t1, _t2, _t3; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(INTRINSIC_ST, Dest, VXC_OP_##Op, _t3);\ + } while(0) + +#define VXC_OP5(Op, Dest, Src0, Src1, Src2, Src3, Src4) \ + do { \ + int _t1, _t2, _t3, _t4; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(PARAM_CHAIN, _t4, _t3, Src4); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t4); \ + } while(0) + +#define VXC_OP5_NoDest(Op, Src0, Src1, Src2, Src3, Src4) \ + do { \ + int _t1, _t2, _t3, _t4, _t5; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(PARAM_CHAIN, _t4, _t3, Src4); \ + _viv_asm(INTRINSIC_ST, _t5, VXC_OP_##Op, _t4); \ + } while(0) + + +#define VXC_5BITOFFSET_XY(offsetX, offsetY) ((((offsetY) & 0x1F) << 5) | ((offsetX) & 0x1F)) + + + +#if !VX_USE_INTRINSIC +#define VXC_AbsDiff(Dest, Src0, Src1, Info) VXC_OP3(abs_diff, Dest, Src0, Src1, Info) +#define VXC_IAccSq(Dest, Src0, Src1, Imm, Info) VXC_OP4(iacc_sq, Dest, Src0, Src1, Imm, Info) +#define VXC_Lerp(Dest, Src0, Src1, Src2, Info) VXC_OP4(lerp, Dest, Src0, Src1, Src2, Info) + +#define VXC_MulShift(Dest, Src0, Src1, Imm, Info) VXC_OP4(mul_shift, Dest, Src0, Src1, Imm, Info) +#define VXC_Clamp(Dest, Src0, Src1, Src2, Info) VXC_OP4(clamp, Dest, Src0, Src1, Src2, Info) +#define VXC_AtomicAdd(Dest, Base, Offset, Data, Info) VXC_OP4_ST(atomic_add, Dest, Base, Offset, Data, Info) +#define VXC_BitExtract(Dest, Src0, Src1, Src2, Info) VXC_OP4(bit_extract, Dest, Src0, Src1, Src2, Info) + +#define VXC_DP16x1(Dest, Src0, Src1, Info, U512) VXC_OP4(dp16x1, Dest, Src0, Src1, Info, U512) +#define VXC_DP8x2(Dest, Src0, Src1, Info, U512) VXC_OP4(dp8x2, Dest, Src0, Src1, Info, U512) +#define VXC_DP4x4(Dest, Src0, Src1, Info, U512) VXC_OP4(dp4x4, Dest, Src0, Src1, Info, U512) +#define VXC_DP2x8(Dest, Src0, Src1, Info, U512) VXC_OP4(dp2x8, Dest, Src0, Src1, Info, U512) + +#define VXC_DP32x1(Dest, Src0, Src1, Info, U512) VXC_OP4(dp32x1, Dest, Src0, Src1, Info, U512) +#define VXC_DP16x2(Dest, Src0, Src1, Info, U512) VXC_OP4(dp16x2, Dest, Src0, Src1, Info, U512) +#define VXC_DP8x4(Dest, Src0, Src1, Info, U512) VXC_OP4(dp8x4, Dest, Src0, Src1, Info, U512) +#define VXC_DP4x8(Dest, Src0, Src1, Info, U512) VXC_OP4(dp4x8, Dest, Src0, Src1, Info, U512) +#if (VX_VERSION >= 2) +#define VXC_DP2x16(Dest, Src0, Src1, Info, U512) VXC_OP1(error, ERROR_DP2x16_NOT_SUPPORTED) +#else +#define VXC_DP2x16(Dest, Src0, Src1, Info, U512) VXC_OP4(dp2x16, Dest, Src0, Src1, Info, U512) +#endif + +#if (VX_VERSION >= 2) + +#define VXC_DP16x1_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp16x1_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP8x2_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp8x2_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP4x4_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp4x4_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP2x8_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp2x8_b, Dest, Src0, Src1, Src2, Info, U512) +#endif + + +#define VXC_DP32x1_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp32x1_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP16x2_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp16x2_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP8x4_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp8x4_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP4x8_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp4x8_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP2x16_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp2x16_b, Dest, Src0, Src1, Src2, Info, U512) + +#define VXC_Gather(Dest, BaseAddr, Offsets, GatherInfo) VXC_OP3(gather, Dest, BaseAddr, Offsets, GatherInfo) +#define VXC_Gather_b(Dest, BaseAddr, Offsets, Offsets_b, GatherInfo) VXC_OP4(gather_b, Dest, BaseAddr, Offsets, Offsets_b, GatherInfo) + +#define VXC_Scatter(BaseAddr, Offsets, Data, ScatterInfo) VXC_OP4_NoDest(scatter, BaseAddr, Offsets, Data, ScatterInfo) +#define VXC_Scatter_b(BaseAddr, Offsets, Offsets_b, Data, ScatterInfo) VXC_OP5_NoDest(scatter_b, BaseAddr, Offsets, Offsets_b, Data, ScatterInfo) + +#define VXC_AtomicS(Dest, BaseAddr, Offsets, Data, AtomicSInfo) VXC_OP4(atomic_s, Dest, BaseAddr, Offsets, Data, AtomicSInfo) +#define VXC_AtomicS_b(Dest, BaseAddr, Offsets, Offsets_b, Data, AtomicSInfo) VXC_OP5(atomic_s_b, Dest, BaseAddr, Offsets, Offsets_b, Data, AtomicSInfo) + + + +#define VXC_ReadImage(Dest, Image, Coord, Offset, Info) VXC_OP4(img_load, Dest, Image, Coord, Offset, Info) +#define VXC_WriteImage(Image, Coord, Color, Info) VXC_OP4_NoDest(img_store, Image, Coord, Color, Info) + + +#define VXC_ReadImage2DArray(Dest, Image, Coord, Offset, Info) \ + do { \ + int8 desc; \ + _viv_asm(COPY, desc, Image, sizeof(desc)); \ + _viv_asm(CLAMP0MAX, (Coord).w, (Coord).z, desc.s5 - 1); \ + int baseAddr = (int)(Coord).w *desc.s4 + desc.s0; \ + _viv_asm(MOV, (Coord).w, baseAddr); \ + VXC_OP4(img_load_3d, Dest, Image, (Coord).xyww, Offset, Info); \ + } while (0) +#define VXC_WriteImage2DArray(Image, Coord, Color, Info) \ + do { \ + int8 desc; \ + _viv_asm(COPY, desc, Image, sizeof(desc)); \ + _viv_asm(CLAMP0MAX, (Coord).w, (Coord).z, desc.s5 - 1); \ + int baseAddr = (int)(Coord).w *(desc).s4 + desc.s0; \ + _viv_asm(MOV, (Coord).w, baseAddr); \ + VXC_OP4_NoDest(img_store_3d, Image, (Coord).xyww, Color, Info); \ + } while (0) + + +#define VXC_ReadImage3D(Dest, Image, Coord, Offset, Info) VXC_OP4(img_load_3d, Dest, Image, Coord, Offset, Info) +#define VXC_WriteImage3D(Image, Coord, Color, Info) VXC_OP4_NoDest(img_store_3d, Image, Coord, Color, Info) + +#define VXC_Vload2(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload2, Dest, Pointer, byteOffset); } while(0) +#define VXC_Vload4(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload4, Dest, Pointer, byteOffset); } while(0) +#define VXC_Vload8(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload8, Dest, Pointer, byteOffset); } while(0) +#define VXC_Vload16(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload16, Dest, Pointer, byteOffset); } while(0) + +#define VXC_Vstore2(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore2, Pointer, byteOffset, Data); } while(0) +#define VXC_Vstore4(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore4, Pointer, byteOffset, Data); } while(0) +#define VXC_Vstore8(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore8, Pointer, byteOffset, Data); } while(0) +#define VXC_Vstore16(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore16, Pointer, byteOffset, Data); } while(0) + + +#define VXC_IndexAdd(Dest, Src0, Src1, Src2, Info) VXC_OP4(index_add, Dest, Src0, Src1, Src2, Info) +#define VXC_VertMin3(Dest, Src0, Src1, Src2, Info) VXC_OP4(vert_min3, Dest, Src0, Src1, Src2, Info) +#define VXC_VertMax3(Dest, Src0, Src1, Src2, Info) VXC_OP4(vert_max3, Dest, Src0, Src1, Src2, Info) +#define VXC_VertMed3(Dest, Src0, Src1, Src2, Info) VXC_OP4(vert_med3, Dest, Src0, Src1, Src2, Info) +#define VXC_HorzMin3(Dest, Src0, Info) VXC_OP2(horz_min3, Dest, Src0, Info) +#define VXC_HorzMax3(Dest, Src0, Info) VXC_OP2(horz_max3, Dest, Src0, Info) +#define VXC_HorzMed3(Dest, Src0, Info) VXC_OP2(horz_med3, Dest, Src0, Info) + +#if (VX_VERSION == 2) +#define VXC_BiLinear(Dest, Src0, Src1, Src2, Info) \ + do { \ + int endBin = ((Info) & VXC_END_BIN_BITMASK) >> 8; \ + int roundMode = ((Info) & VXC_ROUNDING_MODE_BITMASK) >> 2; \ + int clamp = ((Info) & VXC_CLAMP_BITMASK) >> 22; \ + int mod1 = VXC_MODIFIER(0, endBin + 1, 0, roundMode, clamp); \ + int4 bitMask = { 0x00000000, 0x00000008, 0x00000010, 0x00000018}; \ + typeof (Dest) bi1; \ + uint4 bi2; \ + int bi3, bi4; \ + VXC_Lerp(bi1, Src0, Src1, (Src2).y, mod1); \ + _viv_asm(PARAM_CHAIN, bi3, bi1.x!, bitMask); \ + _viv_asm(PARAM_CHAIN, bi4, bi3, 8); \ + _viv_asm(INTRINSIC, bi2, OP_bit_extract, bi4); \ + VXC_Lerp(Dest, bi2!, bi2.y!, (Src2).x, Info); \ + } while (0) + +#define VXC_BitReplace(Dest, Src0, Src1, Src2, Info) +#define VXC_IAdd(Dest, Src0, Src1, Src2, Info) +#define VXC_MagPhase(Dest, Src0, Src1, Info) +#define VXC_SelectAdd(Dest, Src0, Src1, U512, Info) VXC_OP1(error, ERROR_SELECTADD_NOT_SUPPORTED) + +#define VXC_Filter_Box(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Guassian(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_SobelX(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_SobelY(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_ScharrX(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_ScharrY(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Max(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Min(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Median(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter(Dest, Src0, Src1, Src2, Info) do { \ + int filter = (((Info) >> 16)&0x0F); \ + if (filter == VXC_FM_BOX) { VXC_Filter_Box(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Guassian) { VXC_Filter_Guassian(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_SobelX) { VXC_Filter_SobelX(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_SobelY) { VXC_Filter_SobelY(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_ScharrX) { VXC_Filter_ScharrX(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_ScharrY) { VXC_Filter_ScharrY(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Max) { VXC_Filter_Max(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Min) { VXC_Filter_Min(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Median) { VXC_Filter_Median(Dest, Src0, Src1, Src2, Info); } \ + } while (0) + +#else + +#define VXC_BiLinear(Dest, Src0, Src1, Src2, Info) VXC_OP4(bi_linear, Dest, Src0, Src1, Src2, Info) +#define VXC_BitReplace(Dest, Src0, Src1, Src2, Info) VXC_OP4(bit_replace, Dest, Src0, Src1, Src2, Info) +#define VXC_IAdd(Dest, Src0, Src1, Src2, Info) VXC_OP4(iadd, Dest, Src0, Src1, Src2, Info) +#define VXC_MagPhase(Dest, Src0, Src1, Info) VXC_OP3(mag_phase, Dest, Src0, Src1, Info) +#define VXC_SelectAdd(Dest, Src0, Src1, U512, Info) VXC_OP4(select_add, Dest, Src0, Src1, U512, Info) +#define VXC_Filter(Dest, Src0, Src1, Src2, Info) VXC_OP4(filter, Dest, Src0, Src1, Src2, Info) +#endif + +#else + +#ifdef __cplusplus +extern "c" { +#endif + +#define viv_vx_api_only 0 + +#if viv_vx_api_only +#define _RET0_ ; +#define _RET_ ; +#define _EXT_ extern +#else +#define _RET0_ { return (0); } +#define _RET_ { return ; } +#define _EXT_ +#endif + + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_char16 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_char8 a) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_short8 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_short4 a) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_ushort8 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_half8 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_half4 a) _RET0_ + + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_uchar16 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_short8 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_short4 a) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_ushort8 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_half8 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_half4 a) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_uchar16 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_char16 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_char8 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_short8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_short4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_half8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_half4 a) _RET0_ + + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_uchar16 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_char16 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_char8 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_ushort8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_half8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_half4 a) _RET0_ + + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_uchar16 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_char16 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_char8 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_ushort8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_short8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_short4 a) _RET0_ + + + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastD_uc(vxc_char16 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_char8 a) _RET0_ + +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_short8 a) _RET0_ +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_short4 a) _RET0_ + +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_ushort8 a) _RET0_ +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_half8 a) _RET0_ +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_half4 a) _RET0_ + +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_int4 a) _RET0_ +_EXT_ vxc_uchar2 viv_intrinsic_vx_icastD_uc(vxc_int2 a) _RET0_ + +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_uint4 a) _RET0_ +_EXT_ vxc_uchar2 viv_intrinsic_vx_icastD_uc(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_char16 viv_intrinsic_vx_icastD_c(vxc_uchar16 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_short8 a) _RET0_ +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_short4 a) _RET0_ + +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_ushort8 a) _RET0_ +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_half8 a) _RET0_ +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_half4 a) _RET0_ + +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_int4 a) _RET0_ +_EXT_ vxc_char2 viv_intrinsic_vx_icastD_c(vxc_int2 a) _RET0_ + +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_uint4 a) _RET0_ +_EXT_ vxc_char2 viv_intrinsic_vx_icastD_c(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_uchar8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_uchar4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_char8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_char4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_short8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_short4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_half8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_half4 a) _RET0_ + +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_int4 a) _RET0_ +_EXT_ vxc_ushort2 viv_intrinsic_vx_icastD_us(vxc_int2 a) _RET0_ + +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_uint4 a) _RET0_ +_EXT_ vxc_ushort2 viv_intrinsic_vx_icastD_us(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_uchar8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_uchar4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_char8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_char4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_ushort8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_half8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_half4 a) _RET0_ + +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_int4 a) _RET0_ +_EXT_ vxc_short2 viv_intrinsic_vx_icastD_s(vxc_int2 a) _RET0_ + +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_uint4 a) _RET0_ +_EXT_ vxc_short2 viv_intrinsic_vx_icastD_s(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_uchar8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_uchar4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_char8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_char4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_ushort8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_short8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_short4 a) _RET0_ + +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_int4 a) _RET0_ +_EXT_ vxc_half2 viv_intrinsic_vx_icastD_h(vxc_int2 a) _RET0_ + +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_uint4 a) _RET0_ +_EXT_ vxc_half2 viv_intrinsic_vx_icastD_h(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_char4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_uchar4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_short4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_ushort4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_half4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_uint4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_float4 a) _RET0_ + +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_char2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_uchar2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_short2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_ushort2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_half2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_uint2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_float2 a) _RET0_ + + +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_char4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_uchar4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_short4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_ushort4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_half4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_int4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_float4 a) _RET0_ + +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_char2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_uchar2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_short2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_ushort2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_half2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_int2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_float2 a) _RET0_ + + +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_char4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_uchar4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_short4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_ushort4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_half4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_int4 a) _RET0_ + +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_char2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_uchar2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_short2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_ushort2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_half2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_int2 a) _RET0_ + + + +#define VXC_SWIZZLE_MASK8_ALL() 0xFFFF +#define VXC_SWIZZLE_MASK8(E0, E1, E2, E3, E4, E5, E6, E7) \ + (((E0) * 0x3) | ((E1) * (0x3 << 2)) | ((E2) * (0x3 << 4)) | \ + ((E3) * (0x3 << 6)) | ((E4) * (0x3 << 8)) | ((E5) * (0x3 << 10)) | \ + ((E6) * (0x3 << 12)) | ((E7) * (0x3 << 14)) ) + +#define VXC_SWIZZLE_MASK16_ALL() 0xFFFF +#define VXC_SWIZZLE_MASK16(E0, E1, E2, E3, E4, E5, E6, E7, E9, E10, E11, E12, E13, E14, E15) \ + (((E0) * 0x1) | ((E1) * (0x1 << 1)) | ((E2) * (0x1 << 2)) | \ + ((E3) * (0x1 << 1)) | ((E4) * (0x1 << 4)) | ((E5) * (0x1 << 5)) | \ + ((E6) * (0x1 << 6)) | ((E7) * (0x1 << 7)) | ((E8) * (0x1 << 8)) | \ + ((E9) * (0x1 << 9)) | ((E10) * (0x1 << 10)) | ((E11) * (0x1 << 11)) | \ + ((E12) * (0x1 << 12)) | ((E13) * (0x1 << 13)) | ((E14) * (0x1 << 14)) | \ + ((E15) * (0x1 << 15)) ) + +#define VXC_SWIZZLE8(S0, S1, S2, S3, S4, S5, S6, S7) \ + (uint)((S0) << 0 | (S1) << 4 | (S2) << 8 | (S3) << 12 | \ + (S4) << 16 | (S5) << 20 | (S6) << 24 | (S7) << 28 ) + + +_EXT_ vxc_char16 viv_intrinsic_vx_read_imagec (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_read_imageuc (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_read_images (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_read_imageus (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vx_read_imageh (image2d_t image, int2 coord) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_read_imagec (image1d_t image, int coord) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_read_imageuc (image1d_t image, int coord) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_read_images (image1d_t image, int coord) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_read_imageus (image1d_t image, int coord) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vx_read_imageh (image1d_t image, int coord) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_read_imagec (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_read_imageuc (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_read_images (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_read_imageus (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vx_read_imageh (image1d_array_t image, int2 coord) _RET0_ + + +_EXT_ void viv_intrinsic_vx_write_imagec (image2d_t image, int2 coord, vxc_char16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageuc (image2d_t image, int2 coord, vxc_uchar16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_images (image2d_t image, int2 coord, vxc_short8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageus (image2d_t image, int2 coord, vxc_ushort8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageh (image2d_t image, int2 coord, vxc_half8 color) _RET_ + +_EXT_ void viv_intrinsic_vx_write_imagec (image1d_t image, int coord, vxc_char16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageuc (image1d_t image, int coord, vxc_uchar16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_images (image1d_t image, int coord, vxc_short8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageus (image1d_t image, int coord, vxc_ushort8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageh (image1d_t image, int coord, vxc_half8 color) _RET_ + +_EXT_ void viv_intrinsic_vx_write_imagec (image1d_array_t image, int2 coord, vxc_char16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageuc (image1d_array_t image, int2 coord, vxc_uchar16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_images (image1d_array_t image, int2 coord, vxc_short8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageus (image1d_array_t image, int2 coord, vxc_ushort8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageh (image1d_array_t image, int2 coord, vxc_half8 color) _RET_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_AbsDiff_uc(vxc_uchar16 a, vxc_uchar16 b) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_AbsDiff_c(vxc_char16 a, vxc_char16 b) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_AbsDiff_s(vxc_short8 a, vxc_short8 b) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_AbsDiff_us(vxc_ushort8 a, vxc_ushort8 b) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_IAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_IAdd_c(vxc_char16 a, vxc_char16 b, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_IAdd_s(vxc_short8 a, vxc_short8 b, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_IAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_IAccSq_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_IAccSq_c(vxc_char16 a, vxc_char16 b, uint Imm) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_IAccSq_s(vxc_short8 a, vxc_short8 b, uint Imm) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_IAccSq_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_Lerp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_float c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_Lerp_c(vxc_char16 a, vxc_char16 b, vxc_float c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_Lerp_s(vxc_short8 a, vxc_short8 b, vxc_float c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_Lerp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_float c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_Filter_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_filter_mode f) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_Filter_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_filter_mode f) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_Filter_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_filter_mode f) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_Filter_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_filter_mode f) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_MagPhase_uc(vxc_uchar16 a, vxc_uchar16 b) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_MagPhase_c(vxc_char16 a, vxc_char16 b) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_MagPhase_s(vxc_short8 a, vxc_short8 b) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_MagPhase_us(vxc_ushort8 a, vxc_ushort8 b) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_MulShift_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_MulShift_c(vxc_char16 a, vxc_char16 b, uint Imm) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_MulShift_s(vxc_short8 a, vxc_short8 b, uint Imm) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_MulShift_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm) _RET0_ + +/* Clamp: clamps up to 16 values to a min and.or max value + * + * Syntax: + * r = Clamp(a, b, c) ; + * r = ClampBoolean(a, b, c) ; // boolean mode + * Semantics: + * r[i] = clamp(a[i], b[i], c[i]) ; i E [0, elem(r) ) + * + * In boolean mode it will write a 0 in the result if the value + * is inside the specified min/max range, otherwise all 1s will + * be written to the result. + */ +_EXT_ vxc_uchar16 viv_intrinsic_vx_Clamp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_Clamp_c(vxc_char16 a, vxc_char16 b, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_Clamp_s(vxc_short8 a, vxc_short8 b, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_Clamp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_ClampBoolean_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_ClampBoolean_c(vxc_char16 a, vxc_char16 b, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_ClampBoolean_s(vxc_short8 a, vxc_short8 b, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_ClampBoolean_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_BiLinear_uc(vxc_uchar16 a, vxc_uchar16 b, float2 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_BiLinear_c(vxc_char16 a, vxc_char16 b, float2 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_BiLinear_s(vxc_short8 a, vxc_short8 b, float2 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_BiLinear_us(vxc_ushort8 a, vxc_ushort8 b, float2 c) _RET0_ + + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_SelectAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_512bits c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_SelectAdd_c(vxc_char16 a, vxc_char16 b, vxc_512bits c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_SelectAdd_s(vxc_short8 a, vxc_short8 b, vxc_512bits c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_SelectAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_512bits c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_AtomicAdd_uc(vxc_uchar16 * a, vxc_int offset, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_AtomicAdd_c(vxc_char16 * a, vxc_int offset, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_AtomicAdd_s(vxc_short8 * a, vxc_int offset, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_AtomicAdd_us(vxc_ushort8 * a, vxc_int offset, vxc_ushort8 c) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_BitExtract_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_BitExtract_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_BitReplace_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_BitReplace_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ + + + + + + +_EXT_ vxc_char16 viv_intrinsic_vxmc_read_imagec (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_read_imageuc (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_read_images (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_read_imageus (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_read_imageh (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vxmc_read_imagec (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_read_imageuc (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_read_images (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_read_imageus (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_read_imageh (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vxmc_read_imagec (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_read_imageuc (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_read_images (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_read_imageus (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_read_imageh (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ + + +_EXT_ void viv_intrinsic_vxmc_write_imagec (image2d_t image, int2 coord, vxc_char16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageuc (image2d_t image, int2 coord, vxc_uchar16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_images (image2d_t image, int2 coord, vxc_short8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageus (image2d_t image, int2 coord, vxc_ushort8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageh (image2d_t image, int2 coord, vxc_half8 color, vxc_modifier modifier) _RET_ + +_EXT_ void viv_intrinsic_vxmc_write_imagec (image1d_t image, int coord, vxc_char16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageuc (image1d_t image, int coord, vxc_uchar16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_images (image1d_t image, int coord, vxc_short8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageus (image1d_t image, int coord, vxc_ushort8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageh (image1d_t image, int coord, vxc_half8 color, vxc_modifier modifier) _RET_ + +_EXT_ void viv_intrinsic_vxmc_write_imagec (image1d_array_t image, int2 coord, vxc_char16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageuc (image1d_array_t image, int2 coord, vxc_uchar16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_images (image1d_array_t image, int2 coord, vxc_short8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageus (image1d_array_t image, int2 coord, vxc_ushort8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageh (image1d_array_t image, int2 coord, vxc_half8 color, vxc_modifier modifier) _RET_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_AbsDiff_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_AbsDiff_c(vxc_char16 a, vxc_char16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_AbsDiff_s(vxc_short8 a, vxc_short8 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_AbsDiff_us(vxc_ushort8 a, vxc_ushort8 b, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_IAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_IAdd_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_IAdd_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_IAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_IAccSq_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_IAccSq_c(vxc_char16 a, vxc_char16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_IAccSq_s(vxc_short8 a, vxc_short8 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_IAccSq_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_Lerp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_float c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_Lerp_c(vxc_char16 a, vxc_char16 b, vxc_float c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_Lerp_s(vxc_short8 a, vxc_short8 b, vxc_float c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_Lerp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_float c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_Filter_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_Filter_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_Filter_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_Filter_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_MagPhase_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_MagPhase_c(vxc_char16 a, vxc_char16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_MagPhase_s(vxc_short8 a, vxc_short8 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_MagPhase_us(vxc_ushort8 a, vxc_ushort8 b, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_MulShift_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_MulShift_c(vxc_char16 a, vxc_char16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_MulShift_s(vxc_short8 a, vxc_short8 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_MulShift_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uint viv_intrinsic_vxmc_DP16x1(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int viv_intrinsic_vxmc_DP16x1(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_float viv_intrinsic_vxmc_DP16x1(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint2 viv_intrinsic_vxmc_DP8x2(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vxmc_DP8x2(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vxmc_DP8x2(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint4 viv_intrinsic_vxmc_DP4x4(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vxmc_DP4x4(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vxmc_DP4x4(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uchar8 viv_intrinsic_vxmc_DP2x8(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vxmc_DP2x8(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_DP2x8(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint viv_intrinsic_vxmc_DP32x1(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int viv_intrinsic_vxmc_DP32x1(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint2 viv_intrinsic_vxmc_DP16x2(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vxmc_DP16x2(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint4 viv_intrinsic_vxmc_DP8x4(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vxmc_DP8x4(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_DP4x8(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_DP4x8(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_DP2x16(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_DP2x16(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint viv_intrinsic_vxmc_DP32x1_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int viv_intrinsic_vxmc_DP32x1_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint2 viv_intrinsic_vxmc_DP16x2_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vxmc_DP16x2_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint4 viv_intrinsic_vxmc_DP8x4_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vxmc_DP8x4_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_DP4x8_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_DP4x8_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_DP2x16_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_DP2x16_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_Clamp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_Clamp_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_Clamp_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_Clamp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_BiLinear_uc(vxc_uchar16 a, vxc_uchar16 b, float2 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_BiLinear_c(vxc_char16 a, vxc_char16 b, float2 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_BiLinear_s(vxc_short8 a, vxc_short8 b, float2 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_BiLinear_us(vxc_ushort8 a, vxc_ushort8 b, float2 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_SelectAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_512bits c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_SelectAdd_c(vxc_char16 a, vxc_char16 b, vxc_512bits c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_SelectAdd_s(vxc_short8 a, vxc_short8 b, vxc_512bits c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_SelectAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_512bits c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_AtomicAdd_uc(vxc_uchar16 * a, vxc_int offset, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_AtomicAdd_c(vxc_char16 * a, vxc_int offset, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_AtomicAdd_s(vxc_short8 * a, vxc_int offset, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_AtomicAdd_us(vxc_ushort8 * a, vxc_int offset, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_BitExtract_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vxmc_BitExtract_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_BitReplace_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_BitReplace_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ + + +vxc_char2 viv_intrinsic_vx_vload2(size_t Offset, char *Pointer) { + vxc_char2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_char2)); + return dest; +} + +vxc_char4 viv_intrinsic_vx_vload4(size_t Offset, char *Pointer) { + vxc_char4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_char4)); + return dest; +} + +vxc_char8 viv_intrinsic_vx_vload8(size_t Offset, char *Pointer) { + vxc_char8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_char8)); + return dest; +} + +vxc_char16 viv_intrinsic_vx_vload16(size_t Offset, char *Pointer) { + vxc_char16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_char16)); + return dest; +} + +vxc_uchar2 viv_intrinsic_vx_vload2(size_t Offset, uchar *Pointer) { + vxc_uchar2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_uchar2)); + return dest; +} + +vxc_uchar4 viv_intrinsic_vx_vload4(size_t Offset, uchar *Pointer) { + vxc_uchar4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_uchar4)); + return dest; +} + +vxc_uchar8 viv_intrinsic_vx_vload8(size_t Offset, uchar *Pointer) { + vxc_uchar8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_uchar8)); + return dest; +} + +vxc_uchar16 viv_intrinsic_vx_vload16(size_t Offset, uchar *Pointer) { + vxc_uchar16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_uchar16)); + return dest; +} + +vxc_short2 viv_intrinsic_vx_vload2(size_t Offset, short *Pointer) { + vxc_short2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_short2)); + return dest; +} + +vxc_short4 viv_intrinsic_vx_vload4(size_t Offset, short *Pointer) { + vxc_short4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_short4)); + return dest; +} + +vxc_short8 viv_intrinsic_vx_vload8(size_t Offset, short *Pointer) { + vxc_short8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_short8)); + return dest; +} + +vxc_short16 viv_intrinsic_vx_vload16(size_t Offset, short *Pointer) { + vxc_short16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_short16)); + return dest; +} + +vxc_ushort2 viv_intrinsic_vx_vload2(size_t Offset, ushort *Pointer) { + vxc_ushort2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_ushort2)); + return dest; +} + +vxc_ushort4 viv_intrinsic_vx_vload4(size_t Offset, ushort *Pointer) { + vxc_ushort4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_ushort4)); + return dest; +} + +vxc_ushort8 viv_intrinsic_vx_vload8(size_t Offset, ushort *Pointer) { + vxc_ushort8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_ushort8)); + return dest; +} + +vxc_ushort16 viv_intrinsic_vx_vload16(size_t Offset, ushort *Pointer) { + vxc_ushort16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_ushort16)); + return dest; +} + +vxc_half2 viv_intrinsic_vx_vload2(size_t Offset, half *Pointer) { + vxc_half2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_half2)); + return dest; +} + +vxc_half4 viv_intrinsic_vx_vload4(size_t Offset, half *Pointer) { + vxc_half4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_half4)); + return dest; +} + +vxc_half8 viv_intrinsic_vx_vload8(size_t Offset, half *Pointer) { + vxc_half8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_half8)); + return dest; +} + +vxc_half16 viv_intrinsic_vx_vload16(size_t Offset, half *Pointer) { + vxc_half16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_half16)); + return dest; +} + + +void viv_intrinsic_vx_vstore2(vxc_char2 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_char2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_char4 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_char4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_char8 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_char8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_char16 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_char16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_uchar2 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_uchar2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_uchar4 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_uchar4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_uchar8 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_uchar8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_uchar16 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_uchar16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_short2 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_short2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_short4 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_short4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_short8 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_short8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_short16 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_short16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_ushort2 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_ushort2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_ushort4 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_ushort4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_ushort8 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_ushort8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_ushort16 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_ushort16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_half2 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_half2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_half4 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_half4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_half8 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_half8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_half16 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_half16), Data); +} + +#undef _RET0_ +#undef _RET_ +#undef _EXT_ + +#ifdef __cplusplus +} +#endif + +#endif +typedef struct +{ + size_t size; + global char* item; +} vx_array_char; + +typedef struct +{ + size_t size; + global unsigned char* item; +} vx_array_uchar; + +typedef struct +{ + size_t size; + global short* item; +} vx_array_short; + +typedef struct +{ + size_t size; + global unsigned short* item; +} vx_array_ushort; + +typedef struct +{ + size_t size; + global int* item; +} vx_array_int; + +typedef struct +{ + size_t size; + global unsigned int* item; +} vx_array_uint; + + +typedef struct +{ + size_t size; + global float * item; +} vx_array_float; + +typedef struct +{ + size_t size; + global unsigned char* item; +} vx_lut_uchar; + +typedef struct +{ + size_t size; + global unsigned short* item; +} vx_lut_ushort; + +typedef struct +{ + size_t columns; + size_t rows; + global short* matrix; + uint scale; +} vx_convolution; + +typedef struct +{ + size_t columns; + size_t rows; + global char* matrix; +} vx_matrix_char; + +typedef struct +{ + size_t columns; + size_t rows; + global unsigned char* matrix; +} vx_matrix_uchar; + +typedef struct +{ + size_t columns; + size_t rows; + global short* matrix; +} vx_matrix_short; + +typedef struct +{ + size_t columns; + size_t rows; + global unsigned short* matrix; +} vx_matrix_ushort; + +typedef struct +{ + size_t columns; + size_t rows; + global int* matrix; +} vx_matrix_int; + +typedef struct +{ + size_t columns; + size_t rows; + global unsigned int* matrix; +} vx_matrix_uint; + +typedef struct +{ + size_t columns; + size_t rows; + global float* matrix; +} vx_matrix_float; + +typedef struct +{ + int type; + uint value; + uint lower; + uint upper; + uint trueValue; + uint falseValue; +} vx_threshold; + +typedef struct { + int dst_width; + int dst_height; + global float* ptr; +} vx_remap; + +typedef struct +{ + int bins; + int rang; + int offset; + float window_r; + global int* ptr; +} vx_distribution; + +typedef struct _vxc_pyramid +{ + float scale; + uint width; + uint height; + uint format; + uint levelCount; + _viv_image2d_array_t imageArray; +} vxc_pyramid; + +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..c26c2bc Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libGAL.so new file mode 100644 index 0000000..4c5fdaa Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..816a76e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..687ebe9 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..8a1185c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libVSC_Lite.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libVSC_Lite.so new file mode 100644 index 0000000..22d0cc3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/libVSC_Lite.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..1264ce3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64-mini/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/bin/rknn_server b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/bin/rknn_server new file mode 100644 index 0000000..fb5ab85 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/bin/rknn_server differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..c26c2bc Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libCLC.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libCLC.so new file mode 100644 index 0000000..100c901 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libCLC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libGAL.so new file mode 100644 index 0000000..87da367 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..816a76e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNGPUBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNGPUBinary.so new file mode 100644 index 0000000..8987d4d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNGPUBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNVXCBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNVXCBinary.so new file mode 100644 index 0000000..0793f10 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libNNVXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenCL.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenCL.so.1.2 new file mode 100644 index 0000000..94ce057 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenCL.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..23f5ae6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..8a1185c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOvx12VXCBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOvx12VXCBinary.so new file mode 100644 index 0000000..fbdc57d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libOvx12VXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libVSC.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libVSC.so new file mode 100644 index 0000000..ed6e52a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libVSC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libneuralnetworks.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libneuralnetworks.so new file mode 100644 index 0000000..ea9768d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/libneuralnetworks.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..a207e3f Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/memory_profile b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/memory_profile new file mode 100644 index 0000000..c8d125b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/memory_profile differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/libann_plugin.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/libann_plugin.so new file mode 100644 index 0000000..269d25a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/libann_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/librknn_plugin.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/librknn_plugin.so new file mode 100644 index 0000000..27977c6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/librknn_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libGAL.so new file mode 100644 index 0000000..fe54bb2 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..d3e8586 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..ccae677 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libVSC_Lite.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libVSC_Lite.so new file mode 100644 index 0000000..041deca Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/libVSC_Lite.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..b2c409b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-mini/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libGAL.so new file mode 100644 index 0000000..669fadd Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..44c4399 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..40c62f4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libVSC_Lite.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libVSC_Lite.so new file mode 100644 index 0000000..041deca Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/libVSC_Lite.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..f2c5c5f Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma-mini/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/bin/rknn_server b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/bin/rknn_server new file mode 100644 index 0000000..1ff3313 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/bin/rknn_server differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libCLC.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libCLC.so new file mode 100644 index 0000000..642b34b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libCLC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libGAL.so new file mode 100644 index 0000000..7f5902c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNGPUBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNGPUBinary.so new file mode 100644 index 0000000..c43c374 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNGPUBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNVXCBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNVXCBinary.so new file mode 100644 index 0000000..2e20033 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libNNVXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenCL.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenCL.so.1.2 new file mode 100644 index 0000000..e6c22e1 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenCL.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..cb0ef11 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..40c62f4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOvx12VXCBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOvx12VXCBinary.so new file mode 100644 index 0000000..ffb6711 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libOvx12VXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libVSC.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libVSC.so new file mode 100644 index 0000000..639013d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libVSC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libneuralnetworks.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libneuralnetworks.so new file mode 100644 index 0000000..4afe4f3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/libneuralnetworks.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..3576099 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/memory_profile b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/memory_profile new file mode 100644 index 0000000..542fae6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/memory_profile differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/libann_plugin.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/libann_plugin.so new file mode 100644 index 0000000..da693e0 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/libann_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/librknn_plugin.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/librknn_plugin.so new file mode 100644 index 0000000..8d675de Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/librknn_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/bin/rknn_server b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/bin/rknn_server new file mode 100644 index 0000000..3731a46 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/bin/rknn_server differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libCLC.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libCLC.so new file mode 100644 index 0000000..642b34b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libCLC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libGAL.so new file mode 100644 index 0000000..109e22a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNGPUBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNGPUBinary.so new file mode 100644 index 0000000..609e6a2 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNGPUBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNVXCBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNVXCBinary.so new file mode 100644 index 0000000..f7c1460 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libNNVXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenCL.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenCL.so.1.2 new file mode 100644 index 0000000..73e5bfe Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenCL.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..e896ca1 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..ccae677 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOvx12VXCBinary.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOvx12VXCBinary.so new file mode 100644 index 0000000..ac8f547 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libOvx12VXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libVSC.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libVSC.so new file mode 100644 index 0000000..639013d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libVSC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libneuralnetworks.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libneuralnetworks.so new file mode 100644 index 0000000..2266108 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/libneuralnetworks.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..a70f988 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/memory_profile b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/memory_profile new file mode 100644 index 0000000..04dce87 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/memory_profile differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/plugins/libann_plugin.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/plugins/libann_plugin.so new file mode 100644 index 0000000..a3f8ba4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/plugins/libann_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/plugins/librknn_plugin.so b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/plugins/librknn_plugin.so new file mode 100644 index 0000000..b1f81ec Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/linux-armhf/usr/lib/npu/rknn/plugins/librknn_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore.ko new file mode 100644 index 0000000..8ebbbaa Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_fedora.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_fedora.ko new file mode 100644 index 0000000..1a51915 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_fedora.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_puma.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_puma.ko new file mode 100644 index 0000000..4644e82 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_puma.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_puma_tb.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_puma_tb.ko new file mode 100644 index 0000000..1bebce6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_puma_tb.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk1806.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk1806.ko new file mode 100644 index 0000000..f69273f Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk1806.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk3399pro-npu-pcie.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk3399pro-npu-pcie.ko new file mode 100644 index 0000000..3c69e5e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk3399pro-npu-pcie.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk3399pro-npu.ko b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk3399pro-npu.ko new file mode 100644 index 0000000..f694c17 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/drivers/npu_ko/galcore_rk3399pro-npu.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_CN.pdf b/rknn_yolo_demo/libs/rklibs/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_CN.pdf new file mode 100644 index 0000000..9e80b4b --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_CN.pdf @@ -0,0 +1,1290 @@ + 瑞芯微电子股份有限公司 + +密级状态:绝密( ) 秘密( ) 内部( ) 公开(√ ) + +Rockchip User Guide RKNN API + + (技术部,图形计算平台中心) + +文件状态: 当前版本: 1.7.3 + HPC +[ ] 正在修改 作 者: 2022-8-13 + 熊伟 +[√] 正式发布 完成日期: 2022-8-13 + + 审 核: + + 完成日期: + + 瑞芯微电子股份有限公司 + Rockchips Semiconductor Co . , Ltd + + (版本所有,翻版必究) + 瑞芯微电子股份有限公司 + + 更新记录 + + 版本 修改人 修改日期 修改说明 核定人 +v0.9.6 杨华聪 +V0.9.7 杨华聪 2018-12-20 初始版本 熊伟 +V0.9.8 杨华聪 熊伟 + 2019-01-16 1) 添加 RKNN SDK 开发流程说明 卓鸿添 +V1.3.3 卓鸿添 2019-06-05 2) 添加 RKNN Python API 说明 卓鸿添 +V1.4.0 卓鸿添 2020-06-02 1) 添加 RKNN API 库的说明 卓鸿添 + 2) 更新 rknn example 和 rknn-toolkit 路 +v1.6.0 洪启飞 卓鸿添 + 径 +v1.6.1 洪启飞 3) 修正文档中错误 卓鸿添 +v1.7.0 洪启飞 1)支持 RV1126/RV1109 +v1.7.1 洪启飞 2)删除 python 支持说明,关于 python +v1.7.3 洪启飞 支持见 RKNN Toolkit Lite 相关文档。 + + 2020-09-10 1)增加错误码 + + 2021-1-15 1)增加 Matmul 高级 API 说明 + 2)增加一组设置输入和一组获取输出 + 的接口 + 3)增加做量化和反量化的算法说明 + 4)增加 NPU 驱动说明 + 5)增加 FAQ + + 2021-4-26 1)更新 Matmul 高级 API 说明 + + 2021-8-5 1)更新版本号 卓鸿添 + 2021-12-2 1)rknn_inputs_set 接口单通道输入性能 卓鸿添 + 2022-8-13 优化 卓鸿添 + 2)已知 Bug 修复 + 1)更新版本号 + + 1 + 瑞芯微电子股份有限公司 + +1 主要功能说明 ................................................................................................................................................... 5 +2 硬件平台 ........................................................................................................................................................... 5 +3 使用说明 ........................................................................................................................................................... 5 + + 3.1 RKNN SDK 开发流程 ............................................................................................................................... 5 + 3.2 RKNN C API ...............................................................................................................................................6 + + 3.2.1 RKNN API 库 ...................................................................................................................................... 6 + 3.2.2 EXAMPLE 使用说明 ..........................................................................................................................6 + 3.2.3 API 流程说明 ...................................................................................................................................... 7 + + 3.2.3.1 API 内部处理流程 ..........................................................................................................................................9 + 3.2.3.2 量化和反量化 ..............................................................................................................................................10 + 3.2.3.3 零拷贝 .......................................................................................................................................................... 11 + 3.2.4 API 详细说明 .................................................................................................................................... 12 + 3.2.4.1 rknn_init ........................................................................................................................................................ 12 + 3.2.4.2 rknn_destroy ..................................................................................................................................................13 + 3.2.4.3 rknn_query .................................................................................................................................................... 13 + 3.2.4.4 rknn_inputs_set ............................................................................................................................................. 16 + 3.2.4.5 rknn_inputs_map ...........................................................................................................................................16 + 3.2.4.6 rknn_inputs_sync ...........................................................................................................................................18 + 3.2.4.7 rknn_inputs_unmap .......................................................................................................................................18 + 3.2.4.8 rknn_run ........................................................................................................................................................ 19 + 3.2.4.9 rknn_outputs_get ...........................................................................................................................................19 + 3.2.4.10 rknn_outputs_release .................................................................................................................................. 20 + 3.2.4.11 rknn_outputs_map ....................................................................................................................................... 21 + 3.2.4.12 rknn_outputs_sync .......................................................................................................................................21 + + 2 + 瑞芯微电子股份有限公司 + 3.2.4.13 rknn_outputs_unmap ...................................................................................................................................22 + 3.2.5 RKNN 数据结构定义 ....................................................................................................................... 22 + 3.2.5.1 rknn_input_output_num ................................................................................................................................ 22 + 3.2.5.2 rknn_tensor_attr ............................................................................................................................................23 + 3.2.5.3 rknn_input ..................................................................................................................................................... 24 + 3.2.5.4 rknn_tensor_mem ..........................................................................................................................................24 + 3.2.5.5 rknn_output ................................................................................................................................................... 25 + 3.2.5.6 rknn_perf_detail ............................................................................................................................................ 25 + 3.2.5.7 rknn_sdk_version .......................................................................................................................................... 25 + 3.2.6 RKNN 返回值错误码 ....................................................................................................................... 26 +4 高级 API 使用说明 ........................................................................................................................................ 27 + 4.1 MATMUL 算子库 ........................................................................................................................................27 + 4.1.1 简介 ...................................................................................................................................................27 + 4.1.2 数据结构定义 ...................................................................................................................................27 + 4.1.3 详细 API 说明 .................................................................................................................................. 28 + 4.1.3.1 rknn_matmul_load ........................................................................................................................................ 28 + 4.1.3.2 rknn_matmul_run ..........................................................................................................................................28 + 4.1.3.3 rknn_matmul_unload .................................................................................................................................... 29 + 4.1.4 实现限制 ...........................................................................................................................................29 + 4.1.4.1 维度限制 ......................................................................................................................................................29 + 4.1.4.2 输入数据类型限制 ......................................................................................................................................30 + 4.1.5 基准测试 ...........................................................................................................................................30 +5 NPU 驱动说明 .................................................................................................................................................31 + 5.1.1 NPU 驱动目录说明 ...........................................................................................................................31 + 5.1.2 NPU full driver 与 mini driver 的区别 ..............................................................................................31 + + 3 + 瑞芯微电子股份有限公司 +6 FAQ ..................................................................................................................................................................32 + + 6.1.1 输入输出数据格式问题 ...................................................................................................................32 + 6.1.2 输入输出接口使用问题 ...................................................................................................................33 + 6.1.3 API 调用流程问题 ............................................................................................................................ 33 + 6.1.4 性能问题 ...........................................................................................................................................34 + + 4 + 瑞芯微电子股份有限公司 + +1 主要功能说明 + + RKNN SDK 为 RK1808 等 带 有 NPU 的 平 台 提 供 编 程 接 口 , 能 够 帮 助 用 户 部 署 使 用 +RKNN-Toolkit 导出的 RKNN 模型,加速 AI 应用的落地。 + +2 硬件平台 + +本文档适用如下硬件平台: + 1) RK1808、RK1806 + 2) RV1126、RV1109 + +注意:本文档不适用 RK3399Pro +下面的说明以 RK1808 为例,也同时适用上述其他平台。 + +3 使用说明 + +3.1 RKNN SDK 开发流程 + + 在使用 RKNN SDK 之前,用户首先需要使用 RKNN-Toolkit 工具将用户的模型转换为 RKNN + +模型,用户可以在 https://github.com/rockchip-linux/rknn-toolkit 获取工具的完整 + +安装包及使用文档。 + 成功转换生成 RKNN 模型之后,用户可以先通过 RKNN-Toolkit 连接 RK1808 等开发板进行联 + +机调试,确保模型的精度性能符合要求。 + 得到 RKNN 模型文件之后,用户可以选择使用 C 或 Python 接口在 RK1808 等平台开发应用, + +后续章节将说明如何在 RK1808 等平台上基于 RKNN SDK 进行开发。 + + 5 + 瑞芯微电子股份有限公司 + +3.2 RKNN C API + +3.2.1 RKNN API 库 + + RKNN SDK 所提供的库和头文件位于/external/rknpu/rknn/ +rknn_api/librknn_api 目录下,开发者可以在自己应用中引用即可开发应用。 + + 需要注意的是,RK1808 和 RK3399Pro 平台的 RKNN API 是兼容的,两者开发的应用程序 +可以很方便地移植。但是使用过程中需要注意要区分两个平台的 librknn_api.so,如果开发者使 +用 RK3399Pro 的 librknn_api.so 将无法在 RK1808 平台上运行。开发者可以使用以下方法来区分 +librknn_api.so 的平台: + + $ strings librknn_api.so |grep version + librknn_api version 1.7.3 (cf7f05f build: 2022-08-13 10:59:33) + +3.2.2 EXAMPLE 使用说明 + + SDK 提供了 Linux 平台的 MobileNet 图像分类、MobileNet SSD 目标检测以及 YoloV3 Tiny + 目标检测 Demo。这些 Demo 能够为客户基于 RKNN SDK 开发自己的 AI 应用提供参考。Demo + 代码位于/external/rknpu/rknn/rknn_api/examples 目录。下面以 rknn_mobilenet_demo 为例 + 来讲解如何快速上手运行。 + + 1) 编译 Demo + + cd examples/rknn_mobilenet_demo + # 修改 build.sh 中的 GCC_COMPILER,指向目标平台的编译器 + ./build.sh + 2) 部署到 RK1808 设备 + + adb push install/rknn_mobilenet_demo /userdata/ + + 3) 运行 Demo + + 6 + 瑞芯微电子股份有限公司 + + adb shell + cd /userdata/rknn_mobilenet_demo/ + ./rknn_mobilenet_demo model/mobilenet_v1_rk180x.rknn + model/dog_224x224.jpg #for RK1808 + ./rknn_mobilenet_demo model/mobilenet_v1_rv1109_rv1126.rknn + model/dog_224x224.jpg #for RV1109/RV1126 + +3.2.3 API 流程说明 + + 从 RKNN API V1.6.0 版本开始,新增加了一组设置输入的函数: +  rknn_inputs_map +  rknn_inputs_sync +  rknn_inputs_unmap + 以及一组获取输出的函数: +  rknn_outputs_map +  rknn_outputs_sync +  rknn_outputs_unmap + 在设置输入时,用户可以使用 rknn_inputs_set 或者 rknn_inputs_map 系列函数。获取推理 + 的输出时,使用 rknn_outputs_get 或者 rknn_outputs_map 系列函数。特定场景下,使用 map 系 + 列接口可以减少内存拷贝的次数,提高完整推理的速度。 + rknn_inputs_map 系列接口和 rknn_inputs_set 接口的调用流程不同,rknn_outputs_map 系 + 列接口和 rknn_outputs_get 接口的调用流程也不同。两个系列 API 调用流程差异如图 3-1 所示, + 其中(a)为 set/get 系列接口调用流程,(b)为 map 系列接口调用流程。 + + 7 + 瑞芯微电子股份有限公司 + + 图 3-1 使用 set/get 系列(a)和 map 系列(b)接口流程差异 + 设置输入和获取输出接口没有绑定关系,因此可以混合使用 set/get 系列接口和 map 系列 +接口。如图 3-2(c),用户可以使用 rknn_inputs_map 系列接口设置输入,再通过 rknn_outputs_get +接 口 获 取 输 出 , 或 者 如 图 3-2 ( d ) 通 过 rknn_inputs_set 系 列 接 口 设 置 输 入 , 再 使 用 +rknn_outputs_map 接口获取输出。 + + 8 + 瑞芯微电子股份有限公司 + + 图 3-2 混合使用 set/get 系列和 map 系列接口的调用流程 +3.2.3.1 API 内部处理流程 + + 在推理 RKNN 模型时,原始数据要经过输入处理、NPU 运行模型、输出处理三大流程。 + 在典型的图片推理场景中,假设输入数据 data 是 3 通道的图片且为 NHWC 排布格式,运行时 + (Runtime)对数据处 理的流程如图 3-3 所示。在 API 层面上,rknn_inputs_set 接口(当 + pass_through=0 时,详见 rknn_input 结构体)包含了颜色通道交换、归一化、量化、NHWC 转 + 换成 NCHW 的过程,rknn_outputs_get 接口(当 want_float=1 时,详见 rknn_output 结构体) + + 9 + 瑞芯微电子股份有限公司 + +包含了反量化的过程。 + + 图 3-3 完整的图片数据处理流程 + 实际上,对于某些 RKNN 模型,输入处理的流程没有全部执行,例如,当输入数据不是 + 3 通道图像时或者用 rknn-toolkit 导出模型的 config 函数配置为 reorder=”0 1 2”时,没有颜色通 + 道转换流程。当 RKNN 模型输入 tensor 的属性是 NHWC 布局时,没有 NHWC 转换成 NCHW + 的流程。rknn_inputs_se(t 当 pass_through=1 时)和 rknn_inputs_map 不包含任何输入处理流程, + rknn_outputs_get(当 want_float=0 时)和 rknn_outputs_map 不包含任何输出处理流程。此时, + 虽然两组 API 都不包含对应的处理流程,不过,使用 set/get 系列接口会比 map 系列接口多出 + 数据拷贝过程。 + +3.2.3.2 量化和反量化 + + 当使用 rknn_inputs_set(pass_through=1)和 rknn_inputs_map 时,表明在 NPU 推理之前 + 的流程要用户处理。rknn_outputs_map 获取输出后,用户也要做反量化得到 32 位浮点结果。 + + 量化和反量化用到的量化方式、量化数据类型以及量化参数,可以通过 rknn_query 接口 + 查询。目前,RK1808/RK3399Pro/RV1109/RV1126 的 NPU 有非对称量化和动态定点量化两种 + 量化方式,每种量化方式指定相应的量化数据类型。总共有以下四种数据类型和量化方式组 + 合: + +  uint8(非对称量化) +  int8(动态定点) +  int16(动态定点) +  float16(无) + 通常,归一化后的数据用 32 位浮点数保存,32 位浮点转换成 16 位浮点数请参考 IEEE-754 + 标准。假设归一化后的 32 位浮点数据是 D ,下面介绍量化流程: + + 10 + 瑞芯微电子股份有限公司 + +1)float32 转 uint8 +假设输入 tensor 的非对称量化参数是 Sq , ZP ,数据 D 量化过程表示为下式: + + Dq  round (clamp(D / Sq  ZP,0,255)) (3-1) + +上式中,clamp 表示将数值限制在某个范围。round 表示做舍入处理。 +2)float32 转 int8 +假设输入 tensor 的动态定点量化参数是 fl,数据 D 量化过程表示为下式: + + Dq  round (clamp(D * 2 fl ,-128,127)) (3-2) + +3)float32 转 int16 +假设输入 tensor 的动态定点量化参数是 fl,数据 D 量化过程表示为下式: + + Dq  round (clamp(D * 2 fl ,-32768,32767)) (3-3) + +反量化流程是量化的逆过程,可以根据上述量化公式反推出反量化公式,这里不做赘述。 + +3.2.3.3 零拷贝 + + 在特定的条件下,可以把输入数据拷贝次数减少到零,即零拷贝。比如,当 RKNN 模型 +是非对称量化,量化数据类型是 uint8,3 通道的均值是相同的整数同时缩放因子相同的情况 +下,归一化和量化可以省略。证明如下: + +假设输入图像数据是 D f ,量化参数是 Sq , ZP 。 M i 表示第 i 通道的均值, Si 表示第 i + +通道的归一化因子。则第 i 通道归一化后的数据 Di 如下式子: + + Di  (D f  M i ) / Si (3-4) + +数据 Di 量化过程表示为下式: (3-5) + Dq  clamp(Di / Sq  ZP,0,255) + +上述两个式子合并后,可以得出 + + Dq  clamp((D f  Mi ) /(Si * Sq)  ZP) (3-6) +假设量化图片矫正集数据范围包含 0 到 255 的整数值,当 M1  M 2  M 3 ,S1  S2  S3 时, + + 11 + 瑞芯微电子股份有限公司 + +归一化数值范围表示如下: (3-7) + Dmin  (0 - M i ) / Si  M i / Si (3-8) + Dmax  (255 - M i ) / Si + + 因此,量化参数计算如下: + + Sq  (Dmax  Dmin ) / 255  1/Si (3-9) + + ZP  (0  Dmin ) / Sq  M i (3-10) + +把式(3-9)和式(3-10)代入式(3-6),可以得出 D f  Dq ,即符合零拷贝的条件下:3 + +通道的均值是相同的整数同时归一化的缩放因子相同,输入 uint8 数据等于量化后的 uint8 数 +据。 + + 输入零拷贝能降低 CPU 负载,提高整体的推理速度。针对 RGB 或 BGR 输入数据,实现 +输入零拷贝的步骤如下: + + 1)三个通道的均值是相同的整数同时归一化的缩放因子相同。 + 2)在 rknn-toolkit 的 config 函数中,设置 force_builtin_perm=True,导出 NHWC 输入的 +RKNN 模型。 + 3)使用 rknn_inputs_map 接口,获取输入 tensor 内存地址信息。 + 4)往内存地址填充输入数据,比如调用 RGA 缩放函数,目标地址使用 rknn_inputs_map +获取的物理地址。 + 5)调用 rknn_inputs_sync 接口。 + 6)调用 rknn_run 接口。 + 7)调用获取输出接口。 + +3.2.4 API 详细说明 + +3.2.4.1 rknn_init + + rknn_init 初始化函数将创建 rknn_context 对象、加载 RKNN 模型以及根据 flag 执行特定 +的初始化行为。 + + 12 + 瑞芯微电子股份有限公司 + +API rknn_init +功能 初始化 rknn +参数 rknn_context *context:rknn_context 指针。函数调用之后,context 将会被赋值。 + void *model:RKNN 模型的二进制数据。 + uint32_t size:模型大小。 + uint32_t flag:特定的初始化标志。目前 RK1808 平台仅支持以下标志: + + RKNN_FLAG_COLLECT_PERF_MASK:打开性能收集调试开关,打开之后能够通过 + rknn_query 接口查询网络每层运行时间。需要注意,该标志被设置后 rknn_run 的 + 运行时间将会变长。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + rknn_context ctx; + int ret = rknn_init(&ctx, model_data, model_data_size, 0); + +3.2.4.2 rknn_destroy + + rknn_destroy 函数将释放传入的 rknn_context 及其相关资源。 + +API rknn_destroy + +功能 销毁 rknn_context 对象及其相关资源。 + +参数 rknn_context context:要销毁的 rknn_context 对象。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + int ret = rknn_destroy (ctx); + +3.2.4.3 rknn_query + rknn_query 函数能够查询获取到模型输入输出、运行时间以及 SDK 版本等信息。 + + 13 + 瑞芯微电子股份有限公司 + +API rknn_query + +功能 查询模型与 SDK 的相关信息。 + +参数 rknn_context context:rknn_context 对象。 + + rknn_query_cmd cmd:查询命令。 + + void* info:存放返回结果的结构体变量。 + + uint32_t size:info 对应的结构体变量的大小。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 当前 SDK 支持的查询命令如下表所示: + + 查询命令 返回结果结构体 功能 + +RKNN_QUERY_IN_OUT_NUM rknn_input_output_num 查询输入输出 Tensor 个数 + +RKNN_QUERY_INPUT_ATTR rknn_tensor_attr 查询输入 Tensor 属性 + +RKNN_QUERY_OUTPUT_ATTR rknn_tensor_attr 查询输出 Tensor 属性 + +RKNN_QUERY_PERF_DETAIL rknn_perf_detail 查询网络各层运行时间 + +RKNN_QUERY_SDK_VERSION rknn_sdk_version 查询 SDK 版本 + + 接下来的将依次详解各个查询命令如何使用。 + +1) 查询输入输出 Tensor 个数 + 传入 RKNN_QUERY_IN_OUT_NUM 命令可以查询模型输入输出 Tensor 的个数。其中需 + +要先创建 rknn_input_output_num 结构体对象。 + 示例代码如下: + + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, + + sizeof(io_num)); + printf("model input num: %d, output num: %d\n", io_num.n_input, + + io_num.n_output); + +2) 查询输入 Tensor 属性 + 传入 RKNN_QUERY_INPUT_ATTR 命令可以查询模型输入 Tensor 的属性。其中需要先创 + +建 rknn_tensor_attr 结构体对象。 + + 14 + 瑞芯微电子股份有限公司 + +示例代码如下: + +rknn_tensor_attr input_attrs[io_num.n_input]; +memset(input_attrs, 0, sizeof(input_attrs)); +for (int i = 0; i < io_num.n_input; i++) { + + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +3) 查询输出 Tensor 属性 + 传入 RKNN_QUERY_OUTPUT_ATTR 命令可以查询模型输出 Tensor 的属性。其中需要先 + +创建 rknn_tensor_attr 结构体对象。 + 示例代码如下: + +rknn_tensor_attr output_attrs[io_num.n_output]; +memset(output_attrs, 0, sizeof(output_attrs)); +for (int i = 0; i < io_num.n_output; i++) { + + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +4) 查询网络各层运行时间 + 如果在 rknn_init 函数调用时有设置 RKNN_FLAG_COLLECT_PERF_MASK 标志,那么 + +在执行 rknn_run 完成之后,可以传入 RKNN_QUERY_PERF_DETAIL 命令来查询网络每层运 +行时间。其中需要先创建 rknn_perf_detail 结构体对象。 + + 示例代码如下: + +rknn_perf_detail perf_detail; +ret = rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, &perf_detail, + + sizeof(rknn_perf_detail)); +printf("%s", perf_detail.perf_data); + + 注意,用户不需要释放 rknn_perf_detail 中的 perf_data,SDK 会自动管理该 Buffer 内存。 +5) 查询 SDK 版本 + + 传入 RKNN_QUERY_SDK_VERSION 命令可以查询 RKNN SDK 的版本信息。其中需要 +先创建 rknn_sdk_version 结构体对象。 + + 15 + 瑞芯微电子股份有限公司 + + 示例代码如下: + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + + sizeof(rknn_sdk_version)); + printf("sdk api version: %s\n", version.api_version); + printf("driver version: %s\n", version.drv_version); + +3.2.4.4 rknn_inputs_set + + 通过 rknn_inputs_set 函数可以设置模型的输入数据。该函数能够支持多个输入,其中每 + + 个输入是 rknn_input 结构体对象,在传入之前用户需要设置该对象。 + +API rknn_inputs_set + +功能 设置模型输入数据。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + rknn_input inputs[]:输入数据数组,数组每个元素是 rknn_input 结构体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = img_width*img_height*img_channels; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = in_data; + + ret = rknn_inputs_set(ctx, 1, inputs); + +3.2.4.5 rknn_inputs_map + rknn_inputs_map 函数用于获取模型输入 tensor 初始化后的存储状态,存储状态包括虚拟 + + 16 + 瑞芯微电子股份有限公司 + + 地址,物理地址,fd,存储空间大小。它需要和 rknn_inputs_sync 接口(见 rknn_inputs_sync + 函数)配合使用,在模型初始化后,用户通过返回的的内存位置设置输入数据,并且在推理 + + 前调用 rknn_inputs_sync 函数。存储状态使用 rknn_tensor_mem 结构体表示。输入参数 mem 是 + + rknn_tensor_mem 结构体数组。 + 目前 ,在 RK1808/RV1109/RV1126 芯片 上,返回 的 fd 是 -1。当 返回的物 理地址 值是 + + 0xffffffffffffffff(2 的 64 次幂-1),表示无法获取正确的物理地址,而虚拟地址仍然有效。如 + 果有多个模型输入 tensor 的存储空间较大,用户可以在挂载驱动时,适当增加模型输入和输 + 出存储空间或者扩增固件中的 CMA 内存空间。以 RV1109_RV1126 为例,配置驱动存储空间, + 可以参考如下修改: + + 把/etc/init.d/S60NPU_init 文件这一行: + insmod /lib/modules/galcore.ko contiguousSize=0x400000 gpuProfiler=1 + 改成 + insmod /lib/modules/galcore.ko contiguousSize=0x600000 gpuProfiler=1 + 然后重启生效。此配置应该大于用户模型输入和输出总大小,但不超过固件中可用的 + + CMA 空间大小。 + +API rknn_inputs_map + +功能 读取输入存储状态信息。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结 + 构体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + 17 + 瑞芯微电子股份有限公司 + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + +3.2.4.6 rknn_inputs_sync + + rknn_inputs_sync 函数将 CPU 缓存写回内存,让设备能获取正确的数据。 + +API rknn_inputs_sync + +功能 同步输入数据。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + + ret = rknn_inputs_sync(ctx, 1, mem); + +3.2.4.7 rknn_inputs_unmap + + rknn_inputs_unmap 函数将清除 rknn_inputs_map 函数获取的输入 tensor 的存储位置信息和 + + 标志。 + +API rknn_inputs_unmap + +功能 清除 rknn_inputs_map 函数获取的输入 tensor 的存储位置信息和标志。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + 18 + 瑞芯微电子股份有限公司 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + ret = rknn_inputs_sync(ctx, 1, mem); + ret = rknn_run(ctx, NULL); + + ret = rknn_inputs_unmap(ctx, 1, mem); + +3.2.4.8 rknn_run + + rknn_run 函数将执行一次模型推理,调用之前需要先通过 rknn_inputs_set 函数设置输入数 + + 据。 + +API rknn_run + +功能 执行一次模型推理。 + +参数 rknn_context context:rknn_context 对象。 + + rknn_run_extend* extend:保留扩展,当前没有使用,传入 NULL 即可。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + ret = rknn_run(ctx, NULL); + +3.2.4.9 rknn_outputs_get + + rknn_outputs_get 函数可以获取模型推理的输出数据。该函数能够一次获取多个输出数据。 + 其 中 每 个 输 出 是 rknn_output 结 构 体 对 象 , 在 函 数 调 用 之 前 需 要 依 次 创 建 并 设 置 每 个 + rknn_output 对象。 + + 对于输出数据的 buffer 存放可以采用两种方式:一种是用户自行申请和释放,此时 + + 19 + 瑞芯微电子股份有限公司 + + rknn_output 对象的 is_prealloc 需要设置为 1,并且将 buf 指针指向用户申请的 buffer;另一种 + 是由 rknn 来进行分配,此时 rknn_output 对象的 is_prealloc 设置为 0 即可,函数执行之后 buf + 将指向输出数据。 + +API rknn_outputs_get + +功能 获取模型推理输出。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + rknn_output outputs[]:输出数据的数组,其中数组每个元素为 rknn_output 结构体对 + 象,代表模型的一个输出。 + + rknn_output_extend* extend:保留扩展,当前没有使用,传入 NULL 即可 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) { + + outputs[i].want_float = 1; + } + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + +3.2.4.10 rknn_outputs_release + + rknn_outputs_release 函数将释放 rknn_outputs_get 函数得到的输出的相关资源。 + +API rknn_outputs_release + +功能 释放 rknn_output 对象。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + rknn_output outputs[]:要销毁的 rknn_output 数组。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下 + + 20 + 瑞芯微电子股份有限公司 + + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + +3.2.4.11 rknn_outputs_map + + rknn_outputs_map 函 数 获 取 模 型 初 始 化 后 输 出 tensor 的 存 储 状 态 。 需 要 和 + + rknn_outputs_sync 函 数 ( 见 rknn_outputs_sync 函 数 ) 配 合 使 用 , 在 模 型 初 始 化 后 调 用 + rknn_outputs_map 接口,接着每次推理完调用 rknn_outputs_sync 接口。如果用户需要 32 位浮 + 点类型的数据,需要根据量化方式和量化的数据类型做反量化。 + +API rknn_outputs_map + +功能 读取输出存储状态信息。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_map(ctx, 1, mem); + +3.2.4.12 rknn_outputs_sync + + 当使用 rknn_outputs_map 接口映射完模型运行时模型输出 tensor 存储状态信息后,为确 + + 保缓存一致性,使用 rknn_outputs_sync 函数让 CPU 获取推理完最新的数据。 + +API rknn_outputs_sync + +功能 推理完,同步最新的输出数据。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + 21 + 瑞芯微电子股份有限公司 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_sync(ctx, io_num.n_output, mem); + +3.2.4.13 rknn_outputs_unmap + + rknn_outputs_unmap 函数将清除 rknn_outputs_map 函数获取的输出 tensor 的存储状态。 + +API rknn_outputs_unmap + +功能 清除 rknn_outputs_map 函数获取的输出 tensor 的存储状态。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_unmap(ctx, io_num.n_output,mem); + +3.2.5 RKNN 数据结构定义 + +3.2.5.1 rknn_input_output_num + 结构体 rknn_input_output_num 表示输入输出 Tensor 个数,其结构体成员变量如下表所示: + + 22 + 成员变量 数据类型 瑞芯微电子股份有限公司 + n_input uint32_t +n_output uint32_t 含义 + + 输入 Tensor 个数 + 输出 Tensor 个数 + +3.2.5.2 rknn_tensor_attr + +结构体 rknn_tensor_attr 表示模型的 Tensor 的属性,结构体的定义如下表所示: + +成员变量 数据类型 含义 + +index uint32_t 表示输入输出 Tensor 的索引位置。 + +n_dims uint32_t Tensor 维度个数。 + + dims uint32_t[] Tensor 各维度值。 + name char[] Tensor 名称。 +n_elems Tensor 数据元素个数。 + uint32_t + +size uint32_t Tensor 数据所占内存大小。 + +fmt rknn_tensor_format Tensor 维度的格式,有以下格式: + + RKNN_TENSOR_NCHW + RKNN_TENSOR_NHWC + +type rknn_tensor_type Tensor 数据类型,有以下数据类型: + + RKNN_TENSOR_FLOAT32 + RKNN_TENSOR_FLOAT16 + RKNN_TENSOR_INT8 + RKNN_TENSOR_UINT8 + +qnt_type RKNN_TENSOR_INT16 + rknn_tensor_qnt_type Tensor 量化类型,有以下的量化类型: + + RKNN_TENSOR_QNT_NONE:未量化; + RKNN_TENSOR_QNT_DFP:动态定点量化; + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC : 非 + + 23 + fl int8_t 瑞芯微电子股份有限公司 + zp uint32_t + 对称量化。 +scale float RKNN_TENSOR_QNT_DFP 量化类型的参数。 + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 量 化 + 类型的参数。 + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 量 化 + 类型的参数。 + +3.2.5.3 rknn_input + + 结构体 rknn_input 表示模型的一个数据输入,用来作为参数传入给 rknn_inputs_set 函数。 +结构体的定义如下表所示: + +成员变量 数据类型 含义 + +index uint32_t 该输入的索引位置。 + +buf void* 输入数据 Buffer 的指针。 + +size uint32_t 输入数据 Buffer 所占内存大小。 + +pass_through uint8_t 设置为 1 时会将 buf 存放的输入数据直接设置给 + 模型的输入节点,不做任何预处理。 + +type rknn_tensor_type 输入数据的类型。 + +fmt rknn_tensor_format 输入数据的格式。 + +3.2.5.4 rknn_tensor_mem + +结构体 rknn_tensor_mem 表示 tensor 初始化后的存储状态信息,用来作为参数传入给 + +rknn_inputs_map 系列和 rknn_outputs_map 系列函数。结构体的定义如下表所示: + +成员变量 数据类型 含义 + +logical_addr void* 该输入的虚拟地址。 + +physical_addr uint64_t 该输入的物理地址。 + +fd int32_t 该输入的 fd。 + + 24 + size uint32_t 瑞芯微电子股份有限公司 + handle uint32_t + priv_data 该输入 tensor 占用的内存大小。 +reserved_flag void* 该输入的 handle。 + uint64_t 保留的数据。 + 保留的标志位。 + +3.2.5.5 rknn_output + +结构体 rknn_output 表示模型的一个数据输出,用来作为参数传入给 rknn_outputs_get 函 + +数,在函数执行后,结构体对象将会被赋值。结构体的定义如下表所示: + +成员变量 数据类型 含义 + +want_float uint8_t 标识是否需要将输出数据转为 float 类型输出。 + +is_prealloc uint8_t 标识存放输出数据的 Buffer 是否是预分配。 + +index uint32_t 该输出的索引位置。 + +buf void* 输出数据 Buffer 的指针。 + +size uint32_t 输出数据 Buffer 所占内存大小。 + +3.2.5.6 rknn_perf_detail + +结构体 rknn_perf_detail 表示模型的性能详情,结构体的定义如下表所示: + +成员变量 数据类型 含义 + +perf_data char* 性能详情包含网络每层运行时间,能够直接打印 + + 出来查看。 + +data_len uint64_t 存放性能详情的字符串数组的长度。 + +3.2.5.7 rknn_sdk_version + +结构体 rknn_sdk_version 用来表示 RKNN SDK 的版本信息,结构体的定义如下: + + 25 + 成员变量 数据类型 瑞芯微电子股份有限公司 + api_version char[] + drv_version char[] 含义 + SDK 的版本信息。 + SDK 所基于的驱动版本信息。 + +3.2.6 RKNN 返回值错误码 + +RKNN API 函数的返回值错误码定义如下表所示 + + 错误码 错误详情 + +RKNN_SUCC(0) 执行成功 + +RKNN_ERR_FAIL(-1) 执行出错 + +RKNN_ERR_TIMEOUT(-2) 执行超时 + +RKNN_ERR_DEVICE_UNAVAILABLE(-3) NPU 设备不可用 + +RKNN_ERR_MALLOC_FAIL(-4) 内存分配失败 + +RKNN_ERR_PARAM_INVALID(-5) 传入参数错误 + +RKNN_ERR_MODEL_INVALID(-6) 传入的 RKNN 模型无效 + +RKNN_ERR_CTX_INVALID(-7) 传入的 rknn_context 无效 +RKNN_ERR_INPUT_INVALID(-8) 传入的 rknn_input 对象无效 +RKNN_ERR_OUTPUT_INVALID(-9) 传入的 rknn_output 对象无效 + +RKNN_ERR_DEVICE_UNMATCH(-10) 版本不匹配 + +RKNN_ERR_INCOMPATILE_PRE_COMPILE_M RKNN 模型使用 pre_compile 模式,但是和当前驱动不 + +ODEL(-11) 兼容 + +RKNN_ERR_INCOMPATILE_OPTIMIZATION_L RKNN 模型设置了优化等级的选项,但是和当前驱动 + +EVEL_VERSION(-12) 不兼容 + +RKNN_ERR_TARGET_PLATFORM_UNMATCH RKNN 模型和当前平台不兼容,一般是将 RK1808 的平 + +(-13) 台的 RKNN 模型放到了 RV1109/RV1126 上。 + +RKNN_ERR_NON_PRE_COMPILED_MODEL_ RKNN 模型不是 pre_compile 模式,在 mini-driver 上无 + +ON_MINI_DRIVER(-14) 法执行 + + 26 + 瑞芯微电子股份有限公司 + +4 高级 API 使用说明 + +4.1 Matmul 算子库 + +4.1.1 简介 + + 高级 API 旨在利用 NPU 高算力特性,执行特定的数学运算,提供简洁的接口调用,达到 +计算加速的效果。其中,Matmul 算子库是一个定点数矩阵乘法的加速库。该操作定义如下: + + C  AT * B + 这里: + A,B 和 C 是 2 维矩阵 + A 是一个 K*M 的矩阵, + B 是一个 K*N 的矩阵 + C 是一个 M*N 的矩阵 + +4.1.2 数据结构定义 + + rknn_matmul_handle_t 表示用于执行 Matmul 算子操作的句柄,它包含了运行时环境的上 +下文和输入 buffer 的信息。结构体的定义如下表所示: + +成员变量 数据类型 含义 + + A void* 运算时第一个矩阵 buffer 的指针。 + + B void* 运算时第二个矩阵 buffer 的指针。 + +M int32_t A 矩阵的低维度元素个数。 + + K int32_t A 和 B 矩阵的高维度元素个数。 + + N int32_t B 矩阵的低维度元素个数。 + +in_dtype rknn_tensor_type 输入数据的类型。 + +rknn_ctx rknn_context 运行时的上下文对象。 + + 27 + 瑞芯微电子股份有限公司 + +4.1.3 详细 API 说明 + +4.1.3.1 rknn_matmul_load + + rknn_matmul_load 加载函数将加载用户创建的输入 buffer,返回 rknn_matmul_handle_t 类 + 型对象。Matmul 算子 API 不负责管理输入 buffer 的生命周期,用户要确保输入 buffer 在 Matmul + + 算子 API 调用内有效。 + +API rknn_matmul_load + +功能 初始化和设置输入 buffer 指针。 + +参数 void *a:用户创建的第一个矩阵 buffer 的指针,只支持输入是 8-bit 无符号整型或 8-bit + 有符号整型的一维数组指针。 + + void *b:用户创建的第二个矩阵 buffer 的指针,只支持输入是 8-bit 无符号整型或 8-bit + 有符号整型的一维数组指针。 + + int32_t M:A 矩阵的低维度元素个数。 + + int32_t K:A 和 B 矩阵的高维度元素个数。 + int32_t N:B 矩阵的低维度元素个数。 + + rknn_tensor_type dtype:用户指定的输入数据类型,只支持 RKNN_TENSOR_INT8 或 + RKNN_TENSOR_UINT8 类型 + +返回值 rknn_matmul_handle_t 对象。 + + 示例代码如下: + + rknn_tensor_type dtype = RKNN_TENSOR_INT8; + int8_t x[256*1] = {0}; + int8_t y[256*4096] = {0}; + rknn_matmul_handle_t handle= rknn_matmul_load(x,y,1,256,4096,dtype); + +4.1.3.2 rknn_matmul_run + + 在 rknn_matmul_load 被调用后和执行 rknn_matmul_run 前,输入 buffer 的数据由外部更新, + 不用重新调用 rknn_matmul_load。 + + 28 + 瑞芯微电子股份有限公司 + +API rknn_matmul_run + +功能 执行 Matmul 操作。 + +参数 rknn_matmul_handle_t matmul_handle:由 rknn_matmul_load 接口返回的句柄。 + + float *c:用户创建的矩阵浮点 buffer 的指针,用于获取输出。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + ... + float out_fp32_buf[4096] = {0}; + rknn_matmul_run(handle,out_fp32_buf); + +4.1.3.3 rknn_matmul_unload + +API rknn_matmul_unload + +功能 销毁 Matmul 算子运行时上下文。 + +参数 rknn_matmul_handle_t matmul_handle:由 rknn_matmul_load 接口返回的句柄。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + rknn_matmul_unload(handle); + +4.1.4 实现限制 + + Matmul 算子库是基于 NPU 的硬件架构实现,为了达到精度和速度的平衡,有一些限制如下。 + +4.1.4.1 维度限制 + + 按照上述操作描述,该库实现了 M=1 的矩阵乘法。具体而言,Matmul 算子输入 A 必须是 Kx1 +形状的 buffer,即用户必须创建一块包含 K 个 8-bit 无符号整型或者 8-bit 有符号整型元素的数据。 +当算子库运行在 Mini driver 上,K 的值只能设置为 128 或 256 或 512,N 固定为 4096,而在 Full driver +上运行,没有此限制,但建议 K 的值为 128,256,512,1024,2048,N 取 2 的偶数次幂,建议 N + + 29 + 瑞芯微电子股份有限公司 + +不大于 4096。 + +4.1.4.2 输入数据类型限制 + + 只支持 8-bit 无符号整型和 8-bit 有符号整型两种输入。 + +4.1.5 基准测试 + + 输入的两个矩阵使用随机数情况下,在 RV1109-EVB 板子上实测结果如表-1 所示。速度是 + +rknn_matmul_run 接口调用循环 100 次后的平均时间,平均相对误差是 NPU 和 CPU 上执行相同算 + +法的结果的误差值,具体公式是: + + (abs(R1  R2 ) / R2 ) / N + + k + + 其中, + + R1 是 Matmul 算子库输出向量,包含 N 个元素。 + R2 是 CPU 输出向量,包含 N 个元素。 + + 表-1 Matmul 算子库速度/精度结果(RV1109,int8) + +K N 速度(ms) 平均相对误差 + +128 1024 1.0 0.00034 + +256 1024 1.6 0.00032 + +512 2024 3.0 -0.00015 + +1024 1024 5.4 0.00047 + +128 4096 3.0 0.00051 + +256 4096 5.6 0.00024 + +512 4096 10.7 0.00024 + +1024 4096 20.9 0.00051 + +注意,速度可能因为 NPU 驱动版本不同而有些许差异。误差值则根据每次测试的随机数不同也可 +能有些许差异。 + + 30 + 瑞芯微电子股份有限公司 + +5 NPU 驱动说明 + +5.1.1 NPU 驱动目录说明 + + NPU 的驱动在$SDK/external/rknpu/drivers/目录下或者 + +https://github.com/rockchip-linux/rknpu/tree/master/drivers + +其中的编译、安装规则参考$SDK/buildroot/package/rockchip/rknpu/rknpu.mk +drivers/ +├── common +├── linux-aarch64 (for RK1808 npu full driver) +├── linux-aarch64-mini (for RK1808 npu mini driver) +├── linux-armhf (for RK1806 npu full driver) +├── linux-armhf-mini(for RK1806 npu mini driver) +├── linux-armhf-puma (for RV1126/RV1109 npu full driver) +├── linux-armhf-puma-mini(for RV1126/RV1109 npu mini driver) +├── npu_ko (NPU kernel driver) + +5.1.2 NPU full driver 与 mini driver 的区别 + + 主要包含以下几点: + 1)Mini driver 只支持预编译的 rknn 模型,如果跑非预编译模型,会出现 +RKNN_ERR_MODEL_INVALID 的错误,从 1.6.0 开始,会返回 +RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER 的错误; + 2)Full driver 支持 RKNN Toolkit 的联机调试功能,mini driver 不支持; + 3)Mini driver 库大小比 full driver 小很多,以 RV1109/RV1126 1.6.0 驱动为例,full driver 大 +小为 87MB,mini driver 大小为 7.1MB,可以有效的节省 flash 大小。 + 4)Mini driver 库运行时占用的内存比 full driver 小。 + + 31 + 瑞芯微电子股份有限公司 + +6 FAQ + +6.1.1 输入输出数据格式问题 + +6.1.1.1 三通道图片数据输入,采用 RGB 还是 BGR 排布? + + 建议用户输入数据统一使用 RGB 排布。在导出 RKNN 模型时,config 函数的 reorder_channel +参数,有以下两种可能: + + 1)如果原始模型使用 BGR 图片训练,reorder_channel='2 1 0'。 + 2)如果原始模型使用 RGB 图片训练,reorder_channel='0 1 2'。 + +6.1.1.2 rknn_input 结构体该设置的 RKNN_TENSOR_NHWC 还是 RKNN_TENSOR_NCHW? + 两种设置耗时为何不同? + + rknn_input 结构体根据用户自己的数据格式而定,C API 内部会自动转换成 NPU 需要的格式。 +耗时不同的原因是不同输入格式计算量不同,优化方式也不同。 + +6.1.1.3 没量化的 RKNN 模型,输出 rknn_tensor_attr 里面 size 和 rknn_outputs_get 接口返 + 回的 rknn_output 的 size 为何不同? + + 没量化 RKNN 模型,NPU 内部输出数据类型是 float16,大小是元素数量*2 字节。当用户设 +置 want_float=1 时,想要的是 float32 数据,float16 会转换成 float32,大小是元素数量*4 字节。 + +6.1.1.4 rknn_output.index 是用户输入还是驱动返回? + +驱动返回。 + +6.1.1.5 rknn_tensor_attr 中的 dims 数组为何会出现 0? + +0 表示该维度无效。rknn_tensor_attr 中的 n_dims 表示 dims 数组的有效维度数量。 + + 32 + 瑞芯微电子股份有限公司 + +6.1.1.6 rknn_tensor_attr 中的 dims 数组顺序与 rknn_toolkit 的获取的 numpy 的顺序相反? + 是。C API 中的数组排布跟 python 相反,比如 rknn-toolkit 的 run()接口获得 numpy 输出形 + +状是[1,255,20,20],C API 中 dims 数组是{20,20,255,1}。 + +6.1.2 输入输出接口使用问题 + +6.1.2.1 pass_through 用法以及使用 rknn_inputs_map 接口时,如何预处理数据? + 请参考 https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples 下的 + +rknn_pass_through_demo 示例。 +6.1.2.2 使用 rknn_inputs_map 或者 rknn_outputs_map 获取的物理地址为什么会无效?如何 + + 获取有效的物理地址? + + 输入/输出无法分配到物理连续的内存,可能的原因有: + 1)输入/输出的占用空间过大,超过了总的物理连续的内存大小(默认是 4MB)。 + 2)系统中没有足够的物理连续的内存可用。 + 3)导出 RKNN 模型时,config 函数添加如下参数:output_optimize=1。 + 用户可以尝试重启系统,或者让 NPU 驱动挂载时配置更大的连续地址空间,配置方法参考 +rknn_inputs_map 接口说明。 + +6.1.3 API 调用流程问题 + +6.1.3.1 rknn_init 成功后,模型文件占用内存是否可以释放? + 可以。 + +6.1.3.2 rknn_output.is_prealloc=1 时,rknn_outputs_release 是否需要调用? + 需要。 + + 33 + 瑞芯微电子股份有限公司 + +6.1.4 性能问题 + +6.1.4.1 rknn_init 耗时过长? + + 使用预编译模型。使用方法参考 https://github.com/rockchip-linux/rknn-toolkit/tree/master/doc 下 +User Guide 文档的相关章节。 + +6.1.4.2 rknn_inputs_set 接口耗时过长? + + 可能原因是数据量大或格式转换耗时长。如果是格式转换耗时长,用户可以尝试 pass_through +用法自己做转换。转换方式请参考 +https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples 下的 +rknn_pass_through_demo 示例。或者尝试在导出 RKNN 模型时,config 函数添加如下参数: +output_optimize=1。 + +6.1.4.3 rknn_outputs_get 接口耗时过长? + + 可能原因是数据量大或转换格式耗时长。如果是转换格式耗时长,用户可以尝试设置 +want_float=0, 再 自 己 做 转 换 。 或 者 尝 试 在 导 出 RKNN 模 型 时 , config 函 数 添 加 如 下 参 数 : +output_optimize=1。 + + 34 + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_EN.pdf b/rknn_yolo_demo/libs/rklibs/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_EN.pdf new file mode 100644 index 0000000..1fe93f2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_EN.pdf @@ -0,0 +1,1473 @@ + www.rock-chips.com + +Classification Level: Top Secret( ) Secret( ) Internal( ) Public(√) + +Rockchip User Guide RKNN API + +(Technology Department, Graphic Compute Platform Center) + +Mark: Version: 1.7.3 + +[ ] Changing Author: HPC + +[√] Released Completed Date: 13/Aug/2022 + + Reviewer: Vincent + + Reviewed Date: 213/Aug/2022 + + 瑞芯微电子股份有限公司 + Rockchip Electronics Co., Ltd. + + (Copyright Reserved) + www.rock-chips.com + + Revision History + +Version Modifier Date Modify Description Reviewer +v0.9.7 Yang Huacong +V0.9.8 Yang Huacong 25/Jan/2019 Initial version Zhuo + 5/Jun/2019 Hongtian +V1.3.3 Randall 2/June/2020 1. Add RKNN API Library description +V1.4.0 Randall 2. Update rknn example and rknn-toolkit Zhuo + Hongtian +v1.6.0 Chifred Hong path + 3. Fix some mistake Randall +v1.6.1 Chifred Hong 1. Support RV1109/RV1126 +v1.7.0 Chifred Hong 2. Remove the python support +v1.7.1 Chifred Hong instructions, see the RKNN Toolkit Lite +v1.7.3 Chifred Hong related documentation for python support. + + 10/Sep/2020 1. Add some error code Randall + + 15/Jan/2021 1. Add Matmul advanced API Randall + 2. Add a set of API for setting inputs and + a set of API for obtaining outputs + 3. Add quantization and dequantization + algorithm description + 4. Add NPU driver description + 5. Add FAQ + + 26/Apr/2021 1. Update Matmul advanced API Randall + + 5/Aug/2021 1. Update Version number Randall + Randall + 2/Dec/2021 1. Single-channel input performance Randall + optimization + 2. Fix bug + + 13/Aug/2022 1. Update Version number + + 1 + www.rock-chips.com + +1 OVERVIEW ..................................................................................................................................................... 5 +2 SUPPORTED HARDWARE PLATFORMS ................................................................................................. 5 +3 INSTRUCTIONS ..............................................................................................................................................5 + + 3.1 RKNN SDK DEVELOPMENT PROCESS ........................................................................................................ 5 + 3.2 RKNN C API ...............................................................................................................................................6 + + 3.2.1 RKNN API Library .............................................................................................................................. 6 + 3.2.2 EXAMPLES .........................................................................................................................................6 + 3.2.3 API process description ........................................................................................................................7 + + 3.2.3.1 API internal processing flow ........................................................................................................................... 9 + 3.2.3.2 Quantification and dequantization ................................................................................................................10 + 3.2.3.3 Zero copy .......................................................................................................................................................12 + 3.2.4 API Reference .................................................................................................................................... 13 + 3.2.4.1 rknn_init ........................................................................................................................................................ 13 + 3.2.4.2 rknn_destroy ..................................................................................................................................................14 + 3.2.4.3 rknn_query .................................................................................................................................................... 15 + 3.2.4.4 rknn_inputs_set ............................................................................................................................................. 17 + 3.2.4.5 rknn_inputs_map ...........................................................................................................................................18 + 3.2.4.6 rknn_inputs_sync ...........................................................................................................................................19 + 3.2.4.7 rknn_inputs_unmap .......................................................................................................................................20 + 3.2.4.8 rknn_run ........................................................................................................................................................ 21 + 3.2.4.9 rknn_outputs_get ...........................................................................................................................................21 + 3.2.4.10 rknn_outputs_release .................................................................................................................................. 22 + 3.2.4.11 rknn_outputs_map ....................................................................................................................................... 23 + 3.2.4.12 rknn_outputs_sync .......................................................................................................................................23 + + 2 + www.rock-chips.com + 3.2.4.13 rknn_outputs_unmap ...................................................................................................................................24 + 3.2.5 RKNN DataStruct Define .................................................................................................................. 25 + 3.2.5.1 rknn_input_output_num ................................................................................................................................ 25 + 3.2.5.2 rknn_tensor_attr ............................................................................................................................................25 + 3.2.5.3 rknn_input ..................................................................................................................................................... 26 + 3.2.5.4 rknn_tensor_mem ..........................................................................................................................................27 + 3.2.5.5 rknn_output ................................................................................................................................................... 27 + 3.2.5.6 rknn_perf_detail ............................................................................................................................................ 28 + 3.2.5.7 rknn_sdk_version .......................................................................................................................................... 28 + 3.2.6 RKNN Error Code ............................................................................................................................. 28 +4 ADVANCED API INSTRUCTIONS .............................................................................................................29 + 4.1 MATMUL OPERATOR LIBRARY ....................................................................................................................29 + 4.1.1 Introduction ........................................................................................................................................29 + 4.1.2 Data structure definition .....................................................................................................................30 + 4.1.3 Detailed API description .................................................................................................................... 31 + 4.1.3.1 rknn_matmul_load ........................................................................................................................................ 31 + 4.1.3.2 rknn_matmul_run ..........................................................................................................................................31 + 4.1.3.3 rknn_matmul_unload .................................................................................................................................... 32 + 4.1.4 Implementation restrictions ................................................................................................................32 + 4.1.4.1 Dimensional restrictions ............................................................................................................................... 33 + 4.1.4.2 Input data type restriction ............................................................................................................................. 33 + 4.1.5 Benchmark ......................................................................................................................................... 33 +5 NPU DRIVER DESCRIPTION .................................................................................................................... 35 + 5.1.1 Directory structure description ...........................................................................................................35 + 5.1.2 The difference between NPU full driver and mini driver .................................................................. 35 + + 3 + www.rock-chips.com +6 FAQ ..................................................................................................................................................................36 + + 6.1.1 Input and output data format issues ................................................................................................... 36 + 6.1.2 Input and output interface usage problems ........................................................................................ 37 + 6.1.3 API call process issues ....................................................................................................................... 38 + 6.1.4 Performance issues .............................................................................................................................38 + + 4 + www.rock-chips.com + +1 Overview + + RKNN SDK provides a programming interface for platforms with NPU such as RK1808, which can +help users deploy RKNN models exported using RKNN-Toolkit. + +2 Supported hardware platforms + +This document applies to the following hardware platforms: + 1) RK1808, RK1806 + 2) RV1126, RV1109 + +The following description takes RK1808 as an example and also applies to other platforms mentioned +above. + +3 Instructions +3.1 RKNN SDK Development Process + + Before using the RKNN SDK, users first need to use the RKNN-Toolkit tool to convert the + user's model to the RKNN model. The user can obtain the tool's complete installation package and + documentation at https://github.com/rockchip-linux/rknn-toolkit . + + After successful conversion to the RKNN model, users can first connect to the RK1808 device + via RKNN-Toolkit for online debugging to ensure that the accuracy and performance of the model + meet the requirements. + + After getting the RKNN model file, users can choose using C or Python interface to develop + the application. The following chapters will explain how to develop application based on the RKNN + SDK on RK1808 platform. + + 5 + www.rock-chips.com + +3.2 RKNN C API + +3.2.1 RKNN API Library + + The libraries and header files provided by the RKNN SDK are located at +/external/rknpu/rknn/rknn_api/librknn_api directory, developers can use to develop +applications. + + It should be noted that the RKNN API of the RK1808 and RK3399Pro platforms is compatible, +and applications developed by both can be easily ported. However, you need to pay attention to +distinguish between the two platforms librknn_api.so, if the developer uses RK3399Pro's +librknn_api.so will not be able to run on the RK1808 platform. Developers can use the following +methods to distinguish the platform of librknn_api.so. + + $ strings librknn_api.so |grep version + librknn_api version 1.7.3 (cf7f05f build: 2022-08-13 10:59:33) + +3.2.2 EXAMPLES + + The SDK provides MobileNet image classification, MobileNet SSD object detection, and Yolo + v3 object detection demos. These demos provide reference for developer to develop applications + based on the RKNN SDK. The emo code is located in the + /external/rknpu/rknn/rknn_api/examples directory. Let's take rknn_mobilenet_demo as an + example to explain how to get started quickly. + + 1) Compile Demo Source Code + + cd examples/rknn_mobilenet_demo + # modify `GCC_COMPILER` on `build.sh` for target platform, then execute + ./build.sh + 2) Deploy to the RK1808 device + + adb push install/rknn_mobilenet_demo /userdata/ + + 3) Run Demo + + 6 + www.rock-chips.com + + adb shell + cd /userdata/rknn_mobilenet_demo/ + ./rknn_mobilenet_demo model/mobilenet_v1_rk180x.rknn + model/dog_224x224.jpg # RK180x + ./rknn_mobilenet_demo model/mobilenet_v1_rv1109_rv1126.rknn + model/dog_224x224.jpg # RV1109/RV1126 + +3.2.3 API process description + + From RKNN API V1.6.0, a new set of functions for setting input have been added: +  rknn_inputs_map +  rknn_inputs_sync +  rknn_inputs_unmap + And a set of functions to get the output: +  rknn_outputs_map +  rknn_outputs_sync +  rknn_outputs_unmap + When setting input, users can use rknn_inputs_set or rknn_inputs_map series of functions. + When obtaining the output of inference, use the rknn_outputs_get or rknn_outputs_map series of + functions. In certain scenarios, using the map series of API can reduce the number of memory copies + and improve the speed of complete inference. + The calling process of the rknn_inputs_map series interface and the rknn_inputs_set interface is + different, and the calling process of the rknn_outputs_map series interface and the rknn_outputs_get + interface are also different. The difference between the two series of API call flow is shown in Figure + 3-1, where (a) is the set/get series interface call flow, (b) is the map series interface call flow. + + 7 + www.rock-chips.com + + Figure 3-1 callling process difference between set/get series (a) and map series (b) + There is no binding relationship between the set input and get output API, so set/get series +interfaces and map series interfaces can be mixed. As shown in Figure 3-2(c), the user can use the +rknn_inputs_map series interface to set the input, and then get the output through the +rknn_outputs_get interface, or as Figure 3-2(d) set the input through the rknn_inputs_set series +interface, and then use the rknn_outputs_map interface to get the output. + + 8 + www.rock-chips.com + + Figure 3-2 The calling process of mixed use of set/get series and map series interfaces +3.2.3.1 API internal processing flow + + During inference of RKNN model, the original data has to go through three processes: input + processing, NPU running model, and output processing. In a typical picture inference scenario, + assuming that the input data is a 3-channel picture and is in the NHWC layout format, the data + processing flow at runtime is shown in Figure 3-3. At the API level, the rknn_inputs_set interface + (when pass_through=0, see the rknn_input structure for details) includes the process of swapping + + 9 + www.rock-chips.com + + color channel, normalization, quantization, and conversion of NHWC to NCHW. The + rknn_outputs_get interface (when want_float=1, see rknn_output structure) contains the process of + dequantization. + + Figure 3-3 Normal mode image data processing flow + In fact, for some RKNN models, the Runtime input processing flow is not all executed. For + example, when the input data is not a 3-channel image or the config function of the rknn-toolkit is + configured as reorder=”0 1 2” when exporting model, there is no color channel swapping process. + When the attribute of RKNN model input tensor is NHWC layout, there is no process for converting + NHWC to NCHW. rknn_inputs_set (when pass_through=1) and rknn_inputs_map do not contain any + input processing flow, rknn_outputs_get (when want_float=0) and rknn_outputs_map do not contain + any output processing flow. At this time, although the two sets of APIs do not include the + corresponding processing flow, using the set/get series interface will have more data copying process + than the map series interface. + +3.2.3.2 Quantification and dequantization + + When using rknn_inputs_set (pass_through=1) and rknn_inputs_map, it indicates that the + process before NPU inference needs to be processed by the user. After rknn_outputs_map gets the + output, the user also needs to dequantize output to get the 32-bit floating point result. + + The quantization method, quantization data type and quantization parameters used in + quantization and dequantization can be queried through the rknn_query interface. Currently, the NPU + of RK1808/RK3399Pro/RV1109/RV1126 has two quantization methods: asymmetric quantization + and dynamic fixed-point quantization. Each quantization method specifies the corresponding + quantized data type. There are a total of four combinations of data types and quantification methods: + + 10 + www.rock-chips.com + +  uint8 (asymmetric quantization) +  int8 (dynamic fixed-point) +  int16 (dynamic fixed-point) +  float16 (none) + Normally, the normalized data is stored in 32-bit floating point data. For conversion of 32-bit +floating point data to 16-bit floating point data, please refer to the IEEE-754 standard. Assuming that +the normalized 32-bit floating point data is D , the following describes the quantization process: + 1) float32 to uint8 + +Assuming that the asymmetric quantization parameter of the input tensor is Sq , ZP , the data + +quantization process is expressed as the following formula: + + Dq  round (clamp(D / Sq  ZP,0,255)) (3-1) + +In the above formula, clamp means to limit the value to a certain range. round means rounding + +processing. + +2) float32 to int8 + +Assuming that the dynamic fixed-point quantization parameter of the input tensor is fl, the data + +quantization process is expressed as the following formula: + + Dq  round (clamp(D * 2 fl ,-128,127)) (3-2) + + 3) float32 to int16 + Assuming that the dynamic fixed-point quantization parameter of the input tensor is fl, the data +quantization process is expressed as the following formula: + + Dq  round (clamp(D * 2 fl ,-32768,32767)) (3-3) + + The dequantization process is the inverse process of quantization, and the inverse quantization +formula can be deduced according to the above quantization formula, which will not be repeated +here. + + 11 + www.rock-chips.com + +3.2.3.3 Zero copy + + In specific case, the number of input data copies can be reduced to 0, that is, zero copy. For +example, when the RKNN model is asymmetric quantization, the quantization data type is uint8, the +mean value of the 3 channels is the same integer and the scaling factor is the same, the normalization +and quantization can be omitted. The proof is as follows: + +Assume that the input image data is D f , and the quantization parameter is Sq , ZP . M i + +Represents the mean value of the i-th channel, and Si represents the normalization factor of the i-th +channel. Then the normalized data of the i-th channel is as follows: + + Di  (D f  M i ) / Si (3-4) + +The data quantification process is expressed as the following formula: + + Dq  clamp(Di / Sq  ZP,0,255) (3-5) + +After combining the above two formulas, we can get (3-6) + Dq  clamp((D f  Mi ) /(Si * Sq)  ZP) + +Assuming that the data range of the calibration data set contains integer values from 0 to 255, + +when M1  M 2  M3 , S1  S2  S3 , the normalized value range is expressed as follows: + + Dmin  (0 - M i ) / Si  M i / Si (3-7) + + Dmax  (255 - M i ) / Si (3-8) + +So, the quantization parameter is calculated as follows: + + Sq  (Dmax  Dmin ) / 255  1/Si (3-9) + + ZP  (0  Dmin ) / Sq  M i (3-10) + + Substituting formula (3-9) and formula (3-10) into formula (3-6), it can be concluded that under +the condition of zero-copy: the mean value of the 3 channels is the same integer and the normalized +scaling factor is the same , The input uint8 data is equal to the quantized uint8 data. + + Input zero copy can reduce the CPU load and improve the speed of complete inference. For + + 12 + www.rock-chips.com + + RGB or BGR input data, the steps to achieve input zero-copy are as follows: + 1) The mean value of the three channels is the same integer and the normalized scaling factor is + + the same. + 2) In the config function of rknn-toolkit, set force_builtin_perm=True to export the RKNN + + model input by NHWC. + 3) Use the rknn_inputs_map interface to obtain the input tensor memory address information. + 4) Fill the memory address with input data, such as calling the RGA resize function, the target + + address uses the physical address obtained by rknn_inputs_map. + 5) Call the rknn_inputs_sync interface. + 6) Call the rknn_run interface. + 7) Call the get output interface. + +3.2.4 API Reference + +3.2.4.1 rknn_init + The rknn_init function will create a rknn_context object, load the RKNN model, and perform + + specific initialization behavior based on the flag. + + 13 + www.rock-chips.com + +API rknn_init + +Description Initialize rknn + +Parameters rknn_context *context:Pointer to rknn_context object. After the function is called, the + + context object will be assigned. + + void *model:Binary data for the RKNN model. + + uint32_t size:Model size + + uint32_t flag:A specific initialization flag. Currently supports following flags: + + RKNN_FLAG_COLLECT_PERF_MASK : Open the performance collection debugging + + switch. After opening, you can query the running time of each layer of the network + + through the rknn_query interface. Note that the running time of rknn_run will be + + longer after this flag is set. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_context ctx; + int ret = rknn_init(&ctx, model_data, model_data_size, 0); + +3.2.4.2 rknn_destroy + + The rknn_destroy function will release the rknn_context object and its associated resources. + +API rknn_destroy + +Description Destroy the rknn_context object and its related resources. + +Parameters rknn_context context: The rknn_context object to be destroyed. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + 14 + www.rock-chips.com + + int ret = rknn_destroy (ctx); + +3.2.4.3 rknn_query + + The rknn_query function can query the information of model input and output tensor attribute, + + performance information and SDK version etc. + +API rknn_query + +Description Query the information about the model and the SDK. + +Parameters rknn_context context: The object of rknn_contex. + + rknn_query_cmd cmd: Query command. + + void* info: Structure object that stores the result of the query. + + uint32_t size: the size of the info Structure object. + +Return int: Error code (See RKNN Error Code). + + Currently, the SDK supports the following query commands: + + Query command Return result structure Function + +RKNN_QUERY_IN_OUT_NUM rknn_input_output_num Query the number of input and output + + Tensor. + +RKNN_QUERY_INPUT_ATTR rknn_tensor_attr Query input Tensor attribute. + +RKNN_QUERY_OUTPUT_ATTR rknn_tensor_attr Query output Tensor attribute. + +RKNN_QUERY_PERF_DETAIL rknn_perf_detail Query the running time of each layer + + of the network. + +RKNN_QUERY_SDK_VERSION rknn_sdk_version Query the SDK version. + + Next we will explain each query command in detail. + + 1) Query the number of input and output Tensor + + The RKNN_QUERY_IN_OUT_NUM command can be used to query the number of model + + input and output Tensor. You need to create the rknn_input_output_num structure object first. + + 15 + www.rock-chips.com + +Sample Code: + +rknn_input_output_num io_num; +ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, + + sizeof(io_num)); +printf("model input num: %d, output num: %d\n", io_num.n_input, + + io_num.n_output); + +2) Query input Tensor attribute + The RKNN_QUERY_INPUT_ATTR command can be used to query the attribute of the model + +input Tensor. You need to create the rknn_tensor_attr structure object first. +Sample Code: + +rknn_tensor_attr input_attrs[io_num.n_input]; +memset(input_attrs, 0, sizeof(input_attrs)); +for (int i = 0; i < io_num.n_input; i++) { + + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +3) Query output Tensor attribute + The RKNN_QUERY_OUTPUT_ATTR command can be used to query the attribute of the model + +output Tensor. You need to create the rknn_tensor_attr structure object first. + Sample Code: + +rknn_tensor_attr output_attrs[io_num.n_output]; +memset(output_attrs, 0, sizeof(output_attrs)); +for (int i = 0; i < io_num.n_output; i++) { + + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +4) Query the running time of each layer of the network + If the RKNN_FLAG_COLLECT_PERF_MASK flag has been set on the rknn_init function, the + +RKNN_QUERY_PERF_DETAIL command can be passed to query the runtime of each layer of the +network after rknn_run function execution completed. You need to create the rknn_perf_detail + + 16 + www.rock-chips.com + + structure object first. + Sample Code: + + rknn_perf_detail perf_detail; + ret = rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, &perf_detail, + + sizeof(rknn_perf_detail)); + printf("%s", perf_detail.perf_data); + + It should be noted that rknn_perf_detail.perf_data does not need to be released. The SDK will + automatically manage this buffer memory. + 5) Query the SDK version + + The RKNN_QUERY_SDK_VERSION command can be used to query the version information + of the RKNN SDK. You need to create the rknn_sdk_version structure object first. + Sample Code: + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + + sizeof(rknn_sdk_version)); + printf("sdk api version: %s\n", version.api_version); + printf("driver version: %s\n", version.drv_version); + +3.2.4.4 rknn_inputs_set + + The input data of the model can be set by the rknn_inputs_set function. This function can + + support multiple inputs, each one is a rknn_input structure object. Developers needs to set these + + object field before passing in. + +API rknn_inputs_set + +Description Set the model input data. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs. + + rknn_input inputs[]: Array of rknn_input. + +Return int: Error code (See RKNN Error Code). + + 17 + www.rock-chips.com + +Sample Code: + +rknn_input inputs[1]; +memset(inputs, 0, sizeof(inputs)); +inputs[0].index = 0; +inputs[0].type = RKNN_TENSOR_UINT8; +inputs[0].size = img_width*img_height*img_channels; +inputs[0].fmt = RKNN_TENSOR_NHWC; +inputs[0].buf = in_data; + +ret = rknn_inputs_set(ctx, 1, inputs); + +3.2.4.5 rknn_inputs_map + + The rknn_inputs_map function is used to obtain the storage state of the model input tensor after + initialization. The storage state includes virtual address, physical address, fd, and storage space size. + It needs to be used in conjunction with the rknn_inputs_sync interface (see the rknn_inputs_sync + function). After the model is initialized, the user sets the input data through the returned memory + location, and calls the rknn_inputs_sync function before inference. The storage state is represented + by the rknn_tensor_mem structure. The input parameter mem is an array of rknn_tensor_mem + structure. + + Currently, on the RK1808/RV1109/RV1126 chip, the returned fd is -1. When the returned + physical address value is 0xffffffffffffffff (2 to the 64th power-1), it means that the correct physical + address cannot be obtained, and the virtual address is still valid. If there are multiple model input + tensors with large storage space, users can appropriately increase the model input and output storage + space when mounting the driver or increase the CMA memory space in the firmware. Take + RV1109_RV1126 as an example to configure drive storage space, you can refer to the following + modifications: + + Find this line in the /etc/init.d/S60NPU_init file: + insmod /lib/modules/galcore.ko contiguousSize=0x400000 gpuProfiler=1 + Change to + + 18 + www.rock-chips.com + + insmod /lib/modules/galcore.ko contiguousSize=0x600000 gpuProfiler=1 + Then restart to take effect. This configuration should be larger than the total size of user model + + input and output, but not more than the available CMA space in the firmware. + +API rknn_inputs_map + +Description Read input storage status information. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_input inputs[1]; + rknn_tensor_mem mem[1]; + memset(inputs, 0, sizeof(inputs)); + + //set input info returned by rknn_query + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = img_width*img_height*img_channels; + inputs[0].fmt = RKNN_TENSOR_NHWC; + + ret = rknn_inputs_map(ctx, 1, inputs, mem); + +3.2.4.6 rknn_inputs_sync + + The rknn_inputs_sync function writes the CPU cache back to the memory so that the device + + can obtain the correct data. + +API rknn_inputs_sync + +Description Synchronize input data. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs. + + 19 + www.rock-chips.com + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + + ret = rknn_inputs_sync(ctx, 1, mem); + +3.2.4.7 rknn_inputs_unmap + + The rknn_inputs_unmap function will clear the storage location information and flags of the + + input tensor obtained by the rknn_inputs_map function. + +API rknn_inputs_unmap + +Description Clear the storage location information and flags of the input tensor obtained by the + + rknn_inputs_map function. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + 20 + www.rock-chips.com + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + ret = rknn_inputs_sync(ctx, 1, mem); + ret = rknn_run(ctx, NULL); + + ret = rknn_inputs_unmap(ctx, 1, inputs, mem); + +3.2.4.8 rknn_run + + The rknn_run function will perform a model reasoning. The input data need to be set by the + + rknn_inputs_set function before rknn_run is called. + +API rknn_run + +Description Perform a model reasoning. + +Parameter rknn_context context: The object of rknn_contex. + + rknn_run_extend* extend: Reserved for extension, currently not used, you can pass + + NULL. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + ret = rknn_run(ctx, NULL); + +3.2.4.9 rknn_outputs_get + + The rknn_outputs_get function can get the output data of the model reasoning. This function + can get multiple output data. Each of these outputs is a rknn_output structure object, which needs to + be created and set in turn before the function is called. + + There are two ways to store buffers for output data: + 1) Developer allocate and release buffers themselves. At this time, the + + rknn_output.is_prealloc needs to be set to 1, and the rknn_output.buf points to users’ + allocated buffer; + + 21 + www.rock-chips.com + + 2) The other is allocated by SDK. At this time, the rknn_output .is_prealloc needs to be set to + + 0. After the function is executed, rknn_output.buf will be created and store the output data. + +API rknn_outputs_get + +Description Get model inference output data. + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_output outputs[]: Array of rknn_output. + + rknn_run_extend* extend: Reserved for extension, currently not used, you can pass + + NULL. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) { + + outputs[i].want_float = 1; + } + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + +3.2.4.10 rknn_outputs_release + + The rknn_outputs_release function will release the relevant resources of the rknn_output object. + +API rknn_outputs_release + +Description Release the rknn_output object + +Parameter rknn_context context: rknn_context object + + uint32_t n_outputs: Number of output. + + rknn_output outputs[]: rknn_output array to be release. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + 22 + www.rock-chips.com + + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + +3.2.4.11 rknn_outputs_map + + The rknn_outputs_map function obtains the storage state of the output tensor after the model is + + initialized. It needs to be used in conjunction with the rknn_outputs_sync function (see + + rknn_outputs_sync function). After the model is initialized, the rknn_outputs_map interface is called, + + and then the rknn_outputs_sync interface is called after each inference. If users need 32-bit floating + + point data, they need to perform dequantization according to the quantization method and quantized + + data type. + +API rknn_outputs_map + +Description Read output storage status information. + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_map(ctx, 1, mem); + +3.2.4.12 rknn_outputs_sync + + After the rknn_outputs_map interface is used to map the model output tensor storage state + information when the model is running, in order to ensure cache consistency, the rknn_outputs_sync + function is used to let the CPU obtain the latest data after the inference. + + 23 + www.rock-chips.com + +API rknn_outputs_sync + +Description After inference, synchronize the latest output data + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + +Sample Code: + + rknn_tensor_mem mem[1]; + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_sync(ctx, io_num.n_output, mem); + +3.2.4.13 rknn_outputs_unmap + + The rknn_outputs_unmap function will clear the storage status of the output tensor obtained by + + the rknn_outputs_map function. + +API rknn_outputs_unmap + +Description Clear the storage state of the output tensor obtained by the rknn_outputs_map + + function. + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + +Sample Code: + + 24 + www.rock-chips.com + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_unmap(ctx, io_num.n_output,mem); + +3.2.5 RKNN DataStruct Define + +3.2.5.1 rknn_input_output_num + + The structure rknn_input_output_num represents the number of input and output Tensor , The + following table shows the definition: + + Field Type Meaning +n_input uint32_t The number of input tensor +n_output uint32_t The number of output tensor + +3.2.5.2 rknn_tensor_attr + +The structure rknn_tensor_attr represents the attribute of the model's Tensor. The following table + +shows the definition: + +Field Type Meaning + +index uint32_t Indicates the index position of the input and output + + Tensor. + +n_dims uint32_t The number of Tensor dimensions. + +dims uint32_t[] Values for each dimension. + +name char[] Tensor name. + +n_elems uint32_t The number of Tensor data elements. + +size uint32_t The memory size of Tensor data. + +fmt rknn_tensor_format The format of Tensor dimension, has the following + + format: + + 25 + www.rock-chips.com + + RKNN_TENSOR_NCHW + + RKNN_TENSOR_NHWC + + type rknn_tensor_type Tensor data type, has the following data types: + +qnt_type RKNN_TENSOR_FLOAT32 + + fl RKNN_TENSOR_FLOAT16 + zp + scale RKNN_TENSOR_INT8 + + RKNN_TENSOR_UINT8 + + RKNN_TENSOR_INT16 + + rknn_tensor_qnt_type Tensor Quantization Type, has the following types + + of quantization: + + RKNN_TENSOR_QNT_NONE: Not quantified; + + RKNN_TENSOR_QNT_DFP: Dynamic fixed point + + quantization; + + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + + Asymmetric quantification. + + int8_t RKNN_TENSOR_QNT_DFP quantization parameter + + uint32_t RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC + + quantization parameter. + + float RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC + + quantization parameter. + +3.2.5.3 rknn_input + + The structure rknn_input represents a data input to the model, used as a parameter to the +rknn_inputs_set function. The following table shows the definition: + + 26 + www.rock-chips.com + + Field Type Meaning + index + buf uint32_t The index position of this input. + size +pass_through void* Point to the input data Buffer. + + type uint32_t The memory size of the input data Buffer. + fmt + uint8_t When set to 1, buf will be directly set to the input + + node of the model without any pre-processing. + + rknn_tensor_type The type of input data. + + rknn_tensor_format The format of input data. + +3.2.5.4 rknn_tensor_mem + +The structure rknn_tensor_mem represents the storage state information after tensor + +initialization, which is used as a parameter to pass in to the rknn_inputs_map series and + +rknn_outputs_map series functions. The definition of the structure is shown in the following table: + +Field Type Meaning + +logical_addr void* The virtual address of this input. + +physical_addr uint64_t The physical address of this input. + +fd int32_t The fd of this input. + +size uint32_t The memory size of the input tensor. + +handle uint32_t The handle of this input. + +priv_data void* Reserved data. + +reserved_flag int32_t Reserved flag. + +3.2.5.5 rknn_output + + The structure rknn_output represents a data output of the model, used as a parameter to the +rknn_outputs_get function. The following table shows the definition: + + 27 + Field Type www.rock-chips.com +want_float uint8_t + Meaning +is_prealloc uint8_t Indicates if the output data needs to be converted + to float type. + index uint32_t Indicates whether the Buffer that stores the output + buf void* data is pre-allocated. + size The index position of this output. + uint32_t Pointer which point to the output data Buffer. + Output data Buffer memory size. + +3.2.5.6 rknn_perf_detail + +The structure rknn_perf_detail represents the performance details of the model. The following + +table shows the definition: + +Field Type Meaning + +perf_data char* Performance details include the run time of each + + layer of the network. + +data_len uint64_t The Length of perf_data. + +3.2.5.7 rknn_sdk_version + +The structure rknn_sdk_version is used to indicate the version information of the RKNN SDK. + +The following table shows the definition: + +Field Type Meaning + +api_version char[] SDK API Version information. + +drv_version char[] Driver version information. + +3.2.6 RKNN Error Code + +The return code of the RKNN API function is defined as shown in the following table. + + 28 + www.rock-chips.com + + Error Code Message + +RKNN_SUCC(0) Execution is successful + +RKNN_ERR_FAIL (-1) Execution error + +RKNN_ERR_TIMEOUT (-2) Execution timeout + +RKNN_ERR_DEVICE_UNAVAILABLE (-3) NPU device is unavailable + +RKNN_ERR_MALLOC_FAIL (-4) Memory allocation is failed + +RKNN_ERR_PARAM_INVALID (-5) Parameter error + +RKNN_ERR_MODEL_INVALID (-6) RKNN model is invalid + +RKNN_ERR_CTX_INVALID (-7) rknn_context is invalid + +RKNN_ERR_INPUT_INVALID (-8) rknn_input object is invalid + +RKNN_ERR_OUTPUT_INVALID (-9) rknn_output object is invalid + +RKNN_ERR_DEVICE_UNMATCH (-10) Version does not match + +RKNN_ERR_INCOMPATILE_PRE_COMPILE_ This RKNN model use pre_compile mode, but not + +MODEL (-11) compatible with current driver. + +RKNN_ERR_INCOMPATILE_OPTIMIZATION_ This RKNN model use optimization level mode, but not + +LEVEL_VERSION (-12) compatible with current driver. + +RKNN_ERR_TARGET_PLATFORM_UNMATC This RKNN model don’t compatible with current + +H (-13) platform. + +RKNN_ERR_NON_PRE_COMPILED_MODEL The RKNN model is not in pre_compile mode and cannot + +_ON_MINI_DRIVER(-14) be executed on mini-driver. + +4 Advanced API instructions +4.1 Matmul Operator library + +4.1.1 Introduction + + The high-level API is designed to use the high computing power of the NPU to perform specific + + 29 + www.rock-chips.com + +mathematical operations, provide a simple interface call, and achieve the effect of computing acceleration. +Among them, the Matmul operator library is an acceleration library for fixed-point matrix multiplication. +The operation is defined as follows: + + C  AT * B + Here: + A, B and C are 2-dimensional matrices + A is an K*M matrix + B is a K*N matrix + C is an M*N matrix + +4.1.2 Data structure definition + +rknn_matmul_handle_t represents the handle used to perform the operation of the Matmul + +operator, which contains the context of the runtime environment and the information of the input + +buffer. The definition of the structure is shown in the following table: + +Field Type Meaning + +A void* The pointer of the first matrix buffer during + + operation. + +B void* The pointer of the second matrix buffer during + + operation. + +M int32_t The low rank dimension of A matrix. + +K int32_t The high rank dimension of A and B matrix. + +N int32_t The low rank dimension of B matrix. + +in_dtype rknn_tensor_type The type of input data. + +rknn_ctx rknn_context The context object at runtime. + + 30 + www.rock-chips.com + +4.1.3 Detailed API description + +4.1.3.1 rknn_matmul_load + + The rknn_matmul_load loading function will load the input buffer created by the user and + + return an object of type rknn_matmul_handle_t.The Matmul operator API is not responsible for + + managing the life cycle of the input buffer, and the user must ensure that the input buffer is valid + + within the Matmul operator API call. + +API rknn_matmul_load + +Description Initialize and set the input buffer pointer. + +Parameter void *a:The pointer of the first matrix buffer created by the user can only support the + + input of 8-bit unsigned integer or 8-bit signed integer one-dimensional array pointer. + + void *b:The pointer of the second matrix buffer created by the user only supports the + + input of 8-bit unsigned integer or 8-bit signed integer one-dimensional array pointer. + + int32_t M: The low rank dimension of A matrix. + + int32_t K: The high rank dimension of A and B matrix. + + int32_t N: The low rank dimension of B matrix. + + rknn_tensor_type dtype : The input data type specified by the user, only supports + + RKNN_TENSOR_INT8 or RKNN_TENSOR_UINT8 type + +Return rknn_matmul_handle_t object。 + + The sample code is as follows: + + rknn_tensor_type dtype = RKNN_TENSOR_INT8; + int8_t x[256*1] = {0}; + int8_t y[256*4096] = {0}; + rknn_matmul_handle_t handle= rknn_matmul_load(x,y,1,256,4096,dtype); + +4.1.3.2 rknn_matmul_run + After rknn_matmul_load is called and before rknn_matmul_run is executed, the data in the + + 31 + www.rock-chips.com + + input buffer is updated externally, without calling rknn_matmul_load again. + +API rknn_matmul_run + +Description Perform Matmul operations. + +Parameter rknn_matmul_handle_t matmul_handle: The handle returned by the + + rknn_matmul_load interface. + + float *c: The pointer to the matrix floating-point buffer created by the user, used to + + obtain the output. + +Return int: Error code (See RKNN Error Code). + + The sample code is as follows: + + ... + float out_fp32_buf[4096] = {0}; + rknn_matmul_run(handle,out_fp32_buf); + +4.1.3.3 rknn_matmul_unload + +API rknn_matmul_unload + +Description Destroy the Matmul operator runtime context. + +Parameter rknn_matmul_handle_t matmul_handle: The handle returned by the + + rknn_matmul_load interface. + +Return int: Error code (See RKNN Error Code). + + The sample code is as follows: + + ... + rknn_matmul_unload(handle); + +4.1.4 Implementation restrictions + + The Matmul operator library is implemented based on the hardware architecture of the NPU. In +order to achieve a balance between accuracy and speed, there are some restrictions as follows. + + 32 + www.rock-chips.com + +4.1.4.1 Dimensional restrictions + + According to the above operation description, the library realizes the matrix multiplication of M=1. +Specifically, the input A of the Matmul operator must be a Kx1 buffer(row-major), that is, the user must +create a piece of data that contains K 8-bit unsigned integers or 8-bit signed integers. When the operator +library is running on the Mini driver, the value of K can only be set to 128 or 256 or 512, and N is fixed +at 4096. When running on the Full driver, there is no such limit, but the recommended number of K is +128, 256, 512, 1024, 2048, N is an even power of 2. It is recommended that N should not be greater than +4096. + +4.1.4.2 Input data type restriction + + Only supports 8-bit unsigned integer and 8-bit signed integer input. + +4.1.5 Benchmark + + When the two input matrices use random numbers, the measured results on the RV1109-EVB board +are shown in Table-1. The speed is the average time after the rknn_matmul_run interface is called 100 +times. The average relative error is the error value of the result of executing the same algorithm on the +NPU and CPU. The specific formula is: + + (abs(R1  R2 ) / R2 ) / N + + k + + among them, + R1 is the output vector of the Matmul operator library, containing N elements. + R2 is the CPU output vector, containing N elements. + + 33 + www.rock-chips.com + + Table-1 Speed/accuracy results of Matmul operator library (RV1109, int8) + +K N Speed(ms) Average relative error + +128 1024 1.0 0.00034 + +256 1024 1.6 0.00032 + +512 2024 3.0 -0.00015 + +1024 1024 5.4 0.00047 + +128 4096 3.0 0.00051 + +256 4096 5.6 0.00024 + +512 4096 10.7 0.00024 + +1024 4096 20.9 0.00051 + +Note: the speed may vary slightly due to different NPU driver versions. The error value may varies + +slightly according to the random number of each test. + + 34 + www.rock-chips.com + +5 NPU driver description + +5.1.1 Directory structure description + + The NPU driver is in the $SDK/external/rknpu/drivers/ directory or +https://github.com/rockchip-linux/rknpu/tree/master/drivers +The compilation and installation rules refer to $SDK/buildroot/package/rockchip/rknpu/rknpu.mk +drivers/ +├── common +├── linux-aarch64 (for RK1808 npu full driver) +├── linux-aarch64-mini (for RK1808 npu mini driver) +├── linux-armhf (for RK1806 npu full driver) +├── linux-armhf-mini(for RK1806 npu mini driver) +├── linux-armhf-puma (for RV1126/RV1109 npu full driver) +├── linux-armhf-puma-mini(for RV1126/RV1109 npu mini driver) +├── npu_ko (NPU kernel driver) + +5.1.2 The difference between NPU full driver and mini driver + + Include the following points: + 1) Mini driver only supports pre-compiled rknn model. If you run non-pre-compiled model, +RKNN_ERR_MODEL_INVALID error will appear. Starting from 1.6.0, it will return +RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER error; + 2) The full driver supports the online debugging function of RKNN Toolkit, but the mini driver does +not; + 3) Mini driver library size is much smaller than full driver. Taking RV1109/RV1126 1.6.0 driver as +an example, full driver size is 87MB, mini driver size is 7.1MB, which can effectively save flash size. + 4) Mini driver library occupies less memory than full driver when running. + + 35 + www.rock-chips.com + +6 FAQ + +6.1.1 Input and output data format issues + +6.1.1.1 How to choose from RGB or BGR format when given three-channel image data + input? + + It is recommended that using RGB format input data uniformly. When exporting the RKNN model, +there are two possibilities for the reorder_channel parameter of the config function: + + 1) If the original model is trained using BGR images, reorder_channel = '2 1 0'. + 2) If the original model is trained using RGB images, reorder_channel = '0 1 2'. + +6.1.1.2 Which RKNN_TENSOR_NHWC or RKNN_TENSOR_NCHW should be set in the + rknn_input structure? Why are the two settings time-consuming different? + + The rknn_input structure is determined according to the user's own data format, and the C API will +automatically convert it into the format required by the NPU. + + The reason for the different time-consuming is that different input formats have different calculation +amounts and different optimization methods. + +6.1.1.3 For the non-quantized RKNN model, why is the size in the output + rknn_tensor_attr different from the size of the rknn_output returned by the + rknn_outputs_get interface? + + The non-quantized RKNN model, the internal output data type of the NPU is float16, and the size is +the number of elements * 2 bytes. When the user sets want_float = 1, what they want is float32 data, +float16 will be converted to float32, and the size is the number of elements * 4 bytes. + + 36 + www.rock-chips.com + +6.1.1.4 Is rknn_output.index set by user or return by driver? + +Return by driver. + +6.1.1.5 Why does the dims array of the rknn_tensor_attr have 0? + +0 means the size is invalid. n_dims in rknn_tensor_attr represents the number of valid size in dims. + +6.1.1.6 The order of dims in rknn_tensor_attr is opposite to the order of numpy obtained + by rknn_toolkit? + + The layout of arrays in C API is the opposite of python. For example, the numpy output shape +obtained by the run() interface of rknn-toolkit is [1,255,20,20], and the dims array in C API is +{20,20,255,1}. + +6.1.2 Input and output interface usage problems + +6.1.2.1 How to preprocess the data when using pass_through and using + rknn_inputs_map interface? + + Please refer to the rknn_pass_through_demo example under +https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples. + +6.1.2.2 Why is the physical address obtained using rknn_inputs_map or + rknn_outputs_map invalid? How to obtain a valid physical address? + + Input/output cannot be allocated to physically contiguous memory. The possible reasons are: + 1) The input/output size is too large, exceeding the total physically contiguous memory size (the +default is 4MB). + 2) There is not enough physically contiguous memory available in the system. + 3) When exporting the RKNN model, add the following parameter to the config function: + + 37 + www.rock-chips.com + +output_optimize=1. + Users can try to restart the system, or configure a larger physically continuous memory space when + +the NPU driver is mounted. For the configuration method, refer to the rknn_inputs_map interface +description. + +6.1.3 API call process issues + +6.1.3.1 After rknn_init succeeds, can the memory occupied by the model file be + released? + + Yes,you can. + +6.1.3.2 When rknn_output.is_prealloc=1, does rknn_outputs_release need to be called? + + Yes, it needs. + +6.1.4 Performance issues + +6.1.4.1 rknn_init takes too long? + + Use pre-compiled models. Refer to the relevant chapters of the User Guide document under +https://github.com/rockchip-linux/rknn-toolkit/tree/master/doc for usage. + +6.1.4.2 rknn_inputs_set takes too long? + + The possible reason is the large amount of data or the time-consuming format conversion. If it takes +a long time to convert the format, users can try the pass_through usage to do the conversion themselves. +For conversion method, please refer to rknn_pass_through_demo example under +https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples, or try to export the RKNN +model by adding the following parameter to the config function: output_optimize=1. + + 38 + www.rock-chips.com + +6.1.4.3 rknn_outputs_get takes too long? + + The possible reason is the large amount of data or the time-consuming format conversion. If it takes +a long time to convert the format, users can try to set want_float=0 and do the conversion themselves, or +try to export the RKNN model by adding the following parameter to the config function: +output_optimize=1. + + 39 + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/include/rknn_runtime.h b/rknn_yolo_demo/libs/rklibs/rknn/include/rknn_runtime.h new file mode 100644 index 0000000..a114c1f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/include/rknn_runtime.h @@ -0,0 +1,504 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + + +#ifndef _RKNN_RUNTIME_H +#define _RKNN_RUNTIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + Definition of extended flag for rknn_init. +*/ +/* set high priority context. */ +#define RKNN_FLAG_PRIOR_HIGH 0x00000000 + +/* set medium priority context */ +#define RKNN_FLAG_PRIOR_MEDIUM 0x00000001 + +/* set low priority context. */ +#define RKNN_FLAG_PRIOR_LOW 0x00000002 + +/* asynchronous mode. + when enable, rknn_outputs_get will not block for too long because it directly retrieves the result of + the previous frame which can increase the frame rate on single-threaded mode, but at the cost of + rknn_outputs_get not retrieves the result of the current frame. + in multi-threaded mode you do not need to turn this mode on. */ +#define RKNN_FLAG_ASYNC_MASK 0x00000004 + +/* collect performance mode. + when enable, you can get detailed performance reports via rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, ...), + but it will reduce the frame rate. */ +#define RKNN_FLAG_COLLECT_PERF_MASK 0x00000008 + +/* + save pre-compile model. +*/ +#define RKNN_FLAG_PRECOMPILE_MASK 0x00000020 + +/* + Error code returned by the RKNN API. +*/ +#define RKNN_SUCC 0 /* execute succeed. */ +#define RKNN_ERR_FAIL -1 /* execute failed. */ +#define RKNN_ERR_TIMEOUT -2 /* execute timeout. */ +#define RKNN_ERR_DEVICE_UNAVAILABLE -3 /* device is unavailable. */ +#define RKNN_ERR_MALLOC_FAIL -4 /* memory malloc fail. */ +#define RKNN_ERR_PARAM_INVALID -5 /* parameter is invalid. */ +#define RKNN_ERR_MODEL_INVALID -6 /* model is invalid. */ +#define RKNN_ERR_CTX_INVALID -7 /* context is invalid. */ +#define RKNN_ERR_INPUT_INVALID -8 /* input is invalid. */ +#define RKNN_ERR_OUTPUT_INVALID -9 /* output is invalid. */ +#define RKNN_ERR_DEVICE_UNMATCH -10 /* the device is unmatch, please update rknn sdk + and npu driver/firmware. */ +#define RKNN_ERR_INCOMPATILE_PRE_COMPILE_MODEL -11 /* This RKNN model use pre_compile mode, but not compatible with current driver. */ +//add by chifred: for reporting optimization version bug info +#define RKNN_ERR_INCOMPATILE_OPTIMIZATION_LEVEL_VERSION -12 /* This RKNN model set optimization level, but not compatible with current driver. */ +#define RKNN_ERR_TARGET_PLATFORM_UNMATCH -13 /* This RKNN model set target platform, but not compatible with current platform. */ +//chifred add end +#define RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER -14 /* This RKNN model is not a pre-compiled model, but the npu driver is mini driver. */ + +/* + Definition for tensor +*/ +#define RKNN_MAX_DIMS 16 /* maximum dimension of tensor. */ +#define RKNN_MAX_NAME_LEN 256 /* maximum name lenth of tensor. */ + + + +#ifdef __arm__ +typedef uint32_t rknn_context; +#else +typedef uint64_t rknn_context; +#endif + +/* + The query command for rknn_query +*/ +typedef enum _rknn_query_cmd { + RKNN_QUERY_IN_OUT_NUM = 0, /* query the number of input & output tensor. */ + RKNN_QUERY_INPUT_ATTR, /* query the attribute of input tensor. */ + RKNN_QUERY_OUTPUT_ATTR, /* query the attribute of output tensor. */ + RKNN_QUERY_PERF_DETAIL, /* query the detail performance, need set + RKNN_FLAG_COLLECT_PERF_MASK when call rknn_init. */ + RKNN_QUERY_PERF_RUN, /* query the time of run. */ + RKNN_QUERY_SDK_VERSION, /* query the sdk & driver version */ + RKNN_QUERY_PRE_COMPILE, /* query the pre compile model */ + + RKNN_QUERY_CMD_MAX +} rknn_query_cmd; + +/* + the tensor data type. +*/ +typedef enum _rknn_tensor_type { + RKNN_TENSOR_FLOAT32 = 0, /* data type is float32. */ + RKNN_TENSOR_FLOAT16, /* data type is float16. */ + RKNN_TENSOR_INT8, /* data type is int8. */ + RKNN_TENSOR_UINT8, /* data type is uint8. */ + RKNN_TENSOR_INT16, /* data type is int16. */ + + RKNN_TENSOR_TYPE_MAX +} rknn_tensor_type; + +/* + the quantitative type. +*/ +typedef enum _rknn_tensor_qnt_type { + RKNN_TENSOR_QNT_NONE = 0, /* none. */ + RKNN_TENSOR_QNT_DFP, /* dynamic fixed point. */ + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC, /* asymmetric affine. */ + + RKNN_TENSOR_QNT_MAX +} rknn_tensor_qnt_type; + +/* + the tensor data format. +*/ +typedef enum _rknn_tensor_format { + RKNN_TENSOR_NCHW = 0, /* data format is NCHW. */ + RKNN_TENSOR_NHWC, /* data format is NHWC. */ + + RKNN_TENSOR_FORMAT_MAX +} rknn_tensor_format; + +/* + the information for RKNN_QUERY_IN_OUT_NUM. +*/ +typedef struct _rknn_input_output_num { + uint32_t n_input; /* the number of input. */ + uint32_t n_output; /* the number of output. */ +} rknn_input_output_num; + +/* + the information for RKNN_QUERY_INPUT_ATTR / RKNN_QUERY_OUTPUT_ATTR. +*/ +typedef struct _rknn_tensor_attr { + uint32_t index; /* input parameter, the index of input/output tensor, + need set before call rknn_query. */ + + uint32_t n_dims; /* the number of dimensions. */ + uint32_t dims[RKNN_MAX_DIMS]; /* the dimensions array. */ + char name[RKNN_MAX_NAME_LEN]; /* the name of tensor. */ + + uint32_t n_elems; /* the number of elements. */ + uint32_t size; /* the bytes size of tensor. */ + + rknn_tensor_format fmt; /* the data format of tensor. */ + rknn_tensor_type type; /* the data type of tensor. */ + rknn_tensor_qnt_type qnt_type; /* the quantitative type of tensor. */ + int8_t fl; /* fractional length for RKNN_TENSOR_QNT_DFP. */ + uint32_t zp; /* zero point for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ + float scale; /* scale for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ +} rknn_tensor_attr; + +/* + the information for RKNN_QUERY_PERF_DETAIL. +*/ +typedef struct _rknn_perf_detail { + char* perf_data; /* the string pointer of perf detail. don't need free it by user. */ + uint64_t data_len; /* the string length. */ +} rknn_perf_detail; + +/* + the information for RKNN_QUERY_PERF_RUN. +*/ +typedef struct _rknn_perf_run { + int64_t run_duration; /* real inference time (us) */ +} rknn_perf_run; + +/* + the information for RKNN_QUERY_SDK_VERSION. +*/ +typedef struct _rknn_sdk_version { + char api_version[256]; /* the version of rknn api. */ + char drv_version[256]; /* the version of rknn driver. */ +} rknn_sdk_version; + +/* + The flags of rknn_tensor_mem. +*/ +typedef enum _rknn_tensor_mem_flags { + RKNN_TENSOR_MEMORY_FLAGS_UNKNOWN = 0, + RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE = 1, /*Used to mark in rknn_destroy_mem() whether it is necessary to release the "mem" pointer itself. + If the flag RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE is set, rknn_destroy_mem() will call free(mem).*/ + +} rknn_tensor_mem_flags; + + +/* + the memory information of tensor. +*/ +typedef struct _rknn_tensor_memory { + void* logical_addr; /* the virtual address of tensor buffer. */ + uint64_t physical_addr; /* the physical address of tensor buffer. */ + int32_t fd; /* the fd of tensor buffer. */ + uint32_t size; /* the size of tensor buffer. */ + uint32_t handle; /* the handle tensor buffer. */ + void * priv_data; /* the data which is reserved. */ + uint64_t reserved_flag; /* the flag which is reserved. */ +} rknn_tensor_mem; + +/* + the input information for rknn_input_set. +*/ +typedef struct _rknn_input { + uint32_t index; /* the input index. */ + void* buf; /* the input buf for index. */ + uint32_t size; /* the size of input buf. */ + uint8_t pass_through; /* pass through mode. + if TRUE, the buf data is passed directly to the input node of the rknn model + without any conversion. the following variables do not need to be set. + if FALSE, the buf data is converted into an input consistent with the model + according to the following type and fmt. so the following variables + need to be set.*/ + rknn_tensor_type type; /* the data type of input buf. */ + rknn_tensor_format fmt; /* the data format of input buf. + currently the internal input format of NPU is NCHW by default. + so entering NCHW data can avoid the format conversion in the driver. */ +} rknn_input; + +/* + the output information for rknn_outputs_get. +*/ +typedef struct _rknn_output { + uint8_t want_float; /* want transfer output data to float */ + uint8_t is_prealloc; /* whether buf is pre-allocated. + if true, the following variables need to be set. + if false, The following variables do not need to be set. */ + uint32_t index; /* the output index. */ + void* buf; /* the output buf for index. + when is_prealloc = FALSE and rknn_outputs_release called, + this buf pointer will be free and don't use it anymore. */ + uint32_t size; /* the size of output buf. */ +} rknn_output; + +/* + the extend information for rknn_run. +*/ +typedef struct _rknn_run_extend { + uint64_t frame_id; /* output parameter, indicate current frame id of run. */ +} rknn_run_extend; + +/* + the extend information for rknn_outputs_get. +*/ +typedef struct _rknn_output_extend { + uint64_t frame_id; /* output parameter, indicate the frame id of outputs, corresponds to + struct rknn_run_extend.frame_id.*/ +} rknn_output_extend; + +/* + the information for RKNN_QUERY_RKNN_PRECOMPILE. +*/ +typedef struct _rknn_precompile { + void* model_data; /* the pointer of precompile model. don't need free it by user. */ + uint32_t data_len; /* the model length. */ +} rknn_precompile; + + +/* rknn_init + + initial the context and load the rknn model. + + input: + rknn_context* context the pointer of context handle. + void* model pointer to the rknn model. + uint32_t size the size of rknn model. + uint32_t flag extend flag, see the define of RKNN_FLAG_XXX_XXX. + return: + int error code. +*/ +int rknn_init(rknn_context* context, void* model, uint32_t size, uint32_t flag); + + +/* rknn_destroy + + unload the rknn model and destroy the context. + + input: + rknn_context context the handle of context. + return: + int error code. +*/ +int rknn_destroy(rknn_context context); + + +/* rknn_query + + query the information about model or others. see rknn_query_cmd. + + input: + rknn_context context the handle of context. + rknn_query_cmd cmd the command of query. + void* info the buffer point of information. + uint32_t size the size of information. + return: + int error code. +*/ +int rknn_query(rknn_context context, rknn_query_cmd cmd, void* info, uint32_t size); + + +/* rknn_inputs_set + + set inputs information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_input inputs[] the arrays of inputs information, see rknn_input. + return: + int error code +*/ +int rknn_inputs_set(rknn_context context, uint32_t n_inputs, rknn_input inputs[]); + + +/* rknn_inputs_map + + map inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_map(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_sync + + synchronize inputs tensor buffer by input index of rknn model. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_sync(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_unmap + + unmap inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_unmap(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_run + + run the model to execute inference. + + input: + rknn_context context the handle of context. + rknn_run_extend* extend the extend information of run. + return: + int error code. +*/ +int rknn_run(rknn_context context, rknn_run_extend* extend); + + +/* rknn_outputs_get + + wait the inference to finish and get the outputs. + this function will block until inference finish. + the results will set to outputs[]. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_output outputs[] the arrays of output, see rknn_output. + rknn_output_extend* the extend information of output. + return: + int error code. +*/ +int rknn_outputs_get(rknn_context context, uint32_t n_outputs, rknn_output outputs[], rknn_output_extend* extend); + + +/* rknn_outputs_release + + release the outputs that get by rknn_outputs_get. + after called, the rknn_output[x].buf get from rknn_outputs_get will + also be free when rknn_output[x].is_prealloc = FALSE. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_output outputs[] the arrays of output. + return: + int error code +*/ +int rknn_outputs_release(rknn_context context, uint32_t n_ouputs, rknn_output outputs[]); + + +/* rknn_outputs_map + + map the model output tensors memory information. + The difference between this function and "rknn_outputs_get" is + that it directly maps the model output tensor memory location to the user. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_map(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_sync + + synchronize the output tensors buffer to ensure cache cohenrency, wait the inference to finish. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_sync(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_unmap + + unmap the outputs memory information that get by rknn_outputs_map. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_outputs_unmap(rknn_context context, uint32_t n_ouputs, rknn_tensor_mem mem[]); + +/* rknn_create_mem (memory allocated inside) + + Create tensor memory. This API require libdrm support! + + input: + rknn_context ctx the handle of context. + uint64_t size the size of tensor buffer. + return: + rknn_tensor_mem the pointer of tensor memory information. +*/ +rknn_tensor_mem* rknn_create_mem(rknn_context ctx, uint64_t size); + +/* rknn_destroy_mem (support allocate inside and outside) + + destroy tensor memory. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the pointer of tensor memory information. + return: + int error code +*/ +int rknn_destroy_mem(rknn_context ctx, rknn_tensor_mem *mem); + + + +/* rknn_set_io_mem + + set the input and output tensors buffer. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the array of tensor memory information. + rknn_tensor_attr *attr the attribute of input or output tensor buffer. + return: + int error code. +*/ +int rknn_set_io_mem(rknn_context ctx, rknn_tensor_mem *mem, rknn_tensor_attr *attr); + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //_RKNN_RUNTIME_H diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/mobilenet_v1.rknn b/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/mobilenet_v1.rknn new file mode 100644 index 0000000..1a1ff1b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/mobilenet_v1.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/test.py b/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/test.py new file mode 100644 index 0000000..2484b68 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/python/example/mobilenet_v1/test.py @@ -0,0 +1,49 @@ +import numpy as np +import cv2 +from rknn.api import RKNN + +def show_outputs(outputs): + output = outputs[0][0] + output_sorted = sorted(output, reverse=True) + top5_str = 'mobilenet_v1\n-----TOP 5-----\n' + for i in range(5): + value = output_sorted[i] + index = np.where(output == value) + for j in range(len(index)): + if (i + j) >= 5: + break + if value > 0: + topi = '{}: {}\n'.format(index[j], value) + else: + topi = '-1: 0.0\n' + top5_str += topi + print(top5_str) + +if __name__ == '__main__': + + # Create RKNN object + rknn = RKNN() + + # Direct load rknn model + print('--> Loading RKNN model') + ret = rknn.load_rknn('./mobilenet_v1.rknn') + if ret != 0: + print('Load mobilenet_v1.rknn failed!') + exit(ret) + print('done') + + # Set inputs + img = cv2.imread('./dog_224x224.jpg') + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + + # Init Runtime + rknn.init_runtime() + + # Inference + print('--> Running model') + outputs = rknn.inference(inputs=[img]) + show_outputs(outputs) + print('done') + + rknn.release() + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/README b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/README new file mode 100644 index 0000000..7beab1a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/README @@ -0,0 +1 @@ +# RKNN \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/VERSION b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/VERSION new file mode 100644 index 0000000..d612b7f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/VERSION @@ -0,0 +1 @@ +0.9.7.1 diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/__init__.py b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/__init__.py new file mode 100644 index 0000000..cfc82a4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/__init__.py @@ -0,0 +1 @@ +from rknn import api diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/__init__.py b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/__init__.py new file mode 100644 index 0000000..5b98fb2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/__init__.py @@ -0,0 +1 @@ +from rknn.api.rknn import RKNN diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn.py b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn.py new file mode 100644 index 0000000..42b7e69 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn.py @@ -0,0 +1,130 @@ +# -*- coding:utf-8 -*- +import os +import sys +import traceback +import re + +from argparse import Namespace +from .rknn_base import RKNNBase +from .rknn_runtime import RKNNRuntime + +class RKNN: + """ + Rockchip NN SDK + """ + def __init__(self): + cur_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + self.rknn_base = RKNNBase(cur_path) + + def load_rknn(self, path): + """ + Load RKNN model + :param path: RKNN model file path + :return: success: 0, failure: -1 + """ + if not os.path.exists(path): + print('RKNN model file {} not exists!'.format(path)) + return -1 + try: + ret = self.rknn_base.import_rknn(path) + except: + print('Catch exception when loading RKNN model [{}]!'.format(path)) + RKNN._print_traceback(traceback.format_exc()) + return -1 + else: + if ret != 0: + print('Load RKNN model [{}] failed!'.format(path)) + return ret + + def init_runtime(self, perf_debug=False): + """ + Init run time environment. Needed by called before inference or eval performance. + :param perf_debug: enable dump layer performance. + :return: success: 0, failure: -1 + """ + try: + self.rknn_base.init_runtime(target=None, device_id=None, perf_debug=perf_debug) + except: + print('Catch exception when init runtime!') + RKNN._print_traceback(traceback.format_exc()) + return -1 + + return 0 + + def inference(self, inputs, data_type='uint8', data_format='nhwc', outputs=None): + """ + Run model inference + :param inputs: Input data List (ndarray list) + :param data_type: Input data type + :param data_format: Input data format + :param outputs: Output data list, for determine shape and dtype (empty ndarray) + :return: Output data (ndarray list) + """ + try: + results = self.rknn_base.inference(inputs=inputs, data_type=data_type, + data_format=data_format, outputs=outputs) + except: + print('Catch exception when inference!') + RKNN._print_traceback(traceback.format_exc()) + results = None + finally: + useless_file = os.path.join(os.getcwd(), 'viv_vir_cl_intrinsic_ImgLS.lib') + if os.path.exists(useless_file): + os.remove(useless_file) + return results + + + def eval_perf(self, inputs, data_type='uint8', data_format='nhwc', is_print=True): + """ + Evaluate model performance + :param inputs: Input data list (ndarray list) + :param data_type: Input data type + :param data_format: Input data format + :param is_print: Format print perf result + :return: Performance Result (dict) + """ + try: + perfs = self.rknn_base.eval_performance(inputs, data_type, data_format) + if perfs is None: + print('Error: Performance information is empty, some mistakes may happen.') + return perfs + if is_print: + print(self.rknn_base.format_perf_detail(detail=perfs)) + except: + print('Catch exception when evaluating model performance!') + RKNN._print_traceback(traceback.format_exc()) + return None + finally: + useless_file = os.path.join(os.getcwd(), 'viv_vir_cl_intrinsic_ImgLS.lib') + if os.path.exists(useless_file): + os.remove(useless_file) + + return perfs + + def get_sdk_version(self): + """ + Get SDK version + :return: sdk_version + """ + try: + sdk_version = self.rknn_base.get_sdk_version() + except Exception: + print('Catch exception when get sdk version') + RKNN._print_traceback(traceback.format_exc()) + return None + + return sdk_version + + def release(self): + """ + Release RKNN resource + :return: None + """ + self.rknn_base.release() + + @staticmethod + def _print_traceback(traceback_info): + reg = re.compile(re.escape(RKNNBase.redirect_src), re.IGNORECASE) + traceback_info = reg.sub(RKNNBase.redirect_dst, traceback_info) + print(traceback_info) + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_base.cpython-36m-aarch64-linux-gnu.so b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_base.cpython-36m-aarch64-linux-gnu.so new file mode 100644 index 0000000..f94360c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_base.cpython-36m-aarch64-linux-gnu.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_model.cpython-36m-aarch64-linux-gnu.so b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_model.cpython-36m-aarch64-linux-gnu.so new file mode 100644 index 0000000..533a9bb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_model.cpython-36m-aarch64-linux-gnu.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_runtime.cpython-36m-aarch64-linux-gnu.so b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_runtime.cpython-36m-aarch64-linux-gnu.so new file mode 100644 index 0000000..f98b431 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn/api/rknn_runtime.cpython-36m-aarch64-linux-gnu.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn1808-1.2.0-cp36-cp36m-linux_aarch64.whl b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn1808-1.2.0-cp36-cp36m-linux_aarch64.whl new file mode 100644 index 0000000..0b99684 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn1808-1.2.0-cp36-cp36m-linux_aarch64.whl differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/python/rknn1808-1.2.0-cp37-cp37m-linux_aarch64.whl b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn1808-1.2.0-cp37-cp37m-linux_aarch64.whl new file mode 100644 index 0000000..08ca084 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/python/rknn1808-1.2.0-cp37-cp37m-linux_aarch64.whl differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/CImg/CImg.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/CImg/CImg.h new file mode 100644 index 0000000..2bfe567 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/CImg/CImg.h @@ -0,0 +1,65138 @@ +/* + # + # File : CImg.h + # ( C++ header file ) + # + # Description : C++ Template Image Processing Toolkit. + # This file is the main component of the CImg Library project. + # ( http://cimg.eu ) + # + # Project manager : David Tschumperlé + # ( http://tschumperle.users.greyc.fr/ ) + # + # A complete list of contributors is available in file 'README.txt' + # distributed within the CImg package. + # + # Licenses : This file is 'dual-licensed', you have to choose one + # of the two licenses below to apply. + # + # CeCILL-C + # The CeCILL-C license is close to the GNU LGPL. + # ( http://cecill.info/licences/Licence_CeCILL-C_V1-en.html ) + # + # or CeCILL v2.1 + # The CeCILL license is compatible with the GNU GPL. + # ( http://cecill.info/licences/Licence_CeCILL_V2.1-en.html ) + # + # This software is governed either by the CeCILL or the CeCILL-C license + # under French law and abiding by the rules of distribution of free software. + # You can use, modify and or redistribute the software under the terms of + # the CeCILL or CeCILL-C licenses as circulated by CEA, CNRS and INRIA + # at the following URL: "http://cecill.info". + # + # As a counterpart to the access to the source code and rights to copy, + # modify and redistribute granted by the license, users are provided only + # with a limited warranty and the software's author, the holder of the + # economic rights, and the successive licensors have only limited + # liability. + # + # In this respect, the user's attention is drawn to the risks associated + # with loading, using, modifying and/or developing or reproducing the + # software by the user in light of its specific status of free software, + # that may mean that it is complicated to manipulate, and that also + # therefore means that it is reserved for developers and experienced + # professionals having in-depth computer knowledge. Users are therefore + # encouraged to load and test the software's suitability as regards their + # requirements in conditions enabling the security of their systems and/or + # data to be ensured and, more generally, to use and operate it in the + # same conditions as regards security. + # + # The fact that you are presently reading this means that you have had + # knowledge of the CeCILL and CeCILL-C licenses and that you accept its terms. + # +*/ + +// Set version number of the library. +#ifndef cimg_version +#define cimg_version 298 + +/*----------------------------------------------------------- + # + # Test and possibly auto-set CImg configuration variables + # and include required headers. + # + # If you find that the default configuration variables are + # not adapted to your system, you can override their values + # before including the header file "CImg.h" + # (use the #define directive). + # + ------------------------------------------------------------*/ + +// Include standard C++ headers. +// This is the minimal set of required headers to make CImg-based codes compile. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define cimg_str(x) #x +#define cimg_str2(x) cimg_str(x) + +// Detect/configure OS variables. +// +// Define 'cimg_OS' to: '0' for an unknown OS (will try to minize library dependencies). +// '1' for a Unix-like OS (Linux, Solaris, BSD, MacOSX, Irix, ...). +// '2' for Microsoft Windows. +// (auto-detection is performed if 'cimg_OS' is not set by the user). +#ifndef cimg_OS +#if defined(unix) || defined(__unix) || defined(__unix__) \ + || defined(linux) || defined(__linux) || defined(__linux__) \ + || defined(sun) || defined(__sun) \ + || defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined (__DragonFly__) \ + || defined(sgi) || defined(__sgi) \ + || defined(__OSX__) || defined(__MACOSX__) || defined(__APPLE__) \ + || defined(__CYGWIN__) +#define cimg_OS 1 +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +#define cimg_OS 2 +#else +#define cimg_OS 0 +#endif +#elif !(cimg_OS==0 || cimg_OS==1 || cimg_OS==2) +#error CImg Library: Invalid configuration variable 'cimg_OS'. +#error (correct values are '0 = unknown OS', '1 = Unix-like OS', '2 = Microsoft Windows'). +#endif +#ifndef cimg_date +#define cimg_date __DATE__ +#endif +#ifndef cimg_time +#define cimg_time __TIME__ +#endif + +// Disable silly warnings on some Microsoft VC++ compilers. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#pragma warning(disable:4244) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#pragma warning(disable:4319) +#pragma warning(disable:4512) +#pragma warning(disable:4571) +#pragma warning(disable:4640) +#pragma warning(disable:4706) +#pragma warning(disable:4710) +#pragma warning(disable:4800) +#pragma warning(disable:4804) +#pragma warning(disable:4820) +#pragma warning(disable:4996) + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#endif + +// Define correct string functions for each compiler and OS. +#if cimg_OS==2 && defined(_MSC_VER) +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#include +#if defined(__MACOSX__) || defined(__APPLE__) +#define cimg_sscanf cimg::_sscanf +#define cimg_sprintf cimg::_sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf snprintf +#define cimg_vsnprintf vsnprintf +#endif +#endif + +// Include OS-specific headers. +#if cimg_OS==1 +#include +#include +#include +#include +#include +#include +#elif cimg_OS==2 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#ifndef _WIN32_IE +#define _WIN32_IE 0x0400 +#endif +#include +#include +#include +enum {FALSE_WIN = 0}; +#endif + +// Look for C++11 features. +#ifndef cimg_use_cpp11 +#if __cplusplus>201100 +#define cimg_use_cpp11 1 +#else +#define cimg_use_cpp11 0 +#endif +#endif +#if cimg_use_cpp11==1 +#include +#include +#endif + +// Convenient macro to define pragma +#ifdef _MSC_VER +#define cimg_pragma(x) __pragma(x) +#else +#define cimg_pragma(x) _Pragma(#x) +#endif + +// Define own types 'cimg_long/ulong' and 'cimg_int64/uint64' to ensure portability. +// ( constrained to 'sizeof(cimg_ulong/cimg_long) = sizeof(void*)' and 'sizeof(cimg_int64/cimg_uint64)=8' ). +#if cimg_OS==2 + +#define cimg_uint64 unsigned __int64 +#define cimg_int64 __int64 +#define cimg_ulong UINT_PTR +#define cimg_long INT_PTR +#ifdef _MSC_VER +#define cimg_fuint64 "%I64u" +#define cimg_fint64 "%I64d" +#else +#define cimg_fuint64 "%llu" +#define cimg_fint64 "%lld" +#endif + +#else + +#if UINTPTR_MAX==0xffffffff || defined(__arm__) || defined(_M_ARM) || ((ULONG_MAX)==(UINT_MAX)) +#define cimg_uint64 unsigned long long +#define cimg_int64 long long +#define cimg_fuint64 "%llu" +#define cimg_fint64 "%lld" +#else +#define cimg_uint64 unsigned long +#define cimg_int64 long +#define cimg_fuint64 "%lu" +#define cimg_fint64 "%ld" +#endif + +#if defined(__arm__) || defined(_M_ARM) +#define cimg_ulong unsigned long long +#define cimg_long long long +#else +#define cimg_ulong unsigned long +#define cimg_long long +#endif + +#endif + +// Configure filename separator. +// +// Filename separator is set by default to '/', except for Windows where it is '\'. +#ifndef cimg_file_separator +#if cimg_OS==2 +#define cimg_file_separator '\\' +#else +#define cimg_file_separator '/' +#endif +#endif + +// Configure verbosity of output messages. +// +// Define 'cimg_verbosity' to: '0' to hide library messages (quiet mode). +// '1' to output library messages on the console. +// '2' to output library messages on a basic dialog window (default behavior). +// '3' to do as '1' + add extra warnings (may slow down the code!). +// '4' to do as '2' + add extra warnings (may slow down the code!). +// +// Define 'cimg_strict_warnings' to replace warning messages by exception throwns. +// +// Define 'cimg_use_vt100' to allow output of color messages on VT100-compatible terminals. +#ifndef cimg_verbosity +#if cimg_OS==2 +#define cimg_verbosity 2 +#else +#define cimg_verbosity 1 +#endif +#elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4) +#error CImg Library: Configuration variable 'cimg_verbosity' is badly defined. +#error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }). +#endif + +// Configure OpenMP support. +// (http://www.openmp.org) +// +// Define 'cimg_use_openmp' to enable OpenMP support (requires OpenMP 3.0+). +// +// OpenMP directives are used in many CImg functions to get +// advantages of multi-core CPUs. +#if !defined(cimg_use_openmp) +#ifdef _OPENMP +#define cimg_use_openmp 1 +#else +#define cimg_use_openmp 0 +#endif +#endif +#if cimg_use_openmp!=0 +#include +#define cimg_pragma_openmp(p) cimg_pragma(omp p) +#else +#define cimg_pragma_openmp(p) +#endif + +// Configure the 'abort' signal handler (does nothing by default). +// A typical signal handler can be defined in your own source like this: +// #define cimg_abort_test if (is_abort) throw CImgAbortException("") +// +// where 'is_abort' is a boolean variable defined somewhere in your code and reachable in the method. +// 'cimg_abort_test2' does the same but is called more often (in inner loops). +#if defined(cimg_abort_test) && cimg_use_openmp!=0 + +// Define abort macros to be used with OpenMP. +#ifndef _cimg_abort_init_openmp +#define _cimg_abort_init_openmp bool _cimg_abort_go_openmp = true; cimg::unused(_cimg_abort_go_openmp) +#endif +#ifndef _cimg_abort_try_openmp +#define _cimg_abort_try_openmp if (_cimg_abort_go_openmp) try +#endif +#ifndef _cimg_abort_catch_openmp +#define _cimg_abort_catch_openmp catch (CImgAbortException&) { cimg_pragma(omp atomic) _cimg_abort_go_openmp&=false; } +#endif +#ifndef _cimg_abort_catch_fill_openmp +#define _cimg_abort_catch_fill_openmp \ + catch (CImgException& e) { cimg_pragma(omp critical(abort)) CImg::string(e._message).move_to(is_error); \ + cimg_pragma(omp atomic) _cimg_abort_go_openmp&=false; } +#endif +#ifdef cimg_abort_test2 +#ifndef _cimg_abort_try_openmp2 +#define _cimg_abort_try_openmp2 _cimg_abort_try_openmp +#endif +#ifndef _cimg_abort_catch_openmp2 +#define _cimg_abort_catch_openmp2 _cimg_abort_catch_openmp +#endif +#endif +#endif + +#ifndef _cimg_abort_init_openmp +#define _cimg_abort_init_openmp +#endif +#ifndef _cimg_abort_try_openmp +#define _cimg_abort_try_openmp +#endif +#ifndef _cimg_abort_catch_openmp +#define _cimg_abort_catch_openmp +#endif +#ifndef _cimg_abort_try_openmp2 +#define _cimg_abort_try_openmp2 +#endif +#ifndef _cimg_abort_catch_openmp2 +#define _cimg_abort_catch_openmp2 +#endif +#ifndef _cimg_abort_catch_fill_openmp +#define _cimg_abort_catch_fill_openmp +#endif +#ifndef cimg_abort_init +#define cimg_abort_init +#endif +#ifndef cimg_abort_test +#define cimg_abort_test +#endif +#ifndef cimg_abort_test2 +#define cimg_abort_test2 +#endif + +// Configure display framework. +// +// Define 'cimg_display' to: '0' to disable display capabilities. +// '1' to use the X-Window framework (X11). +// '2' to use the Microsoft GDI32 framework. +#ifndef cimg_display +#if cimg_OS==0 +#define cimg_display 0 +#elif cimg_OS==1 +#define cimg_display 1 +#elif cimg_OS==2 +#define cimg_display 2 +#endif +#elif !(cimg_display==0 || cimg_display==1 || cimg_display==2) +#error CImg Library: Configuration variable 'cimg_display' is badly defined. +#error (should be { 0=none | 1=X-Window (X11) | 2=Microsoft GDI32 }). +#endif + +// Include display-specific headers. +#if cimg_display==1 +#include +#include +#include +#include +#ifdef cimg_use_xshm +#include +#include +#include +#endif +#ifdef cimg_use_xrandr +#include +#endif +#endif +#ifndef cimg_appname +#define cimg_appname "CImg" +#endif + +// Configure OpenCV support. +// (http://opencv.willowgarage.com/wiki/) +// +// Define 'cimg_use_opencv' to enable OpenCV support. +// +// OpenCV library may be used to access images from cameras +// (see method 'CImg::load_camera()'). +#ifdef cimg_use_opencv +#ifdef True +#undef True +#define _cimg_redefine_True +#endif +#ifdef False +#undef False +#define _cimg_redefine_False +#endif +#ifdef Status +#undef Status +#define _cimg_redefine_Status +#endif +#include +#include +#if CV_MAJOR_VERSION>=3 +#define _cimg_fourcc cv::VideoWriter::fourcc +#define _cimg_cap_prop_frame_width cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH +#define _cimg_cap_prop_frame_height cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT +#define _cimg_cap_prop_frame_count cv::VideoCaptureProperties::CAP_PROP_FRAME_COUNT +#else +#define _cimg_fourcc CV_FOURCC +#define _cimg_cap_prop_frame_width CV_CAP_PROP_FRAME_WIDTH +#define _cimg_cap_prop_frame_height CV_CAP_PROP_FRAME_HEIGHT +#define _cimg_cap_prop_frame_count CV_CAP_PROP_FRAME_COUNT +#endif +#endif + +// Configure LibPNG support. +// (http://www.libpng.org) +// +// Define 'cimg_use_png' to enable LibPNG support. +// +// PNG library may be used to get a native support of '.png' files. +// (see methods 'CImg::{load,save}_png()'. +#ifdef cimg_use_png +extern "C" { +#include "png.h" +} +#endif + +// Configure LibJPEG support. +// (http://en.wikipedia.org/wiki/Libjpeg) +// +// Define 'cimg_use_jpeg' to enable LibJPEG support. +// +// JPEG library may be used to get a native support of '.jpg' files. +// (see methods 'CImg::{load,save}_jpeg()'). +#ifdef cimg_use_jpeg +extern "C" { +#include "jpeglib.h" +#include "setjmp.h" +} +#endif + +// Configure LibTIFF support. +// (http://www.libtiff.org) +// +// Define 'cimg_use_tiff' to enable LibTIFF support. +// +// TIFF library may be used to get a native support of '.tif' files. +// (see methods 'CImg[List]::{load,save}_tiff()'). +#ifdef cimg_use_tiff +extern "C" { +#define uint64 uint64_hack_ +#define int64 int64_hack_ +#include "tiffio.h" +#undef uint64 +#undef int64 +} +#endif + +// Configure HEIF support +// (https://github.com/strukturag/libheif) +// +// Define 'cimg_use_heif' to enable HEIF support. +// +// HEIF library may be used to get a native support of '.heic' and '.avif' files. +// (see method 'CImg::load_heif()'). +#ifdef cimg_use_heif +#include +#endif + +// Configure LibMINC2 support. +// (http://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_File_Format_Reference) +// +// Define 'cimg_use_minc2' to enable LibMINC2 support. +// +// MINC2 library may be used to get a native support of '.mnc' files. +// (see methods 'CImg::{load,save}_minc2()'). +#ifdef cimg_use_minc2 +#include "minc_io_simple_volume.h" +#include "minc_1_simple.h" +#include "minc_1_simple_rw.h" +#endif + +// Configure Zlib support. +// (http://www.zlib.net) +// +// Define 'cimg_use_zlib' to enable Zlib support. +// +// Zlib library may be used to allow compressed data in '.cimgz' files +// (see methods 'CImg[List]::{load,save}_cimg()'). +#ifdef cimg_use_zlib +extern "C" { +#include "zlib.h" +} +#endif + +// Configure libcurl support. +// (http://curl.haxx.se/libcurl/) +// +// Define 'cimg_use_curl' to enable libcurl support. +// +// Libcurl may be used to get a native support of file downloading from the network. +// (see method 'cimg::load_network()'.) +#ifdef cimg_use_curl +#include "curl/curl.h" +#endif + +// Configure Magick++ support. +// (http://www.imagemagick.org/Magick++) +// +// Define 'cimg_use_magick' to enable Magick++ support. +// +// Magick++ library may be used to get a native support of various image file formats. +// (see methods 'CImg::{load,save}()'). +#ifdef cimg_use_magick +#include "Magick++.h" +#endif + +// Configure FFTW3 support. +// (http://www.fftw.org) +// +// Define 'cimg_use_fftw3' to enable libFFTW3 support. +// +// FFTW3 library may be used to efficiently compute the Fast Fourier Transform +// of image data, without restriction on the image size. +// (see method 'CImg[List]::FFT()'). +#ifdef cimg_use_fftw3 +extern "C" { +#include "fftw3.h" +} +#endif + +// Configure LibBoard support. +// (http://libboard.sourceforge.net/) +// +// Define 'cimg_use_board' to enable Board support. +// +// Board library may be used to draw 3D objects in vector-graphics canvas +// that can be saved as '.ps' or '.svg' files afterwards. +// (see method 'CImg::draw_object3d()'). +#ifdef cimg_use_board +#include "Board.h" +#endif + +// Configure OpenEXR support. +// (http://www.openexr.com/) +// +// Define 'cimg_use_openexr' to enable OpenEXR support. +// +// OpenEXR library may be used to get a native support of '.exr' files. +// (see methods 'CImg::{load,save}_exr()'). +#ifdef cimg_use_openexr +#if __GNUC__>=5 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wshadow" +#endif +#include "ImfRgbaFile.h" +#include "ImfInputFile.h" +#include "ImfChannelList.h" +#include "ImfMatrixAttribute.h" +#include "ImfArray.h" +#if __GNUC__>=5 +#pragma GCC diagnostic pop +#endif +#endif + +// Configure TinyEXR support. +// (https://github.com/syoyo/tinyexr) +// +// Define 'cimg_use_tinyexr' to enable TinyEXR support. +// +// TinyEXR is a small, single header-only library to load and save OpenEXR(.exr) images. +#ifdef cimg_use_tinyexr +#ifndef TINYEXR_IMPLEMENTATION +#define TINYEXR_IMPLEMENTATION +#endif +#include "tinyexr.h" +#endif + +// Lapack configuration. +// (http://www.netlib.org/lapack) +// +// Define 'cimg_use_lapack' to enable LAPACK support. +// +// Lapack library may be used in several CImg methods to speed up +// matrix computations (eigenvalues, inverse, ...). +#ifdef cimg_use_lapack +extern "C" { + extern void sgetrf_(int*, int*, float*, int*, int*, int*); + extern void sgetri_(int*, float*, int*, int*, float*, int*, int*); + extern void sgetrs_(char*, int*, int*, float*, int*, int*, float*, int*, int*); + extern void sgesvd_(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*); + extern void ssyev_(char*, char*, int*, float*, int*, float*, float*, int*, int*); + extern void dgetrf_(int*, int*, double*, int*, int*, int*); + extern void dgetri_(int*, double*, int*, int*, double*, int*, int*); + extern void dgetrs_(char*, int*, int*, double*, int*, int*, double*, int*, int*); + extern void dgesvd_(char*, char*, int*, int*, double*, int*, double*, double*, + int*, double*, int*, double*, int*, int*); + extern void dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*); + extern void dgels_(char*, int*,int*,int*,double*,int*,double*,int*,double*,int*,int*); + extern void sgels_(char*, int*,int*,int*,float*,int*,float*,int*,float*,int*,int*); +} +#endif + +// Check if min/max/PI macros are defined. +// +// CImg does not compile if macros 'min', 'max' or 'PI' are defined, +// because it redefines functions min(), max() and const variable PI in the cimg:: namespace. +// so it '#undef' these macros if necessary, and restore them to reasonable +// values at the end of this file. +#ifdef min +#undef min +#define _cimg_redefine_min +#endif +#ifdef max +#undef max +#define _cimg_redefine_max +#endif +#ifdef PI +#undef PI +#define _cimg_redefine_PI +#endif + +// Define 'cimg_library' namespace suffix. +// +// You may want to add a suffix to the 'cimg_library' namespace, for instance if you need to work +// with several versions of the library at the same time. +#ifdef cimg_namespace_suffix +#define __cimg_library_suffixed(s) cimg_library_##s +#define _cimg_library_suffixed(s) __cimg_library_suffixed(s) +#define cimg_library_suffixed _cimg_library_suffixed(cimg_namespace_suffix) +#else +#define cimg_library_suffixed cimg_library +#endif + +/*------------------------------------------------------------------------------ + # + # Define user-friendly macros. + # + # These CImg macros are prefixed by 'cimg_' and can be used safely in your own + # code. They are useful to parse command line options, or to write image loops. + # + ------------------------------------------------------------------------------*/ + +// Macros to define program usage, and retrieve command line arguments. +#define cimg_usage(usage) cimg_library_suffixed::cimg::option((char*)0,argc,argv,(char*)0,usage,false) +#define cimg_help(str) cimg_library_suffixed::cimg::option((char*)0,argc,argv,str,(char*)0) +#define cimg_option(name,_default,usage) cimg_library_suffixed::cimg::option(name,argc,argv,_default,usage) + +// Macros to define and manipulate local neighborhoods. +#define CImg_2x2(I,T) T I[4]; \ + T& I##cc = I[0]; T& I##nc = I[1]; \ + T& I##cn = I[2]; T& I##nn = I[3]; \ + I##cc = I##nc = \ + I##cn = I##nn = 0 + +#define CImg_3x3(I,T) T I[9]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; \ + T& I##pc = I[3]; T& I##cc = I[4]; T& I##nc = I[5]; \ + T& I##pn = I[6]; T& I##cn = I[7]; T& I##nn = I[8]; \ + I##pp = I##cp = I##np = \ + I##pc = I##cc = I##nc = \ + I##pn = I##cn = I##nn = 0 + +#define CImg_4x4(I,T) T I[16]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; T& I##ap = I[3]; \ + T& I##pc = I[4]; T& I##cc = I[5]; T& I##nc = I[6]; T& I##ac = I[7]; \ + T& I##pn = I[8]; T& I##cn = I[9]; T& I##nn = I[10]; T& I##an = I[11]; \ + T& I##pa = I[12]; T& I##ca = I[13]; T& I##na = I[14]; T& I##aa = I[15]; \ + I##pp = I##cp = I##np = I##ap = \ + I##pc = I##cc = I##nc = I##ac = \ + I##pn = I##cn = I##nn = I##an = \ + I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_5x5(I,T) T I[25]; \ + T& I##bb = I[0]; T& I##pb = I[1]; T& I##cb = I[2]; T& I##nb = I[3]; T& I##ab = I[4]; \ + T& I##bp = I[5]; T& I##pp = I[6]; T& I##cp = I[7]; T& I##np = I[8]; T& I##ap = I[9]; \ + T& I##bc = I[10]; T& I##pc = I[11]; T& I##cc = I[12]; T& I##nc = I[13]; T& I##ac = I[14]; \ + T& I##bn = I[15]; T& I##pn = I[16]; T& I##cn = I[17]; T& I##nn = I[18]; T& I##an = I[19]; \ + T& I##ba = I[20]; T& I##pa = I[21]; T& I##ca = I[22]; T& I##na = I[23]; T& I##aa = I[24]; \ + I##bb = I##pb = I##cb = I##nb = I##ab = \ + I##bp = I##pp = I##cp = I##np = I##ap = \ + I##bc = I##pc = I##cc = I##nc = I##ac = \ + I##bn = I##pn = I##cn = I##nn = I##an = \ + I##ba = I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_2x2x2(I,T) T I[8]; \ + T& I##ccc = I[0]; T& I##ncc = I[1]; \ + T& I##cnc = I[2]; T& I##nnc = I[3]; \ + T& I##ccn = I[4]; T& I##ncn = I[5]; \ + T& I##cnn = I[6]; T& I##nnn = I[7]; \ + I##ccc = I##ncc = \ + I##cnc = I##nnc = \ + I##ccn = I##ncn = \ + I##cnn = I##nnn = 0 + +#define CImg_3x3x3(I,T) T I[27]; \ + T& I##ppp = I[0]; T& I##cpp = I[1]; T& I##npp = I[2]; \ + T& I##pcp = I[3]; T& I##ccp = I[4]; T& I##ncp = I[5]; \ + T& I##pnp = I[6]; T& I##cnp = I[7]; T& I##nnp = I[8]; \ + T& I##ppc = I[9]; T& I##cpc = I[10]; T& I##npc = I[11]; \ + T& I##pcc = I[12]; T& I##ccc = I[13]; T& I##ncc = I[14]; \ + T& I##pnc = I[15]; T& I##cnc = I[16]; T& I##nnc = I[17]; \ + T& I##ppn = I[18]; T& I##cpn = I[19]; T& I##npn = I[20]; \ + T& I##pcn = I[21]; T& I##ccn = I[22]; T& I##ncn = I[23]; \ + T& I##pnn = I[24]; T& I##cnn = I[25]; T& I##nnn = I[26]; \ + I##ppp = I##cpp = I##npp = \ + I##pcp = I##ccp = I##ncp = \ + I##pnp = I##cnp = I##nnp = \ + I##ppc = I##cpc = I##npc = \ + I##pcc = I##ccc = I##ncc = \ + I##pnc = I##cnc = I##nnc = \ + I##ppn = I##cpn = I##npn = \ + I##pcn = I##ccn = I##ncn = \ + I##pnn = I##cnn = I##nnn = 0 + +#define cimg_def2x2(img,x,y) \ + int _n1##x = x<(img).width() - 1?x + 1:(img).width() - 1, \ + _n1##y = y<(img).height() - 1?y + 1:(img).height() - 1 + +#define cimg_def3x3(img,x,y) \ + cimg_def2x2(img,x,y); \ + int _p1##x = x>1?x - 1:0, \ + _p1##y = y>1?y - 1:0 + +#define cimg_def4x4(img,x,y) \ + cimg_def3x3(img,x,y); \ + int _n2##x = x<(img).width() - 2?x + 2:(img).width() - 1, \ + _n2##y = y<(img).height() - 2?y + 2:(img).height() - 1 + +#define cimg_def5x5(img,x,y) \ + cimg_def4x4(img,x,y); \ + int _p2##x = x>2?x - 2:0, \ + _p2##y = y>2?y - 2:0 + +#define cimg_def6x6(img,x,y) \ + cimg_def5x5(img,x,y); \ + int _n3##x = x<(img).width() - 3?x + 3:(img).width() - 1, \ + _n3##y = y<(img).height() - 3?y + 3:(img).height() - 1 + +#define cimg_def7x7(img,x,y) \ + cimg_def6x6(img,x,y); \ + int _p3##x = x>3?x - 3:0, \ + _p3##y = y>3?y - 3:0 + +#define cimg_def8x8(img,x,y) \ + cimg_def7x7(img,x,y); \ + int _n4##x = x<(img).width() - 4?x + 4:(img).width() - 1, \ + _n4##y = y<(img).height() - 4?y + 4:(img).height() - 1 + +#define cimg_def9x9(img,x,y) \ + cimg_def8x8(img,x,y); \ + int _p4##x = x>4?x - 4:0, \ + _p4##y = y>4?y - 4:0 + +#define cimg_def2x2x2(img,x,y,z) \ + cimg_def2x2(img,x,y); \ + int _n1##z = z<(img).depth() - 1?z + 1:(img).depth() - 1 + +#define cimg_def3x3x3(img,x,y,z) \ + cimg_def2x2x2(img,x,y,z); \ + int _p1##x = x>1?x - 1:0, \ + _p1##y = y>1?y - 1:0, \ + _p1##z = z>1?z - 1:0 + +#define cimg_get2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_p1##x,y,z,c), I[4] = (T)(img)(x,y,z,c), I[5] = (T)(img)(_n1##x,y,z,c), \ + I[6] = (T)(img)(_p1##x,_n1##y,z,c), I[7] = (T)(img)(x,_n1##y,z,c), I[8] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get4x4(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_n2##x,_p1##y,z,c), I[4] = (T)(img)(_p1##x,y,z,c), I[5] = (T)(img)(x,y,z,c), \ + I[6] = (T)(img)(_n1##x,y,z,c), I[7] = (T)(img)(_n2##x,y,z,c), I[8] = (T)(img)(_p1##x,_n1##y,z,c), \ + I[9] = (T)(img)(x,_n1##y,z,c), I[10] = (T)(img)(_n1##x,_n1##y,z,c), I[11] = (T)(img)(_n2##x,_n1##y,z,c), \ + I[12] = (T)(img)(_p1##x,_n2##y,z,c), I[13] = (T)(img)(x,_n2##y,z,c), I[14] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[15] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get5x5(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[6] = (T)(img)(_p1##x,_p1##y,z,c), I[7] = (T)(img)(x,_p1##y,z,c), I[8] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[9] = (T)(img)(_n2##x,_p1##y,z,c), I[10] = (T)(img)(_p2##x,y,z,c), I[11] = (T)(img)(_p1##x,y,z,c), \ + I[12] = (T)(img)(x,y,z,c), I[13] = (T)(img)(_n1##x,y,z,c), I[14] = (T)(img)(_n2##x,y,z,c), \ + I[15] = (T)(img)(_p2##x,_n1##y,z,c), I[16] = (T)(img)(_p1##x,_n1##y,z,c), I[17] = (T)(img)(x,_n1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_n1##y,z,c), I[19] = (T)(img)(_n2##x,_n1##y,z,c), I[20] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_n2##y,z,c), I[22] = (T)(img)(x,_n2##y,z,c), I[23] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get6x6(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[6] = (T)(img)(_p2##x,_p1##y,z,c), I[7] = (T)(img)(_p1##x,_p1##y,z,c), I[8] = (T)(img)(x,_p1##y,z,c), \ + I[9] = (T)(img)(_n1##x,_p1##y,z,c), I[10] = (T)(img)(_n2##x,_p1##y,z,c), I[11] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[12] = (T)(img)(_p2##x,y,z,c), I[13] = (T)(img)(_p1##x,y,z,c), I[14] = (T)(img)(x,y,z,c), \ + I[15] = (T)(img)(_n1##x,y,z,c), I[16] = (T)(img)(_n2##x,y,z,c), I[17] = (T)(img)(_n3##x,y,z,c), \ + I[18] = (T)(img)(_p2##x,_n1##y,z,c), I[19] = (T)(img)(_p1##x,_n1##y,z,c), I[20] = (T)(img)(x,_n1##y,z,c), \ + I[21] = (T)(img)(_n1##x,_n1##y,z,c), I[22] = (T)(img)(_n2##x,_n1##y,z,c), I[23] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[24] = (T)(img)(_p2##x,_n2##y,z,c), I[25] = (T)(img)(_p1##x,_n2##y,z,c), I[26] = (T)(img)(x,_n2##y,z,c), \ + I[27] = (T)(img)(_n1##x,_n2##y,z,c), I[28] = (T)(img)(_n2##x,_n2##y,z,c), I[29] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[30] = (T)(img)(_p2##x,_n3##y,z,c), I[31] = (T)(img)(_p1##x,_n3##y,z,c), I[32] = (T)(img)(x,_n3##y,z,c), \ + I[33] = (T)(img)(_n1##x,_n3##y,z,c), I[34] = (T)(img)(_n2##x,_n3##y,z,c), I[35] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get7x7(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_p3##x,_p2##y,z,c), I[8] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p1##x,_p2##y,z,c), I[10] = (T)(img)(x,_p2##y,z,c), I[11] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[12] = (T)(img)(_n2##x,_p2##y,z,c), I[13] = (T)(img)(_n3##x,_p2##y,z,c), I[14] = (T)(img)(_p3##x,_p1##y,z,c), \ + I[15] = (T)(img)(_p2##x,_p1##y,z,c), I[16] = (T)(img)(_p1##x,_p1##y,z,c), I[17] = (T)(img)(x,_p1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_p1##y,z,c), I[19] = (T)(img)(_n2##x,_p1##y,z,c), I[20] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[21] = (T)(img)(_p3##x,y,z,c), I[22] = (T)(img)(_p2##x,y,z,c), I[23] = (T)(img)(_p1##x,y,z,c), \ + I[24] = (T)(img)(x,y,z,c), I[25] = (T)(img)(_n1##x,y,z,c), I[26] = (T)(img)(_n2##x,y,z,c), \ + I[27] = (T)(img)(_n3##x,y,z,c), I[28] = (T)(img)(_p3##x,_n1##y,z,c), I[29] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_n1##y,z,c), I[31] = (T)(img)(x,_n1##y,z,c), I[32] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_n1##y,z,c), I[34] = (T)(img)(_n3##x,_n1##y,z,c), I[35] = (T)(img)(_p3##x,_n2##y,z,c), \ + I[36] = (T)(img)(_p2##x,_n2##y,z,c), I[37] = (T)(img)(_p1##x,_n2##y,z,c), I[38] = (T)(img)(x,_n2##y,z,c), \ + I[39] = (T)(img)(_n1##x,_n2##y,z,c), I[40] = (T)(img)(_n2##x,_n2##y,z,c), I[41] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p3##x,_n3##y,z,c), I[43] = (T)(img)(_p2##x,_n3##y,z,c), I[44] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[45] = (T)(img)(x,_n3##y,z,c), I[46] = (T)(img)(_n1##x,_n3##y,z,c), I[47] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[48] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get8x8(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_n4##x,_p3##y,z,c), I[8] = (T)(img)(_p3##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p2##x,_p2##y,z,c), I[10] = (T)(img)(_p1##x,_p2##y,z,c), I[11] = (T)(img)(x,_p2##y,z,c), \ + I[12] = (T)(img)(_n1##x,_p2##y,z,c), I[13] = (T)(img)(_n2##x,_p2##y,z,c), I[14] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[15] = (T)(img)(_n4##x,_p2##y,z,c), I[16] = (T)(img)(_p3##x,_p1##y,z,c), I[17] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[18] = (T)(img)(_p1##x,_p1##y,z,c), I[19] = (T)(img)(x,_p1##y,z,c), I[20] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[21] = (T)(img)(_n2##x,_p1##y,z,c), I[22] = (T)(img)(_n3##x,_p1##y,z,c), I[23] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[24] = (T)(img)(_p3##x,y,z,c), I[25] = (T)(img)(_p2##x,y,z,c), I[26] = (T)(img)(_p1##x,y,z,c), \ + I[27] = (T)(img)(x,y,z,c), I[28] = (T)(img)(_n1##x,y,z,c), I[29] = (T)(img)(_n2##x,y,z,c), \ + I[30] = (T)(img)(_n3##x,y,z,c), I[31] = (T)(img)(_n4##x,y,z,c), I[32] = (T)(img)(_p3##x,_n1##y,z,c), \ + I[33] = (T)(img)(_p2##x,_n1##y,z,c), I[34] = (T)(img)(_p1##x,_n1##y,z,c), I[35] = (T)(img)(x,_n1##y,z,c), \ + I[36] = (T)(img)(_n1##x,_n1##y,z,c), I[37] = (T)(img)(_n2##x,_n1##y,z,c), I[38] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[39] = (T)(img)(_n4##x,_n1##y,z,c), I[40] = (T)(img)(_p3##x,_n2##y,z,c), I[41] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p1##x,_n2##y,z,c), I[43] = (T)(img)(x,_n2##y,z,c), I[44] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[45] = (T)(img)(_n2##x,_n2##y,z,c), I[46] = (T)(img)(_n3##x,_n2##y,z,c), I[47] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[48] = (T)(img)(_p3##x,_n3##y,z,c), I[49] = (T)(img)(_p2##x,_n3##y,z,c), I[50] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[51] = (T)(img)(x,_n3##y,z,c), I[52] = (T)(img)(_n1##x,_n3##y,z,c), I[53] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[54] = (T)(img)(_n3##x,_n3##y,z,c), I[55] = (T)(img)(_n4##x,_n3##y,z,c), I[56] = (T)(img)(_p3##x,_n4##y,z,c), \ + I[57] = (T)(img)(_p2##x,_n4##y,z,c), I[58] = (T)(img)(_p1##x,_n4##y,z,c), I[59] = (T)(img)(x,_n4##y,z,c), \ + I[60] = (T)(img)(_n1##x,_n4##y,z,c), I[61] = (T)(img)(_n2##x,_n4##y,z,c), I[62] = (T)(img)(_n3##x,_n4##y,z,c), \ + I[63] = (T)(img)(_n4##x,_n4##y,z,c); + +#define cimg_get9x9(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p4##x,_p4##y,z,c), I[1] = (T)(img)(_p3##x,_p4##y,z,c), I[2] = (T)(img)(_p2##x,_p4##y,z,c), \ + I[3] = (T)(img)(_p1##x,_p4##y,z,c), I[4] = (T)(img)(x,_p4##y,z,c), I[5] = (T)(img)(_n1##x,_p4##y,z,c), \ + I[6] = (T)(img)(_n2##x,_p4##y,z,c), I[7] = (T)(img)(_n3##x,_p4##y,z,c), I[8] = (T)(img)(_n4##x,_p4##y,z,c), \ + I[9] = (T)(img)(_p4##x,_p3##y,z,c), I[10] = (T)(img)(_p3##x,_p3##y,z,c), I[11] = (T)(img)(_p2##x,_p3##y,z,c), \ + I[12] = (T)(img)(_p1##x,_p3##y,z,c), I[13] = (T)(img)(x,_p3##y,z,c), I[14] = (T)(img)(_n1##x,_p3##y,z,c), \ + I[15] = (T)(img)(_n2##x,_p3##y,z,c), I[16] = (T)(img)(_n3##x,_p3##y,z,c), I[17] = (T)(img)(_n4##x,_p3##y,z,c), \ + I[18] = (T)(img)(_p4##x,_p2##y,z,c), I[19] = (T)(img)(_p3##x,_p2##y,z,c), I[20] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_p2##y,z,c), I[22] = (T)(img)(x,_p2##y,z,c), I[23] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_p2##y,z,c), I[25] = (T)(img)(_n3##x,_p2##y,z,c), I[26] = (T)(img)(_n4##x,_p2##y,z,c), \ + I[27] = (T)(img)(_p4##x,_p1##y,z,c), I[28] = (T)(img)(_p3##x,_p1##y,z,c), I[29] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_p1##y,z,c), I[31] = (T)(img)(x,_p1##y,z,c), I[32] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_p1##y,z,c), I[34] = (T)(img)(_n3##x,_p1##y,z,c), I[35] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[36] = (T)(img)(_p4##x,y,z,c), I[37] = (T)(img)(_p3##x,y,z,c), I[38] = (T)(img)(_p2##x,y,z,c), \ + I[39] = (T)(img)(_p1##x,y,z,c), I[40] = (T)(img)(x,y,z,c), I[41] = (T)(img)(_n1##x,y,z,c), \ + I[42] = (T)(img)(_n2##x,y,z,c), I[43] = (T)(img)(_n3##x,y,z,c), I[44] = (T)(img)(_n4##x,y,z,c), \ + I[45] = (T)(img)(_p4##x,_n1##y,z,c), I[46] = (T)(img)(_p3##x,_n1##y,z,c), I[47] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[48] = (T)(img)(_p1##x,_n1##y,z,c), I[49] = (T)(img)(x,_n1##y,z,c), I[50] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[51] = (T)(img)(_n2##x,_n1##y,z,c), I[52] = (T)(img)(_n3##x,_n1##y,z,c), I[53] = (T)(img)(_n4##x,_n1##y,z,c), \ + I[54] = (T)(img)(_p4##x,_n2##y,z,c), I[55] = (T)(img)(_p3##x,_n2##y,z,c), I[56] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[57] = (T)(img)(_p1##x,_n2##y,z,c), I[58] = (T)(img)(x,_n2##y,z,c), I[59] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[60] = (T)(img)(_n2##x,_n2##y,z,c), I[61] = (T)(img)(_n3##x,_n2##y,z,c), I[62] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[63] = (T)(img)(_p4##x,_n3##y,z,c), I[64] = (T)(img)(_p3##x,_n3##y,z,c), I[65] = (T)(img)(_p2##x,_n3##y,z,c), \ + I[66] = (T)(img)(_p1##x,_n3##y,z,c), I[67] = (T)(img)(x,_n3##y,z,c), I[68] = (T)(img)(_n1##x,_n3##y,z,c), \ + I[69] = (T)(img)(_n2##x,_n3##y,z,c), I[70] = (T)(img)(_n3##x,_n3##y,z,c), I[71] = (T)(img)(_n4##x,_n3##y,z,c), \ + I[72] = (T)(img)(_p4##x,_n4##y,z,c), I[73] = (T)(img)(_p3##x,_n4##y,z,c), I[74] = (T)(img)(_p2##x,_n4##y,z,c), \ + I[75] = (T)(img)(_p1##x,_n4##y,z,c), I[76] = (T)(img)(x,_n4##y,z,c), I[77] = (T)(img)(_n1##x,_n4##y,z,c), \ + I[78] = (T)(img)(_n2##x,_n4##y,z,c), I[79] = (T)(img)(_n3##x,_n4##y,z,c), I[80] = (T)(img)(_n4##x,_n4##y,z,c) + +#define cimg_get2x2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c), I[4] = (T)(img)(x,y,_n1##z,c), I[5] = (T)(img)(_n1##x,y,_n1##z,c), \ + I[6] = (T)(img)(x,_n1##y,_n1##z,c), I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +#define cimg_get3x3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c), I[1] = (T)(img)(x,_p1##y,_p1##z,c), \ + I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c), I[3] = (T)(img)(_p1##x,y,_p1##z,c), I[4] = (T)(img)(x,y,_p1##z,c), \ + I[5] = (T)(img)(_n1##x,y,_p1##z,c), I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c), I[7] = (T)(img)(x,_n1##y,_p1##z,c), \ + I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c), I[9] = (T)(img)(_p1##x,_p1##y,z,c), I[10] = (T)(img)(x,_p1##y,z,c), \ + I[11] = (T)(img)(_n1##x,_p1##y,z,c), I[12] = (T)(img)(_p1##x,y,z,c), I[13] = (T)(img)(x,y,z,c), \ + I[14] = (T)(img)(_n1##x,y,z,c), I[15] = (T)(img)(_p1##x,_n1##y,z,c), I[16] = (T)(img)(x,_n1##y,z,c), \ + I[17] = (T)(img)(_n1##x,_n1##y,z,c), I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c), I[19] = (T)(img)(x,_p1##y,_n1##z,c), \ + I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c), I[21] = (T)(img)(_p1##x,y,_n1##z,c), I[22] = (T)(img)(x,y,_n1##z,c), \ + I[23] = (T)(img)(_n1##x,y,_n1##z,c), I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c), I[25] = (T)(img)(x,_n1##y,_n1##z,c), \ + I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +// Macros to perform various image loops. +// +// These macros are simpler to use than loops with C++ iterators. +#define cimg_for(img,ptrs,T_ptrs) \ + for (T_ptrs *ptrs = (img)._data, *_max##ptrs = (img)._data + (img).size(); ptrs<_max##ptrs; ++ptrs) +#define cimg_rof(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size() - 1; ptrs>=(img)._data; --ptrs) +#define cimg_foroff(img,off) for (cimg_ulong off = 0, _max##off = (img).size(); off<_max##off; ++off) +#define cimg_rofoff(img,off) for (cimg_long off = (cimg_long)((img).size() - 1); off>=0; --off) + +#define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i) +#define cimg_forX(img,x) cimg_for1((img)._width,x) +#define cimg_forY(img,y) cimg_for1((img)._height,y) +#define cimg_forZ(img,z) cimg_for1((img)._depth,z) +#define cimg_forC(img,c) cimg_for1((img)._spectrum,c) +#define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x) +#define cimg_forXZ(img,x,z) cimg_forZ(img,z) cimg_forX(img,x) +#define cimg_forYZ(img,y,z) cimg_forZ(img,z) cimg_forY(img,y) +#define cimg_forXC(img,x,c) cimg_forC(img,c) cimg_forX(img,x) +#define cimg_forYC(img,y,c) cimg_forC(img,c) cimg_forY(img,y) +#define cimg_forZC(img,z,c) cimg_forC(img,c) cimg_forZ(img,z) +#define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y) +#define cimg_forXYC(img,x,y,c) cimg_forC(img,c) cimg_forXY(img,x,y) +#define cimg_forXZC(img,x,z,c) cimg_forC(img,c) cimg_forXZ(img,x,z) +#define cimg_forYZC(img,y,z,c) cimg_forC(img,c) cimg_forYZ(img,y,z) +#define cimg_forXYZC(img,x,y,z,c) cimg_forC(img,c) cimg_forXYZ(img,x,y,z) + +#define cimg_rof1(bound,i) for (int i = (int)(bound) - 1; i>=0; --i) +#define cimg_rofX(img,x) cimg_rof1((img)._width,x) +#define cimg_rofY(img,y) cimg_rof1((img)._height,y) +#define cimg_rofZ(img,z) cimg_rof1((img)._depth,z) +#define cimg_rofC(img,c) cimg_rof1((img)._spectrum,c) +#define cimg_rofXY(img,x,y) cimg_rofY(img,y) cimg_rofX(img,x) +#define cimg_rofXZ(img,x,z) cimg_rofZ(img,z) cimg_rofX(img,x) +#define cimg_rofYZ(img,y,z) cimg_rofZ(img,z) cimg_rofY(img,y) +#define cimg_rofXC(img,x,c) cimg_rofC(img,c) cimg_rofX(img,x) +#define cimg_rofYC(img,y,c) cimg_rofC(img,c) cimg_rofY(img,y) +#define cimg_rofZC(img,z,c) cimg_rofC(img,c) cimg_rofZ(img,z) +#define cimg_rofXYZ(img,x,y,z) cimg_rofZ(img,z) cimg_rofXY(img,x,y) +#define cimg_rofXYC(img,x,y,c) cimg_rofC(img,c) cimg_rofXY(img,x,y) +#define cimg_rofXZC(img,x,z,c) cimg_rofC(img,c) cimg_rofXZ(img,x,z) +#define cimg_rofYZC(img,y,z,c) cimg_rofC(img,c) cimg_rofYZ(img,y,z) +#define cimg_rofXYZC(img,x,y,z,c) cimg_rofC(img,c) cimg_rofXYZ(img,x,y,z) + +#define cimg_for_in1(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), _max##i = (int)(i1)<(int)(bound)?(int)(i1):(int)(bound) - 1; i<=_max##i; ++i) +#define cimg_for_inX(img,x0,x1,x) cimg_for_in1((img)._width,x0,x1,x) +#define cimg_for_inY(img,y0,y1,y) cimg_for_in1((img)._height,y0,y1,y) +#define cimg_for_inZ(img,z0,z1,z) cimg_for_in1((img)._depth,z0,z1,z) +#define cimg_for_inC(img,c0,c1,c) cimg_for_in1((img)._spectrum,c0,c1,c) +#define cimg_for_inXY(img,x0,y0,x1,y1,x,y) cimg_for_inY(img,y0,y1,y) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXZ(img,x0,z0,x1,z1,x,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXC(img,x0,c0,x1,c1,x,c) cimg_for_inC(img,c0,c1,c) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inYZ(img,y0,z0,y1,z1,y,z) cimg_for_inZ(img,x0,z1,z) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inYC(img,y0,c0,y1,c1,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inZC(img,z0,c0,z1,c1,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inZ(img,z0,z1,z) +#define cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXZ(img,x0,z0,x1,z1,x,z) +#define cimg_for_inYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inYZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_inXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_inC(img,c0,c1,c) cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_insideX(img,x,n) cimg_for_inX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_insideY(img,y,n) cimg_for_inY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_insideZ(img,z,n) cimg_for_inZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_insideC(img,c,n) cimg_for_inC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_insideXY(img,x,y,n) cimg_for_inXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_insideXYZ(img,x,y,z,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_insideXYZC(img,x,y,z,c,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) + +#define cimg_for_out1(boundi,i0,i1,i) \ + for (int i = (int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); ++i, i = i==(int)(i0)?(int)(i1) + 1:i) +#define cimg_for_out2(boundi,boundj,i0,j0,i1,j1,i,j) \ + for (int j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out3(boundi,boundj,boundk,i0,j0,k0,i1,j1,k1,i,j,k) \ + for (int k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j || _n1k?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out4(boundi,boundj,boundk,boundl,i0,j0,k0,l0,i1,j1,k1,l1,i,j,k,l) \ + for (int l = 0; l<(int)(boundl); ++l) \ + for (int _n1l = (int)(l<(int)(l0) || l>(int)(l1)), k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k || _n1l?0:(int)(i0)>0?0:(int)(i1) + 1; \ + i<(int)(boundi); ++i, i = _n1j || _n1k || _n1l?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_outX(img,x0,x1,x) cimg_for_out1((img)._width,x0,x1,x) +#define cimg_for_outY(img,y0,y1,y) cimg_for_out1((img)._height,y0,y1,y) +#define cimg_for_outZ(img,z0,z1,z) cimg_for_out1((img)._depth,z0,z1,z) +#define cimg_for_outC(img,c0,c1,c) cimg_for_out1((img)._spectrum,c0,c1,c) +#define cimg_for_outXY(img,x0,y0,x1,y1,x,y) cimg_for_out2((img)._width,(img)._height,x0,y0,x1,y1,x,y) +#define cimg_for_outXZ(img,x0,z0,x1,z1,x,z) cimg_for_out2((img)._width,(img)._depth,x0,z0,x1,z1,x,z) +#define cimg_for_outXC(img,x0,c0,x1,c1,x,c) cimg_for_out2((img)._width,(img)._spectrum,x0,c0,x1,c1,x,c) +#define cimg_for_outYZ(img,y0,z0,y1,z1,y,z) cimg_for_out2((img)._height,(img)._depth,y0,z0,y1,z1,y,z) +#define cimg_for_outYC(img,y0,c0,y1,c1,y,c) cimg_for_out2((img)._height,(img)._spectrum,y0,c0,y1,c1,y,c) +#define cimg_for_outZC(img,z0,c0,z1,c1,z,c) cimg_for_out2((img)._depth,(img)._spectrum,z0,c0,z1,c1,z,c) +#define cimg_for_outXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) \ + cimg_for_out3((img)._width,(img)._height,(img)._depth,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_outXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) \ + cimg_for_out3((img)._width,(img)._height,(img)._spectrum,x0,y0,c0,x1,y1,c1,x,y,c) +#define cimg_for_outXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) \ + cimg_for_out3((img)._width,(img)._depth,(img)._spectrum,x0,z0,c0,x1,z1,c1,x,z,c) +#define cimg_for_outYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) \ + cimg_for_out3((img)._height,(img)._depth,(img)._spectrum,y0,z0,c0,y1,z1,c1,y,z,c) +#define cimg_for_outXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_out4((img)._width,(img)._height,(img)._depth,(img)._spectrum,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) +#define cimg_for_borderX(img,x,n) cimg_for_outX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_borderY(img,y,n) cimg_for_outY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_borderZ(img,z,n) cimg_for_outZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_borderC(img,c,n) cimg_for_outC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_borderXY(img,x,y,n) cimg_for_outXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_borderXYZ(img,x,y,z,n) \ + cimg_for_outXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_borderXYZC(img,x,y,z,c,n) \ + cimg_for_outXYZC(img,n,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n), \ + (img)._depth - 1 - (n),(img)._spectrum - 1 - (n),x,y,z,c) + +#define cimg_for_spiralXY(img,x,y) \ + for (int x = 0, y = 0, _n1##x = 1, _n1##y = (img).width()*(img).height(); _n1##y; \ + --_n1##y, _n1##x+=(_n1##x>>2) - ((!(_n1##x&3)?--y:((_n1##x&3)==1?(img)._width - 1 - ++x:\ + ((_n1##x&3)==2?(img)._height - 1 - ++y:--x))))?0:1) + +#define cimg_for_lineXY(x,y,x0,y0,x1,y1) \ + for (int x = (int)(x0), y = (int)(y0), _sx = 1, _sy = 1, _steep = 0, \ + _dx=(x1)>(x0)?(int)(x1) - (int)(x0):(_sx=-1,(int)(x0) - (int)(x1)), \ + _dy=(y1)>(y0)?(int)(y1) - (int)(y0):(_sy=-1,(int)(y0) - (int)(y1)), \ + _counter = _dx, \ + _err = _dx>_dy?(_dy>>1):((_steep=1),(_counter=_dy),(_dx>>1)); \ + _counter>=0; \ + --_counter, x+=_steep? \ + (y+=_sy,(_err-=_dx)<0?_err+=_dy,_sx:0): \ + (y+=(_err-=_dy)<0?_err+=_dx,_sy:0,_sx)) + +#define cimg_for2(bound,i) \ + for (int i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + ++i, ++_n1##i) +#define cimg_for2X(img,x) cimg_for2((img)._width,x) +#define cimg_for2Y(img,y) cimg_for2((img)._height,y) +#define cimg_for2Z(img,z) cimg_for2((img)._depth,z) +#define cimg_for2C(img,c) cimg_for2((img)._spectrum,c) +#define cimg_for2XY(img,x,y) cimg_for2Y(img,y) cimg_for2X(img,x) +#define cimg_for2XZ(img,x,z) cimg_for2Z(img,z) cimg_for2X(img,x) +#define cimg_for2XC(img,x,c) cimg_for2C(img,c) cimg_for2X(img,x) +#define cimg_for2YZ(img,y,z) cimg_for2Z(img,z) cimg_for2Y(img,y) +#define cimg_for2YC(img,y,c) cimg_for2C(img,c) cimg_for2Y(img,y) +#define cimg_for2ZC(img,z,c) cimg_for2C(img,c) cimg_for2Z(img,z) +#define cimg_for2XYZ(img,x,y,z) cimg_for2Z(img,z) cimg_for2XY(img,x,y) +#define cimg_for2XZC(img,x,z,c) cimg_for2C(img,c) cimg_for2XZ(img,x,z) +#define cimg_for2YZC(img,y,z,c) cimg_for2C(img,c) cimg_for2YZ(img,y,z) +#define cimg_for2XYZC(img,x,y,z,c) cimg_for2C(img,c) cimg_for2XYZ(img,x,y,z) + +#define cimg_for_in2(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + ++i, ++_n1##i) +#define cimg_for_in2X(img,x0,x1,x) cimg_for_in2((img)._width,x0,x1,x) +#define cimg_for_in2Y(img,y0,y1,y) cimg_for_in2((img)._height,y0,y1,y) +#define cimg_for_in2Z(img,z0,z1,z) cimg_for_in2((img)._depth,z0,z1,z) +#define cimg_for_in2C(img,c0,c1,c) cimg_for_in2((img)._spectrum,c0,c1,c) +#define cimg_for_in2XY(img,x0,y0,x1,y1,x,y) cimg_for_in2Y(img,y0,y1,y) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XZ(img,x0,z0,x1,z1,x,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XC(img,x0,c0,x1,c1,x,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2YC(img,y0,c0,y1,c1,y,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2ZC(img,z0,c0,z1,c1,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Z(img,z0,z1,z) +#define cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in2XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in2YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in2XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in2C(img,c0,c1,c) cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i) +#define cimg_for3X(img,x) cimg_for3((img)._width,x) +#define cimg_for3Y(img,y) cimg_for3((img)._height,y) +#define cimg_for3Z(img,z) cimg_for3((img)._depth,z) +#define cimg_for3C(img,c) cimg_for3((img)._spectrum,c) +#define cimg_for3XY(img,x,y) cimg_for3Y(img,y) cimg_for3X(img,x) +#define cimg_for3XZ(img,x,z) cimg_for3Z(img,z) cimg_for3X(img,x) +#define cimg_for3XC(img,x,c) cimg_for3C(img,c) cimg_for3X(img,x) +#define cimg_for3YZ(img,y,z) cimg_for3Z(img,z) cimg_for3Y(img,y) +#define cimg_for3YC(img,y,c) cimg_for3C(img,c) cimg_for3Y(img,y) +#define cimg_for3ZC(img,z,c) cimg_for3C(img,c) cimg_for3Z(img,z) +#define cimg_for3XYZ(img,x,y,z) cimg_for3Z(img,z) cimg_for3XY(img,x,y) +#define cimg_for3XZC(img,x,z,c) cimg_for3C(img,c) cimg_for3XZ(img,x,z) +#define cimg_for3YZC(img,y,z,c) cimg_for3C(img,c) cimg_for3YZ(img,y,z) +#define cimg_for3XYZC(img,x,y,z,c) cimg_for3C(img,c) cimg_for3XYZ(img,x,y,z) + +#define cimg_for_in3(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + _p1##i = i++, ++_n1##i) +#define cimg_for_in3X(img,x0,x1,x) cimg_for_in3((img)._width,x0,x1,x) +#define cimg_for_in3Y(img,y0,y1,y) cimg_for_in3((img)._height,y0,y1,y) +#define cimg_for_in3Z(img,z0,z1,z) cimg_for_in3((img)._depth,z0,z1,z) +#define cimg_for_in3C(img,c0,c1,c) cimg_for_in3((img)._spectrum,c0,c1,c) +#define cimg_for_in3XY(img,x0,y0,x1,y1,x,y) cimg_for_in3Y(img,y0,y1,y) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XZ(img,x0,z0,x1,z1,x,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XC(img,x0,c0,x1,c1,x,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3YC(img,y0,c0,y1,c1,y,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3ZC(img,z0,c0,z1,c1,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Z(img,z0,z1,z) +#define cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in3XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in3YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in3XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in3C(img,c0,c1,c) cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for4(bound,i) \ + for (int i = 0, _p1##i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for4X(img,x) cimg_for4((img)._width,x) +#define cimg_for4Y(img,y) cimg_for4((img)._height,y) +#define cimg_for4Z(img,z) cimg_for4((img)._depth,z) +#define cimg_for4C(img,c) cimg_for4((img)._spectrum,c) +#define cimg_for4XY(img,x,y) cimg_for4Y(img,y) cimg_for4X(img,x) +#define cimg_for4XZ(img,x,z) cimg_for4Z(img,z) cimg_for4X(img,x) +#define cimg_for4XC(img,x,c) cimg_for4C(img,c) cimg_for4X(img,x) +#define cimg_for4YZ(img,y,z) cimg_for4Z(img,z) cimg_for4Y(img,y) +#define cimg_for4YC(img,y,c) cimg_for4C(img,c) cimg_for4Y(img,y) +#define cimg_for4ZC(img,z,c) cimg_for4C(img,c) cimg_for4Z(img,z) +#define cimg_for4XYZ(img,x,y,z) cimg_for4Z(img,z) cimg_for4XY(img,x,y) +#define cimg_for4XZC(img,x,z,c) cimg_for4C(img,c) cimg_for4XZ(img,x,z) +#define cimg_for4YZC(img,y,z,c) cimg_for4C(img,c) cimg_for4YZ(img,y,z) +#define cimg_for4XYZC(img,x,y,z,c) cimg_for4C(img,c) cimg_for4XYZ(img,x,y,z) + +#define cimg_for_in4(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in4X(img,x0,x1,x) cimg_for_in4((img)._width,x0,x1,x) +#define cimg_for_in4Y(img,y0,y1,y) cimg_for_in4((img)._height,y0,y1,y) +#define cimg_for_in4Z(img,z0,z1,z) cimg_for_in4((img)._depth,z0,z1,z) +#define cimg_for_in4C(img,c0,c1,c) cimg_for_in4((img)._spectrum,c0,c1,c) +#define cimg_for_in4XY(img,x0,y0,x1,y1,x,y) cimg_for_in4Y(img,y0,y1,y) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XZ(img,x0,z0,x1,z1,x,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XC(img,x0,c0,x1,c1,x,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4YC(img,y0,c0,y1,c1,y,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4ZC(img,z0,c0,z1,c1,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Z(img,z0,z1,z) +#define cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in4XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in4YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in4XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in4C(img,c0,c1,c) cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for5(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for5X(img,x) cimg_for5((img)._width,x) +#define cimg_for5Y(img,y) cimg_for5((img)._height,y) +#define cimg_for5Z(img,z) cimg_for5((img)._depth,z) +#define cimg_for5C(img,c) cimg_for5((img)._spectrum,c) +#define cimg_for5XY(img,x,y) cimg_for5Y(img,y) cimg_for5X(img,x) +#define cimg_for5XZ(img,x,z) cimg_for5Z(img,z) cimg_for5X(img,x) +#define cimg_for5XC(img,x,c) cimg_for5C(img,c) cimg_for5X(img,x) +#define cimg_for5YZ(img,y,z) cimg_for5Z(img,z) cimg_for5Y(img,y) +#define cimg_for5YC(img,y,c) cimg_for5C(img,c) cimg_for5Y(img,y) +#define cimg_for5ZC(img,z,c) cimg_for5C(img,c) cimg_for5Z(img,z) +#define cimg_for5XYZ(img,x,y,z) cimg_for5Z(img,z) cimg_for5XY(img,x,y) +#define cimg_for5XZC(img,x,z,c) cimg_for5C(img,c) cimg_for5XZ(img,x,z) +#define cimg_for5YZC(img,y,z,c) cimg_for5C(img,c) cimg_for5YZ(img,y,z) +#define cimg_for5XYZC(img,x,y,z,c) cimg_for5C(img,c) cimg_for5XYZ(img,x,y,z) + +#define cimg_for_in5(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in5X(img,x0,x1,x) cimg_for_in5((img)._width,x0,x1,x) +#define cimg_for_in5Y(img,y0,y1,y) cimg_for_in5((img)._height,y0,y1,y) +#define cimg_for_in5Z(img,z0,z1,z) cimg_for_in5((img)._depth,z0,z1,z) +#define cimg_for_in5C(img,c0,c1,c) cimg_for_in5((img)._spectrum,c0,c1,c) +#define cimg_for_in5XY(img,x0,y0,x1,y1,x,y) cimg_for_in5Y(img,y0,y1,y) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XZ(img,x0,z0,x1,z1,x,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XC(img,x0,c0,x1,c1,x,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5YC(img,y0,c0,y1,c1,y,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5ZC(img,z0,c0,z1,c1,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Z(img,z0,z1,z) +#define cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in5XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in5YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in5XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in5C(img,c0,c1,c) cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for6(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for6X(img,x) cimg_for6((img)._width,x) +#define cimg_for6Y(img,y) cimg_for6((img)._height,y) +#define cimg_for6Z(img,z) cimg_for6((img)._depth,z) +#define cimg_for6C(img,c) cimg_for6((img)._spectrum,c) +#define cimg_for6XY(img,x,y) cimg_for6Y(img,y) cimg_for6X(img,x) +#define cimg_for6XZ(img,x,z) cimg_for6Z(img,z) cimg_for6X(img,x) +#define cimg_for6XC(img,x,c) cimg_for6C(img,c) cimg_for6X(img,x) +#define cimg_for6YZ(img,y,z) cimg_for6Z(img,z) cimg_for6Y(img,y) +#define cimg_for6YC(img,y,c) cimg_for6C(img,c) cimg_for6Y(img,y) +#define cimg_for6ZC(img,z,c) cimg_for6C(img,c) cimg_for6Z(img,z) +#define cimg_for6XYZ(img,x,y,z) cimg_for6Z(img,z) cimg_for6XY(img,x,y) +#define cimg_for6XZC(img,x,z,c) cimg_for6C(img,c) cimg_for6XZ(img,x,z) +#define cimg_for6YZC(img,y,z,c) cimg_for6C(img,c) cimg_for6YZ(img,y,z) +#define cimg_for6XYZC(img,x,y,z,c) cimg_for6C(img,c) cimg_for6XYZ(img,x,y,z) + +#define cimg_for_in6(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in6X(img,x0,x1,x) cimg_for_in6((img)._width,x0,x1,x) +#define cimg_for_in6Y(img,y0,y1,y) cimg_for_in6((img)._height,y0,y1,y) +#define cimg_for_in6Z(img,z0,z1,z) cimg_for_in6((img)._depth,z0,z1,z) +#define cimg_for_in6C(img,c0,c1,c) cimg_for_in6((img)._spectrum,c0,c1,c) +#define cimg_for_in6XY(img,x0,y0,x1,y1,x,y) cimg_for_in6Y(img,y0,y1,y) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XZ(img,x0,z0,x1,z1,x,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XC(img,x0,c0,x1,c1,x,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6YC(img,y0,c0,y1,c1,y,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6ZC(img,z0,c0,z1,c1,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Z(img,z0,z1,z) +#define cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in6XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in6YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in6XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in6C(img,c0,c1,c) cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for7(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for7X(img,x) cimg_for7((img)._width,x) +#define cimg_for7Y(img,y) cimg_for7((img)._height,y) +#define cimg_for7Z(img,z) cimg_for7((img)._depth,z) +#define cimg_for7C(img,c) cimg_for7((img)._spectrum,c) +#define cimg_for7XY(img,x,y) cimg_for7Y(img,y) cimg_for7X(img,x) +#define cimg_for7XZ(img,x,z) cimg_for7Z(img,z) cimg_for7X(img,x) +#define cimg_for7XC(img,x,c) cimg_for7C(img,c) cimg_for7X(img,x) +#define cimg_for7YZ(img,y,z) cimg_for7Z(img,z) cimg_for7Y(img,y) +#define cimg_for7YC(img,y,c) cimg_for7C(img,c) cimg_for7Y(img,y) +#define cimg_for7ZC(img,z,c) cimg_for7C(img,c) cimg_for7Z(img,z) +#define cimg_for7XYZ(img,x,y,z) cimg_for7Z(img,z) cimg_for7XY(img,x,y) +#define cimg_for7XZC(img,x,z,c) cimg_for7C(img,c) cimg_for7XZ(img,x,z) +#define cimg_for7YZC(img,y,z,c) cimg_for7C(img,c) cimg_for7YZ(img,y,z) +#define cimg_for7XYZC(img,x,y,z,c) cimg_for7C(img,c) cimg_for7XYZ(img,x,y,z) + +#define cimg_for_in7(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in7X(img,x0,x1,x) cimg_for_in7((img)._width,x0,x1,x) +#define cimg_for_in7Y(img,y0,y1,y) cimg_for_in7((img)._height,y0,y1,y) +#define cimg_for_in7Z(img,z0,z1,z) cimg_for_in7((img)._depth,z0,z1,z) +#define cimg_for_in7C(img,c0,c1,c) cimg_for_in7((img)._spectrum,c0,c1,c) +#define cimg_for_in7XY(img,x0,y0,x1,y1,x,y) cimg_for_in7Y(img,y0,y1,y) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XZ(img,x0,z0,x1,z1,x,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XC(img,x0,c0,x1,c1,x,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7YC(img,y0,c0,y1,c1,y,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7ZC(img,z0,c0,z1,c1,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Z(img,z0,z1,z) +#define cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in7XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in7YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in7XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in7C(img,c0,c1,c) cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for8(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for8X(img,x) cimg_for8((img)._width,x) +#define cimg_for8Y(img,y) cimg_for8((img)._height,y) +#define cimg_for8Z(img,z) cimg_for8((img)._depth,z) +#define cimg_for8C(img,c) cimg_for8((img)._spectrum,c) +#define cimg_for8XY(img,x,y) cimg_for8Y(img,y) cimg_for8X(img,x) +#define cimg_for8XZ(img,x,z) cimg_for8Z(img,z) cimg_for8X(img,x) +#define cimg_for8XC(img,x,c) cimg_for8C(img,c) cimg_for8X(img,x) +#define cimg_for8YZ(img,y,z) cimg_for8Z(img,z) cimg_for8Y(img,y) +#define cimg_for8YC(img,y,c) cimg_for8C(img,c) cimg_for8Y(img,y) +#define cimg_for8ZC(img,z,c) cimg_for8C(img,c) cimg_for8Z(img,z) +#define cimg_for8XYZ(img,x,y,z) cimg_for8Z(img,z) cimg_for8XY(img,x,y) +#define cimg_for8XZC(img,x,z,c) cimg_for8C(img,c) cimg_for8XZ(img,x,z) +#define cimg_for8YZC(img,y,z,c) cimg_for8C(img,c) cimg_for8YZ(img,y,z) +#define cimg_for8XYZC(img,x,y,z,c) cimg_for8C(img,c) cimg_for8XYZ(img,x,y,z) + +#define cimg_for_in8(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in8X(img,x0,x1,x) cimg_for_in8((img)._width,x0,x1,x) +#define cimg_for_in8Y(img,y0,y1,y) cimg_for_in8((img)._height,y0,y1,y) +#define cimg_for_in8Z(img,z0,z1,z) cimg_for_in8((img)._depth,z0,z1,z) +#define cimg_for_in8C(img,c0,c1,c) cimg_for_in8((img)._spectrum,c0,c1,c) +#define cimg_for_in8XY(img,x0,y0,x1,y1,x,y) cimg_for_in8Y(img,y0,y1,y) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XZ(img,x0,z0,x1,z1,x,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XC(img,x0,c0,x1,c1,x,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8YC(img,y0,c0,y1,c1,y,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8ZC(img,z0,c0,z1,c1,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Z(img,z0,z1,z) +#define cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in8XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in8YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in8XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in8C(img,c0,c1,c) cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for9(bound,i) \ + for (int i = 0, _p4##i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(int)(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(int)(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(int)(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(int)(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for9X(img,x) cimg_for9((img)._width,x) +#define cimg_for9Y(img,y) cimg_for9((img)._height,y) +#define cimg_for9Z(img,z) cimg_for9((img)._depth,z) +#define cimg_for9C(img,c) cimg_for9((img)._spectrum,c) +#define cimg_for9XY(img,x,y) cimg_for9Y(img,y) cimg_for9X(img,x) +#define cimg_for9XZ(img,x,z) cimg_for9Z(img,z) cimg_for9X(img,x) +#define cimg_for9XC(img,x,c) cimg_for9C(img,c) cimg_for9X(img,x) +#define cimg_for9YZ(img,y,z) cimg_for9Z(img,z) cimg_for9Y(img,y) +#define cimg_for9YC(img,y,c) cimg_for9C(img,c) cimg_for9Y(img,y) +#define cimg_for9ZC(img,z,c) cimg_for9C(img,c) cimg_for9Z(img,z) +#define cimg_for9XYZ(img,x,y,z) cimg_for9Z(img,z) cimg_for9XY(img,x,y) +#define cimg_for9XZC(img,x,z,c) cimg_for9C(img,c) cimg_for9XZ(img,x,z) +#define cimg_for9YZC(img,y,z,c) cimg_for9C(img,c) cimg_for9YZ(img,y,z) +#define cimg_for9XYZC(img,x,y,z,c) cimg_for9C(img,c) cimg_for9XYZ(img,x,y,z) + +#define cimg_for_in9(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p4##i = i - 4<0?0:i - 4, \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in9X(img,x0,x1,x) cimg_for_in9((img)._width,x0,x1,x) +#define cimg_for_in9Y(img,y0,y1,y) cimg_for_in9((img)._height,y0,y1,y) +#define cimg_for_in9Z(img,z0,z1,z) cimg_for_in9((img)._depth,z0,z1,z) +#define cimg_for_in9C(img,c0,c1,c) cimg_for_in9((img)._spectrum,c0,c1,c) +#define cimg_for_in9XY(img,x0,y0,x1,y1,x,y) cimg_for_in9Y(img,y0,y1,y) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XZ(img,x0,z0,x1,z1,x,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XC(img,x0,c0,x1,c1,x,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9YC(img,y0,c0,y1,c1,y,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9ZC(img,z0,c0,z1,c1,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Z(img,z0,z1,z) +#define cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in9XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in9YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in9XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in9C(img,c0,c1,c) cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[4] = (T)(img)(x,y,z,c)), \ + (I[7] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for4x4(img,x,y,z,c,I,T) \ + cimg_for4((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = I[5] = (T)(img)(0,y,z,c)), \ + (I[8] = I[9] = (T)(img)(0,_n1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in4x4(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in4((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = (T)(img)(_p1##x,y,z,c)), \ + (I[8] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[5] = (T)(img)(x,y,z,c)), \ + (I[9] = (T)(img)(x,_n1##y,z,c)), \ + (I[13] = (T)(img)(x,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for5x5(img,x,y,z,c,I,T) \ + cimg_for5((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = I[6] = I[7] = (T)(img)(0,_p1##y,z,c)), \ + (I[10] = I[11] = I[12] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = I[17] = (T)(img)(0,_n1##y,z,c)), \ + (I[20] = I[21] = I[22] = (T)(img)(0,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in5x5(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in5((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[10] = (T)(img)(_p2##x,y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[11] = (T)(img)(_p1##x,y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[7] = (T)(img)(x,_p1##y,z,c)), \ + (I[12] = (T)(img)(x,y,z,c)), \ + (I[17] = (T)(img)(x,_n1##y,z,c)), \ + (I[22] = (T)(img)(x,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for6x6(img,x,y,z,c,I,T) \ + cimg_for6((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = I[7] = I[8] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = I[14] = (T)(img)(0,y,z,c)), \ + (I[18] = I[19] = I[20] = (T)(img)(0,_n1##y,z,c)), \ + (I[24] = I[25] = I[26] = (T)(img)(0,_n2##y,z,c)), \ + (I[30] = I[31] = I[32] = (T)(img)(0,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in6x6(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in6((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)x0, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p2##x,y,z,c)), \ + (I[18] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[30] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[7] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_p1##x,y,z,c)), \ + (I[19] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[25] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[31] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[8] = (T)(img)(x,_p1##y,z,c)), \ + (I[14] = (T)(img)(x,y,z,c)), \ + (I[20] = (T)(img)(x,_n1##y,z,c)), \ + (I[26] = (T)(img)(x,_n2##y,z,c)), \ + (I[32] = (T)(img)(x,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for7x7(img,x,y,z,c,I,T) \ + cimg_for7((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = I[8] = I[9] = I[10] = (T)(img)(0,_p2##y,z,c)), \ + (I[14] = I[15] = I[16] = I[17] = (T)(img)(0,_p1##y,z,c)), \ + (I[21] = I[22] = I[23] = I[24] = (T)(img)(0,y,z,c)), \ + (I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_n1##y,z,c)), \ + (I[35] = I[36] = I[37] = I[38] = (T)(img)(0,_n2##y,z,c)), \ + (I[42] = I[43] = I[44] = I[45] = (T)(img)(0,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in7x7(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in7((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[14] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[21] = (T)(img)(_p3##x,y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[35] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[42] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[22] = (T)(img)(_p2##x,y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[36] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[43] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[23] = (T)(img)(_p1##x,y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[37] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[44] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[10] = (T)(img)(x,_p2##y,z,c)), \ + (I[17] = (T)(img)(x,_p1##y,z,c)), \ + (I[24] = (T)(img)(x,y,z,c)), \ + (I[31] = (T)(img)(x,_n1##y,z,c)), \ + (I[38] = (T)(img)(x,_n2##y,z,c)), \ + (I[45] = (T)(img)(x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for8x8(img,x,y,z,c,I,T) \ + cimg_for8((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = I[9] = I[10] = I[11] = (T)(img)(0,_p2##y,z,c)), \ + (I[16] = I[17] = I[18] = I[19] = (T)(img)(0,_p1##y,z,c)), \ + (I[24] = I[25] = I[26] = I[27] = (T)(img)(0,y,z,c)), \ + (I[32] = I[33] = I[34] = I[35] = (T)(img)(0,_n1##y,z,c)), \ + (I[40] = I[41] = I[42] = I[43] = (T)(img)(0,_n2##y,z,c)), \ + (I[48] = I[49] = I[50] = I[51] = (T)(img)(0,_n3##y,z,c)), \ + (I[56] = I[57] = I[58] = I[59] = (T)(img)(0,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in8x8(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in8((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[24] = (T)(img)(_p3##x,y,z,c)), \ + (I[32] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[56] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[17] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_p2##x,y,z,c)), \ + (I[33] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[49] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[57] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[10] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_p1##x,y,z,c)), \ + (I[34] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[42] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[50] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[58] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[11] = (T)(img)(x,_p2##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,z,c)), \ + (I[27] = (T)(img)(x,y,z,c)), \ + (I[35] = (T)(img)(x,_n1##y,z,c)), \ + (I[43] = (T)(img)(x,_n2##y,z,c)), \ + (I[51] = (T)(img)(x,_n3##y,z,c)), \ + (I[59] = (T)(img)(x,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for9x9(img,x,y,z,c,I,T) \ + cimg_for9((img)._height,y) for (int x = 0, \ + _p4##x = 0, _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = I[4] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = I[10] = I[11] = I[12] = I[13] = (T)(img)(0,_p3##y,z,c)), \ + (I[18] = I[19] = I[20] = I[21] = I[22] = (T)(img)(0,_p2##y,z,c)), \ + (I[27] = I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_p1##y,z,c)), \ + (I[36] = I[37] = I[38] = I[39] = I[40] = (T)(img)(0,y,z,c)), \ + (I[45] = I[46] = I[47] = I[48] = I[49] = (T)(img)(0,_n1##y,z,c)), \ + (I[54] = I[55] = I[56] = I[57] = I[58] = (T)(img)(0,_n2##y,z,c)), \ + (I[63] = I[64] = I[65] = I[66] = I[67] = (T)(img)(0,_n3##y,z,c)), \ + (I[72] = I[73] = I[74] = I[75] = I[76] = (T)(img)(0,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in9x9(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in9((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p4##x = x - 4<0?0:x - 4, \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = (T)(img)(_p4##x,_p3##y,z,c)), \ + (I[18] = (T)(img)(_p4##x,_p2##y,z,c)), \ + (I[27] = (T)(img)(_p4##x,_p1##y,z,c)), \ + (I[36] = (T)(img)(_p4##x,y,z,c)), \ + (I[45] = (T)(img)(_p4##x,_n1##y,z,c)), \ + (I[54] = (T)(img)(_p4##x,_n2##y,z,c)), \ + (I[63] = (T)(img)(_p4##x,_n3##y,z,c)), \ + (I[72] = (T)(img)(_p4##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p3##x,_p4##y,z,c)), \ + (I[10] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[19] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[37] = (T)(img)(_p3##x,y,z,c)), \ + (I[46] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[55] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[64] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[73] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p2##x,_p4##y,z,c)), \ + (I[11] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[38] = (T)(img)(_p2##x,y,z,c)), \ + (I[47] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[56] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[65] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[74] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,_p4##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[39] = (T)(img)(_p1##x,y,z,c)), \ + (I[48] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[57] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[66] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[75] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[4] = (T)(img)(x,_p4##y,z,c)), \ + (I[13] = (T)(img)(x,_p3##y,z,c)), \ + (I[22] = (T)(img)(x,_p2##y,z,c)), \ + (I[31] = (T)(img)(x,_p1##y,z,c)), \ + (I[40] = (T)(img)(x,y,z,c)), \ + (I[49] = (T)(img)(x,_n1##y,z,c)), \ + (I[58] = (T)(img)(x,_n2##y,z,c)), \ + (I[67] = (T)(img)(x,_n3##y,z,c)), \ + (I[76] = (T)(img)(x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for2x2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._depth,z) cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + (I[4] = (T)(img)(0,y,_n1##z,c)), \ + (I[6] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in2((img)._depth,z0,z1,z) cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + (I[4] = (T)(img)(x,y,_n1##z,c)), \ + (I[6] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for3x3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._depth,z) cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,_p1##z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,_p1##z,c)), \ + (I[9] = I[10] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = (T)(img)(0,_n1##y,z,c)), \ + (I[18] = I[19] = (T)(img)(0,_p1##y,_n1##z,c)), \ + (I[21] = I[22] = (T)(img)(0,y,_n1##z,c)), \ + (I[24] = I[25] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in3((img)._depth,z0,z1,z) cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = (T)(img)(_p1##x,y,_p1##z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c)), \ + (I[9] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,y,z,c)), \ + (I[15] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c)), \ + (I[21] = (T)(img)(_p1##x,y,_n1##z,c)), \ + (I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c)), \ + (I[1] = (T)(img)(x,_p1##y,_p1##z,c)), \ + (I[4] = (T)(img)(x,y,_p1##z,c)), \ + (I[7] = (T)(img)(x,_n1##y,_p1##z,c)), \ + (I[10] = (T)(img)(x,_p1##y,z,c)), \ + (I[13] = (T)(img)(x,y,z,c)), \ + (I[16] = (T)(img)(x,_n1##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,_n1##z,c)), \ + (I[22] = (T)(img)(x,y,_n1##z,c)), \ + (I[25] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimglist_for(list,l) for (int l = 0; l<(int)(list)._width; ++l) +#define cimglist_rof(list,l) for (int l = (int)(list)._width - 1; l>=0; --l) +#define cimglist_for_in(list,l0,l1,l) \ + for (int l = (int)(l0)<0?0:(int)(l0), _max##l = (unsigned int)l1<(list)._width?(int)(l1):(int)(list)._width - 1; \ + l<=_max##l; ++l) + +#define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn + +// Macros used to display error messages when exceptions are thrown. +// You should not use these macros is your own code. +#define _cimgdisplay_instance "[instance(%u,%u,%u,%c%s%c)] CImgDisplay::" +#define cimgdisplay_instance _width,_height,_normalization,_title?'\"':'[',_title?_title:"untitled",_title?'\"':']' +#define _cimg_instance "[instance(%u,%u,%u,%u,%p,%sshared)] CImg<%s>::" +#define cimg_instance _width,_height,_depth,_spectrum,_data,_is_shared?"":"non-",pixel_type() +#define _cimglist_instance "[instance(%u,%u,%p)] CImgList<%s>::" +#define cimglist_instance _width,_allocated_width,_data,pixel_type() + +/*------------------------------------------------ + # + # + # Define cimg_library:: namespace + # + # + -------------------------------------------------*/ +//! Contains all classes and functions of the \CImg library. +/** + This namespace is defined to avoid functions and class names collisions + that could happen with the inclusion of other C++ header files. + Anyway, it should not happen often and you should reasonably start most of your + \CImg-based programs with + \code + #include "CImg.h" + using namespace cimg_library; + \endcode + to simplify the declaration of \CImg Library objects afterwards. +**/ +namespace cimg_library_suffixed { + + // Declare the four classes of the CImg Library. + template struct CImg; + template struct CImgList; + struct CImgDisplay; + struct CImgException; + + // Declare cimg:: namespace. + // This is an incomplete namespace definition here. It only contains some + // necessary stuff to ensure a correct declaration order of the classes and functions + // defined afterwards. + namespace cimg { + + // Define character sequences for colored terminal output. +#ifdef cimg_use_vt100 + static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 }; + static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 }; + static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 }; + static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 }; + static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 }; + static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 }; + static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 }; + static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 }; + static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 }; + static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 }; + static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 }; +#else + static const char t_normal[] = { 0 }; + static const char *const t_black = cimg::t_normal, + *const t_red = cimg::t_normal, + *const t_green = cimg::t_normal, + *const t_yellow = cimg::t_normal, + *const t_blue = cimg::t_normal, + *const t_magenta = cimg::t_normal, + *const t_cyan = cimg::t_normal, + *const t_white = cimg::t_normal, + *const t_bold = cimg::t_normal, + *const t_underscore = cimg::t_normal; +#endif + + inline std::FILE* output(std::FILE *file=0); + inline void info(); + + //! Avoid warning messages due to unused parameters. Do nothing actually. + template + inline void unused(const T&, ...) {} + + // [internal] Lock/unlock a mutex for managing concurrent threads. + // 'lock_mode' can be { 0=unlock | 1=lock | 2=trylock }. + // 'n' can be in [0,31] but mutex range [0,15] is reserved by CImg. + inline int mutex(const unsigned int n, const int lock_mode=1); + + inline unsigned int& exception_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = cimg_verbosity; + if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); } + return mode; + } + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + inline FILE* _stdin(const bool throw_exception=true); + inline FILE* _stdout(const bool throw_exception=true); + inline FILE* _stderr(const bool throw_exception=true); + + // Mandatory because Microsoft's _snprintf() and _vsnprintf() do not add the '\0' character + // at the end of the string. +#if cimg_OS==2 && defined(_MSC_VER) + inline int _snprintf(char *const s, const size_t size, const char *const format, ...) { + va_list ap; + va_start(ap,format); + const int result = _vsnprintf(s,size,format,ap); + va_end(ap); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) { + int result = -1; + cimg::mutex(6); + if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap); + if (result==-1) result = _vscprintf(format,ap); + cimg::mutex(6,0); + return result; + } + + // Mutex-protected version of sscanf, sprintf and snprintf. + // Used only MacOSX, as it seems those functions are not re-entrant on MacOSX. +#elif defined(__MACOSX__) || defined(__APPLE__) + inline int _sscanf(const char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsscanf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _sprintf(char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsprintf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _snprintf(char *const s, const size_t n, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsnprintf(s,n,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) { + cimg::mutex(6); + const int result = std::vsnprintf(s,size,format,ap); + cimg::mutex(6,0); + return result; + } +#endif + + //! Set current \CImg exception mode. + /** + The way error messages are handled by \CImg can be changed dynamically, using this function. + \param mode Desired exception mode. Possible values are: + - \c 0: Hide library messages (quiet mode). + - \c 1: Print library messages on the console. + - \c 2: Display library messages on a dialog window. + - \c 3: Do as \c 1 + add extra debug warnings (slow down the code!). + - \c 4: Do as \c 2 + add extra debug warnings (slow down the code!). + **/ + inline unsigned int& exception_mode(const unsigned int mode) { + return exception_mode(mode,true); + } + + //! Return current \CImg exception mode. + /** + \note By default, return the value of configuration macro \c cimg_verbosity + **/ + inline unsigned int& exception_mode() { + return exception_mode(0,false); + } + + inline unsigned int openmp_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = 2; + if (is_set) { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); } + return mode; + } + + //! Set current \CImg openmp mode. + /** + The way openmp-based methods are handled by \CImg can be changed dynamically, using this function. + \param mode Desired openmp mode. Possible values are: + - \c 0: Never parallelize. + - \c 1: Always parallelize. + - \c 2: Adaptive parallelization mode (default behavior). + **/ + inline unsigned int openmp_mode(const unsigned int mode) { + return openmp_mode(mode,true); + } + + //! Return current \CImg openmp mode. + inline unsigned int openmp_mode() { + return openmp_mode(0,false); + } + +#ifndef cimg_openmp_sizefactor +#define cimg_openmp_sizefactor 1 +#endif +#define cimg_openmp_if(cond) if ((cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond)))) +#define cimg_openmp_if_size(size,min_size) cimg_openmp_if((size)>=(cimg_openmp_sizefactor)*(min_size)) +#ifdef _MSC_VER +// Disable 'collapse()' directive for MSVC (supports only OpenMP 2.0). +#define cimg_openmp_collapse(k) +#else +#define cimg_openmp_collapse(k) collapse(k) +#endif + +#if cimg_OS==2 +// Disable parallelization of simple loops on Windows, due to noticed performance drop. +#define cimg_openmp_for(instance,expr,min_size) cimg_rof((instance),ptr,T) *ptr = (T)(expr); +#else +#define cimg_openmp_for(instance,expr,min_size) \ + cimg_pragma_openmp(parallel for cimg_openmp_if_size((instance).size(),min_size)) \ + cimg_rof((instance),ptr,T) *ptr = (T)(expr); +#endif + + // Display a simple dialog box, and wait for the user's response. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label="OK", const char *const button2_label=0, + const char *const button3_label=0, const char *const button4_label=0, + const char *const button5_label=0, const char *const button6_label=0, + const bool centering=false); + + // Evaluate math expression. + inline double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0); + + } // namespace cimg { ... + + /*--------------------------------------- + # + # Define the CImgException structures + # + --------------------------------------*/ + //! Instances of \c CImgException are thrown when errors are encountered in a \CImg function call. + /** + \par Overview + + CImgException is the base class of all exceptions thrown by \CImg (except \b CImgAbortException). + CImgException is never thrown itself. Derived classes that specify the type of errord are thrown instead. + These classes can be: + + - \b CImgAbortException: Thrown when a computationally-intensive function is aborted by an external signal. + This is the only \c non-derived exception class. + + - \b CImgArgumentException: Thrown when one argument of a called \CImg function is invalid. + This is probably one of the most thrown exception by \CImg. + For instance, the following example throws a \c CImgArgumentException: + \code + CImg img(100,100,1,3); // Define a 100x100 color image with float-valued pixels + img.mirror('e'); // Try to mirror image along the (non-existing) 'e'-axis + \endcode + + - \b CImgDisplayException: Thrown when something went wrong during the display of images in CImgDisplay instances. + + - \b CImgInstanceException: Thrown when an instance associated to a called \CImg method does not fit + the function requirements. For instance, the following example throws a \c CImgInstanceException: + \code + const CImg img; // Define an empty image + const float value = img.at(0); // Try to read first pixel value (does not exist) + \endcode + + - \b CImgIOException: Thrown when an error occurred when trying to load or save image files. + This happens when trying to read files that do not exist or with invalid formats. + For instance, the following example throws a \c CImgIOException: + \code + const CImg img("missing_file.jpg"); // Try to load a file that does not exist + \endcode + + - \b CImgWarningException: Thrown only if configuration macro \c cimg_strict_warnings is set, and + when a \CImg function has to display a warning message (see cimg::warn()). + + It is not recommended to throw CImgException instances by yourself, + since they are expected to be thrown only by \CImg. + When an error occurs in a library function call, \CImg may display error messages on the screen or on the + standard output, depending on the current \CImg exception mode. + The \CImg exception mode can be get and set by functions cimg::exception_mode() and + cimg::exception_mode(unsigned int). + + \par Exceptions handling + + In all cases, when an error occurs in \CImg, an instance of the corresponding exception class is thrown. + This may lead the program to break (this is the default behavior), but you can bypass this behavior by + handling the exceptions by yourself, + using a usual try { ... } catch () { ... } bloc, as in the following example: + \code + #define "CImg.h" + using namespace cimg_library; + int main() { + cimg::exception_mode(0); // Enable quiet exception mode + try { + ... // Here, do what you want to stress CImg + } catch (CImgException& e) { // You succeeded: something went wrong! + std::fprintf(stderr,"CImg Library Error: %s",e.what()); // Display your custom error message + ... // Do what you want now to save the ship! + } + } + \endcode + **/ + struct CImgException : public std::exception { +#define _cimg_exception_err(etype,disp_flag) \ + std::va_list ap, ap2; \ + va_start(ap,format); va_start(ap2,format); \ + int size = cimg_vsnprintf(0,0,format,ap2); \ + if (size++>=0) { \ + delete[] _message; \ + _message = new char[(size_t)size]; \ + cimg_vsnprintf(_message,(size_t)size,format,ap); \ + if (cimg::exception_mode()) { \ + std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \ + if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \ + catch (CImgException&) {} \ + if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \ + } \ + } \ + va_end(ap); va_end(ap2); + + char *_message; + CImgException() { _message = new char[1]; *_message = 0; } + CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); } + CImgException(const CImgException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgException() throw() { delete[] _message; } + CImgException& operator=(const CImgException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; // struct CImgException { ... + + // The CImgAbortException class is used to throw an exception when + // a computationally-intensive function has been aborted by an external signal. + struct CImgAbortException : public std::exception { + char *_message; + CImgAbortException() { _message = new char[1]; *_message = 0; } + CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); } + CImgAbortException(const CImgAbortException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgAbortException() throw() { delete[] _message; } + CImgAbortException& operator=(const CImgAbortException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; // struct CImgAbortException { ... + + // The CImgArgumentException class is used to throw an exception related + // to invalid arguments encountered in a library function call. + struct CImgArgumentException : public CImgException { + CImgArgumentException(const char *const format, ...) { _cimg_exception_err("CImgArgumentException",true); } + }; // struct CImgArgumentException { ... + + // The CImgDisplayException class is used to throw an exception related + // to display problems encountered in a library function call. + struct CImgDisplayException : public CImgException { + CImgDisplayException(const char *const format, ...) { _cimg_exception_err("CImgDisplayException",false); } + }; // struct CImgDisplayException { ... + + // The CImgInstanceException class is used to throw an exception related + // to an invalid instance encountered in a library function call. + struct CImgInstanceException : public CImgException { + CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); } + }; // struct CImgInstanceException { ... + + // The CImgIOException class is used to throw an exception related + // to input/output file problems encountered in a library function call. + struct CImgIOException : public CImgException { + CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); } + }; // struct CImgIOException { ... + + // The CImgWarningException class is used to throw an exception for warnings + // encountered in a library function call. + struct CImgWarningException : public CImgException { + CImgWarningException(const char *const format, ...) { _cimg_exception_err("CImgWarningException",false); } + }; // struct CImgWarningException { ... + + /*------------------------------------- + # + # Define cimg:: namespace + # + -----------------------------------*/ + //! Contains \a low-level functions and variables of the \CImg Library. + /** + Most of the functions and variables within this namespace are used by the \CImg library for low-level operations. + You may use them to access specific const values or environment variables internally used by \CImg. + \warning Never write using namespace cimg_library::cimg; in your source code. Lot of functions in the + cimg:: namespace have the same names as standard C functions that may be defined in the global + namespace ::. + **/ + namespace cimg { + + // Define traits that will be used to determine the best data type to work in CImg functions. + // + template struct type { + static const char* string() { + static const char* s[] = { "unknown", "unknown8", "unknown16", "unknown24", + "unknown32", "unknown40", "unknown48", "unknown56", + "unknown64", "unknown72", "unknown80", "unknown88", + "unknown96", "unknown104", "unknown112", "unknown120", + "unknown128" }; + return s[(sizeof(T)<17)?sizeof(T):0]; + } + static bool is_float() { return false; } + static bool is_inf(const T) { return false; } + static bool is_nan(const T) { return false; } + static bool is_finite(const T) { return true; } + static T min() { return ~max(); } + static T max() { return (T)1<<(8*sizeof(T) - 1); } + static T inf() { return max(); } + static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; } + static const char* format() { return "%s"; } + static const char* format_s() { return "%s"; } + static const char* format(const T& val) { static const char *const s = "unknown"; cimg::unused(val); return s; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "bool"; return s; } + static bool is_float() { return false; } + static bool is_inf(const bool) { return false; } + static bool is_nan(const bool) { return false; } + static bool is_finite(const bool) { return true; } + static bool min() { return false; } + static bool max() { return true; } + static bool inf() { return max(); } + static bool is_inf() { return false; } + static bool cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(bool)val; } + static const char* format() { return "%s"; } + static const char* format_s() { return "%s"; } + static const char* format(const bool val) { static const char* s[] = { "false", "true" }; return s[val?1:0]; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned char) { return false; } + static bool is_nan(const unsigned char) { return false; } + static bool is_finite(const unsigned char) { return true; } + static unsigned char min() { return 0; } + static unsigned char max() { return (unsigned char)-1; } + static unsigned char inf() { return max(); } + static unsigned char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned char val) { return (unsigned int)val; } + }; + +#if defined(CHAR_MAX) && CHAR_MAX==255 + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static bool is_finite(const char) { return true; } + static char min() { return 0; } + static char max() { return (char)-1; } + static char inf() { return max(); } + static char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const char val) { return (unsigned int)val; } + }; +#else + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static bool is_finite(const char) { return true; } + static char min() { return ~max(); } + static char max() { return (char)((unsigned char)-1>>1); } + static char inf() { return max(); } + static char cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(char)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const char val) { return (int)val; } + }; +#endif + + template<> struct type { + static const char* string() { static const char *const s = "signed char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const signed char) { return false; } + static bool is_nan(const signed char) { return false; } + static bool is_finite(const signed char) { return true; } + static signed char min() { return ~max(); } + static signed char max() { return (signed char)((unsigned char)-1>>1); } + static signed char inf() { return max(); } + static signed char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(signed char)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const signed char val) { return (int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned short) { return false; } + static bool is_nan(const unsigned short) { return false; } + static bool is_finite(const unsigned short) { return true; } + static unsigned short min() { return 0; } + static unsigned short max() { return (unsigned short)-1; } + static unsigned short inf() { return max(); } + static unsigned short cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned short)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned short val) { return (unsigned int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const short) { return false; } + static bool is_nan(const short) { return false; } + static bool is_finite(const short) { return true; } + static short min() { return ~max(); } + static short max() { return (short)((unsigned short)-1>>1); } + static short inf() { return max(); } + static short cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(short)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const short val) { return (int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned int) { return false; } + static bool is_nan(const unsigned int) { return false; } + static bool is_finite(const unsigned int) { return true; } + static unsigned int min() { return 0; } + static unsigned int max() { return (unsigned int)-1; } + static unsigned int inf() { return max(); } + static unsigned int cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned int)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned int val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const int) { return false; } + static bool is_nan(const int) { return false; } + static bool is_finite(const int) { return true; } + static int min() { return ~max(); } + static int max() { return (int)((unsigned int)-1>>1); } + static int inf() { return max(); } + static int cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(int)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const int val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_uint64) { return false; } + static bool is_nan(const cimg_uint64) { return false; } + static bool is_finite(const cimg_uint64) { return true; } + static cimg_uint64 min() { return 0; } + static cimg_uint64 max() { return (cimg_uint64)-1; } + static cimg_uint64 inf() { return max(); } + static cimg_uint64 cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(cimg_uint64)val; } + static const char* format() { return cimg_fuint64; } + static const char* format_s() { return cimg_fuint64; } + static cimg_uint64 format(const cimg_uint64 val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_int64) { return false; } + static bool is_nan(const cimg_int64) { return false; } + static bool is_finite(const cimg_int64) { return true; } + static cimg_int64 min() { return ~max(); } + static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); } + static cimg_int64 inf() { return max(); } + static cimg_int64 cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(cimg_int64)val; + } + static const char* format() { return cimg_fint64; } + static const char* format_s() { return cimg_fint64; } + static long format(const long val) { return (long)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const double val) { // Custom version that works with '-ffast-math' + if (sizeof(double)==8) { + cimg_uint64 u; + std::memcpy(&u,&val,sizeof(double)); + return ((unsigned int)(u>>32)&0x7fffffff) + ((unsigned int)u!=0)>0x7ff00000; + } +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const double val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static double min() { return -DBL_MAX; } + static double max() { return DBL_MAX; } + static double inf() { +#ifdef INFINITY + return (double)INFINITY; +#else + return max()*max(); +#endif + } + static double nan() { +#ifdef NAN + return (double)NAN; +#else + const double val_nan = -std::sqrt(-1.); return val_nan; +#endif + } + static double cut(const double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const double val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "float"; return s; } + static bool is_float() { return true; } + static bool is_inf(const float val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const float val) { // Custom version that works with '-ffast-math' + if (sizeof(float)==4) { + unsigned int u; + std::memcpy(&u,&val,sizeof(float)); + return (u&0x7fffffff)>0x7f800000; + } +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const float val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static float min() { return -FLT_MAX; } + static float max() { return FLT_MAX; } + static float inf() { return (float)cimg::type::inf(); } + static float nan() { return (float)cimg::type::nan(); } + static float cut(const double val) { return (float)val; } + static float cut(const float val) { return (float)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const float val) { return (double)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "long double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const long double val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const long double val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static long double min() { return -LDBL_MAX; } + static long double max() { return LDBL_MAX; } + static long double inf() { return max()*max(); } + static long double nan() { const long double val_nan = -std::sqrt(-1.L); return val_nan; } + static long double cut(const long double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const long double val) { return (double)val; } + }; + +#ifdef cimg_use_half + template<> struct type { + static const char* string() { static const char *const s = "half"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const half val) { // Custom version that works with '-ffast-math' + if (sizeof(half)==2) { + short u; + std::memcpy(&u,&val,sizeof(short)); + return (bool)((u&0x7fff)>0x7c00); + } + return cimg::type::is_nan((float)val); + } + static bool is_finite(const half val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static half min() { return (half)-65504; } + static half max() { return (half)65504; } + static half inf() { return max()*max(); } + static half nan() { const half val_nan = (half)-std::sqrt(-1.); return val_nan; } + static half cut(const double val) { return (half)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const half val) { return (double)val; } + }; +#endif + + template struct superset { typedef T type; }; + template<> struct superset { typedef unsigned char type; }; + template<> struct superset { typedef char type; }; + template<> struct superset { typedef signed char type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + +#ifdef cimg_use_half + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; +#endif + + template struct superset2 { + typedef typename superset::type>::type type; + }; + + template struct superset3 { + typedef typename superset::type>::type type; + }; + + template struct last { typedef t2 type; }; + +#define _cimg_Tt typename cimg::superset::type +#define _cimg_Tfloat typename cimg::superset::type +#define _cimg_tfloat typename cimg::superset::type +#define _cimg_Ttfloat typename cimg::superset2::type +#define _cimg_Ttdouble typename cimg::superset2::type + + // Define variables used internally by CImg. +#if cimg_display==1 + struct X11_static { + unsigned int nb_wins; + pthread_t *events_thread; + pthread_cond_t wait_event; + pthread_mutex_t wait_event_mutex; + CImgDisplay **wins; + Display *display; + unsigned int nb_bits; + bool is_blue_first; + bool is_shm_enabled; + bool byte_order; + +#ifdef cimg_use_xrandr + XRRScreenSize *resolutions; + Rotation curr_rotation; + unsigned int curr_resolution; + unsigned int nb_resolutions; +#endif + X11_static():nb_wins(0),events_thread(0),display(0), + nb_bits(0),is_blue_first(false),is_shm_enabled(false),byte_order(false) { +#ifdef __FreeBSD__ + XInitThreads(); +#endif + wins = new CImgDisplay*[1024]; + pthread_mutex_init(&wait_event_mutex,0); + pthread_cond_init(&wait_event,0); + +#ifdef cimg_use_xrandr + resolutions = 0; + curr_rotation = 0; + curr_resolution = nb_resolutions = 0; +#endif + } + + ~X11_static() { + delete[] wins; + /* + if (events_thread) { + pthread_cancel(*events_thread); + delete events_thread; + } + if (display) { } // XCloseDisplay(display); } + pthread_cond_destroy(&wait_event); + pthread_mutex_unlock(&wait_event_mutex); + pthread_mutex_destroy(&wait_event_mutex); + */ + } + }; // struct X11_static { ... +#if defined(cimg_module) + X11_static& X11_attr(); +#elif defined(cimg_main) + X11_static& X11_attr() { static X11_static val; return val; } +#else + inline X11_static& X11_attr() { static X11_static val; return val; } +#endif + +#elif cimg_display==2 + struct Win32_static { + HANDLE wait_event; + Win32_static() { wait_event = CreateEvent(0,FALSE_WIN,FALSE_WIN,0); } + }; // struct Win32_static { ... +#if defined(cimg_module) + Win32_static& Win32_attr(); +#elif defined(cimg_main) + Win32_static& Win32_attr() { static Win32_static val; return val; } +#else + inline Win32_static& Win32_attr() { static Win32_static val; return val; } +#endif +#endif +#define cimg_lock_display() cimg::mutex(15) +#define cimg_unlock_display() cimg::mutex(15,0) + + struct Mutex_static { +#if cimg_OS==1 && (defined(cimg_use_pthread) || cimg_display==1) + pthread_mutex_t mutex[32]; + Mutex_static() { for (unsigned int i = 0; i<32; ++i) pthread_mutex_init(&mutex[i],0); } + void lock(const unsigned int n) { pthread_mutex_lock(&mutex[n]); } + void unlock(const unsigned int n) { pthread_mutex_unlock(&mutex[n]); } + int trylock(const unsigned int n) { return pthread_mutex_trylock(&mutex[n]); } +#elif cimg_OS==2 + HANDLE mutex[32]; + Mutex_static() { for (unsigned int i = 0; i<32; ++i) mutex[i] = CreateMutex(0,FALSE_WIN,0); } + void lock(const unsigned int n) { WaitForSingleObject(mutex[n],INFINITE); } + void unlock(const unsigned int n) { ReleaseMutex(mutex[n]); } + int trylock(const unsigned int) { return 0; } +#else + Mutex_static() {} + void lock(const unsigned int) {} + void unlock(const unsigned int) {} + int trylock(const unsigned int) { return 0; } +#endif + }; // struct Mutex_static { ... +#if defined(cimg_module) + Mutex_static& Mutex_attr(); +#elif defined(cimg_main) + Mutex_static& Mutex_attr() { static Mutex_static val; return val; } +#else + inline Mutex_static& Mutex_attr() { static Mutex_static val; return val; } +#endif + +#if defined(cimg_use_magick) + struct Magick_static { + Magick_static() { + Magick::InitializeMagick(""); + } + }; // struct Magick_static { ... + static Magick_static _Magick_static; +#endif + +#if defined(cimg_use_fftw3) && !defined(cimg_use_fftw3_singlethread) + struct FFTW3_static { + FFTW3_static() { + fftw_init_threads(); + } + }; // struct FFTW3_static { ... + static FFTW3_static _FFTW3_static; +#endif + +#if cimg_display==1 + // Define keycodes for X11-based graphical systems. + const unsigned int keyESC = XK_Escape; + const unsigned int keyF1 = XK_F1; + const unsigned int keyF2 = XK_F2; + const unsigned int keyF3 = XK_F3; + const unsigned int keyF4 = XK_F4; + const unsigned int keyF5 = XK_F5; + const unsigned int keyF6 = XK_F6; + const unsigned int keyF7 = XK_F7; + const unsigned int keyF8 = XK_F8; + const unsigned int keyF9 = XK_F9; + const unsigned int keyF10 = XK_F10; + const unsigned int keyF11 = XK_F11; + const unsigned int keyF12 = XK_F12; + const unsigned int keyPAUSE = XK_Pause; + const unsigned int key1 = XK_1; + const unsigned int key2 = XK_2; + const unsigned int key3 = XK_3; + const unsigned int key4 = XK_4; + const unsigned int key5 = XK_5; + const unsigned int key6 = XK_6; + const unsigned int key7 = XK_7; + const unsigned int key8 = XK_8; + const unsigned int key9 = XK_9; + const unsigned int key0 = XK_0; + const unsigned int keyBACKSPACE = XK_BackSpace; + const unsigned int keyINSERT = XK_Insert; + const unsigned int keyHOME = XK_Home; + const unsigned int keyPAGEUP = XK_Page_Up; + const unsigned int keyTAB = XK_Tab; + const unsigned int keyQ = XK_q; + const unsigned int keyW = XK_w; + const unsigned int keyE = XK_e; + const unsigned int keyR = XK_r; + const unsigned int keyT = XK_t; + const unsigned int keyY = XK_y; + const unsigned int keyU = XK_u; + const unsigned int keyI = XK_i; + const unsigned int keyO = XK_o; + const unsigned int keyP = XK_p; + const unsigned int keyDELETE = XK_Delete; + const unsigned int keyEND = XK_End; + const unsigned int keyPAGEDOWN = XK_Page_Down; + const unsigned int keyCAPSLOCK = XK_Caps_Lock; + const unsigned int keyA = XK_a; + const unsigned int keyS = XK_s; + const unsigned int keyD = XK_d; + const unsigned int keyF = XK_f; + const unsigned int keyG = XK_g; + const unsigned int keyH = XK_h; + const unsigned int keyJ = XK_j; + const unsigned int keyK = XK_k; + const unsigned int keyL = XK_l; + const unsigned int keyENTER = XK_Return; + const unsigned int keySHIFTLEFT = XK_Shift_L; + const unsigned int keyZ = XK_z; + const unsigned int keyX = XK_x; + const unsigned int keyC = XK_c; + const unsigned int keyV = XK_v; + const unsigned int keyB = XK_b; + const unsigned int keyN = XK_n; + const unsigned int keyM = XK_m; + const unsigned int keySHIFTRIGHT = XK_Shift_R; + const unsigned int keyARROWUP = XK_Up; + const unsigned int keyCTRLLEFT = XK_Control_L; + const unsigned int keyAPPLEFT = XK_Super_L; + const unsigned int keyALT = XK_Alt_L; + const unsigned int keySPACE = XK_space; + const unsigned int keyALTGR = XK_Alt_R; + const unsigned int keyAPPRIGHT = XK_Super_R; + const unsigned int keyMENU = XK_Menu; + const unsigned int keyCTRLRIGHT = XK_Control_R; + const unsigned int keyARROWLEFT = XK_Left; + const unsigned int keyARROWDOWN = XK_Down; + const unsigned int keyARROWRIGHT = XK_Right; + const unsigned int keyPAD0 = XK_KP_0; + const unsigned int keyPAD1 = XK_KP_1; + const unsigned int keyPAD2 = XK_KP_2; + const unsigned int keyPAD3 = XK_KP_3; + const unsigned int keyPAD4 = XK_KP_4; + const unsigned int keyPAD5 = XK_KP_5; + const unsigned int keyPAD6 = XK_KP_6; + const unsigned int keyPAD7 = XK_KP_7; + const unsigned int keyPAD8 = XK_KP_8; + const unsigned int keyPAD9 = XK_KP_9; + const unsigned int keyPADADD = XK_KP_Add; + const unsigned int keyPADSUB = XK_KP_Subtract; + const unsigned int keyPADMUL = XK_KP_Multiply; + const unsigned int keyPADDIV = XK_KP_Divide; + +#elif cimg_display==2 + // Define keycodes for Windows. + const unsigned int keyESC = VK_ESCAPE; + const unsigned int keyF1 = VK_F1; + const unsigned int keyF2 = VK_F2; + const unsigned int keyF3 = VK_F3; + const unsigned int keyF4 = VK_F4; + const unsigned int keyF5 = VK_F5; + const unsigned int keyF6 = VK_F6; + const unsigned int keyF7 = VK_F7; + const unsigned int keyF8 = VK_F8; + const unsigned int keyF9 = VK_F9; + const unsigned int keyF10 = VK_F10; + const unsigned int keyF11 = VK_F11; + const unsigned int keyF12 = VK_F12; + const unsigned int keyPAUSE = VK_PAUSE; + const unsigned int key1 = '1'; + const unsigned int key2 = '2'; + const unsigned int key3 = '3'; + const unsigned int key4 = '4'; + const unsigned int key5 = '5'; + const unsigned int key6 = '6'; + const unsigned int key7 = '7'; + const unsigned int key8 = '8'; + const unsigned int key9 = '9'; + const unsigned int key0 = '0'; + const unsigned int keyBACKSPACE = VK_BACK; + const unsigned int keyINSERT = VK_INSERT; + const unsigned int keyHOME = VK_HOME; + const unsigned int keyPAGEUP = VK_PRIOR; + const unsigned int keyTAB = VK_TAB; + const unsigned int keyQ = 'Q'; + const unsigned int keyW = 'W'; + const unsigned int keyE = 'E'; + const unsigned int keyR = 'R'; + const unsigned int keyT = 'T'; + const unsigned int keyY = 'Y'; + const unsigned int keyU = 'U'; + const unsigned int keyI = 'I'; + const unsigned int keyO = 'O'; + const unsigned int keyP = 'P'; + const unsigned int keyDELETE = VK_DELETE; + const unsigned int keyEND = VK_END; + const unsigned int keyPAGEDOWN = VK_NEXT; + const unsigned int keyCAPSLOCK = VK_CAPITAL; + const unsigned int keyA = 'A'; + const unsigned int keyS = 'S'; + const unsigned int keyD = 'D'; + const unsigned int keyF = 'F'; + const unsigned int keyG = 'G'; + const unsigned int keyH = 'H'; + const unsigned int keyJ = 'J'; + const unsigned int keyK = 'K'; + const unsigned int keyL = 'L'; + const unsigned int keyENTER = VK_RETURN; + const unsigned int keySHIFTLEFT = VK_SHIFT; + const unsigned int keyZ = 'Z'; + const unsigned int keyX = 'X'; + const unsigned int keyC = 'C'; + const unsigned int keyV = 'V'; + const unsigned int keyB = 'B'; + const unsigned int keyN = 'N'; + const unsigned int keyM = 'M'; + const unsigned int keySHIFTRIGHT = VK_SHIFT; + const unsigned int keyARROWUP = VK_UP; + const unsigned int keyCTRLLEFT = VK_CONTROL; + const unsigned int keyAPPLEFT = VK_LWIN; + const unsigned int keyALT = VK_LMENU; + const unsigned int keySPACE = VK_SPACE; + const unsigned int keyALTGR = VK_CONTROL; + const unsigned int keyAPPRIGHT = VK_RWIN; + const unsigned int keyMENU = VK_APPS; + const unsigned int keyCTRLRIGHT = VK_CONTROL; + const unsigned int keyARROWLEFT = VK_LEFT; + const unsigned int keyARROWDOWN = VK_DOWN; + const unsigned int keyARROWRIGHT = VK_RIGHT; + const unsigned int keyPAD0 = 0x60; + const unsigned int keyPAD1 = 0x61; + const unsigned int keyPAD2 = 0x62; + const unsigned int keyPAD3 = 0x63; + const unsigned int keyPAD4 = 0x64; + const unsigned int keyPAD5 = 0x65; + const unsigned int keyPAD6 = 0x66; + const unsigned int keyPAD7 = 0x67; + const unsigned int keyPAD8 = 0x68; + const unsigned int keyPAD9 = 0x69; + const unsigned int keyPADADD = VK_ADD; + const unsigned int keyPADSUB = VK_SUBTRACT; + const unsigned int keyPADMUL = VK_MULTIPLY; + const unsigned int keyPADDIV = VK_DIVIDE; + +#else + // Define random keycodes when no display is available. + // (should rarely be used then!). + const unsigned int keyESC = 1U; //!< Keycode for the \c ESC key (architecture-dependent) + const unsigned int keyF1 = 2U; //!< Keycode for the \c F1 key (architecture-dependent) + const unsigned int keyF2 = 3U; //!< Keycode for the \c F2 key (architecture-dependent) + const unsigned int keyF3 = 4U; //!< Keycode for the \c F3 key (architecture-dependent) + const unsigned int keyF4 = 5U; //!< Keycode for the \c F4 key (architecture-dependent) + const unsigned int keyF5 = 6U; //!< Keycode for the \c F5 key (architecture-dependent) + const unsigned int keyF6 = 7U; //!< Keycode for the \c F6 key (architecture-dependent) + const unsigned int keyF7 = 8U; //!< Keycode for the \c F7 key (architecture-dependent) + const unsigned int keyF8 = 9U; //!< Keycode for the \c F8 key (architecture-dependent) + const unsigned int keyF9 = 10U; //!< Keycode for the \c F9 key (architecture-dependent) + const unsigned int keyF10 = 11U; //!< Keycode for the \c F10 key (architecture-dependent) + const unsigned int keyF11 = 12U; //!< Keycode for the \c F11 key (architecture-dependent) + const unsigned int keyF12 = 13U; //!< Keycode for the \c F12 key (architecture-dependent) + const unsigned int keyPAUSE = 14U; //!< Keycode for the \c PAUSE key (architecture-dependent) + const unsigned int key1 = 15U; //!< Keycode for the \c 1 key (architecture-dependent) + const unsigned int key2 = 16U; //!< Keycode for the \c 2 key (architecture-dependent) + const unsigned int key3 = 17U; //!< Keycode for the \c 3 key (architecture-dependent) + const unsigned int key4 = 18U; //!< Keycode for the \c 4 key (architecture-dependent) + const unsigned int key5 = 19U; //!< Keycode for the \c 5 key (architecture-dependent) + const unsigned int key6 = 20U; //!< Keycode for the \c 6 key (architecture-dependent) + const unsigned int key7 = 21U; //!< Keycode for the \c 7 key (architecture-dependent) + const unsigned int key8 = 22U; //!< Keycode for the \c 8 key (architecture-dependent) + const unsigned int key9 = 23U; //!< Keycode for the \c 9 key (architecture-dependent) + const unsigned int key0 = 24U; //!< Keycode for the \c 0 key (architecture-dependent) + const unsigned int keyBACKSPACE = 25U; //!< Keycode for the \c BACKSPACE key (architecture-dependent) + const unsigned int keyINSERT = 26U; //!< Keycode for the \c INSERT key (architecture-dependent) + const unsigned int keyHOME = 27U; //!< Keycode for the \c HOME key (architecture-dependent) + const unsigned int keyPAGEUP = 28U; //!< Keycode for the \c PAGEUP key (architecture-dependent) + const unsigned int keyTAB = 29U; //!< Keycode for the \c TAB key (architecture-dependent) + const unsigned int keyQ = 30U; //!< Keycode for the \c Q key (architecture-dependent) + const unsigned int keyW = 31U; //!< Keycode for the \c W key (architecture-dependent) + const unsigned int keyE = 32U; //!< Keycode for the \c E key (architecture-dependent) + const unsigned int keyR = 33U; //!< Keycode for the \c R key (architecture-dependent) + const unsigned int keyT = 34U; //!< Keycode for the \c T key (architecture-dependent) + const unsigned int keyY = 35U; //!< Keycode for the \c Y key (architecture-dependent) + const unsigned int keyU = 36U; //!< Keycode for the \c U key (architecture-dependent) + const unsigned int keyI = 37U; //!< Keycode for the \c I key (architecture-dependent) + const unsigned int keyO = 38U; //!< Keycode for the \c O key (architecture-dependent) + const unsigned int keyP = 39U; //!< Keycode for the \c P key (architecture-dependent) + const unsigned int keyDELETE = 40U; //!< Keycode for the \c DELETE key (architecture-dependent) + const unsigned int keyEND = 41U; //!< Keycode for the \c END key (architecture-dependent) + const unsigned int keyPAGEDOWN = 42U; //!< Keycode for the \c PAGEDOWN key (architecture-dependent) + const unsigned int keyCAPSLOCK = 43U; //!< Keycode for the \c CAPSLOCK key (architecture-dependent) + const unsigned int keyA = 44U; //!< Keycode for the \c A key (architecture-dependent) + const unsigned int keyS = 45U; //!< Keycode for the \c S key (architecture-dependent) + const unsigned int keyD = 46U; //!< Keycode for the \c D key (architecture-dependent) + const unsigned int keyF = 47U; //!< Keycode for the \c F key (architecture-dependent) + const unsigned int keyG = 48U; //!< Keycode for the \c G key (architecture-dependent) + const unsigned int keyH = 49U; //!< Keycode for the \c H key (architecture-dependent) + const unsigned int keyJ = 50U; //!< Keycode for the \c J key (architecture-dependent) + const unsigned int keyK = 51U; //!< Keycode for the \c K key (architecture-dependent) + const unsigned int keyL = 52U; //!< Keycode for the \c L key (architecture-dependent) + const unsigned int keyENTER = 53U; //!< Keycode for the \c ENTER key (architecture-dependent) + const unsigned int keySHIFTLEFT = 54U; //!< Keycode for the \c SHIFTLEFT key (architecture-dependent) + const unsigned int keyZ = 55U; //!< Keycode for the \c Z key (architecture-dependent) + const unsigned int keyX = 56U; //!< Keycode for the \c X key (architecture-dependent) + const unsigned int keyC = 57U; //!< Keycode for the \c C key (architecture-dependent) + const unsigned int keyV = 58U; //!< Keycode for the \c V key (architecture-dependent) + const unsigned int keyB = 59U; //!< Keycode for the \c B key (architecture-dependent) + const unsigned int keyN = 60U; //!< Keycode for the \c N key (architecture-dependent) + const unsigned int keyM = 61U; //!< Keycode for the \c M key (architecture-dependent) + const unsigned int keySHIFTRIGHT = 62U; //!< Keycode for the \c SHIFTRIGHT key (architecture-dependent) + const unsigned int keyARROWUP = 63U; //!< Keycode for the \c ARROWUP key (architecture-dependent) + const unsigned int keyCTRLLEFT = 64U; //!< Keycode for the \c CTRLLEFT key (architecture-dependent) + const unsigned int keyAPPLEFT = 65U; //!< Keycode for the \c APPLEFT key (architecture-dependent) + const unsigned int keyALT = 66U; //!< Keycode for the \c ALT key (architecture-dependent) + const unsigned int keySPACE = 67U; //!< Keycode for the \c SPACE key (architecture-dependent) + const unsigned int keyALTGR = 68U; //!< Keycode for the \c ALTGR key (architecture-dependent) + const unsigned int keyAPPRIGHT = 69U; //!< Keycode for the \c APPRIGHT key (architecture-dependent) + const unsigned int keyMENU = 70U; //!< Keycode for the \c MENU key (architecture-dependent) + const unsigned int keyCTRLRIGHT = 71U; //!< Keycode for the \c CTRLRIGHT key (architecture-dependent) + const unsigned int keyARROWLEFT = 72U; //!< Keycode for the \c ARROWLEFT key (architecture-dependent) + const unsigned int keyARROWDOWN = 73U; //!< Keycode for the \c ARROWDOWN key (architecture-dependent) + const unsigned int keyARROWRIGHT = 74U; //!< Keycode for the \c ARROWRIGHT key (architecture-dependent) + const unsigned int keyPAD0 = 75U; //!< Keycode for the \c PAD0 key (architecture-dependent) + const unsigned int keyPAD1 = 76U; //!< Keycode for the \c PAD1 key (architecture-dependent) + const unsigned int keyPAD2 = 77U; //!< Keycode for the \c PAD2 key (architecture-dependent) + const unsigned int keyPAD3 = 78U; //!< Keycode for the \c PAD3 key (architecture-dependent) + const unsigned int keyPAD4 = 79U; //!< Keycode for the \c PAD4 key (architecture-dependent) + const unsigned int keyPAD5 = 80U; //!< Keycode for the \c PAD5 key (architecture-dependent) + const unsigned int keyPAD6 = 81U; //!< Keycode for the \c PAD6 key (architecture-dependent) + const unsigned int keyPAD7 = 82U; //!< Keycode for the \c PAD7 key (architecture-dependent) + const unsigned int keyPAD8 = 83U; //!< Keycode for the \c PAD8 key (architecture-dependent) + const unsigned int keyPAD9 = 84U; //!< Keycode for the \c PAD9 key (architecture-dependent) + const unsigned int keyPADADD = 85U; //!< Keycode for the \c PADADD key (architecture-dependent) + const unsigned int keyPADSUB = 86U; //!< Keycode for the \c PADSUB key (architecture-dependent) + const unsigned int keyPADMUL = 87U; //!< Keycode for the \c PADMUL key (architecture-dependent) + const unsigned int keyPADDIV = 88U; //!< Keycode for the \c PADDDIV key (architecture-dependent) +#endif + + const double PI = 3.14159265358979323846; //!< Value of the mathematical constant PI + + // Define a 10x13 binary font (small sans). + static const char *const data_font_small[] = { + " UwlwnwoyuwHwlwmwcwlwnw[xuwowlwmwoyuwRwlwnxcw Mw (wnwnwuwpwuypwuwoy" + "ZwnwmwuwowuwmwnwnwuwowuwfwuxnwnwmwuwpwuypwuwZwnwnwtwpwtwow'y Hw cwnw >{ jw %xdxZwdw_wexfwYwkw 7yowoyFx=w " + "ry qw %wuw !xnwkwnwoyuwfwuw[wkwnwcwowrwpwdwuwoxuwpwkwnwoyuwRwkwnwbwpwNyoyoyoyoy;wdwnxpxtxowG|!ydwnwuwowtwow" + "pxswqxlwnxnxmwDwoyoxnyoymwp{oyq{pyoy>ypwqwpwp{oyqzo{q{pzrwrwowlwqwswpwnwqwsxswpypzoyqzozq}swrwrwqwtwswswtxsxswq" + "ws}qwnwkwnydwew_wfwdwkwmwowkw(w0wmwmwGwtwdxQw swuwnwo{q{pynwp|rwtwtwqydwcwcwcwmwmxgwqwpwnzpwuwpzoyRzoyoyexnynwd" + "z\\xnxgxrwsxrwsyswowmwmwmwmwmwmwo}ryp{q{q{q{nwmwnwmwozqxswpyoyoyoyoyeyuwswrwrwrwrwrwrwrwrwqwrwmwtwnwmwnwuwpwuyp" + "wuwoyZwmwnwuwowuwmwqwkwuwowuwoxnwuxowmwnwuwpwuypwuwZwmwnwuwowuwnwowmwtw\\wuwuwqwswqwswqwswqwswEwqwtweypzr~qyIw " + "rwswewnwuwowuwozswtwuwqwtwmwnwlwowuwuwowOxpxuxqwuwowswqwswoxpwlwjwqwswqwswy~}P{|k~-{|w~}k{|w~}Ww~|S{|k~X{|v~vv~|Y{|}k~}|Z{|y~" + "}y|xy|}w~| s{|}k~}|Z{|l~|V{}p~}\"{|y~}|w{|}w~|V{|}|u{|v~P{}x~} {{}h~} N{|~y}y|}x~|S{|v~}|y{|}w~}2{|w~y}x~|g{}x" + "~|k{|w~y}x~|g{}x~|kx}|w{|}w~}k{}x~}%{}t~|P{}t~|P{}t~|P{}t~|P{}t~|P{}t~}W{|[~}e{}f~}b{}c~|a{}c~|a{}c~|a{}c~|X{}w" + "~}M{}w~}M{}w~}M{}w~}Z{|d~}|`{}t~}kv~b{|g~}]{|g~}]{|g~}]{|g~}]{|g~}){|g~|{|w~|h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f" + "{|v~h{}w~}f{|v~|j{|v~|b{}w~}L{|u~}|w{|}v~|W{|w~|Iw~}Qw~x{}x~|V{}y~}x{}s~|X{|v~|wv~}Vx~}v{|x~| D{}x~}I{}w~Q{}x~|" + "xw~U{}w~}w{|v~T{|w~|J{|w~Q{|x~}x{|x~|V{|v~vv~|T{}q~}|Wx~|x{}s~T{|w~I{|w~|R{|x~}x{}x~|Vx~}x{}s~|X{|v~vv~| Fw~}J{" + "|w~|R{|x~}x{|x~}Uv~|w{}w~}Q{|w~|Ww~}Hv~}w{}w~} Pw~}y{|x~}cY~ i{}y~|#{|w~}Qm~|`m~}w{|m~|\\{}v~| ;{}`~} -" + "{|r~x}t~}$v~}R{}x~}vw~}S{|w~t{|x~}U{|y~|_{|w~}w{}w~|n{}x~}_{|t~w}u~|Q{}x~}K{}w~N{}x~}Jx~ +{|w~Xs~y}s~|\\m~}X{}" + "f~\\{}g~}R{|s~}\\{|g~}Y{|i~|`{}c~|_{|s~w}s~}]{|s~x}s~ hr~}r~|[{|f~}Xs~}Y{}d~|\\{|c~}g{}b~|^{}c~|`{}e~_{|a~|g{" + "}w~}hv~|Y{}w~}M{}w~}W{}w~}n{|u~|_{}w~}V{}s~}jr~|h{}s~|lv~c{|p~}q~}^{}f~}_{|p~}q~}`{}e~[{}q~}p~dZ~g{|v~h{}w~}h{|" + "v~|f{|v~p{|v~m{|t~}m{}w~}m{|v~|m{}v~c{}v~jv~}e\\~]{|w~}Nw~}D{|w~|Sp~| ww~|!w~} `{|w~|${}w~}!w~}Cv~Lv~Tw~}Dv~ " + " Ov~ !{}w~}Mw~|N{|v~ :{}v~|s{|v~V{|t}|V{|t~s}w~| p{|v~ {{|v~|t{|v~|Vs~}W{}c~|_{}d~}c{|d~|W{|v~Y{}^~|iv~" + "}r{|v~qv~}f{|p~}q~}${}r~} v{}w~ v{}q~| ?y~}Ps~x}u~,v~k{}w~|Ww~|Su~}v|}w~X{|v~vv~|Z{}v~}y|wy|}v~}[{|}q{}x~} t{}" + "v~}y|wy|}v~}&{}w~|x{|w~}#y|r{}x~}Kw~|R{|w~ {{}p~}v|x~} H{}x~|S{}w~t{}w~|3x|x{}x~|h{|x~}j{|}|x{}x~|h{|x~}`{|w~l{" + "|w~$s~}Ps~}Ps~}Ps~}Ps~}Pr~W{}[~}g{|c~}c{}c~|a{}c~|a{}c~|a{}c~|X{}w~}M{}w~}M{}w~}M{}w~}Z{|b~}a{}s~|lv~c{|p~}q~}_" + "{|p~}q~}_{|p~}q~}_{|p~}q~}_{|p~}q~}+{|p~}q~}w~|g{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}e{}v~jv~}a{}w~}Lu~r{" + "|v~V{|w~J{}x~}Q{}x~|w{}x~Vx~|w{}u~}Vv|vv|U{}x~}x|}w~ Bw~|K{|w~|R{|x~}w{|x~}Vu|vv|S{|w~K{|w~|Qx~}v{}x~Uv|vv|T{|}" + "t~}|Tx~|w{|u~|S{}x~}Jw~}Qw~vw~Vx~|w{}u~}Vv|vv| Dw~|Kw~|Qw~v{}x~|Vv|vv|Pw~|Vw~}Hv|uv| G{|t}|P{|t}|P{|t}|P{|t}|P{" + "|t}|Lw~|xw~c{|[~} iy~}\"u~|S{|l~a{}l~|x{}l~]{}t~ ={|^~} .{|u~}|u{|}w~}$v~}R{}x~}vw~}S{}x~}t{}x~}Xy|y}y~y}x" + "|cw~}u{}w~o{|w~^u~}t{|}y~|Q{}x~}Kw~|N{|w~|T{}sx~s{} 4{}x~}Y{}v~}|v{}u~\\m~}X{}v~y}|wy|s~]{}x~}x|v{|}t~}Sr~}\\{" + "|v~k|Z{|t~}|v{|y}y~|`h|u~^t~|u{|}u~|^u~}|v{|}v~} iv~y|v{|t~]{|o~y}p~|[{|r~|Z{}w~}q|}s~]{|s~}|t{|}u~}g{}w~}r|y" + "}q~}_{}w~}h|_{}w~}j|`{|s~}|s{|}t~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}o{}u~|^{}w~}V{}r~k{|r~|h{}r~lv~d{|t~}|uy|s~_{}w~}" + "s|y}t~}a{|t~}|uy|s~a{}w~}s|y}s~]{}u~}|ty|}v~dn|}v~}n|g{|v~h{}w~}gv~}f{}w~}ov~|n{|t~}mv~|l{}v~|o{|v~|bv~}l{}v~dc" + "|u~}]{|w~}N{}w~D{|w~|T{}o~| x{|w~!w~} `{|w~|${}w~ w~} >w~}Dv~ Ov~ !{}w~|Mw~|M{}w~ :v~|q{}w~|Xp~}X{}v~|p{|" + "}| o{}w~| v~|r{|v~W{|r~|X{}v~}i|^{}w~}h|d{|s~}y|xy|}s~}[{|y}u~y}y|]{}w~}h|v~|iv~}r{|v~qv~}g{|t~}|uy|s~&{}p" + "~} w{}w~ w{}o~| @y~}Q{}v~}|u{|}y~,{|w~}m{|w~}Vw~|T{|v~|s{|}~({|w~}|o{|}w~|P{}x~| w{|w~}|o{|}w~|(x~}tw~ rw~K{}x" + "~|Rw~ {{}o~}w{|x~} H{}x~|T{|w~r{}x~}-{}x~|hw~|d{}x~|hw~|_{}x~|mw~|%{|r~|R{|r~|R{|r~|R{|r~|R{|r~|R{}r~|Y{|v~|y{|" + "v~}h|h{|s~}|t{|}u~}c{}w~}h|`{}w~}h|`{}w~}h|`{}w~}h|W{}w~}M{}w~}M{}w~}M{}w~}Z{|v~r|x}q~b{}r~lv~d{|t~}|uy|s~a{|t~" + "}|uy|s~a{|t~}|uy|s~a{|t~}|uy|s~a{|t~}|uy|s~-{|t~}|u{|}q~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}dv~}l{}v~`" + "{}w~}M{|v~p{}w~|V{}x~}L{}x~}Q{|x~|ux~}Wx~|v{|w~} {{}q~| Aw~|Lw~|Qw~u{}x~| y{|x~}Lw~|Q{}x~tx~}#{|}r~}Rx~u{|}y~}|" + "Q{}x~}L{}x~}Q{}x~|v{|x~}Wx~|v{}w~} j{|w~L{}x~}Q{}x~|u{}x~ x{}x~}Uw~} b{|}p~}|V{|}p~}|V{|}p~}|V{|}p~}|V{|}p~}|" + "P{|w~|xx|av~|fv~| j{|y~|#{}t~Sk~|c{|k~}y{|k~}_{|s~} ?{}t~}y| u{|u~|p{}y~}$v~}R{}x~}vw~}Sw~|tw~|[{|}m~}|h{" + "|w~sw~|p{}x~|_{}v~|q{|}|Q{}x~}L{}w~Lw~}U{}y~|ux~u{|y~}U{|x}| `w~|Z{|v~}s{|v~}]w~y}y|{}w~}X{}x~|p{|u~|^y}|n{|u~" + "|U{}x~y}w~}\\{|w~}K{|u~}o{}|Mv~|_{}v~}q{|u~_{}v~}r{|v~| jy~}|qu~|_{}t~}y|s{|}t~}\\{}w~}w~}Z{}w~}o{|u~}_{|t~|n" + "{|}x~}g{}w~}n{|}t~}`{}w~}L{}w~}P{|t~}m{|}w~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}p{}u~|]{}w~}V{}w~}w~|l{}r~|h{}r~|mv~e{|" + "u~}|p{|t~`{}w~}q{|}u~|c{|u~}|p{|t~b{}w~}p{}u~|_{|u~|n{|}y~W{|v~|Z{|v~h{}w~}g{|v~fv~|o{}w~}n{}x~}w~mv~|kv~}ov~}a" + "{|v~|n{|v~|M{}v~}\\{|w~}N{|w~|E{|w~|U{}v~}{|u~| x{|x~}\"w~} `{|w~|$v~ w~} >w~}Dv~ Ov~ !v~Lw~|M{}w~| <{|w~" + "}p{|w~}Xn~|Zv~ _{|v~ !{|w~}p{}w~}X{}w~}w~}W{}v~|M{}w~}R{|t~|p{|t~|_{|}l~}|`{}w~}hv~|iv~}r{|v~qv~}h{|u~}|p{|" + "t~({}n~} x{}w~ x{}m~| Ay~}R{|v~}p{}+{}w~|nv~Uw~|T{}w~| x{|w~|k{|w~|Q{|x~| x{|w~|k{|w~|*{|x~rx~|R{|w}Fw~Kw~|S{}" + "x~| {|n~}w{|x~} H{}x~|T{}x~}qw~|.{}x~|i{}x~}c{}x~|i{}x~}^{}x~|n{}x~}${}w~}w~}R{}w~}w~}R{}w~}w~}R{}w~}w~}R{}w~}w" + "~}Rv~|w~}Y{}w~}x{|v~U{|t~|n{|}x~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~n{|}s~c{}r~|mv~e{|u~}|p{|" + "t~c{|u~}|p{|t~c{|u~}|p{|t~c{|u~}|p{|t~c{|u~}|p{|t~/{|u~}|p{}t~}e{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}d{|v" + "~|n{|v~|`{}w~}M{}w~}ow~}U{}x~|N{|w~Px~}t{|x~|Xx|sy| w{}s~| @{|w~M{}x~|Q{}x~|tw~ x{}x~}N{}x~|Q{|x~|t{|x~|&{}t~}v" + "~} t{}x~|N{|x~}Q{|x~}t{}x~|Xx|sy| g{|x~}N{|x~}Q{|x~}sx~} {{|x~}Tw~} d{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|j~|R{|w~Z{}w~}" + "g{}w~} Ay|J{}y~#{|s~}Tk~}c{}j~|{}j~_q~| A{}u~} q{}v~|n{}~}$v~}R{}x~}vw~}Sw~t{|w~\\{|h~|i{}x~}s{}x~}q{|x~}^" + "v~|C{}x~}Lw~}L{}w~V{|v~|wx~w{|v~|V{}w~ a{|w~Yv~}q{|v~|^{}y|u{}w~}Xy}|m{|u~M{|v~}V{|w~|}w~}\\{|w~}Ku~|?{|v~^u~o" + "{}v~|a{|v~}p{}v~ j{~|nv~}`u~}|l{|}u~]v~{v~Z{}w~}mu~_u~}j{|y~}g{}w~}l{|}u~}a{}w~}L{}w~}Q{|u~}i{|}y~|g{}w~}hv~|" + "Y{}w~}M{}w~}W{}w~}q{}u~|\\{}w~}V{}w~|w~}lw~|v~|h{}q~mv~f{|u~}m{|u~}a{}w~}o{}v~}d{|u~}m{|u~}c{}w~}o{|u~_{}v~|j{|" + "W{|v~|Z{|v~h{}w~}fv~|h{}v~n{}w~}nw~|w~|o{|v~j{|v~}q{}v~_{}v~nv~}M{|u~[{|w~}Mw~}E{|w~|V{}v~}x{|u~| vw~} `{|w~|$" + "w~} w~} >w~}Dv~ Ov~ !v~Lw~|M{}w~| <{}w~|ow~}Xm~|[v~ ^v~| \"v~|p{|v~Xv~{v~V{}v~|N{}w~}Ru~}l{}u~|b{|g~}" + "|b{}w~}hv~|iv~}r{|v~qv~}i{|u~}m{|u~}*{}l~} y{}w~ y{}k~| By~}R{}v~ y{|w~}o{|w~}Uw~|T{}w~ x{|x~}g{}x~|R{|x~} y{|" + "x~}g{}x~|+{}y~}r{}y~}R{}w~Fx~}M{|}w~ Mm~}w{|x~} H{}x~|Tw~p{}x~|.{}x~|j{|w~b{}x~|j{|w~]w~n{|w~#v~{v~Rv~{v~Rv~{v~" + "Rv~{v~Rv~{v~S{|w~}{}w~|Zv~|x{|v~Uu~}j{|y~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~k{}t~d{}q~mv~f{|" + "u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}1{|u~}m{|u~}e{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w" + "~}c{}v~nv~}_{}w~}Mv~n{}w~Tw}N{|x}P{|x}r{|x} F{|}x~}| ={|x}|O{|x}|Px}|s{|x}| xw|Nw|Pw|rw|'{|v~}|y{|v~} tw}Nw}P{|" + "x}rx}| 6w|Nw|Ox|rw| Nw~} e{}h~}\\{}h~}\\{}h~}\\{}h~}\\{}h~}S{|w~Z{|v~gv~| Ay~}L{|y~}${|q~}V{|j~ci~}|i~|a{}p~|" + "Oy|Uw|jw|Vu|Wv|kw|b{}v~} p{|v~|l{|}$v~}R{}x~}vw~}T{|x~}t{|x~}]{|g~|i{}x~|s{|w~qw~|^v~B{}x~}M{|w~|L{|w~}V{|}" + "w~}xx~x{}w~}|U{}w~ a{}w~Z{|v~o{}w~}U{}w~}X{|j{}v~|M{}v~Vw~}{}w~}\\{|w~}L{|v~|>v~}_{|v~|nv~}a{}v~nv~| \\{}w~}" + "b{|u~|h{|}v~|`{|w~}{}w~|[{}w~}m{|v~|a{}v~}gy}g{}w~}j{}u~|b{}w~}L{}w~}Q{}v~}f{|~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}r{}" + "u~|[{}w~}V{}w~y|w~m{|w~{v~|h{}w~}v~|nv~f{}v~}ju~|b{}w~}nu~d{}v~}ju~|d{}w~}n{}v~|`v~}D{|v~|Z{|v~h{}w~}f{}w~}hv~}" + "n{|v~o{|w~{}x~}o{}w~}i{}v~|s{|v~|^v~}p{}v~M{|u~|[{|w~}M{}x~}E{|w~|W{}v~|v{|u~| ww~} `{|w~|$w~} w~} >w~}Dv~ " + "Ov~ !v~Lw~|M{|w~| <{}w~|ow~}Xy~}w|}t~[v~| _{}w~} #{|w~}n{}w~|Z{|w~}{}w~|Vu~|O{}w~}S{}v~}j{}u~c{}d~|c{}w~" + "}hv~|iv~}r{|v~qv~}i{}v~}ju~|,{}v~y}w~|v~} {{}w~ {{}v~y}w~|u~| Cy~}R{}w~}R{|ey|_{}w~|pv~Tw~|T{}w~ y{|x~}e{}x~|\\" + "{|}p~} {{|x~}e{}x~|,{}y~}r{}y~}R{}w~G{}x~|Rq~| N{|m~}w{|x~} H{}x~|U{|w~p{|x~}.{}x~|j{}x~|b{}x~|j{}x~|_{|w~|n{}" + "x~|${|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{}w~|{|w~}[{|v~w{|v~V{}v~}gy}c{}w~}M{}w~}M{}w~}M{}w~" + "}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~j{|u~}e{}w~}v~|nv~f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|c{}d{}|d{}v~}" + "k{}u~|f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}bv~}p{}v~^{}m~y}|Yv~o{|}w~ Py~}|u{|v~} 2w~} f{" + "}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~T{|w~Yv~|i{|v~ A{}x~}M{}y~|$o~|W{|j~ch~}i~}" + "b{}n~T{|}t~y}|Zw~}kw~}X{}u~|X{}w~|m{}w~|d{|v~| ov~}j{|$v~}R{}x~}vw~}T{}x~}t{}x~}]u~}|{|y~|y{|y}x~|iw~|rw~r{" + "}x~}]v~B{}x~}Mv~Jv~T{|}w~|{x~{|w~}|S{}w~ aw~}Z{}w~}o{|v~U{}w~}Ev~}M{|v~W{}w~y{}w~}\\{|w~}Lv~}>{|v~|_{|v~m{}w~}" + "av~|n{|v~ 8{|y}6{|~|4{}v~c{|v~}d{|v~`{}w~|{|w~}[{}w~}lv~|b{|v~}e{|g{}w~}i{}u~b{}w~}L{}w~}R{|v~}dy|g{}w~}hv~|Y{}" + "w~}M{}w~}W{}w~}s{}u~Y{}w~}V{}w~|{w~|nw~}{v~|h{}w~y|v~nv~g{|v~}i{|u~b{}w~}n{|v~|f{|v~}i{|u~d{}w~}n{|v~|a{|v~C{|v" + "~|Z{|v~h{}w~}f{|v~|j{|v~|mv~|p{|w~{|x~}ov~|hv~}sv~}]{|v~|r{|v~|Mu~|Z{|w~}M{|w~E{|w~|X{}v~|t{|u~| xw~} `{|w~|$w" + "~} w~} >w~}Dv~ Ov~ !w~}Lw~|M{|w~| {|v~]{|v~m{}w~}b{|w~}l{}w~}W{|v}M{}v~D{}r~}6{|r~}|>{|v~|e{}w~|^{|w~|dv~w{|v~\\{}w~}lv~|c{}v~N{}w~}g{}v~|d{" + "}w~}L{}w~}S{}v~L{}w~}hv~|Y{}w~}M{}w~}W{}w~}vu~}V{}w~}V{}w~|yw~}pw~}yv~|h{}w~|y{}w~}pv~h{}v~e{}v~|d{}w~}mv~}g{}v" + "~e{}v~|f{}w~}mv~}a{|v~C{|v~|Z{|v~h{}w~}dv~|l{|v~k{|v~q{|w~x{}x~}q{}w~}e{}v~wv~}Y{|v~|v{|v~|N{|v~}W{|w~}L{|w~F{|" + "w~|[{}v~l{}v~ S{|}k~|Zw~}y{|o~}V{|k~|\\{|o~}y{|w~|\\{|m~}X{}k~}Y{|o~}y{|w~|`w~}y{|o~}Sv~Lv~Tw~}o{|v~}Wv~_w~}y{|" + "o~|v{|o~|ew~}y{|o~}Y{|}n~}|[w~}y{|o~}Y{|o~}y{|w~|Zw~}y{|r~|[{}j~[{}i~]{|w~|m{}w~|b{}w~|k{|w~}i{|w~}q{|u~|q{|w~|" + "h{|v~|o{|v~}b{}w~|k{|w~}`d~Uw~}Lw~|M{|w~| n{|o~}vw~|av~o{}w~|M{|v~[{|o~}|U{}k~}]w~}y{|o~}_u~|k{|w~}Wu~X{|w~|m{" + "}w~|dv~|h{|v~_{}x~}x{}s~}__~|dv~t{}w~t{|w~}\\{}n~}Y{|}e~}f{|`~b{|w~}l{}w~|\\v~w{|v~T{|u~R{}w~}U{}v~dv~}i{}u~u{|" + "v~u{|u~|g{}w~}hv~|iv~}r{|v~qv~|k{}v~e{}v~|c{~}I{|y~}w{}w~w{|y~}I{}~|U{}w~T{}~|k{}~|\\y~}w{}w~w{|y~| v~}P{}k~Z{|" + "v~S{|v~}x{|}v~}|y{|v~}^{|w~}u{|w~}Rw~|S{|u~}${}y~|v{}v~}|wy|}y~u{|y~}c{|x~}r{|x~}Q{|q{| W{}y~|uw~vy|v~u{|y~}-w~" + "|v{|w~Q{}w~K{|w~|I{|w~'{|w~|m{}w~|a{}m~}w{|x~} H{}x~|U{|x~}p{|x~}]{|q{|X{}x~|m{|w~_{}x~|m{|w~]{|}w~}q{|w~Pv~|Sv" + "~w{|v~Vv~w{|v~Vv~w{|v~Vv~w{|v~Vv~w{|v~W{|v~vv~^{|v~|v{|v~X{}v~J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z" + "{|v~g{|v~}g{}w~|y{}w~}pv~h{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|g{|u~l{}v~}g{}v~kw~}{}v~g{|v~h{" + "}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}`{|v~|v{|v~|\\{}w~}s|y}t~}_w~}u{|v~|Y{|}k~|Z{|}k~|Z{|}k~|Z{|}k~|Z{|}k~|Z{|" + "}k~|d{|}k~|v{|m~}_{|k~|[{|m~}W{|m~}W{|m~}W{|m~}Rv~Lv~Lv~Lv~Q{|}l~\\w~}y{|o~}Y{|}n~}|X{|}n~}|X{|}n~}|X{|}n~}|X{|" + "}n~}|S{}u~S{|}n~}{|x~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|b{}w~|k{|w~}aw~}y{|o~}^{}w~|k{|w~} X{|w~}" + "t{}w~t{|w~}f{|w~}h{|w~}f{|w~}yy|p{|}y{|w~}f{|w~}ly|y{|w~}f{|w~}h{|w~}X{}x~}X{|v~kv~| Cv~|Lx~&{|i~|Y{|m~}bU~|e{}" + "h~\\{|u~}|xy|}u~^w~}kw~}Yr~}X{}w~}ov~d{}w~ lv~| lv~}R{}x~}vw~}^{}Z~f{|w~|v{|y~|`w~|s{|w~tw~|[{|v~|D{}x~}Nw~" + "}H{}w~|Q{|t~|N{}w~ c{|w~|Zv~|lv~|W{}w~}E{}w~}M{}w~}Z{|w~|w{}w~}\\{|w~}N{|v~={}w~}\\v~|nv~|b{}w~}l{}v~W{}v~M{}v" + "~G{|}p~|6{|o~}@u~e{|w~|\\{}w~e{|w~}v{}w~|]{}w~}m{|v~|cv~}N{}w~}g{|v~}d{}w~}L{}w~}Sv~}L{}w~}hv~|Y{}w~}M{}w~}W{}w" + "~}x{|u~}U{}w~}V{}w~|y{}w~q{|w~|yv~|h{}w~|y{|v~pv~hv~}e{|v~}d{}w~}mv~}gv~}e{|v~}f{}w~}mv~}a{|v~|D{|v~|Z{|v~h{}w~" + "}d{}w~}l{}w~}jv~|r{|w~x{|x~}qv~|e{|v~}y{}v~W{}v~vv~}N{|u~V{|w~}Kw~|G{|w~|\\{}w~}j{}v~ T{}i~}[w~}{}m~}X{}j~|]{}m" + "~}{|w~|]{}j~Y{}k~}Z{}m~}{|w~|`w~}{|l~Tv~Lv~Tw~}p{}v~}Vv~_w~}{|m~|x{|m~|fw~}{|m~}[{|j~|\\w~}{}m~}[{}m~}{|w~|Zw~}" + "{|q~|\\{}i~[{}i~]{|w~|m{}w~|b{|w~}k{}w~|hw~}q{|u~}q{}w~|g{}v~ov~}a{|w~}k{}w~|`d~Uw~}Lw~|M{|w~| Gy|l{|Z{}m~}x{|w" + "~`v~p{|v~Kv~Z{|m~|X{}j~}]w~}{|l~`t~|l{}w~|X{|u~}Y{|w~|m{}w~|e{}v~f{}w~}b{|v~}y{|q~}`_~|dv~t{}w~t{|w~}^{|k~}[{|c" + "~}f{|`~b{}w~}l{}w~}]{|w~}vv~|T{|v~}S{}w~}Uv~}d{}v~j{|u~t{|v~t{|u~g{}w~}hv~|iv~}r{|v~r{|v~|kv~}e{|v~}dx~}I{|}v{}" + "w~v{|}I{}x~|V{}w~U{}x~|m{}x~|\\{|v{}w~vy| {{v~}R{|i~Z{|v~R{|v~}|q~}|v~}\\v~u{}w~Qw~|R{|t~|'{|y~}v{}w~}p{|t{}y~|" + "d{}x~|r{|x~}Ry}r{|~ X{|y~}tw~sw~|u{}y~|.{|w~}x|}w~|Q{}w~L{|w~|G{|x~}({|w~|m{}w~|a{}m~}w{|x~} H{}x~|U{|w~p{|x~}]" + "{~|r{|}Y{}x~|mw~|_{}x~|m{}x~|[{|w~|r{}x~|Pv~|T{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{}w~}" + "v{}w~}_{}w~}u{|v~Xv~}J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~fu~g{}w~|y{|v~pv~hv~}e{|v~}jv~}e{|v~}" + "jv~}e{|v~}jv~}e{|v~}jv~}e{|v~}f{|u~n{}v~}fv~}l{}x~}y{|v~|h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}_{}v~vv~}[" + "{}w~}q{|}u~|`w~}uv~W{}i~}[{}i~}[{}i~}[{}i~}[{}i~}[{}i~}e{}i~}x{}k~}a{}j~|\\{}j~Y{}j~Y{}j~Y{}j~Sv~Lv~Lv~Lv~R{}j~" + "}]w~}{|m~}[{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|j~|T{}u~T{|f~`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|b{|w~}k{}w~|a" + "w~}{}m~}_{|w~}k{}w~| Xw~}s{}w~s{}w~fw~}f{}w~fw~}y{|y~|r{|y~}y{}w~fw~}l{|y~}y{}w~fw~}f{}w~X{}x~}Wv~|m{|v~ C{}w~}" + "[{|}|o{|y~|&g~|Y{}n~|b{}V~e{|g~}]v~}r{|v~}_w~}kw~}Z{|r~}X{|v~p{|w~}dw~} pw|v~l| {{v~}R{}x~}vw~}^{}Z~f{|w~|v" + "{|y~|`{}x~}s{|x~}u{}x~}Y{}v~|E{}x~}O{|w~}H{}w~|S{|}r~}|P{}w~ c{|w~Yv~|lv~|W{}w~}Ev~|N{|v~|Zw~}v{}w~}\\{|w~}|}v" + "~y}|X{}w~}>{|v~|\\{}w~}o{|v~a{}w~}l{}v~W{}v~M{}v~J{|}p~}|2{|}p~}|D{}v~|e{}x~}p{|}w~}|vx|uw~|f{}w~|v{|w~}]{}w~}m" + "{}v~c{|v~|N{}w~}fv~}d{}w~}L{}w~}T{|v~|L{}w~}hv~|Y{}w~}M{}w~}W{}w~}y{|u~}T{}w~}V{}w~|y{|w~|r{}x~}xv~|h{}w~|x{}w~" + "}qv~i{|v~|dv~}d{}w~}mv~}h{|v~|dv~}f{}w~}n{|v~|`u~D{|v~|Z{|v~h{}w~}d{|v~m{|v~|j{}w~}r{}x~}x{|w~qv~|d{}v~y|v~|Vv~" + "}x{}v~Mu~|V{|w~}K{}x~}G{|w~|]{}w~}h{|v~ U{}u~v}s~}\\w~}|v~w}t~}Zr~v}v~|^{}t~w}v~}|w~|^{}t~v}t~Zv}v~s}[{}t~w}v~}" + "|w~|`w~}|u~x}t~}Uv~Lv~Tw~}q{}v~|Uv~_w~}|v~x}s~y{|v~x}s~fw~}|u~x}t~}]{|s~x}s~|]w~}|v~w}t~}]{|t~w}v~}|w~|Zw~}|t~}" + "x~|]{}t~u}u~[{|x}v~q}]{|w~|m{}w~|av~kv~g{}w~q{}t~qv~e{}v~q{}v~_v~|m{|v~_d~Uw~}Lw~|M{|w~| J{|}v~}r{}v~}|_{}u~w}u" + "~|y{}x~}`v~q{|v~}K{}w~|\\{}w~}p~}Z{}s~w}u~}]w~}|u~x}t~}as~m{|v~W{}t~Y{|w~|m{}w~|ev~|f{|v~c{|u~}yn~a_~|dv~t{}w~t" + "{|w~}_{|t~w}t~}]{|b~}f{|`~b{}w~|l{}w~}]{}w~|v{|w~}S{|v~}T{}w~}Uv~|d{|v~|k{}v~|t{|v~s{}v~|h{}w~}hv~|i{}w~}r{|v~r" + "{|v~|l{|v~|dv~}ev~}C{}w~C{}v~|W{}w~V{}v~n{|v~|W{}w~ sv~}S{|s~}y~x}v~Z{|v~Q{|e~}[{|w~}w{|w~}Qw~|R{}r~|){}y~|w{|w" + "~}g{|y~}dw~q{}x~}S{}~}s{}y~ X{}y~|tw~s{}x~}u{|y~}-{}p~}P{}w~M{|w~|F{|x~}({|w~|m{}w~|a{}m~}w{|x~} H{}x~|Tw~p{}x~" + "|]y~}s{|y~Z{}x~|n{|x~}^{}x~|n{|w~Y{|x~}s{|x~}Ov~|T{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}Xv" + "~u{|v~_v~|u{|v~Y{|v~|J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{}v~g{}w~|x{}w~}qv~i{|v~|dv~}k{|v~|d" + "v~}k{|v~|dv~}k{|v~|dv~}k{|v~|dv~}e{|u~p{}v~}f{|v~|m{}w~wv~}h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}^v~}x{}v" + "~Z{}w~}o{}v~}`w~}v{|w~|W{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}f{}u~v}s~}{s~w}t~}cr~v}" + "v~|]{}t~v}t~[{}t~v}t~[{}t~v}t~[{}t~v}t~Tv~Lv~Lv~Lv~S{}h~|^w~}|u~x}t~}]{|s~x}s~|\\{|s~x}s~|\\{|s~x}s~|\\{|s~x}s~" + "|\\{|s~x}s~|U{}u~U{|s~x}q~|`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|av~|m{|v~`w~}|v~w}t~}_v~|m{|v~ X{|w~" + "r{}w~rw~}h{|w~dw~}h{|w~y{|w~|t{|w~}yw~}h{|w~l{|w~}yw~}h{|w~dw~}Y{}x~}W{}w~}m{}w~} Xg|}v~s|e{|}x~}o{}y~&{}f~Y{|o" + "~}a{|V~f{|e~}_{|w~}p{|v~_w~}kw~}Z{}w~}v~Wv~|q{}w~}e{|w~ pc~} {{v~}R{|x}|v{|x}|^{}Z~f{|w~|v{|y~|`{|w~s{}x~}v" + "{|w~Wu~|F{|x}|O{}w~|H{|w~}U{|}w~|x~|w~}|R{}w~ c{}x~}Yv~|lv~|W{}w~}F{|v~N{|v~}Z{}w~u{}w~}\\{|k~}Z{}w~}x{|}u~y}|" + "L{}v~Zv~|pv~}a{|v~l{}v~|X{}v~M{}v~M{|}p~}|,{|}p~}|H{}v~|e{|w~q{|q~}y{}x~|v{|x~}fv~tv~]{}w~}n{}v~|c{|v~|N{}w~}f{" + "}v~d{}w~}L{}w~}T{}v~|L{}w~}hv~|Y{}w~}M{}w~}W{}w~}{|u~}S{}w~}V{}w~|xw~}rw~|xv~|h{}w~|x{|v~|rv~i{|v~|d{}v~d{}w~}n" + "{|v~|h{|v~|d{}v~f{}w~}n{}v~|`{}v~}|F{|v~|Z{|v~h{}w~}cv~|n{}v~i{}w~}rw~|ww~|s{|v~b{}q~}U{|v~|{|v~|N{}v~|U{|w~}K{" + "|w~G{|w~|^{}w~}f{|v~ V{}y~}|r{|u~|]r~|u{|u~}\\{}u~}s{|}y~|_{|u~|u{|}s~|_{}v~}|t{}v~}Vw~}T{|u~|u{|}s~|`r~|u{|u~|" + "Vv~Lv~Tw~}ru~|Tv~_r~|v{|}v~}{w~|u{}v~}gr~|u{|u~|^u~}|v{|}u~]r~|u{|u~|_{|u~|u{|}s~|Zr~}|v{|\\v~}|r{|}y~Wv~S{|w~|" + "m{}w~|a{}w~|m{|w~}g{}w~|rs~qw~}dv~}s{|v~|_{}w~}m{}w~|Nu~Uw~}Lw~|M{|w~| K{}r~u{|r~}a{|v~}|v{}v~yw~|`v~r{|u~|K{|w" + "~|]{}w~|xy|}t~}[u~}|s{|}~}]r~|u{|u~|ay|v~|n{}w~|X{|s~|Z{|w~|m{}w~|f{|v~dv~|e{|u~}|{|v~y|}v~}bx}u~q}u~x}|dv~t{}w" + "~t{|w~}_u~|u{|u~|_{|u~}|v{|}t~v}f{|q}u~p}b{}w~|l{|v~]v~tv~R{}v~}U{}w~}V{|v~|cv~}l{|v~}s{|v~s{|v~}h{}w~}hv~|i{}v" + "~r{|v~r{|v~|l{|v~|d{}v~fu~|C{}w~C{|u~|X{}w~W{}v~}m{}v~|X{}w~ sv~}T{|u~}|yy~}x{|}y~Z{|v~P{|g~}Y{}w~|xv~Pw~|T{|v~" + "}u~}*x~v{}w~ex~dw~qw~}U{|x~}t{}x~ Xx~sw~s{}x~}tx~,{|r~|O{}w~N{|w~|Dw~({|w~|m{}w~|a{|m~}w{|x~} H{}x~|T{}x~}qw~|]" + "x~}t{|x~|\\{}x~|nw~]{}x~|nw~|Xw~sw~|Ov~|Tv~tv~Xv~tv~Xv~tv~Xv~tv~Xv~tv~Y{|w~}tv~|a{|v~t{|v~Y{|v~|J{}w~}M{}w~}M{}" + "w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|x{|v~|rv~i{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{" + "}v~d{|u~r{}v~}e{|v~|n{}w~v{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}^{|v~|{|v~|Z{}w~}nu~`w~}v{}w~V{}y~}|r" + "{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|g{}y~}|r{|o~}|u{|}v~}e{}u~}s{|}y~|^{}v~}|" + "t{}v~}]{}v~}|t{}v~}]{}v~}|t{}v~}]{}v~}|t{}v~}Uv~Lv~Lv~Lv~T{}u~}|v{|}v~}^r~|u{|u~|^u~}|v{|}u~\\u~}|v{|}u~\\u~}|v" + "{|}u~\\u~}|v{|}u~\\u~}|v{|}u~U{}u~Uu~}|u{}u~|_{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{}w~}m{}w~|`r~|u{" + "|u~|`{}w~}m{}w~| Xw~|r{}w~r{|w~hw~|d{|w~hw~|yu~|v{|u~y{|w~hw~|m{|u~y{|w~hw~|d{|w~Y{}x~}Vv~mv~| XZ~}g{}t~oy~}'{}" + "e~}Y{}p~_W~|fc~|`v~n{}w~|`w~}kw~}Zv~|}w~|X{}w~}qv~|e{}x~} q{|c~| {{v~} y{|x~}t{}x~}]{|w~}v{|y~|_w~|u{|w~|vw" + "~|Wt~ p{}w~|H{|v~V{}w~}yx~y{}w~}S{}w~ cw~|Z{|v~k{}w~}W{}w~}Fv~}Qy|u~}Z{|w~|u{}w~}\\{|i~|\\v~|y{}p~}|Nv~}Z{|v~|" + "s{|v~}`{|v~lu~|X{}v~M{}v~P{|}p~}|b{|Z~}b{|}p~}|L{}v~}d{}x~|r{|n~{}x~|uw~|h{}w~}t{}w~|^{}w~}q{|}u~}b{}v~M{}w~}f{" + "}v~d{}w~}L{}w~}T{}v~K{}w~}hv~|Y{}w~}M{}w~}W{}w~}|u~}R{}w~}V{}w~|x{|w~s{}w~wv~|h{}w~|w{}w~}rv~i{}v~c{}v~d{}w~}n{" + "}v~|h{}v~c{}v~f{}w~}o{|u~_{|t~}|H{|v~|Z{|v~h{}w~}c{}v~nv~}i{|v~s{|w~|w{}x~}s{}w~}b{|q~S{}v~|v~}N{}v~}T{|w~}K{|w" + "~|H{|w~| s{}|m{}w~}]t~}q{}v~|^{}v~}ny|_u~q{}t~|`{|v~|q{|v~|Ww~}Tu~q{|t~|`t~}r{|v~}Vv~Lv~Tw~}t{|u~Rv~_t~}r{}v~}" + "y~}r{}v~gt~}r{|v~}_{}v~|r{|v~}^s~q{}v~_{}v~|r{}t~|Zs~T{|w~}m{|Wv~S{|w~|m{}w~|a{|w~}mv~|g{|w~}s{|s~|s{|w~|d{|v~|" + "u{|v~}]v~mv~N{}v~Tw~}Lw~|M{|w~| L{}p~w{|p~}bv~}s{}w~y|w~_v~wx|}t~}J{|w~}^{}w~r{}u~|]{|v~|Ot~}r{|v~}_{|v~nv~W{}s" + "~}Z{|w~|m{}w~|f{}w~}d{}w~}eu~}x{|w~|x{}v~|`{|w~}q{|w~}`v~t{}w~t{|w~}`{}v~q{}v~_u~}r{|v~}V{|w~}Wv~|l{|v~^{}w~}t{" + "}w~|R{}v~}V{}w~}V{|v~bv~}l{|v~|s{|v~r{}v~h{}w~}hv~|i{}v~r{|v~r{}v~k{}v~c{}v~gu~|B{}w~B{|u~|Y{}w~X{}v~}k{}v~|Y{}" + "w~ sv~}Tu~|wy~}u{|Z{|v~O{|u~}|x{|}v~}_{|p~}y{|p~}Ww~|Tw~}y{|t~|,y~}vw~|e{}y~dw~|s{}w~}V{|w~}u{}w~ Xy~}sw~s{}x~}" + "t{}y~*y}x~}|[m|}w~l|^{}w~C{|x~}({|w~|m{}w~|`m~}w{|x~} H{}x~|T{|w~|s{}x~}\\w~}u{|w~|]{}x~|o{}x~}]{}x~|o{}x~}Ww~t" + "{}x~}Nv~|U{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~|t{|w~}av~}t{|v~Y{}v~I{}w~}M{}w~}M{}w" + "~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|w{}w~}rv~i{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~c{|" + "u~t{}v~}d{}v~n{|w~|v{|v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}]{}v~|v~}Y{}w~}n{|v~|aw~}vv~V{}|m{}w~}]{}|m" + "{}w~}]{}|m{}w~}]{}|m{}w~}]{}|m{}w~}]{}|m{}w~}g{}|m{}r~|q{|v~|g{}v~}ny|_{|v~|q{|v~|_{|v~|q{|v~|_{|v~|q{|v~|_{|v~" + "|q{|v~|Vv~Lv~Lv~Lv~U{|v~}q{|v~|_t~}r{|v~}_{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}V{}u~V{}v~" + "|r{|v~}_{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|`v~mv~_s~q{}v~_v~mv~ X{|w~q{}w~q{}x~|j{|w~b{}x~|j{|w~wu~" + "|x{|u~|x{}x~|j{|w~m{|u~|x{}x~|j{|w~b{}x~|Z{}x~}V{}w~|o{|v~ WZ~}gx~}w~|q{}y~|({|c~}_v|{}r~u|d{}X~f{}b~|b{|w~}mw~" + "}`w~}kw~}[{|v~{}w~}X{|w~}r{|v~d{}x~| q{}c~ yv~} y{}x~}t{}x~}\\v~}w{|y~|_{}w~|vw~}v{|x~}X{|r~ qv~Fv~X{}w~}|x" + "x~x{|}w~}U{}w~ d{|w~Y{|v~k{}w~}W{}w~}G{}v~|Xm~}Y{}x~}t{}w~}\\{|h~}]v~y|l~}P{|v~|Y{|u~u|}v~}_{|v~|n{|u~|X{}v~M{" + "}v~R{|o~}|`{|Z~}_{|}p~}|P{}v~}cw~r{|l~}x~|u{|x~|hv~|t{|v~^{}e~}a{}v~M{}w~}f{|v~|e{}d~|_{}g~|d{}v~K{}^~|Y{}w~}M{" + "}w~}W{}p~|Q{}w~}V{}w~|ww~|tw~}wv~|h{}w~|vv~|sv~i{}v~c{|v~|e{}w~}o{|u~g{}v~c{|v~|g{}w~}p{|u~|^{}q~y}|M{|v~|Z{|v~" + "h{}w~}c{|v~|p{|v~gv~|t{|w~v{|x~}sv~|a{|s~|Rq~}N{}v~}S{|w~}Jw~}H{|w~| bv~|^t~ov~}^v~}P{|v~|p{}u~|`v~|o{|v~Ww~}U" + "{|v~o{}u~|`u~}p{|v~Vv~Lv~Tw~}u{|v~}Qv~_u~}pt~}pv~|hu~}p{|v~`{|v~|p{|v~|_t~ov~}a{|v~|p{}u~|Zt~S{}w~Gv~S{|w~|m{}w" + "~|`v~|o{|v~ev~s{|x~y}x~}s{}w~|c{}v~uv~}\\{}w~|o{|w~}O{}v~|U{|w~}Lw~|M{|w~} M{|x~}x|}w~}xv~}x|}x~|d{}v~qw~y}x~}_" + "v~x{}q~}I{|w~}_{|w~|q{|u~]{}w~|Nu~}p{|v~^{}w~|p{|w~}X{|q~Z{|w~|m{}w~|fv~|d{|v~f{|v~}w{}w~|wu~`{|w~}q{|w~}`v~t{}" + "w~t{|w~}a{|v~ov~}a{|v~}p{}v~|W{|w~}Wv~}l|}v~^v~|t{|v~Q{}v~}W{}w~}V{|v~b{}w~}l{}v~r{|v~r{}v~|i{}w~}hv~|i{|v~|s{|" + "v~r{}v~k{}v~xi~}y{|v~|iu~|A{}w~A{|u~|Z{}w~Y{}v~}i{}v~|Z{}w~ sv}|U{}v~|vy~}S{|v~O{|w~}s{|v~_{|o~|{o~}Ww~|U{}x~}v" + "{}u~}.{|y~|w{|w~d{|y~|e{}w~t{}v~}W{|v~|v{}w~}cY|8{|y~|sw~sw~|t{|y~| `{|Z~}_{}x~}C{|w~}({|w~|m{}w~|`{|n~}w{|x~} " + "H{}x~|Sv~|u{}w~|\\{}v~v{|v~|^{}x~|p{|w~\\{}x~|p{|w~W{|x~}u{|w~Mv}|Uv~|t{|v~Zv~|t{|v~Zv~|t{|v~Zv~|t{|v~Zv~|t{|v~" + "Zv~rv~b{|v~s{|c~l{}v~I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}Z{|v~ev~}h{}w~|vv~|sv~i{}v~c{|v~|l{}v~c{|v" + "~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|c{|u~v{}v~}c{}v~o{|w~|u{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}\\q~" + "}X{}w~}mv~}aw~}vv~Ev~|Mv~|Mv~|Mv~|Mv~|Mv~|Ws~|o{}w~}gv~}Ov~|o{|v~_v~|o{|v~_v~|o{|v~_v~|o{|v~Vv~Lv~Lv~Lv~Uv~}o{}" + "w~}_u~}p{|v~`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|Wt|W{|v~|q{}u~|`{|w~|m{}w~|a{|w~|m{}w~|" + "a{|w~|m{}w~|a{|w~|m{}w~|`{}w~|o{|w~}_t~ov~}`{}w~|o{|w~} X{}x~}q{}w~q{|x~}j{}x~}b{|x~}j{}x~}vu~|yu~|w{|x~}j{}x~}" + "mu~|w{|x~}j{}x~}b{|x~}Z{}x~}V{|v~o{}w~} WZ~}g{}|yw~}qx~'a~|c{|}t~}k~}|fY~}g{}`~b{|w~|m{}w~`w~}kw~}[{|w~}{|v~Wv~" + "r{}w~}dw~| lv~| kv~| yw~|tw~|\\{}v~}|y{|y~|^v~}y|}v~uw~X{|p~ rv~Fv~Xw~|vx~v{|w~U{}w~ d{}x~}Y{|v~k{}w~}W{}w" + "~}H{|v~}Wo~}|Y{|w~|t{}w~}\\{|v~x}|x}s~}^v~|j~}Q{}w~}V{}l~}]v~}n{}u~}X{}v~M{|v}U{|}p~}|]{|Z~}\\{}o~|S{}v~}c{|x~}" + "rv~}|w{|}t~|tx~}i{|v~rv~|_{}h~}|_v~}M{}w~}f{|v~|e{}d~|_{}g~|dv~}K{}^~|Y{}w~}M{}w~}W{}q~|P{}w~}V{}w~|w{}w~u{|w~|" + "wv~|h{}w~|v{}w~}sv~iv~}c{|v~|e{}w~}p{|u~|gv~}c{|v~|g{}w~}sy|}u~}\\{}m~}|Q{|v~|Z{|v~h{}w~}bv~}p{}w~}g{}w~}t{}x~}" + "v{|w~sv~|`{}u~}Q{|r~|O{|u~R{|w~}J{}w~H{|w~| b{|w~}^u~|o{|v~_{}v~Ov~}nu~|a{}w~}m{}w~|Xw~}Uv~|nu~|`u~nv~|Wv~Lv~T" + "w~}v{}v~}Pv~_u~o{}u~|p{}w~}hu~nv~|a{}w~}n{}w~}_u~|o{|v~a{}w~}nu~|Zu~|S{}w~Gv~S{|w~|m{}w~|`{}w~}o{}w~}e{}w~s{}x~" + "}|w~sv~a{}v~w{}v~[{|w~}ov~|P{}v~|T{|w~}Lw~|M{|w~}:{|4x~|v{|w~}{}x~}u{}x~dv~}q{}s~|_v~x{}r~}S{|y}~y}|w{|w~}_w~}o" + "{|v~}^{}w~Mu~nv~|_{|w~}pv~|X{}w~}v~|[{|w~|m{}w~|g{|v~bv~|g{}v~v{}w~v{|v~|a{|w~}q{|w~}`v~t{}w~t{|w~}a{}w~|o{|v~a" + "{}v~nv~}W{|w~}W`~_{|v~rv~|Q{}v~|X{}w~}V{|v~b{}w~}lu~r{|v~r{|v~|i{}w~}hv~|hv~}s{|v~rv~}kv~}xi~}y{|v~|ju~|@{}w~@{" + "|u~|[{}w~Z{}v~}g{}v~|[{}w~ Gv~}uy~}S{|v~Ow~}q{|w~|`{|n~}o~}Ww~|Uw~|t{}u~|0{|y~|w{|x~}d{|y~|e{|v~}w|t~}X{|v~|vv~" + "}c{|Z~}8{|y~|sw~t{}w~s{|y~| `{|Z~}`{}x~}M{|~}|v{|}v~'{|w~|m{}w~|_{}o~}w{|x~}Vv}| s{}x~|S{|v~}|{y|}w~}Z{}v~|w{|v" + "~}_{}x~|pw~|o{}w~m{}x~|p{}x~|vy|}w~y}|g{|w~|u{}x~|o{}w~3{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{}w~}" + "r{}w~|c{}w~}s{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w~|v{}w~}sv~iv~}c{|v~|lv~}c{|" + "v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|b{|u~x{}v~}bv~}p{|w~}t{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}\\{|r~|" + "X{}w~}mv~}aw~}v{}w~}F{|w~}M{|w~}M{|w~}M{|w~}M{|w~}M{|w~}W{|u~}m{}w~h{}v~O{}w~}m{}w~|a{}w~}m{}w~|a{}w~}m{}w~|a{}" + "w~}m{}w~|Wv~Lv~Lv~Lv~V{}v~n{|v~_u~nv~|a{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~},{}w~}q{}t~}`" + "{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|`{|w~}ov~|_u~|o{|v~`{|w~}ov~| X{}x~|q{}w~q{|w~j{}x~|b{|w~j{}x~|u" + "u~|u~|v{|w~j{}x~|nu~|v{|w~j{}x~|b{|w~Zw~}Uv~|q{|v~ VZ~}c{}w~r{|y~}({}`~d{}^~|h{|Z~g{|_~}c{}w~l{|w~`w~}kw~}[{}w~" + "|yv~|X{}w~|sv~|dV~} 2v~| k{}w~| {{|w~t{|w~Zs~y}y~|^{|o~|v{}x~}rx|e{|v~y}u~n{|w~},{|v~Fv~|Y{|~}tx~t{}~|U{}w~ " + " dw~|Y{|v~k{}w~}W{}w~}Hu~Vp~}|Y{|w~}s{}w~}\\{|~}|q{}t~|`{|q~}|xy|t~|Rv~|U{|}p~|[{}v~|ot~} V{|}p~}|Z{|Z~}Z{|}p~}" + "|W{}v~|b{}x~|s{}w~|s{|u~|tw~i{}w~}r{}w~}_{}g~}|`v~}M{}w~}f{|v~|e{}d~|_{}g~|dv~}K{}^~|Y{}w~}M{}w~}W{}q~O{}w~}V{}" + "w~|w{|w~|v{}w~vv~|h{}w~|uv~|tv~iv~}c{|v~|e{}w~}sy|s~fv~}c{|v~|g{}f~}Z{}k~}S{|v~|Z{|v~h{}w~}b{|v~pv~|g{}w~}tw~|u" + "w~|u{|v~_{}u~O{}t~|O{|u~|R{|w~}J{|w~|I{|w~| aw~}^v~}m{}w~}`v~|P{|v~m{}v~|av~l{|w~}Xw~}V{|v~m{|v~|`v~}n{}w~|Wv~" + "Lv~Tw~}w{}v~}Ov~_v~}o{|v~}o{|w~}hv~}n{}w~|av~|n{|v~|`u~mv~|bv~m{}v~|Zv~}R{}w~Gv~S{|w~|m{}w~|`{|v~ov~d{}w~|tw~|{" + "w~|u{|w~}`v~}y{|v~|Z{}w~|q{|v~P{}v~|Sv~|Lw~|Lv~|W{|y}w~}|iy}5{|y~}sw~|x~}s{}y~|f{|v~|ps~^v~x{}q~}|W{|r~|y{|w~}`" + "{}w~m{}v~^{}w~Mv~}n{}w~|^{}w~q{|v~Wv~y|w~}[{|w~|m{}w~|g{}v~b{}w~}h{|v~|v{}w~u{}w~}a{|w~}q{|w~}`v~t{}w~t{|w~}av~" + "mv~|c{|v~|n{|v~W{|w~}W`~_{}w~}r{}w~}Q{|v~}X{}w~}V{|v~b{}w~}lv~}r{|v~r{|v~|i{}w~}hv~|h{}v~s{|v~s{|v~|kv~}xi~}y{|" + "v~|ku~|?{}w~?{|u~|\\{}w~[{}v~}e{}v~|\\{}w~ H{}v~ty~}S{|v~P{|w~o{}w~_s|}r~s|Vw~|V{|w~r{|u~0{|y~v{}x~}d{|y~|d{}o~" + "|x~}Y{}v~v{|v~|b{|Z~}8{|y~rw~u}v~|s{|y~| `{|Z~}a{}l~|X{|m~|'{|w~|m{}w~|^o~}w{|x~}W{|v~| xm~}W{|n~}X{|v~|vv~}e{}" + "n~}v{}x~}o{|v~m{}x~|q{|w~w{|o~|t{|~}y|w{|}v~u{|x~}o{|v~3{}w~}r{}w~}\\{}w~}r{}w~}\\{}w~}r{}w~}\\{}w~}r{}w~}\\{}w" + "~}r{}w~}\\v~|r{|w~}cv~|s{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w~|uv~|tv~iv~}c{|v" + "~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|a{|u~|}v~}av~}pw~}s{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}[" + "{}t~|W{}w~}mv~}aw~}v{}v~|Fw~}Lw~}Lw~}Lw~}Lw~}Lw~}Vu~l{|w~|iv~|Ov~l{|w~}av~l{|w~}av~l{|w~}av~l{|w~}Wv~Lv~Lv~Lv~V" + "v~|mv~|`v~}n{}w~|av~|n{|v~|av~|n{|v~|av~|n{|v~|av~|n{|v~|av~|n{|v~|-v~|r{|x~}v~`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{" + "}w~|a{|w~|m{}w~|_{}w~|q{|v~^u~mv~|`{}w~|q{|v~ Ww~p{}w~pw~jw~yd|yw~jw~t{|p~|tw~jw~nu~|tw~jw~pv~}qw~Zw~|U{}w~}q{}" + "w~} F{}w~}W{|w~|s{}y~|){|_~}f{}\\~|h{}\\~|g{}^~c{}w~l{|w~|aw~}kw~}[v~x{}w~}X{|w~}t{|v~cV~} 2v~| k{}w~| {{|x~" + "}t{|x~}Z{|o~}y|`{|}r~|v{|w~t{}u~}|hv~}y{}u~o{|w~|,{|v~F{}w~|X{|sx~s{|T{}w~ e{|w~X{|v~k{}w~}W{}w~}Iu~|Vm~|[{}w~" + "r{}w~}L{}u~`{|r~|s{|u~S{}v~V{|}m~}|\\u~p{}t~} Y{|}p~}|VY|W{|}p~}|[{|v~|aw~rw~}q{|v~|t{}x~iv~q{|v~_{}e~}av~}M{}w" + "~}f{|v~|e{}d~|_{}g~|dv~}m{}n~|h{}^~|Y{}w~}M{}w~}W{}q~}P{}w~}V{}w~|vw~}vw~}vv~|h{}w~|u{}v~tv~iv~}bv~|e{}e~|fv~}b" + "v~|g{}g~}X{|}k~}U{|v~|Z{|v~h{}w~}av~|r{|v~f{|v~u{|w~|u{}x~}u{}w~}`{|t~|O{}v~}Nu~|Q{|w~}Iw~}I{|w~| a{}w~^v~|m{|" + "w~}a{|v~O{|w~}lv~|b{|w~}kv~Xw~}V{|w~}lv~|`v~|n{|w~}Wv~Lv~Tw~}x{}v~|Nv~_v~|nv~|nv~hv~|n{|w~}b{|v~lv~|`v~}m{|w~}c" + "{|w~}m{|v~|Zv~|R{}w~|Hv~S{|w~|m{}w~|_{}w~|q{|w~}d{|w~}u{|w~y{}x~|u{|w~|`{|v~y|v~}Y{|w~}q{}w~|Q{|v~}S{}v~Kw~|L{}" + "w~}Y{|p~}|n{|y~}5{}y~r{|t~qy~}f{}v~ot~}^v~x{}o~}Y{}p~|{|w~|`w~}lv~|_{|w~}Nv~|n{|w~}^{|w~|r{}w~|X{}w~}yv~[{|w~|m" + "{}w~|gv~}b{}v~h{|v~u{}w~u{|v~a{|w~}q{|w~}`v~t{}w~t{|w~}b{|w~}m{|w~}c{|v~lv~|X{|w~}W`~_v~|r{|v~Qu~W{}w~}V{|v~b{}" + "w~}lv~}r{|v~qv~|i{}w~}hv~|h{|v~|t{|v~s{}v~jv~}xi~}xv~|lu~[|]{}w~\\\\|u~|]{}w~\\{}v~}c|u~|]{}w~ H{}w~}ty~}X{}g~|" + "[{}x~}nw~Vs~|Nw~|V{}x~}pv~}1{}y~v{}x~}d{|y~}c{}r~}{|x~}Z{}w~}v{|v~|a{|Z~}8{}y~rn~}q{|y~} `{|Z~}a{}l~|X{|o~}|&{|" + "w~|m{}w~|]{}q~}w{|x~}W{|v~| xm~}V{|}q~|V{|v~|v{}w~}fm~}vw~o{|u~rm~}vw~|w{}n~|u{|m~|uw~|p{|u~3v~q{|v~\\v~q{|v~\\" + "v~q{|v~\\v~q{|v~\\v~q{|v~]{|v~pv~|e{}w~}r{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w" + "~|u{}v~tv~iv~}bv~|lv~}bv~|lv~}bv~|lv~}bv~|lv~}bv~|`{|p~}`v~}q{}x~}qv~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}" + "w~}Z{}v~}V{}w~}mv~}aw~}uu~}G{}w~L{}w~L{}w~L{}w~L{}w~L{}w~V{}w~}kw~}j{|v~O{|w~}kv~b{|w~}kv~b{|w~}kv~b{|w~}kv~Wv~" + "Lv~Lv~Lv~W{|v~l{}w~}`v~|n{|w~}b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|.{|v~r{|w~{}w~|a{|w~|m{}w~|a{|w~|m{}" + "w~|a{|w~|m{}w~|a{|w~|m{}w~|_{|w~}q{}w~|^v~}m{|w~}`{|w~}q{}w~| Ww~yd~|{w~jw~yd~|{w~jw~s{|r~|sw~jw~ou~|sw~jw~pv~}" + "qw~Zw~|U{|v~qv~| G{}w~}Uw~}sx~({}^~g{}Z~g]~}f{|_~|cw~}l{|w~|aw~}kw~}\\{|v~x{|v~Wv~t{}w~}cV~} 2v~| k{}w~| {{}" + "x~}t{}x~}Y{|}m~}`{|}w~}|tw~|v{|q~}j{}v~w{}u~p{}w~|,{|w~}F{}w~|Ox~Z{|Z~} t{}x~}X{|v~k{}w~}W{}w~}J{}v~|Ut|}t~}]{" + "|w~|r{}w~}K{}v~|a{|s~p{|v~}Tv~}W{}i~}]{}u~|t{|}s~} Z{|q~}| e{|}q~}\\v~}`x~}s{}w~ov~|t{}x~|k{|w~}p{}w~|`{}w~}p|}" + "t~|cv~}M{}w~}f{|v~|e{}w~}i|^{}w~}l|cv~}m{}n~|h{}w~}h|v~|Y{}w~}M{}w~}W{}w~}u~}Q{}w~}V{}w~|v{}w~w{|w~uv~|h{}w~|tv" + "~|uv~iv~}c{|v~|e{}f~|ev~}c{|v~|g{}i~}S{|}m~}V{|v~|Z{|v~h{}w~}a{}w~}rv~}ev~|v{|w~t{|w~uv~|`r~O{|v~|O{}v~}P{|w~}I" + "{}w~I{|w~| a{}w~^v~|lv~a{}w~}O{}w~|lv~|b{|w~|k{}w~Xw~}V{}w~|lv~|`v~m{|w~}Wv~Lv~Tw~}yu~|Mv~_v~mv~mv~hv~m{|w~}b{" + "}w~}l{}w~}`v~|m{|v~c{}w~|lv~|Zv~Q{}v~|Iv~S{|w~|m{}w~|_{|w~}q{}w~|cv~u{}x~}y{}x~}u{}w~^{}q~}Wv~qv~Q{|v~}Uy|}v~|K" + "w~|L{|u~}|^{|k~}|s{|}x~}5y~}q{}v~|q{}y~f{}w~}o{}u~|^v~ty|}s~[{|u~y}v~y|w~|a{|w~}l{}w~}^{}w~|Ov~m{|w~}]w~}rv~Wv~" + "|y{}w~}\\{|w~|m{}w~|gv~|b{|v~h{}w~}u{}w~tv~a{|w~}q{|w~}`v~t{}w~t{|w~}b{}w~|m{|v~c{}w~}l{}w~}X{|w~}W`~`{|w~}pv~|" + "S{}v~|W{}w~}V{|v~bv~}lv~}r{|v~r{|v~|i{}w~}hv~|gu~t{|v~t{|v~}jv~}xh|y{|v~|mT~]{}w~]T~|^{}w~]{}U~|^{}w~ Hv~|ty~}X" + "{}g~|[w~|nw~|W{}u~}Mw~|V{}w~ov~1{|y~v{}x~}d{|y~|ay}x~y}ww|[{}w~}v{|v~|`{|Z~}8{|y~ro~o{|y~| Q{}w~R{}l~|V{|y}v~y}" + "|${|w~|m{}w~|\\{|}s~}w{|x~}W{|v~| xm~}T{|y}w~}|S{|v~|v{}w~}gm~}w{}x~}oy~y}x~rm~}w{}x~}v{}~}y|w{|v~u{|o~}t{}x~}o", + "t~^v|V{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{}w~}p{}w~}ev~|r{|v~h|lv~}I{}w~}i|_{}w~}i|_{}" + "w~}i|_{}w~}i|V{}w~}M{}w~}M{}w~}M{}w~}_v}u~r}nv~}h{}w~|tv~|uv~iv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|" + "_{|r~}_v~}r{}w~q{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}mv~}aw~}u{|t~|I{}w~L{}w~L{}w~L{}w~" + "L{}w~L{}w~V{}w~|kv~j{}w~}O{|w~|k{}w~b{|w~|k{}w~b{|w~|k{}w~b{|w~|k{}w~Wv~Lv~Lv~Lv~W{}w~}l{|w~}`v~m{|w~}b{}w~}l{}" + "w~}b{}w~}l{}w~}b{}w~}l{}w~}b{}w~}l{}w~}b{}w~}l{}w~}eY|f{}w~}rw~y{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|" + "m{}w~|^v~qv~]v~|m{|v~_v~qv~ Vw~yd~|{}x~|kw~yd~|{}x~|kw~r{|t~|r{}x~|kw~pu~|r{}x~|kw~pv~}q{}x~|[w~|T{}w~|s{|v~ G{" + "}v~T{}w~t{|y~}(]~|i{|Y~}h{|_~}d{|a~}bw~}kw~|aw~}kw~}\\{}w~}wv~|Xv~|u{}w~|cV~} 2v~| k{}w~| {{w~|tw~|W{|}m~}T{" + "}x~}v{|o~}l{|v~|v{}u~q{}w~+{|w~}F{}w~|Ox~Z{|Z~}+m| ww~|X{|v~k{}w~}W{}w~}K{}v~}K{|}v~}^w~}q{}w~}Ju~a{|t~|o{}v~U{" + "|v~|X{}u~}|wy|u~}]t~}y|{y|}q~} Z{|t~}| _{|}t~}\\v~`{|x~}s{}x~}o{|w~|t{}x~|kv~|p{|w~}`{}w~}n{|u~cv~}M{}w~}f{|v~|" + "e{}w~}L{}w~}Tv~}m{}n~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}|u~}R{}w~}V{}w~|v{|w~|x{}x~}uv~|h{}w~|t{|v~uv~iv~}c{|v~|e{}h~" + "}cv~}c{|v~|g{}h~}Qy|y}p~W{|v~|Z{|v~h{}w~}a{|v~s{|v~|e{}w~}v{}x~}t{|w~uv~|a{}r~}P{|v~|P{}v~}O{|w~}I{|w~|J{|w~| " + "n{|y}l~^v~kv~a{}w~|Ov~|l{}w~|b{}w~|k{}w~|Yw~}Vv~|l{}w~|`v~m{|w~}Wv~Lv~Tw~}|u~Kv~_v~mv~mv~hv~m{|w~}b{}w~|l{|v~`v" + "~kv~c{}w~|l{}w~|Zv~Pu~}|Kv~S{|w~|m{}w~|^v~qv~b{}w~u{}x~|y{|w~uv~]{}r~V{}w~|s{|w~}R{|v~}X{|q~}Jw~|K{|q~}c{}g~}w|" + "}u~}5y~}pw~}p{}y~fv~|o{}u~]v~p{|t~\\v~}w{|w~}w~|a{}w~|l{|w~}]{}w~}y|Rv~m{|w~}]{}w~s{}w~}X{}w~}x{|v~\\{|w~|m{}w~" + "|h{|v~|b{|v~|i{}w~|u{}w~tv~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~kv~c{}w~|l{|w~}X{|w~}Wv~jv~`v~|p{}w~}T{}v~|V{}w~}V{|v~" + "|cv~|lv~}r{|v~r{|v~|i{}w~}hv~|g{}v~}u{|v~tu~|jv~}c{|v~|n{|T~]{}w~]T~}^{}w~]T~}^{}w~ I{|v~sy~}X{}g~|[w~m{}x~|Vu~" + "|#{|w~|p{|w~|2{|y~|w{|x~}d{|y~|3v~}v{}v~|Aw~}8{|y~|sw~x{|w~}p{|y~| Q{}w~ p{|w~|m{}w~|Y{|}v~}w{|x~}W{|v~| jv~}" + "v{}v~|W{|w~o{}y~{}x~r{}n~}x{|w~uy|rw~|ty|t}|s{|w~o{}y~|}x~^{}w~|Wv~|p{|w~}^v~|p{|w~}^v~|p{|w~}^v~|p{|w~}^v~|p{|" + "w~}^v~|p{|v~f{|v~q{|v~Yv~}I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~ev~}h{}w~|t{|v~uv~iv~}c{|v~|lv~}" + "c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|^{|t~}^v~}s{}w~p{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w" + "~}n{|v~|aw~}t{}t~}W{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~c{|y}l~j{}w~j{}w~|O{}w~|k{}w~|c{}w~|k{}w~|c{}w~|k{}" + "w~|c{}w~|k{}w~|Xv~Lv~Lv~Lv~W{}w~|l{|v~`v~m{|w~}b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~f{|Z~}f{}" + "w~|s{}x~|y{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|^{}w~|s{|w~}]v~kv~_{}w~|s{|w~} Vw~yd~|{}x~|kw~yd" + "~|{}x~|kw~qt~|r{}x~|kw~qu~|q{}x~|kw~pv~}q{}x~|[w~|T{|w~}s{}w~} H{|v~|T{|w~|u{}y~({|]~}i{}X~g{|`~b{}b~aw~}kw~}aw" + "~}kw~}\\v~|w{}w~}X{}w~}uv~bw~}Z| 5x|v~}p| v{}w~| {|w~t{|w~S{|}n~|Vw~uv~|y{|}w~}m{}w~}t{}u~rw~}+{|w~}F{}w~|Ox" + "~Z{|Z~},{|m~ x{|w~|X{|v~k{}w~}W{}w~}L{}v~}H{}v~}`{}w~p{}w~}J{}v~`t~n{|v~|V{}v~X{}v~}q{}v~}^{|j~|v~| Z{|t~| ]{|}" + "u~}]{|w~}`{|x~|sw~|o{|w~|t{}x~|l{|v~nv~`{}w~}lv~}dv~}M{}w~}f{|v~|e{}w~}L{}w~}Tv~}m{}n~|h{}w~}hv~|Y{}w~}M{}w~}W{" + "}w~}{|t~S{}w~}V{}w~|u{}x~}y{|w~|uv~|h{}w~|sv~|vv~iv~}c{|v~|e{}k~}|av~}c{|v~|g{}w~}t|y}u~}M{|}s~}X{|v~|Z{|v~h{}w" + "~}`v~}t{}v~d{}w~}vw~|sw~|w{|v~a{|v~}v~|Q{|v~|Q{|u~N{|w~}Hw~|J{|w~| p{}h~|_v~k{}w~|bv~|Ov~k{}w~|bv~j}v~|Yw~}Vv~" + "k{}w~|`w~}m{|w~}Wv~Lv~Tq~}Jv~_w~}mv~mv~hw~}m{|w~}bv~|l{|v~`v~kv~|dv~k{}w~|Zv~P{}r~}y|Pv~S{|w~|m{}w~|^{}w~|s{|w~" + "}b{|w~|vw~|xw~|w{|w~}\\s~|Uv~sv~|Ru~W{|s~}|Iw~|I{|}t~}d{|u~}w|}g~}5{|y~|p{|x~|p{}y~fv~|o{|v~}]v~n{}v~|^{}w~|ts~" + "`v~|l{|v~\\{}p~}Xw~}m{|w~}]{|w~|tv~|Xv~|wv~|]{|w~|m{}w~|h{|v~|q{}x~}q{|v~|iv~|u{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{" + "|w~}bv~kv~|dv~|l{|v~X{|w~}Wv~|l{|v~a{|v~nv~U{|v~}U{}w~}Uv~}d{|v~|l{}v~r{|v~r{|v~|i{}w~}hv~|fu~|v{|v~u{}v~}iv~}c" + "{|v~|n{|T~]{}w~]T~}^{}w~]T~}^{}w~ rw|V{|w~}sy~}X{|w}u~q}Zw~m{}x~|V{}v~\"{|v~ow~|2{|y~|w{|w~d{|y~|4{}w~}v{|v~?w~" + "}8{|y~|sw~vw~}q{|y~| Q{}w~ p{|w~|m{}w~|Ux~}w{|x~}W{|v~| i{}w~|v{|v~Ww~|p{|y~|{}x~`{}x~|j{|x~}bw~|p{|y~}{}x~^{" + "}w~|X{|v~nv~_{|v~nv~_{|v~nv~_{|v~nv~_{|v~nv~_{|w~}nv~|g{}w~}q{|v~Yv~}I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}" + "M{}w~}Z{|v~ev~}h{}w~|sv~|vv~iv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|]{}u~|^v~}t{|w~|p{|v~|i{|v~h{}w~}" + "f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}n{}v~|aw~}s{|s~|[{}h~|\\{}h~|\\{}h~|\\{}h~|\\{}h~|\\{}h~|f{}h~j}v~" + "jv~|Ov~j}v~|cv~j}v~|cv~j}v~|cv~j}v~|Xv~Lv~Lv~Lv~Wv~|l{|v~`w~}m{|w~}bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v" + "~f{|Z~}fv~|t{}x~|wv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|]v~sv~|]v~kv~|_v~sv~| Vw~yd~|{w~jw~yd~|{w~j" + "w~rr~|sw~jw~ru~|pw~jw~pv~}qw~Zw~|Sv~sv~ H{|v~|Rw~}uy~}({|]~}i{}X~|g{}b~|a{}d~|aw~}kw~}aw~}kw~}]{|v~v{|v~X{|v~v{" + "|w~}b{}x~} pf~ v{|w~ {{|w~t{|x~}P{|y~}r~W{}x~|v{}w~u{}w~mv~r{}u~t{|w~|+{|v~F{}w~|Ox~Z{|Z~},{|m~ x{}w~W{|v~k" + "{}w~}W{}w~}M{}v~}F{}v~a{|w~|p{}w~}Iv~|au~}mv~}Vv~|Y{|v~}o{|v~|]{}m~|{v~| Z{|r~}| c{|}r~}]{|w~}`{|x~|sw~|nw~|t{}" + "x~k{}w~}n{}w~}a{}w~}l{|v~|e{}v~M{}w~}f{}v~d{}w~}L{}w~}T{}v~mr|v~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}y{|t~T{}w~}V{}w~|u" + "{|w~y{}w~tv~|h{}w~|s{|v~vv~i{}v~c{|v~|e{}w~}r|]{}v~c{|v~|g{}w~}q{}v~}K{|t~|Y{|v~|Z{|v~h{}w~}`{}v~tv~|d{|v~w{|w~" + "|s{}x~}w{}w~}av~}{}v~Q{|v~|R{|u~M{|w~}H{}x~}J{|w~| r{|f~|_w~}k{}w~|bv~|Ov~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~" + "Lv~Tq~Iv~_w~}mv~mv~hw~}m{|w~}bv~jv~`v~k{}w~|dv~k{}w~|Zw~}O{}o~}|Sv~S{|w~|m{}w~|^{|w~}s{}w~|b{|w~}w{|w~w{}x~}w{|" + "w~|\\{|u~}T{}w~|u{|w~}Ru~V{|s~}|Iw~|J{|}s~}d{|w~|s{|}k~|3y~}p{|x~}p{}y~fv~mv~|]v~m{}v~_{|w~}rt~`v~jv~Z{}r~}Xw~}" + "m{|w~}\\w~}u{|w~}X{|w~}v{}w~}]{|w~|m{}w~|h{|v~|q{}x~}pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~k{}w~|dv~jv" + "~X{|w~}W{}w~|l{|v~a{}w~}n{}w~}W{|u~T{}w~}U{}w~}d{}v~k{}v~|s{|v~r{}v~h{}w~}hv~|f{|u~|w{|v~v{}u~h{}v~c{|v~|n{|T~]" + "{}w~]T~|^{}w~]{}U~}^{}w~ s{|w~V{|w~}sy~}S{|v~Pw~|nw~|V{|w~}!{}v~|q{}x~|1y~}vw~|e{}y~ci|]{}w~u{|w~|?w~}7y~}sw~v{" + "|w~|r{}y~ P{}w~ p{|w~|m{}w~|Ux~}w{|x~}W{|v~| Fi|U{|w~|u{}w~X{}x~}p{|y~}y{}x~a{|w~i{|x~}c{}x~}p{|y~}y{}x~^{}w~|" + "X{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~|n{}w~}h{|v~p{|v~Y{}v~I{}w~}M{}w~}M{}w~}M{}w~}" + "D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|s{|v~vv~i{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|^{}s~|_" + "{}v~u{|w~|o{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}o{|u~`w~}q{}t~|^{|f~|^{|f~|^{|f~|^{|f~|" + "^{|f~|^{|f~|h{|P~jv~|O`~|c`~|c`~|c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~f{|Z~}fv~|u{}x~}" + "vv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|]{}w~|u{|w~}\\v~k{}w~|_{}w~|u{|w~} Uw~yq}w~r}yw~jw~yd|yw~jw~" + "sp~|tw~jw~su~|ow~jw~pv~}qw~Zw~|S{}w~}u{|w~} Hv~|Q{}w~|w{|y~|({|\\~iW~|f{}d~|_e~|`w~}kw~}aw~}kw~|]{}w~}uv~Wv~|w{" + "}w~|b{}x~} q{|g~| v{|w~({}Z~X{|y~|{|}u~}Y{|w~uw~|tw~}o{|w~}q{}u~u{}w~*{|v~F{}w~|*m|}w~l|,{|m~ xw~}W{|v~k{}w" + "~}W{}w~}N{}v~}Dv~|bw~}o{}w~}Iv~|au~|m{}w~}W{|v~X{}v~m{}v~\\{|p~}xv~| Y{}p~}| i{|}p~}|]{}w~}`{|x~|sw~mw~|t{}x~kv" + "~}n|}v~a{}w~}kv~}e{}v~M{}w~}f{}v~d{}w~}L{}w~}T{}v~dv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}x{|t~U{}w~}V{}w~|tw~|{w~}tv~|" + "h{}w~|rv~}wv~i{}v~c{}v~d{}w~}T{}v~c{}v~f{}w~}p{}v~|Ju~}Y{|v~|Z{|v~h{}w~}_v~|v{|v~bv~|x{|w~r{}w~wv~|b{}v~xv~}R{|" + "v~|Ru~|M{|w~}H{|w~J{|w~| s{|q~t}v~|_w~}k{}w~|bv~Nv~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tp~Jv~_w~}mv~mv~hw~}" + "m{|w~}bv~jv~`w~}k{}w~|dv~k{}w~|Zw~}N{|m~|Uv~S{|w~|m{}w~|]v~t{|v~`v~w{}x~}w{|x~}w{}w~[{|u~|T{|w~}u{}w~|S{}v~|V{|" + "x}t~}Jw~|K{|s~y}|d{|y~}n{|}p~}1y~}p{}w~p{}y~fv~mv~\\v~lv~|`{}w~|r{|v~}`v~jv~\\{|p~}Xw~}m{|w~}\\{}w~u{}w~|Xv~|v{" + "|v~]{|w~|m{}w~|h{|v~p{}w~pv~}iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bw~}k{}w~|dv~jv~X{|w~}W{}w~|l{|w~}av~|n{|v" + "~Wu~|T{}w~}U{}v~dv~}k{|v~}s{|v~s{|v~}h{}w~}hv~|e{}u~|x{|v~w{}u~|h{}v~c{}v~l{|u~}\\|]{}w~][|u~|]{}w~\\{}v~}c|u~}" + "]{}w~ s{|w~V{|w~}sy~}S{|v~P{}x~}o{|w~`{|a~}+u~|rw~|1y~}v{}w~ex~d{|j~}]{}w~}v{|v~|@w~}7y~}sw~u{}w~rx~ P{}w~ p{|" + "w~|m{}w~|Ux~}w{|x~} w{|j~}V{|v~|v{}w~}Xw~oy~}x{}x~aw~|i{|x~|cw~ox~x{}x~^{}w~|Xv~}n|}v~`v~}n|}v~`v~}n|}v~`v~}n|" + "}v~`v~}n|}v~a{|b~h{}v~p|}v~Y{}v~I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|rv~}wv~i{}v~c{" + "}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~^{}q~|`{}v~v{|w~}n{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{" + "|v~|V{}w~}p{|u~|`w~}p{|t~}`{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|i{|q~t}`~|kv~N`~|c`~|c`~|" + "c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~f{|Z~}fv~u{|x~}uv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m" + "{}w~|a{|w~|m{}w~|]{|w~}u{}w~|\\w~}k{}w~|_{|w~}u{}w~| U{}x~|q{}w~q{|w~j{}x~|b{|w~j{}x~|uu~|u~|v{|w~j{}x~|uu~|o{|" + "w~j{}x~|qv}|r{|w~[{|w~|S{|v~uv~| TZ~}a{|w~}wx~'{|\\~iW~|ee~|^{|g~}_w~}kw~}aw~}kw~|]v~|u{}w~|X{}w~}wv~|b{|w~| " + " r{}g~ u{|w~({}Z~X{|y~|w{}v~|Zw~|v{|w~s{|w~o{|w~}p{}u~vw~})v~Fv~| w{}w~ x{|m~ y{|w~|Vv~|lv~|W{}w~}O{}v~}C{}w~}" + "c{|w~n|}w~}v|N{}w~}au~l{|v~Wv~}Xv~}m{|v~|[{|y}w~y}|x{|v~ V{|}p~}|XY|X{|}q~}|Z{}w~}`{|x~|sw~mw~|tw~l{|b~|b{}w~}k" + "{}v~e{|v~|N{}w~}fv~}d{}w~}L{}w~}T{|v~|ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}w{|t~V{}w~}V{}w~|t{}w~|w~|tv~|h{}w~|r{|v~" + "wv~i{|v~|d{}v~d{}w~}T{|v~|d{}v~f{}w~}o{}v~J{|u~Y{|v~|Z{|v~h{}w~}_{}w~}v{}w~}b{}w~}x{}x~}r{|w~wv~b{|v~|x{|v~|S{|" + "v~|S{}v~|L{|w~}Gw~|K{|w~| t{|u~}|q{}w~|_v~k{}w~|bv~Nv~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tw~}|u~Kv~_w~}mv~" + "mv~hw~}m{|w~}bv~jv~`w~}k{}w~|dv~k{}w~|Zw~}L{|}o~}Vv~S{|w~|m{}w~|]{}w~}u{}w~}`{}w~|xw~|w{|w~wv~\\{|s~Sv~uv~S{}v~" + "|O{}v~}Kw~|L{|v~}|_{|~|j{|y}x~y}|/x~q{|v~}qx~fv~m{}x~}\\v~l{}w~|`v~pv~}`v~jv~]n~}Xw~}m{|w~}\\{|w~|vv~X{|v~t{}w~" + "|^{|w~|m{}w~|h{|v~p{}w~pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bw~}k{}w~|dv~jv~X{|w~}W{}w~}l{}w~}b{|v~lv~|Y" + "{}v~|S{}w~}U{|v~}f{|v~|ju~|t{|v~s{}v~|h{}w~}hv~|dt~}y{|v~y{|t~|g{|v~|d{}v~k{|u~|?{}w~>u~|b{|v{}w~[{}v~|e{}v~}\\" + "{}w~ s{|w~V{|w~}sy~}S{|v~P{|w~o{}x~}`{|a~}+{|u~}|u{|w~0{}y~v{|w~}g{|y~}d{|j~}\\{}v~|w{|v~}Aw~}7{}y~sw~tw~}t{|y~" + "} P{}w~ p{|w~|m{}w~|Ux~}w{|x~} w{|j~}W{|v~|vv~}X{}x~|p{}y~|x{}x~b{}x~}hw~c{}x~}p{}y~|x{}x~^v~X{|b~|b{|b~|b{|b" + "~|b{|b~|b{|b~|b{}b~}id~Y{|v~|J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{}v~g{}w~|r{|v~wv~i{|v~|d{}v" + "~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~_{}v~}u~|a{|v~|ww~}m{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w" + "~}Z{|v~|V{}w~}sy|s~_w~}n{}u~|b{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|j{|u" + "~}|q{}a~|kv~N`~|c`~|c`~|c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~.v~v{|w~tv~a{|w~|m{}w~|a{" + "|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|\\v~uv~[w~}k{}w~|^v~uv~ T{}x~}q{}w~q{|x~}j{}x~}b{|x~}j{}x~}vu~|{|u~|w{|x~}j{}" + "x~}vu~|n{|x~}j{}x~}b{|x~}[{|w~Qv~|w{|v~ SZ~}`v~x{|y~}'{|]~}iW~|e{|g~}\\{}i~}^w~}kw~}aw~}l{|w~|^{|v~t{|w~}X{|v~x" + "{|v~`w~} m{|v~ jw|({}Z~X{|y~|v{}w~}[{}x~}u{}x~}s{|w~o{}w~}o{}u~x{|w~|)v~Fv~ v{}w~ g{}w~Uv~|lv~|W{}w~}P{}v~" + "}B{|v~c{|_~|O{}w~}a{}v~l{|v~X{|v~|Y{|v~|lv~|N{|v~ S{|}p~|[{|Z~}[{|}p~}|X{}w~}`{|x~|sw~|nw~|u{|x~}l{}b~}b{}w~}k{" + "|v~e{|v~}N{}w~}g{|v~}d{}w~}L{}w~}T{|v~}ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}v{|t~W{}w~}V{}w~|t{|r~sv~|h{}w~|q{}w~}xv" + "~i{|v~}dv~}d{}w~}T{|v~}dv~}f{}w~}nv~}J{}v~Y{|v~|Z{|v~|i{}w~}_{|v~vv~|b{}w~}xw~|qw~|y{|v~bv~}v{}v~S{|v~|T{}v~}K{" + "|w~}G{}x~}K{|w~| tv~}n{}w~|_v~kv~|bv~|Ov~k{}w~|bv~Bw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tw~}{|u~|Mv~_w~}mv~mv~hw~}m{|w~" + "}bv~|kv~`v~k{}w~|dv~k{}w~|Zw~}Iy|}q~Wv~S{|w~|m{}w~|]{|v~uv~_{|w~|xw~uw~|y{|w~}\\r~}T{|w~|w{}w~}T{}v~|M{|v~Kw~|L" + "{}w~} O{}y~|rt~|s{|y~}fv~|nw~}\\v~l{|w~}`w~}p{}w~|`v~|kv~^u~}|Qw~}m{|w~}[w~}w{}w~}X{}w~|t{|w~}^{|w~|m{}w~|h{|v~" + "pv~pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~k{}w~|dv~|l{|v~X{|w~}W{|w~}l{}w~|b{}w~}l{}w~}Z{|v~}R{}w~}T{}v" + "~f{}v~i{|u~t{|v~t{|u~g{}w~}hv~|cr~}v~}s~}f{|v~}dv~}j{|u~|@{}w~?u~|b{}~|w{}w~vy~a{}v~|g{}v~}b{}~|w{}w~vy} {{}w~|" + "W{|w~}sy~}S{|v~Ow~}q{|w~|`{|a~}){}u~}vw~}0{|y~}v{}w~}p{|t{}y~|d{|j~}[{|v~|vv~}Bw~}7{|y~}tw~t{|w~|u{}y~| P{}w~ " + "p{|w~|m{}w~|Ux~}w{|x~} w{|j~}X{}v~v{|v~}X{|w~p{|y~|w{}x~bw~h{}x~|d{|w~p{|y~}w{}x~^v~X{}b~}b{}b~}b{}b~}b{}b~}b{" + "}b~}b`~j{}d~Y{|v~}J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~fv~}g{}w~|q{}w~}xv~i{|v~}dv~}k{|v~}dv~}k" + "{|v~}dv~}k{|v~}dv~}k{|v~}dv~}`{}v~|{|u~|b{|v~}x{}x~}lv~}h{|v~|i{}w~}f{|v~|i{}w~}f{|v~|i{}w~}f{|v~|i{}w~}Z{|v~|V" + "{}e~|_w~}m{|u~bv~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|jv~}n{}w~Tv~|Ov~Lv~Lv~Lv~Av~Lv~Lv~Lv~" + "Wv~|l{|v~`w~}m{|w~}bv~|kv~bv~|kv~bv~|kv~bv~|kv~bv~|kv~.v~vw~|u{|v~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}" + "w~|\\{|w~|w{}w~}[v~k{}w~|^{|w~|w{}w~} T{|w~q{}w~q{}x~|j{|w~b{}x~|j{|w~wu~|x{|u~|x{}x~|j{|w~wu~|m{}x~|j{|w~b{}x~" + "|[{|w~Q{|w~}w{}w~} SZ~}`{}w~|y{}y~|'{|n~y}~|n~}i{}k~x}k~c{|i~}Z{}j~]w~}kw~}a{}w~l{|w~|^{}w~}sv~Wv~|y{}w~}`{}w~|" + " mv~| o{}Z~X{|y~|v{|w~}\\{|w~t{}x~|rw~|p{}w~}n{}u~yw~}(v~|Gv~ v{}w~ gw~}U{}w~}m{|v~V{}w~}Q{}v~}A{|v~c{|_~" + "|O{}w~}a{}v~l{|v~X{}v~X{|v~k{}w~}N{}w~} Q{|}p~}|^{|Z~}^{|}p~}|U{}w~}`{|x~}sw~|o{|w~|u{}x~|l`~b{}w~}k{|v~|eu~N{}" + "w~}g{}v~|d{}w~}L{}w~}Su~ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}u{|t~X{}w~}V{}w~|ss~}sv~|h{}w~|q{|v~|yv~hu~e{|v~|d{}w~}" + "Su~e{|v~|f{}w~}n{}v~|K{|v~|Z{|v~|Yv~|i{}w~}^v~|x{}v~a{|v~y{|w~|q{}x~}y{}w~}c{}v~tv~}T{|v~|U{|v~}J{|w~}G{|w~K{|w" + "~| u{|v~m{}w~|_v~kv~a{}w~|O{}w~|l{}w~|bv~|Cw~}V{}w~|l{}w~|`w~}m{|w~}Wv~Lv~Tw~}y{|u~|Nv~_w~}mv~mv~hw~}m{|w~}bv~" + "|l{|v~`v~kv~cv~|l{}w~|Zw~}D{|}u~}Xv~S{|w~|m{}w~|\\{}w~|w{|w~}^w~}y{|w~u{}x~}y{}w~|]{}q~|Tv~wv~|U{|v~}K{}w~|Lw~|" + "Lv~ N{|x~s{}x~{w~|tx~|fv~|o{|v~\\v~l{|w~}a{|w~|p{}w~_{}w~|l{|v~_{}v~|Ow~}m{|w~}[{}w~|xv~X{|v~rv~|_{|w~|m{}w~|h{" + "|v~|qv~pv~|iv~|u{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~|bv~kv~c{}w~|l{|v~X{|w~}Vv~l{}w~|bv~|l{|v~[{|v~}Q{}w~}T{|v~}" + "h{|v~|hu~}u{|v~u{|u~|g{}w~}hv~|b{}f~|du~e{|v~|i{|u~|A{}w~@u~|b{}x~|x{}w~ww~a{}v~|i{}v~}b{}x~|x{}w~w{}y~} {}w~|W" + "{|v~sy~}S{|v~O{|w~}s{}w~}^q|}v~q|'{}t~|{|w~}.x~u{}v~}|wy|}y~tx~/{|v~|v{}w~}Cw~}6x~tw~s{}w~ux~ O{}w~ p{|w~|m{}w" + "~|Ux~}w{|x~} B{}w~}v{|v~|Ww~|q{|y~}v{}x~c{}x~|i{}x~}cw~|q{|y~}v{}x~_{|v~X`~b`~b`~b`~b`~c{|`~|kc~Xu~J{}w~}M{}w~" + "}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~g{|v~}g{}w~|q{|v~|yv~hu~e{|v~|ju~e{|v~|ju~e{|v~|ju~e{|v~|ju~e{|v~|a{}" + "v~|x{|u~|bu~y{}w~l{|v~|gv~|i{}w~}ev~|i{}w~}ev~|i{}w~}ev~|i{}w~}Z{|v~|V{}f~|^w~}l{|v~|d{|v~m{}w~|a{|v~m{}w~|a{|v" + "~m{}w~|a{|v~m{}w~|a{|v~m{}w~|a{|v~m{}w~|k{|v~m{}w~T{}w~|Ov~|Mv~|Mv~|Mv~|Bv~Lv~Lv~Lv~W{}w~|l{|v~`w~}m{|w~}bv~|l{" + "|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~.v~|x{}x~|t{|v~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|[v~wv~|[v" + "~kv~\\v~wv~| Sw~|r{}w~r{|w~hw~|d{|w~hw~|yu~|v{|u~y{|w~hw~|yu~|m{|w~hw~|d{|w~Z{|w~Pv~wv~| SZ~}_w~}yx~%n~{|~{|o~|" + "i{|l~}|}|l~}b{}j~Xk~|]w~}kw~}a{}w~l{}w~]v~|s{}w~|X{}w~}yv~|_w~} mv~} g{}x~}t{}x~}O{|y~|uw~}\\{}x~|t{}x~|rw" + "~|p{|w~}m{}u~}w~|({}w~|H{|w~} v{}w~ h{|w~|U{}w~}m{|v~V{}w~}R{}v~}@{|v~c{|_~|Ov~|a{|v~l{}w~}Xv~}X{|v~k{}w~}Nv~|" + " N{|}p~}|a{|Z~}a{|}p~}|R{|w}|_x~}s{}x~}o{}w~|v{|w~l{}`~|c{}w~}k{|v~|e{}v~|O{}w~}gu~c{}w~}L{}w~}S{}v~|fv~|h{}w~}" + "hv~|Y{}w~}M{}w~}W{}w~}t{|t~Y{}w~}V{}w~|s{}t~rv~|h{}w~|p{}w~}yv~h{}v~|f{}v~c{}w~}S{}v~|f{}v~e{}w~}mv~}K{|v~|Z{|v" + "~|Yv~|iv~|^{}w~}xv~}`v~|{|w~p{}w~yv~|d{|v~|t{|v~|U{|v~|V{|u~I{|w~}Fw~|L{|w~| u{}w~|mv~|_v~|m{|v~a{}w~}O{}w~|lv" + "~|b{}w~|Cw~}V{}w~|lv~|`w~}m{|w~}Wv~Lv~Tw~}x{|u~|Ov~_w~}mv~mv~hw~}m{|w~}b{}w~|l{|w~}`v~kv~c{}w~|lv~|Zw~}B{|u~Xv~" + "S{|w~|m{}w~|\\{|w~}w{}w~|^v~y{}x~}u{|x~}y{}w~]{|v~|}v~T{}w~|y{|w~}U{|v~}J{|w~}Lw~|M{|w~} Mx~}v{|w~|{|w~|v{}x~e{" + "}w~|o{}v~\\v~l{|w~}a{|w~|pw~}_{}w~|l{|w~}_v~Mw~}m{|w~}[{|w~}y{|w~}X{}w~|r{}w~}_{|w~|m{}w~|h{|v~|qv~|r{|v~|i{}w~" + "|u{}w~tv~|b{|w~}q{|w~}`v~t{}w~t{}w~|bv~kv~c{}w~|l{|w~}X{|w~}Vv~lv~b{}v~jv~|\\u~P{}w~}S{}v~|iu~g{|t~|w{|v~v{}u~}" + "f{}w~}hv~|a{}h~|c{}v~|f{}v~g{|u~|B{}w~Au~|b{}v~|y{}w~xu~a{}v~|k{}v~}b{}v~|y{}w~x{}w~}!{}w~|Vv~sy~}S{|v~O{|u~}y|" + "{y|u~}T{|w~}Lw}|P{|}p~}-{|y~}u{}l~u{}y~|.{|v~|v{}w~}Dw~}6{|y~}uw~rw~}w{}y~| O{}w~ p{|w~|m{}w~|Ux~}w{|x~} C{}w" + "~}v{|v~|W{}x~}px~u{}x~d{|w~i{}x~}c{}x~}px~u{}x~_{}w~}Y{}`~|d{}`~|d{}`~|d{}`~|d{}`~|d{}w~}j|}w~}l{|c~X{}v~|K{}w~" + "}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~gu~|g{}w~|p{}w~}yv~h{}v~|f{}v~i{}v~|f{}v~i{}v~|f{}v~i{}v~|f{}v~" + "i{}v~|f{}v~a{}v~|v{|u~|c{}v~|}w~|l{}v~fv~|iv~|ev~|iv~|ev~|iv~|ev~|iv~|Z{|v~|V{}h~}\\w~}k{}w~|d{}w~|mv~|a{}w~|mv" + "~|a{}w~|mv~|a{}w~|mv~|a{}w~|mv~|a{}w~|mv~|k{}w~|mv~|U{}w~}O{}w~|M{}w~|M{}w~|M{}w~|Bv~Lv~Lv~Lv~W{}w~}l{}w~}`w~}m" + "{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}.{}w~|y{}x~|s{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w" + "~|m{}w~|a{|w~|m{}w~|[{}w~|y{|w~}Zv~kv~\\{}w~|y{|w~} R{|w~r{}w~rw~}h{|w~dw~}h{|w~y{|w~|t{|w~}yw~}h{|w~y{|w~|lw~}" + "h{|w~dw~}Z{|w~P{}w~|y{|w~} Rs}v~g}|_{}w~{|y~}%{|p~|{|~yp~}g{}m~{}~{}m~|a{}l~|X{|m~}\\w~}kw~}a{|w~|mv~]v~r{}w~}X" + "{|v~{|v~^{}w~} n{}v~ gw~|tw~|O{|y~|uw~}]{|x~}sw~|rw~|p{|v~l{}r~}'{|w~}H{|w~} v{}w~ h{|w~T{|v~m{}w~}V{}w~}" + "S{}v~}?{|v~c{|_~|Ov~|`v~|m{}w~}Y{|v~W{|v~k{}w~}O{|v~ J{|}p~}|d{|Z~}d{|}p~}|-w~s{|w~ov~|v{}x~|lv~|j{|v~c{}w~}k{}" + "v~cv~}O{}w~}h{}v~|c{}w~}L{}w~}Rv~}fv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}rt~Z{}w~}V{}w~|ru~}rv~|h{}w~|p{|v~|{v~h{|v~}g" + "{|v~}c{}w~}Rv~}g{|v~}e{}w~}m{|v~|L{|v~|Z{|v~|Y{}w~}j{|v~|^{|v~|{|v~_{}w~}{}x~}p{|w~yv~cv~}r{}v~U{|v~|W{|u~|I{|w" + "~}F{}x~}L{|w~| u{}w~|n{|v~|_v~}m{}w~}a{|w~}O{|w~}m{|v~|b{}w~}Cw~}V{|w~}m{|v~|`w~}m{|w~}Wv~Lv~Tw~}vu~|Pv~_w~}mv" + "~mv~hw~}m{|w~}b{|w~}l{}w~}`v~|m{|w~}c{|w~}lv~|Zw~}@v~|Yv~S{|w~}mv~|[v~wv~]{}w~|{w~|u{|w~yw~}]v~}y{}v~U{|w~}y{}w" + "~|V{|v~}I{|w~}Lw~|M{|w~} M{|w~x}v~}x{}v~x}w~|e{}w~}ou~|]v~l{|w~|a{|w~p{}w~|_{|w~}l{}w~}`{|w~}Mw~}m{|w~}Zv~y{}w~" + "|Y{|v~q{|v~_{|w~}m{}w~|gv~|r{|v~|r{|v~h{}w~}u{}w~tv~a{|w~}q{|w~}`v~t{}w~t{}w~|bv~|m{|w~}c{|w~}l{}w~}X{|w~}V{}w~" + "|n{|w~}bv~}j{}v~]{}v~|P{}w~}Ru~j{}v~|f{|t~}|y{|v~x{|t~}e{}w~}hv~|`{|}l~}`v~}g{|v~}f{|u~|C{}w~Bu~|`u~|{}w~yu~|`{" + "}v~|m{}v~}a{|u~|{}w~y{}v~}!{}w~|Vv~|ty~}S{|v~P{|g~}U{|w~}Lw~|N{|r~}+{}y~|u{|}o~}v{|y~}+v~}v{}v~Ew~}5{}y~|vw~r{|" + "w~|y{|y~} N{}w~ p{|w~}m{}w~|Ux~}w{|x~} Dv~}v{}v~|W{|w~p{}y~|u{}x~dw~|j{}w~c{|w~p{}y~|u{}x~`{}v~|Yv~|j{|v~dv~|" + "j{|v~dv~|j{|v~dv~|j{|v~dv~|j{|v~dv~|j{|v~l{}w~}n{|v~Wv~}K{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~h{" + "|v~}f{}w~|p{|v~|{v~h{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}b{}v~|t{|u~|cq~|l{|v~}f{}w~}j{|v" + "~|e{}w~}j{|v~|e{}w~}j{|v~|e{}w~}j{|v~|Z{|v~|V{}k~}|Zw~}k{}w~}d{}w~|n{|v~|a{}w~|n{|v~|a{}w~|n{|v~|a{}w~|n{|v~|a{" + "}w~|n{|v~|a{}w~|n{|v~|k{}w~|n{|v~}U{|w~}O{}w~}M{}w~}M{}w~}M{}w~}Bv~Lv~Lv~Lv~W{|v~lv~|`w~}m{|w~}b{|w~}l{}w~}b{|w" + "~}l{}w~}b{|w~}l{}w~}b{|w~}l{}w~}b{|w~}l{}w~}Xt|X{}w~}{}x~}r{}w~}a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|[{|w~}y" + "{}w~|Zv~|m{|w~}\\{|w~}y{}w~| Qw~}s{}w~s{}w~fw~}f{}w~fw~}y{|y~|r{|y~}y{}w~fw~}y{|y~|l{}w~fw~}f{}w~Y{|w~P{|v~y{}w" + "~| Kv~}J{|w~|}y~|${}r~}y{}~y{|q~f{|n~|{}~yn~}_m~|V{|o~}[w~}kw~}`w~}n{|w~}^{|w~}r{|v~Wv~{}w~}]v~| o{|v~| hw" + "~t{|w~N{|y~|uw~}]w~|s{}x~|rw~|ov~|l{}s~&{|w~}H{}w~| v{}w~ h{}x~}Sv~|nv~|V{}w~}T{}v~}>{}w~}Q{}w~}J{}v~_{}w~}mv~" + "}Y{}w~}Vv~|lv~|Ov~} G{|}p~}|0{|}o~}*{}x~rw~}q{}v~|w{}w~l{|v~hv~|d{}w~}ku~c{}v~}P{}w~}i{}u~b{}w~}L{}w~}R{}v~|gv~" + "|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}qt~[{}w~}V{}w~|r{}v~|rv~|h{}w~|o{}w~}{v~g{}v~|hu~|c{}w~}R{}v~|hu~|e{}w~}lv~}L{}v~Y" + "{|v~|Y{}v~j{}v~\\{}w~}{}w~}_{|v~{w~|ow~y|v~d{}v~pv~}V{|v~|Wu~|H{|w~}F{|w~L{|w~| u{}w~m{}v~|_u~mv~|a{|v~Nv~|n{}" + "v~|b{|v~Cw~}Uv~|n{}v~|`w~}m{|w~}Wv~Lv~Tw~}uu~|Qv~_w~}mv~mv~hw~}m{|w~}b{|v~lv~|`v~}m{}w~}c{|v~m{|v~|Zw~}@{}w~|Yv" + "~S{|w~}mv~|[{}w~|y{|w~}]{|w~}{w~sw~y|w~}^{}w~}wv~}U{}w~yv~Uv~}Gw~}Lw~|M{|w~| L{|q~}v{}q~|d{|w~}p{|u~|]v~l{}w~|a" + "{|w~pv~^{|v~lv~|`{|w~|Mw~}m{|w~}Z{}w~y|v~X{}w~}pv~|`{|w~}mv~|gv~}r{|v~}r{}v~h{|v~u{}w~u{|w~}a{|w~}q{|w~}`{}w~|u" + "{}w~tv~av~}m{}w~}c{|v~lv~|X{|w~}V{|w~}n{}w~|c{|v~i{|v~|_{}v~}O{}w~}R{|v~}l{}v~|d{|r~y}v~y}s~}d{}w~}hv~|]{|}s~y}" + "|^{}v~|hu~|e{|v~}C{}w~C{}v~|^u~|}w~{}v~|^{}v~n{|v~}_{|u~|}w~{}v~} {}w~|V{}w~}ty~}S{|v~Q{}e~}V{|w~}Lw~|L{|t~*{|x" + "~|t{|y}u~}|u{|x~|*{}w~|v{|v~Fw~}5{|x~|ww|qw|y{|x~| >{|w~}mv~|Ux~}w{|x~} Ev~}v{|v~U{}x~|q{|y~}t{}x~e{}x~}j{}w" + "~b{}x~|q{|y~}t{}x~a{}v~}Y{|v~hv~|f{|v~hv~|f{|v~hv~|f{|v~hv~|f{|v~hv~|f{}v~hv~|n{|v~|n{|v~W{}v~}L{}w~}M{}w~}M{}w" + "~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~i{|u~|f{}w~|o{}w~}{v~g{}v~|hu~|h{}v~|hu~|h{}v~|hu~|h{}v~|hu~|h{}v~|hu~|c{}" + "v~|r{|u~|d{}s~|ku~|f{}v~j{}v~d{}v~j{}v~d{}v~j{}v~d{}v~j{}v~Y{|v~|V{}w~}r|Vw~}k{|w~|d{}w~m{}v~|a{}w~m{}v~|a{}w~m" + "{}v~|a{}w~m{}v~|a{}w~m{}v~|a{}w~m{}v~|k{}w~m{}u~U{|v~O{|v~M{|v~M{|v~M{|v~Bv~Lv~Lv~Lv~Vv~|n{|v~_w~}m{|w~}b{|v~lv" + "~|b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|X{}u~X{|v~|x~}qv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|Z{}w~yv~Yv~}m{}" + "w~}[{}w~yv~ P{|w~}t{}w~t{|w~}f{|w~}h{|w~}f{|w~}yy|p{|}y{|w~}f{|w~}yy|l{|w~}f{|w~}h{|w~}Y{|w~Ov~y|v~ K{}w~}Hw~}y" + "~}\"{}t~}x{}~x{|s~d{|p~}y{}~y{|p~}]o~|T{}p~Zw~}kw~}`{}w~|o{}w~|^{}w~|qv~|X{}w~|v~|]{|v~| o{}v~j{} {|x~}t{|" + "x~}N{|y~|v{}w~}^{}x~}r{}x~}rw~|o{}v~k{}u~|%v~Hv~ u{}w~ hw~|S{}v~o{}v~U{}w~}U{}v~}>{|v~}Q{}w~}Ju~_{|v~n{|v~|Z{|" + "v~|Vv~}m{|v~|P{}v~ C{}o~}4{|o~}|({|x~}s{}w~}s{}u~|x{}w~|l{}w~}h{}w~}d{}w~}l{|v~}bu~|g{|}g{}w~}j{}u~|b{}w~}L{}w~" + "}R{|u~|hv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}pt~\\{}w~}V{}w~|r{|v}qv~|h{}w~|nv~|v~g{|u~|j{}v~}b{}w~}R{|u~i{}v~}d{}w~}" + "l{|v~|M{}v~Y{|v~|Y{|v~|kv~}\\{|v~{v~|_{|v~|w~|o{}x~y}w~}e{|v~|p{|v~|W{|v~|X{}v~}G{|w~}F{|w~|M{|w~| u{}w~|nu~|_" + "u~}o{}v~_v~}O{}w~}o{|u~|av~}Dw~}U{}w~}o{|u~|`w~}m{|w~}Wv~Lv~Tw~}t{}v~|Rv~_w~}mv~mv~hw~}m{|w~}av~|n{|v~_u~mv~|bv" + "~|n{}v~|Zw~}@{}w~|Yv~Rv~n{}v~|[{|w~}y{}w~|\\w~}|x~}s{}x~y}w~|_{}v~v{|v~|V{|w~y}w~}Vu~Fw~}Lw~|M{|w~| K{|s~}t{}s~" + "|bv~p{}u~}]v~|mv~`{|w~q{}w~}]v~}n{}v~_{|w~|Mw~}m{|w~}Yw~y}w~|Xv~o{|w~}`{|v~n{|v~|g{}v~r{}u~rv~}gv~|v{}w~uv~|a{|" + "w~}q{|w~}`{|w~}u{}w~u{|v~au~mv~|bv~}n{}v~Vv~Uv~nv~b{}w~}hv~}`{|v~}N{}w~}Q{|v~}n{}v~}b{|c~}c{}w~}hv~|Z{|v~Z{|u~|" + "j{}v~}c{|w~B{}w~B{}x~|\\u~}w~}v~|\\{}x~|m{}x~}]{|u~}w~}v~} {{v~|V{|v~|uy~}S{|v~R{}v~y|q~}|u~W{|w~}Lw~|J{}u~*{|x" + "~|e{|x~|({}x~}u{|w~F{|x}|4{|x~|e{|x~| ={|v~n{|v~|Ux~}w{|x~} Ew~|u{|x~}U{|x~}p{}j~}iw~j{}w~b{|x~}p{}j~}f{}v~}" + "X{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}fv~}h{}w~}n{}w~}m{|v~Vu~|g{|}c{}w~}M{}w~}M{}w~}M{}w" + "~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~j{|u~}e{}w~|nv~|v~g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}c{" + "}v~|p{|u~|e{|t~}k{}v~}e{|v~|kv~}d{|v~|kv~}d{|v~|kv~}d{|v~|kv~}Y{|v~|V{}w~}Mw~}k{}w~|d{}w~|nu~|a{}w~|nu~|a{}w~|n" + "u~|a{}w~|nu~|a{}w~|nu~|a{}w~|nu~|k{}w~|nt~|Uv~}Ov~}Mv~}Mv~}Mv~}Cv~Lv~Lv~Lv~V{}v~nv~}_w~}m{|w~}av~|n{|v~`v~|n{|v" + "~`v~|n{|v~`v~|n{|v~`v~|n{|v~W{}u~Wr~q{|v~_v~n{}v~|`v~n{}v~|`v~n{}v~|`v~n{}v~|Z{|w~y}w~}Yu~mv~|[{|w~y}w~} O{}w~}" + "u{}w~u{}w~}d{}w~}j{}w~}d{}w~}j{}w~}d{}w~}j{}w~}d{}w~}j{}w~}X{}w~O{|w~y}w~} L{}w~}G{}u~|!{|}x~}|w{}~v{}w~}b{|r~|" + "x{}~w{}s~|\\{|q~}Rq~|Zw~}kw~}`{|v~p{|v~]v~p{}w~}X{|q~[{}v~} p{|v~}ly}$v}|\"{}x~}t{}x~}Yy}|s{|y~|w{|v~|_{|w~" + "q{}x~}s{|w~n{|v~}l{|u~}%{}w~|Iw~} u{}w~L{}w~} tv}|P{|w~R{|v~|pv~}U{}w~}V{}v~}={}v~|Q{}w~}K{}v~|^v~|o{}v~Y{}v~U{" + "}v~m{}v~P{|v~}U{|v}M{}w~}F{|}q~}6{|q~}|G{|w}|^w~ru~y|x{|}t~y|}v~|kv~|h{|v~d{}w~}m{|u~|b{|u~|i{|~}g{}w~}l{|}u~}a" + "{}w~}L{}w~}Q{}u~|iv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}ot~]{}w~}V{}w~|bv~|h{}w~|n{}q~f{}u~k{}u~a{}w~}Q{}u~k{|u~c{}w~}" + "kv~}c{|}h{|v~}Y{|v~|X{}v~l{}v~|[v~}v~]v~}w~n{}r~|ev~}n{}v~W{|v~|Y{}v~}F{|w~}Ew~}M{|w~| u{}w~|o{}u~|_t~|q{|v~}_" + "{|v~|P{|v~}pt~|a{|v~|Ew~}U{|v~|pt~|`w~}m{|w~}Wv~Lv~Tw~}s{}v~|Sv~_w~}mv~mv~hw~}m{|w~}a{}v~nv~}_u~}o{}v~a{}v~o{|u" + "~|Zw~}@{}w~|Y{}w~|Sv~|p{|u~|Zv~{|v~[v~}x~}s{|r~_{|v~|u{}v~Uq~V{}v~|Fw~}Lw~|M{|w~| I{|y}~y}|r{|}x~}|`{}w~}qs~]u~" + "n{|v~`{|w~r{|v~\\{|v~nv~}_{|w~}Mw~}m{|w~}Y{}r~X{}w~}nv~`{|v~|o{}v~|g{|v~|st~|t{|v~|g{}v~v{}w~v{|v~`{|w~}q{|w~}_" + "v~|v{}w~uv~}au~}o{}v~a{|v~nv~}Vv~U{|w~}p{}w~}bv~|h{|v~`u~M{}w~}P{|u~|q{}v~}_{}g~}|b{}w~}hv~|Z{|v~Y{}u~k{}u~a{|y" + "~A{}w~A{}~|Zl~|Z{}~|k{}~}[{|l~} yv~}Uv~}uy~}S{|v~S{}v~|x{|y}x~}|wu~X{|w~}Lw~|I{|v~}*{}x~|g{|x~}&{}y~}t{|x~ T{}x" + "~|g{|x~} <{|v~|o{}v~|Ux~}w{|x~} Ex~|t{|y~}Tw~|p{}j~}j{}x~|k{}x~}aw~|p{}j~}g{}v~}Wv~|h{|v~fv~|h{|v~fv~|h{|v~f" + "v~|h{|v~fv~|h{|v~g{|v~g{|v~|ov~|m{|v~V{|u~|i{|~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~k{}t~d{}w~" + "|n{}q~f{}u~k{}u~e{}u~k{}u~e{}u~k{}u~e{}u~k{}u~e{}u~k{}u~c{}v~|n{|u~|e{}u~|l{}u~c{}v~l{}v~|c{}v~l{}v~|c{}v~l{}v~" + "|c{}v~l{}v~|Y{|v~|V{}w~}Mw~}kv~c{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|k{}w~|o{" + "}s~U{|v~|P{|v~|N{|v~|N{|v~|N{|v~|Dv~Lv~Lv~Lv~Uv~}p{}v~^w~}m{|w~}a{}v~nv~}`{}v~nv~}`{}v~nv~}`{}v~nv~}`{}v~nv~}W{" + "}u~W{}t~|qv~}_v~|p{|u~|`v~|p{|u~|`v~|p{|u~|`v~|p{|u~|Yq~Xu~}o{}v~Yq~ M{}w~}|w{}x~}v{}v~b{}w~}|m{}v~b{}w~}|m{}v~" + "b{}w~}|m{}v~b{}w~}|m{}v~W{}x~}Nq~| M{|v~F{|u~ py~|V{|}y~y}|vy~|w{|y}y~y}Y{|s~}Q{|s~|Yw~}kw~}_{}v~|s{}v~|^{|w~}p" + "{|v~X{|r~}Z{}u~} q{}v~}o{|y~}$v~}\"w~|tw~|Y{}y~}|u{|y~|x{|u~^{}x~|q{|w~s{}x~}mu~}n{|s~}&{|w~|J{|w~| u{}w~L{" + "}v~ u{|v~|P{}x~}Q{}v~|r{}v~T{}w~}W{}v~}O{}|k{}v~}P{}w~}]{}|l{}u~]{|v~|q{}v~|Yv~}U{|v~}o{}v~}Q{|v~}T{}v~M{}v~C{|" + "}t~}6{|t~}|D{}w~}^{}x~|s{|m~y}q~|k{|v~fv~|e{}w~}n{|u~}`{}u~|l{|}y~}g{}w~}n{|}t~}`{}w~}L{}w~}P{}u~}jv~|h{}w~}hv~" + "|Y{}w~}M{}w~}W{}w~}nt~^{}w~}V{}w~|bv~|h{}w~|mq~e{}u~|n{}u~|a{}w~}P{}u~|n{}u~|c{}w~}k{|v~|d{|y~}k{|u~|Y{|v~|X{|u" + "~n{|u~Z{}r~}]{}s~}n{|r~e{}v~lv~}X{|v~|Z{|u~E{|w~}E{}w~M{|w~| u{|v~p{|t~|_s~|s{|u~]u~|P{}v~}s{|s~|`u~|k{|Ww~}T{" + "}v~}s{|s~|`w~}m{|w~}Wv~Lv~Tw~}r{}v~}Tv~_w~}mv~mv~hw~}m{|w~}`v~}p{}v~|_t~|q{|v~|`v~}q{|t~|Zw~}Q{|kv~|Y{}w~}S{}v~" + "pt~|Z{}w~y}w~}[{}s~|rs~}_v~}s{}w~}V{}s~}W{}v~|Ew~}Lw~|M{|w~| r{|v~|s{}s~}^u~}ov~|_w~|s{}w~|[v~}pu~]v~|Nw~}m{|w" + "~}Y{|s~}Xv~m{}w~|a{|u~p{|u~|fv~}t{}x~}x~}t{}v~ev~}w{}w~w{|v~}`{|w~}q{|w~}_{}v~|w{}w~v{}v~`t~|q{|v~|`v~}p{}v~U{}" + "w~|Uv~|r{|v~b{|v~fv~|bu~|M{}w~}O{|u~}t{|u~}\\{|k~}|`{}w~}hv~|Z{|v~X{}u~|n{}u~|`{|@{}w~@{|Xn~|X{|i{|Y{|n~} xv~}U" + "{|v~}vy~}S{|v~T{|v~|jv~}Y{|w~}Lw~|H{|v~|*{}x~}i{}x~}${}~}s{|y~ S{}x~}i{}x~} ;{|u~p{|u~|Ux~}w{|x~} Ey~|s{|~}T" + "{}x~}o{}j~}k{|w~k{}x~}a{}x~}o{}j~}h{}v~}W{|v~fv~|h{|v~fv~|h{|v~fv~|h{|v~fv~|h{|v~fv~|h{}w~}f{}w~}p{|v~l{|v~U{}u" + "~|l{|}y~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~n{|}s~c{}w~|mq~e{}u~|n{}u~|d{}u~|n{}u~|d{}u~|n{}u" + "~|d{}u~|n{}u~|d{}u~|n{}u~|d{}v~|l{|u~|et~|n{}u~|c{|u~n{|u~b{|u~n{|u~b{|u~n{|u~b{|u~n{|u~X{|v~|V{}w~}Mw~}x{|p{}v" + "~c{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|k{|v~p{|q~j{|gu~|Pu~|k{|_u~|k{|_u~|k{|_u~|k{" + "|Vv~Lv~Lv~Lv~U{|v~}r{}v~}^w~}m{|w~}`v~}p{}v~|_v~}p{}v~|_v~}p{}v~|_v~}p{}v~|_v~}p{}v~|W{}u~Vu~|q{}v~|_{}v~pt~|`{" + "}v~pt~|`{}v~pt~|`{}v~pt~|Y{}s~}Xt~|q{|v~|Y{}s~} Lu~}p{}u~|au~}p{}u~|au~}p{}u~|au~}p{}u~|au~}p{}u~|W{}x~}N{}s~} " + "M{|v~|Ev~} py~|Jy~|M{}t~O{|u~}Xw~}kw~}_{|t~}w|}u~}]{}w~}ov~|Xr~|Y{}t~}y| tt~|r{}x~}$v~}\"w~t{|w~X{}v~}y|y{|" + "y~y|}t~|_{|x~}ow~}tw~|m{|t~|r{|}q~}&w~}J{}w~ t{}w~L{}v~ u{|v~|Pw~|Pu~|t{}v~|\\s|}w~}r|a{}v~}Nx~}|p{}t~O{}w~}]{}" + "y~}|q{}t~|\\{}v~|s{}u~Y{|v~|T{}u~|r{}u~|_{~}|r{|}u~|T{}v~M{}v~@{|}w~}6{|w~}|A{}w~}^{|w~r{|o~}{}s~}iv~}f{}w~}e{}" + "w~}q|y}s~|_{}t~|p{|}w~}g{}w~}r|y}q~}_{}w~}g|`{}w~}O{}t~}o{|}u~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}mt~_{}w~}h|i{}w~|bv~" + "|h{}w~|m{}r~dt~}|r{|t~|`{}w~}Ot~}q{|t~}b{}w~}jv~}d{|w~}|p{|}u~}X{|v~|W{}u~|q{}u~|Z{|r~|]{|s~|mr~f{|v~|l{|v~|Y{|" + "v~|[{|u~}b|^{|w~}E{|w~|N{|w~| tv~}r{}s~|_w~y}x~}|w{|}u~|]{|u~|p{|}|^t~y|x{|}w~}w~|`{|u~|n{|y~|Xw~}St~y|x{|}w~}" + "w~|`w~}m{|w~}Wv~Lv~Tw~}q{}v~}Uv~_w~}mv~mv~hw~}m{|w~}`{}v~}r{}v~}^s~}s{|v~}_{}v~}s{|s~|Zw~}Qy~}|o{}w~}X{|v~}|U{|" + "v~}s{|s~|Z{|q~Z{|s~qs~|`{}w~}qv~}Vs~|X{}v~|Dw~}Lw~|M{|w~| qu~|u{}w~|v~}_s~|s{|u~^{}w~t{}w~}Z{|v~}|t{|}v~|]{}v~" + "|ny|^w~}m{|w~}Xs~|Y{}w~}m{|w~}a{|t~|s{}t~}f{}v~}v{|w~{w~|v{}v~}e{}v~}x{}w~x{}u~_{|w~}q{|w~}^u~}|y{}w~x{}u~}`s~}" + "s{|v~}_{|v~}|t{|}v~|U{|v~}|W{|v~|t{|v~|bu~f|v~}c{}v~}h|_{}w~}Vs}t~}v{}t~s}`{|y}t~y}|]{}w~}hv~|Z{|v~Wt~}|r{|t~|#" + "{}w~ vp~| {|p~} wv~}T{}v~}wy~}v{}~Z{|v~S{}x~|hx~}X{|w~}Lw~|G{}w~}){|w~|m{|w~|\"{|}q{} R{|w~|m{|w~| XY| ${|u~}r{" + "|t~}Ux~}w{|x~} E{}qy|T{|w~c{}x~gw~|lw~}a{|w~c{}x~e{}v~}Vv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~|f" + "{|v~pv~}l{|v~}h|h{}t~|p{|}w~}c{}w~}g|a{}w~}g|a{}w~}g|a{}w~}g|X{}w~}M{}w~}M{}w~}M{}w~}Z{|v~r|x}q~b{}w~|m{}r~dt~}" + "|r{|t~|bt~}|r{|t~|bt~}|r{|t~|bt~}|r{|t~|bt~}|r{|t~|d{|v~|j{|v~}f{}s~}|r{|t~|a{}u~|q{}u~|a{}u~|q{}u~|a{}u~|q{}u~" + "|a{}u~|q{}u~|X{|v~|V{}w~}Mw~}xy~}y|wy|u~|bv~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|jv~}r{}w~}" + "|u~|o{|}y~g{|u~|p{|}|_{|u~|n{|y~|`{|u~|n{|y~|`{|u~|n{|y~|`{|u~|n{|y~|Wv~Lv~Lv~Lv~T{}u~}|x{|}u~}]w~}m{|w~}`{}v~}" + "r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}V{}u~V{|v~}r{}v~}^{|v~}s{|s~|`{|v~}s{|s~|`{|v~}s{|s~|`{|v" + "~}s{|s~|Xs~|Xs~}s{|v~}Ws~| K{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~U{}x~}N{|s~| M" + "{|w~|D{}w~| q{|y~}K{|y~}L{}v~|N{}v~Ww~}kw~}^{|j~}\\v~|o{}w~}X{}s~W{|^~} -s~}v|}v~}$v~}#{|w~t{|x~}X{}e~|^w~|o" + "{|w~|v{}w~k{|s~}v|}t~y}v~}'{}w~Jw~} t{}w~L{}v~ u{|v~|Q{|w~O{|u~}w|}u~}\\{|e~|ab~`u~w}|x}r~|O{}w~}]{}v~w}|x}s~}Z" + "t~}w|}t~X{}w~}S{|t~y}v|}t~}^v~y}y|y}s~|S{}v~M{}v~={|}~}6{|y~}|?{}w~}]w~}q{}r~|y{}u~}h{|v~|f{|v~e{}c~|]{}s~y}v|y" + "}t~}g{}b~|^{}c~}`{}w~}N{}r~y}v|y}r~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}lt~`{}d~}i{}w~|bv~|h{}w~|lr~cr~}v|}s~}_{}w~}Ns~" + "y}v|}s~}a{}w~}j{|v~|e{|s~}u|}r~W{|v~|Vs~}v|y}t~|Xs~}\\{|s~|m{}t~}fv~}j{}v~Y{|v~|[{}\\~}^{|w~}Dw~}N{|w~| t{}u~y" + "|x{|}w~y}w~|_w~}{k~|[{|t~}|wy|}x~|^{|k~y|w~|_{|t~}|vy|y}w~|Xw~}S{|k~y|w~|`w~}m{|w~}Wv~Lv~Tw~}p{}v~}Vv~_w~}mv~mv" + "~hw~}m{|w~}_{}u~}|x{|}u~}]w~y}w~y|yy|}u~|^{}u~}|x{|}w~}w~|Zw~}Qv~}y|v{|}u~|Wm~[{}u~}w|}v~}w~|Y{}s~}Yt~}q{}t~|a{" + "}v~p{|v~|W{}t~W{}d~Uw~}Lw~|M{|w~| q{|u~}|y{|}v~{|s~br~}y|yy|}u~|^{|w~}v{}v~X{}u~}y|{y|}u~}\\{|t~}|vy|y}y~}^w~}" + "m{|w~}X{}t~Xv~|lv~|b{|s~}v|}q~x}hu~}|{y|w~}{}w~}|{|}u~c{}u~}|}w~|}t~|_{|w~}q{|v~}_{|s~}v~}s~}_w~y}w~y|yy|}u~|^{" + "}u~}y|{y|}u~}S{}r~}Z{}v~}|x{|}v~}b{|Z~c{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~Vr~}v|}s~|\"{}w~ ur~| y{|r~} vv~" + "}St~}y|y~}{y|}x~`{}b~}a{}~|f{~}W{|w~}Lw~|G{|w~}({|v~}|s{|}v~| E{|v~}|s{|}v~| X{|Z~} ${|s~}y|{y|}q~}|}Xx~}w{|x~" + "} l{}x~|c{}x~h{}x~}m{|w~|`{}x~|c{}x~f{|v~}V{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~dv~|r{|" + "v~k{|b~g{}s~y}v|y}t~}c{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|b~}a{}w~|lr~cr~}v|}s~}`r~}v|}s~}`r~}v|}" + "s~}`r~}v|}s~}`r~}v|}s~}b{|x~|h{|x~}f{}o~}v|}s~}_s~}v|y}t~|_s~}v|y}t~|_s~}v|y}t~|_s~}v|y}t~|W{|v~|V{}w~}Mw~}xk~}" + "a{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|j{}" + "u~y|x{|}u~y{|t~}|vy|}v~f{|t~}|wy|}x~|^{|t~}|vy|y}w~|_{|t~}|vy|y}w~|_{|t~}|vy|y}w~|_{|t~}|vy|y}w~|Wv~Lv~Lv~Lv~S{" + "}j~}\\w~}m{|w~}_{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}U{}u~V{}t~}|x{|}u~}\\{" + "}u~}w|}v~}w~|_{}u~}w|}v~}w~|_{}u~}w|}v~}w~|_{}u~}w|}v~}w~|X{}t~Ww~y}w~y|yy|}u~|W{}t~ I{}h~}\\{}h~}\\{}h~}\\{}h~" + "}\\{}h~}T{}x~}Ms~ K{|y~}C{|w~ p{}x~K{}x~Kw~|L{}x~|Ww~}kw~}]{|l~}\\{|v~n{|w~}X{|s~U{}`~} -{|h~|$v~}#{}x~}t{}x" + "~}X{|}g~|^{}x~}m{}w~}y|}v~|j{|g~}y{}v~}({|w~|L{|w~| t{}w~L{}v~ u{|v~|Q{}x~}N{}k~}[{|e~|ab~`e~|N{}w~}]{}g~}Y{|i~" + "|Xv~|R{|g~}]i~|R{}v~M{}v~;y|5{|<{}w~}]{|w~|p{|v}|w{|x}|e{}v~dv~}f{}e~}|[{}d~|g{}d~}\\{}c~}`{}w~}M{}c~}|g{}w~}hv" + "~|Y{}w~}M{}w~}W{}w~}kt~a{}d~}i{}w~|bv~|h{}w~|l{|s~b{}f~|^{}w~}M{}f~|`{}w~}iv~}e{|c~V{|v~|Uf~}W{}t~|[s~l{}t~|g{}" + "v~hv~}Z{|v~|[{}\\~}^{|w~}D{}w~N{|w~| sj~{}w~|_w~}{|m~|Y{}i~|]{|m~|{|w~|^{|f~|Xw~}R{|m~|{}w~|`w~}m{|w~}Wv~Lv~Tw" + "~}o{}v~}Wv~_w~}mv~mv~hw~}m{|w~}^h~\\w~}{k~|\\k~y|w~|Zw~}Qg~}V{|n~Zk~{}w~|Y{|s~|Y{}u~}q{|t~a{|v~|o{}v~W{|u~|W{}d" + "~Uw~}Lw~|M{|w~| p{|l~|ys~be~}\\{}v~x}u~V{}j~}Z{|h~}^w~}m{|w~}X{|u~|Y{|w~}k{}w~}b{|w~}m~|s~h{|m~xm~|b{}g~|^{|w~" + "}pr~a{|f~}^w~}{k~|\\{}j~}R{|r~}Y{}l~}a{}Z~}d{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~U{}f~|!{}w~ tt~| w{|t~} uv~" + "}R{}i~`{}b~}`{|?{|w~}Lw~|Fw~}&{}t~w}t~} A{}t~w}t~} V{|Z~} ${|w~}m~|s~Xx~}w{|x~} m{|x~}b{}x~hw~lk~k{|x~}b{}x~" + "fv~}U{}v~dv~}j{}v~dv~}j{}v~dv~}j{}v~dv~}j{}v~dv~}j{}w~}d{}w~}r{}w~}k{|b~f{}d~|c{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}" + "w~}M{}w~}M{}w~}Z{|d~}|`{}w~|l{|s~b{}f~|^{}f~|^{}f~|^{}f~|^{}f~|`{|~|f{|~}f{|w~|}f~|]f~}]f~}]f~}]f~}V{|v~|V{}w~}" + "Mw~}xl~}_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|ii~w{|f~e{}i~|]{|f~|^{|f~|^{|f~|^{|f~|Wv~Lv~Lv~Lv~R{}l~" + "}[w~}m{|w~}^h~Zh~Zh~Zh~Zh~){|f~Zk~{}w~|^k~{}w~|^k~{}w~|^k~{}w~|X{|u~|Ww~}{k~|V{|u~| H{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|" + "j~|S{}x~}M{}u~} I{}Ax~} pw~|Lw~|L{|y~|Jy~|Vw~}kw~}[{}o~|[{}w~}mv~Wt~}T{|}b~} +{}l~}\"v~}#w~|tw~|U{|}l~}]{|w~" + "ko~|h{|j~}|w{}u~({}w~L{}w~ s{}w~Lv~| u{|v~|Qw~}M{|m~}Z{|e~|ab~`g~}|M{}w~}]{}h~|W{|k~W{}v~P{|i~|\\k~}P{}v~Mv~| " + "i{}w~}\\{}w~Jv~}d{}v~f{}g~}|X{|}h~}e{}g~}|Z{}c~}`{}w~}L{|}g~}|e{}w~}hv~|Y{}w~}M{}w~}W{}w~}jt~b{}d~}i{}w~|bv~|h{" + "}w~|ks~a{|i~}\\{}w~}L{|i~}^{}w~}i{|v~|e{}f~}U{|v~|T{}i~|Ut~Z{}u~}l{|t~g{|v~|h{|v~|[{|v~|[{}\\~}^{|w~}D{|w~N{|w~" + "| s{|l~|{}w~|_w~}x{}q~}|W{|j~|[{}p~|y{|w~|]{|g~|Xw~}P{}q~}|y{}w~|`w~}m{|w~}Wv~Lv~Tw~}n{|v~}Xv~_w~}mv~mv~hw~}m{" + "|w~}]{}l~}[w~}{|m~|Zm~|{|w~|Zw~}Qh~|T{|o~Z{|m~|{}w~|Xs~X{}u~|pu~}av~}m{}w~}Wu~V{}d~Uw~}Lw~|M{|w~| o{|n~|w{}u~b" + "f~}Z{}p~}T{}l~}X{|i~}^w~}m{|w~}Wu~Xv~|k{|v~b{|w~y|o~|{}t~g{|o~|x{|o~}`{}i~|]{|w~}p{}s~_{}j~}|]w~}{|m~|Z{}l~}P{|" + "s~}X{}n~}`X~d{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~T{|i~} {{}w~ sv~| u{|v~} tv~}Q{}j~`{}b~}#{|w~}Lw~|G{|w~}${" + "}m~} ={}m~} T{|Z~} ${|w~y|o~|{}t~Xx~}w{|x~} mw~|b{}x~i{}x~|lk~kw~|b{}x~g{|v~Tv~}d{}v~jv~}d{}v~jv~}d{}v~jv~}d" + "{}v~jv~}d{}v~k{|v~|d{|v~rv~|k{|b~e{|}h~}a{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|g~}|]{}w~|ks~a{|i~}[" + "{|i~}[{|i~}[{|i~}[{|i~}/{|w~|y{|i~}Z{}i~|[{}i~|[{}i~|[{}i~|U{|v~|V{}w~}Mw~}xm~|^{|l~|{}w~|_{|l~|{}w~|_{|l~|{}w~" + "|_{|l~|{}w~|_{|l~|{}w~|_{|l~|{}w~|i{|l~}u{|g~d{|j~|\\{|g~|]{|g~|]{|g~|]{|g~|Wv~Lv~Lv~Lv~Q{|}p~}|Zw~}m{|w~}]{}l~" + "}X{}l~}X{}l~}X{}l~}X{}l~}){|w~}l~}Y{|m~|{}w~|^{|m~|{}w~|^{|m~|{}w~|^{|m~|{}w~|Wu~Vw~}{|m~|Tu~ E{|}p~}|V{|}p~}|V" + "{|}p~}|V{|}p~}|V{|}p~}|Qw~}Lu~| i{}y~| q{|w~}M{|w~}K{|}I{|}Uw~}kw~}Y{|y}w~y}|Yv~|m{}w~|X{}u~|Q{|}e~} *{|}p~" + "}|!v~}#w~t{|w~Py|x}y~x}y|[w~|j{}r~|e{|n~}|t{}u~){|w~|N{|w~| s{}w~Lv~ t{|v~|R{|w~|L{|}p~|Y{|e~|ab~`y|}l~}|K{}w~}" + "]{|}k~|S{}o~|Vv~}N{|m~}Z{}n~}|O{}v~Mv~ h{}w~}[v~L{|v~|d{|v~|g{}k~y}y|T{|}m~}|c{}m~x}y|W{}c~}`{}w~}J{|}k~}|c{}w" + "~}hv~|Y{}w~}M{}w~}W{}w~}it~c{}d~}i{}w~|bv~|h{}w~|k{|t~_{|m~}|[{}w~}J{|l~|]{}w~}h{}w~}c{|}k~}|T{|v~R{|}m~|S{}v~}" + "Z{|u~|kt~gv~}f{}v~[{|v~|[{}\\~}^{|w~}Cw~|O{|w~| q{}p~}x{}w~|_v}vy}w~y}|S{}m~}Xy}w~y}|w{|w}|[{|l~}|Vw~}N{|}w~y}" + "|w{}w~|`v}lw}|Wv~Lv~Tv}m{|u}Yv}_w~}mv~mv~hw~}m{|w~}\\{|n~|Zw~}x{}q~}W{}q~}|y{|w~|Zw~}Q{|}l~}P{|y}s~X{}q~}x{}w~|" + "X{}u~}X{|u~o{}v~|b{}w~}kv~}X{}w~}V{}d~Uv~Lw~|M{|w~| n{|}q~}u{|}w~bv~{}o~}|X{|r~|R{|}p~}|U{}l~}|^w~}m{|w~}W{}w~" + "}Xw}|i{|w}b{|w~|{|q~|y{|t~f{|q~|v{|q~|^{|l~}[{|w~}os~]{|}o~}|[w~}x{}q~}W{|}p~}|M{|}v~}W{|p~|`{|X~|e{}c~}_{}w~}V" + "k~v{}l~|^{|v~Y{}w~}hv~|Z{|v~R{|m~}| y{}w~ rx~| s{|x~} sv~}P{|}n~}|`{}b~}#{|w~}Lw~|Ty|pv~|\"y|}u~}y| 9y|}u~}y| " + "R{|Z~} ${|w~|{|q~|y{|t~Xx~}w{|x~} y}| q{}x~}aw}j{|w~kk~l{}x~}aw}gv~}U{|v~|d{|v~|l{|v~|d{|v~|l{|v~|d{|v~|l{|v~|" + "d{|v~|l{|v~|d{|v~|l{|v}bv}|t{}w~}j{|b~c{|}m~}|_{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|m~x}y|Z{}w~|k{" + "|t~_{|m~}|X{|m~}|X{|m~}|X{|m~}|X{|m~}|.w~}v{|}n~}|X{|}m~|X{|}m~|X{|}m~|X{|}m~|S{|v~|V{}w~}Mv|wy|}u~y}|Z{}p~}x{}" + "w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|g{}o~|r{|l~}|a{}m~}Y{|l~}|Y{|l~}|Y{|l~}|Y{|l~}|U" + "v~Lv~Lv~Lv~O{|y}v~y}|Xw~}m{|w~}\\{|n~|V{|n~|V{|n~|V{|n~|V{|n~|(w~|{|n~|V{}q~}x{}w~|\\{}q~}x{}w~|\\{}q~}x{}w~|\\" + "{}q~}x{}w~|W{}w~}Vw~}x{}q~}R{}w~} B{|t}|P{|t}|P{|t}|P{|t}|P{|t}|Nw~} 3{|~} ;f| '{|y}w~}y| 8{|y~|X{|x~}" + "h{|}w~}|ay|y}w~y}| rw~}N{}w~ ?{|w~| D{}w~I{|y}w~y}|%b|\\{|x}u~y}|!y|y}u~y}y|O{|y}w~y}| {{y|}u~y}|Vy|y}v~}y| u{|" + "w~| B{|v~| 1{|y}u~y}| o{|x}u~y}y| Fv~| 7y|y}v~y}| {{y|y}q~|#y|y}u~y}y| {{|y}v~y}y| a{|w~}C{}x~}O{|w~| oy}" + "v~}|vv|!{|}t~y}|!{|y}t~y}|Sv|Av~\"v|Lv~ Rv|mv|mv|hv|lv|Z{|y}u~}|Xw~}v{|}w~y}|T{|}w~y}|w{|w~|Zv|Ny|y}u~y}| {{|y}" + "w~}|uw|W{|u}|Wv}|o{|v}av|ju|Xv~| sv~Lw~|M{}w~| ly|}v~}|Uv~yy|}v~y}|S{|y}~y}|N{|y}v~y}|Qy|y}v~x}|[v|m{|w~}W{|w~" + "|#{|w~|x{|}w~}|v{|}y~y}c{|y}x~y}ry}x~y}|Z{|y}s~}y|G{}w~}|Zy|v~}|Ww~}v{|}w~y}|T{|y}v~y}| x{|y}w~}| Ry|y}v~y}|" + " Zy| rv~}M{|y}u~}|]`| Iw~|T{|y~}|u{|u~ 5{|w~|x{|}w~}|v{|}x~}Wx~}w{|x~} {}y~} r{|y}|Kw~|L{|y}|Hv~| E" + "{|y}u~y}| qy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|+{|y~}r{|y}v~y}|R{|y}v~y}y|S{|y}v~y}y|S{|y}v~y" + "}y|S{|y}v~y}y| oy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|d{|}v~y}|n{|y}u~y}y|\\{|}t~y}|U{|y}" + "t~y}|T{|y}t~y}|T{|y}t~y}|T{|y}t~y}|Rv|Lv|Lv|Lv|!v|lv|Z{|y}u~}|R{|y}u~}|R{|y}u~}|R{|y}u~}|R{|y}u~}|'{}x~|w{|y}u~" + "}|S{|y}w~}|uw|Z{|y}w~}|uw|Z{|y}w~}|uw|Z{|y}w~}|uw|Vv~|Vw~}v{|}w~y}|Qv~| Mw~| K{|y~| e{|w~Nw~" + "| ?{}w~ Cw~} .{}w~ @{|v~|d{}| Kv~| !u~| J{|w~}C{|w~O{|w~| 9w~} Iv~ bw~}9{|w~| X{|v~ rv" + "~Lw~|M{}w~| w~| D{|w~| .w~| ?{|v~}g{|x~| M{|v~ {|u~| K{|w~}Bw~|P{|w~| :{}w~} Iw~} bw~}9{" + "|w~| X{}w~| r{}w~|Mw~|Mv~ ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~|T{|l~| 4{|w~" + "|Ax~}w{|x~} {{}y~} /v~| ?x~| f{|x~ M{} %{}w~|Uw~}D{}w~| Lw~| K" + "{|y~| d{|w~Pw~| ?{|w~ C{}w~ .{|w~ ={|u~}|l{|u~| N{}v~ {{|u~| L{|q~}H{}x~}V{}q~| :v~| Iw~}" + " bw~}9{|w~| Xv~ q{}w~}Mw~|N{|v~ ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~|T{|}o~}| " + " 3{|w~|Ax~}w{|x~} {{|x~| 0v~}m{} N{|x~ e{}y~} Rv~Tw~}Dv~ S{}x~x{|w~| " + " K{|y~| c{}x~}R{}x~} >{|x~| Cw~} .{|x~| ;{}t~}|sy|}t~| N{|v~} y{|u~| M{|q~}H{|w~V" + "{}q~| ;{}v~ I{|w~} bw~}9{|w~| Y{}w~} q{|v~}|Ow~|P{|}v~} ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} " + " )v~}Iy~} gw~|Q{|y}v~y}| 1{|w~|Ax~}w{|x~} yx~| 0{}v~|p{|~} N{|x~| f{|x~ " + " S{}w~}Tw~}E{}w~} S{}x~|y{|w~ J{|y~| bw~|Sw~| >{}y~} K{}y~} 9{|p~x}q~}| N{|u~" + "| x{|u~ M{|q~} y{}q~| K{|}|p{|u~| I{}w~| bw~}9{|w~| Z{|v~ o{}q~}Tw~|U{|p~ :v~ S{|w~}W{|w~|#{|" + "w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~| W{|w~|Aw|vx| y{|x~} 0{|u~|s{}x~} N{|x~| " + " f{|x~| U{|v~Sw~}F{|v~ R{|x~}y{}w~ J{|y~| b{|x}|T{|x}| w{}g~}| Q" + "x|y}u~} v{|u~ N{|p} yp}| K{|x~}y|wy|}u~} J{|}v~ aw~}9{|w~| \\{|}v~} nq~}Tw~|U{|q~| :v~ S{|w~}" + "W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~| W{|w~| :{|}w|}w~| /t~y}x|y}v~} U{|}|x{|w~| " + " f{}x~| W{|}v~}Sw~}H{|}v~} Qq~| J{|y} *{|}l~}| O{}q" + "~ tt| `{|i~} Lr~| aw~}9{|w~| `{}q~ l{}s~}Tw~|U{|s~}| 9v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~" + "} )v~}Iy~} gw~| W{|w~| :{|q~ .{|i~} U{|q~ ly}w|}w~| [{}q~Rw~}" + "L{}q~ P{}r~ M{|y}u~y}y| L{}r~| R{|j~} Ks~} `w~}9{|w~| " + " `{}r~| jy|v}|Tw~|U{|u}| 6v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy}| gw~| W{|w~| :{|r~| " + " -{|k~}| U{|r~} l{}r~} Z{}r~|Rw~}L{}r~| O{}t~ " + " k{}t~} -{|`}| `{|}m~}| Jt~} _w~}9{|w~| `{}s~| :w~| cv~ S{|w~}W{|w~|#{|w~| j{}w~ s{}" + "w~Uw~} )v~} d{|w~| 9y}w~y} ){}o~}| S{|}u~}| k{}r~ Y{}s~|Qw~" + "}L{}s~| M{}w~} j{}w~}| +{}`~} ]{|x}v~y}| Gw~y} ]w~}9{|w~" + "| `{}v~}| 8w~| cv~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} g{|w~| 8{|}v~y}| Ly| " + " g{|y}w~}| X{}v~}|Ow~}L{}v~}| Iy| " + "l{}`~} Ww~| " + " L{}`~} Ww}| " + " r{" }; + + // Define a 104x128 binary font (huge sans). + static const char *const data_font_huge[] = { + " " + " " + " " + " " + " " + " " + " " + " " + " FY AY " + "'Z ;W @Y @Y 'Z Y @Y (Z :Y ?Y (Z 0Y ?Y (Z >X " + " " + " " + " " + " " + " )X AX '\\ )XAV 7YDY -] BY BY '[ +YEY 2X AY (\\ -YDY 'XAU 3Y AY (\\ )XAV 8YD" + "Y LY AY (\\ ,YEY #Y " + " " + " " + " " + " (X CX '^ +[CU 6ZEY .` C" + "X CY '] -ZEZ 2X CY (^ .ZEZ )[CU 2Y CY (] *[CU 7ZEZ LY CY (] -ZEZ %Y " + " " + " " + " " + " " + " 'Y EY '^ ,^FV 6ZEY /b CX DX '_ .ZEZ 2Y DX '_ /ZEZ +_FV 1X CX (_ ,^FV 7ZEZ " + " KX CX (_ .ZEZ &Y " + " " + " " + " " + " %Y GY '` .aHV 6ZEY 1e DY FX" + " 'a /ZEZ 1Y FX '` /ZEZ +aHV 0X EX '` .aHV 7ZEZ JX EX (a /ZEZ &X " + " " + " " + " " + " " + " #X GX 'XNX 0dKW 6ZEY 1f DY HX &WMX 0ZEZ 0X GX 'XMW 0ZEZ ,dLX /X GX 'WMX 0dLX 7ZEZ" + " IX GX 'WMX 0ZEZ 'X :T " + " " + " " + " " + " ;X IX 'XLX 1o 5ZEY 2ZLY " + " CX IX &WKW 0ZEZ /X HX (XLX 1ZEZ ,o .Y HX (WKX 1o 6ZEZ IY IY (WKW 0ZEZ (X X MX &WH" + "W 3VHa 4ZEY 3WDW CX LX 'WGW 2ZEZ -X LX 'WHW 2ZEZ -VHa +X KX (XHW 3VHa 5ZEZ GX KX (WGW 2ZEZ )X " + " ?b " + " " + " " + " " + " ?W MW &WFW 4VF^ 3ZEY 4WBV BW MX 'WEW 3ZEZ ,W M" + "X 'WFW 3ZEZ -VF^ )X MX 'WFW 4VF^ 4ZEZ FX MX 'WFW 3ZEZ *X ?d " + " " + " " + " " + " " + " ?W X 'WDW 5UC[ 2ZEY 4VAV AW X &WDW 4ZEZ +W NW 'WDW 4ZEZ -UC[ 'W MW 'WDW 5UC[ 3ZEZ " + "EW MW 'WDW 4ZEZ +X ?f " + " " + " " + " " + " @X \"X 'WBW 6UAW 0ZEY 4V@V B" + "X !W &WBV 4ZEZ +X !W 'WBW 5ZEZ .VAW $W W 'WBW 6UAW 1ZEZ DW W 'WBV 4ZEZ +W >f " + " " + " " + " " + " " + " ?X #W 'W@W U?V AX #W &W@V NX #W &V@W 9W \"W 'W@V .W " + "\"W 'W@V !W >XHX " + " 3Y " + " " + " " + " 6W $W &V>V U?V @W $W &W>V " + " NW $X 'V>V 8W $X (W>V /X $W 'W>V #W >XFX " + " 5Z " + " " + " ,Z " + " GZ " + " #U?V NY 7Z ,X CVCW MY " + " 7Z ,X $Z 7Z ,X >Z 6Y ,X 4Z 7Y +W 7Y @Z " + " " + " +Z " + " " + " HY \"U?V " + " MY 8Y ,Y CVBV LY 9Z ,Y #Z 9Z ,Z >Z 8Y ,Y 3Y 8Z ,Y 9Y " + " ?Z " + " *Y " + " " + " IY !U?V " + " LY :Y ,[ $R>U ,V@V MZ :Y +Z #Y 9Y +Z ?R" + ">U 8Y 9Y +Z %S?U HY :Z ,[ ;Y ?[ " + " " + " )Y " + " 8U " + " 9Y V@U JY Y @Y /X 0Y K` .X " + " ^ =ZEY @Y " + " NVAV

Y E^ /X 0_ %f 1] 'c " + " @ZEZ AY MV" + "CW X *^ +]DU 7ZEZ 5U>U JY ?Y *^ -YEZ 4Y " + " ?Y *^ .ZEZ 5[ ]DU 5Y >Y +^ ,]DU 6ZEZ Y ?Y +_ .ZEZ \"Y Z G[ G\\ @e !f JX !Y " + "LY %d :Y Y Ha /X 0b *j L] D_ " + " +g A[ LY 8Z -ZEZ \"Y 1o )V FX NZ FY " + "%Y ,X NX*Z NW 3WEW H\\ #[ !Z \"[ \"[ \"[ G[7T 8g 0Y " + "@Y +_ ,_FV 7ZEZ 5U>U IY @Y +` .YEZ 3X ?X *` /ZEZ 4[:P 8_FV 4X ?Y +` ._EU 6ZEZ NX @Y *_ .ZEZ #Y ;Y" + " FYEZ ;] GU W ,X " + " FV a \"d -g >d (d +b %b 4f Bg Ie \"e \"h " + " Ge !f IX \"Y LY &e :Y Y Jc /X 0c " + " -n $g I` .j >a ;e HU .U +b Ac 2ZEZ 'b " + " 5o -] Na (c KY .Y #_ 8Y!W'Y\"X.c$X 3XGX Mf -e +d " + ",e ,e ,e \"e=V ;k 1Y BY +XNW .aGV 7ZEZ 5V@V HX AY +XNW .YEZ 3Y AY *WNW /ZEZ 4\\>T 9`GV 3" + "X AY +XNW .`GV 6ZEZ NY AX *XNW /ZEZ $Y :Y FYEZ <_ IU (Q LZ 4Z2Z 1Q " + " &g %Z +XCX MT Y Kd /X 0e 0p " + " (m Lb 1m ,\\ 5~S E~R Ah 'Z :~]+[;Z;Z Ik LW DX DW /i ?Y(Y 4h 5ZEZ" + " ,\\ ,h 7\\ -o .` $f -h NY No %_ %c @_\"X-_\"W0h&W .\\ $\\ \"\\ #\\ #\\ )g 5~a Lm D~S I~S " + "H~R H~R 6Z !Z !Z \"Z :r 8^,Y Bk 2k 2k 2k 2k (kAX+Z(Z#Z(Z$Z(Z$Y'Y&[%[ MZ Im 1X CY *WMX /bHV 7ZEZ 5V@V G" + "X CY *WLW /YEZ 2Y CY *WLW 0ZEZ 3[AW :bHV 3Y BX *WLW 0bHV 6ZEZ MY CX *XMX 0ZEZ $X 9Y FYEZ " + " =a M~i 7U (Q N_ 9_8_ 3R )k 'Z +XCX +X@X 4T >e,X Cl &X IX *X GV " + " GX 5i 0d 2p ;u !^ ?y 2o F~S @n 4j /l N\\ 8x .r Nx 7~R E} >t KZ(Z :Z \"Z 4Z-] KZ 2_'_(^-Z" + " Ep =t 5o Au 1u N~d'Z(Z)Z MZY " + " Le /X 0e 1r +r c 3o -\\ 5~S E~R Dn *Z :~]+[;Z;Z Ko " + " Y EX EY 2m @Y)Y 6l 7ZEZ 0e 2k >e 1o 0c 'j /i X !r (b 'g Eb\"W0c#X0i(W -" + "\\ $] #\\ $] #\\ (f 6~b r F~S I~S H~R H~R 6Z !Z !Z \"Z :w =^,Y Ep 6p 7p 7o 7p ,oDY+Z(Z#Z(Z$Z(Z$Y'Y%Z%Z LZ Kp" + " 1X DX *WKW /WMYJV 6ZEZ 5V@V GY EY *WKX 0YEZ 1Y EY *XKW 1ZEZ 2[EZ :WMZKV 1Y DX *WKX 1WLYKW 6ZEZ L" + "Y EY *WKW 0ZEZ %X 8Y FYEZ >c M~h 7T (S !a Y >X 8f /X 0f 3t -s c " + " 4q /^ 6~S E~R Fr ,Z :~]+[;Z;Z Ms #[ FX F[ 4n @Y*Y 6m 7ZEZ 3k 5l Bk 4o 1f )k 0k #" + "X #u (b (i Fb#X0c#W/k+X .^ %] $^ %] $^ (d 5~b\"v H~S I~S H~R H~R 6Z !Z !Z \"Z :{ A_-Y Gt :t ;t ;s ;t " + " 0sGY*Z(Z#Z(Z$Z(Z$Y'Y$Z'[ LZ Ls 2X FX *WIW 1WJc 6ZEZ 4VBV EY FX *XJW 0YEZ 0X EX )WJW 1ZEZ 1[I^ x %_ ?y 5r F~S Ct :p" + " 6s /e *^ 9| 6z#~ =~R E} B}!Z(Z :Z \"Z 4Z/\\ HZ 2`)`(_.Z Iw @y >w Ez 9z!~d'Z(Z)[ Z;Z0]/Z4Z,Z$[(Z%~^ " + "@e 2X Gf +a MX %Y LY *i :Y Y >Y 9f /X 0g 5v " + " 0u d 6_K_ 0^ 6~S E~R Gu .Z :~]+[;Z;Z w &] GX G] 6U &o ?Y+Y 7X )n 7ZEZ " + "6p 7m Eo 6o 2h *l 1l %X #v (b )k Gb$X/c$X/l,W -^ &_ %^ &_ %^ 'b 4~b$z J~S I~S H~R H~R 6Z !Z " + "!Z \"Z :~ D_-Y Hw =v >w >w >w 4wIX)Z(Z#Z(Z$Z(Z$Y'Y$[)[ KZ Mt 1X HX )WHW 2VHb 6ZEZ 4WDW DX GX )WHW 1YE" + "Z /X GX )WHW 2ZEZ 0[M` ;VHb /X GY *WHW 3VHb 5ZEZ JX GX )WHW 2ZEZ 'Y 7Y FYEZ ?e M~f " + " 7U )U %g Bh@g :W .~T 't +Z +XCX ,X@X 3T Ak1X Er (X JX 'X IV HX 8q" + " =m 7y ?y '` ?y 6s F~S Dv Y >Y " + " :] %X &] 5]C\\ 1v Nc 7\\D\\ 1_ 6~S E~R Iy 0Z :~]+[;Z;Z!y (_ H" + "X H_ 7U 'p ?Y,Y 6X *o 7ZEZ 8t 9YH] Ht 9o 3i *XG[ 1VE[ &Y %x (b *[I[ Hb$W.c%X.VE[-X " + " ._ &_ %_ '_ %_ '` 4~c%} L~S I~S H~R H~R 6Z !Z !Z \"Z :~Q F`.Y Jz @z Az Ay Az 7zKX(Z(Z#Z(Z$Z(Z$Y'Y#[*Z JZ Na" + "J_ 2X IX )WGW 2VG` 5ZEZ 4XFX CX IX )WFW 2YEZ .X IX )WFW 3ZEZ /j 8VG` -X HX *WFW 4VG` 4ZEZ IX IX " + ")WGW 2ZEZ 'X 6Y FYEZ ?XKX M~f 7T )W 'i DiAi ;X 1~V (w -Z " + "+XCX ,X@X 3T AZI[2W Es (X KX &X IV HX 9s >m 7z @z )a ?y 7t F~R Dx >t 9v 8s 2` :~P <~Q&~S" + " A~R E} E~T$Z(Z :Z \"Z 4Z2] FZ 2a+a(`/Z K| C{ C} H| =|!~d'Z(Z(Z!Z9Z1^1Z2[0[!Z+[$~^ @X $X ;Y -e MX 'Y " + "LY +[ +Y Y >Y :[ #X #Z 6\\?[ 2v F\\ " + " 8Z@[ 2` 7~S E~R J{ 1Z :~]+[;Z;Z#} +` HX Ia 8U (q >Y-Y 6X +p 7ZEZ 9bMb ;U@Y JbMb :" + "n 3ZIZ +T@Y 2R>Y 'X %y (XLV +ZEZ IXMW%X.YMW%W-R>Y.W -` '_ &` '_ &` '` 4~c'~R N~S I~S H~R H~R 6Z !Z " + "!Z \"Z :~S Ha/Y K| B| C| D} D| 9|MX'Z(Z#Z(Z$Z(Z$Y'Y\"Z+[ JZ N]B\\ 2X JX *WEW 3UE_ 5ZEZ 3YJY AX JW )WE" + "W 2YEZ -X KX (WFW 3ZEZ .f 5UE_ ,X JX )WFW 4VF_ 4ZEZ HX KX )WEW 3ZEZ (X 5Y FYEZ @YJW M~" + "e 7U *X (j EkCk =Y 3~X )x -Z +XCX ,W?X 3T BYEY3X Ft (X KX %X JV " + " IX 9u ?m 7{ A{ *a ?y 8u F~R Ez @v :v :w 4` :~Q >~S'~U C~R E} G~V$Z(Z :Z \"Z 4Z3] EZ 2a+a(a0Z M~P D" + "| E~P I} ?}!~d'Z(Z'Z\"Z9Z1^1Z1Z0Z [,Z#~^ @X $X ;Y .g MW 'Y LY +Y )Y Y " + " >Y :Z \"X \"Z 7[=Z 3aE[ E[ 9Z>[ 3` 7~S E~R L~ 2Z :~]+[;Z;Z$" + "~P -b IX Jc 9U )r >Y.Y 5X ,]DX 7ZEZ ;\\>\\ \\ 0XDX ,R=Y MX (X %hEW (SG" + "V ,YAY JSHW%W-SGW&X GX/W ,` (a '` (a '` (a 5~d(~S N~S I~S H~R H~R 6Z !Z !Z \"Z :~T Ia/Y L~P F~P F~P F~P F~P" + " <~X&Z(Z#Z(Z$Z(Z$Y'Y\"[-[ IZ \\>Z 1X LX )VCW 4UD] 4ZEZ 2f ?X LX )WDW 3YEZ ,W KX )WDW 4ZEZ -b 2UD] *W" + " KX )WDW 5UD] 3ZEZ GW LX (VCW 4ZEZ )X 4Y FYEZ @XIX M~d 7U *Y *l GmDl ?[ " + " 6~Z *`C\\ -Z +XCX ,W?W 2T CYCY5X E]CZ (X LX $X JV IX 9]E^ @m 7aGb B^Ec ,b ?y " + "9aF[ F~R E_C_ B_E^ ;]E_ ={ 7b ;~R @cBb'~V D~R E} HeBc$Z(Z :Z \"Z 4Z4] DZ 2b-b(a0Z NbCb E} GbCb J~ Aa" + "B_!~d'Z(Z'Z#[9Z2_1Z0Z2[ N[.Z\"~^ @X $X ;Y /i MW (Y LY ,Y (Y Y >Y " + " :Y !X !Y 8[;Z 1\\ 0\\:U D[ ;ZbCh%Z(Z" + "#Z(Z$Z(Z$Y'Y![.Z HZ Z;Z 1X NX )WBV 5VBZ $e >W MX )WBW !X MX )WBW #` /UBZ (W MX )WBW 6UBZ " + " 9X MW (WCW MX 3Y GXHW M~d 8U *[ +m HnFn A] 9~\\ +^=Y" + " -Z +XCX -X@X 2U DXAX5W E\\=V (X LX #X .R@V?Q ,X :\\A\\ @m 7\\>_ CY<_ -c ?y :^=V F~Q E]>^ D]@] " + " j E~R E| Ha8^$Z(Z :Z \"Z 4Z5] CZ 2b-b(b1Z `<_ FZ@d I`=` K[@d C_:Z ~b&Z(Z'Z#Z8Z2`" + "2Z0[4[ LZ/[\"~^ @X #X Y >Y ;Z " + "!X !Y 8Z9Y 6d 4[5R CZ ;Y:Z 5b 8~R D~Q MbAb 8` =~]+[;Z;Z&`=` 1f KX Lg " + " ;U *\\=T =Y0Y 4X ,Z;R 5Z3Y &W !Y3Y 3W@W EW LX *W %jEW KV -X=X @W'X W'X EX1W ,b " + "*b (b )b )b )b 7ZH~R)a:] N~R H~R G~R H~R 6Z !Z !Z \"Z :Z>j Lb0Y N_<` J`<_ J`=` J`=` J`=` @`=e%Z(Z#Z(Z$Z(Z$Y'Y" + " Z/[ HZ !Z9Y 0W X )WAW 6VAW \"d Y >Y ;Y X !Y " + " 8Y8Y 6f 6Z2P BY j BZ(Z+[;Z;Z'_9_ 3h LX Mi <" + "U *[:R V EW KW +W %kEW KV .X;W @W'W NW(X CW2X -c *c )b " + "*c )c +c 7ZHZ 2_5[ NZ !Z Z !Z >Z !Z !Z \"Z :Z7d Mc1Y ^8_ K^8^ L_8^ L_9_ L^8_ B_9b$Z(Z#Z(Z$Z(Z$Y'Y [1[ GZ !Z" + "8Y 0W !W (V?W I` :X !W (V?W X \"X (W@W *d EX !W (W@W 0X \"X (V?W !W 1Y #d ," + "e +d +d ,e #XHW LZ#Z 7U +] -o KqHp C_ X #X " + " Y >Y ;Y X X 9Z7X 6g 7Y" + " #Z =Y8Z 7d 7[ Z )_7_ Bp EZ(Z+[;Z;Z(^5^ 5j MX Nk =U +[7P Z !Z !Z \"Z :Z3a Nc1Y!^5] L]4] N^5^ N^5^ N^5] C^5_#Z(Z#Z(Z$Z(Z$Y'Y N[2Z FZ \"Z7Y /W #W (W>V H^" + " 8X #W (W>V NW \"W (W>W .h EW \"X )W>W 0W #X (V=V \"W 0Y &j 1i 0j 1j 1i &X ` .\\5U -Z +XCX -W?W =r'X>W8X EZ ;X NY !X 1XDVDX 2X " + " &X ;[;[ BWDZ 7T2\\ \"\\ 1XMZ ?Y L\\ 2Z E[7[ G\\9[ >S5[ F`7` ?YNY Y >Y ;Y X Y :Y6Y 7i 9Y \"Y " + " >Y6Y 7YNY 6[ !Z *^3] Dt GZ(Z+[;Z;Z)]2] 6l NX m >U +Z !Y4Z 3X -Y NW(W (W " + " &X)X 8VZ !Z !Z \"Z :Z1` d2Y\"]2] N]2] ]2]!^2]!]2] E]2]\"Z(Z#Z(Z$Z(Z$Y'Y MZ3[ FZ \"Z6X .V $W 'VR4[ G^1^ AZNY Y >Y ;Y X Y :Y6Y 7j :Y \"Y " + " >Y6Z 9YMY 5[ \"Z *]1] Hy IZ(Z+[;Z;Z)\\/\\ 8n X !o ?U ,[ Y5Y 2X -Y W&W )W 'W%W 9V" + "Z " + "!Z !Z \"Z :Z/_!d2Y#]0]!]0]\"]0\\!\\/\\\"]0] F\\0]#Z(Z#Z(Z$Z(Z$Y'Y M[5[ EZ \"Y5X +P " + " %_K[ CY *r 9q 8r 9r 9q *X ;Z%Z >Q JT ,b 0q MsKs Ge " + "C^ *[0R -Z +XCX .X@X @v)X=X:W CY :X Y NX 1[HVH[ 1X 'X ;Z7Z 0Z 7P,[ ![ 3XLZ ?Y M[" + " 1Z EZ4[ I[5Z ?P1Z I^-] BYLY =Z1[ H\\(T'Z-^ JZ MZ *\\$S$Z(Z :Z \"Z 4Z:] >Z 2YMX1XMY(YNZ4Z$].\\ JZ5" + "\\!\\-\\ Z4[ GZ ;Y 9Z(Z%Z'Z4Z5XNX5Z*Z:[ F[6Z [ ;X \"X =Y 5\\C[ #Y LY -Y 'Y 8X >Y " + " >Y ;Y X Y :Y6Y 7k ;Y \"Z @Z5Y 9YLY 5[ #Z +\\.] J| KZ" + "(Z+[;Z;Z*\\-\\ :p !X \"q @U ,Z NY6Y 1X -X W#V *W (W#W :U;V +X DW LW )mEW KV" + " /X9X BW*X LW*X BW3W +YLY -YMY ,YLY -YMY ,YLY -YMZ ;ZFZ 5\\'S NZ !Z Z !Z >Z !Z !Z \"Z :Z-^\"e3Y#\\.]#].\\" + "#\\-\\#\\-\\#\\-\\ H\\.]$Z(Z#Z(Z$Z(Z$Y'Y L[6Z DZ \"Y5Y /[G[ " + " DY +u =u S LU ,c 1q MtLt Hf E] )[.Q " + " -Z +XCX .W?X Bx)X=X;X DZ :X X MY 0ZIVIZ /X 'X ;Z7[ 1Z AZ ![ 4XKZ ?Y MZ 0Z EZ3Z I[5Z " + "Z J])\\ CYLY =Z1[ I\\%R'Z+] KZ MZ +\\\"R$Z(Z :Z \"Z 4Z;] =Z 2YMX1XMY(YNZ4Z$\\,\\ KZ4[\"\\+[ Z4\\ I[ ;Y 9Z(Z$Z" + "(Z4Z5WLW5Z*[<[ DZ7[ !\\ ;X \"X =Y 6\\A[ $Y LY -Y 'Y 8X >Y >Y " + " ;Y X Y :Y6Y 7l Z !Z !Z \"Z :Z,^#YNZ3Y$\\,\\#\\,\\$\\,\\%\\+\\%\\,\\ MP" + " NP N\\-]$Z(Z#Z(Z$Z(Z$Y'Y KZ7[ Dq :Z4X /XC[ EY " + " -x @x >x ?x @x -X :Z'Z ?U MU -e 2q MtLt Ig E[ 'Z,P -Z +XCX .W?W By)" + "XZ0Z" + " J\\#Q'Z*\\ KZ MZ +[ Q$Z(Z :Z \"Z 4Z<] Y 7[>[ %Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y" + "5Y 7UH_ Z !Z !Z \"Z :Z+]#YMZ4Y%\\*\\%\\*\\&\\*[%[)[%[*\\ R!R [-_%Z(Z#Z" + "(Z$Z(Z$Y'Y K[9[ Ct =Y3X /U@[ \"Q EY .z B{ " + "B{ Az B{ /X :Z'Y >V U -g 4r NvNu Ji *\\ 5X.X 6\\ 7Z1Z M[ '[ 8Z +XCX /X@X C`MTL_)W;" + "WZ0Z " + "J[ 'Z)\\ LZ MZ ,\\ \"Z(Z :Z \"Z 4Z=] ;Z 2YLX3XLY(YMZ5Z%[([ LZ3[$\\)\\\"Z3[ IZ :Y 9Z(Z$Z)Z3Z6XLX6Z(Z>[ B[:Z !" + "\\ 9X !X >Y 8[<[ &Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y5Y " + "7RB] =\\ $Z BY2Y ;YJY 3[ &Z -[(\\!~U Z(Z+[;Z;Z,\\)\\ ?\\MXL[ $X %\\LXM\\ CU" + " ,Y *Q\"R DY9Y 0X -Y #V=_?V Cm *V LV Z !Z !Z \"Z :Z*]$YMZ4Y%[([%[(['\\)\\'\\)\\'\\)[!T#T\"\\-`&Z(Z#Z(" + "Z$Z(Z$Y'Y J[:Z Bw @Y6[ .Q<[ #S GY /`Da E`C" + "` DaD` C`Da E`C` 0X 9Y(Z ?X !U .h 4r NvNu Kk .c 9X.X 7^ 7Y1Y M[ &Z 7Z +XCX /X@X C\\" + "ITFY)W;W=X BY 9X !X KY +YNVNZ *X (X ;Z4Z 2Z @Z !Z 6YJZ ?Y Z /Z DY2Z JZ1Y ,T T MZ N[ NZ HZJ" + "Y >Z0Z K[ &Z(\\ MZ MZ ,[ !Z(Z :Z \"Z 4Z>] :Z 2YLX3XLY(YLZ6Z&['\\ MZ3[$['[\"Z2Z IZ :Y 9Z(Z#Z*Z2Z7XLX7Z'[@[ @Z;" + "[ ![ 8X !X >Y 9[:[ 'Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y" + "5Y %\\ =] %Y BY2Z =ZJY 3\\ 'Z .\\'[#cLZLb!Z(Z+[;Z;Z,['[ @\\LXK[ %X &\\KXL\\ " + " DU -Z +S$T EY:Y /X -Z %V?fBU Eo +VEg=V =VZ !Z !Z \"Z :Z)\\$YLZ5Y&\\'['['\\(['['['['['[#V%V#[-a&Z(Z#Z(Z$" + "Z(Z$Y'Y IZ;Z Ay BY9^ G[ %U HY 0]<^ G^=^ F" + "^<] E]<^ G^=^ 1X 9Z)Z @Z \"U .i 5r NvNu Lm 2h ;X.X 7^ 7Y1Y N[ &[ 7Z +XCX /W?X D[GTC" + "V)W;W=W AZ :X \"Y KY *j (X (X ZY .Y3Y 3Z '\\ MZ )Z ;Z 2^ +Y ;Y " + "X Y 6Y /Y5Y $[ =` G^ !Z IZ M\\ #Y2Z =YIZ 3\\ (Z .[%[%aIZI`\"Z(Z+[;Z;Z-[%[ B\\KXJ[" + " &X '\\JXK\\ H\\ 1Z ,U&V EY;Y /X ,Z 'V@jDV Gp +UDj?V >VZ !Z !Z \"Z :Z(\\%YLZ5Y&[&['[&[)\\&[)[%[)" + "[&[$X'X%[-b&Z(Z#Z(Z$Z(Z$Y'Y I[=[ Az CY;` 5\\ $] $\\ \"\\ #\\ $] 8\\/[ 3\\ '\\ #\\ \"[ \"[ \"[ &Z &[ ![" + " #\\ #[ ![ G[@W IYBZ J]8] I\\7\\ H]8] I]8] I\\7\\ 2X 8Y*Z @Z \"U .k 5q N~o Mm 4l =X" + ".X 7^ 7Z3Z NZ %Z 6Z +XCX /W?W D[FT@S)W;W>X AZ :X \"Y JX (f &X )X ;Z3Z 2Z @Z !Z 7" + "XHZ ?Y !Z /Z CY1Y JZ1Z 2Y Y $Z Z HY JYHY ?Z/Y L[ %Z'\\ NZ MZ -[ Z(Z :Z \"Z 4Z@\\ 7Z 2YKX5XKY(YKZ7Z'[" + "$[ NZ2Z%[%[#Z2[ JZ :Y 9Z(Z#[,Z1Z8XJW7Z%ZB[ >[>Z !\\ 7X X ?Y ;[6[ (e 7YE` (e 3aEY 8c 2r 5`DX GYEa (X NX " + "0X1Z 8Y FXD`9` YD` -c 9XD` /aEX :XD] 6g 7t BX0Y LY)Y+X6Z6X)Z/Z NX)Y I} 2Y X Y 9_>W KY5Y #[ =c h >XD` " + "AT#X 5Y 6X0X LY'Y ?RCW ?~Y!X?X?X ;d 'r!~W KZ1Y =YHY 2\\ )Z /[$[%_GZG_#Z(Z+[;Z;Z-[%[ C\\JXI[ 'X (\\IXJ\\ " + " (Y d 5Z -W(X FYV=W +X HX )^ ,Y1Y HnEW KV 0X7W BW-W HW.X M^/X )" + "Y +YHY 2YHZ 1YHY 2ZHY 1YHY 2ZHY ?ZDZ 9[ LZ !Z Z !Z >Z !Z !Z \"Z :Z'[%YKZ6Y'\\%[)[$[*[%[)[%[)[%[%Y)Z&[.d'Z(Z#" + "Z(Z$Z(Z$Y'Y H[>Z @{ DY=b ;f -f -f ,e -f -f Ae7c ;e /b )c *c *c 'Y NX NX X E[ >XD` -c )c *b *c )c '\\ &bDX L" + "X0X GX0X GX0X GX0X KY)X KYE` ?Y*Y 8[4\\ K[3[ J\\4[ I[4\\ K[3[ 3X 8Z+Z AZ !U /m 6q N~o No 6o ?X.X 8_ " + "6Y3Z Z $Z 6Z +XCX 0X@X DZET>Q)W;W>W ?Y :X \"X IY 'b $X )X ;Z2Y 2Z @Z !Z 8YHZ ?Y " + "!Z 0[ CY1Y JZ1Z 5\\ \\ 'Z!Z FY LZHZ @Z/Y L[ %Z&[ NZ MZ .[ NZ(Z :Z \"Z 4ZA\\ 6Z 2YKX6YKY(YKZ7Z'[$[ NZ" + "2Z&[#Z#Z2[ JZ :Y 9Z(Z\"Z,Z1Z8XJX8Z%[D[ ZHY 1\\ *Z /[#['^EZE^$Z(Z+[;Z;Z.[#Z C[IXH[ (X ([HXI[ (" + "Z $k 9Z .Y*Z FY=Y .X ,\\ *UAnCU J^CW -VCmAV ?W>V *X IX (a /Y1Y HnEW KV 0X7W BW.X HW.W La3X " + "(Y ,ZHY 2YGY 2ZHZ 3YGY 1YHZ 3YGY @ZCZ 9[ LZ !Z Z !Z >Z !Z !Z \"Z :Z'\\&YJY6Y'[$[)[$[*[$[+[#[+[$[&[+\\([.e'Z(" + "Z#Z(Z$Z(Z$Y'Y GZ?Z ?| EY>c >l 4l 3l 2l 3l 4l Gl=h @k 5h /h /h /h )Y Y NX Y E[ ?XFd 1g .h /h /h /h )\\ )hHX " + "LY0X HY0X GX0X GX0Y LZ+Y KYGd AY*Y 9[EXD[ M[1[ L[1[ K[1[ M[1[ 4X 8Z+Y A[ !T /n 6q N~o q 8q @X.X 8` 7" + "Y3Y Z $Z 5Z +XCX 0X@X DYDT EW;W?X ?Y :X #Y IY %^ \"X )X k 5}\"~W KY0Z ?YGZ 1[ *Z /Z\"[(]CZD^%Z(Z+[;Z;Z.[#[ CYHXGY 'X 'YGXHY 'Z &o" + " ;Z /[,[ FZ?Y -X +\\ +UBoBU LZ>W -UBnAU >W@W *X JX 'c 1Y1Y HnEW KV /W7W BW.W GW/X Lc5W 'Y ," + "YFY 4ZGY 2YFY 3YGZ 3YFY 3YGZ AZCZ 9Z KZ !Z Z !Z >Z !Z !Z \"Z :Z&[&YJZ7Y'[#[*Z\"Z+[#[+[#[+[#[&[-\\'[/YM[(Z(Z#" + "Z(Z$Z(Z$Y'Y G[A[ ?} FY?] :p 8q 8q 7q 8q 8p LqAl Do 9l 3l 3l 3l +Y Y NX Y #i @XHh 5k 2l 3l 3k 2l +\\ +lKX KY0" + "X HY0X GX0X GX0Y KY,Z KYIh CZ,Z :ZCXC[ [/[ N[.Z MZ.[ [/[ 5X 7Y,Z AZ !U /o 7p M~n s :s AX.X 8` 7Z4Y Y" + " #Z 5Z +XCX 0W?X EYCT EW;W@X >Z ;X #Y HX #Z X *X ;Z1Z 3Z @Z !Z 9XFZ ?Y \"Z /Z " + "BY2Z KZ0[ [/Z 4t =YJj 3q >kJY >o 8r ;kJY GYJk .Y NX 0X5\\ 6Y FY" + "JiBi$YJk 8o ?YJj 9kJX ;YJc Z !Z !Z \"Z :Z&[&YIZ8Y([\"[+[\"[,[\"Z+Z!Z,[\"[%[/\\" + "&Z/YL[(Z(Z#Z(Z$Z(Z$Y'Y F[BZ >Z@d GY@\\ :t ;t t TAU NX;W )P9P =UAWAYAU >XDX )X LX HY 3Y1Y HnEW KV /W7W " + "AP9P 9W0X FW0X ?Y8W &Y -YEZ 5YEY 4ZFZ 5YEY 4ZEY 5YEY BZBZ :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z%['YIZ8Y([!Z+Z![,Z![-" + "[![-[!Z$[1\\&[/XJZ(Z(Z#Z(Z$Z(Z$Y'Y EZCZ =Z;` HYA[ 8u oLX ;YLe ?u VAW?XAU ?ZHY (X MX EX 4Y1Y HnE" + "W KV /W7W AQ:Q :W0W EW1X Z !Z !Z \"Z :Z%['YHZ" + "9Y(Z Z+Z Z-[![-[![-Z [$[3\\%[0XI[)Z(Z#Z(Z$Z(Z$Y'Y E[E[ =Z9^ HYBZ 6v =v >w =w >v =v\"vIt Lt >t ;t ;t ;t /Y Y N" + "X Y *r BXKn qMY GYMp 0Y NX 0X8[ 2Y FYMoIp'YMq ?v BYMp ?qMX ;YMf ?u U@W?XAU >j (X " + " NX CX 5Y1Y HnEW KV /W7W AR;R ;W1X EW1W :XZ " + "!Z !Z \"Z :Z$Z'YHZ9Y)[ [-[ [.[ Z-Z NZ-Z [#[5\\$Z0XH[)Z(Z#Z(Z$Z(Z$Y'Y D[FZ w ?x >x ?w >w#wKv Nu ?v" + " =v =v =v 0Y Y NX Y +s BXLp >u \\ DX.X :c 7Z7Z!Y \"Z 4Z +XCX C~d&XBT DW=XB" + "X :[ >X $Y FY +f &X +X ;Z/Z 4Z AZ !Z ;YDZ ?YFP -Z?Q BZ ?Z5Z JZ/Z 5Z \"[ Gj Ii ;[\"X1Q,W\"YCZ BZ1" + "Z MZ \"Z$[!Z MZ /Z LZ(Z :Z \"Z 4ZH] 0Z 2YHX;XHY(YHZ:Z)Z N[!Z2Z([ NZ%Z2Z I[ ;Y 9Z(Z Z1Z,Z;XGW;Z N[L[ 4[H[ #\\" + " 1X MX AY BZ&Z 8^Ga AYN[H_ " + "YDY *X )b 6UDY%U V9W ,SU@W>W@T =h 'X X AW 5Y1Y HnEW KV /X9X ASZ !Z !Z \"Z :Z$Z'YGZ:Y)[ NZ-[ [.Z N[.Z NZ.[ NZ\"[7\\$[1XFZ)Z(Z#Z(" + "Z$Z(Z$Y'Y CZGZ ;Z6\\ IYCY 4^Ga ?^Ga @_Hb ?^Ga ?^Ga ?^Ga$^GaMaI`!bH\\ @aI` ?aI` ?aI` ?aI` 1Y Y NX Y ,u CXM^Nb" + " @aKa >aJa ?aJa ?aKa =`Ja 1\\ 0`Ic GY0X HY0X GX0X GX0Y IY0Z IYN[H_ FZ0Z X>Y&X#X%YJT9TIY&Y.TJY&X#X 8X 5Y0" + "Z CZ ;P4U 1w 9l J~m#z B[;[ EX.X :d 7Y7Y X )~Q #Z +XCX C~d&XBT DW=XCX 9\\ ?X $Y FY " + "-j (X +X ;Z/Z 4Z AZ \"Z :XCZ ?YM_ 5ZE^ IZ >Y6Z IZ0[ 5Z \"[ Jj Ci ?\\\"X6\\2X#YBY BZ1Z MZ \"Z$[!Z " + "MZ 0[ LZ(Z :Z \"Z 4ZI] /Z 2YHX;XHY(YGZ;Z)Z N[!Z3[([ NZ%Z2Z H[ ^ BcB] >_?W C^CYNY C]A] 4Y /]Bc GYNYD^ 2Y NX 0X;\\ 0Y FYNXC\\KYD](YNYC] A]B^ DcB] C^CYNX ;YNZDQ A\\" + ";V 5Y .Y1Y IY/Y&Y;_;Y\"Z;Z FZ0Y $[ 2Y X Y M];\\ F]E[JX IY9[ LY >ZKf =]=V CYNYC] K`2Z 5^ 9Y1Y!Z\"Z!^JZM^" + " K~Y!Y@X@Y E]C^ CaHl\"~W LY.Z BYBY .\\ 0Z 1Z M[-[>Z>[(Z(Z*Z;Z<[0[ N[$[ W@U =f &X !X @W 5Y1Y HnEW KV /X9X AT=T =W2X DW2W 8W=X $Y .YBY 8ZC" + "Z 7YBY 8ZCZ 7YBY 8ZBY FZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(YGZ:Y)[ NZ-Z MZ.Z N[/[ N[/[ NZ![9\\#[2YFZ)Z(Z#Z(Z" + "$Z(Z$Y'Y C[I[ ;Z5\\ JYCY 4X=^ @X=] @Y=] ?Y>^ @X=^ @X=^%X=l@\\\"_?W A]@\\ @]@\\ @^A\\ @^A\\ 1Y Y NX Y -w DXNY" + "C] A^C^ ?^C^ A^B] @^C^ ?^C^ 2\\ 1^C_ FY0X HY0X GX0X GX0Y IY0Y HcB] FY0Y ;X=X=Y(Y#Y'YJV;VIX&X.VJY(Y#Y 9W 4Z1" + "Z DZ =S4U 2y 9j I~l#{ BZ9Z EX.X :d 7Z8Y!Y *~R #Z +XCX C~d'YBT DX?XBW 7\\ @X $Y FY " + "/ZNVNZ *X ,X :Z/Z 4Z AZ #Z :XBZ ?o 9ZGc MZ =Z8[ HY0\\ 6Z \"[ Li >j C\\\"X8aGVBW$ZBZ CZ2Z LZ \"Z#Z!" + "Z MZ 0[ LZ(Z :Z \"Z 4ZJ] .Z 2YHXY 9Z(Z NZ2Z,Z\\ @^:T C\\?b D\\=\\ 5Y 0\\>a Ga?\\ 2Y NX 0X<\\ /Y Fa@\\MX@[(b@\\ B]?\\ Da?] D\\?a ;b 1Z6" + "S 5Y .Y1Y IZ1Z&Y;_;X![=Z DY1Y #[ 2Y X Y `>` I\\B[KX IY:\\ LY ?ZDa ?\\7R Cb?\\ F[3Y 5_ 9Y1Y\"Z Y!]IYJ] L" + "~Y!Y@X@Y F\\?\\ D^Ai\"~W LY.Z CZBZ .\\ 1Z 1Z LZ.[=Z>[(Z(Z*Z;Z<[0[ N[%\\ XAU V ?W3X CW3X 8X>W #Y /Z" + "BZ 9YAY 8ZBZ 9YAY 8ZBZ 9YAY FZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(YFZ;Y)Z MZ-Z MZ/[ MZ/[ N[/Z M[![;\\\"[3YE[*" + "Z(Z#Z(Z$Z(Z$Y'Y B[JZ :Z4[ JYCX 3U8\\ @U8\\ AV8\\ @U7\\ AU7[ @U8\\%U8h=\\$]9T B\\=\\ B\\=\\ B\\=\\ B\\<[ 2Y Y " + "NX Y .x Da?\\ C]?] A]?] B\\?] B]?] A]?] 3\\ 2]?] FY0X HY0X GX0X GX0Y IZ1Y Ha?] GY1Z ~d W5T 2{ 9i H~k$} DZ7Z FX.X :d 7Z9Z!X )~R #Z 0~d&XBT DX?XCX 6\\ " + " =Y EY 0ZMVMZ +X ,X :Z/Z 4Z B[ %\\ :XBZ ?q ;YHg Z \\ 0Z 6Y.Z CYAZ -\\ 2Z 1Z LZ.[=Z=[)Z(Z*Z;ZW>X@T ;a #X #X =W 6Y1Y GmEW KV .X;X @W@W @W3W BW4X 6W?X #Y /Y@Y :" + "ZAY 8Y@Y 9YAZ 9Y@Y 9YAZ GZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(YFZ;Y)Z M[/[ MZ/[ MZ/Z LZ/Z M[ [=\\!Z3YD[*Z(Z#Z" + "(Z$Z(Z$Y'Y AZKZ 9Z4[ JYDY 3R3[ AR3[ BS3Z @S4[ AS4[ AR3[&R3e:[&]6R C\\:[ D\\:[ D\\:[ D\\:[ 3Y Y NX Y /_B] E_<" + "[ C[;[ B\\<\\ C\\<\\ C[;\\ C\\<\\ 3\\ 3\\<\\ FY0X HY0X GX0X GX0Y HY2Z H`<[ FY2Y ;X~d#Z6U 3} :h G~k%~P EY5Y FX.X ;ZNY 6Y9Z!X *~R \"Z 0~d&YCT CXAXBW 5] " + " >Y EY 2ZKVKZ -X ,X :Z/Z 4Z BZ &] :XAZ ?s =YJk #[ ;[=[ FZ1\\ 6Z \"[ #j L~d Ki J\\!X:hKVAW%Y@Y CZ5\\ L" + "[ \"Z#Z!Z MZ 0Z KZ(Z :Z \"Z 4ZL] ,Z 2YGX=XGY(YEZ=Z*[ M[\"Z4['Z LZ&Z4[ F` BY 9Z(Z MZ4Z*Z=XEW=Z Jd .ZLZ #\\ .X" + " LX BY JQ1[ D_:[ B\\ ([9_ F[7Z 6Y 1[:_ G^9Z 3Y NX 0X>\\ -Y F^;b;Z)_:Z D[:\\ F_:[ G[9^ ;_ /Y EY .Y1Y " + "HY2Z$Y=a=Y NZ@[ BY3Z %[ 0Y X Y \"eCd L[>YLX HY>^ IY AY=] @Z &_:Z DY4Y 5a :Y1Y\"Z Z$\\GYG\\ EY9Y IY@X@Y G" + "Z9[ G\\;[ 0Y 5Y.Z DZ@Y ,\\ 3Z 1Z LZ.ZUDX!T\"XW>X@U :] !X $X Z !Z !Z \"Z :Z#Z(YEZ~d&^7U 4~ 9f E~i%~R GY4Y FX.X ;ZNZ 7Y9Y!X )~R \"Z NW?W BYCT CYBXCX 6_ ?Y EZ 5ZI" + "VIZ /X ,X :Z.Y 4Z C[ )_ :YAZ ?t >YKn %Z 9\\A\\ EZ1\\ 6Z \"[ &j I~d Hi N\\ W:jLVAW&Z@Z DZ8^ KZ !Z#[\"Z " + " MZ 0Z KZ(Z :Z \"Z 4ZM] +Z 2YGY?XFY(YEZ=Z*Z L[\"Z4['Z LZ&Z4[ Fc EY 9Z(Z MZ5Z)Z>XDW=Z Ic .[NZ #\\ -X KX CY " + " )Z D^8[ D\\ '[8^ FZ5Z 7Y 2[8^ G]8Z 3Y NX 0X?[ +Y F]9`9Y)^9Z E[8[ F^8Z GZ8^ ;^ .Y EY .Y1Y GY3Y#Y=WNX=Y M" + "ZAZ AY3Y %[ /Y X Y #gEf N[W>W?U 7W <~d BX ;W 6Y1Y GmEW KV -X=X ?YBY BW4W AW5X 5W@W !Y 0Y?Z ;Y?Y :Z@Z ;Y?Y :Z?Y ;Y" + "?Y HZ?Z <[ IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(YEZY D~P JZ !Z#[\"~Q Dy Z K~] :Z \"Z 4ZN] *Z 2YFX?XF" + "Y(YDZ>Z*Z L[\"Z5\\([ LZ&Z5\\ Eg JY 9Z(Z MZ5Z)Z>XDX>Z Ib ,f $\\ ,X KX CY (Y D]6Z D[ '[7^ GZ4Z 7Y 2Z6] " + "G]7Z 4Y NX 0X@[ *Y F]8^8Z*]7Z FZ6[ G]6Z I[7] ;] -X DY .Y1Y GY3Y#Y=WNX=X L[CZ ?Y4Y &[ .X NX Y $iGh Z:XNX" + " GYHg HY CY8\\ CY $]7Z DY6Y 4b ;Y1Y#Z MZ&[EYE[ FY9Y IY@X@Y HZ7[ I[7[ 2Y 5~V DY>Y +\\ 5Z 2Z KZ/[W>W?U K~d CX ;X " + " 6Y1Y FlEW KV -Y?Y ?ZCZ CW5X AW5W 5XAX !Y 0Y>Y Y Y ;Y?Z JZ>~Q3[ I~Q G~Q F~Q G~Q 5Z !Z !Z " + "\"Z :Z#Z(YDZ=Y*[ LZ/Z L[0Z L[0Z LZ0[ LZ L[C\\ N[5X@Z*Z(Z#Z(Z$Z(Z$Y'Y ?e 7Z3[ KYDY @Y Y !Z Y Y Y 4_4Y)[ %Z3" + "Y GZ3Y FZ4Y FZ4Y 4Y Y NX Y 1[8Z F\\7Z F[7[ EZ6[ G[6[ G[6Z EZ6[ Y D~ IZ !Z#[\"~Q Dy![ K~] :Z \"Z 4h )Z 2YFX@YFY(YDZ>Z*Z KZ\"Z5\\([ LZ&Z6\\ Ck Y 9Z(Z LZ6Z(" + "Z?XDX?Z G` *d #[ +X KX CY 'Y E]6[ F[ &Z5] GY2Y 7Y 3Z4\\ G\\6Z 4Y NX 0XA[ )Y F\\7]6Y*\\5Y G[5Z G\\5Z I" + "Z5\\ ;] -X DY .Y1Y GZ5Z#Y>XMW>Y K[E[ ?Y5Y &[ .Y NX Y $XIZHZIY!Z:XNX GYHf GY DY6[ CY $\\5Y CX6Y 5c ;Y1Y#" + "Z MZ&[EYDZ FY9Y IY@X@Y IZ5Z IZ5Z 2Y 5~V EZ>Y *[ 5Z 2Z KZ/[Z EiKh 6X /XC^ BTDX U\"YA\\ 4ZCZ N~d &U>W?X>T K~d EY :W 5Y1Y EkEW KV ,YAY =ZCZ DW6X @W6" + "X 5W@W 'Z>Y Z =Y=Y ;Y>Z =Z>Y JZ>~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z :Z#[)YDZ=Y*[ LZ/Z KZ0Z L[1[ LZ0[ L" + "Z K[E\\ M[6Y@Z*Z(Z#Z(Z$Z(Z$Y'Y >d 7Z2Z KYDY @Y Y Y NY Y !Y 4^3Z*Z $Z3Z HZ3Z HZ3Z HZ2Y 5Y Y NX Y 2[6Z G" + "\\6Y FZ5[ G[5Z GZ5[ GZ5[ G[5Z =[:_ HY0X HY0X GX0X GX0Y GZ5Y F\\5Z GY5Z Z6Y &[ .Y NX Y %WEYJYEX#Z8a GYHe FY DX4[ DY $\\5Y CY8Z 5d Y*Z KZ/Z KZ0Z L[1[ L[1[ LZ J[G\\ L[7Y?Z*Z(Z#Z(Z$Z(Z$" + "Y'Y >c 6Z2Z KYDY ?Y X NX NY Y Y 4\\1Y+[ %Z1Y HY1Y HY1Y HY1Y 5Y Y NX Y 3[5Z G[5Z HZ3Z GZ4[ HZ4Z HZ3Z GZ" + "4[ >Z9` IY0X HY0X GX0X GX0Y FY6Z F\\4Z GY6Y ;W9X9W-X JX,WD[I\\DW,W1[DW-X JX =X 1Y6Z <~d'RKY:U 5~U J" + "~T$~g'~X KY1X GX.X Z ?y DgF` *Z 2k >Z4^ 6Z \"[ 1j >~d =i -[ LW=\\C_?W)YZ=Z =YZ=Z =YZ=Z LZ=~Q3Z H~Q G~Q F~Q G~Q" + " 5Z !Z !Z \"Z Ew5[)YCZ>Y*Z KZ/Z KZ0Z KZ1[ L[1Z KZ I[I\\ K[8Y>[+Z(Z#Z(Z$Z(Z$Y'Y =a 5Z2Z KYDY ?Y Y X MX Y Y" + " 4\\1Y+Z $Y0Y IZ1Y IZ1Y IZ0X 5Y Y NX Y 3Z3Y GZ3Y HZ3Z HZ2Z IZ2Z IZ3Z GZ3Z >Z:a IY0X HY0X GX0X GX0Y FZ7Y E[" + "3Z GY6Y ;W9X9W-W HW,WC[K\\CW,W2[CW-W HW =X 1Z7Z <~d NX:U 5~V M~X%~e&~Y LX0Y HX.X =ZJY 6Y=Z W " + " NZ 3Y X@X ?]IT ?hCW 7h2X ;Y CY 7TAVAT 1X .X 8Z.Y 4Z G\\ 6g 5X=Z ?X?a EeB^ +Z /f ;[5" + "^ 4i ;~d :i 1[ LWr *Y " + "9Z(Z KZ8Z'Z@XBX@Y D\\ &` $\\ )X JX DY &X E[2Z HZ %Z3\\ IZ/X 8Y 4Z2[ GZ3Y 4Y NX 0XE\\ &Y FZ4[5Y*[4Z IZ" + "2Z H[2Y KY2[ ;[ +X DY .Y1Y FZ7Z!Y?WLX?X H[IZ ;Y7Y '[ ,Y NX NY *Q NV@WLW?U#Z8` FYHd .^FY EX2[ DX $[3Y CX8Y" + " 5YMY [/[IuI[.\\ 4X 4\\ =X =\\$\\" + " =X MZAU -Z &X8Y G~W 6X 0W<\\ FUEX MT iNW 8[D[ K~d &T=WE\\QZZeBX] ,Z 1j <[7_ 7i 8~d 7i 5[ KW=Z=" + "\\?W*Y:Y F{ FZ !Z\"Z\"~Q Dy![1j&~] :Z \"Z 4e &Z 2YDXCXDY(YBZ@Z*Z KZ\"Z[/[IuI[/\\ 3X 3\\ >X >\\\"\\ >X MZAU -Z 'X6X 5c " + "%X 1X;\\ GUEX MT NgMW 9[D[ J~d &T=m;T K~d In 4TA[ 4Y1Y BhEW 3Z DX )i 5[D[ IX9W5Z3W8WFj?TA[BX5Z KY" + ";Z @Z;Z ?Y:Y @Z;Z ?Z;Y ?Y;Z NZ<~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)YAY?Y*Z KZ/Z KZ1[ KZ1[ L[1Z KZ G[M\\ IZ8" + "X<[+Z(Z#Z(Z$Z(Z$Y'Y <_ 4Z2Z KYD[ @X NX Y NY X NX 3Z/Y-Z $Z/Y KZ/Y KZ/Y KZ/Y 6Y Y NX Y 4Z2Z HZ3Y IZ1Z I" + "Z1Z JY1Z JZ1Z IZ1Z @Z;XNZ JY0X HY0X GX0X GX0Y EY8Y D[2Z GY8Y ;X9X8W.W HW-W@hAW-X4[@W.W:[:W =X 0Z9Z I" + "[ 7YY ~m 4Z 3Y W?X >g =cAW?]'[K\\5Y ;Y CZ %V M" + "X /X 7Y-Z 5Z H[ 4l ;XZ>Z.[IuI[0\\ 2X 2\\ ?X ?\\ \\ ?X MY@U 8y ;X6X 4a $X 1X9[ HUEX MT MeLW :[D[ I~d &T=l:T " + "K~d Io 5m 3Y1Y AgEW 3Z Nl 2g 3[D[%lDX5Z>mDXFk@mAW5[ LZ:Y @Y:Z ?Y:Y @Z:Y ?Y:Z AZ:Y NZ<~Q3Z H~Q G~Q F~Q G" + "~Q 5Z !Z !Z \"Z Ew5[)YAZ@Y*Z KZ/Z KZ1[ KZ1[ L[1Z K[ Gh HZ9X;[+Z(Z#Z(Z$Z(Z$Y'Y ;] 3Z2Z KYC[ AX NX Y NY Y X" + " 3Y.Y-Z $Y.Y KY.Y KY.Y KY.Y 6Y Y NX Y 4Z1Y HY2Y IZ1Z IY0Z KZ0Z KZ1Z IY0Z @Y;XMZ JY0X HY0X GX0X GX0Y DY9Y D" + "Z0Y GY9Z ;W8X8W.W HW-W?f?W.W4[?W.W:[:W =X 0Z9Y HZ 5X_@XAa*[I\\6Y ;Y CZ %V MX /X 7Y-Z 5Z I[ 3n >X;Z ] G`9\\ .Z 4s @[9` " + " =i /i ;Z IV=Y9Z>V+Z:Z G~P JZ !Z\"Z\"~Q Dy!Z1l'~] :Z \"Z 4g (Z 2YDYEXCY(YAZAZ*Z KZ\"}$Z K['z 5r /Y 9Z(Z JZ;Z" + "$ZAW@WAZ F_ %\\ $[ &X IX EY &Y FZ0Y IZ %Y/Z IY.Y 9Y 4Y0Z GY1Y 5Y NX 0XH[ \"Y FY3Z3Y+Z2Y JZ0Z IZ0Y MY0" + "Z ;Z *Z FY .Y1Y DY9Y MYAWJXAY F[MZ 8Z:Y )[ +Z MX N[ 7g1U U<^;U&Z6^ EYHj 9gJY FX/Y CY &Z2Y BYY1Y%Z" + " J[*ZBYBZ HY9Y IY@X@Y KY0Z MY/Y 4Y 6~W GZ:Z ,[ 6Z 2Z KZ/Z;Z;Z*Z(Z([>Z?[.ZHuI[1\\ 1X 1\\ @X @\\ M\\ @X NZ" + "@U 8y ;W4X 5` #X 1X8Z HUEX MT LbJW ;ZC[ H~d &T=j8U L~d Io 5l 2Y1Y @fEW 3Z Nl 0c 0[CZ&lDW5[>mEXE\\N^" + "AlAX6\\ LZ:Z AY9Y @Z:Z AY9Y @Z:Z AY9Z!Z;~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)Y@ZAY*Z KZ/Z KZ1[ KZ1[ L[1Z K" + "[ Ff GZ:X:[+Z(Z#Z(Z$Z(Z$Y'Y :\\ 3Z2Z KYC\\ BY X NX NY Y X 3Y-X-Y #Y-X KY-X KY-X KY-X 6Y Y NX Y 5Z0Y HY" + "2Y IY/Y JZ0Z KZ0Z KY/Z KZ/Y AZ;WKY JY0X HY0X GX0X GX0Y DY:Z DZ0Y FY:Y :WK~KW.WK}KW-W>d>W.W5[>W.W:[:W =X /" + "Y:Z IZ 4Y=T 6~[%~b'~_%~\\ NY/X HX.X >ZHY 6Y?Y N~m 4Z 3Y !X@X ;l @[>WBe,ZG\\7Y ;Y" + " CZ %V ;~c LX 7Y-Z 5Z J\\ 2n @Y;Z N\\ G`8\\ /Z 5u A\\V+Y8Y G~R LZ !Z\"Z\"~Q" + " Dy![2l'~] :Z \"Z 4h )Z 2YCXEXCY(Y@ZBZ*Z KZ\"|#Z K['x 0q 1Y 9Z(Z IZY1Y%Z IZ*YAYBZ HY9Y IY@X@Y KY/Y MY/Y 4Y 6~W GY9Z " + "-[ 5Z 2[ LZ/Z;Z;Z*Z(Z'[?Z?[.[IuI[2~n BX B~n AX A~m AX NZ@U 8y dEW 3Z Nl ._ ,ZCZ'lEX6\\>mEWDVCZBkAX6] LY8Y BZ9Z AY8Y BZ9Z AY8Y BZ9Z!Z;~Q3Z H~Q " + "G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)Y@ZAY*Z KZ/Z KZ1[ KZ1[ L[1Z KZ Ee FZ;Y:[+Z(Z#Z(Z$Z(Z$Y'Y :[ 2Z2Z KYB\\ CY X NX" + " NY Y Y 4Y-Y.Y #Y-X KY-X KY-Y LY-Y 7Y Y NX Y 5Z0Z IY2Y JZ/Z KZ/Y KY/Z KY/Z KZ/Y#~d$ZX /Z;Z JZ 2X>U 6~\\'~c&~^$~Z MY/X HX.X >YGZ 7Z@Y " + "N~m 4Z 3Y !X@X :n 'WBg.ZE\\8X :Y CZ %V <~e NX 6Y-Y 4Z K\\ #a AX:Z M\\ H_6[ 0Z" + " 6aI` A]?c ?f $f ?Z IW>Y7Y>V,Z8Z HZ8` MZ !Z\"Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZN] *Z 2YCXFYCY(Y@ZBZ*Z KZ\"{\"Z " + "K['v +o 2Y 9Z(Z IZq:X !U:[9U&Y5] DY?d =jLX FY/Z C[ " + ")Y1Y AX=Z 6ZIY >Y1Y%Z IZ*YAYAY HY9Y IY@X@Y KY/Y NZ/Z 5Y 5Y-Y HZ8Y .[ 4Z 1Z LZ/Z;Z;Z*Z(Z'[?Z@[-[ L[3~o BX B~o BX" + " B~o BX NZ@U 8y mFXDS?YBi?W5] CY 4Z8Y BY7Y BZ8Z CY7Y AY8Z CZ8Y!Y:Z Z !Z !Z \"Z Ew5[)Y?ZBY*Z KZ/Z KZ1[ KZ" + "1[ L[1Z KZ Dc E[=Y9[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z2Z KYB^ &i 0i 1i /i 0i 0i Ej-Y/Z $Z-Y MZ-Y MZ-Y LY-Y 7Y Y NX Y 5Y/" + "Z IY1X JZ/Z KZ/Z LY.Y LZ/Z KZ/Z$~d$Z=WIZ KY0X HY0X GX0X GX0Y CYX .Y;Y JZ 1Y?U 6~\\(~e'~]\"~X LX.X HX.X >YFY 7ZAZ N~m 4Z 3Y !W?X 9p +XCi0ZC\\9X " + " :Y CZ %V <~e NX 6Z.Y 4Z L\\ M^ CY:Z L[ H^4Z 0Z 7^A^ C_Ce ?c Mc @Z HW>X6Y>V,Y7Z HZ5^ NZ !Z\"" + "Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZM] +Z 2YBXGXBY(Y?ZCZ*Z KZ\"z![ LZ&w 'k 3Y 9Z(Z IZ=Z\"ZCX@XCZ Gc &Z &\\ $X HX FY " + " >q FY.Y JY $Y/Z JY,X 9Y 5Y.Y GY1Y 5Y NX 0XL\\ NY FY3Z3Y+Y1Y JY.Z JY/Z NY/Y ;Y (^ KY .Y1Y CY;Y KYCXIXCY " + "Bc 4Y\\IYMX FY/Z B\\ +Y1Y AY>Y 5ZIZ ?Y1Y%Z IZ*YAYAY HY9Y IY@X@Y KY/Y NZ" + "/Z 5Y 5Y-Y HZ8Z 0\\ 4Z 1Z LZ/Z;Z;Z*Z(Z&[@Z@[-[ L[4~p BX B~o BX B~p CX NY?U 8y mFWCQ;XAe>X6UNW CY 4Y7Z DZ7Y BZ8Z CY7Z CZ7" + "Y CY7Z#Z:Z Z !Z !Z \"Z :Z#[)Y?ZBY*Z KZ/Z KZ0Z KZ1[ L[1Z KZ Ca D[>Y8[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ " + "KYA^ /q 9r 9q 7q 8q 9r Mq,Y/Z $Y,Y MY,Y MY,Y MZ-Y 7Y Y NX Y 5Y.Y IY1X JZ/Z KY.Z LY.Y LZ/Z KY.Z$~d$Y=XIZ KY0X" + " HY0X GX0X GX0Y CYX .YW-Y6Y HZ2\\ Z !Z\"Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZL] ,Z 2YBXGXBY(Y?Z" + "CZ*Z KZ\"x N[ LZ&x #f 3Y 9Z(Z HZ>Z\"ZCW>WCZ Hd &Z &[ #X HX FY At FY.Y JY $Y/Z JY,Y :Y 5Y.Y GY1Y 5Y NX" + " 0XM\\ MY FY3Y2Y+Y1Y JY.Z JY.Y Z/Y ;Y (b Y .Y1Y CY;Y KYCWHXCY Bb 3Y=Y *[ 6e JX Ke KzF^ !U9Y7T'Z4[ CY7] @[E" + "XNX GZ.Y Ai 9Y1Y AY>Y 5YHZ ?Y1Y&[ IZ+ZAYAY HY9Y IY@X@Y KY/Y NZ.Y 5Y 5Y-Y IZ6Y 0[ 3Z 1Z LZ/Z;Z;Z*Z(Z&\\AZA[,[ L[" + "4~p BX B~o BX C~q CX NY?U 8y Z !Z !Z \"Z :Z#[)Y>ZCY*Z K" + "Z/Z KZ0Z L[1[ L[1Z KZ B_ C[>X7[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ KY@_ 5u XHZ KY0X HY0X GX0X GX0Y BY=Y BY.Y FY=Z 9WK~KW/WJ}JW.W:\\:W.W" + "9[:W/W9[9W >X .Z=Y JZ /X@U 6~^*~g&~Y N~V KX.Y IX.X ?ZFZ 7ZBY L~l 4Z 3Y \"X@X 3n /X" + "CZIZ2Z@\\W.Z6" + "Z IZ1[ Z !Z#[\"Z MZ 1[2l'Z(Z :Z \"Z 4ZK] -Z 2YBXHYBY(Y>ZDZ*Z KZ\"v L[ LZ&z !c 4Y 9Z(Z HZ>Z\"ZDX>XDY Ge 'Z '[ " + "\"X GX GY Dw FY.Y JY %Z/Z J~W :Y 5Y.Y GY1Y 5Y NX 0XN\\ LY FY3Y2Y+Y1Y JY.Z JY.Y Z/Y ;Y 'e $Y .Y1Y CZ=Z" + " KYDXGWDY @a 3Z>Y +[ 5d IX Ic L~d !U8X7T'Z4[ CY5\\ AZCa GY-Y @h 9Y1Y @X?Z 6ZGY ?Y1Y&[9X9Z+ZAYAZ IY9Y IY@X@Y " + "KY/Z Y-Y 5Y 5Y.Z IZ6Z 2[ 2Z 1Z M[/Z;Z<[*Z(Z%[AZB\\,[ LZ3~p BX B~o BX C~q CX NY?U 8y Z !Z !Z \"Z :Z#[)Y>ZCY*Z KZ/Z KZ0Z L[1[ L[1[ LZ A] B[?X6Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ KY?" + "_ 8w ?x ?w =w >w >w$~u/Y #~W M~W M~W M~W 7Y Y NX Y 6Z.Y IX0X JY-Y KY.Z MZ.Z MY-Y KY-Y$~d$Y?XFY KY0X HY0X GX0" + "X GX0Y BY>Z BY.Y EY>Y 8WK~KW/WJ}JW.W;]:W.W:[9W/W9[9W >X -Y>Z KZ .YAU 6~^*~g%~W L~T JX.Y IX.X ?YEZ 7Z" + "CZ L~k :y KY \"X@X 0m 1WCYEY3Y>\\=X 9Y BY %V <~e =l X 5Z.Y 4Z \\ E[ GY8Z JZ I]" + "2Z 2Z 8[7[ BqMZ ?^ C^ @Y GV=W4X>V-Y5Z IZ0[!Z !Z#[\"Z MZ 1[2l'Z(Z :Z \"Z 4ZJ] .Z 2YAXIXAY(Y=YDZ*Z L[\"s" + " I[ LZ&[Cc Na 5Y 9Z(Z HZ?Z YDX>XEZ Hg (Z (\\ \"X GX GY Fy FY.Y KZ %Z/Z J~W :Y 5Y.Y GY1Y 5Y NX 0e KY" + " FY3Y2Y+Y1Y KZ.Z JY.Y Y.Y ;Y &h (Y .Y1Y BY=Y IXDXGWDY ?_ 1Y?Z ,[ 4b GX Ga L~c T6V6T'Z4[ CY4\\ CZ@_ GY-Y >f " + "9Y1Y @Y@Y 5YFZ @Y1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y KX.Z Y-Y 5Y 5Y.Z IY5Z 3[ 1Z 1Z M[/[WEY9T -X EY1Y 1WEW 3Z 6ZCZ 7X7" + "UKV HW*W KX6ULW CY 5Y5Z FZ5Z EY4Y FZ5Z EZ5Y EY5Z%Z9Z Z !Z !Z \"Z :Z#Z(Y=ZDY*[ LZ/Z KZ0Z L[0Z " + "LZ0[ LZ A] B[@X5Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z4[ JY>` Y 8WK~KW/WJ}JW.W<_;W.W;[8W/W9[9W >X -Z?Z " + " LZ -YBU 5~^*~h%~U J~R IX.Y IX.X @ZDY 6YCZ LW 'y JY \"W?X ,j 3WCYCY4Y=\\>X 9Y CZ" + " %V <~e =l X 5Z.Y 4Z !\\ C[ IY7Z JZ I]2Z 3[ 9[5[ BoLZ ?a Ia @Y HW>X3W>V.Z4Y IZ/Z!Z !Z#[\"Z MZ 0" + "Z Z'Z(Z :Z \"Z 4ZI] /Z 2YAXIXAY(Y=ZEZ*Z L[\"o DZ LZ&Z<^ M_ 5Y 9Z(Z GZ@Z ZEX>XEZ I[MZ (Z )\\ !X GX GY " + "Gz FY.Y KZ %Y-Y J~W :Y 5Y.Y GY1Y 5Y NX 0c IY FY3Y2Y+Y1Y KZ.Z JY.Y Y.Y ;Y %j +Y .Y1Y BY=Y IYEXGXEY >] 0Y?Y ,[ " + "3` EX E_ L\\Cx NT6V6T'Z4Z BY2Z CY>^ GY-Y ;c 9Y1Y @YAZ 6ZEY @Y1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y KX.Z Y-Y 5Y 5Y.Z JZ" + "4Y 4\\ 1Z 1[ NZ.[" + "WDX:U -X EY1Y 1WEW 3Z 5YBY 7W6UKV IX*W KW6UKW CY 6Z4Y FZ5Z FZ4Z GZ4Y EY4Z GZ4Y%Y8Z <[ IZ !Z " + " Z !Z >Z !Z !Z \"Z :Z#Z(Y=ZDY*[ LZ/Z L[0Z L[0Z LZ0[ LZ B_ BZAY5Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z5\\ JY=` ?{ B{ Bz @z B{ " + "B{'~x/Y #~W M~W M~W M~W 7Y Y NX Y 6Z.Y IX0X JY-Y LZ-Y MZ.Z MY-Y KY-Y$~d$Y@WDY KY0X HY0X GX0X GX0Y AY@Z AY.Y " + "DY@Z 8WK~KW/WJ}JW.W=aX ,Y?Y LZ +XBU 6~_+~i%~U I~P HX.Y IX.X @ZDZ 7YCY KX " + " (y JY \"W?W (h 5XCXAX5Z<\\@Y 9Y CZ $T ;~e =l X 5Z/Z 4Z \"\\ AZ IX6Z JZ I\\1[ 4Z 8Z3Z AmKZ" + " ?d d AZ HW>X3W>V.Z4Z JZ.Z\"[ \"Z#[\"Z MZ 0Z Z'Z(Z :Z \"Z 4ZH] 0Z 2YAYKX@Y(YWCX;U -X EY1Y 1WEW 3Z Is 0YAX 8W6UJV IW)W" + " LX7UJW CY 6Z4Z GY3Y FZ4Z GY3Y FZ4Z GY3Z'Z8Z <[ IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(Yc=W.W=[6W/X:[:X >X ,Y@Z M[ " + "+YCT 5~`,~i$~S H~P HX.Y IX.X @YCZ 7ZDY KX )y HX #X@X (TNc 6WCX@X5Y:\\AX 8Y CZ :~e" + " =l !X 4Z/Z 4Z #\\ @[ KY6Z IZ I[0Z 4Z 9Z2[ @jJZ ?f %g AZ HW>X3W>V.Y2Y JZ.Z\"[ \"Z#Z!Z MZ 0Z Z'Z(Z" + " :Z \"Z 4ZG] 1Z 2Y@XKX@Y(YWBXZ !Z !Z \"Z :Z#Z(YW.W>[5W.W:[:W =W +ZAY LZ *YDU 5~`,~i#~Q F} GX.Y IX.X AZBY 7ZEZ KX " + ")y HX 6~e 9TJ_ 7XCX?X6Y9\\BX 8Y CZ KX Nl !X 4Z/Z 4Z $\\ >Z LY5Z IZ I[0Z 5Z 8Z1Z >fHY =h " + " +i @Z HW>X3W?W/Z2Z KZ.[#[ \"Z#Z!Z MZ 0Z Z'Z(Z :Z \"Z 4ZF] 2Z 2Y@XLY@Y(Y;ZGZ*[ MZ!Z /Z M[&Z7[ K\\ 6Y 9Z(Z FZ" + "BZ MYFXY FY.Y KZ %Y-Y K~X :Y 5Y.Y GY1Y 5Y NX 0e KY FY3Y2Y+Y1Y KZ-Y JY.Y" + " Y-X ;Y !m 2Y .Y1Y AZAZ GYGXEXGY >] .ZBY -[ 1e JX Ke LU4k IU8Y8T'Y2X AY0Y EX:[ FY-Z Ah 9Y1Y >XCZ 6YBY AY1Y&" + "Z8X8Z,Y@YAZ IY9Y IY@X@Y LY-Y Y-Y 5Y 5Z/Y JZ2Z 8[ .Z 0[!Z,[=Z=[)Z(Z\"]FZG]'Z M[1] 1X 1\\ @X @\\ L\\ AX DX 4" + "Z?U -Z (X4X H~W ;\\;W GTDX\"U s A[D[ 6X %T>WBXZ !Z !Z \"Z :Z$[(Y;ZFY)Z M[/[ MZ/[ MZ/Z M[/Z M[ Ee EZC" + "X3[*Z(Z#Z(Z$Z(Z$Y(Z 9Z 2Z8^ IY9` Fb=Y Eb=Y Eb=X Cb>Y Eb=Y Eb=Y*b=~V/Y #~W M~W M~W M~W 7Y Y NX Y 6Y-Z JX0X JY" + "-Y LZ-Y MY-Z MY-Y LZ-Y CZCXBY KY0X HY0X GX0X GX0Y @YBZ @Y.Y CYBY 6W8X8W.W HW-W@g@X.W?[4W.W:[:W =W *YBZ " + " MZ (XDU 5~`,~i\"~ D{ FX.Y IX.X AZBZ 7YEY IX +y GX 6~e 9TG] 8WBW>X6Y8\\DY 8Y CZ " + " KX Nl !X 4Z/Z 4Z %\\ =Z LX4Z IZ I[0Z 5Z 9Z0Z X3W?W/~S KZ-Z\"Z \"Z#Z!Z MZ 0[!Z" + "'Z(Z :Z \"Z 4ZE] 3Z 2Y?XMX?Y(Y;ZGZ)Z MZ!Z /[ N[&Z6[ K\\ 7Y 9Z(Z FZCZ LZGX^ .YCZ ." + "[ )_ KX L_ ES/e FU8Z9T'Z3X AY0Y FY:[ FY-Z Cj 9Y1Y >XCY 6ZBZ BY1Y&Z8X9[,Y@YAZ IY9Y IY@X@Y LY-Y Y-Y 5Y 5Z/Y J" + "Z2Z 9\\ .Z /Z!Z,\\>Z>[(Z(Z!]GZH^'[ N[0\\ 1X 2\\ ?X ?[ M\\ @X DX 4Z?U -Z 'W4W G~W :]>X GTDY#U s @[D[ 7" + "X %U?WAX>U ,X EY1Y 1WEW \"s 3ZC[ 9X7UHV KW(W MX7UHW CY 7~S J~S H~S I~S I~S I~S)} ;Z IZ !Z Z" + " !Z >Z !Z !Z \"Z :Z$[(Y;ZFY)Z MZ-Z MZ/[ N[/[ N[/Z MZ Eg F[EX2[*Z(Z#Z(Z$Z(Z$Y(Z 9Z 2Z9^ HY7_ G]8Y F^8Y F^8X D]8" + "Y E]8Y F^8Y+^8~V/Y #~W M~W M~W M~W 7Y Y NX Y 6Y-Z JX0X JY-Y LZ-Y MY-Z MY-Y LZ-Y BYDXAY KY0X HY0X GX0X GX0Y" + " @ZCY ?Y.Y CYBY 5W9X8W.W HW-WAiAW,WA[3W.W9Y9W >X *ZCZ 6~d IYET 4~`,~i!| By EX.Y IX.X AYAZ 7ZFY IX " + " Z 3X 6~e 9TF\\ 9WBX=W7Z7\\EX 7Y CZ KX Nl \"X 3Z/Z 4Z &\\ ;Z M~Z %Z I[0Z 6[ 9Z/" + "Y 8ZCZ 8i 6~d 5i ;Z HW>X3W?W0~T KZ-Z\"Z \"Z$[!Z MZ 0[!Z'Z(Z :Z \"Z 4ZD] 4Z 2Y?XMX?Y(Y:ZHZ)Z N[!Z /[ NZ%Z6[" + " J[ 7Y 9Z(Y DZDZ LZGW:WGZ K[GZ +Z -\\ LX EX IY L\\6Y FY.Y KZ %Y-Y K~W 9Y 5Y.Y GY1Y 5Y NX 0XM\\ MY " + "FY3Y2Y+Y1Y KZ.Z JY.Y Y-X ;Y Ji 4Y .Y1Y @YAY FYGWDXGX >` /YCY .[ $\\ LX M\\ AR+` CT9[:U'Z3X AY0Y FY9Z FY-Z " + "D` .Y1Y >YEZ 6YAZ BY1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y LY.Z Y-Y 5Y 5Z/Y KZ1Z 9[ -Z /Z\"[+[>Z>[(Z(Z ^IZJ_&[ NZ.\\ 2X 3" + "\\ >X >[ \\ ?X DX 4Z?U -Z 'X6X G~W 9^@X GUDY$T Ns ?[CZ 8X %U?WAY?U ,X EY1Y 1WEW \"s 4" + "ZCZ 7W7UGV LX)X MW7UGW CY 8~T J~T I~S J~T I~T K~T*~ ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(Y:ZGY)[ NZ-Z N[.Z N[/[ N" + "[/[ NZ Fi G[FX1Z)Z(Z#Z(Z$Z(Z$Z)Z 9Z 2ZX )YCY 5~d IYFU 4~`,~i!{ @x EX.Y IX.X AY@Y 7ZGZ IX Z 3X 6~e 9TD[ ;XBX=X8" + "Z6\\GY 7Y CY JX Nl \"X 2Y/Z 4Z '\\ :Z M~Z %Z I[0Z 6Z 8Z/Z \"Z 5i 9~d 8i 8Z HW>X3W?W0~U LZ-Z\"[ " + "#Z$[!Z MZ /Z!Z'Z(Z :Z \"Z 4ZC] 5Z 2Y?XNY?Y(Y:ZHZ)[ [!Z .Z NZ%Z5[ K[ 7Y 9Z(Y DZDY KZHX:XHY K[EZ ,Z .\\ KX EX" + " IY LZ4Y FY.Y KZ %Z.Y KZ X DX 4Z?U -Z 'X6X G~W " + "8^BX FUDY%U Ns =ZCZ 9X $U@W@X?T +X EY1Y 1WEW \"s 5ZCZ 7W7UFV LW(W MX8UFW CY 8~U K~T J~U K~" + "T J~U K~T*~ ;[ JZ !Z Z !Z >Z !Z !Z \"Z :Z$Z'Y9YGY)[ [-[ [.Z N[.Z NZ.[ NZ G\\L[ GZGX0Z)Z(Z#Z(Z$Z(Y#Z)Z 9Z 2~ " + "GY4] J[4Y G[4Y G[4X EZ4Y FZ4Y G[4Y,[4X 1Y #Y Y Y Y 9Y Y NX Y 6Y-Z JX0X JY-Y LZ-Y MZ.Z MY-Y KY-Y BYEW?Y" + " KY0X HY0X GX0X GX0Y ?YDY >Y.Y BYDY 4W9X9W-X JX,WD\\J[CW,WC[2W-X JX >X )YDZ 5~d HXFU 4~_+~i z @w DX.Y" + " IX.X BZ@Y 6YGZ IY Y @~e 9TCZ ;WAX=X8Y4\\HX 6Y CY JX Mj !X 2Y/Y 3Z (\\ 9Z" + " M~Z %Z I[0Z 6Z 8Z/Z \"Z 2i <~d ;i 5Z HW>X3W@W/~U LZ-[#[ #Z$Z Z MZ /Z!Z'Z(Z :Z \"Z 4ZB] 6Z 2Y>a>Y(Y9ZIZ)[ " + "Z Z .Z [%Z4Z JZ 7Y 9Z)Z DZEZ JYHX:XIZ KZD[ -Z /\\ JX EX IY MZ3Y FY.Y JY %Z/Z JY Z !Z !Z \"Z :Z%['Y9ZHY(Z [-[ Z" + "-[ Z-Z [-Z [ H\\J[ HZHY1[)Z(Z#Z(Z$Z(Y#Z)Z 9Z 2} FY2\\ KZ3Y GZ3Y GY3Y FZ3Y GZ3Y GZ3Y,Z3X 1Y #Y Y Y Y 9Y Y " + "NX Y 6Y-Z JX0X JY-Y KY.Z MZ.Z MY-Y KY-Y BYFX?Y KY0X HY0X GX0X GX0Y >YEY >Y.Y BYEZ 4X:X9W,W JW+WE\\H[EX,X" + "E[1W,W JW =X )ZEY 4~d HYHU 2~^+~i Nx >u CX.Y IX.X BY?Z 7ZHY GX Z A~e 9TCZ ~d >i 2Z GV>X3W@W0~V LZ-[\"Z " + "#Z%[ Z MZ /[\"Z'Z(Z :Z \"Z 4ZA] 7Z 2Y>a>Y(Y9ZIZ(Z Z Z .[![%Z4[ KZ 7Y 9Z)Z CZFZ JZIX:XIZ L[CZ -Z /[ IX DX J" + "Y MY2Y FY.Y JY %Z/Z JY Y CY1Y&Z9Y9Z+ZAYAY HY9Y IY@X@Y LZ/Y N" + "Y-Y 5Y 4Y0Z LZ.Y =[ *Z .[%Z(]AZA]'Z(Z L~\"[![+\\ 5X 6\\ JTEXET J[&\\ KSDXES $Y 3Y?U -Z &Y:Y F~W 5_GX DU" + "CZ9QAU DZCZ ;X $VAW?YBU +X EY1Y 1WEW DZCZ 6W7UEV NX)X MX8UEW DY 8~V L~V L~W M~V K~V M~V" + ",~P :Z JZ !Z Z !Z >Z !Z !Z \"Z :Z%['Y8ZIY(Z Z+Z Z-[![-[![-[![ I\\H[ I[JY0[(Y(Z#Z(Z$Z)Z#Z)Z 9Z 2| EY1\\ LY2Y " + "HZ2Y HZ3Y FY2Y GY2Y GY2Y-Z2X 1Y #Y Y Y Y 9Y Y NX Y 6Z.Y IX0X JY-Y KY.Z MZ.Z MY-Y KY.Z BYGX?Z KY1Y HY0X" + " GX0X GX0Y >YFZ >Y.Y AYFY 2W:X:X,W JW+XG\\F[FW+XF[1X,W JW =X (YEY 4~d GXHU 2kNRMk*tNq Mv Y 7ZIZ GY !Z A~e 9TBY `=Y(Y8ZJZ([\"[ Z " + ".[!Z$Z3Z KZ 7Y 9Z)Z CZGZ IZIW8WIZ M[AZ .Z 0\\ IX DX JY MY2Y FY.Y JY $Y/Z JY YEY CYIWBXIX @f 0YGZ 0[ LZ NX NY 'U>WMW?V&Z4Y AY/Y HY8Y" + " EZ.Y FZ %Y1Y Y CY1Y&[:Z:Z+ZAYAY HY9Y IY@X@Y LZ/Y NZ.Y 5Y 4Y0Y KZ.Z ?\\ *Z -['['\\AZB]&Z(Z K|![!Z)\\ 6" + "X 7\\ JVFXFV J[(\\ KUEXFU %Y 3Y?U -Z %YXCU *X EY1Y 1WEW" + " F[CZ 6X8UDV NW)X MX8UDW DY 8~W N~W L~W M~V L~W M~W-~P :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z%['Y8ZIY([\"[+[" + "\"[,Z![-[!Z,[!Z I\\F[ J[KY/Z'Z)Z#Z)Z#Z)Z#Z)Z 9Z 2{ DY0[ MY1Y HY1Y HY2Y FY2Y HZ2Y HY1Y-Y2Y 1Z $Y Y Y Z :Y Y" + " NX Y 6Z.Y IX0X JZ.Y KY.Z MZ.Y LZ.Y KY.Z BYHX>Z KY1Y HY1Y GX0X GX0Y =YGY =Y.Y AYFY 2X;X:W+X LX*WH\\D[HX" + "*WG[0W+X LX =X (YFZ 4~d GYIU 2jLQLj*pNRNq Lt :q AX.Y IY0Y CZ>Y 6YIZ FX !Z A~e 9T" + "BZ >W?W;W8Z2\\MY 4Y DY JX 4X 1Z1Z 3Z +\\ 6Z M~Z %Z HZ0Z 8[ 7Y.Z #Z )i D~d Ci -Z GV=W4XAW/~W M" + "Z-[\"[ $Z&[ NZ MZ .Z\"Z'Z(Z :Z \"Z 4Z?] 9Z 2Y=_=Y(Y8ZJZ([\"[ Z -Z\"[$Z3[ L[ 8Y 9Z)Z BZHZ IZJX8XJY LZ@[ /Z 1\\" + " HX DX JY NY1Y FZ0Z JY $Y/Z JY YEY BXJXAWJY A[N[ 1YGY 0[ JY NX NY 'V@WLX@U$Y5[ BY/Y HX7X DZ.Y FY $Y1Y Z " + "/Z K_MZ BUC]BVBU A[D[ >X #VBW=XDU *X EY1Y 1WEW G[D[ 5W8UCV X*X LW8UCW EZ 8~W N~X M" + "~W N~X M~W N~X.~Q :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z&[&Y7ZJY([\"[+[\"[,[\"Z+[#[+Z\"[ J\\D[ JZKX/['Z*[#[*Z#Z)Z#Z)Z" + " 9Z 2z CY/Z MY1Y HY2Z HY2Y GY1Y HY1Y HY1Y-Y2Z 2Z $Z !Z !Z !Z :Y Y NX Y 6Z.Y IX0X JZ/Z KY.Z LY.Y LZ/Z KY.Z " + " BYHW=Z KY1Y GX1Y GX1Y GX0Y =YHZ =Y/Z @YHY 1X;X;X*W LW)XJ\\B[IX*XI[0X*W LW Z 7ZJY EY !Z 1X@X &TAY ?X?W;W8Z1\\NX 3Y DY JX 5Y 0" + "Y1Z 3Z ,\\ 5Z M~Z %Z HZ0Z 8Z 6Y.Z #Z &i G~d Fi )X FV=X5XAW0~Y NZ-[!Z $Z&[ NZ MZ .[#Z'Z(Z :Z \"Z 4Z>] :Z 2" + "Y=_=Y(Y7ZKZ'Z#[ NZ -[#[$Z2[ M[ 8Y 9Z)Z BZHZ HYJX8XKZ M[?Z /Z 2\\ GX CX KY NY1Y FZ0Z JZ %Y/Z JZ =Y 4" + "Y0Z GY1Y 5Y NX 0XG\\ $Y FY3Y2Y+Y1Y JZ/Y IZ0Y MY/Y ;Y 8[ 8Y .Y1Y >ZGZ BYKXAXKY B[LZ 0YHY 1[ IY NX Z &VB" + "XKXBV$Y5[ BY/Y HX8Y CY/Z GY #Y1Y Z !Z !Z \"Z :Z&[&" + "Y7ZJY'[#Z)Z#[+[#[+[#[+[#[ K\\B[ K[MX.['Z*Z!Z*Z#Z)Z#Z)Z 9Z 2x AY.Z NY2Z HY2Z IY1Y GY1Y HY1Y HY2Z-X1Z 2Z $Z !Z !Z" + " !Z :Y Y NX Y 5Y/Z IX0X JZ/Z KZ/Y KY.Y LZ/Z KZ/Y AYIWW;W8Z0e 3Y EZ JX 5X /Z2Y 2Z -\\ 4Z M~Z %Z HZ0Z 8Z 6Z/Z $Z #j J~d Ii CW>X6Y" + "BX0~Y NZ-[![ %Z'\\ NZ MZ -Z#Z'Z(Z :Z \"Z 4Z=] ;Z 2Y<][ 0" + "Z 3\\ FX CX KY NY2Z FZ0Y IZ %Y/Z JZ =Y 4Y0Z GY1Y 5Y NX 0XF\\ %Y FY3Y2Y+Y1Y JZ/Y IZ0Y MY/Y ;Y 7Z 8Y" + " .Y2Z =YGY AYKW@XKY BZJZ 1YIY 1[ HY NX Y %WEYIYFW#Y5[ BY/Y HX8Y CY/Z GY #Y1Y ;XIY 6Y;Z EY1Y%Z:Z:Z*ZBYBZ " + "HY9Y IY@X@Y LZ/Y MY/Z 4Y 4Y2Y KZ,Z B[ 'Z +[+[#_FZF_$Z(Z Gt JZ$[%\\ 9X :\\ J\\IXI[ I\\/\\ K[HXI[ (Y 3Z@U -Z " + "%^F^ /Z X \"f >VBnCU >[D[ @X \"VCWZ !Z !Z \"Z :Z'[%Y6ZKY'[$[)[$[*[$[*[%[*[$[ K\\@[ Le.[&Z*Z!Z*Z\"Z*Z#Z*[ 9Z 2v " + "?Y.Z NY2Z HX1Z IY1Y GY1Y HY2Z HX1Z.Y1Z 1Y #Y Y Y Y :Y Y NX Y 5Y/Z IX0X IY/Z KZ/Y KY/Z KY/Z KZ/Y 7\\ 7ZKW" + ";Y IX1Y GX1Y GY2Y GY2Z YJX(XJY/X)X Y W;W7Y/c 2Y EY IX 5X /Z3Z 2Z .\\" + " 3Z M~Z &Z FY1Z 8[ 6Z/Z $Z i L~d Li @W>Y7YBW0Z*Y NZ-[![ %Z'[ MZ MZ -[$Z'Z(Z :Z \"Z 4Z<] Z !Z !Z \"Z :Z(\\%" + "Y6ZKY&[%[)\\&[)[%[)[%[)[%[ L\\>[ Ld.[&Z*Z!Z*Z\"Z+[\"Z+Z 8Z 2s YJY .X=X=Y(" + "X!X'YJWX.Y HY2Y CZW=X8ZC" + "W/Z*Z Z-Z N[ &Z(\\ MZ MZ -\\%Z'Z(Z :Z \"Z 4Z;] =Z 2Y<]Y 4Z2[ GY1Y 5Y NX 0XD\\ 'Y FY3Y2Y+Y1Y IY0Z IZ1Z MZ1Z ;Y 6Y" + " 8Y .Y2Z =ZIZ @XLX?WLY C[H[ 2YKZ 3[ EX NX Y $hFh\"Z7\\ BY0Y GX9Y BZ1Z FX \"Y1Y ;YKY 6Y9Y EY2Z%Z;[:Z*ZBYB" + "Y GY9Y IY@XAZ L[1Y LZ1Z 3Y 3Y3Y LZ*Z D[ &Z *[-[ aJZJa\"Z(Z Cl F\\'[\"\\ ;X <\\ F\\KXK\\ F\\3\\ H\\JXK\\ 'Y " + "2ZAU -Z 'z 1Z X Na ;V@jDV :ZCZ BX UDW;XIU 'X EY2Z 1WEW KZCZ 3X9U@V\"W*X LX9VAW H[ " + "8Z*Z\"Y)Y!Z*Z\"Z*Y!Z*Z\"Z*Z1Z3Z 8[ MZ !Z Z !Z >Z !Z !Z \"Z :Z(\\%Y5ZLY&[&['[&[([&[)\\'\\)[&[ L\\<[ Mc.[$Z,[!" + "[,[\"Z+Z!Z+Z 8Z 2n 7Y-Y NX1Z IY2[ IY2Z GY2Z HY2Z IY2[.Y2\\ 2Z $Z !Z !Z !Z ;Y Y NX Y 5Z0Y HX0X IZ1Z IY0Z KZ0" + "Y JZ1Z IZ1Z 7\\ 6YMX;Z IY3Z GY2Y GY2Y GY2Z ;YKY ;Z1Z >YJY .Y>X=X'Y#Y&XIU:UJY&YJU.X'Y#Y ;X &YJZ #Z JXLU" + " -dIQId%kKRKk El 2j >X.Y HY2Y CY;Z 7ZMZ BZ #Z 3X@X %TAX @WZ 2Y;[;Y(Y5ZMZ&\\([ LZ +['[\"Z0[ Z 7Y 8[,Z ?YKZ EYLX6XLY [:[ 2Z 5\\ DX BX LY NY3[ F[2Z HZ %Y1" + "[ IZ >Y 3Y2[ GY1Y 5Y NX 0XC\\ (Y FY3Y2Y+Y1Y IZ2Z H[2Z LY1Z ;Y 6Z 9Y .Y2Z Z !Z" + " !Z \"Z :Z)\\$Y5ZLY%[(\\'\\(['\\(['['['[(\\ M\\:[ Ma-[$Z,Z NZ,Z![,Z!Z,[ 8Z 2Z #Y-Y NX2[ IY2[ IY2Z GY3[ HX2[ IY2" + "[.Y2\\ 2Z $Z !Z !Z Y ;Y Y NX Y 5Z1Z HX0X IZ1Z IZ1Z JZ2Z JZ1Z IZ1Z 7\\ 6c:Z IY3Z GY3Z GY3Z GY3[ ;YKY ;[2Z =" + "YLY ,Y?X>Y&Y%Y%YIS8SJY$YJS.Y&Y%Y :X &ZKY #Z IYNU ,cISIb#jKRJi Cj 1i =X.Y GY4Y BY:Y 7ZMZ AZ " + " $[,P )W?X %TBY AXXMY DZDZ 2YLY 3[ DY X Y \"eCd NY8^ CY0Y GX:Y @Z2Z FX \"Y1Y :YMY 6Y7Y " + "FY2Z%[<\\a@V 7YBY CX NV LV BZ3Z 1WEW LYBY 2W8U?V#W+X KX9U" + "?W J[ 7Z(Y#Z)Z#Z(Z$Z)Z\"Y(Z$Z(Y2Z2Z 7\\\"P NZ !Z Z !Z >Z !Z !Z \"Z :Z*\\#Y4ZMY%\\)[%[)\\&[)\\'\\)\\'\\)[ M\\8" + "[ N`-[#Z,Z NZ,Z Z-[![-[ 8Z 2Z #Y-Y NX2[ IY2[ IY3[ GY3[ HY3[ HX2[.Y3^ 2Z $Z !Z !Z !Z ZMZ DZMW4WMZ![7Z 3Z 7\\ BX AX MY NY3" + "[ F\\4Z FZ &Z3\\ HZ ?Y 3Z4\\ GY1Y 5Y NX 0X@[ *Y FY3Y2Y+Y1Y HZ3Z H\\4Z KZ3[ ;Y 5Y 9Y -Y4[ ;YKY >YNX=WNY D[D[ " + "3YMY 3[ CY X Y !cAb MZ9^ CZ2Z GX:Y @Z3Z EX \"Y1Y :YMY 7Z7Y FZ4[$Z<\\Z !Z !Z \"Z :Z+]#Y4ZMY$[*\\%\\*[%\\+\\%\\+\\%\\+\\ N\\6[ N^-\\#[.[ N[.[ [.Z NZ-Z 7Z 2Z #Y-Y NY4\\ IY3" + "\\ IY3[ GY3[ HY4\\ HX3\\.Y3^ 2Z $Z !Z !Z !Z i i 2WZ4" + "Z EY #Y1Y 9XNZ 7Y6Z GZ4[$Z=]=['ZDYDZ FY9Y HZBXBZ K]5Z J[5[ 2Y 2Z7Y L[(Z H[ #Z '\\5[ F~ LZ(Z :Z :\\-\\ KW :X :" + "V >r >V/V @s #Z 2[CU -Z +[MeL[ 5Z X G\\ :W!V 3W@W 7V!W AZ4[ 1WEW LW@W 1W7s,X-" + "Y JX8t$\\ 7Z'Z%Z'Z$Z'Y%Z'Z$Z'Y%Z'Z4Z1Z 6\\&S NZ !Z Z !Z >Z !Z !Z \"Z :Z,]\"Y3ZNY$\\,\\#\\,\\$\\,\\$\\-\\$\\," + "\\ N\\4[ ]-\\![/Z LZ/[ N[/[ N[/[ 7Z 2Z #Y-Y NY4\\ HY5] IY4\\ GY4\\ HY4\\ HY4\\.Z5` 2Z $Z !Z !Z !Z =Y Y NX Y " + "3Z4Z GX0X H[5[ GZ4Z GZ4Z H[5[ GZ4[ 6\\ 5_9[ HZ5[ GZ5[ FY5[ FY5\\ :YNZ :\\4Z ;YNY )YAXAZ\"Z+Z!Z*Y Y*Z\"Z+Z 8" + "X $YMY %[ F^ '\\FSF\\ LcGRGc >f ,c :X.Y FZ7Y BY8Y 7e >[ %[1S -Y 'X@X ;Q:TCZ CX:X=X" + "5[.] /Y HY HX NZ GZ 'X +[8Z 0Z 4\\ 0[ 'Z M\\ CZ6[ 9Z 2[3[ '[ 0Y Y ?f f BX DW=\\C_J[.Z&Z\"Z0\\ " + "J\\(T'Z._ JZ MZ *])Z'Z(Z :Z \"Z 4Z6] BZ 2Y JY(Y3e#\\.\\ JZ )]/\\ NZ.[ NQ'[ 6Y 6[0[ =ZNZ CYNX4XNY!Z4[ 5Z 8[ @X" + " AX MY NY5] F]6Z DZ &Z5] G[ AY 2[8^ GY1Y 5Y NX 0X>[ ,Y FY3Y2Y+Y1Y H[6[ G]6Z IZ5\\ ;Y 6Y 8Y -Z6\\ ;Z" + "MZ =b=b EZ@Z 3d 5[ AY X Y L[:\\ IZ;` D[4Z FXZ5[ EY #Y1Y 9c 7Z5Y GZ5\\$[>^>['[EYE[ FY9Y HZBXCZ J]5Z " + "IZ5Z 1Y 1Y8Z LZ&Z J[ \"Z &\\8] E| KZ(Z :Z :]/] JU 9X 9T

q \"Z 1ZCU -Z ,[JaI[ 6Z X F\\ :W#V 1" + "V?V 7W#W @[5[ 1WEW LV?V 1X7s,W-Y JX7t%\\ 6Z&Z&Z'Z%Z&Z&Z'Z%Z&Z&Z&Y4Y0Z 5\\(T NZ !Z Z " + "!Z >Z !Z !Z \"Z :Z.^!Y3e#\\.\\!\\.\\#].\\#]/]#\\.\\ N\\2[ ]/]![0[ L[0[ M[0[ N\\1[ 6Z 2Z #Y-Y NY5] HY5] IZ6] GY" + "5] HY5] HY5]-Y5a 3[ %[ \"[ \"[ \"[ >Y Y NX Y 3Z5[ GX0X GZ5Z F[6[ G[6[ GZ5Z F[5Z 5\\ 4^9Z FY6\\ FY6\\ FY6\\ " + "FY6] 9c 9]6Z :d )[CXBZ Z-Z NZ-[ [-Z Z-Z 7X $YNZ %Z D] $VCSDW G`FSG` ;d +c :X.Y F[9Z CZ8Y 6d =\\ " + " '\\3T -Z (W?X ;Sd c @Z EW<_Ks-Z&Z\"Z1] J^,V'Z/_ IZ MZ )]*Z'Z(Z :Z \"Z 4Z5] CZ 2Y JY(Y2d#]0\\ IZ (]1] NZ-" + "Z NS*\\ 6Y 6[1[ Z 4c 5[ @Y X Y HS3V FZZ%ZEYF[ EY9Y GZCXD[ J^7Z H[7[ 1Y 1Z:Z KZ&Z K[ !Z %];] Bx IZ(Z :Z 9]1] HS 8X 8R :n :R+R U 6W%W ?[6\\ 1WEW LU>U 0W6s-X.X HW6t&\\ 5Z&Z'Z" + "%Z&Z&Z'Z%Z&Z&Z&Z&Z6Z0Z 4],V NZ !Z Z !Z >Z !Z !Z \"Z :Z0`!Y2d\"\\0]!]0\\!]0\\!]1]!]1] \\0[ ]1] N[2\\ L\\2[ L\\" + "2[ L[1[ 6Z 2Z #Y.Y MZ7^ HY6^ HY6] GZ6] HZ7^ HZ7^-Y6c 3[ %[ \"[ \"[ \"[ ?Y Y NX Y 3[7[ FX0X G[7[ E[7[ FZ7[ F" + "[7[ E[7[ 5\\ 4]9[ FZ8] FZ8] FZ8] FZ7] 9c 9]7[ 9b '[DXD[ N[/Z LZ/[ M[0[ N[/Z 6X $d %Z C\\ ?S 2\\ETD" + "\\ 9b )a 9X.Y E[<[ BY7Z 7c ;\\ '\\5U -Z (W?W :U>TE[ CX8X?X3\\3b 1Y IY GX NZ GZ (" + "X )[;[ /Z 5[ %Q-\\ &Z BQ/] AZ9\\ 9Z 0[6\\ (\\ /Z \"[ ;a ` =Z EX[ 4b 6[ ?Y X Y " + "FZ=b E]7Z EX=Z <[9\\ D[ %Y1Y 8a 6Y3Y H\\8]#[@WNW@[%[FYG\\ EY9Y G[DXD[ J_9[ G[9[ /Y 1Z;Z LZ%Z L\\ !Z $]=\\ >t GZ" + "(Z :Z 8]3] FQ 7X 7P 8l 8P)P :m Z 0[EU -Z .[?P?[ 8Z X D[ 9W(W -T\\8] 1WEW " + " LSZ !Z !Z \"Z :Z2a Y2d\"^3] N]3^ ]3" + "] N]3] N]3] \\.[!^3] M\\4\\ J\\4\\ K\\4\\ L\\4\\ 5Z 2Z #Y.Y MZ8_ HZ8_ HZ8^ FZ8^ HZ8_ HZ8_-Z8e-Q)\\ &\\-Q G\\-Q " + "G\\-Q G\\-Q 5Y Y NX Y 2[9\\ FX0X F[9[ D\\9[ E[8[ E[9[ D\\9[ 4\\ 3[9[ EZ9^ FZ9^ FZ9^ F[9^ 9b 8^9[ 8b &[2[" + " L\\3\\ K[2[ K[2[ L\\3\\ 6X #c &Z B\\ ?S /UATAT 4a '_ 8X.Y E\\>\\ BY6Y 7c :] (\\7V " + "-Z )X@X :W@TF[ BW7X?X3]6e 1X IY GX NZ GZ (X ([=[ .Z 6[ $S1^ &Z BS3^ @\\<\\ 8Z 0]9] FR6] .Z \"[ 8^ " + " ^ ;Z DW;lMc+Z$Z#Z4_ G_2Y'Z5c GZ MZ '^/\\'Z(Z :Z \"Z 4Z3] EZ 2Y JY(Y1c!^6^ HZ '^6^ LZ,Z X1] 5Y 5]6\\ :c Ab2a" + "\"Z0[ 7Z ;\\ >X @X NY MZ:` F_:[ B\\3P D[;` E\\1S 7Y 0\\>a GY1Y 5Y NX 0X;\\ 0Y FY3Y2Y+Y1Y F[:[ E_;\\ " + "F[;_ ;Y *S1Y 6Z .[;_ :e ;`;` G[<[ 5a 6[ >Y X Y F[?YNY F_:[ DX?Z :[;\\ B[ &Y1Y 8a 7Z3Y H]:^#\\BXNWA[#[" + "GYH\\ DY9Y F\\FXF\\ I`;[ F\\;\\ /Z 2[=Z KZ$Z N\\ Z #^A] :n DZ(Z :Z 7]5] +X Mj (k NZ 0\\FUBP ;Z /[,[ " + "9Z X CZ 8X+W *R;R 4X+X =]:^ 1WEW LR;R /X5s.W.X GW5t(\\ 4Z$Z(Z%Z'Z$Z(Z$Y'Z$Z(Z$Z" + "8Z/Z 3_2Y NZ !Z Z !Z >Z !Z !Z \"Z :Z5c NY1c!^6^ L^6^ M^6^ M]5] M^6^ \\,[#a7^ K\\6] I\\6\\ J]6\\ J\\6] 5Z 2Z #" + "Y/Z LZ:` H[:` H[:_ FZ:` GZ:` GZ:`-[:YN\\0S(\\4Q C\\0S F\\0S F\\0S F\\0S 5Y Y NX Y 1[:[ EX0X F\\;\\ C\\;[ C[:" + "[ D\\;\\ C\\;\\ 4\\ 3[:\\ DZ;_ EZ;_ EZ;_ EZ;` 8a 8_;\\ 7a %\\6\\ J\\5\\ I\\6\\ I\\6\\ J\\5\\ 5X #c 'Z " + "@[ @T JT _ %] 7X.Y D^D^ BZ6Y 6b 9_ *];X -Z )X@X :ZCTH] CX7YAX1^:h 2Y JY GX NZ" + " GZ (X (\\?\\ .Z 7\\ $W7_ %Z BV8` ?\\>] 9[ /];] ET9] -Z \"[ 5[ [ 8Z DX;jLb*Z$Z#Z7a E`7\\'Z9f FZ MZ &`4^" + "'Z(Z :Z \"Z 4Z2] FZ 2Y JY(Y1c _:_ GZ &_9^ KZ,[![6^ 4Y 4]9] 8b @a2a#[/Z 7Z ;[ =X @X NY M[\\ @]7R" + " D\\=a E]4U 7Y /]Bc GY1Y 5Y NX 0X:\\ 1Y FY3Y2Y+Y1Y E\\>] E`=\\ E\\=` ;Y *U5[ 6[ /\\>a 9c :_:` GZ:Z 4` 6[ >Y " + "X Y E[AYMZ G`<[ CX@Z 9\\=\\ A\\3Q EY1Y 7` 7Y2Z I^<_\"[BWMXC\\#]IYI\\ CY9Y F]GXG] Ia=\\ E\\=\\ .[ 2[?Z J" + "Z$Z N[ NZ \"^C^ 7g @Z(Z :Z 7_9_ +X Lh &i MZ /]HUDR ;Z .Y*Y 8Z X BZ 8Y/X (Q:Q 2X/Y " + " <^<` 2WEW LQ:Q .W MV(X/X GX NW\"\\ 3Z$Z)Z#Z(Z$Z)Z#Z(Z$Z)Z#Z8Z/Z 2`7\\ NZ !Z Z !Z >Z !Z !Z \"Z :" + "Z9f MY0b _:_ J_:_ K_:_ L_9_ L_9^ N[*[$c:^ J^:^ H^:^ I^:] H]9] 4Z 2Z #YIP7[ L[] C\\=\\ A\\=\\ 3\\ 2\\=\\ C[=` E[=` E[=" + "` E[=a 8a 8`=\\ 6` #]:] H]9] G]:] G]:] H]9] 4W !a 'Z ?Z ?U KT N] $] 7X.Y Cv AZ6Z 7a 7a " + " -_?Z -Z )W?X :^GTK_ CX5XAX0_>k 3Y JX FX NZ GZ )Y ']C] ?} I~S IZ=b %Z BZ>a =]B^ 8Z ._?^ DX" + "@_ ,Z \"[ 3Y X 5Z CW:gJ`)Z\"Z$~T Cb=_'~W E~S FZ %b:a'Z(Z :Z \"Z 4Z1] G~Q)Y JY(Y0b N`>` FZ %a?` JZ+Z!^_ 8b @a2a$[.[ 8Z <~` AX ?X Y L\\@c Fb@] ?^` H`>` I`>` Ja?a Ja?` LY(Y$f?` H_>_ F_>_ G_>_ H_>" + "_ 3Z 2Z #YIS;[ K\\?c G\\?c G\\?b E\\@c F\\@c G\\?c,\\?[L^9Y'^} I~S I~ $Z B| ;^F_ 7Z -aEa Dv +Z \"[ 0V U 2Z CX9dI^'Z\"Z$~S AfGd'~U C~S FZ $gGg&Z(Z :Z \"Z 4Z0] H" + "~Q)Y JY(Y0b McGd EZ $dGc IZ+[\"cEd 3Y 3cGc 7a ?`1a$Z,[ 9Z =~a AX ?X Y L^DZNY FYNZF_ =`CY B^EZNY CaB] 7" + "Y .qMY GY1Y 5Y NX 0X8\\ 3Y FY3Y2Y+Y1Y D_F_ CYNYE_ B^EZNX ;Y *]A^ 4k >^G[NY 8a 9_9^ H[8[ 5^ 6~P 2Y X Y " + " D^H[La NfH` AYD[ 6^E_ ?`?X EY1Y 7_ 7Y0Y IcFk(]HZLZI^ `Nk BY9Z E~Q GYNZE^ B_E_ ,e ;]G] J~c!~T FZ 3oDo @Z :Z(Z :" + "Z 5dGd )X Jd \"e KZ -`MUKY H~U IU&U 6Z X AY 5Z7Z LZ7Z ;~d 3cFk 8WEW " + " BW LV)X0X FW LW$\\ 2Z\"Z+[#Z)Z\"Z*Z\"Z*Z\"Z*Z\"Z:Z.~T*fGd N~T J~T I~S I~S 7Z !Z !Z \"Z :~U JY/a MdGc FcGd GcGd" + " HdGd HdGc JW&W$kGc FbFb DbFb FcFb FcGc 3Z 2Z #YIWB] I^DZNY F]D[NY F]D[NX E^DZNY F^DZNY F^E[NY+]D]J`@]&`BY AaA]" + " DaA] DaA] DaA] 5Y Y NX Y /_F_ CX0X D_E_ ?_F_ ?_F_ @_E_ ?_F_ 7aF_ @^FZMX D^FZMX D_GZMX D_G[NY 7_ 7YNYE_ 4^" + " dLd CdMd BdLd CdLd DeMd 2X !` %X =Y ?U LV MZ !Y 5X.Y As AZ4Y 6` 5~] )x -Z " + "*X@X 9} BX3YFZ-{L] 4Y LY FX NZ GZ )X $t >} I~S I} #Z B{ :v 7[ ,{ Cu *Z \"[ -S S 0Z BW8aG[%[\"Z$~R" + " ?~S'~T B~S FZ #~V%Z(Z :Z \"Z 4Z/] I~Q)Y JY(Y/a L~ DZ #~ HZ*Z\"~R 2Y 2} 5` ?`0_$[+Z 9Z =~a AX ?X Y KsN" + "Y FYNr ;u AqMY B{ 7Y -oLY GY1Y 5Y NX 0X7\\ 4Y FY3Y2Y+Y1Y Cv BYNr ArMX ;Y *y 2j >qMY 8a 8^9^ I[6Z 5^ 6~P 2Y X " + " Y CpK` N} ?YF[ 5w =x EY1Y 6] 7Z0Z J~Y(nJm M{ AY9\\ F~ FYMq @w *d ;r J~d!~T FZ 3oDo @Z :Z(Z :Z 4~ 'X " + " Ib c JZ ,u H~U HS$S 5Z X AY 4\\>\\ I]>\\ :~d 3~Y 8WEW CW KV)W0X FX LW" + "$[ 2[\"Z+Z!Z*Z\"Z+Z!Z*Z!Z,Z!Z:Z.~T)~S N~T J~T I~S I~S 7Z !Z !Z \"Z :~T IY/a L~ D~ E~ F~ E~ HU$U$~X D| B| D} D} " + "2Z 2Z #YIr HrMY FsMY FsMX DsNY ErMY FsMY+uH|%v @| C| C| C| 5Y Y NX Y .v BX0X Cw =w >v >w =w 8{ ?qMX CqMX C" + "qMX CqMY 6] 6YNr 3^ My Ay @y @z Ay 1X _ $V X !" + "Y JqMY FYMp 9t ApLY Az 7Y ,mKY GY1Y 5Y NX 0X6\\ 5Y FY3Y2Y+Y1Y Bt AYMp ?pLX ;Y *x 1j =oLY 8a 8]8^ IZ4Z 6" + "] 5~P 2Y X Y CoI_ N} ?[K] 3u ;w EY1Y 6] 7Y.Y JvM_'mJm Ly @Y9b K| EYLp ?u (c :p I~e\"~T FZ 3oDo @Z :Z(Z" + " :Z 2{ &X H` Ma IZ +t H~U GQ\"Q 4Z X AY 2aLb FaKa 8~d 3YNlN_ 8WEW " + "DX KV*W0o-W KW%[ 1Z Z,Z!Z+Z Z,Z!Z+Z Z,Z!Z;Z-~T'~P M~T J~T I~S I~S 7Z !Z !Z \"Z :~R GY.` K| B| C{ B{ B{ FS\"S$YM" + "{ Bz @z B{ B{ 1Z 2Z #YIq GqLY EqLY EqLX CqMY ErMY EqLY*sF{$u ?{ B{ B{ B{ 5Y Y NX Y -t AX0X Bu ;u pLX CpLX CpLX BoLY 6] 6YMp 1] Lv >w =v =v >w 0X _ #T ;X ?W MV LW LV 4X.Y ?n >Y3Z 7_ 1~Z " + " 't +Z *W?X 8y @X1j)vG] 5X MY EX NZ GZ *X !p <} I~S Iz Z By 6r 5Z )w As (Z \"[ " + " 5Z AX HZ Z%~ 9|$~P >~S FZ ~P\"Z(Z :Z \"Z 4Z-] K~Q)Y JY(Y.` Jy AZ x EZ)Z#~P 0Y /x 3_ =_0_%Z([ ;Z =~a AX " + ">X !Y JpLY FYLn 7s @nKY @y 7Y +kJY GY1Y 5Y NX 0X5\\ 6Y FY3Y2Y+Y1Y Ar @YLn =nKX ;Y *w /i x ?x @y 0Z 2Z #YIp EoKY DoKY DoKX BoLY DpLY DoKY)qCy#t =y @y @y @y 5Y Y NX Y ,r @X0X As 9s :r :s 9s 7z <" + "nKX BnKX BnKX BnKY 6] 6YLn 0\\ Jt ;s :t ;t ;s .X N] !R 9V >W NX LU KU 3X.Y >l =Y2Y 7_ /~X " + " %p )Z *W?W 4u @X/i(tE] 6Y NX DX NZ GZ *X m :} I~S Iy NZ Bw 2o 5Z 'u @r 'Z \"Z " + " 4Z AY J[ Z%} 6x\"} <~S FZ N| Z(Z :Z \"Z 4Z,] L~Q)Y JY(Y.` Hv @Z Mu DZ)[$~ /Y .u 0^ =^/_&['Z ;Z =~a AX >X" + " !Y InKY FYKl 5r ?lJY >w 7Y )hIY GY1Y 5Y NX 0X4\\ 7Y FY3Y2Y+Y1Y @p ?YKl ;lJX ;Y *v -h ;kJY 7_ 7]7\\ J[2" + "[ 7\\ 5~P 2Y X Y AkE] Nz :i .p 7u EY1Y 5[ 7Y,Y KYMiL_%iGj Hu >Y8a Hv BYJl :p $a 7k H~f\"~T FZ 3oDo @Z " + ":Z(Z :Z /u #X F\\ I] GZ )r H~U *Z X AY /p >o 4~d 3YMiK^ 8WEW EX " + "JV+W/o/X JW&Z 0[ Z-Z NZ-[ [.Z NZ,Z NZ.Z NZ=Z,~T$x I~T J~T I~S I~S 7Z !Z !Z \"Z :| BY-_ Hv p %Z \"Z " + " 4Z @X JZ MZ&{ 3u z 9~S FZ Lx MZ(Z :Z \"Z 4Z+] M~Q)Y JY(Y-_ Fr >Z Lr BZ(Z!y -Y -s /] <^.]&[&[ m >YJj 8iIX ;Y *u *f :iIY 7_ 6\\7" + "\\ K[0Z 6Z 4~P 2Y X Y ?hC\\ NYMm 8f +m 3s EY1Y 5[ 8Z,Y KYLgJ^$gEh Fs =Y8a Fr @YIi 7m !` 6i G~g#~T FZ 3o" + "Do @Z :Z(Z :Z .s \"X EZ G[ FZ 'p H~U *Z X AY ,k :k 2~d 3YLgJ^ 8WEW " + " EW IV,X/o/W IW&Z 0Z MZ/[ NZ-Z MZ.Z N[.Z MZ.Z MZ>Z,~T\"t G~T J~T I~S I~S 7Z !Z !Z \"Z :y ?Y-_ Fr 8r 9r :s :r " + " AXEr :r 8r :s :s -Z 2Z #YIn AkIY BkIY BkIX @jIY BkIY BkIY'l=t Mq :t ;t ;t ;t 3Y Y NX Y *m =X0X >m 3m 5n 5m" + " 3m 6XLm 7iHX @iHX @jIX @jIY 5[ 5YJj -Z El 3k 2l 3l 4l *X N\\ 5U ?Y Y KR HQ 1X.Y 9b 9Y1Z 7" + "] )~S \"j &Z +X@X -h ;X+c!l?\\ 6X Y DX Z FZ +X Kh 8} I~S Fr JZ As ,i 3[ $n ;m " + "#Z \"Y 3Z ?X KZ MZ&x -p Mu 4~S FZ Js JZ(Z :Z \"Z 4Z*] N~Q)Y JY(Y-_ Dn gB[ NYLj 5d (j 0q EY1Y 5Z 7Y+Z LYKdG]\"dBd Bo ;Y7` Dn >YHg 4i L^ 4e " + "E~g#~T FZ 3oDo @Z :Z(Z :Z ,n NX DX EY EZ %m G~U *Z X BZ )e 4e /~d 3YKeH] 8" + "WEW FW HV,W.o0X IW'Z /Z MZ/Z LZ.Z MZ/[ MZ.Z MZ/[ MZ>Y+~T p E~T J~T I~S I~S 7Z !Z !Z \"Z :u ;Y,^ Dn 4" + "n 5n 6o 6n @XBm 5n 4n 6o 6o +Z 2Z #YIl =gGY AhGY AhGX ?hHY @hHY @gGY%i:o Hm 7p 6o 6p 7p 1Y Y NX Y (i ;X0X " + "fGX >fGX >fGY 4Y 4YHf +Z Bg /g .g -g /g (X M[ 5T ?Z !Z JP 'X.Y 5" + "[ 6Y0Y 7] &~P Ne $Z +W?X '] 6W)a Mh<\\ 7Y !X CX Y EZ +X Id 6} I~S Cm HZ =l 'e " + "1Z i 6h !Z #Z 3Z ?Y M[ M['s &k Jo .~S FZ Gm GZ(Z :Z \"Z 4Z)] ~Q)Y JY(Y,^ Bi 9Z Gl AZ'Z Jm (Y (i )\\ " + ";].]'[#Z =Z =~a AX =X \"Y DdFY FYFb *h 6cFY 8j 0Y \"YAY GY1Y 5Y NX 0X1\\ :Y FY3Y2Y+Y1Y ;f :YFb 1cFX ;Y" + " $k ` 7cFY 6] 5[5Z KZ-[ 8Y 3~P 2Y X Y ;b=X NYJe 0` $e +l BY1Y 4Y 7Y*Y LYIaE[ b@a >k 9Y6_ Ah ;YFc 0e " + "FZ 2a D~i$~T FZ 3oDo @Z :Z(Z :Z )i LX CV CW DZ #h D~U *Z X -R9Z #[ *[ *~d 3" + "YIaE\\ 8WEW GX HV-W-o0W HW'Z 0Z L[0Z LZ/[ LZ0Z LZ/[ LZ0Z LZ?Z+~T Lj B~T J~T I~S I~S 7Z !Z !Z \"Z :o " + "5Y,^ Ai /h 0i 0i 0i >W?i 1j 0j 1j 1i (Z 2Z #YGh 9cEY ?dEY ?dEX =dFY >dFY >cEY#d5j Ch 1j 1j 1j 1j -Y Y NX Y" + " &e 9X0X :e ,f -f -e ,f 4XFe 0cEX a NU CZ N` 9X -T<[ " + " LYG]BX 5WEW %U HW NX MX GZ (d +b (b )b )a )b 9V;a " + ")c *c *c *c =a 4_ &^ %^ $^ &_ &_ :_/c RM] !R Z 5\\ " + " 9X ;X $Y HY NY 0Y 'X NY BY X !Y " + ":Y 8Y 4Y *Y 1Y EX 3Y CZ IU 3X -p " + " IY 8WEW #V &Z MV " + " 0U 'P ;Y 2Y >Z 8X " + " MT *X &X 9X DX " + " 5X ?\\%W ?Z 4\\ :X ;X $Y " + " IZ NY 0Y 'X NY BZ !X !Y :Y 8Y 4Y *Y 1Y EX 3Y " + " CZ IU 3X -o HY 8WEW \"V " + " 'Z LU 0V " + " CZ 2Y >Y 7X " + " MT )X 'X 9X DX 5W <\\(X ?" + "Z 3\\ ;Y e GX 2f KZ LY 0Y 'X !Y >" + "\\ %X &] 9Y 8Y 4Y *Y 1Y EX 3Y CZ IU 3" + "X $^ @Y 8WEW !V '\\:V ;V " + " 1W GZ 0Y @Z " + " FWHX LT 'X +W 7W " + " V 5b?c A[ -\\ ?e !f " + " f /X 0g 9Y 8Y 4Y *Y " + " 1Y EX 3Y CZ IU 3X 5Y " + " NV &\\=X ;V " + "1W GY /Y AZ EWHX " + " LT &W ,X 7V V 3~T " + " A] ,\\ @e !f d " + " %e -Y Nd @c " + " (m @c " + " +u $b -Y 'X 0d 2^ /X 0_ 1Y 8Y 4Y *Y " + " 1Y EX 3Y CZ IT 2X 5Y " + "-c !q Hd >c " + " $d ,Y Nd ?b " + " %g =" + "b *t #a ,Y 'X 0d " + " ,X /X 0Y +Y 8Y 4Y *Y 1Y EX 3Y CZ '" + "X 5Y -c Nm Fc " + " =c $c +Y Nc " + " >a " + " M\\ 8a \"~Y 1" + "r !` +Y 'X 0c 1X 1Y 8Y 4Y *Y 1Y EX 3Y " + " CZ &W 5Y -b Lj " + " Db std::printf(). + \note If configuration macro \c cimg_strict_warnings is set, this function throws a + \c CImgWarningException instead. + \warning As the first argument is a format string, it is highly recommended to write + \code + cimg::warn("%s",warning_message); + \endcode + instead of + \code + cimg::warn(warning_message); + \endcode + if \c warning_message can be arbitrary, to prevent nasty memory access. + **/ + inline void warn(const char *const format, ...) { + if (cimg::exception_mode()>=1) { + char *const message = new char[16384]; + std::va_list ap; + va_start(ap,format); + cimg_vsnprintf(message,16384,format,ap); + va_end(ap); +#ifdef cimg_strict_warnings + throw CImgWarningException(message); +#else + std::fprintf(cimg::output(),"\n%s[CImg] *** Warning ***%s%s\n",cimg::t_red,cimg::t_normal,message); +#endif + delete[] message; + } + } + + // Execute an external system command. + /** + \param command C-string containing the command line to execute. + \param module_name Module name. + \return Status value of the executed command, whose meaning is OS-dependent. + \note This function is similar to std::system() + but it does not open an extra console windows + on Windows-based systems. + **/ + inline int system(const char *const command, const char *const module_name=0, const bool is_verbose=false) { + cimg::unused(module_name); +#ifdef cimg_no_system_calls + return -1; +#else + if (is_verbose) return std::system(command); +#if cimg_OS==1 + const unsigned int l = (unsigned int)std::strlen(command); + if (l) { + char *const ncommand = new char[l + 24]; + std::memcpy(ncommand,command,l); + std::strcpy(ncommand + l," >/dev/null 2>&1"); // Make command silent + const int out_val = std::system(ncommand); + delete[] ncommand; + return out_val; + } else return -1; +#elif cimg_OS==2 + PROCESS_INFORMATION pi; + STARTUPINFOA si; + std::memset(&pi,0,sizeof(PROCESS_INFORMATION)); + std::memset(&si,0,sizeof(STARTUPINFO)); + GetStartupInfoA(&si); + si.cb = sizeof(si); + si.wShowWindow = SW_HIDE; + si.dwFlags |= SW_HIDE | STARTF_USESHOWWINDOW; + const BOOL res = CreateProcessA((LPCSTR)module_name,(LPSTR)command,0,0,FALSE,0,0,0,&si,&pi); + if (res) { + WaitForSingleObject(pi.hProcess,INFINITE); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return 0; + } else { + char* lpMsgBuf; + + // Get the error message. + DWORD errorCode = GetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0,errorCode,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPSTR)&lpMsgBuf,0,0); + cimg::warn("cimg::system() : Command '%s' (module name '%s) failed with error %lu: %s", + module_name==0?"(null)":module_name, + command==0?"(null)":command, + errorCode,lpMsgBuf); + return -1; + } +#else + return std::system(command); +#endif +#endif + } + + //! Return a reference to a temporary variable of type T. + template + inline T& temporary(const T&) { + static T temp; + return temp; + } + + //! Exchange values of variables \c a and \c b. + template + inline void swap(T& a, T& b) { T t = a; a = b; b = t; } + + //! Exchange values of variables (\c a1,\c a2) and (\c b1,\c b2). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) { + cimg::swap(a1,b1); cimg::swap(a2,b2); + } + + //! Exchange values of variables (\c a1,\c a2,\c a3) and (\c b1,\c b2,\c b3). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3) { + cimg::swap(a1,b1,a2,b2); cimg::swap(a3,b3); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a4) and (\c b1,\c b2,...,\c b4). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4) { + cimg::swap(a1,b1,a2,b2,a3,b3); cimg::swap(a4,b4); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a5) and (\c b1,\c b2,...,\c b5). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4); cimg::swap(a5,b5); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a6) and (\c b1,\c b2,...,\c b6). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5); cimg::swap(a6,b6); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a7) and (\c b1,\c b2,...,\c b7). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6); cimg::swap(a7,b7); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a8) and (\c b1,\c b2,...,\c b8). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7, T8& a8, T8& b8) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7); cimg::swap(a8,b8); + } + + //! Return the endianness of the current architecture. + /** + \return \c false for Little Endian or \c true for Big Endian. + **/ + inline bool endianness() { + const int x = 1; + return ((unsigned char*)&x)[0]?false:true; + } + + //! Reverse endianness of all elements in a memory buffer. + /** + \param[in,out] buffer Memory buffer whose endianness must be reversed. + \param size Number of buffer elements to reverse. + **/ + template + inline void invert_endianness(T* const buffer, const cimg_ulong size) { + if (size) switch (sizeof(T)) { + case 1 : break; + case 2 : { + for (unsigned short *ptr = (unsigned short*)buffer + size; ptr>(unsigned short*)buffer; ) { + const unsigned short val = *(--ptr); + *ptr = (unsigned short)((val>>8) | ((val<<8))); + } + } break; + case 4 : { + for (unsigned int *ptr = (unsigned int*)buffer + size; ptr>(unsigned int*)buffer; ) { + const unsigned int val = *(--ptr); + *ptr = (val>>24) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | (val<<24); + } + } break; + case 8 : { + const cimg_uint64 + m0 = (cimg_uint64)0xff, m1 = m0<<8, m2 = m0<<16, m3 = m0<<24, + m4 = m0<<32, m5 = m0<<40, m6 = m0<<48, m7 = m0<<56; + for (cimg_uint64 *ptr = (cimg_uint64*)buffer + size; ptr>(cimg_uint64*)buffer; ) { + const cimg_uint64 val = *(--ptr); + *ptr = (((val&m7)>>56) | ((val&m6)>>40) | ((val&m5)>>24) | ((val&m4)>>8) | + ((val&m3)<<8) |((val&m2)<<24) | ((val&m1)<<40) | ((val&m0)<<56)); + } + } break; + default : { + for (T* ptr = buffer + size; ptr>buffer; ) { + unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T); + for (int i = 0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe)); + } + } + } + } + inline void invert_endianness(bool* const, const cimg_ulong) {} + inline void invert_endianness(unsigned char* const, const cimg_ulong) {} + inline void invert_endianness(char* const, const cimg_ulong) {} + + //! Reverse endianness of a single variable. + /** + \param[in,out] a Variable to reverse. + \return Reference to reversed variable. + **/ + template + inline T& invert_endianness(T& a) { + invert_endianness(&a,1); + return a; + } + + // Conversion functions to get more precision when trying to store unsigned ints values as floats. + inline unsigned int float2uint(const float f) { + int tmp = 0; + std::memcpy(&tmp,&f,sizeof(float)); + if (tmp>=0) return (unsigned int)f; + unsigned int u; + // use memcpy instead of assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&u,&f,sizeof(float)); + return ((u)<<2)>>2; // set sign & exponent bit to 0 + } + + inline float uint2float(const unsigned int u) { + if (u<(1U<<19)) return (float)u; // Consider safe storage of unsigned int as floats until 19bits (i.e 524287) + float f; + const unsigned int v = u|(3U<<(8*sizeof(unsigned int)-2)); // set sign & exponent bit to 1 + // use memcpy instead of simple assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&f,&v,sizeof(float)); + return f; + } + + //! Return the value of a system timer, with a millisecond precision. + /** + \note The timer does not necessarily starts from \c 0. + **/ + inline cimg_uint64 time() { +#if cimg_OS==1 + struct timeval st_time; + gettimeofday(&st_time,0); + return (cimg_uint64)st_time.tv_sec*1000 + (cimg_uint64)st_time.tv_usec/1000; +#elif cimg_OS==2 + ULARGE_INTEGER ul; + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + ul.LowPart = ft.dwLowDateTime; + ul.HighPart = ft.dwHighDateTime; + return (cimg_uint64)ul.QuadPart/10000; +#else + return 0; +#endif + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_uint64 tictoc(const bool is_tic); + + //! Start tic/toc timer for time measurement between code instructions. + /** + \return Current value of the timer (same value as time()). + **/ + inline cimg_uint64 tic() { + return cimg::tictoc(true); + } + + //! End tic/toc timer and displays elapsed time from last call to tic(). + /** + \return Time elapsed (in ms) since last call to tic(). + **/ + inline cimg_uint64 toc() { + return cimg::tictoc(false); + } + + //! Sleep for a given numbers of milliseconds. + /** + \param milliseconds Number of milliseconds to wait for. + \note This function frees the CPU resources during the sleeping time. + It can be used to temporize your program properly, without wasting CPU time. + **/ + inline void sleep(const unsigned int milliseconds) { +#if cimg_OS==1 + struct timespec tv; + tv.tv_sec = milliseconds/1000; + tv.tv_nsec = (milliseconds%1000)*1000000; + nanosleep(&tv,0); +#elif cimg_OS==2 + Sleep(milliseconds); +#else + cimg::unused(milliseconds); +#endif + } + + inline unsigned int wait(const unsigned int milliseconds, cimg_uint64 *const p_timer) { + if (!*p_timer) *p_timer = cimg::time(); + const cimg_uint64 current_time = cimg::time(); + if (current_time<*p_timer || current_time>=*p_timer + milliseconds) { *p_timer = current_time; return 0; } + const unsigned int time_diff = (unsigned int)(*p_timer + milliseconds - current_time); + *p_timer = current_time + time_diff; + cimg::sleep(time_diff); + return time_diff; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \return Number of milliseconds elapsed since the last call to wait(). + \note Same as sleep() with a waiting time computed with regard to the last call + of wait(). It may be used to temporize your program properly, without wasting CPU time. + **/ + inline unsigned int wait(const unsigned int milliseconds) { + cimg::mutex(3); + static cimg_uint64 timer = cimg::time(); + cimg::mutex(3,0); + return cimg::wait(milliseconds,&timer); + } + + // Custom random number generator (allow re-entrance). + inline cimg_uint64& rng() { // Used as a shared global number for rng + static cimg_uint64 rng = 0xB16B00B5U; + return rng; + } + + inline unsigned int _rand(cimg_uint64 *const p_rng) { + *p_rng = *p_rng*1103515245 + 12345U; + return (unsigned int)*p_rng; + } + + inline unsigned int _rand() { + cimg::mutex(4); + const unsigned int res = cimg::_rand(&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline void srand(cimg_uint64 *const p_rng) { +#if cimg_OS==1 + *p_rng = cimg::time() + (cimg_uint64)getpid(); +#elif cimg_OS==2 + *p_rng = cimg::time() + (cimg_uint64)_getpid(); +#endif + } + + inline void srand() { + cimg::mutex(4); + cimg::srand(&cimg::rng()); + cimg::mutex(4,0); + } + + inline void srand(const cimg_uint64 seed) { + cimg::mutex(4); + cimg::rng() = seed; + cimg::mutex(4,0); + } + + inline double rand(const double val_min, const double val_max, cimg_uint64 *const p_rng) { + const double val = cimg::_rand(p_rng)/(double)~0U; + return val_min + (val_max - val_min)*val; + } + + inline double rand(const double val_min, const double val_max) { + cimg::mutex(4); + const double res = cimg::rand(val_min,val_max,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline double rand(const double val_max, cimg_uint64 *const p_rng) { + const double val = cimg::_rand(p_rng)/(double)~0U; + return val_max*val; + } + + inline double rand(const double val_max=1) { + cimg::mutex(4); + const double res = cimg::rand(val_max,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline double grand(cimg_uint64 *const p_rng) { + double x1, w; + do { + const double x2 = cimg::rand(-1,1,p_rng); + x1 = cimg::rand(-1,1,p_rng); + w = x1*x1 + x2*x2; + } while (w<=0 || w>=1.); + return x1*std::sqrt((-2*std::log(w))/w); + } + + inline double grand() { + cimg::mutex(4); + const double res = cimg::grand(&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline unsigned int prand(const double z, cimg_uint64 *const p_rng) { + if (z<=1.e-10) return 0; + if (z>100) return (unsigned int)((std::sqrt(z) * cimg::grand(p_rng)) + z); + unsigned int k = 0; + const double y = std::exp(-z); + for (double s = 1.; s>=y; ++k) s*=cimg::rand(1,p_rng); + return k - 1; + } + + inline unsigned int prand(const double z) { + cimg::mutex(4); + const unsigned int res = cimg::prand(z,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + //! Cut (i.e. clamp) value in specified interval. + template + inline T cut(const T& val, const t& val_min, const t& val_max) { + return val<=val_min?(T)val_min:val>=val_max?(T)val_max:val; + } + + //! Bitwise-rotate value on the left. + template + inline T rol(const T& a, const unsigned int n=1) { + return n?(T)((a<>((sizeof(T)<<3) - n))):a; + } + + inline float rol(const float a, const unsigned int n=1) { + return (float)rol((int)a,n); + } + + inline double rol(const double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + + inline double rol(const long double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half rol(const half a, const unsigned int n=1) { + return (half)rol((int)a,n); + } +#endif + + //! Bitwise-rotate value on the right. + template + inline T ror(const T& a, const unsigned int n=1) { + return n?(T)((a>>n)|(a<<((sizeof(T)<<3) - n))):a; + } + + inline float ror(const float a, const unsigned int n=1) { + return (float)ror((int)a,n); + } + + inline double ror(const double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + + inline double ror(const long double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half ror(const half a, const unsigned int n=1) { + return (half)ror((int)a,n); + } +#endif + + //! Return absolute value of a value. + template + inline T abs(const T& a) { + return a>=0?a:-a; + } + inline bool abs(const bool a) { + return a; + } + inline int abs(const unsigned char a) { + return (int)a; + } + inline int abs(const unsigned short a) { + return (int)a; + } + inline int abs(const unsigned int a) { + return (int)a; + } + inline int abs(const int a) { + return std::abs(a); + } + inline cimg_int64 abs(const cimg_uint64 a) { + return (cimg_int64)a; + } + inline double abs(const double a) { + return std::fabs(a); + } + inline float abs(const float a) { + return (float)std::fabs((double)a); + } + + //! Return hyperbolic arcosine of a value. + inline double acosh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::acosh(x); +#else + return std::log(x + std::sqrt(x*x - 1)); +#endif + } + + //! Return hyperbolic arcsine of a value. + inline double asinh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::asinh(x); +#else + return std::log(x + std::sqrt(x*x + 1)); +#endif + } + + //! Return hyperbolic arctangent of a value. + inline double atanh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::atanh(x); +#else + return 0.5*std::log((1. + x)/(1. - x)); +#endif + } + + //! Return the sinc of a given value. + inline double sinc(const double x) { + return x?std::sin(x)/x:1; + } + + //! Return base-2 logarithm of a value. + inline double log2(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::log2(x); +#else + const double base2 = std::log(2.); + return std::log(x)/base2; +#endif + } + + //! Return square of a value. + template + inline T sqr(const T& val) { + return val*val; + } + + // Return inverse of error function. + template + inline T erfinv(const T& val) { + const T + sgn = val<0?-1:1, + x = (1 - val)*(1 + val), + lnx = std::log(x), + tt1 = (T)(2/(cimg::PI*0.147) + 0.5*lnx), + tt2 = lnx/(T)0.147; + return sgn*std::sqrt(-tt1 + std::sqrt(tt1*tt1 - tt2)); + } + + //! Return cubic root of a value. + template + inline double cbrt(const T& x) { +#if cimg_use_cpp11==1 + return std::cbrt(x); +#else + return x>=0?std::pow((double)x,1./3):-std::pow(-(double)x,1./3); +#endif + } + + template + inline T pow3(const T& val) { + return val*val*val; + } + template + inline T pow4(const T& val) { + return val*val*val*val; + } + + //! Return the minimum between three values. + template + inline t min(const t& a, const t& b, const t& c) { + return std::min(std::min(a,b),c); + } + + //! Return the minimum between four values. + template + inline t min(const t& a, const t& b, const t& c, const t& d) { + return std::min(std::min(a,b),std::min(c,d)); + } + + //! Return the minabs between two values. + template + inline t minabs(const t& a, const t& b) { + return cimg::abs(b) + inline t minabs(const t& a, const t& b, const t& abs_b) { + return abs_b + inline t max(const t& a, const t& b, const t& c) { + return std::max(std::max(a,b),c); + } + + //! Return the maximum between four values. + template + inline t max(const t& a, const t& b, const t& c, const t& d) { + return std::max(std::max(a,b),std::max(c,d)); + } + + //! Return the maxabs between two values. + template + inline t maxabs(const t& a, const t& b) { + return cimg::abs(b)>cimg::abs(a)?b:a; + } + + template + inline t maxabs(const t& a, const t& b, const t& abs_b) { + return abs_b>cimg::abs(a)?b:a; + } + + //! Return the sign of a value. + template + inline T sign(const T& x) { + return (T)(cimg::type::is_nan(x)?0:x<0?-1:x>0); + } + + //! Return the nearest power of 2 higher than given value. + template + inline cimg_uint64 nearest_pow2(const T& x) { + cimg_uint64 i = 1; + while (x>i) i<<=1; + return i; + } + + //! Return the modulo of a value. + /** + \param x Input value. + \param m Modulo value. + \note This modulo function accepts negative and floating-points modulo numbers, as well as variables of any type. + **/ + template + inline T mod(const T& x, const T& m) { + const double dx = (double)x, dm = (double)m; + if (!cimg::type::is_finite(dm)) return x; + if (cimg::type::is_finite(dx)) return (T)(dx - dm * std::floor(dx / dm)); + return (T)0; + } + inline int mod(const bool x, const bool m) { + return m?(x?1:0):0; + } + inline int mod(const unsigned char x, const unsigned char m) { + return x%m; + } + inline int mod(const char x, const char m) { +#if defined(CHAR_MAX) && CHAR_MAX==255 + return x%m; +#else + return x>=0?x%m:(x%m?m + x%m:0); +#endif + } + inline int mod(const unsigned short x, const unsigned short m) { + return (int)(x%m); + } + inline int mod(const short x, const short m) { + return (int)(x>=0?x%m:(x%m?m + x%m:0)); + } + inline int mod(const unsigned int x, const unsigned int m) { + return (int)(x%m); + } + inline int mod(const int x, const int m) { + return (int)(x>=0?x%m:(x%m?m + x%m:0)); + } + inline cimg_int64 mod(const cimg_uint64 x, const cimg_uint64 m) { + return (cimg_int64)(x%m); + } + inline cimg_int64 mod(const cimg_int64 x, const cimg_int64 m) { + return (cimg_int64)(x>=0?x%m:(x%m?m + x%m:0)); + } + + //! Return the min-mod of two values. + /** + \note minmod(\p a,\p b) is defined to be: + - minmod(\p a,\p b) = min(\p a,\p b), if \p a and \p b have the same sign. + - minmod(\p a,\p b) = 0, if \p a and \p b have different signs. + **/ + template + inline T minmod(const T& a, const T& b) { + return a*b<=0?0:(a>0?(a + inline T round(const T& x) { + return (T)std::floor((_cimg_Tfloat)x + 0.5f); + } + + template + inline int uiround(const T x) { + return cimg::type::is_float()?(int)(x + 0.5f):(int)x; + } + + //! Return rounded value. + /** + \param x Value to be rounded. + \param y Rounding precision. + \param rounding_type Type of rounding operation (\c 0 = nearest, \c -1 = backward, \c 1 = forward). + \return Rounded value, having the same type as input value \c x. + **/ + template + inline T round(const T& x, const double y, const int rounding_type=0) { + if (y<=0) return x; + if (y==1) switch (rounding_type) { + case 0 : return cimg::round(x); + case 1 : return (T)std::ceil((_cimg_Tfloat)x); + default : return (T)std::floor((_cimg_Tfloat)x); + } + const double sx = (double)x/y, floor = std::floor(sx), delta = sx - floor; + return (T)(y*(rounding_type<0?floor:rounding_type>0?std::ceil(sx):delta<0.5?floor:std::ceil(sx))); + } + + // Code to compute fast median from 2,3,5,7,9,13,25 and 49 values. + // (contribution by RawTherapee: http://rawtherapee.com/). + template + inline T median(T val0, T val1) { + return (val0 + val1)/2; + } + + template + inline T median(T val0, T val1, T val2) { + return std::max(std::min(val0,val1),std::min(val2,std::max(val0,val1))); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = std::max(val0,tmp); val1 = std::min(val1,val4); tmp = std::min(val1,val2); val2 = std::max(val1,val2); + val1 = tmp; tmp = std::min(val2,val3); + return std::max(val1,tmp); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6) { + T tmp = std::min(val0,val5); + val5 = std::max(val0,val5); val0 = tmp; tmp = std::min(val0,val3); val3 = std::max(val0,val3); val0 = tmp; + tmp = std::min(val1,val6); val6 = std::max(val1,val6); val1 = tmp; tmp = std::min(val2,val4); + val4 = std::max(val2,val4); val2 = tmp; val1 = std::max(val0,val1); tmp = std::min(val3,val5); + val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); + val3 = std::max(tmp,val3); val3 = std::min(val3,val6); tmp = std::min(val4,val5); val4 = std::max(val1,tmp); + tmp = std::min(val1,tmp); val3 = std::max(tmp,val3); + return std::min(val3,val4); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8) { + T tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val7 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); + val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val6,val7); + val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val3 = std::max(val0,val3); val5 = std::min(val5,val8); + val7 = std::max(val4,tmp); tmp = std::min(val4,tmp); val6 = std::max(val3,val6); + val4 = std::max(val1,tmp); val2 = std::min(val2,val5); val4 = std::min(val4,val7); + tmp = std::min(val4,val2); val2 = std::max(val4,val2); val4 = std::max(val6,tmp); + return std::min(val4,val2); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8, T val9, T val10, T val11, + T val12) { + T tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = tmp; tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; + tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val5,val8); + val8 = std::max(val5,val8); val5 = tmp; tmp = std::min(val0,val12); val12 = std::max(val0,val12); + val0 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val2,val3); val3 = std::max(val2,val3); val2 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val8,val11); + val11 = std::max(val8,val11); val8 = tmp; tmp = std::min(val7,val12); val12 = std::max(val7,val12); val7 = tmp; + tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val10,val11); val11 = std::max(val10,val11); val10 = tmp; tmp = std::min(val1,val4); + val4 = std::max(val1,val4); val1 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val8); val8 = std::max(val7,val8); val7 = tmp; val11 = std::min(val11,val12); + tmp = std::min(val4,val9); val9 = std::max(val4,val9); val4 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; + tmp = std::min(val5,val6); val6 = std::max(val5,val6); val5 = tmp; val8 = std::min(val8,val9); + val10 = std::min(val10,val11); tmp = std::min(val1,val7); val7 = std::max(val1,val7); val1 = tmp; + tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; val3 = std::max(val1,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; val8 = std::min(val8,val10); + val5 = std::max(val0,val5); val5 = std::max(val2,val5); tmp = std::min(val6,val8); val8 = std::max(val6,val8); + val5 = std::max(val3,val5); val7 = std::min(val7,val8); val6 = std::max(val4,tmp); tmp = std::min(val4,tmp); + val5 = std::max(tmp,val5); val6 = std::min(val6,val7); + return std::max(val5,val6); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, + T val5, T val6, T val7, T val8, T val9, + T val10, T val11, T val12, T val13, T val14, + T val15, T val16, T val17, T val18, T val19, + T val20, T val21, T val22, T val23, T val24) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); val2 = std::min(tmp,val3); + val3 = std::max(tmp,val3); tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; + tmp = std::min(val5,val7); val7 = std::max(val5,val7); val5 = std::min(tmp,val6); val6 = std::max(tmp,val6); + tmp = std::min(val9,val10); val10 = std::max(val9,val10); val9 = tmp; tmp = std::min(val8,val10); + val10 = std::max(val8,val10); val8 = std::min(tmp,val9); val9 = std::max(tmp,val9); + tmp = std::min(val12,val13); val13 = std::max(val12,val13); val12 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val15,val16); val16 = std::max(val15,val16); val15 = tmp; tmp = std::min(val14,val16); + val16 = std::max(val14,val16); val14 = std::min(tmp,val15); val15 = std::max(tmp,val15); + tmp = std::min(val18,val19); val19 = std::max(val18,val19); val18 = tmp; tmp = std::min(val17,val19); + val19 = std::max(val17,val19); val17 = std::min(tmp,val18); val18 = std::max(tmp,val18); + tmp = std::min(val21,val22); val22 = std::max(val21,val22); val21 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = std::min(tmp,val21); val21 = std::max(tmp,val21); + tmp = std::min(val23,val24); val24 = std::max(val23,val24); val23 = tmp; tmp = std::min(val2,val5); + val5 = std::max(val2,val5); val2 = tmp; tmp = std::min(val3,val6); val6 = std::max(val3,val6); val3 = tmp; + tmp = std::min(val0,val6); val6 = std::max(val0,val6); val0 = std::min(tmp,val3); val3 = std::max(tmp,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = std::min(tmp,val4); val4 = std::max(tmp,val4); tmp = std::min(val11,val14); + val14 = std::max(val11,val14); val11 = tmp; tmp = std::min(val8,val14); val14 = std::max(val8,val14); + val8 = std::min(tmp,val11); val11 = std::max(tmp,val11); tmp = std::min(val12,val15); + val15 = std::max(val12,val15); val12 = tmp; tmp = std::min(val9,val15); val15 = std::max(val9,val15); + val9 = std::min(tmp,val12); val12 = std::max(tmp,val12); tmp = std::min(val13,val16); + val16 = std::max(val13,val16); val13 = tmp; tmp = std::min(val10,val16); val16 = std::max(val10,val16); + val10 = std::min(tmp,val13); val13 = std::max(tmp,val13); tmp = std::min(val20,val23); + val23 = std::max(val20,val23); val20 = tmp; tmp = std::min(val17,val23); val23 = std::max(val17,val23); + val17 = std::min(tmp,val20); val20 = std::max(tmp,val20); tmp = std::min(val21,val24); + val24 = std::max(val21,val24); val21 = tmp; tmp = std::min(val18,val24); val24 = std::max(val18,val24); + val18 = std::min(tmp,val21); val21 = std::max(tmp,val21); tmp = std::min(val19,val22); + val22 = std::max(val19,val22); val19 = tmp; val17 = std::max(val8,val17); tmp = std::min(val9,val18); + val18 = std::max(val9,val18); val9 = tmp; tmp = std::min(val0,val18); val18 = std::max(val0,val18); + val9 = std::max(tmp,val9); tmp = std::min(val10,val19); val19 = std::max(val10,val19); val10 = tmp; + tmp = std::min(val1,val19); val19 = std::max(val1,val19); val1 = std::min(tmp,val10); + val10 = std::max(tmp,val10); tmp = std::min(val11,val20); val20 = std::max(val11,val20); val11 = tmp; + tmp = std::min(val2,val20); val20 = std::max(val2,val20); val11 = std::max(tmp,val11); + tmp = std::min(val12,val21); val21 = std::max(val12,val21); val12 = tmp; tmp = std::min(val3,val21); + val21 = std::max(val3,val21); val3 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val13,val22); val22 = std::max(val13,val22); val4 = std::min(val4,val22); + val13 = std::max(val4,tmp); tmp = std::min(val4,tmp); val4 = tmp; tmp = std::min(val14,val23); + val23 = std::max(val14,val23); val14 = tmp; tmp = std::min(val5,val23); val23 = std::max(val5,val23); + val5 = std::min(tmp,val14); val14 = std::max(tmp,val14); tmp = std::min(val15,val24); + val24 = std::max(val15,val24); val15 = tmp; val6 = std::min(val6,val24); tmp = std::min(val6,val15); + val15 = std::max(val6,val15); val6 = tmp; tmp = std::min(val7,val16); val7 = std::min(tmp,val19); + tmp = std::min(val13,val21); val15 = std::min(val15,val23); tmp = std::min(val7,tmp); + val7 = std::min(tmp,val15); val9 = std::max(val1,val9); val11 = std::max(val3,val11); + val17 = std::max(val5,val17); val17 = std::max(val11,val17); val17 = std::max(val9,val17); + tmp = std::min(val4,val10); val10 = std::max(val4,val10); val4 = tmp; tmp = std::min(val6,val12); + val12 = std::max(val6,val12); val6 = tmp; tmp = std::min(val7,val14); val14 = std::max(val7,val14); + val7 = tmp; tmp = std::min(val4,val6); val6 = std::max(val4,val6); val7 = std::max(tmp,val7); + tmp = std::min(val12,val14); val14 = std::max(val12,val14); val12 = tmp; val10 = std::min(val10,val14); + tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val10,val12); + val12 = std::max(val10,val12); val10 = std::max(val6,tmp); tmp = std::min(val6,tmp); + val17 = std::max(tmp,val17); tmp = std::min(val12,val17); val17 = std::max(val12,val17); val12 = tmp; + val7 = std::min(val7,val17); tmp = std::min(val7,val10); val10 = std::max(val7,val10); val7 = tmp; + tmp = std::min(val12,val18); val18 = std::max(val12,val18); val12 = std::max(val7,tmp); + val10 = std::min(val10,val18); tmp = std::min(val12,val20); val20 = std::max(val12,val20); val12 = tmp; + tmp = std::min(val10,val20); + return std::max(tmp,val12); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, + T val7, T val8, T val9, T val10, T val11, T val12, T val13, + T val14, T val15, T val16, T val17, T val18, T val19, T val20, + T val21, T val22, T val23, T val24, T val25, T val26, T val27, + T val28, T val29, T val30, T val31, T val32, T val33, T val34, + T val35, T val36, T val37, T val38, T val39, T val40, T val41, + T val42, T val43, T val44, T val45, T val46, T val47, T val48) { + T tmp = std::min(val0,val32); + val32 = std::max(val0,val32); val0 = tmp; tmp = std::min(val1,val33); val33 = std::max(val1,val33); val1 = tmp; + tmp = std::min(val2,val34); val34 = std::max(val2,val34); val2 = tmp; tmp = std::min(val3,val35); + val35 = std::max(val3,val35); val3 = tmp; tmp = std::min(val4,val36); val36 = std::max(val4,val36); val4 = tmp; + tmp = std::min(val5,val37); val37 = std::max(val5,val37); val5 = tmp; tmp = std::min(val6,val38); + val38 = std::max(val6,val38); val6 = tmp; tmp = std::min(val7,val39); val39 = std::max(val7,val39); val7 = tmp; + tmp = std::min(val8,val40); val40 = std::max(val8,val40); val8 = tmp; tmp = std::min(val9,val41); + val41 = std::max(val9,val41); val9 = tmp; tmp = std::min(val10,val42); val42 = std::max(val10,val42); + val10 = tmp; tmp = std::min(val11,val43); val43 = std::max(val11,val43); val11 = tmp; + tmp = std::min(val12,val44); val44 = std::max(val12,val44); val12 = tmp; tmp = std::min(val13,val45); + val45 = std::max(val13,val45); val13 = tmp; tmp = std::min(val14,val46); val46 = std::max(val14,val46); + val14 = tmp; tmp = std::min(val15,val47); val47 = std::max(val15,val47); val15 = tmp; + tmp = std::min(val16,val48); val48 = std::max(val16,val48); val16 = tmp; tmp = std::min(val0,val16); + val16 = std::max(val0,val16); val0 = tmp; tmp = std::min(val1,val17); val17 = std::max(val1,val17); + val1 = tmp; tmp = std::min(val2,val18); val18 = std::max(val2,val18); val2 = tmp; tmp = std::min(val3,val19); + val19 = std::max(val3,val19); val3 = tmp; tmp = std::min(val4,val20); val20 = std::max(val4,val20); val4 = tmp; + tmp = std::min(val5,val21); val21 = std::max(val5,val21); val5 = tmp; tmp = std::min(val6,val22); + val22 = std::max(val6,val22); val6 = tmp; tmp = std::min(val7,val23); val23 = std::max(val7,val23); val7 = tmp; + tmp = std::min(val8,val24); val24 = std::max(val8,val24); val8 = tmp; tmp = std::min(val9,val25); + val25 = std::max(val9,val25); val9 = tmp; tmp = std::min(val10,val26); val26 = std::max(val10,val26); + val10 = tmp; tmp = std::min(val11,val27); val27 = std::max(val11,val27); val11 = tmp; + tmp = std::min(val12,val28); val28 = std::max(val12,val28); val12 = tmp; tmp = std::min(val13,val29); + val29 = std::max(val13,val29); val13 = tmp; tmp = std::min(val14,val30); val30 = std::max(val14,val30); + val14 = tmp; tmp = std::min(val15,val31); val31 = std::max(val15,val31); val15 = tmp; + tmp = std::min(val32,val48); val48 = std::max(val32,val48); val32 = tmp; tmp = std::min(val16,val32); + val32 = std::max(val16,val32); val16 = tmp; tmp = std::min(val17,val33); val33 = std::max(val17,val33); + val17 = tmp; tmp = std::min(val18,val34); val34 = std::max(val18,val34); val18 = tmp; + tmp = std::min(val19,val35); val35 = std::max(val19,val35); val19 = tmp; tmp = std::min(val20,val36); + val36 = std::max(val20,val36); val20 = tmp; tmp = std::min(val21,val37); val37 = std::max(val21,val37); + val21 = tmp; tmp = std::min(val22,val38); val38 = std::max(val22,val38); val22 = tmp; + tmp = std::min(val23,val39); val39 = std::max(val23,val39); val23 = tmp; tmp = std::min(val24,val40); + val40 = std::max(val24,val40); val24 = tmp; tmp = std::min(val25,val41); val41 = std::max(val25,val41); + val25 = tmp; tmp = std::min(val26,val42); val42 = std::max(val26,val42); val26 = tmp; + tmp = std::min(val27,val43); val43 = std::max(val27,val43); val27 = tmp; tmp = std::min(val28,val44); + val44 = std::max(val28,val44); val28 = tmp; tmp = std::min(val29,val45); val45 = std::max(val29,val45); + val29 = tmp; tmp = std::min(val30,val46); val46 = std::max(val30,val46); val30 = tmp; + tmp = std::min(val31,val47); val47 = std::max(val31,val47); val31 = tmp; tmp = std::min(val0,val8); + val8 = std::max(val0,val8); val0 = tmp; tmp = std::min(val1,val9); val9 = std::max(val1,val9); val1 = tmp; + tmp = std::min(val2,val10); val10 = std::max(val2,val10); val2 = tmp; tmp = std::min(val3,val11); + val11 = std::max(val3,val11); val3 = tmp; tmp = std::min(val4,val12); val12 = std::max(val4,val12); val4 = tmp; + tmp = std::min(val5,val13); val13 = std::max(val5,val13); val5 = tmp; tmp = std::min(val6,val14); + val14 = std::max(val6,val14); val6 = tmp; tmp = std::min(val7,val15); val15 = std::max(val7,val15); val7 = tmp; + tmp = std::min(val16,val24); val24 = std::max(val16,val24); val16 = tmp; tmp = std::min(val17,val25); + val25 = std::max(val17,val25); val17 = tmp; tmp = std::min(val18,val26); val26 = std::max(val18,val26); + val18 = tmp; tmp = std::min(val19,val27); val27 = std::max(val19,val27); val19 = tmp; + tmp = std::min(val20,val28); val28 = std::max(val20,val28); val20 = tmp; tmp = std::min(val21,val29); + val29 = std::max(val21,val29); val21 = tmp; tmp = std::min(val22,val30); val30 = std::max(val22,val30); + val22 = tmp; tmp = std::min(val23,val31); val31 = std::max(val23,val31); val23 = tmp; + tmp = std::min(val32,val40); val40 = std::max(val32,val40); val32 = tmp; tmp = std::min(val33,val41); + val41 = std::max(val33,val41); val33 = tmp; tmp = std::min(val34,val42); val42 = std::max(val34,val42); + val34 = tmp; tmp = std::min(val35,val43); val43 = std::max(val35,val43); val35 = tmp; + tmp = std::min(val36,val44); val44 = std::max(val36,val44); val36 = tmp; tmp = std::min(val37,val45); + val45 = std::max(val37,val45); val37 = tmp; tmp = std::min(val38,val46); val46 = std::max(val38,val46); + val38 = tmp; tmp = std::min(val39,val47); val47 = std::max(val39,val47); val39 = tmp; + tmp = std::min(val8,val32); val32 = std::max(val8,val32); val8 = tmp; tmp = std::min(val9,val33); + val33 = std::max(val9,val33); val9 = tmp; tmp = std::min(val10,val34); val34 = std::max(val10,val34); + val10 = tmp; tmp = std::min(val11,val35); val35 = std::max(val11,val35); val11 = tmp; + tmp = std::min(val12,val36); val36 = std::max(val12,val36); val12 = tmp; tmp = std::min(val13,val37); + val37 = std::max(val13,val37); val13 = tmp; tmp = std::min(val14,val38); val38 = std::max(val14,val38); + val14 = tmp; tmp = std::min(val15,val39); val39 = std::max(val15,val39); val15 = tmp; + tmp = std::min(val24,val48); val48 = std::max(val24,val48); val24 = tmp; tmp = std::min(val8,val16); + val16 = std::max(val8,val16); val8 = tmp; tmp = std::min(val9,val17); val17 = std::max(val9,val17); + val9 = tmp; tmp = std::min(val10,val18); val18 = std::max(val10,val18); val10 = tmp; + tmp = std::min(val11,val19); val19 = std::max(val11,val19); val11 = tmp; tmp = std::min(val12,val20); + val20 = std::max(val12,val20); val12 = tmp; tmp = std::min(val13,val21); val21 = std::max(val13,val21); + val13 = tmp; tmp = std::min(val14,val22); val22 = std::max(val14,val22); val14 = tmp; + tmp = std::min(val15,val23); val23 = std::max(val15,val23); val15 = tmp; tmp = std::min(val24,val32); + val32 = std::max(val24,val32); val24 = tmp; tmp = std::min(val25,val33); val33 = std::max(val25,val33); + val25 = tmp; tmp = std::min(val26,val34); val34 = std::max(val26,val34); val26 = tmp; + tmp = std::min(val27,val35); val35 = std::max(val27,val35); val27 = tmp; tmp = std::min(val28,val36); + val36 = std::max(val28,val36); val28 = tmp; tmp = std::min(val29,val37); val37 = std::max(val29,val37); + val29 = tmp; tmp = std::min(val30,val38); val38 = std::max(val30,val38); val30 = tmp; + tmp = std::min(val31,val39); val39 = std::max(val31,val39); val31 = tmp; tmp = std::min(val40,val48); + val48 = std::max(val40,val48); val40 = tmp; tmp = std::min(val0,val4); val4 = std::max(val0,val4); + val0 = tmp; tmp = std::min(val1,val5); val5 = std::max(val1,val5); val1 = tmp; tmp = std::min(val2,val6); + val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val8,val12); val12 = std::max(val8,val12); val8 = tmp; tmp = std::min(val9,val13); + val13 = std::max(val9,val13); val9 = tmp; tmp = std::min(val10,val14); val14 = std::max(val10,val14); + val10 = tmp; tmp = std::min(val11,val15); val15 = std::max(val11,val15); val11 = tmp; + tmp = std::min(val16,val20); val20 = std::max(val16,val20); val16 = tmp; tmp = std::min(val17,val21); + val21 = std::max(val17,val21); val17 = tmp; tmp = std::min(val18,val22); val22 = std::max(val18,val22); + val18 = tmp; tmp = std::min(val19,val23); val23 = std::max(val19,val23); val19 = tmp; + tmp = std::min(val24,val28); val28 = std::max(val24,val28); val24 = tmp; tmp = std::min(val25,val29); + val29 = std::max(val25,val29); val25 = tmp; tmp = std::min(val26,val30); val30 = std::max(val26,val30); + val26 = tmp; tmp = std::min(val27,val31); val31 = std::max(val27,val31); val27 = tmp; + tmp = std::min(val32,val36); val36 = std::max(val32,val36); val32 = tmp; tmp = std::min(val33,val37); + val37 = std::max(val33,val37); val33 = tmp; tmp = std::min(val34,val38); val38 = std::max(val34,val38); + val34 = tmp; tmp = std::min(val35,val39); val39 = std::max(val35,val39); val35 = tmp; + tmp = std::min(val40,val44); val44 = std::max(val40,val44); val40 = tmp; tmp = std::min(val41,val45); + val45 = std::max(val41,val45); val41 = tmp; tmp = std::min(val42,val46); val46 = std::max(val42,val46); + val42 = tmp; tmp = std::min(val43,val47); val47 = std::max(val43,val47); val43 = tmp; + tmp = std::min(val4,val32); val32 = std::max(val4,val32); val4 = tmp; tmp = std::min(val5,val33); + val33 = std::max(val5,val33); val5 = tmp; tmp = std::min(val6,val34); val34 = std::max(val6,val34); + val6 = tmp; tmp = std::min(val7,val35); val35 = std::max(val7,val35); val7 = tmp; + tmp = std::min(val12,val40); val40 = std::max(val12,val40); val12 = tmp; tmp = std::min(val13,val41); + val41 = std::max(val13,val41); val13 = tmp; tmp = std::min(val14,val42); val42 = std::max(val14,val42); + val14 = tmp; tmp = std::min(val15,val43); val43 = std::max(val15,val43); val15 = tmp; + tmp = std::min(val20,val48); val48 = std::max(val20,val48); val20 = tmp; tmp = std::min(val4,val16); + val16 = std::max(val4,val16); val4 = tmp; tmp = std::min(val5,val17); val17 = std::max(val5,val17); + val5 = tmp; tmp = std::min(val6,val18); val18 = std::max(val6,val18); val6 = tmp; + tmp = std::min(val7,val19); val19 = std::max(val7,val19); val7 = tmp; tmp = std::min(val12,val24); + val24 = std::max(val12,val24); val12 = tmp; tmp = std::min(val13,val25); val25 = std::max(val13,val25); + val13 = tmp; tmp = std::min(val14,val26); val26 = std::max(val14,val26); val14 = tmp; + tmp = std::min(val15,val27); val27 = std::max(val15,val27); val15 = tmp; tmp = std::min(val20,val32); + val32 = std::max(val20,val32); val20 = tmp; tmp = std::min(val21,val33); val33 = std::max(val21,val33); + val21 = tmp; tmp = std::min(val22,val34); val34 = std::max(val22,val34); val22 = tmp; + tmp = std::min(val23,val35); val35 = std::max(val23,val35); val23 = tmp; tmp = std::min(val28,val40); + val40 = std::max(val28,val40); val28 = tmp; tmp = std::min(val29,val41); val41 = std::max(val29,val41); + val29 = tmp; tmp = std::min(val30,val42); val42 = std::max(val30,val42); val30 = tmp; + tmp = std::min(val31,val43); val43 = std::max(val31,val43); val31 = tmp; tmp = std::min(val36,val48); + val48 = std::max(val36,val48); val36 = tmp; tmp = std::min(val4,val8); val8 = std::max(val4,val8); + val4 = tmp; tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val7,val11); val11 = std::max(val7,val11); val7 = tmp; + tmp = std::min(val12,val16); val16 = std::max(val12,val16); val12 = tmp; tmp = std::min(val13,val17); + val17 = std::max(val13,val17); val13 = tmp; tmp = std::min(val14,val18); val18 = std::max(val14,val18); + val14 = tmp; tmp = std::min(val15,val19); val19 = std::max(val15,val19); val15 = tmp; + tmp = std::min(val20,val24); val24 = std::max(val20,val24); val20 = tmp; tmp = std::min(val21,val25); + val25 = std::max(val21,val25); val21 = tmp; tmp = std::min(val22,val26); val26 = std::max(val22,val26); + val22 = tmp; tmp = std::min(val23,val27); val27 = std::max(val23,val27); val23 = tmp; + tmp = std::min(val28,val32); val32 = std::max(val28,val32); val28 = tmp; tmp = std::min(val29,val33); + val33 = std::max(val29,val33); val29 = tmp; tmp = std::min(val30,val34); val34 = std::max(val30,val34); + val30 = tmp; tmp = std::min(val31,val35); val35 = std::max(val31,val35); val31 = tmp; + tmp = std::min(val36,val40); val40 = std::max(val36,val40); val36 = tmp; tmp = std::min(val37,val41); + val41 = std::max(val37,val41); val37 = tmp; tmp = std::min(val38,val42); val42 = std::max(val38,val42); + val38 = tmp; tmp = std::min(val39,val43); val43 = std::max(val39,val43); val39 = tmp; + tmp = std::min(val44,val48); val48 = std::max(val44,val48); val44 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val1,val3); val3 = std::max(val1,val3); val1 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val5,val7); + val7 = std::max(val5,val7); val5 = tmp; tmp = std::min(val8,val10); val10 = std::max(val8,val10); val8 = tmp; + tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; tmp = std::min(val12,val14); + val14 = std::max(val12,val14); val12 = tmp; tmp = std::min(val13,val15); val15 = std::max(val13,val15); + val13 = tmp; tmp = std::min(val16,val18); val18 = std::max(val16,val18); val16 = tmp; + tmp = std::min(val17,val19); val19 = std::max(val17,val19); val17 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = tmp; tmp = std::min(val21,val23); val23 = std::max(val21,val23); + val21 = tmp; tmp = std::min(val24,val26); val26 = std::max(val24,val26); val24 = tmp; + tmp = std::min(val25,val27); val27 = std::max(val25,val27); val25 = tmp; tmp = std::min(val28,val30); + val30 = std::max(val28,val30); val28 = tmp; tmp = std::min(val29,val31); val31 = std::max(val29,val31); + val29 = tmp; tmp = std::min(val32,val34); val34 = std::max(val32,val34); val32 = tmp; + tmp = std::min(val33,val35); val35 = std::max(val33,val35); val33 = tmp; tmp = std::min(val36,val38); + val38 = std::max(val36,val38); val36 = tmp; tmp = std::min(val37,val39); val39 = std::max(val37,val39); + val37 = tmp; tmp = std::min(val40,val42); val42 = std::max(val40,val42); val40 = tmp; + tmp = std::min(val41,val43); val43 = std::max(val41,val43); val41 = tmp; tmp = std::min(val44,val46); + val46 = std::max(val44,val46); val44 = tmp; tmp = std::min(val45,val47); val47 = std::max(val45,val47); + val45 = tmp; tmp = std::min(val2,val32); val32 = std::max(val2,val32); val2 = tmp; tmp = std::min(val3,val33); + val33 = std::max(val3,val33); val3 = tmp; tmp = std::min(val6,val36); val36 = std::max(val6,val36); val6 = tmp; + tmp = std::min(val7,val37); val37 = std::max(val7,val37); val7 = tmp; tmp = std::min(val10,val40); + val40 = std::max(val10,val40); val10 = tmp; tmp = std::min(val11,val41); val41 = std::max(val11,val41); + val11 = tmp; tmp = std::min(val14,val44); val44 = std::max(val14,val44); val14 = tmp; + tmp = std::min(val15,val45); val45 = std::max(val15,val45); val15 = tmp; tmp = std::min(val18,val48); + val48 = std::max(val18,val48); val18 = tmp; tmp = std::min(val2,val16); val16 = std::max(val2,val16); + val2 = tmp; tmp = std::min(val3,val17); val17 = std::max(val3,val17); val3 = tmp; + tmp = std::min(val6,val20); val20 = std::max(val6,val20); val6 = tmp; tmp = std::min(val7,val21); + val21 = std::max(val7,val21); val7 = tmp; tmp = std::min(val10,val24); val24 = std::max(val10,val24); + val10 = tmp; tmp = std::min(val11,val25); val25 = std::max(val11,val25); val11 = tmp; + tmp = std::min(val14,val28); val28 = std::max(val14,val28); val14 = tmp; tmp = std::min(val15,val29); + val29 = std::max(val15,val29); val15 = tmp; tmp = std::min(val18,val32); val32 = std::max(val18,val32); + val18 = tmp; tmp = std::min(val19,val33); val33 = std::max(val19,val33); val19 = tmp; + tmp = std::min(val22,val36); val36 = std::max(val22,val36); val22 = tmp; tmp = std::min(val23,val37); + val37 = std::max(val23,val37); val23 = tmp; tmp = std::min(val26,val40); val40 = std::max(val26,val40); + val26 = tmp; tmp = std::min(val27,val41); val41 = std::max(val27,val41); val27 = tmp; + tmp = std::min(val30,val44); val44 = std::max(val30,val44); val30 = tmp; tmp = std::min(val31,val45); + val45 = std::max(val31,val45); val31 = tmp; tmp = std::min(val34,val48); val48 = std::max(val34,val48); + val34 = tmp; tmp = std::min(val2,val8); val8 = std::max(val2,val8); val2 = tmp; tmp = std::min(val3,val9); + val9 = std::max(val3,val9); val3 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val13); val13 = std::max(val7,val13); val7 = tmp; tmp = std::min(val10,val16); + val16 = std::max(val10,val16); val10 = tmp; tmp = std::min(val11,val17); val17 = std::max(val11,val17); + val11 = tmp; tmp = std::min(val14,val20); val20 = std::max(val14,val20); val14 = tmp; + tmp = std::min(val15,val21); val21 = std::max(val15,val21); val15 = tmp; tmp = std::min(val18,val24); + val24 = std::max(val18,val24); val18 = tmp; tmp = std::min(val19,val25); val25 = std::max(val19,val25); + val19 = tmp; tmp = std::min(val22,val28); val28 = std::max(val22,val28); val22 = tmp; + tmp = std::min(val23,val29); val29 = std::max(val23,val29); val23 = tmp; tmp = std::min(val26,val32); + val32 = std::max(val26,val32); val26 = tmp; tmp = std::min(val27,val33); val33 = std::max(val27,val33); + val27 = tmp; tmp = std::min(val30,val36); val36 = std::max(val30,val36); val30 = tmp; + tmp = std::min(val31,val37); val37 = std::max(val31,val37); val31 = tmp; tmp = std::min(val34,val40); + val40 = std::max(val34,val40); val34 = tmp; tmp = std::min(val35,val41); val41 = std::max(val35,val41); + val35 = tmp; tmp = std::min(val38,val44); val44 = std::max(val38,val44); val38 = tmp; + tmp = std::min(val39,val45); val45 = std::max(val39,val45); val39 = tmp; tmp = std::min(val42,val48); + val48 = std::max(val42,val48); val42 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); + val2 = tmp; tmp = std::min(val3,val5); val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val6,val8); + val8 = std::max(val6,val8); val6 = tmp; tmp = std::min(val7,val9); val9 = std::max(val7,val9); val7 = tmp; + tmp = std::min(val10,val12); val12 = std::max(val10,val12); val10 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = tmp; tmp = std::min(val14,val16); val16 = std::max(val14,val16); + val14 = tmp; tmp = std::min(val15,val17); val17 = std::max(val15,val17); val15 = tmp; + tmp = std::min(val18,val20); val20 = std::max(val18,val20); val18 = tmp; tmp = std::min(val19,val21); + val21 = std::max(val19,val21); val19 = tmp; tmp = std::min(val22,val24); val24 = std::max(val22,val24); + val22 = tmp; tmp = std::min(val23,val25); val25 = std::max(val23,val25); val23 = tmp; + tmp = std::min(val26,val28); val28 = std::max(val26,val28); val26 = tmp; tmp = std::min(val27,val29); + val29 = std::max(val27,val29); val27 = tmp; tmp = std::min(val30,val32); val32 = std::max(val30,val32); + val30 = tmp; tmp = std::min(val31,val33); val33 = std::max(val31,val33); val31 = tmp; + tmp = std::min(val34,val36); val36 = std::max(val34,val36); val34 = tmp; tmp = std::min(val35,val37); + val37 = std::max(val35,val37); val35 = tmp; tmp = std::min(val38,val40); val40 = std::max(val38,val40); + val38 = tmp; tmp = std::min(val39,val41); val41 = std::max(val39,val41); val39 = tmp; + tmp = std::min(val42,val44); val44 = std::max(val42,val44); val42 = tmp; tmp = std::min(val43,val45); + val45 = std::max(val43,val45); val43 = tmp; tmp = std::min(val46,val48); val48 = std::max(val46,val48); + val46 = tmp; val1 = std::max(val0,val1); val3 = std::max(val2,val3); val5 = std::max(val4,val5); + val7 = std::max(val6,val7); val9 = std::max(val8,val9); val11 = std::max(val10,val11); + val13 = std::max(val12,val13); val15 = std::max(val14,val15); val17 = std::max(val16,val17); + val19 = std::max(val18,val19); val21 = std::max(val20,val21); val23 = std::max(val22,val23); + val24 = std::min(val24,val25); val26 = std::min(val26,val27); val28 = std::min(val28,val29); + val30 = std::min(val30,val31); val32 = std::min(val32,val33); val34 = std::min(val34,val35); + val36 = std::min(val36,val37); val38 = std::min(val38,val39); val40 = std::min(val40,val41); + val42 = std::min(val42,val43); val44 = std::min(val44,val45); val46 = std::min(val46,val47); + val32 = std::max(val1,val32); val34 = std::max(val3,val34); val36 = std::max(val5,val36); + val38 = std::max(val7,val38); val9 = std::min(val9,val40); val11 = std::min(val11,val42); + val13 = std::min(val13,val44); val15 = std::min(val15,val46); val17 = std::min(val17,val48); + val24 = std::max(val9,val24); val26 = std::max(val11,val26); val28 = std::max(val13,val28); + val30 = std::max(val15,val30); val17 = std::min(val17,val32); val19 = std::min(val19,val34); + val21 = std::min(val21,val36); val23 = std::min(val23,val38); val24 = std::max(val17,val24); + val26 = std::max(val19,val26); val21 = std::min(val21,val28); val23 = std::min(val23,val30); + val24 = std::max(val21,val24); val23 = std::min(val23,val26); + return std::max(val23,val24); + } + + //! Return sqrt(x^2 + y^2). + template + inline T hypot(const T x, const T y) { + return std::sqrt(x*x + y*y); + } + + template + inline T hypot(const T x, const T y, const T z) { + return std::sqrt(x*x + y*y + z*z); + } + + template + inline T _hypot(const T x, const T y) { // Slower but more precise version + T nx = cimg::abs(x), ny = cimg::abs(y), t; + if (nx0) { t/=nx; return nx*std::sqrt(1 + t*t); } + return 0; + } + + //! Return the factorial of n + inline double factorial(const int n) { + if (n<0) return cimg::type::nan(); + if (n<2) return 1; + double res = 2; + for (int i = 3; i<=n; ++i) res*=i; + return res; + } + + //! Return the number of permutations of k objects in a set of n objects. + inline double permutations(const int k, const int n, const bool with_order) { + if (n<0 || k<0) return cimg::type::nan(); + if (k>n) return 0; + double res = 1; + for (int i = n; i>=n - k + 1; --i) res*=i; + return with_order?res:res/cimg::factorial(k); + } + + inline double _fibonacci(int exp) { + double + base = (1 + std::sqrt(5.))/2, + result = 1/std::sqrt(5.); + while (exp) { + if (exp&1) result*=base; + exp>>=1; + base*=base; + } + return result; + } + + //! Calculate fibonacci number. + // (Precise up to n = 78, less precise for n>78). + inline double fibonacci(const int n) { + if (n<0) return cimg::type::nan(); + if (n<3) return 1; + if (n<11) { + cimg_uint64 fn1 = 1, fn2 = 1, fn = 0; + for (int i = 3; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + if (n<75) // precise up to n = 74, faster than the integer calculation above for n>10 + return (double)((cimg_uint64)(_fibonacci(n) + 0.5)); + + if (n<94) { // precise up to n = 78, less precise for n>78 up to n = 93, overflows for n>93 + cimg_uint64 + fn1 = ((cimg_uint64)303836)<<32 | 3861581201UL, // 1304969544928657ULL (avoid C++98 warning with ULL) + fn2 = ((cimg_uint64)187781)<<32 | 2279239217UL, // 806515533049393ULL + fn = 0; + for (int i = 75; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + return _fibonacci(n); // Not precise, but better than the wrong overflowing calculation + } + + //! Calculate greatest common divisor. + inline long gcd(long a, long b) { + while (a) { const long c = a; a = b%a; b = c; } + return b; + } + + //! Convert character to lower case. + inline char lowercase(const char x) { + return (char)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + inline double lowercase(const double x) { + return (double)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + + //! Convert C-string to lower case. + inline void lowercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = lowercase(*ptr); + } + + //! Convert character to upper case. + inline char uppercase(const char x) { + return (char)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + inline double uppercase(const double x) { + return (double)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + //! Convert C-string to upper case. + inline void uppercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = uppercase(*ptr); + } + + //! Return \c true if input character is blank (space, tab, or non-printable character). + inline bool is_blank(const char c) { + return c>=0 && (unsigned char)c<=' '; + } + + //! Read value in a C-string. + /** + \param str C-string containing the float value to read. + \return Read value. + \note Same as std::atof() extended to manage the retrieval of fractions from C-strings, + as in "1/2". + **/ + inline double atof(const char *const str) { + double x = 0, y = 1; + return str && cimg_sscanf(str,"%lf/%lf",&x,&y)>0?x/y:0; + } + + //! Compare the first \p l characters of two C-strings, ignoring the case. + /** + \param str1 C-string. + \param str2 C-string. + \param l Number of characters to compare. + \return \c 0 if the two strings are equal, something else otherwise. + \note This function has to be defined since it is not provided by all C++-compilers (not ANSI). + **/ + inline int strncasecmp(const char *const str1, const char *const str2, const int l) { + if (!l) return 0; + if (!str1) return str2?-1:0; + const char *nstr1 = str1, *nstr2 = str2; + int k, diff = 0; for (k = 0; kp && str[q]==delimiter; ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Remove white spaces on the start and/or end of a C-string. + inline bool strpare(char *const str, const bool is_symmetric, const bool is_iterative) { + if (!str) return false; + const int l = (int)std::strlen(str); + int p, q; + if (is_symmetric) for (p = 0, q = l - 1; pp && is_blank(str[q]); ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Replace reserved characters (for Windows filename) by another character. + /** + \param[in,out] str C-string to work with (modified at output). + \param[in] c Replacement character. + **/ + inline void strwindows_reserved(char *const str, const char c='_') { + for (char *s = str; *s; ++s) { + const char i = *s; + if (i=='<' || i=='>' || i==':' || i=='\"' || i=='/' || i=='\\' || i=='|' || i=='?' || i=='*') *s = c; + } + } + + //! Replace escape sequences in C-strings by character values. + /** + \param[in,out] str C-string to work with (modified at output). + **/ + inline void strunescape(char *const str) { +#define cimg_strunescape(ci,co) case ci : *nd = co; ++ns; break; + + unsigned char val = 0; + for (char *ns = str, *nd = str; *ns || (bool)(*nd = 0); ++nd) if (*ns=='\\') switch (*(++ns)) { + cimg_strunescape('a','\a'); + cimg_strunescape('b','\b'); + cimg_strunescape('e',0x1B); + cimg_strunescape('f','\f'); + cimg_strunescape('n','\n'); + cimg_strunescape('r','\r'); + cimg_strunescape('t','\t'); + cimg_strunescape('v','\v'); + cimg_strunescape('\\','\\'); + cimg_strunescape('\'','\''); + cimg_strunescape('\"','\"'); + cimg_strunescape('\?','\?'); + case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : + val = (unsigned char)(*(ns++) - '0'); + if (*ns>='0' && *ns<='7') (val<<=3)|=*(ns++) - '0'; + if (*ns>='0' && *ns<='7') (val<<=3)|=*(ns++) - '0'; + *nd = (char)val; + break; + case 'x' : { + char c = lowercase(*(++ns)); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + val = (unsigned char)(c<='9'?c - '0':c - 'a' + 10); + c = lowercase(*(++ns)); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + (val<<=4)|=(c<='9'?c - '0':c - 'a' + 10); + ++ns; + } + *nd = (char)val; + } else *nd = c; + } break; + case 'u' : { // UTF-8 BMP + char c1, c2, c3, c4; + if ((((c1 = lowercase(ns[1]))>='0' && c1<='9') || (c1>='a' && c1<='f')) && + (((c2 = lowercase(ns[2]))>='0' && c2<='9') || (c2>='a' && c2<='f')) && + (((c3 = lowercase(ns[3]))>='0' && c3<='9') || (c3>='a' && c3<='f')) && + (((c4 = lowercase(ns[4]))>='0' && c4<='9') || (c4>='a' && c4<='f'))) { + c1 = (c1<='9'?c1 - '0':c1 - 'a' + 10); + c2 = (c2<='9'?c2 - '0':c2 - 'a' + 10); + c3 = (c3<='9'?c3 - '0':c3 - 'a' + 10); + c4 = (c4<='9'?c4 - '0':c4 - 'a' + 10); + const unsigned int ival = + ((unsigned int)c1<<12) | ((unsigned int)c2<<8) | ((unsigned int)c3<<4) | c4; + if (ival<=0x007f) *nd = (char)ival; + else if (ival<=0x07ff) { + *(nd++) = (char)((ival>>6)|0xc0); + *nd = (char)((ival&0x3f)|0x80); + } else { + *(nd++) = (char)((ival>>12)|0xe0); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } + ns+=5; + } else *nd = *(ns++); + } break; + case 'U' : { // UTF-8 astral planes + char c1, c2, c3, c4, c5, c6, c7, c8; + if ((((c1 = lowercase(ns[1]))>='0' && c1<='9') || (c1>='a' && c1<='f')) && + (((c2 = lowercase(ns[2]))>='0' && c2<='9') || (c2>='a' && c2<='f')) && + (((c3 = lowercase(ns[3]))>='0' && c3<='9') || (c3>='a' && c3<='f')) && + (((c4 = lowercase(ns[4]))>='0' && c4<='9') || (c4>='a' && c4<='f')) && + (((c5 = lowercase(ns[5]))>='0' && c5<='9') || (c5>='a' && c5<='f')) && + (((c6 = lowercase(ns[6]))>='0' && c6<='9') || (c6>='a' && c6<='f')) && + (((c7 = lowercase(ns[7]))>='0' && c7<='9') || (c7>='a' && c7<='f')) && + (((c8 = lowercase(ns[8]))>='0' && c8<='9') || (c8>='a' && c8<='f'))) { + c1 = (c1<='9'?c1 - '0':c1 - 'a' + 10); + c2 = (c2<='9'?c2 - '0':c2 - 'a' + 10); + c3 = (c3<='9'?c3 - '0':c3 - 'a' + 10); + c4 = (c4<='9'?c4 - '0':c4 - 'a' + 10); + c5 = (c5<='9'?c5 - '0':c5 - 'a' + 10); + c6 = (c6<='9'?c6 - '0':c6 - 'a' + 10); + c7 = (c7<='9'?c7 - '0':c7 - 'a' + 10); + c8 = (c8<='9'?c8 - '0':c8 - 'a' + 10); + const unsigned int ival = + ((unsigned int)c1<<28) | ((unsigned int)c2<<24) | ((unsigned int)c3<<20) | ((unsigned int)c4<<16) | + ((unsigned int)c5<<12) | ((unsigned int)c6<<8) | ((unsigned int)c7<<4) | (unsigned int)c8; + if (ival<=0x007f) *nd = (char)ival; + else if (ival<=0x07ff) { + *(nd++) = (char)((ival>>6)|0xc0); + *nd = (char)((ival&0x3f)|0x80); + } else if (ival<=0xffff) { + *(nd++) = (char)((ival>>12)|0xe0); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } else { + *(nd++) = (char)((ival>>18)|0xf0); + *(nd++) = (char)(((ival>>12)&0x3f)|0x80); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } + ns+=9; + } else *nd = *(ns++); + } break; + default : if (*ns) *nd = *(ns++); + } + else *nd = *(ns++); + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size); + + // Return string that identifies the running OS. + inline const char *stros() { +#if defined(linux) || defined(__linux) || defined(__linux__) + static const char *const str = "Linux"; +#elif defined(sun) || defined(__sun) + static const char *const str = "Sun OS"; +#elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__) + static const char *const str = "BSD"; +#elif defined(sgi) || defined(__sgi) + static const char *const str = "Irix"; +#elif defined(__MACOSX__) || defined(__APPLE__) + static const char *const str = "Mac OS"; +#elif defined(unix) || defined(__unix) || defined(__unix__) + static const char *const str = "Generic Unix"; +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ + defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + static const char *const str = "Windows"; +#else + const char + *const _str1 = std::getenv("OSTYPE"), + *const _str2 = _str1?_str1:std::getenv("OS"), + *const str = _str2?_str2:"Unknown OS"; +#endif + return str; + } + + //! Return the basename of a filename. + inline const char* basename(const char *const s, const char separator=cimg_file_separator) { + const char *p = 0, *np = s; + while (np>=s && (p=np)) np = std::strchr(np,separator) + 1; + return p; + } + + // Return a random filename. + inline const char* filenamerand() { + cimg::mutex(6); + static char randomid[9]; + for (unsigned int k = 0; k<8; ++k) { + const int v = (int)cimg::rand(65535)%3; + randomid[k] = (char)(v==0?('0' + ((int)cimg::rand(65535)%10)): + (v==1?('a' + ((int)cimg::rand(65535)%26)): + ('A' + ((int)cimg::rand(65535)%26)))); + } + cimg::mutex(6,0); + return randomid; + } + + // Convert filename as a Windows-style filename (short path name). + inline void winformat_string(char *const str) { + if (str && *str) { +#if cimg_OS==2 + char *const nstr = new char[MAX_PATH]; + if (GetShortPathNameA(str,nstr,MAX_PATH)) std::strcpy(str,nstr); + delete[] nstr; +#endif + } + } + + // Open a file (similar to std:: fopen(), but with wide character support on Windows). + inline std::FILE *std_fopen(const char *const path, const char *const mode); + + + //! Open a file. + /** + \param path Path of the filename to open. + \param mode C-string describing the opening mode. + \return Opened file. + \note Same as std::fopen() but throw a \c CImgIOException when + the specified file cannot be opened, instead of returning \c 0. + **/ + inline std::FILE *fopen(const char *const path, const char *const mode) { + if (!path) + throw CImgArgumentException("cimg::fopen(): Specified file path is (null)."); + if (!mode) + throw CImgArgumentException("cimg::fopen(): File '%s', specified mode is (null).", + path); + std::FILE *res = 0; + if (*path=='-' && (!path[1] || path[1]=='.')) { + res = (*mode=='r')?cimg::_stdin():cimg::_stdout(); +#if cimg_OS==2 + if (*mode && mode[1]=='b') { // Force stdin/stdout to be in binary mode +#ifdef __BORLANDC__ + if (setmode(_fileno(res),0x8000)==-1) res = 0; +#else + if (_setmode(_fileno(res),0x8000)==-1) res = 0; +#endif + } +#endif + } else res = cimg::std_fopen(path,mode); + if (!res) throw CImgIOException("cimg::fopen(): Failed to open file '%s' with mode '%s'.", + path,mode); + return res; + } + + //! Close a file. + /** + \param file File to close. + \return \c 0 if file has been closed properly, something else otherwise. + \note Same as std::fclose() but display a warning message if + the file has not been closed properly. + **/ + inline int fclose(std::FILE *file) { + if (!file) { warn("cimg::fclose(): Specified file is (null)."); return 0; } + if (file==cimg::_stdin(false) || file==cimg::_stdout(false)) return 0; + const int errn = std::fclose(file); + if (errn!=0) warn("cimg::fclose(): Error code %d returned during file closing.", + errn); + return errn; + } + + //! Version of 'fseek()' that supports >=64bits offsets everywhere (for Windows). + inline int fseek(FILE *stream, cimg_long offset, int origin) { +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + return _fseeki64(stream,(__int64)offset,origin); +#else + return std::fseek(stream,offset,origin); +#endif + } + + //! Version of 'ftell()' that supports >=64bits offsets everywhere (for Windows). + inline cimg_long ftell(FILE *stream) { +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + return (cimg_long)_ftelli64(stream); +#else + return (cimg_long)std::ftell(stream); +#endif + } + + // Get the file or directory attributes with support for UTF-8 paths (Windows only). +#if cimg_OS==2 + inline DWORD win_getfileattributes(const char *const path); +#endif + + //! Check if a path is a directory. + /** + \param path Specified path to test. + **/ + inline bool is_directory(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==1 + struct stat st_buf; + return (!stat(path,&st_buf) && S_ISDIR(st_buf.st_mode)); +#elif cimg_OS==2 + const DWORD res = win_getfileattributes(path); + return res!=INVALID_FILE_ATTRIBUTES && (res&FILE_ATTRIBUTE_DIRECTORY); +#else + return false; +#endif + } + + //! Check if a path is a file. + /** + \param path Specified path to test. + **/ + inline bool is_file(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==2 + const DWORD res = cimg::win_getfileattributes(path); + return res!=INVALID_FILE_ATTRIBUTES && !(res&FILE_ATTRIBUTE_DIRECTORY); +#else + std::FILE *const file = cimg::std_fopen(path,"rb"); + if (!file) return false; + cimg::fclose(file); + return !is_directory(path); +#endif + } + + //! Get file size. + /** + \param filename Specified filename to get size from. + \return File size or '-1' if file does not exist. + **/ + inline cimg_int64 fsize(const char *const filename) { + std::FILE *const file = cimg::std_fopen(filename,"rb"); + if (!file) return (cimg_int64)-1; + std::fseek(file,0,SEEK_END); + const cimg_int64 siz = (cimg_int64)std::ftell(file); + cimg::fclose(file); + return siz; + } + + //! Get last write time of a given file or directory (multiple-attributes version). + /** + \param path Specified path to get attributes from. + \param[in,out] attr Type of requested time attributes. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second } + Replaced by read attributes after return (or -1 if an error occurred). + \param nb_attr Number of attributes to read/write. + \return Latest read attribute. + **/ + template + inline int fdate(const char *const path, T *attr, const unsigned int nb_attr) { +#define _cimg_fdate_err() for (unsigned int i = 0; i + inline int date(T *attr, const unsigned int nb_attr) { + int res = -1; + cimg::mutex(6); +#if cimg_OS==2 + SYSTEMTIME st; + GetLocalTime(&st); + for (unsigned int i = 0; itm_year + 1900: + attr[i]==1?st->tm_mon + 1: + attr[i]==2?st->tm_mday: + attr[i]==3?st->tm_wday: + attr[i]==4?st->tm_hour: + attr[i]==5?st->tm_min: + attr[i]==6?st->tm_sec: + attr[i]==7?_st.tv_usec/1000:-1); + attr[i] = (T)res; + } +#endif + cimg::mutex(6,0); + return res; + } + + //! Get current local time (single-attribute version). + /** + \param attr Type of requested time attribute. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second | + 7=millisecond } + \return Specified attribute or -1 if an error occurred. + **/ + inline int date(unsigned int attr) { + int out = (int)attr; + return date(&out,1); + } + + // Get/set path to the \c curl binary. + inline const char *curl_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c dcraw binary. + inline const char *dcraw_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the custom's \c custom binary. + inline const char *custom_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the GraphicsMagick's \c gm binary. + inline const char* graphicsmagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gunzip binary. + inline const char *gunzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gzip binary. + inline const char *gzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the ImageMagick's \c convert binary. + inline const char* imagemagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the Medcon's \c medcon binary. + inline const char* medcon_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to store temporary files. + inline const char* temporary_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c wget binary. + inline const char *wget_path(const char *const user_path=0, const bool reinit_path=false); + + //! Split filename into two C-strings \c body and \c extension. + /** + filename and body must not overlap! + **/ + inline const char *split_filename(const char *const filename, char *const body=0) { + if (!filename) { if (body) *body = 0; return ""; } + const char * p = std::strrchr(filename,'.'); + if (!p || std::strchr(p,'/') || std::strchr(p,'\\')) { // No extension. + if (body) std::strcpy(body,filename); + return filename + std::strlen(filename); + } + const unsigned int l = (unsigned int)(p - filename); + if (body) { if (l) std::memcpy(body,filename,l); body[l] = 0; } + return p + 1; + } + + // Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str); + + //! Read data from file. + /** + \param[out] ptr Pointer to memory buffer that will contain the binary data read from file. + \param nmemb Number of elements to read. + \param stream File to read data from. + \return Number of read elements. + \note Same as std::fread() but may display warning message if all elements could not be read. + **/ + template + inline size_t fread(T *const ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fread(): Invalid reading request of %u %s%s from file %p to buffer %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",stream,ptr); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0; + do { + l_to_read = (to_read*sizeof(T))0); + if (to_read>0) + warn("cimg::fread(): Only %lu/%lu elements could be read from file.", + (unsigned long)al_read,(unsigned long)nmemb); + return al_read; + } + + //! Write data to file. + /** + \param ptr Pointer to memory buffer containing the binary data to write on file. + \param nmemb Number of elements to write. + \param[out] stream File to write data on. + \return Number of written elements. + \note Similar to std::fwrite but may display warning messages if all elements could not be written. + **/ + template + inline size_t fwrite(const T *ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",ptr,stream); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0; + do { + l_to_write = (to_write*sizeof(T))0); + if (to_write>0) + warn("cimg::fwrite(): Only %lu/%lu elements could be written in file.", + (unsigned long)al_write,(unsigned long)nmemb); + return al_write; + } + + //! Create an empty file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + **/ + inline void fempty(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::fempty(): Specified filename is (null)."); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (!file) cimg::fclose(nfile); + } + + // Try to guess format from an image file. + inline const char *ftype(std::FILE *const file, const char *const filename); + + // Get or set load from network mode (can be { 0=disabled | 1=enabled }). + inline bool& network_mode(const bool value, const bool is_set) { + static bool mode = true; + if (is_set) { cimg::mutex(0); mode = value; cimg::mutex(0,0); } + return mode; + } + + inline bool& network_mode() { + return network_mode(false,false); + } + + // Load file from network as a local temporary file. + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout=0, const bool try_fallback=false, + const char *const referer=0); + + //! Return options specified on the command line. + inline const char* option(const char *const name, const int argc, const char *const *const argv, + const char *const _default, const char *const usage, const bool reset_static) { + static bool first = true, visu = false; + if (reset_static) { first = true; return 0; } + const char *res = 0; + if (first) { + first = false; + visu = cimg::option("-h",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("-help",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("--help",argc,argv,(char*)0,(char*)0,false)!=0; + } + if (!name && visu) { + if (usage) { + std::fprintf(cimg::output(),"\n %s%s%s",cimg::t_red,cimg::basename(argv[0]),cimg::t_normal); + std::fprintf(cimg::output(),": %s",usage); + std::fprintf(cimg::output()," (%s, %s)\n\n",cimg_date,cimg_time); + } + if (_default) std::fprintf(cimg::output(),"%s\n",_default); + } + if (name) { + if (argc>0) { + int k = 0; + while (k Operating System: %s%-13s%s %s('cimg_OS'=%d)%s\n", + cimg::t_bold, + cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknown"), + cimg::t_normal,cimg::t_green, + cimg_OS, + cimg::t_normal); + + std::fprintf(cimg::output()," > CPU endianness: %s%s Endian%s\n", + cimg::t_bold, + cimg::endianness()?"Big":"Little", + cimg::t_normal); + + std::fprintf(cimg::output()," > Verbosity mode: %s%-13s%s %s('cimg_verbosity'=%d)%s\n", + cimg::t_bold, + cimg_verbosity==0?"Quiet": + cimg_verbosity==1?"Console": + cimg_verbosity==2?"Dialog": + cimg_verbosity==3?"Console+Warnings":"Dialog+Warnings", + cimg::t_normal,cimg::t_green, + cimg_verbosity, + cimg::t_normal); + + std::fprintf(cimg::output()," > Stricts warnings: %s%-13s%s %s('cimg_strict_warnings' %s)%s\n", + cimg::t_bold, +#ifdef cimg_strict_warnings + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Support for C++11: %s%-13s%s %s('cimg_use_cpp11'=%d)%s\n", + cimg::t_bold, + cimg_use_cpp11?"Yes":"No", + cimg::t_normal,cimg::t_green, + (int)cimg_use_cpp11, + cimg::t_normal); + + std::fprintf(cimg::output()," > Using VT100 messages: %s%-13s%s %s('cimg_use_vt100' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_vt100 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Display type: %s%-13s%s %s('cimg_display'=%d)%s\n", + cimg::t_bold, + cimg_display==0?"No display":cimg_display==1?"X11":cimg_display==2?"Windows GDI":"Unknown", + cimg::t_normal,cimg::t_green, + (int)cimg_display, + cimg::t_normal); + +#if cimg_display==1 + std::fprintf(cimg::output()," > Using XShm for X11: %s%-13s%s %s('cimg_use_xshm' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xshm + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using XRand for X11: %s%-13s%s %s('cimg_use_xrandr' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xrandr + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); +#endif + std::fprintf(cimg::output()," > Using OpenMP: %s%-13s%s %s('cimg_use_openmp' %s)%s\n", + cimg::t_bold, +#if cimg_use_openmp!=0 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using PNG library: %s%-13s%s %s('cimg_use_png' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_png + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using JPEG library: %s%-13s%s %s('cimg_use_jpeg' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_jpeg + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using TIFF library: %s%-13s%s %s('cimg_use_tiff' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_tiff + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using Magick++ library: %s%-13s%s %s('cimg_use_magick' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_magick + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using FFTW3 library: %s%-13s%s %s('cimg_use_fftw3' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_fftw3 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using LAPACK library: %s%-13s%s %s('cimg_use_lapack' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_lapack + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + char *const tmp = new char[1024]; + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::curl_path()); + std::fprintf(cimg::output()," > Path of 'curl': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::dcraw_path()); + std::fprintf(cimg::output()," > Path of 'dcraw': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::custom_path()); + std::fprintf(cimg::output()," > Path of 'custom': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::graphicsmagick_path()); + std::fprintf(cimg::output()," > Path of 'graphicsmagick': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::gunzip_path()); + std::fprintf(cimg::output()," > Path of 'gunzip': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::gzip_path()); + std::fprintf(cimg::output()," > Path of 'gzip': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::imagemagick_path()); + std::fprintf(cimg::output()," > Path of 'imagemagick': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::medcon_path()); + std::fprintf(cimg::output()," > Path of 'medcon': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::temporary_path()); + std::fprintf(cimg::output()," > Temporary path: %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::wget_path()); + std::fprintf(cimg::output()," > Path of 'wget': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + std::fprintf(cimg::output(),"\n"); + delete[] tmp; + } + + // Declare LAPACK function signatures if LAPACK support is enabled. +#ifdef cimg_use_lapack + template + inline void getrf(int &N, T *lapA, int *IPIV, int &INFO) { + dgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + inline void getrf(int &N, float *lapA, int *IPIV, int &INFO) { + sgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + template + inline void getri(int &N, T *lapA, int *IPIV, T* WORK, int &LWORK, int &INFO) { + dgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + inline void getri(int &N, float *lapA, int *IPIV, float* WORK, int &LWORK, int &INFO) { + sgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + template + inline void gesvd(char &JOB, int &M, int &N, T *lapA, int &MN, + T *lapS, T *lapU, T *lapV, T *WORK, int &LWORK, int &INFO) { + dgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + inline void gesvd(char &JOB, int &M, int &N, float *lapA, int &MN, + float *lapS, float *lapU, float *lapV, float *WORK, int &LWORK, int &INFO) { + sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + template + inline void getrs(char &TRANS, int &N, T *lapA, int *IPIV, T *lapB, int &INFO) { + int one = 1; + dgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + inline void getrs(char &TRANS, int &N, float *lapA, int *IPIV, float *lapB, int &INFO) { + int one = 1; + sgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + template + inline void syev(char &JOB, char &UPLO, int &N, T *lapA, T *lapW, T *WORK, int &LWORK, int &INFO) { + dsyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + inline void syev(char &JOB, char &UPLO, int &N, float *lapA, float *lapW, float *WORK, int &LWORK, int &INFO) { + ssyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + template + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, T* lapA, int &LDA, + T* lapB, int &LDB, T* WORK, int &LWORK, int &INFO) { + dgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, float* lapA, int &LDA, + float* lapB, int &LDB, float* WORK, int &LWORK, int &INFO) { + sgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + +#endif + + } // namespace cimg { ... + + /*------------------------------------------------ + # + # + # Definition of mathematical operators and + # external functions. + # + # + -------------------------------------------------*/ + +#define _cimg_create_operator(typ) \ + template \ + inline CImg::type> operator+(const typ val, const CImg& img) { \ + return img + val; \ + } \ + template \ + inline CImg::type> operator-(const typ val, const CImg& img) { \ + typedef typename cimg::superset::type Tt; \ + return CImg(img._width,img._height,img._depth,img._spectrum,val)-=img; \ + } \ + template \ + inline CImg::type> operator*(const typ val, const CImg& img) { \ + return img*val; \ + } \ + template \ + inline CImg::type> operator/(const typ val, const CImg& img) { \ + return val*img.get_invert(); \ + } \ + template \ + inline CImg::type> operator&(const typ val, const CImg& img) { \ + return img & val; \ + } \ + template \ + inline CImg::type> operator|(const typ val, const CImg& img) { \ + return img | val; \ + } \ + template \ + inline CImg::type> operator^(const typ val, const CImg& img) { \ + return img ^ val; \ + } \ + template \ + inline bool operator==(const typ val, const CImg& img) { \ + return img == val; \ + } \ + template \ + inline bool operator!=(const typ val, const CImg& img) { \ + return img != val; \ + } + + _cimg_create_operator(bool) + _cimg_create_operator(unsigned char) + _cimg_create_operator(char) + _cimg_create_operator(signed char) + _cimg_create_operator(unsigned short) + _cimg_create_operator(short) + _cimg_create_operator(unsigned int) + _cimg_create_operator(int) + _cimg_create_operator(cimg_uint64) + _cimg_create_operator(cimg_int64) + _cimg_create_operator(float) + _cimg_create_operator(double) + _cimg_create_operator(long double) + + template + inline CImg<_cimg_Tfloat> operator+(const char *const expression, const CImg& img) { + return img + expression; + } + + template + inline CImg<_cimg_Tfloat> operator-(const char *const expression, const CImg& img) { + return CImg<_cimg_Tfloat>(img,false).fill(expression,true)-=img; + } + + template + inline CImg<_cimg_Tfloat> operator*(const char *const expression, const CImg& img) { + return img*expression; + } + + template + inline CImg<_cimg_Tfloat> operator/(const char *const expression, const CImg& img) { + return expression*img.get_invert(); + } + + template + inline CImg operator&(const char *const expression, const CImg& img) { + return img & expression; + } + + template + inline CImg operator|(const char *const expression, const CImg& img) { + return img | expression; + } + + template + inline CImg operator^(const char *const expression, const CImg& img) { + return img ^ expression; + } + + template + inline bool operator==(const char *const expression, const CImg& img) { + return img==expression; + } + + template + inline bool operator!=(const char *const expression, const CImg& img) { + return img!=expression; + } + + template + inline CImg transpose(const CImg& instance) { + return instance.get_transpose(); + } + + template + inline CImg<_cimg_Tfloat> invert(const CImg& instance, const bool use_LU=true) { + return instance.get_invert(use_LU); + } + + template + inline CImg<_cimg_Tfloat> pseudoinvert(const CImg& instance, const bool use_LU=false) { + return instance.get_pseudoinvert(use_LU); + } + +#define _cimg_create_pointwise_function(name) \ + template \ + inline CImg<_cimg_Tfloat> name(const CImg& instance) { \ + return instance.get_##name(); \ + } + + _cimg_create_pointwise_function(sqr) + _cimg_create_pointwise_function(sqrt) + _cimg_create_pointwise_function(exp) + _cimg_create_pointwise_function(log) + _cimg_create_pointwise_function(log2) + _cimg_create_pointwise_function(log10) + _cimg_create_pointwise_function(abs) + _cimg_create_pointwise_function(sign) + _cimg_create_pointwise_function(cos) + _cimg_create_pointwise_function(sin) + _cimg_create_pointwise_function(sinc) + _cimg_create_pointwise_function(tan) + _cimg_create_pointwise_function(acos) + _cimg_create_pointwise_function(asin) + _cimg_create_pointwise_function(atan) + _cimg_create_pointwise_function(cosh) + _cimg_create_pointwise_function(sinh) + _cimg_create_pointwise_function(tanh) + _cimg_create_pointwise_function(acosh) + _cimg_create_pointwise_function(asinh) + _cimg_create_pointwise_function(atanh) + + /*----------------------------------- + # + # Define the CImgDisplay structure + # + ----------------------------------*/ + //! Allow the creation of windows, display images on them and manage user events (keyboard, mouse and windows events). + /** + CImgDisplay methods rely on a low-level graphic library to perform: it can be either \b X-Window + (X11, for Unix-based systems) or \b GDI32 (for Windows-based systems). + If both libraries are missing, CImgDisplay will not be able to display images on screen, and will enter + a minimal mode where warning messages will be outputted each time the program is trying to call one of the + CImgDisplay method. + + The configuration variable \c cimg_display tells about the graphic library used. + It is set automatically by \CImg when one of these graphic libraries has been detected. + But, you can override its value if necessary. Valid choices are: + - 0: Disable display capabilities. + - 1: Use \b X-Window (X11) library. + - 2: Use \b GDI32 library. + + Remember to link your program against \b X11 or \b GDI32 libraries if you use CImgDisplay. + **/ + struct CImgDisplay { + cimg_uint64 _timer, _fps_frames, _fps_timer; + unsigned int _width, _height, _normalization; + float _fps_fps, _min, _max; + bool _is_fullscreen; + char *_title; + unsigned int _window_width, _window_height, _button, *_keys, *_released_keys; + int _window_x, _window_y, _mouse_x, _mouse_y, _wheel; + bool _is_closed, _is_resized, _is_moved, _is_event, + _is_keyESC, _is_keyF1, _is_keyF2, _is_keyF3, _is_keyF4, _is_keyF5, _is_keyF6, _is_keyF7, + _is_keyF8, _is_keyF9, _is_keyF10, _is_keyF11, _is_keyF12, _is_keyPAUSE, _is_key1, _is_key2, + _is_key3, _is_key4, _is_key5, _is_key6, _is_key7, _is_key8, _is_key9, _is_key0, + _is_keyBACKSPACE, _is_keyINSERT, _is_keyHOME, _is_keyPAGEUP, _is_keyTAB, _is_keyQ, _is_keyW, _is_keyE, + _is_keyR, _is_keyT, _is_keyY, _is_keyU, _is_keyI, _is_keyO, _is_keyP, _is_keyDELETE, + _is_keyEND, _is_keyPAGEDOWN, _is_keyCAPSLOCK, _is_keyA, _is_keyS, _is_keyD, _is_keyF, _is_keyG, + _is_keyH, _is_keyJ, _is_keyK, _is_keyL, _is_keyENTER, _is_keySHIFTLEFT, _is_keyZ, _is_keyX, + _is_keyC, _is_keyV, _is_keyB, _is_keyN, _is_keyM, _is_keySHIFTRIGHT, _is_keyARROWUP, _is_keyCTRLLEFT, + _is_keyAPPLEFT, _is_keyALT, _is_keySPACE, _is_keyALTGR, _is_keyAPPRIGHT, _is_keyMENU, _is_keyCTRLRIGHT, + _is_keyARROWLEFT, _is_keyARROWDOWN, _is_keyARROWRIGHT, _is_keyPAD0, _is_keyPAD1, _is_keyPAD2, _is_keyPAD3, + _is_keyPAD4, _is_keyPAD5, _is_keyPAD6, _is_keyPAD7, _is_keyPAD8, _is_keyPAD9, _is_keyPADADD, _is_keyPADSUB, + _is_keyPADMUL, _is_keyPADDIV; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- + +#ifdef cimgdisplay_plugin +#include cimgdisplay_plugin +#endif +#ifdef cimgdisplay_plugin1 +#include cimgdisplay_plugin1 +#endif +#ifdef cimgdisplay_plugin2 +#include cimgdisplay_plugin2 +#endif +#ifdef cimgdisplay_plugin3 +#include cimgdisplay_plugin3 +#endif +#ifdef cimgdisplay_plugin4 +#include cimgdisplay_plugin4 +#endif +#ifdef cimgdisplay_plugin5 +#include cimgdisplay_plugin5 +#endif +#ifdef cimgdisplay_plugin6 +#include cimgdisplay_plugin6 +#endif +#ifdef cimgdisplay_plugin7 +#include cimgdisplay_plugin7 +#endif +#ifdef cimgdisplay_plugin8 +#include cimgdisplay_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + \note If the associated window is visible on the screen, it is closed by the call to the destructor. + **/ + ~CImgDisplay() { + assign(); + delete[] _keys; + delete[] _released_keys; + } + + //! Construct an empty display. + /** + \note Constructing an empty CImgDisplay instance does not make a window appearing on the screen, until + display of valid data is performed. + \par Example + \code + CImgDisplay disp; // Does actually nothing + ... + disp.display(img); // Construct new window and display image in it + \endcode + **/ + CImgDisplay(): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(); + } + + //! Construct a display with specified dimensions. + /** \param width Window width. + \param height Window height. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note A black background is initially displayed on the associated window. + **/ + CImgDisplay(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(width,height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image. + /** \param img Image used as a model to create the window. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note The pixels of the input image are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(img,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list. + /** \param list The images list to display. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note All images of the list, appended along the X-axis, are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(list,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of an existing one. + /** + \param disp Display instance to copy. + \note The pixel buffer of the input window is initially displayed on the associated window. + **/ + CImgDisplay(const CImgDisplay& disp): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(disp); + } + + //! Take a screenshot. + /** + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(CImg& img) { + return screenshot(0,0,cimg::type::max(),cimg::type::max(),img); + } + +#if cimg_display==0 + + static void _no_display_exception() { + throw CImgDisplayException("CImgDisplay(): No display available."); + } + + //! Destructor - Empty constructor \inplace. + /** + \note Replace the current instance by an empty display. + **/ + CImgDisplay& assign() { + return flush(); + } + + //! Construct a display with specified dimensions \inplace. + /** + **/ + CImgDisplay& assign(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + cimg::unused(width,height,title,normalization,is_fullscreen,is_closed); + _no_display_exception(); + return assign(); + } + + //! Construct a display from an image \inplace. + /** + **/ + template + CImgDisplay& assign(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(img._width,img._height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list \inplace. + /** + **/ + template + CImgDisplay& assign(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(list._width,list._width,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of another one \inplace. + /** + **/ + CImgDisplay& assign(const CImgDisplay &disp) { + _no_display_exception(); + return assign(disp._width,disp._height); + } + +#endif + + //! Return a reference to an empty display. + /** + \note Can be useful for writing function prototypes where one of the argument (of type CImgDisplay&) + must have a default value. + \par Example + \code + void foo(CImgDisplay& disp=CImgDisplay::empty()); + \endcode + **/ + static CImgDisplay& empty() { + static CImgDisplay _empty; + return _empty.assign(); + } + + //! Return a reference to an empty display \const. + static const CImgDisplay& const_empty() { + static const CImgDisplay _empty; + return _empty; + } + +#define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,-25,-85,false), \ + CImgDisplay::_fitscreen(dx,dy,dz,-25,-85,true) + static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy, const unsigned int dz, + const int dmin, const int dmax, const bool return_y) { + const int + u = CImgDisplay::screen_width(), + v = CImgDisplay::screen_height(); + const float + mw = dmin<0?cimg::round(u*-dmin/100.f):(float)dmin, + mh = dmin<0?cimg::round(v*-dmin/100.f):(float)dmin, + Mw = dmax<0?cimg::round(u*-dmax/100.f):(float)dmax, + Mh = dmax<0?cimg::round(v*-dmax/100.f):(float)dmax; + float + w = (float)std::max(1U,dx), + h = (float)std::max(1U,dy); + if (dz>1) { w+=dz; h+=dz; } + if (wMw) { h = h*Mw/w; w = Mw; } + if (h>Mh) { w = w*Mh/h; h = Mh; } + if (wdisp = img is equivalent to disp.display(img). + **/ + template + CImgDisplay& operator=(const CImg& img) { + return display(img); + } + + //! Display list of images on associated window. + /** + \note disp = list is equivalent to disp.display(list). + **/ + template + CImgDisplay& operator=(const CImgList& list) { + return display(list); + } + + //! Construct a display as a copy of another one \inplace. + /** + \note Equivalent to assign(const CImgDisplay&). + **/ + CImgDisplay& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return \c false if display is empty, \c true otherwise. + /** + \note if (disp) { ... } is equivalent to if (!disp.is_empty()) { ... }. + **/ + operator bool() const { + return !is_empty(); + } + + //@} + //------------------------------------------ + // + //! \name Instance Checking + //@{ + //------------------------------------------ + + //! Return \c true if display is empty, \c false otherwise. + /** + **/ + bool is_empty() const { + return !(_width && _height); + } + + //! Return \c true if display is closed (i.e. not visible on the screen), \c false otherwise. + /** + \note + - When a user physically closes the associated window, the display is set to closed. + - A closed display is not destroyed. Its associated window can be show again on the screen using show(). + **/ + bool is_closed() const { + return _is_closed; + } + + //! Return \c true if associated window has been resized on the screen, \c false otherwise. + /** + **/ + bool is_resized() const { + return _is_resized; + } + + //! Return \c true if associated window has been moved on the screen, \c false otherwise. + /** + **/ + bool is_moved() const { + return _is_moved; + } + + //! Return \c true if any event has occurred on the associated window, \c false otherwise. + /** + **/ + bool is_event() const { + return _is_event; + } + + //! Return \c true if current display is in fullscreen mode, \c false otherwise. + /** + **/ + bool is_fullscreen() const { + return _is_fullscreen; + } + + //! Return \c true if any key is being pressed on the associated window, \c false otherwise. + /** + \note The methods below do the same only for specific keys. + **/ + bool is_key() const { + return _is_keyESC || _is_keyF1 || _is_keyF2 || _is_keyF3 || + _is_keyF4 || _is_keyF5 || _is_keyF6 || _is_keyF7 || + _is_keyF8 || _is_keyF9 || _is_keyF10 || _is_keyF11 || + _is_keyF12 || _is_keyPAUSE || _is_key1 || _is_key2 || + _is_key3 || _is_key4 || _is_key5 || _is_key6 || + _is_key7 || _is_key8 || _is_key9 || _is_key0 || + _is_keyBACKSPACE || _is_keyINSERT || _is_keyHOME || + _is_keyPAGEUP || _is_keyTAB || _is_keyQ || _is_keyW || + _is_keyE || _is_keyR || _is_keyT || _is_keyY || + _is_keyU || _is_keyI || _is_keyO || _is_keyP || + _is_keyDELETE || _is_keyEND || _is_keyPAGEDOWN || + _is_keyCAPSLOCK || _is_keyA || _is_keyS || _is_keyD || + _is_keyF || _is_keyG || _is_keyH || _is_keyJ || + _is_keyK || _is_keyL || _is_keyENTER || + _is_keySHIFTLEFT || _is_keyZ || _is_keyX || _is_keyC || + _is_keyV || _is_keyB || _is_keyN || _is_keyM || + _is_keySHIFTRIGHT || _is_keyARROWUP || _is_keyCTRLLEFT || + _is_keyAPPLEFT || _is_keyALT || _is_keySPACE || _is_keyALTGR || + _is_keyAPPRIGHT || _is_keyMENU || _is_keyCTRLRIGHT || + _is_keyARROWLEFT || _is_keyARROWDOWN || _is_keyARROWRIGHT || + _is_keyPAD0 || _is_keyPAD1 || _is_keyPAD2 || + _is_keyPAD3 || _is_keyPAD4 || _is_keyPAD5 || + _is_keyPAD6 || _is_keyPAD7 || _is_keyPAD8 || + _is_keyPAD9 || _is_keyPADADD || _is_keyPADSUB || + _is_keyPADMUL || _is_keyPADDIV; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode Keycode to test. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.key(cimg::keyTAB)) { ... } // Equivalent to 'if (disp.is_keyTAB())' + disp.wait(); + } + \endcode + **/ + bool is_key(const unsigned int keycode) const { +#define _cimg_iskey_test(k) if (keycode==cimg::key##k) return _is_key##k; + _cimg_iskey_test(ESC); _cimg_iskey_test(F1); _cimg_iskey_test(F2); _cimg_iskey_test(F3); + _cimg_iskey_test(F4); _cimg_iskey_test(F5); _cimg_iskey_test(F6); _cimg_iskey_test(F7); + _cimg_iskey_test(F8); _cimg_iskey_test(F9); _cimg_iskey_test(F10); _cimg_iskey_test(F11); + _cimg_iskey_test(F12); _cimg_iskey_test(PAUSE); _cimg_iskey_test(1); _cimg_iskey_test(2); + _cimg_iskey_test(3); _cimg_iskey_test(4); _cimg_iskey_test(5); _cimg_iskey_test(6); + _cimg_iskey_test(7); _cimg_iskey_test(8); _cimg_iskey_test(9); _cimg_iskey_test(0); + _cimg_iskey_test(BACKSPACE); _cimg_iskey_test(INSERT); _cimg_iskey_test(HOME); + _cimg_iskey_test(PAGEUP); _cimg_iskey_test(TAB); _cimg_iskey_test(Q); _cimg_iskey_test(W); + _cimg_iskey_test(E); _cimg_iskey_test(R); _cimg_iskey_test(T); _cimg_iskey_test(Y); + _cimg_iskey_test(U); _cimg_iskey_test(I); _cimg_iskey_test(O); _cimg_iskey_test(P); + _cimg_iskey_test(DELETE); _cimg_iskey_test(END); _cimg_iskey_test(PAGEDOWN); + _cimg_iskey_test(CAPSLOCK); _cimg_iskey_test(A); _cimg_iskey_test(S); _cimg_iskey_test(D); + _cimg_iskey_test(F); _cimg_iskey_test(G); _cimg_iskey_test(H); _cimg_iskey_test(J); + _cimg_iskey_test(K); _cimg_iskey_test(L); _cimg_iskey_test(ENTER); + _cimg_iskey_test(SHIFTLEFT); _cimg_iskey_test(Z); _cimg_iskey_test(X); _cimg_iskey_test(C); + _cimg_iskey_test(V); _cimg_iskey_test(B); _cimg_iskey_test(N); _cimg_iskey_test(M); + _cimg_iskey_test(SHIFTRIGHT); _cimg_iskey_test(ARROWUP); _cimg_iskey_test(CTRLLEFT); + _cimg_iskey_test(APPLEFT); _cimg_iskey_test(ALT); _cimg_iskey_test(SPACE); _cimg_iskey_test(ALTGR); + _cimg_iskey_test(APPRIGHT); _cimg_iskey_test(MENU); _cimg_iskey_test(CTRLRIGHT); + _cimg_iskey_test(ARROWLEFT); _cimg_iskey_test(ARROWDOWN); _cimg_iskey_test(ARROWRIGHT); + _cimg_iskey_test(PAD0); _cimg_iskey_test(PAD1); _cimg_iskey_test(PAD2); + _cimg_iskey_test(PAD3); _cimg_iskey_test(PAD4); _cimg_iskey_test(PAD5); + _cimg_iskey_test(PAD6); _cimg_iskey_test(PAD7); _cimg_iskey_test(PAD8); + _cimg_iskey_test(PAD9); _cimg_iskey_test(PADADD); _cimg_iskey_test(PADSUB); + _cimg_iskey_test(PADMUL); _cimg_iskey_test(PADDIV); + return false; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode C-string containing the keycode label of the key to test. + \note Use it when the key you want to test can be dynamically set by the user. + \par Example + \code + CImgDisplay disp(400,400); + const char *const keycode = "TAB"; + while (!disp.is_closed()) { + if (disp.is_key(keycode)) { ... } // Equivalent to 'if (disp.is_keyTAB())' + disp.wait(); + } + \endcode + **/ + bool& is_key(const char *const keycode) { + static bool f = false; + f = false; +#define _cimg_iskey_test2(k) if (!cimg::strcasecmp(keycode,#k)) return _is_key##k; + _cimg_iskey_test2(ESC); _cimg_iskey_test2(F1); _cimg_iskey_test2(F2); _cimg_iskey_test2(F3); + _cimg_iskey_test2(F4); _cimg_iskey_test2(F5); _cimg_iskey_test2(F6); _cimg_iskey_test2(F7); + _cimg_iskey_test2(F8); _cimg_iskey_test2(F9); _cimg_iskey_test2(F10); _cimg_iskey_test2(F11); + _cimg_iskey_test2(F12); _cimg_iskey_test2(PAUSE); _cimg_iskey_test2(1); _cimg_iskey_test2(2); + _cimg_iskey_test2(3); _cimg_iskey_test2(4); _cimg_iskey_test2(5); _cimg_iskey_test2(6); + _cimg_iskey_test2(7); _cimg_iskey_test2(8); _cimg_iskey_test2(9); _cimg_iskey_test2(0); + _cimg_iskey_test2(BACKSPACE); _cimg_iskey_test2(INSERT); _cimg_iskey_test2(HOME); + _cimg_iskey_test2(PAGEUP); _cimg_iskey_test2(TAB); _cimg_iskey_test2(Q); _cimg_iskey_test2(W); + _cimg_iskey_test2(E); _cimg_iskey_test2(R); _cimg_iskey_test2(T); _cimg_iskey_test2(Y); + _cimg_iskey_test2(U); _cimg_iskey_test2(I); _cimg_iskey_test2(O); _cimg_iskey_test2(P); + _cimg_iskey_test2(DELETE); _cimg_iskey_test2(END); _cimg_iskey_test2(PAGEDOWN); + _cimg_iskey_test2(CAPSLOCK); _cimg_iskey_test2(A); _cimg_iskey_test2(S); _cimg_iskey_test2(D); + _cimg_iskey_test2(F); _cimg_iskey_test2(G); _cimg_iskey_test2(H); _cimg_iskey_test2(J); + _cimg_iskey_test2(K); _cimg_iskey_test2(L); _cimg_iskey_test2(ENTER); + _cimg_iskey_test2(SHIFTLEFT); _cimg_iskey_test2(Z); _cimg_iskey_test2(X); _cimg_iskey_test2(C); + _cimg_iskey_test2(V); _cimg_iskey_test2(B); _cimg_iskey_test2(N); _cimg_iskey_test2(M); + _cimg_iskey_test2(SHIFTRIGHT); _cimg_iskey_test2(ARROWUP); _cimg_iskey_test2(CTRLLEFT); + _cimg_iskey_test2(APPLEFT); _cimg_iskey_test2(ALT); _cimg_iskey_test2(SPACE); _cimg_iskey_test2(ALTGR); + _cimg_iskey_test2(APPRIGHT); _cimg_iskey_test2(MENU); _cimg_iskey_test2(CTRLRIGHT); + _cimg_iskey_test2(ARROWLEFT); _cimg_iskey_test2(ARROWDOWN); _cimg_iskey_test2(ARROWRIGHT); + _cimg_iskey_test2(PAD0); _cimg_iskey_test2(PAD1); _cimg_iskey_test2(PAD2); + _cimg_iskey_test2(PAD3); _cimg_iskey_test2(PAD4); _cimg_iskey_test2(PAD5); + _cimg_iskey_test2(PAD6); _cimg_iskey_test2(PAD7); _cimg_iskey_test2(PAD8); + _cimg_iskey_test2(PAD9); _cimg_iskey_test2(PADADD); _cimg_iskey_test2(PADSUB); + _cimg_iskey_test2(PADMUL); _cimg_iskey_test2(PADDIV); + return f; + } + + //! Return \c true if specified key sequence has been typed on the associated window, \c false otherwise. + /** + \param keycodes_sequence Buffer of keycodes to test. + \param length Number of keys in the \c keycodes_sequence buffer. + \param remove_sequence Tells if the key sequence must be removed from the key history, if found. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + const unsigned int key_seq[] = { cimg::keyCTRLLEFT, cimg::keyD }; + while (!disp.is_closed()) { + if (disp.is_key_sequence(key_seq,2)) { ... } // Test for the 'CTRL+D' keyboard event + disp.wait(); + } + \endcode + **/ + bool is_key_sequence(const unsigned int *const keycodes_sequence, const unsigned int length, + const bool remove_sequence=false) { + if (keycodes_sequence && length) { + const unsigned int + *const ps_end = keycodes_sequence + length - 1, + *const pk_end = (unsigned int*)_keys + 1 + 128 - length, + k = *ps_end; + for (unsigned int *pk = (unsigned int*)_keys; pk[0,255]. + If the range of values of the data to display is different, a normalization may be required for displaying + the data in a correct way. The normalization type can be one of: + - \c 0: Value normalization is disabled. It is then assumed that all input data to be displayed by the + CImgDisplay instance have values in range [0,255]. + - \c 1: Value normalization is always performed (this is the default behavior). + Before displaying an input image, its values will be (virtually) stretched + in range [0,255], so that the contrast of the displayed pixels will be maximum. + Use this mode for images whose minimum and maximum values are not prescribed to known values + (e.g. float-valued images). + Note that when normalized versions of images are computed for display purposes, the actual values of these + images are not modified. + - \c 2: Value normalization is performed once (on the first image display), then the same normalization + coefficients are kept for next displayed frames. + - \c 3: Value normalization depends on the pixel type of the data to display. For integer pixel types, + the normalization is done regarding the minimum/maximum values of the type (no normalization occurs then + for unsigned char). + For float-valued pixel types, the normalization is done regarding the minimum/maximum value of the image + data instead. + **/ + unsigned int normalization() const { + return _normalization; + } + + //! Return title of the associated window as a C-string. + /** + \note Window title may be not visible, depending on the used window manager or if the current display is + in fullscreen mode. + **/ + const char *title() const { + return _title?_title:""; + } + + //! Return width of the associated window. + /** + \note The width of the display (i.e. the width of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual width of the associated window. + **/ + int window_width() const { + return (int)_window_width; + } + + //! Return height of the associated window. + /** + \note The height of the display (i.e. the height of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual height of the associated window. + **/ + int window_height() const { + return (int)_window_height; + } + + //! Return X-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_x() const { + return _window_x; + } + + //! Return Y-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_y() const { + return _window_y; + } + + //! Return X-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,width()-1]. + **/ + int mouse_x() const { + return _mouse_x; + } + + //! Return Y-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,height()-1]. + **/ + int mouse_y() const { + return _mouse_y; + } + + //! Return current state of the mouse buttons. + /** + \note Three mouse buttons can be managed. If one button is pressed, its corresponding bit in the returned + value is set: + - bit \c 0 (value \c 0x1): State of the left mouse button. + - bit \c 1 (value \c 0x2): State of the right mouse button. + - bit \c 2 (value \c 0x4): State of the middle mouse button. + + Several bits can be activated if more than one button are pressed at the same time. + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.button()&1) { // Left button clicked + ... + } + if (disp.button()&2) { // Right button clicked + ... + } + if (disp.button()&4) { // Middle button clicked + ... + } + disp.wait(); + } + \endcode + **/ + unsigned int button() const { + return _button; + } + + //! Return current state of the mouse wheel. + /** + \note + - The returned value can be positive or negative depending on whether the mouse wheel has been scrolled + forward or backward. + - Scrolling the wheel forward add \c 1 to the wheel value. + - Scrolling the wheel backward subtract \c 1 to the wheel value. + - The returned value cumulates the number of forward of backward scrolls since the creation of the display, + or since the last reset of the wheel value (using set_wheel()). It is strongly recommended to quickly reset + the wheel counter when an action has been performed regarding the current wheel value. + Otherwise, the returned wheel value may be for instance \c 0 despite the fact that many scrolls have been done + (as many in forward as in backward directions). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.wheel()) { + int counter = disp.wheel(); // Read the state of the mouse wheel + ... // Do what you want with 'counter' + disp.set_wheel(); // Reset the wheel value to 0 + } + disp.wait(); + } + \endcode + **/ + int wheel() const { + return _wheel; + } + + //! Return one entry from the pressed keys history. + /** + \param pos Index to read from the pressed keys history (index \c 0 corresponds to latest entry). + \return Keycode of a pressed key or \c 0 for a released key. + \note + - Each CImgDisplay stores a history of the pressed keys in a buffer of size \c 128. When a new key is pressed, + its keycode is stored in the pressed keys history. When a key is released, \c 0 is put instead. + This means that up to the 64 last pressed keys may be read from the pressed keys history. + When a new value is stored, the pressed keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int& key(const unsigned int pos=0) const { + static unsigned int key0; + return pos<128?_keys[pos]:(key0 = 0); + + } + + //! Return one entry from the released keys history. + /** + \param pos Index to read from the released keys history (index \c 0 corresponds to latest entry). + \return Keycode of a released key or \c 0 for a pressed key. + \note + - Each CImgDisplay stores a history of the released keys in a buffer of size \c 128. When a new key is released, + its keycode is stored in the pressed keys history. When a key is pressed, \c 0 is put instead. + This means that up to the 64 last released keys may be read from the released keys history. + When a new value is stored, the released keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int& released_key(const unsigned int pos=0) const { + static unsigned int key0; + return pos<128?_released_keys[pos]:(key0 = 0); + } + + //! Return keycode corresponding to the specified string. + /** + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + const unsigned int keyTAB = CImgDisplay::keycode("TAB"); // Return cimg::keyTAB + \endcode + **/ + static unsigned int keycode(const char *const keycode) { +#define _cimg_keycode(k) if (!cimg::strcasecmp(keycode,#k)) return cimg::key##k; + _cimg_keycode(ESC); _cimg_keycode(F1); _cimg_keycode(F2); _cimg_keycode(F3); + _cimg_keycode(F4); _cimg_keycode(F5); _cimg_keycode(F6); _cimg_keycode(F7); + _cimg_keycode(F8); _cimg_keycode(F9); _cimg_keycode(F10); _cimg_keycode(F11); + _cimg_keycode(F12); _cimg_keycode(PAUSE); _cimg_keycode(1); _cimg_keycode(2); + _cimg_keycode(3); _cimg_keycode(4); _cimg_keycode(5); _cimg_keycode(6); + _cimg_keycode(7); _cimg_keycode(8); _cimg_keycode(9); _cimg_keycode(0); + _cimg_keycode(BACKSPACE); _cimg_keycode(INSERT); _cimg_keycode(HOME); + _cimg_keycode(PAGEUP); _cimg_keycode(TAB); _cimg_keycode(Q); _cimg_keycode(W); + _cimg_keycode(E); _cimg_keycode(R); _cimg_keycode(T); _cimg_keycode(Y); + _cimg_keycode(U); _cimg_keycode(I); _cimg_keycode(O); _cimg_keycode(P); + _cimg_keycode(DELETE); _cimg_keycode(END); _cimg_keycode(PAGEDOWN); + _cimg_keycode(CAPSLOCK); _cimg_keycode(A); _cimg_keycode(S); _cimg_keycode(D); + _cimg_keycode(F); _cimg_keycode(G); _cimg_keycode(H); _cimg_keycode(J); + _cimg_keycode(K); _cimg_keycode(L); _cimg_keycode(ENTER); + _cimg_keycode(SHIFTLEFT); _cimg_keycode(Z); _cimg_keycode(X); _cimg_keycode(C); + _cimg_keycode(V); _cimg_keycode(B); _cimg_keycode(N); _cimg_keycode(M); + _cimg_keycode(SHIFTRIGHT); _cimg_keycode(ARROWUP); _cimg_keycode(CTRLLEFT); + _cimg_keycode(APPLEFT); _cimg_keycode(ALT); _cimg_keycode(SPACE); _cimg_keycode(ALTGR); + _cimg_keycode(APPRIGHT); _cimg_keycode(MENU); _cimg_keycode(CTRLRIGHT); + _cimg_keycode(ARROWLEFT); _cimg_keycode(ARROWDOWN); _cimg_keycode(ARROWRIGHT); + _cimg_keycode(PAD0); _cimg_keycode(PAD1); _cimg_keycode(PAD2); + _cimg_keycode(PAD3); _cimg_keycode(PAD4); _cimg_keycode(PAD5); + _cimg_keycode(PAD6); _cimg_keycode(PAD7); _cimg_keycode(PAD8); + _cimg_keycode(PAD9); _cimg_keycode(PADADD); _cimg_keycode(PADSUB); + _cimg_keycode(PADMUL); _cimg_keycode(PADDIV); + return 0; + } + + //! Return the current refresh rate, in frames per second. + /** + \note Returns a significant value when the current instance is used to display successive frames. + It measures the delay between successive calls to frames_per_second(). + **/ + float frames_per_second() { + if (!_fps_timer) _fps_timer = cimg::time(); + const float delta = (float)((cimg::time() - _fps_timer)/1000.f); + ++_fps_frames; + if (delta>=1) { + _fps_fps = _fps_frames/delta; + _fps_frames = 0; + _fps_timer = cimg::time(); + } + return _fps_fps; + } + + // Move current display window so that its content stays inside the current screen. + CImgDisplay& move_inside_screen() { + if (is_empty()) return *this; + const int + x0 = window_x(), + y0 = window_y(), + x1 = x0 + window_width() - 1, + y1 = y0 + window_height() - 1, + sw = CImgDisplay::screen_width(), + sh = CImgDisplay::screen_height(); + if (x0<0 || y0<0 || x1>=sw || y1>=sh) + move(std::max(0,std::min(x0,sw - x1 + x0)), + std::max(0,std::min(y0,sh - y1 + y0))); + return *this; + } + + //@} + //--------------------------------------- + // + //! \name Window Manipulation + //@{ + //--------------------------------------- + +#if cimg_display==0 + + //! Display image on associated window. + /** + \param img Input image to display. + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImg& img) { + return assign(img); + } + +#endif + + //! Display list of images on associated window. + /** + \param list List of images to display. + \param axis Axis used to append the images along, for the visualization (can be \c x, \c y, \c z or \c c). + \param align Relative position of aligned images when displaying lists with images of different sizes + (\c 0 for upper-left, \c 0.5 for centering and \c 1 for lower-right). + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImgList& list, const char axis='x', const float align=0) { + if (list._width==1) { + const CImg& img = list[0]; + if (img._depth==1 && (img._spectrum==1 || img._spectrum>=3) && _normalization!=1) return display(img); + } + CImgList::ucharT> visu(list._width); + unsigned int dims = 0; + cimglist_for(list,l) { + const CImg& img = list._data[l]; + img._get_select(*this,_normalization,(img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2).move_to(visu[l]); + dims = std::max(dims,visu[l]._spectrum); + } + cimglist_for(list,l) if (visu[l]._spectrumimg.width() become equal, as well as height() and + img.height(). + - The associated window is also resized to specified dimensions. + **/ + template + CImgDisplay& resize(const CImg& img, const bool force_redraw=true) { + return resize(img._width,img._height,force_redraw); + } + + //! Resize display to the size of another CImgDisplay instance. + /** + \param disp Input display to take size from. + \param force_redraw Tells if the previous window content must be resized and updated as well. + \note + - Calling this method ensures that width() and disp.width() become equal, as well as height() and + disp.height(). + - The associated window is also resized to specified dimensions. + **/ + CImgDisplay& resize(const CImgDisplay& disp, const bool force_redraw=true) { + return resize(disp.width(),disp.height(),force_redraw); + } + + // [internal] Render pixel buffer with size (wd,hd) from source buffer of size (ws,hs). + template + static void _render_resize(const T *ptrs, const unsigned int ws, const unsigned int hs, + t *ptrd, const unsigned int wd, const unsigned int hd) { + typedef typename cimg::last::type ulongT; + const ulongT one = (ulongT)1; + CImg off_x(wd), off_y(hd + 1); + if (wd==ws) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + for (unsigned int x = 0; xstd::printf(). + \warning As the first argument is a format string, it is highly recommended to write + \code + disp.set_title("%s",window_title); + \endcode + instead of + \code + disp.set_title(window_title); + \endcode + if \c window_title can be arbitrary, to prevent nasty memory access. + **/ + CImgDisplay& set_title(const char *const format, ...) { + return assign(0,0,format); + } + +#endif + + //! Enable or disable fullscreen mode. + /** + \param is_fullscreen Tells is the fullscreen mode must be activated or not. + \param force_redraw Tells if the previous window content must be displayed as well. + \note + - When the fullscreen mode is enabled, the associated window fills the entire screen but the size of the + current display is not modified. + - The screen resolution may be switched to fit the associated window size and ensure it appears the largest + as possible. + For X-Window (X11) users, the configuration flag \c cimg_use_xrandr has to be set to allow the screen + resolution change (requires the X11 extensions to be enabled). + **/ + CImgDisplay& set_fullscreen(const bool is_fullscreen, const bool force_redraw=true) { + if (is_empty() || _is_fullscreen==is_fullscreen) return *this; + return toggle_fullscreen(force_redraw); + } + +#if cimg_display==0 + + //! Toggle fullscreen mode. + /** + \param force_redraw Tells if the previous window content must be displayed as well. + \note Enable fullscreen mode if it was not enabled, and disable it otherwise. + **/ + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + return assign(_width,_height,0,3,force_redraw); + } + + //! Show mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& show_mouse() { + return assign(); + } + + //! Hide mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& hide_mouse() { + return assign(); + } + + //! Move mouse pointer to a specified location. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& set_mouse(const int pos_x, const int pos_y) { + return assign(pos_x,pos_y); + } + +#endif + + //! Simulate a mouse button release event. + /** + \note All mouse buttons are considered released at the same time. + **/ + CImgDisplay& set_button() { + _button = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a mouse button press or release event. + /** + \param button Buttons event code, where each button is associated to a single bit. + \param is_pressed Tells if the mouse button is considered as pressed or released. + **/ + CImgDisplay& set_button(const unsigned int button, const bool is_pressed=true) { + const unsigned int buttoncode = button==1U?1U:button==2U?2U:button==3U?4U:0U; + if (is_pressed) _button |= buttoncode; else _button &= ~buttoncode; + _is_event = buttoncode?true:false; + if (buttoncode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all mouse wheel events. + /** + \note Make wheel() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_wheel() { + _wheel = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a wheel event. + /** + \param amplitude Amplitude of the wheel scrolling to simulate. + \note Make wheel() to return \c amplitude, if called afterwards. + **/ + CImgDisplay& set_wheel(const int amplitude) { + _wheel+=amplitude; + _is_event = amplitude?true:false; + if (amplitude) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all key events. + /** + \note Make key() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_key() { + std::memset((void*)_keys,0,128*sizeof(unsigned int)); + std::memset((void*)_released_keys,0,128*sizeof(unsigned int)); + _is_keyESC = _is_keyF1 = _is_keyF2 = _is_keyF3 = _is_keyF4 = _is_keyF5 = _is_keyF6 = _is_keyF7 = _is_keyF8 = + _is_keyF9 = _is_keyF10 = _is_keyF11 = _is_keyF12 = _is_keyPAUSE = _is_key1 = _is_key2 = _is_key3 = _is_key4 = + _is_key5 = _is_key6 = _is_key7 = _is_key8 = _is_key9 = _is_key0 = _is_keyBACKSPACE = _is_keyINSERT = + _is_keyHOME = _is_keyPAGEUP = _is_keyTAB = _is_keyQ = _is_keyW = _is_keyE = _is_keyR = _is_keyT = _is_keyY = + _is_keyU = _is_keyI = _is_keyO = _is_keyP = _is_keyDELETE = _is_keyEND = _is_keyPAGEDOWN = _is_keyCAPSLOCK = + _is_keyA = _is_keyS = _is_keyD = _is_keyF = _is_keyG = _is_keyH = _is_keyJ = _is_keyK = _is_keyL = + _is_keyENTER = _is_keySHIFTLEFT = _is_keyZ = _is_keyX = _is_keyC = _is_keyV = _is_keyB = _is_keyN = + _is_keyM = _is_keySHIFTRIGHT = _is_keyARROWUP = _is_keyCTRLLEFT = _is_keyAPPLEFT = _is_keyALT = _is_keySPACE = + _is_keyALTGR = _is_keyAPPRIGHT = _is_keyMENU = _is_keyCTRLRIGHT = _is_keyARROWLEFT = _is_keyARROWDOWN = + _is_keyARROWRIGHT = _is_keyPAD0 = _is_keyPAD1 = _is_keyPAD2 = _is_keyPAD3 = _is_keyPAD4 = _is_keyPAD5 = + _is_keyPAD6 = _is_keyPAD7 = _is_keyPAD8 = _is_keyPAD9 = _is_keyPADADD = _is_keyPADSUB = _is_keyPADMUL = + _is_keyPADDIV = false; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a keyboard press/release event. + /** + \param keycode Keycode of the associated key. + \param is_pressed Tells if the key is considered as pressed or released. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + CImgDisplay& set_key(const unsigned int keycode, const bool is_pressed=true) { +#define _cimg_set_key(k) if (keycode==cimg::key##k) _is_key##k = is_pressed; + _cimg_set_key(ESC); _cimg_set_key(F1); _cimg_set_key(F2); _cimg_set_key(F3); + _cimg_set_key(F4); _cimg_set_key(F5); _cimg_set_key(F6); _cimg_set_key(F7); + _cimg_set_key(F8); _cimg_set_key(F9); _cimg_set_key(F10); _cimg_set_key(F11); + _cimg_set_key(F12); _cimg_set_key(PAUSE); _cimg_set_key(1); _cimg_set_key(2); + _cimg_set_key(3); _cimg_set_key(4); _cimg_set_key(5); _cimg_set_key(6); + _cimg_set_key(7); _cimg_set_key(8); _cimg_set_key(9); _cimg_set_key(0); + _cimg_set_key(BACKSPACE); _cimg_set_key(INSERT); _cimg_set_key(HOME); + _cimg_set_key(PAGEUP); _cimg_set_key(TAB); _cimg_set_key(Q); _cimg_set_key(W); + _cimg_set_key(E); _cimg_set_key(R); _cimg_set_key(T); _cimg_set_key(Y); + _cimg_set_key(U); _cimg_set_key(I); _cimg_set_key(O); _cimg_set_key(P); + _cimg_set_key(DELETE); _cimg_set_key(END); _cimg_set_key(PAGEDOWN); + _cimg_set_key(CAPSLOCK); _cimg_set_key(A); _cimg_set_key(S); _cimg_set_key(D); + _cimg_set_key(F); _cimg_set_key(G); _cimg_set_key(H); _cimg_set_key(J); + _cimg_set_key(K); _cimg_set_key(L); _cimg_set_key(ENTER); + _cimg_set_key(SHIFTLEFT); _cimg_set_key(Z); _cimg_set_key(X); _cimg_set_key(C); + _cimg_set_key(V); _cimg_set_key(B); _cimg_set_key(N); _cimg_set_key(M); + _cimg_set_key(SHIFTRIGHT); _cimg_set_key(ARROWUP); _cimg_set_key(CTRLLEFT); + _cimg_set_key(APPLEFT); _cimg_set_key(ALT); _cimg_set_key(SPACE); _cimg_set_key(ALTGR); + _cimg_set_key(APPRIGHT); _cimg_set_key(MENU); _cimg_set_key(CTRLRIGHT); + _cimg_set_key(ARROWLEFT); _cimg_set_key(ARROWDOWN); _cimg_set_key(ARROWRIGHT); + _cimg_set_key(PAD0); _cimg_set_key(PAD1); _cimg_set_key(PAD2); + _cimg_set_key(PAD3); _cimg_set_key(PAD4); _cimg_set_key(PAD5); + _cimg_set_key(PAD6); _cimg_set_key(PAD7); _cimg_set_key(PAD8); + _cimg_set_key(PAD9); _cimg_set_key(PADADD); _cimg_set_key(PADSUB); + _cimg_set_key(PADMUL); _cimg_set_key(PADDIV); + if (is_pressed) { + if (*_keys) + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = keycode; + if (*_released_keys) { + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = 0; + } + } else { + if (*_keys) { + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = 0; + } + if (*_released_keys) + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = keycode; + } + _is_event = keycode?true:false; + if (keycode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all display events. + /** + \note Remove all passed events from the current display. + **/ + CImgDisplay& flush() { + set_key().set_button().set_wheel(); + _is_resized = _is_moved = _is_event = false; + _fps_timer = _fps_frames = _timer = 0; + _fps_fps = 0; + return *this; + } + + //! Wait for any user event occurring on the current display. + CImgDisplay& wait() { + wait(*this); + return *this; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \note Similar to cimg::wait(). + **/ + CImgDisplay& wait(const unsigned int milliseconds) { + cimg::wait(milliseconds,&_timer); + return *this; + } + + //! Wait for any event occurring on the display \c disp1. + static void wait(CImgDisplay& disp1) { + disp1._is_event = false; + while (!disp1._is_closed && !disp1._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1 or \c disp2. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2) { + disp1._is_event = disp2._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed) && + !disp1._is_event && !disp2._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2 or \c disp3. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3) { + disp1._is_event = disp2._is_event = disp3._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3 or \c disp4. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4 or \c disp5. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, + CImgDisplay& disp5) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event) + wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp6. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp7. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp8. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp9. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp10. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9, + CImgDisplay& disp10) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = disp10._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed || !disp10._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event && !disp10._is_event) + wait_all(); + } + +#if cimg_display==0 + + //! Wait for any window event occurring in any opened CImgDisplay. + static void wait_all() { + return _no_display_exception(); + } + + //! Render image into internal display buffer. + /** + \param img Input image data to render. + \note + - Convert image data representation into the internal display buffer (architecture-dependent structure). + - The content of the associated window is not modified, until paint() is called. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + template + CImgDisplay& render(const CImg& img) { + return assign(img); + } + + //! Paint internal display buffer on associated window. + /** + \note + - Update the content of the associated window with the internal display buffer, e.g. after a render() call. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + CImgDisplay& paint() { + return assign(); + } + + + //! Take a snapshot of the current screen content. + /** + \param x0 X-coordinate of the upper left corner. + \param y0 Y-coordinate of the upper left corner. + \param x1 X-coordinate of the lower right corner. + \param y1 Y-coordinate of the lower right corner. + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + cimg::unused(x0,y0,x1,y1,&img); + _no_display_exception(); + } + + //! Take a snapshot of the associated window content. + /** + \param[out] img Output snapshot. Can be empty on input. + **/ + template + const CImgDisplay& snapshot(CImg& img) const { + cimg::unused(img); + _no_display_exception(); + return *this; + } +#endif + + // X11-based implementation + //-------------------------- +#if cimg_display==1 + + Atom _wm_window_atom, _wm_protocol_atom; + Window _window, _background_window; + Colormap _colormap; + XImage *_image; + void *_data; + +#ifdef cimg_use_xshm + XShmSegmentInfo *_shminfo; +#endif + + static int screen_width() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_width(): Failed to open X11 display."); + res = DisplayWidth(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width; + else res = DisplayWidth(dpy,DefaultScreen(dpy)); +#else + res = DisplayWidth(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static int screen_height() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_height(): Failed to open X11 display."); + res = DisplayHeight(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height; + else res = DisplayHeight(dpy,DefaultScreen(dpy)); +#else + res = DisplayHeight(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static void wait_all() { + if (!cimg::X11_attr().display) return; + pthread_mutex_lock(&cimg::X11_attr().wait_event_mutex); + pthread_cond_wait(&cimg::X11_attr().wait_event,&cimg::X11_attr().wait_event_mutex); + pthread_mutex_unlock(&cimg::X11_attr().wait_event_mutex); + } + + void _handle_events(const XEvent *const pevent) { + Display *const dpy = cimg::X11_attr().display; + XEvent event = *pevent; + switch (event.type) { + case ClientMessage : { + if ((int)event.xclient.message_type==(int)_wm_protocol_atom && + (int)event.xclient.data.l[0]==(int)_wm_window_atom) { + XUnmapWindow(cimg::X11_attr().display,_window); + _is_closed = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case ConfigureNotify : { + while (XCheckWindowEvent(dpy,_window,StructureNotifyMask,&event)) {} + const unsigned int nw = event.xconfigure.width, nh = event.xconfigure.height; + const int nx = event.xconfigure.x, ny = event.xconfigure.y; + if (nw && nh && (nw!=_window_width || nh!=_window_height)) { + _window_width = nw; _window_height = nh; _mouse_x = _mouse_y = -1; + XResizeWindow(dpy,_window,_window_width,_window_height); + _is_resized = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + if (nx!=_window_x || ny!=_window_y) { + _window_x = nx; + _window_y = ny; + _is_moved = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case Expose : { + while (XCheckWindowEvent(dpy,_window,ExposureMask,&event)) {} + _paint(false); + if (_is_fullscreen) { + XWindowAttributes attr; + do { + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + XSetInputFocus(dpy,_window,RevertToParent,CurrentTime); + } + } break; + case ButtonPress : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1); break; + case 3 : set_button(2); break; + case 2 : set_button(3); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonPressMask,&event)); + } break; + case ButtonRelease : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1,false); break; + case 3 : set_button(2,false); break; + case 2 : set_button(3,false); break; + case 4 : set_wheel(1); break; + case 5 : set_wheel(-1); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonReleaseMask,&event)); + } break; + case KeyPress : { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,true); + } break; + case KeyRelease : { + char keys_return[32]; // Check that the key has been physically unpressed + XQueryKeymap(dpy,keys_return); + const unsigned int kc = event.xkey.keycode, kc1 = kc/8, kc2 = kc%8; + const bool is_key_pressed = kc1>=32?false:(keys_return[kc1]>>kc2)&1; + if (!is_key_pressed) { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,false); + } + } break; + case EnterNotify: { + while (XCheckWindowEvent(dpy,_window,EnterWindowMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + } break; + case LeaveNotify : { + while (XCheckWindowEvent(dpy,_window,LeaveWindowMask,&event)) {} + _mouse_x = _mouse_y = -1; _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + case MotionNotify : { + while (XCheckWindowEvent(dpy,_window,PointerMotionMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + } + } + + static void* _events_thread(void *arg) { // Thread to manage events for all opened display windows + Display *const dpy = cimg::X11_attr().display; + XEvent event; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); + if (!arg) for ( ; ; ) { + cimg_lock_display(); + bool event_flag = XCheckTypedEvent(dpy,ClientMessage,&event); + if (!event_flag) event_flag = XCheckMaskEvent(dpy, + ExposureMask | StructureNotifyMask | ButtonPressMask | + KeyPressMask | PointerMotionMask | EnterWindowMask | + LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask,&event); + if (event_flag) + for (unsigned int i = 0; i_is_closed && event.xany.window==cimg::X11_attr().wins[i]->_window) + cimg::X11_attr().wins[i]->_handle_events(&event); + cimg_unlock_display(); + pthread_testcancel(); + cimg::sleep(8); + } + return 0; + } + + void _set_colormap(Colormap& cmap, const unsigned int dim) { + XColor *const colormap = new XColor[256]; + switch (dim) { + case 1 : { // colormap for greyscale images + for (unsigned int index = 0; index<256; ++index) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].green = colormap[index].blue = (unsigned short)(index<<8); + colormap[index].flags = DoRed | DoGreen | DoBlue; + } + } break; + case 2 : { // colormap for RG images + for (unsigned int index = 0, r = 8; r<256; r+=16) + for (unsigned int g = 8; g<256; g+=16) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].blue = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } break; + default : { // colormap for RGB images + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap[index].pixel = index; + colormap[index].red = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index].blue = (unsigned short)(b<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } + } + XStoreColors(cimg::X11_attr().display,cmap,colormap,256); + delete[] colormap; + } + + void _map_window() { + Display *const dpy = cimg::X11_attr().display; + bool is_exposed = false, is_mapped = false; + XWindowAttributes attr; + XEvent event; + XMapRaised(dpy,_window); + do { // Wait for the window to be mapped + XWindowEvent(dpy,_window,StructureNotifyMask | ExposureMask,&event); + switch (event.type) { + case MapNotify : is_mapped = true; break; + case Expose : is_exposed = true; break; + } + } while (!is_exposed || !is_mapped); + do { // Wait for the window to be visible + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + _window_x = attr.x; + _window_y = attr.y; + } + + void _paint(const bool wait_expose=true) { + if (_is_closed || !_image) return; + Display *const dpy = cimg::X11_attr().display; + if (wait_expose) { // Send an expose event sticked to display window to force repaint + XEvent event; + event.xexpose.type = Expose; + event.xexpose.serial = 0; + event.xexpose.send_event = 1; + event.xexpose.display = dpy; + event.xexpose.window = _window; + event.xexpose.x = 0; + event.xexpose.y = 0; + event.xexpose.width = width(); + event.xexpose.height = height(); + event.xexpose.count = 0; + XSendEvent(dpy,_window,0,0,&event); + } else { // Repaint directly (may be called from the expose event) + GC gc = DefaultGC(dpy,DefaultScreen(dpy)); + +#ifdef cimg_use_xshm + if (_shminfo) XShmPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height,1); + else XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#else + XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#endif + } + } + + template + void _resize(T pixel_type, const unsigned int ndimx, const unsigned int ndimy, const bool force_redraw) { + Display *const dpy = cimg::X11_attr().display; + cimg::unused(pixel_type); + +#ifdef cimg_use_xshm + if (_shminfo) { + XShmSegmentInfo *const nshminfo = new XShmSegmentInfo; + XImage *const nimage = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy); + if (!nimage) { delete nshminfo; return; } + else { + nshminfo->shmid = shmget(IPC_PRIVATE,ndimx*ndimy*sizeof(T),IPC_CREAT | 0777); + if (nshminfo->shmid==-1) { XDestroyImage(nimage); delete nshminfo; return; } + else { + nshminfo->shmaddr = nimage->data = (char*)shmat(nshminfo->shmid,0,0); + if (nshminfo->shmaddr==(char*)-1) { + shmctl(nshminfo->shmid,IPC_RMID,0); XDestroyImage(nimage); delete nshminfo; return; + } else { + nshminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,nshminfo); + XFlush(dpy); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(nshminfo->shmaddr); + shmctl(nshminfo->shmid,IPC_RMID,0); + XDestroyImage(nimage); + delete nshminfo; + return; + } else { + T *const ndata = (T*)nimage->data; + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + XShmDetach(dpy,_shminfo); + XDestroyImage(_image); + shmdt(_shminfo->shmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = nshminfo; + _image = nimage; + _data = (void*)ndata; + } + } + } + } + } else +#endif + { + T *ndata = (T*)std::malloc(ndimx*ndimy*sizeof(T)); + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + _data = (void*)ndata; + XDestroyImage(_image); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,(char*)_data,ndimx,ndimy,8,0); + } + } + + void _init_fullscreen() { + if (!_is_fullscreen || _is_closed) return; + Display *const dpy = cimg::X11_attr().display; + _background_window = 0; + +#ifdef cimg_use_xrandr + int foo; + if (XRRQueryExtension(dpy,&foo,&foo)) { + XRRRotations(dpy,DefaultScreen(dpy),&cimg::X11_attr().curr_rotation); + if (!cimg::X11_attr().resolutions) { + cimg::X11_attr().resolutions = XRRSizes(dpy,DefaultScreen(dpy),&foo); + cimg::X11_attr().nb_resolutions = (unsigned int)foo; + } + if (cimg::X11_attr().resolutions) { + cimg::X11_attr().curr_resolution = 0; + for (unsigned int i = 0; i=_width && nh>=_height && + nw<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width) && + nh<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height)) + cimg::X11_attr().curr_resolution = i; + } + if (cimg::X11_attr().curr_resolution>0) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy), + cimg::X11_attr().curr_resolution,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + } + } + } + if (!cimg::X11_attr().resolutions) + cimg::warn(_cimgdisplay_instance + "init_fullscreen(): Xrandr extension not supported by the X server.", + cimgdisplay_instance); +#endif + + const unsigned int sx = screen_width(), sy = screen_height(); + if (sx==_width && sy==_height) return; + XSetWindowAttributes attr_set; + + attr_set.background_pixel = XBlackPixel(dpy,XDefaultScreen(dpy)); + attr_set.override_redirect = 1; + _background_window = XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,sx,sy,0,0, + InputOutput,CopyFromParent,CWBackPixel | CWOverrideRedirect,&attr_set); + XEvent event; + XSelectInput(dpy,_background_window,StructureNotifyMask); + XMapRaised(dpy,_background_window); + do XWindowEvent(dpy,_background_window,StructureNotifyMask,&event); + while (event.type!=MapNotify); + + XWindowAttributes attr; + do { + XGetWindowAttributes(dpy,_background_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + Display *const dpy = cimg::X11_attr().display; + XUngrabKeyboard(dpy,CurrentTime); + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy),0,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + cimg::X11_attr().curr_resolution = 0; + } +#endif + if (_background_window) XDestroyWindow(dpy,_background_window); + _background_window = 0; + _is_fullscreen = false; + } + + static int _assign_xshm(Display *dpy, XErrorEvent *error) { + cimg::unused(dpy,error); + cimg::X11_attr().is_shm_enabled = false; + return 0; + } + + void _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + cimg::mutex(14); + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous display window if existing + if (!is_empty()) assign(); + + // Open X11 display and retrieve graphical properties. + Display* &dpy = cimg::X11_attr().display; + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Failed to open X11 display.", + cimgdisplay_instance); + + cimg::X11_attr().nb_bits = DefaultDepth(dpy,DefaultScreen(dpy)); + if (cimg::X11_attr().nb_bits!=8 && cimg::X11_attr().nb_bits!=16 && + cimg::X11_attr().nb_bits!=24 && cimg::X11_attr().nb_bits!=32) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Invalid %u bits screen mode detected " + "(only 8, 16, 24 and 32 bits modes are managed).", + cimgdisplay_instance, + cimg::X11_attr().nb_bits); + XVisualInfo vtemplate; + vtemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy,DefaultScreen(dpy))); + int nb_visuals; + XVisualInfo *vinfo = XGetVisualInfo(dpy,VisualIDMask,&vtemplate,&nb_visuals); + if (vinfo && vinfo->red_maskblue_mask) cimg::X11_attr().is_blue_first = true; + cimg::X11_attr().byte_order = ImageByteOrder(dpy); + XFree(vinfo); + + cimg_lock_display(); + cimg::X11_attr().events_thread = new pthread_t; + pthread_create(cimg::X11_attr().events_thread,0,_events_thread,0); + } else cimg_lock_display(); + + // Set display variables. + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = cimg::type::min(); + _is_closed = closed_flag; + _title = tmp_title; + flush(); + + // Create X11 window (and LUT, if 8bits display) + if (_is_fullscreen) { + if (!_is_closed) _init_fullscreen(); + const unsigned int sx = screen_width(), sy = screen_height(); + XSetWindowAttributes attr_set; + attr_set.override_redirect = 1; + _window = XCreateWindow(dpy,DefaultRootWindow(dpy),(sx - _width)/2,(sy - _height)/2,_width,_height,0,0, + InputOutput,CopyFromParent,CWOverrideRedirect,&attr_set); + } else + _window = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,_width,_height,0,0L,0L); + + XSelectInput(dpy,_window, + ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask | + EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask); + + XStoreName(dpy,_window,_title?_title:" "); + if (cimg::X11_attr().nb_bits==8) { + _colormap = XCreateColormap(dpy,_window,DefaultVisual(dpy,DefaultScreen(dpy)),AllocAll); + _set_colormap(_colormap,3); + XSetWindowColormap(dpy,_window,_colormap); + } + + static const char *const _window_class = cimg_appname; + XClassHint *const window_class = XAllocClassHint(); + window_class->res_name = (char*)_window_class; + window_class->res_class = (char*)_window_class; + XSetClassHint(dpy,_window,window_class); + XFree(window_class); + + _window_width = _width; + _window_height = _height; + + // Create XImage +#ifdef cimg_use_xshm + _shminfo = 0; + if (XShmQueryExtension(dpy)) { + _shminfo = new XShmSegmentInfo; + _image = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,_shminfo,_width,_height); + if (!_image) { delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmid = shmget(IPC_PRIVATE,_image->bytes_per_line*_image->height,IPC_CREAT|0777); + if (_shminfo->shmid==-1) { XDestroyImage(_image); delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmaddr = _image->data = (char*)(_data = shmat(_shminfo->shmid,0,0)); + if (_shminfo->shmaddr==(char*)-1) { + shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); delete _shminfo; _shminfo = 0; + } else { + _shminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,_shminfo); + XSync(dpy,0); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(_shminfo->shmaddr); shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); + delete _shminfo; _shminfo = 0; + } + } + } + } + } + if (!_shminfo) +#endif + { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*(cimg::X11_attr().nb_bits==8?1: + (cimg::X11_attr().nb_bits==16?2:4)); + _data = std::malloc(buf_size); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,(char*)_data,_width,_height,8,0); + } + + _wm_window_atom = XInternAtom(dpy,"WM_DELETE_WINDOW",0); + _wm_protocol_atom = XInternAtom(dpy,"WM_PROTOCOLS",0); + XSetWMProtocols(dpy,_window,&_wm_window_atom,1); + + if (_is_fullscreen) XGrabKeyboard(dpy,_window,1,GrabModeAsync,GrabModeAsync,CurrentTime); + cimg::X11_attr().wins[cimg::X11_attr().nb_wins++]=this; + if (!_is_closed) _map_window(); else _window_x = _window_y = cimg::type::min(); + cimg_unlock_display(); + cimg::mutex(14,0); + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + + // Remove display window from event thread list. + unsigned int i; + for (i = 0; ishmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = 0; + } +#endif + + XDestroyImage(_image); + if (cimg::X11_attr().nb_bits==8) XFreeColormap(dpy,_colormap); + XDestroyWindow(dpy,_window); + XSync(dpy,0); + _window = 0; _colormap = 0; _data = 0; _image = 0; + + // Reset display variables. + delete[] _title; + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = cimg::type::min(); + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + + cimg_unlock_display(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + (cimg::X11_attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))* + (size_t)_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + cimg::X11_attr().nb_bits==16?sizeof(unsigned short): + sizeof(unsigned int))*(size_t)_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign(nwidth,nheight); + Display *const dpy = cimg::X11_attr().display; + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*width()/100), + tmpdimy = (nheight>0)?nheight:(-nheight*height()/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + show(); + cimg_lock_display(); + if (_window_width!=dimx || _window_height!=dimy) { + XWindowAttributes attr; + for (unsigned int i = 0; i<10; ++i) { + XResizeWindow(dpy,_window,dimx,dimy); + XGetWindowAttributes(dpy,_window,&attr); + if (attr.width==(int)dimx && attr.height==(int)dimy) break; + cimg::wait(5,&_timer); + } + } + if (_width!=dimx || _height!=dimy) switch (cimg::X11_attr().nb_bits) { + case 8 : { unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + case 16 : { unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + default : { unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } + } + _window_width = _width = dimx; _window_height = _height = dimy; + cimg_unlock_display(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - _width)/2,(screen_height() - _height)/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height* + (cimg::X11_attr().nb_bits==8?1:(cimg::X11_attr().nb_bits==16?2:4)); + void *image_data = std::malloc(buf_size); + std::memcpy(image_data,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,image_data,buf_size); + std::free(image_data); + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + cimg_lock_display(); + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + _map_window(); + cimg_unlock_display(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (_is_fullscreen) _desinit_fullscreen(); + XUnmapWindow(dpy,_window); + _window_x = _window_y = cimg::type::min(); + _is_closed = true; + cimg_unlock_display(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + show(); + if (_window_x!=posx || _window_y!=posy) { + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XMoveWindow(dpy,_window,posx,posy); + _window_x = posx; + _window_y = posy; + cimg_unlock_display(); + } + _is_moved = false; + return paint(); + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XUndefineCursor(dpy,_window); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + static const char pix_data[8] = { 0 }; + XColor col; + col.red = col.green = col.blue = 0; + Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8); + Cursor cur = XCreatePixmapCursor(dpy,pix,pix,&col,&col,0,0); + XFreePixmap(dpy,pix); + XDefineCursor(dpy,_window,cur); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XWarpPointer(dpy,0L,_window,0,0,0,0,posx,posy); + _mouse_x = posx; _mouse_y = posy; + _is_moved = false; + XSync(dpy,0); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XStoreName(dpy,_window,tmp); + cimg_unlock_display(); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(false); + } + + CImgDisplay& paint(const bool wait_expose=true) { + if (is_empty()) return *this; + cimg_lock_display(); + _paint(wait_expose); + cimg_unlock_display(); + return *this; + } + + template + CImgDisplay& render(const CImg& img, const bool flag8=false) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + if (cimg::X11_attr().nb_bits==8 && (img._width!=_width || img._height!=_height)) + return render(img.get_resize(_width,_height,1,-100,1)); + if (cimg::X11_attr().nb_bits==8 && !flag8 && img._spectrum==3) { + static const CImg::ucharT> default_colormap = CImg::ucharT>::default_LUT256(); + return render(img.get_index(default_colormap,1,false)); + } + + const T + *data1 = img._data, + *data2 = (img._spectrum>1)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>2)?img.data(0,0,0,2):data1; + + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + cimg_lock_display(); + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, no normalization + _set_colormap(_colormap,img._spectrum); + unsigned char + *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height], + *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + (*ptrd++) = (unsigned char)*(data1++); + break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, no normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (G>>1); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (G<<5) | (G>>1); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, no normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | + (unsigned char)*(data3++); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data3++)<<24) | ((unsigned char)*(data2++)<<16) | + ((unsigned char)*(data1++)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = 0; + ptrd[3] = 0; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = 0; + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = (unsigned char)*(data2++); + ptrd[3] = (unsigned char)*(data3++); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)*(data3++); + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { _min = (float)cimg::type::min(); _max = (float)cimg::type::max(); } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.f); + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, with normalization + _set_colormap(_colormap,img._spectrum); + unsigned char *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char R = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = R; + } break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, with normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (val>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (G<<5) | (val>>3); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, with normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<24) | (val<<16) | (val<<8); + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8) | + (unsigned char)((*(data3++) - _min)*mm); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data3++) - _min)*mm)<<24) | + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = 0; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = val; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = val; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[3] = (unsigned char)((*(data3++) - _min)*mm); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)((*(data3++) - _min)*mm); + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } + cimg_unlock_display(); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + img.assign(); + Display *dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException("CImgDisplay::screenshot(): Failed to open X11 display."); + } + Window root = DefaultRootWindow(dpy); + XWindowAttributes gwa; + XGetWindowAttributes(dpy,root,&gwa); + const int width = gwa.width, height = gwa.height; + int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1; + if (_x0>_x1) cimg::swap(_x0,_x1); + if (_y0>_y1) cimg::swap(_y0,_y1); + + XImage *image = 0; + if (_x1>=0 && _x0=0 && _y0red_mask, + green_mask = image->green_mask, + blue_mask = image->blue_mask; + img.assign(image->width,image->height,1,3); + T *pR = img.data(0,0,0,0), *pG = img.data(0,0,0,1), *pB = img.data(0,0,0,2); + cimg_forXY(img,x,y) { + const unsigned long pixel = XGetPixel(image,x,y); + *(pR++) = (T)((pixel & red_mask)>>16); + *(pG++) = (T)((pixel & green_mask)>>8); + *(pB++) = (T)(pixel & blue_mask); + } + XDestroyImage(image); + } + } + if (!cimg::X11_attr().display) XCloseDisplay(dpy); + cimg_unlock_display(); + if (img.is_empty()) + throw CImgDisplayException("CImgDisplay::screenshot(): Failed to take screenshot " + "with coordinates (%d,%d)-(%d,%d).", + x0,y0,x1,y1); + } + + template + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned char *ptrs = (unsigned char*)_data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + switch (cimg::X11_attr().nb_bits) { + case 8 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = *(ptrs++); + *(data1++) = (T)(val&0xe0); + *(data2++) = (T)((val&0x1c)<<3); + *(data3++) = (T)(val<<6); + } + } break; + case 16 : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val0&0xf8); + *(data2++) = (T)((val0<<5) | ((val1&0xe0)>>5)); + *(data3++) = (T)(val1<<3); + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned short + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val1&0xf8); + *(data2++) = (T)((val1<<5) | ((val0&0xe0)>>5)); + *(data3++) = (T)(val0<<3); + } + } break; + default : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ++ptrs; + *(data1++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data3++) = (T)ptrs[2]; + ptrs+=3; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + *(data3++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data1++) = (T)ptrs[2]; + ptrs+=3; + ++ptrs; + } + } + } + return *this; + } + + // Windows-based implementation. + //------------------------------- +#elif cimg_display==2 + + bool _is_mouse_tracked, _is_cursor_visible; + HANDLE _thread, _is_created, _mutex; + HWND _window, _background_window; + CLIENTCREATESTRUCT _ccs; + unsigned int *_data; + DEVMODE _curr_mode; + BITMAPINFO _bmi; + HDC _hdc; + + static int screen_width() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsWidth; + } + + static int screen_height() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsHeight; + } + + static void wait_all() { + WaitForSingleObject(cimg::Win32_attr().wait_event,INFINITE); + } + + static LRESULT APIENTRY _handle_events(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { +#ifdef _WIN64 + CImgDisplay *const disp = (CImgDisplay*)GetWindowLongPtr(window,GWLP_USERDATA); +#else + CImgDisplay *const disp = (CImgDisplay*)GetWindowLong(window,GWL_USERDATA); +#endif + MSG st_msg; + switch (msg) { + case WM_CLOSE : + disp->_mouse_x = disp->_mouse_y = -1; + disp->_window_x = disp->_window_y = cimg::type::min(); + disp->set_button().set_key(0).set_key(0,false)._is_closed = true; + ReleaseMutex(disp->_mutex); + ShowWindow(disp->_window,SW_HIDE); + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + return 0; + case WM_SIZE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam); + if (nw && nh && (nw!=disp->_width || nh!=disp->_height)) { + disp->_window_width = nw; + disp->_window_height = nh; + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_resized = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_MOVE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const int nx = (int)(short)(LOWORD(lParam)), ny = (int)(short)(HIWORD(lParam)); + if (nx!=disp->_window_x || ny!=disp->_window_y) { + disp->_window_x = nx; + disp->_window_y = ny; + disp->_is_moved = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_PAINT : + disp->paint(); + cimg_lock_display(); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE_WIN)>=0); + cimg_unlock_display(); + break; + case WM_ERASEBKGND : + // return 0; + break; + case WM_KEYDOWN : + disp->set_key((unsigned int)wParam); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_KEYUP : + disp->set_key((unsigned int)wParam,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MOUSEMOVE : { + while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE)) {} + disp->_mouse_x = LOWORD(lParam); + disp->_mouse_y = HIWORD(lParam); +#if (_WIN32_WINNT>=0x0400) && !defined(NOTRACKMOUSEEVENT) + if (!disp->_is_mouse_tracked) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = disp->_window; + if (TrackMouseEvent(&tme)) disp->_is_mouse_tracked = true; + } +#endif + if (disp->_mouse_x<0 || disp->_mouse_y<0 || disp->_mouse_x>=disp->width() || disp->_mouse_y>=disp->height()) + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + cimg_lock_display(); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE_WIN)>=0); + cimg_unlock_display(); + } break; + case WM_MOUSELEAVE : { + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_mouse_tracked = false; + cimg_lock_display(); + while (ShowCursor(TRUE)<0) {} + cimg_unlock_display(); + } break; + case WM_LBUTTONDOWN : + disp->set_button(1); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONDOWN : + disp->set_button(2); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONDOWN : + disp->set_button(3); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_LBUTTONUP : + disp->set_button(1,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONUP : + disp->set_button(2,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONUP : + disp->set_button(3,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case 0x020A : // WM_MOUSEWHEEL: + disp->set_wheel((int)((short)HIWORD(wParam))/120); + SetEvent(cimg::Win32_attr().wait_event); + } + return DefWindowProc(window,msg,wParam,lParam); + } + + static DWORD WINAPI _events_thread(void* arg) { + CImgDisplay *const disp = (CImgDisplay*)(((void**)arg)[0]); + const char *const title = (const char*)(((void**)arg)[1]); + MSG msg; + delete[] (void**)arg; + disp->_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + disp->_bmi.bmiHeader.biWidth = disp->width(); + disp->_bmi.bmiHeader.biHeight = -disp->height(); + disp->_bmi.bmiHeader.biPlanes = 1; + disp->_bmi.bmiHeader.biBitCount = 32; + disp->_bmi.bmiHeader.biCompression = BI_RGB; + disp->_bmi.bmiHeader.biSizeImage = 0; + disp->_bmi.bmiHeader.biXPelsPerMeter = 1; + disp->_bmi.bmiHeader.biYPelsPerMeter = 1; + disp->_bmi.bmiHeader.biClrUsed = 0; + disp->_bmi.bmiHeader.biClrImportant = 0; + disp->_data = new unsigned int[(size_t)disp->_width*disp->_height]; + if (!disp->_is_fullscreen) { // Normal window + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)disp->_width - 1; rect.bottom = (LONG)disp->_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int + border1 = (int)((rect.right - rect.left + 1 - disp->_width)/2), + border2 = (int)(rect.bottom - rect.top + 1 - disp->_height - border1), + ww = disp->width() + 2*border1, + wh = disp->height() + border1 + border2, + sw = CImgDisplay::screen_width(), + sh = CImgDisplay::screen_height(); + int + wx = (int)cimg::round(cimg::rand(0,sw - ww -1)), + wy = (int)cimg::round(cimg::rand(64,sh - wh - 65)); + if (wx + ww>=sw) wx = sw - ww; + if (wy + wh>=sh) wy = sh - wh; + if (wx<0) wx = 0; + if (wy<0) wy = 0; + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + (DWORD)(WS_OVERLAPPEDWINDOW | (disp->_is_closed?0:WS_VISIBLE)), + wx,wy,ww,wh,0,0,0,&(disp->_ccs)); + if (!disp->_is_closed) { + GetWindowRect(disp->_window,&rect); + disp->_window_x = rect.left; + disp->_window_y = rect.top; + } else disp->_window_x = disp->_window_y = cimg::type::min(); + } else { // Fullscreen window + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + (DWORD)(WS_POPUP | (disp->_is_closed?0:WS_VISIBLE)), + (int)(sx - disp->_width)/2, + (int)(sy - disp->_height)/2, + disp->width(),disp->height(),0,0,0,&(disp->_ccs)); + disp->_window_x = disp->_window_y = 0; + } + SetForegroundWindow(disp->_window); + disp->_hdc = GetDC(disp->_window); + disp->_window_width = disp->_width; + disp->_window_height = disp->_height; + disp->flush(); +#ifdef _WIN64 + SetWindowLongPtr(disp->_window,GWLP_USERDATA,(LONG_PTR)disp); + SetWindowLongPtr(disp->_window,GWLP_WNDPROC,(LONG_PTR)_handle_events); +#else + SetWindowLong(disp->_window,GWL_USERDATA,(LONG)disp); + SetWindowLong(disp->_window,GWL_WNDPROC,(LONG)_handle_events); +#endif + SetEvent(disp->_is_created); + while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg); + return 0; + } + + CImgDisplay& _update_window_pos() { + if (_is_closed) _window_x = _window_y = cimg::type::min(); + else { + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)_width - 1; rect.bottom = (LONG)_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + GetWindowRect(_window,&rect); + _window_x = rect.left; + _window_y = rect.top; + } + return *this; + } + + void _init_fullscreen() { + _background_window = 0; + if (!_is_fullscreen || _is_closed) _curr_mode.dmSize = 0; + else { + DEVMODE mode; + unsigned int imode = 0, ibest = 0, bestbpp = 0, bw = ~0U, bh = ~0U; + for (mode.dmSize = sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(0,imode,&mode); ++imode) { + const unsigned int nw = mode.dmPelsWidth, nh = mode.dmPelsHeight; + if (nw>=_width && nh>=_height && mode.dmBitsPerPel>=bestbpp && nw<=bw && nh<=bh) { + bestbpp = mode.dmBitsPerPel; + ibest = imode; + bw = nw; bh = nh; + } + } + if (bestbpp) { + _curr_mode.dmSize = sizeof(DEVMODE); _curr_mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&_curr_mode); + EnumDisplaySettings(0,ibest,&mode); + ChangeDisplaySettings(&mode,0); + } else _curr_mode.dmSize = 0; + + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + if (sx!=_width || sy!=_height) { + CLIENTCREATESTRUCT background_ccs = { 0,0 }; + _background_window = CreateWindowA("MDICLIENT","",WS_POPUP | WS_VISIBLE, + 0,0,(int)sx,(int)sy,0,0,0,&background_ccs); + SetForegroundWindow(_background_window); + } + } + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + if (_background_window) DestroyWindow(_background_window); + _background_window = 0; + if (_curr_mode.dmSize) ChangeDisplaySettings(&_curr_mode,0); + _is_fullscreen = false; + } + + CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous window if existing + if (!is_empty()) assign(); + + // Set display variables + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = cimg::type::min(); + _is_closed = closed_flag; + _is_cursor_visible = true; + _is_mouse_tracked = false; + _title = tmp_title; + flush(); + if (_is_fullscreen) _init_fullscreen(); + + // Create event thread + void *const arg = (void*)(new void*[2]); + ((void**)arg)[0] = (void*)this; + ((void**)arg)[1] = (void*)_title; + _mutex = CreateMutex(0,FALSE_WIN,0); + _is_created = CreateEvent(0,FALSE_WIN,FALSE_WIN,0); + _thread = CreateThread(0,0,_events_thread,arg,0,0); + WaitForSingleObject(_is_created,INFINITE); + return *this; + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + DestroyWindow(_window); + TerminateThread(_thread,0); + delete[] _data; + delete[] _title; + _data = 0; + _title = 0; + if (_is_fullscreen) _desinit_fullscreen(); + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = cimg::type::min(); + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,sizeof(unsigned int)*_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,sizeof(unsigned int)*_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign((unsigned int)nwidth,(unsigned int)nheight); + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*_width/100), + tmpdimy = (nheight>0)?nheight:(-nheight*_height/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + if (_window_width!=dimx || _window_height!=dimy) { + RECT rect; rect.left = rect.top = 0; rect.right = (LONG)dimx - 1; rect.bottom = (LONG)dimy - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1; + SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS); + } + if (_width!=dimx || _height!=dimy) { + unsigned int *const ndata = new unsigned int[dimx*dimy]; + if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy); + else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy); + delete[] _data; + _data = ndata; + _bmi.bmiHeader.biWidth = (LONG)dimx; + _bmi.bmiHeader.biHeight = -(int)dimy; + _width = dimx; + _height = dimy; + } + _window_width = dimx; _window_height = dimy; + show(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - width())/2,(screen_height() - height())/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*4; + void *odata = std::malloc(buf_size); + if (odata) { + std::memcpy(odata,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,odata,buf_size); + std::free(odata); + } + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + ShowWindow(_window,SW_SHOW); + _update_window_pos(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + _is_closed = true; + if (_is_fullscreen) _desinit_fullscreen(); + ShowWindow(_window,SW_HIDE); + _window_x = _window_y = cimg::type::min(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + if (_window_x!=posx || _window_y!=posy) { + SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER); + _window_x = posx; + _window_y = posy; + } + show(); + _is_moved = false; + return *this; + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = true; + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = false; + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed || posx<0 || posy<0) return *this; + if (!_is_closed) { + _update_window_pos(); + const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy); + if (res) { _mouse_x = posx; _mouse_y = posy; } + } + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + SetWindowTextA(_window, tmp); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(); + } + + CImgDisplay& paint() { + if (_is_closed) return *this; + WaitForSingleObject(_mutex,INFINITE); + SetDIBitsToDevice(_hdc,0,0,_width,_height,0,0,0,_height,_data,&_bmi,DIB_RGB_COLORS); + ReleaseMutex(_mutex); + return *this; + } + + template + CImgDisplay& render(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + + const T + *data1 = img._data, + *data2 = (img._spectrum>=2)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>=3)?img.data(0,0,0,2):data1; + + WaitForSingleObject(_mutex,INFINITE); + unsigned int + *const ndata = (img._width==_width && img._height==_height)?_data: + new unsigned int[(size_t)img._width*img._height], + *ptrd = ndata; + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { + _min = (float)cimg::type::min(); + _max = (float)cimg::type::max(); + } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.f); + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } + if (ndata!=_data) { _render_resize(ndata,img._width,img._height,_data,_width,_height); delete[] ndata; } + ReleaseMutex(_mutex); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + img.assign(); + HDC hScreen = GetDC(GetDesktopWindow()); + if (hScreen) { + const int + width = GetDeviceCaps(hScreen,HORZRES), + height = GetDeviceCaps(hScreen,VERTRES); + int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1; + if (_x0>_x1) cimg::swap(_x0,_x1); + if (_y0>_y1) cimg::swap(_y0,_y1); + if (_x1>=0 && _x0=0 && _y0 + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned int *ptrs = _data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned int val = *(ptrs++); + *(data1++) = (T)(unsigned char)(val>>16); + *(data2++) = (T)(unsigned char)((val>>8)&0xFF); + *(data3++) = (T)(unsigned char)(val&0xFF); + } + return *this; + } +#endif + + //@} + }; // struct CImgDisplay { ... + + /* + #-------------------------------------- + # + # + # + # Definition of the CImg structure + # + # + # + #-------------------------------------- + */ + + //! Class representing an image (up to 4 dimensions wide), each pixel being of type \c T. + /** + This is the main class of the %CImg Library. It declares and constructs + an image, allows access to its pixel values, and is able to perform various image operations. + + \par Image representation + + A %CImg image is defined as an instance of the container \c CImg, which contains a regular grid of pixels, + each pixel value being of type \c T. The image grid can have up to 4 dimensions: width, height, depth + and number of channels. + Usually, the three first dimensions are used to describe spatial coordinates (x,y,z), + while the number of channels is rather used as a vector-valued dimension + (it may describe the R,G,B color channels for instance). + If you need a fifth dimension, you can use image lists \c CImgList rather than simple images \c CImg. + + Thus, the \c CImg class is able to represent volumetric images of vector-valued pixels, + as well as images with less dimensions (1D scalar signal, 2D color images, ...). + Most member functions of the class CImg<\c T> are designed to handle this maximum case of (3+1) dimensions. + + Concerning the pixel value type \c T: + fully supported template types are the basic C++ types: unsigned char, char, short, unsigned int, int, + unsigned long, long, float, double, ... . + Typically, fast image display can be done using CImg images, + while complex image processing algorithms may be rather coded using CImg or CImg + images that have floating-point pixel values. The default value for the template T is \c float. + Using your own template types may be possible. However, you will certainly have to define the complete set + of arithmetic and logical operators for your class. + + \par Image structure + + The \c CImg structure contains \e six fields: + - \c _width defines the number of \a columns of the image (size along the X-axis). + - \c _height defines the number of \a rows of the image (size along the Y-axis). + - \c _depth defines the number of \a slices of the image (size along the Z-axis). + - \c _spectrum defines the number of \a channels of the image (size along the C-axis). + - \c _data defines a \a pointer to the \a pixel \a data (of type \c T). + - \c _is_shared is a boolean that tells if the memory buffer \c data is shared with + another image. + + You can access these fields publicly although it is recommended to use the dedicated functions + width(), height(), depth(), spectrum() and ptr() to do so. + Image dimensions are not limited to a specific range (as long as you got enough available memory). + A value of \e 1 usually means that the corresponding dimension is \a flat. + If one of the dimensions is \e 0, or if the data pointer is null, the image is considered as \e empty. + Empty images should not contain any pixel data and thus, will not be processed by CImg member functions + (a CImgInstanceException will be thrown instead). + Pixel data are stored in memory, in a non interlaced mode (See \ref cimg_storage). + + \par Image declaration and construction + + Declaring an image can be done by using one of the several available constructors. + Here is a list of the most used: + + - Construct images from arbitrary dimensions: + - CImg img; declares an empty image. + - CImg img(128,128); declares a 128x128 greyscale image with + \c unsigned \c char pixel values. + - CImg img(3,3); declares a 3x3 matrix with \c double coefficients. + - CImg img(256,256,1,3); declares a 256x256x1x3 (color) image + (colors are stored as an image with three channels). + - CImg img(128,128,128); declares a 128x128x128 volumetric and greyscale image + (with \c double pixel values). + - CImg<> img(128,128,128,3); declares a 128x128x128 volumetric color image + (with \c float pixels, which is the default value of the template parameter \c T). + - \b Note: images pixels are not automatically initialized to 0. You may use the function \c fill() to + do it, or use the specific constructor taking 5 parameters like this: + CImg<> img(128,128,128,3,0); declares a 128x128x128 volumetric color image with all pixel values to 0. + + - Construct images from filenames: + - CImg img("image.jpg"); reads a JPEG color image from the file "image.jpg". + - CImg img("analyze.hdr"); reads a volumetric image (ANALYZE7.5 format) from the + file "analyze.hdr". + - \b Note: You need to install ImageMagick + to be able to read common compressed image formats (JPG,PNG, ...) (See \ref cimg_files_io). + + - Construct images from C-style arrays: + - CImg img(data_buffer,256,256); constructs a 256x256 greyscale image from a \c int* buffer + \c data_buffer (of size 256x256=65536). + - CImg img(data_buffer,256,256,1,3); constructs a 256x256 color image + from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others). + + The complete list of constructors can be found here. + + \par Most useful functions + + The \c CImg class contains a lot of functions that operates on images. + Some of the most useful are: + + - operator()(): Read or write pixel values. + - display(): displays the image in a new window. + **/ + template + struct CImg { + + unsigned int _width, _height, _depth, _spectrum; + bool _is_shared; + T *_data; + + //! Simple iterator type, to loop through each pixel value of an image instance. + /** + \note + - The \c CImg::iterator type is defined to be a T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + CImg img("reference.jpg"); // Load image from file + // Set all pixels to '0', with a CImg iterator. + for (CImg::iterator it = img.begin(), it::const_iterator type is defined to be a \c const \c T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + const CImg img("reference.jpg"); // Load image from file + float sum = 0; + // Compute sum of all pixel values, with a CImg iterator. + for (CImg::iterator it = img.begin(), it::value_type type of a \c CImg is defined to be a \c T. + - \c CImg::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + // Return 'dx*dy*dz*dc' as a 'size_t' and check no overflow occurs. + static size_t safe_size(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + if (!(dx && dy && dz && dc)) return 0; + size_t siz = (size_t)dx, osiz = siz; + if ((dy==1 || (siz*=dy)>osiz) && + ((osiz = siz), dz==1 || (siz*=dz)>osiz) && + ((osiz = siz), dc==1 || (siz*=dc)>osiz) && + ((osiz = siz), sizeof(T)==1 || (siz*sizeof(T))>osiz)) return siz; + throw CImgArgumentException("CImg<%s>::safe_size(): Specified size (%u,%u,%u,%u) overflows 'size_t'.", + pixel_type(),dx,dy,dz,dc); + } + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimg_plugin +#include cimg_plugin +#endif +#ifdef cimg_plugin1 +#include cimg_plugin1 +#endif +#ifdef cimg_plugin2 +#include cimg_plugin2 +#endif +#ifdef cimg_plugin3 +#include cimg_plugin3 +#endif +#ifdef cimg_plugin4 +#include cimg_plugin4 +#endif +#ifdef cimg_plugin5 +#include cimg_plugin5 +#endif +#ifdef cimg_plugin6 +#include cimg_plugin6 +#endif +#ifdef cimg_plugin7 +#include cimg_plugin7 +#endif +#ifdef cimg_plugin8 +#include cimg_plugin8 +#endif + + //@} + //--------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //--------------------------------------------------------- + + //! Destroy image. + /** + \note + - The pixel buffer data() is deallocated if necessary, e.g. for non-empty and non-shared image instances. + - Destroying an empty or shared image does nothing actually. + \warning + - When destroying a non-shared image, make sure that you will \e not operate on a remaining shared image + that shares its buffer with the destroyed instance, in order to avoid further invalid memory access + (to a deallocated buffer). + **/ + ~CImg() { + if (!_is_shared) delete[] _data; + } + + //! Construct empty image. + /** + \note + - An empty image has no pixel data and all of its dimensions width(), height(), depth(), spectrum() + are set to \c 0, as well as its pixel buffer pointer data(). + - An empty image may be re-assigned afterwards, e.g. with the family of + assign(unsigned int,unsigned int,unsigned int,unsigned int) methods, + or by operator=(const CImg&). In all cases, the type of pixels stays \c T. + - An empty image is never shared. + \par Example + \code + CImg img1, img2; // Construct two empty images + img1.assign(256,256,1,3); // Re-assign 'img1' to be a 256x256x1x3 (color) image + img2 = img1.get_rand(0,255); // Re-assign 'img2' to be a random-valued version of 'img1' + img2.assign(); // Re-assign 'img2' to be an empty image again + \endcode + **/ + CImg():_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {} + + //! Construct image with specified size. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \note + - It is able to create only \e non-shared images, and allocates thus a pixel buffer data() + for each constructed image instance. + - Setting one dimension \c size_x,\c size_y,\c size_z or \c size_c to \c 0 leads to the construction of + an \e empty image. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values during construction (e.g. with \c 0), use constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) instead. + \par Example + \code + CImg img1(256,256,1,3); // Construct a 256x256x1x3 (color) image, filled with garbage values + CImg img2(256,256,1,3,0); // Construct a 256x256x1x3 (color) image, filled with value '0' + \endcode + **/ + explicit CImg(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1): + _is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value Initialization value. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), + but it also fills the pixel buffer with the specified \c value. + \warning + - It cannot be used to construct a vector-valued image and initialize it with \e vector-valued pixels + (e.g. RGB vector, for color images). + For this task, you may use fillC() after construction. + **/ + CImg(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value): + _is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(value); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified sequence of integers \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be an \e integer). + \param value1 Second value of the initialization sequence (must be an \e integer). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \warning + - You must specify \e exactly \c size_x*\c size_y*\c size_z*\c size_c integers in the initialization sequence. + Otherwise, the constructor may crash or fill your image pixels with garbage. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image + 0,255,0,255, // Set the 4 values for the red component + 0,0,255,255, // Set the 4 values for the green component + 64,64,64,64); // Set the 4 values for the blue component + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _CImg_stdarg(img,a0,a1,N,t) { \ + size_t _siz = (size_t)N; \ + if (_siz--) { \ + va_list ap; \ + va_start(ap,a1); \ + T *ptrd = (img)._data; \ + *(ptrd++) = (T)a0; \ + if (_siz--) { \ + *(ptrd++) = (T)a1; \ + for ( ; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \ + } \ + va_end(ap); \ + } \ + } + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),int); + } + +#if cimg_use_cpp11==1 + //! Construct image with specified size and initialize pixel values from an initializer list of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... } + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param { value0, value1, ... } Initialization list + \param repeat_values Tells if the value filling process is repeated over the image. + + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image + { 0,255,0,255, // Set the 4 values for the red component + 0,0,255,255, // Set the 4 values for the green component + 64,64,64,64 }); // Set the 4 values for the blue component + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _cimg_constructor_cpp11(repeat_values) \ + auto it = values.begin(); \ + size_t siz = size(); \ + if (repeat_values) for (T *ptrd = _data; siz--; ) { \ + *(ptrd++) = (T)(*(it++)); if (it==values.end()) it = values.begin(); } \ + else { siz = std::min(siz,values.size()); for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); } + assign(size_x,size_y,size_z,size_c); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, + std::initializer_list values, + const bool repeat_values=true):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x); + _cimg_constructor_cpp11(repeat_values); + } + + //! Construct single channel 1D image with pixel values and width obtained from an initializer list of integers. + /** + Construct a new image instance of size \c width x \c 1 x \c 1 x \c 1, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... }. Image width is + given by the size of the initializer list. + \param { value0, value1, ... } Initialization list + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int) with height=1, depth=1, and spectrum=1, + but it also fills the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img = {10,20,30,20,10 }; // Construct a 5x1 image with one channel, and set its pixel values + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const std::initializer_list values): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(values.size(),1,1,1); + auto it = values.begin(); + unsigned int siz = _width; + for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); + } + + template + CImg& operator=(std::initializer_list values) { + _cimg_constructor_cpp11(siz>values.size()); + return *this; + } +#endif + + //! Construct image with specified size and initialize pixel values from a sequence of doubles. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initialize pixel values from the specified sequence of doubles \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be a \e double). + \param value1 Second value of the initialization sequence (must be a \e double). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...), but + takes a sequence of double values instead of integers. + \warning + - You must specify \e exactly \c dx*\c dy*\c dz*\c dc doubles in the initialization sequence. + Otherwise, the constructor may crash or fill your image with garbage. + For instance, the code below will probably crash on most platforms: + \code + const CImg img(2,2,1,1, 0.5,0.5,255,255); // FAIL: The two last arguments are 'int', not 'double'! + \endcode + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),double); + } + + //! Construct image with specified size and initialize pixel values from a value string. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified string \c values. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param values Value string describing the way pixel values are set. + \param repeat_values Tells if the value filling process is repeated over the image. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with values described in the value string \c values. + - Value string \c values may describe two different filling processes: + - Either \c values is a sequences of values assigned to the image pixels, as in "1,2,3,7,8,2". + In this case, set \c repeat_values to \c true to periodically fill the image with the value sequence. + - Either, \c values is a formula, as in "cos(x/10)*sin(y/20)". + In this case, parameter \c repeat_values is pointless. + - For both cases, specifying \c repeat_values is mandatory. + It disambiguates the possible overloading of constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) with \c T being a const char*. + - A \c CImgArgumentException is thrown when an invalid value string \c values is specified. + \par Example + \code + const CImg img1(129,129,1,3,"0,64,128,192,255",true), // Construct image from a value sequence + img2(129,129,1,3,"if(c==0,255*abs(cos(x/10)),1.8*y)",false); // Construct image from a formula + (img1,img2).display(); + \endcode + \image html ref_constructor2.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values):_is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(values,repeat_values); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified \c t* memory buffer. + \param values Pointer to the input memory buffer. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param is_shared Tells if input memory buffer must be shared by the current instance. + \note + - If \c is_shared is \c false, the image instance allocates its own pixel buffer, + and values from the specified input buffer are copied to the instance buffer. + If buffer types \c T and \c t are different, a regular static cast is performed during buffer copy. + - Otherwise, the image instance does \e not allocate a new buffer, and uses the input memory buffer as its + own pixel buffer. This case requires that types \c T and \c t are the same. Later, destroying such a shared + image will not deallocate the pixel buffer, this task being obviously charged to the initial buffer allocator. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - You must take care when operating on a shared image, since it may have an invalid pixel buffer pointer data() + (e.g. already deallocated). + \par Example + \code + unsigned char tab[256*256] = { 0 }; + CImg img1(tab,256,256,1,1,false), // Construct new non-shared image from buffer 'tab' + img2(tab,256,256,1,1,true); // Construct new shared-image from buffer 'tab' + tab[1024] = 255; // Here, 'img2' is indirectly modified, but not 'img1' + \endcode + **/ + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a (%u,%u,%u,%u) shared instance " + "from a (%s*) buffer (pixel types are different).", + cimg_instance, + size_x,size_y,size_z,size_c,CImg::pixel_type()); + } + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + + } + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = is_shared; + if (_is_shared) _data = const_cast(values); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy(_data,values,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from memory buffer with specified size and pixel ordering scheme. + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const axes_order):_data(0),_is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = c; } + } + if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { + const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + int s0 = 0, s1 = 0, s2 = 0, s3 = 0; + const char *inv_order = 0; + switch (code) { + case 0x0123 : inv_order = "xyzc"; s0 = size_x; s1 = size_y; s2 = size_z; s3 = size_c; break; // xyzc + case 0x0132 : inv_order = "xyzc"; s0 = size_x; s1 = size_y; s2 = size_c; s3 = size_z; break; // xycz + case 0x0213 : inv_order = "xzyc"; s0 = size_x; s1 = size_z; s2 = size_y; s3 = size_c; break; // xzyc + case 0x0231 : inv_order = "xcyz"; s0 = size_x; s1 = size_z; s2 = size_c; s3 = size_y; break; // xzcy + case 0x0312 : inv_order = "xzcy"; s0 = size_x; s1 = size_c; s2 = size_y; s3 = size_z; break; // xcyz + case 0x0321 : inv_order = "xczy"; s0 = size_x; s1 = size_c; s2 = size_z; s3 = size_y; break; // xczy + case 0x1023 : inv_order = "yxzc"; s0 = size_y; s1 = size_x; s2 = size_z; s3 = size_c; break; // yxzc + case 0x1032 : inv_order = "yxcz"; s0 = size_y; s1 = size_x; s2 = size_c; s3 = size_z; break; // yxcz + case 0x1203 : inv_order = "zxyc"; s0 = size_y; s1 = size_z; s2 = size_x; s3 = size_c; break; // yzxc + case 0x1230 : inv_order = "cxyz"; s0 = size_y; s1 = size_z; s2 = size_c; s3 = size_x; break; // yzcx + case 0x1302 : inv_order = "zxcy"; s0 = size_y; s1 = size_c; s2 = size_x; s3 = size_z; break; // ycxz + case 0x1320 : inv_order = "cxzy"; s0 = size_y; s1 = size_c; s2 = size_z; s3 = size_x; break; // yczx + case 0x2013 : inv_order = "yzxc"; s0 = size_z; s1 = size_x; s2 = size_y; s3 = size_c; break; // zxyc + case 0x2031 : inv_order = "ycxz"; s0 = size_z; s1 = size_x; s2 = size_c; s3 = size_y; break; // zxcy + case 0x2103 : inv_order = "zyxc"; s0 = size_z; s1 = size_y; s2 = size_x; s3 = size_c; break; // zyxc + case 0x2130 : inv_order = "cyxz"; s0 = size_z; s1 = size_y; s2 = size_c; s3 = size_x; break; // zycx + case 0x2301 : inv_order = "zcxy"; s0 = size_z; s1 = size_c; s2 = size_x; s3 = size_y; break; // zcxy + case 0x2310 : inv_order = "czxy"; s0 = size_z; s1 = size_c; s2 = size_y; s3 = size_x; break; // zcyx + case 0x3012 : inv_order = "yzcx"; s0 = size_c; s1 = size_x; s2 = size_y; s3 = size_z; break; // cxyz + case 0x3021 : inv_order = "yczx"; s0 = size_c; s1 = size_x; s2 = size_z; s3 = size_y; break; // cxzy + case 0x3102 : inv_order = "zycx"; s0 = size_c; s1 = size_y; s2 = size_x; s3 = size_z; break; // cyxz + case 0x3120 : inv_order = "cyzx"; s0 = size_c; s1 = size_y; s2 = size_z; s3 = size_x; break; // cyzx + case 0x3201 : inv_order = "zcyx"; s0 = size_c; s1 = size_z; s2 = size_x; s3 = size_y; break; // czxy + case 0x3210 : inv_order = "czyx"; s0 = size_c; s1 = size_z; s2 = size_y; s3 = size_x; break; // czyx + } + CImg(values,s0,s1,s2,s3,true).get_permute_axes(inv_order).move_to(*this); + } else { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from reading an image file. + /** + Construct a new image instance with pixels of type \c T, and initialize pixel values with the data read from + an image file. + \param filename Filename, as a C-string. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it reads the image + dimensions and pixel values from the specified image file. + - The recognition of the image file format by %CImg higlhy depends on the tools installed on your system + and on the external libraries you used to link your code against. + - Considered pixel type \c T should better fit the file format specification, or data loss may occur during + file load (e.g. constructing a \c CImg from a float-valued image file). + - A \c CImgIOException is thrown when the specified \c filename cannot be read, or if the file format is not + recognized. + \par Example + \code + const CImg img("reference.jpg"); + img.display(); + \endcode + \image html ref_image.jpg + **/ + explicit CImg(const char *const filename):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(filename); + } + + //! Construct image copy. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance. + \param img Input image to copy. + \note + - Constructed copy has the same size width() x height() x depth() x spectrum() and pixel values as the + input image \c img. + - If input image \c img is \e shared and if types \c T and \c t are the same, the constructed copy is also + \e shared, and shares its pixel buffer with \c img. + Modifying a pixel value in the constructed copy will thus also modifies it in the input image \c img. + This behavior is needful to allow functions to return shared images. + - Otherwise, the constructed copy allocates its own pixel buffer, and copies pixel values from the input + image \c img into its buffer. The copied pixel values may be eventually statically casted if types \c T and + \c t are different. + - Constructing a copy from an image \c img when types \c t and \c T are the same is significantly faster than + with different types. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. not enough available memory). + **/ + template + CImg(const CImg& img):_is_shared(false) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image copy \specialization. + CImg(const CImg& img) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = img._is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Advanced copy constructor. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance, + while forcing the shared state of the constructed copy. + \param img Input image to copy. + \param is_shared Tells about the shared state of the constructed copy. + \note + - Similar to CImg(const CImg&), except that it allows to decide the shared state of + the constructed image, which does not depend anymore on the shared state of the input image \c img: + - If \c is_shared is \c true, the constructed copy will share its pixel buffer with the input image \c img. + For that case, the pixel types \c T and \c t \e must be the same. + - If \c is_shared is \c false, the constructed copy will allocate its own pixel buffer, whether the input + image \c img is shared or not. + - A \c CImgArgumentException is thrown when a shared copy is requested with different pixel types \c T and \c t. + **/ + template + CImg(const CImg& img, const bool is_shared):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a shared instance from a " + "CImg<%s> image (%u,%u,%u,%u,%p) (pixel types are different).", + cimg_instance, + CImg::pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data); + } + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Advanced copy constructor \specialization. + CImg(const CImg& img, const bool is_shared) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image with dimensions borrowed from another image. + /** + Construct a new image instance with pixels of type \c T, and size get from some dimensions of an existing + \c CImg instance. + \param img Input image from which dimensions are borrowed. + \param dimensions C-string describing the image size along the X,Y,Z and C-dimensions. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it takes the image dimensions + (\e not its pixel values) from an existing \c CImg instance. + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values (e.g. with \c 0), use constructor CImg(const CImg&,const char*,T) + instead. + \par Example + \code + const CImg img1(256,128,1,3), // 'img1' is a 256x128x1x3 image + img2(img1,"xyzc"), // 'img2' is a 256x128x1x3 image + img3(img1,"y,x,z,c"), // 'img3' is a 128x256x1x3 image + img4(img1,"c,x,y,3",0), // 'img4' is a 3x128x256x3 image (with pixels initialized to '0') + \endcode + **/ + template + CImg(const CImg& img, const char *const dimensions): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values. + /** + Construct a new image instance with pixels of type \c T, and size get from the dimensions of an existing + \c CImg instance, and set all pixel values to specified \c value. + \param img Input image from which dimensions are borrowed. + \param dimensions String describing the image size along the X,Y,Z and V-dimensions. + \param value Value used for initialization. + \note + - Similar to CImg(const CImg&,const char*), but it also fills the pixel buffer with the specified \c value. + **/ + template + CImg(const CImg& img, const char *const dimensions, const T& value): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions).fill(value); + } + + //! Construct image from a display window. + /** + Construct a new image instance with pixels of type \c T, as a snapshot of an existing \c CImgDisplay instance. + \param disp Input display window. + \note + - The width() and height() of the constructed image instance are the same as the specified \c CImgDisplay. + - The depth() and spectrum() of the constructed image instance are respectively set to \c 1 and \c 3 + (i.e. a 2D color image). + - The image pixels are read as 8-bits RGB values. + **/ + explicit CImg(const CImgDisplay &disp):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + disp.snapshot(*this); + } + + // Constructor and assignment operator for rvalue references (c++11). + // This avoids an additional image copy for methods returning new images. Can save RAM for big images ! +#if cimg_use_cpp11==1 + CImg(CImg&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + swap(img); + } + + CImg& operator=(CImg&& img) { + if (_is_shared) return assign(img); + return img.swap(*this); + } +#endif + + //! Construct empty image \inplace. + /** + In-place version of the default constructor CImg(). It simply resets the instance to an empty image. + **/ + CImg& assign() { + if (!_is_shared) delete[] _data; + _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; + return *this; + } + + //! Construct image with specified size \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (siz!=curr_siz) { + if (_is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from specified " + "image (%u,%u,%u,%u).", + cimg_instance, + size_x,size_y,size_z,size_c); + else { + delete[] _data; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + return *this; + } + + //! Construct image with specified size and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,T). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value) { + return assign(size_x,size_y,size_z,size_c).fill(value); + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),int); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a sequence of doubles \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,double,double,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),double); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a value string \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,const char*,bool). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values) { + return assign(size_x,size_y,size_z,size_c).fill(values,repeat_values); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \inplace. + /** + In-place version of the constructor CImg(const t*,unsigned int,unsigned int,unsigned int,unsigned int). + **/ + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + assign(size_x,size_y,size_z,size_c); + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (values==_data && siz==curr_siz) return assign(size_x,size_y,size_z,size_c); + if (_is_shared || values + siz<_data || values>=_data + size()) { + assign(size_x,size_y,size_z,size_c); + if (_is_shared) std::memmove((void*)_data,(void*)values,siz*sizeof(T)); + else std::memcpy((void*)_data,(void*)values,siz*sizeof(T)); + } else { + T *new_data = 0; + try { new_data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy((void*)new_data,(void*)values,siz*sizeof(T)); + delete[] _data; _data = new_data; _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + } + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + if (is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from (%s*) buffer" + "(pixel types are different).", + cimg_instance, + CImg::pixel_type()); + return assign(values,size_x,size_y,size_z,size_c); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); } + else { + if (!_is_shared) { + if (values + siz<_data || values>=_data + size()) assign(); + else cimg::warn(_cimg_instance + "assign(): Shared image instance has overlapping memory.", + cimg_instance); + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = true; + _data = const_cast(values); + } + return *this; + } + + //! Construct image from memory buffer with specified size and pixel ordering scheme. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const axes_order) { + CImg(values,size_x,size_y,size_z,size_c,axes_order).move_to(*this); + } + + //! Construct image from reading an image file \inplace. + /** + In-place version of the constructor CImg(const char*). + **/ + CImg& assign(const char *const filename) { + return load(filename); + } + + //! Construct image copy \inplace. + /** + In-place version of the constructor CImg(const CImg&). + **/ + template + CImg& assign(const CImg& img) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum); + } + + //! In-place version of the advanced copy constructor. + /** + In-place version of the constructor CImg(const CImg&,bool). + **/ + template + CImg& assign(const CImg& img, const bool is_shared) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum,is_shared); + } + + //! Construct image with dimensions borrowed from another image \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions) { + if (!dimensions || !*dimensions) return assign(img._width,img._height,img._depth,img._spectrum); + unsigned int siz[4] = { 0,1,1,1 }, k = 0; + CImg item(256); + for (const char *s = dimensions; *s && k<4; ++k) { + if (cimg_sscanf(s,"%255[^0-9%xyzvwhdcXYZVWHDC]",item._data)>0) s+=std::strlen(item); + if (*s) { + unsigned int val = 0; char sep = 0; + if (cimg_sscanf(s,"%u%c",&val,&sep)>0) { + if (sep=='%') siz[k] = val*(k==0?_width:k==1?_height:k==2?_depth:_spectrum)/100; + else siz[k] = val; + while (*s>='0' && *s<='9') ++s; + if (sep=='%') ++s; + } else switch (cimg::lowercase(*s)) { + case 'x' : case 'w' : siz[k] = img._width; ++s; break; + case 'y' : case 'h' : siz[k] = img._height; ++s; break; + case 'z' : case 'd' : siz[k] = img._depth; ++s; break; + case 'c' : case 's' : siz[k] = img._spectrum; ++s; break; + default : + throw CImgArgumentException(_cimg_instance + "assign(): Invalid character '%c' detected in specified dimension string '%s'.", + cimg_instance, + *s,dimensions); + } + } + } + return assign(siz[0],siz[1],siz[2],siz[3]); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*,T). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions, const T& value) { + return assign(img,dimensions).fill(value); + } + + //! Construct image from a display window \inplace. + /** + In-place version of the constructor CImg(const CImgDisplay&). + **/ + CImg& assign(const CImgDisplay &disp) { + disp.snapshot(*this); + return *this; + } + + //! Construct empty image \inplace. + /** + Equivalent to assign(). + \note + - It has been defined for compatibility with STL naming conventions. + **/ + CImg& clear() { + return assign(); + } + + //! Transfer content of an image instance into another one. + /** + Transfer the dimensions and the pixel buffer content of an image instance into another one, + and replace instance by an empty image. It avoids the copy of the pixel buffer + when possible. + \param img Destination image. + \note + - Pixel types \c T and \c t of source and destination images can be different, though the process is + designed to be instantaneous when \c T and \c t are the same. + \par Example + \code + CImg src(256,256,1,3,0), // Construct a 256x256x1x3 (color) image filled with value '0' + dest(16,16); // Construct a 16x16x1x1 (scalar) image + src.move_to(dest); // Now, 'src' is empty and 'dest' is the 256x256x1x3 image + \endcode + **/ + template + CImg& move_to(CImg& img) { + img.assign(*this); + assign(); + return img; + } + + //! Transfer content of an image instance into another one \specialization. + CImg& move_to(CImg& img) { + if (_is_shared || img._is_shared) img.assign(*this); + else swap(img); + assign(); + return img; + } + + //! Transfer content of an image instance into a new image in an image list. + /** + Transfer the dimensions and the pixel buffer content of an image instance + into a newly inserted image at position \c pos in specified \c CImgList instance. + \param list Destination list. + \param pos Position of the newly inserted image in the list. + \note + - When optional parameter \c pos is omitted, the image instance is transferred as a new + image at the end of the specified \c list. + - It is convenient to sequentially insert new images into image lists, with no + additional copies of memory buffer. + \par Example + \code + CImgList list; // Construct an empty image list + CImg img("reference.jpg"); // Read image from filename + img.move_to(list); // Transfer image content as a new item in the list (no buffer copy) + \endcode + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos=~0U) { + const unsigned int npos = pos>list._width?list._width:pos; + move_to(list.insert(1,npos)[npos]); + return list; + } + + //! Swap fields of two image instances. + /** + \param img Image to swap fields with. + \note + - It can be used to interchange the content of two images in a very fast way. Can be convenient when dealing + with algorithms requiring two swapping buffers. + \par Example + \code + CImg img1("lena.jpg"), + img2("milla.jpg"); + img1.swap(img2); // Now, 'img1' is 'milla' and 'img2' is 'lena' + \endcode + **/ + CImg& swap(CImg& img) { + cimg::swap(_width,img._width,_height,img._height,_depth,img._depth,_spectrum,img._spectrum); + cimg::swap(_data,img._data); + cimg::swap(_is_shared,img._is_shared); + return img; + } + + //! Return a reference to an empty image. + /** + \note + This function is useful mainly to declare optional parameters having type \c CImg in functions prototypes, + e.g. + \code + void f(const int x=0, const int y=0, const CImg& img=CImg::empty()); + \endcode + **/ + static CImg& empty() { + static CImg _empty; + return _empty.assign(); + } + + //! Return a reference to an empty image \const. + static const CImg& const_empty() { + static const CImg _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Access to a pixel value. + /** + Return a reference to a located pixel value of the image instance, + being possibly \e const, whether the image instance is \e const or not. + This is the standard method to get/set pixel values in \c CImg images. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Range of pixel coordinates start from (0,0,0,0) to + (width() - 1,height() - 1,depth() - 1,spectrum() - 1). + - Due to the particular arrangement of the pixel buffers defined in %CImg, you can omit one coordinate if the + corresponding dimension is equal to \c 1. + For instance, pixels of a 2D image (depth() equal to \c 1) can be accessed by img(x,y,c) instead of + img(x,y,0,c). + \warning + - There is \e no boundary checking done in this operator, to make it as fast as possible. + You \e must take care of out-of-bounds access by yourself, if necessary. + For debugging purposes, you may want to define macro \c 'cimg_verbosity'>=3 to enable additional boundary + checking operations in this operator. In that case, warning messages will be printed on the error output + when accessing out-of-bounds pixels. + \par Example + \code + CImg img(100,100,1,3,0); // Construct a 100x100x1x3 (color) image with pixels set to '0' + const float + valR = img(10,10,0,0), // Read red value at coordinates (10,10) + valG = img(10,10,0,1), // Read green value at coordinates (10,10) + valB = img(10,10,2), // Read blue value at coordinates (10,10) (Z-coordinate can be omitted) + avg = (valR + valG + valB)/3; // Compute average pixel value + img(10,10,0) = img(10,10,1) = img(10,10,2) = avg; // Replace the color pixel (10,10) by the average grey value + \endcode + **/ +#if cimg_verbosity>=3 + T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (!_data || off>=size()) { + cimg::warn(_cimg_instance + "operator(): Invalid pixel request, at coordinates (%d,%d,%d,%d) [offset=%u].", + cimg_instance, + (int)x,(int)y,(int)z,(int)c,off); + return *_data; + } + else return _data[off]; + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->operator()(x,y,z,c); + } + + //! Access to a pixel value. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param wh Precomputed offset, must be equal to width()*\ref height(). + \param whd Precomputed offset, must be equal to width()*\ref height()*\ref depth(). + \note + - Similar to (but faster than) operator()(). + It uses precomputed offsets to optimize memory access. You may use it to optimize + the reading/writing of several pixel values in the same image (e.g. in a loop). + **/ + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) const { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } +#else + T& operator()(const unsigned int x) { + return _data[x]; + } + + const T& operator()(const unsigned int x) const { + return _data[x]; + } + + T& operator()(const unsigned int x, const unsigned int y) { + return _data[x + y*_width]; + } + + const T& operator()(const unsigned int x, const unsigned int y) const { + return _data[x + y*_width]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) { + return _data[x + y*_width + z*wh]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) const { + return _data[x + y*_width + z*wh]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) { + return _data[x + y*_width + z*wh + c*whd]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) const { + return _data[x + y*_width + z*wh + c*whd]; + } +#endif + + //! Implicitly cast an image into a \c T*. + /** + Implicitly cast a \c CImg instance into a \c T* or \c const \c T* pointer, whether the image instance + is \e const or not. The returned pointer points on the first value of the image pixel buffer. + \note + - It simply returns the pointer data() to the pixel buffer. + - This implicit conversion is convenient to test the empty state of images (data() being \c 0 in this case), e.g. + \code + CImg img1(100,100), img2; // 'img1' is a 100x100 image, 'img2' is an empty image + if (img1) { // Test succeeds, 'img1' is not an empty image + if (!img2) { // Test succeeds, 'img2' is an empty image + std::printf("'img1' is not empty, 'img2' is empty."); + } + } + \endcode + - It also allows to use brackets to access pixel values, without need for a \c CImg::operator[](), e.g. + \code + CImg img(100,100); + const float value = img[99]; // Access to value of the last pixel on the first row + img[510] = 255; // Set pixel value at (10,5) + \endcode + **/ + operator T*() { + return _data; + } + + //! Implicitly cast an image into a \c T* \const. + operator const T*() const { + return _data; + } + + //! Assign a value to all image pixels. + /** + Assign specified \c value to each pixel value of the image instance. + \param value Value that will be assigned to image pixels. + \note + - The image size is never modified. + - The \c value may be casted to pixel type \c T if necessary. + \par Example + \code + CImg img(100,100); // Declare image (with garbage values) + img = 0; // Set all pixel values to '0' + img = 1.2; // Set all pixel values to '1' (cast of '1.2' as a 'char') + \endcode + **/ + CImg& operator=(const T& value) { + return fill(value); + } + + //! Assign pixels values from a specified expression. + /** + Initialize all pixel values from the specified string \c expression. + \param expression Value string describing the way pixel values are set. + \note + - String parameter \c expression may describe different things: + - If \c expression is a list of values (as in \c "1,2,3,8,3,2"), or a formula (as in \c "(x*y)%255"), + the pixel values are set from specified \c expression and the image size is not modified. + - If \c expression is a filename (as in \c "reference.jpg"), the corresponding image file is loaded and + replace the image instance. The image size is modified if necessary. + \par Example + \code + CImg img1(100,100), img2(img1), img3(img1); // Declare 3 scalar images 100x100 with uninitialized values + img1 = "0,50,100,150,200,250,200,150,100,50"; // Set pixel values of 'img1' from a value sequence + img2 = "10*((x*y)%25)"; // Set pixel values of 'img2' from a formula + img3 = "reference.jpg"; // Set pixel values of 'img3' from a file (image size is modified) + (img1,img2,img3).display(); + \endcode + \image html ref_operator_eq.jpg + **/ + CImg& operator=(const char *const expression) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + _fill(expression,true,1,0,0,"operator=",0); + } catch (CImgException&) { + cimg::exception_mode(omode); + load(expression); + } + cimg::exception_mode(omode); + return *this; + } + + //! Copy an image into the current image instance. + /** + Similar to the in-place copy constructor assign(const CImg&). + **/ + template + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy an image into the current image instance \specialization. + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy the content of a display window to the current image instance. + /** + Similar to assign(const CImgDisplay&). + **/ + CImg& operator=(const CImgDisplay& disp) { + disp.snapshot(*this); + return *this; + } + + //! In-place addition operator. + /** + Add specified \c value to all pixels of an image instance. + \param value Value to add. + \note + - Resulting pixel values are casted to fit the pixel type \c T. + For instance, adding \c 0.2 to a \c CImg is possible but does nothing indeed. + - Overflow values are treated as with standard C++ numeric types. For instance, + \code + CImg img(100,100,1,1,255); // Construct a 100x100 image with pixel values '255' + img+=1; // Add '1' to each pixels -> Overflow + // here all pixels of image 'img' are equal to '0'. + \endcode + - To prevent value overflow, you may want to consider pixel type \c T as \c float or \c double, + and use cut() after addition. + \par Example + \code + CImg img1("reference.jpg"); // Load a 8-bits RGB image (values in [0,255]) + CImg img2(img1); // Construct a float-valued copy of 'img1' + img2+=100; // Add '100' to pixel values -> goes out of [0,255] but no problems with floats + img2.cut(0,255); // Cut values in [0,255] to fit the 'unsigned char' constraint + img1 = img2; // Rewrite safe result in 'unsigned char' version 'img1' + const CImg img3 = (img1 + 100).cut(0,255); // Do the same in a more simple and elegant way + (img1,img2,img3).display(); + \endcode + \image html ref_operator_plus.jpg + **/ + template + CImg& operator+=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr + value,524288); + return *this; + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the specified string \c expression. + \param expression Value string describing the way pixel values are added. + \note + - Similar to operator=(const char*), except that it adds values to the pixels of the current image instance, + instead of assigning them. + **/ + CImg& operator+=(const char *const expression) { + return *this+=(+*this)._fill(expression,true,1,0,0,"operator+=",this); + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the values of the input image \c img. + \param img Input image to add. + \note + - The size of the image instance is never modified. + - It is not mandatory that input image \c img has the same size as the image instance. + If less values are available in \c img, then the values are added periodically. For instance, adding one + WxH scalar image (spectrum() equal to \c 1) to one WxH color image (spectrum() equal to \c 3) + means each color channel will be incremented with the same values at the same locations. + \par Example + \code + CImg img1("reference.jpg"); // Load a RGB color image (img1.spectrum()==3) + // Construct a scalar shading (img2.spectrum()==1). + const CImg img2(img1.width(),img.height(),1,1,"255*(x/w)^2"); + img1+=img2; // Add shading to each channel of 'img1' + img1.cut(0,255); // Prevent [0,255] overflow + (img2,img1).display(); + \endcode + \image html ref_operator_plus1.jpg + **/ + template + CImg& operator+=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this+=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator++() { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr + 1,524288); + return *this; + } + + //! In-place increment operator (postfix). + /** + Add \c 1 to all image pixels, and return a new copy of the initial (pre-incremented) image instance. + \note + - Use the prefixed version operator++() if you don't need a copy of the initial + (pre-incremented) image instance, since a useless image copy may be expensive in terms of memory usage. + **/ + CImg operator++(int) { + const CImg copy(*this,false); + ++*this; + return copy; + } + + //! Return a non-shared copy of the image instance. + /** + \note + - Use this operator to ensure you get a non-shared copy of an image instance with same pixel type \c T. + Indeed, the usual copy constructor CImg(const CImg&) returns a shared copy of a shared input image, + and it may be not desirable to work on a regular copy (e.g. for a resize operation) if you have no + information about the shared state of the input image. + - Writing \c (+img) is equivalent to \c CImg(img,false). + **/ + CImg operator+() const { + return CImg(*this,false); + } + + //! Addition operator. + /** + Similar to operator+=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const t value) const { + return CImg<_cimg_Tt>(*this,false)+=value; + } + + //! Addition operator. + /** + Similar to operator+=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator+(const char *const expression) const { + return CImg(*this,false)+=expression; + } + + //! Addition operator. + /** + Similar to operator+=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)+=img; + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const t), except that it performs a subtraction instead of an addition. + **/ + template + CImg& operator-=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr - value,524288); + return *this; + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const char*), except that it performs a subtraction instead of an addition. + **/ + CImg& operator-=(const char *const expression) { + return *this-=(+*this)._fill(expression,true,1,0,0,"operator-=",this); + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const CImg&), except that it performs a subtraction instead of an addition. + **/ + template + CImg& operator-=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this-=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator--() { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr - 1,524288); + return *this; + } + + //! In-place decrement operator (postfix). + /** + Similar to operator++(int), except that it performs a decrement instead of an increment. + **/ + CImg operator--(int) { + const CImg copy(*this,false); + --*this; + return copy; + } + + //! Replace each pixel by its opposite value. + /** + \note + - If the computed opposite values are out-of-range, they are treated as with standard C++ numeric types. + For instance, the \c unsigned \c char opposite of \c 1 is \c 255. + \par Example + \code + const CImg + img1("reference.jpg"), // Load a RGB color image + img2 = -img1; // Compute its opposite (in 'unsigned char') + (img1,img2).display(); + \endcode + \image html ref_operator_minus.jpg + **/ + CImg operator-() const { + return CImg(_width,_height,_depth,_spectrum,(T)0)-=*this; + } + + //! Subtraction operator. + /** + Similar to operator-=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const t value) const { + return CImg<_cimg_Tt>(*this,false)-=value; + } + + //! Subtraction operator. + /** + Similar to operator-=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator-(const char *const expression) const { + return CImg(*this,false)-=expression; + } + + //! Subtraction operator. + /** + Similar to operator-=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)-=img; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const t), except that it performs a multiplication instead of an addition. + **/ + template + CImg& operator*=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr * value,262144); + return *this; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const char*), except that it performs a multiplication instead of an addition. + **/ + CImg& operator*=(const char *const expression) { + return mul((+*this)._fill(expression,true,1,0,0,"operator*=",this)); + } + + //! In-place multiplication operator. + /** + Replace the image instance by the matrix multiplication between the image instance and the specified matrix + \c img. + \param img Second operand of the matrix multiplication. + \note + - It does \e not compute a pointwise multiplication between two images. For this purpose, use + mul(const CImg&) instead. + - The size of the image instance can be modified by this operator. + \par Example + \code + CImg A(2,2,1,1, 1,2,3,4); // Construct 2x2 matrix A = [1,2;3,4] + const CImg X(1,2,1,1, 1,2); // Construct 1x2 vector X = [1;2] + A*=X; // Assign matrix multiplication A*X to 'A' + // 'A' is now a 1x2 vector whose values are [5;11]. + \endcode + **/ + template + CImg& operator*=(const CImg& img) { + return ((*this)*img).move_to(*this); + } + + //! Multiplication operator. + /** + Similar to operator*=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const t value) const { + return CImg<_cimg_Tt>(*this,false)*=value; + } + + //! Multiplication operator. + /** + Similar to operator*=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator*(const char *const expression) const { + return CImg(*this,false)*=expression; + } + + //! Multiplication operator. + /** + Similar to operator*=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const CImg& img) const { + typedef _cimg_Ttdouble Ttdouble; + typedef _cimg_Tt Tt; + if (_width!=img._height || _depth!=1 || _spectrum!=1) + throw CImgArgumentException(_cimg_instance + "operator*(): Invalid multiplication of instance by specified " + "matrix (%u,%u,%u,%u,%p).", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + CImg res(img._width,_height); + + // Check for common cases to optimize. + if (img._width==1) { // Matrix * Vector + if (_height==1) switch (_width) { // Vector^T * Vector + case 1 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0]); + return res; + case 2 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1]); + return res; + case 3 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2]); + return res; + case 4 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2] + (Ttdouble)_data[3]*img[3]); + return res; + default : { + Ttdouble val = 0; + cimg_pragma_openmp(parallel for reduction(+:val) cimg_openmp_if_size(size(),4096)) + cimg_forX(*this,i) val+=(Ttdouble)_data[i]*img[i]; + res[0] = val; + return res; + } + } else if (_height==_width) switch (_width) { // Square_matrix * Vector + case 2 : // 2x2_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1]); + res[1] = (Tt)((Ttdouble)_data[2]*img[0] + (Ttdouble)_data[3]*img[1]); + return res; + case 3 : // 3x3_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2]); + res[1] = (Tt)((Ttdouble)_data[3]*img[0] + (Ttdouble)_data[4]*img[1] + + (Ttdouble)_data[5]*img[2]); + res[2] = (Tt)((Ttdouble)_data[6]*img[0] + (Ttdouble)_data[7]*img[1] + + (Ttdouble)_data[8]*img[2]); + return res; + case 4 : // 4x4_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2] + (Ttdouble)_data[3]*img[3]); + res[1] = (Tt)((Ttdouble)_data[4]*img[0] + (Ttdouble)_data[5]*img[1] + + (Ttdouble)_data[6]*img[2] + (Ttdouble)_data[7]*img[3]); + res[2] = (Tt)((Ttdouble)_data[8]*img[0] + (Ttdouble)_data[9]*img[1] + + (Ttdouble)_data[10]*img[2] + (Ttdouble)_data[11]*img[3]); + res[3] = (Tt)((Ttdouble)_data[12]*img[0] + (Ttdouble)_data[13]*img[1] + + (Ttdouble)_data[14]*img[2] + (Ttdouble)_data[15]*img[3]); + return res; + } + } else if (_height==_width) { + if (img._height==img._width) switch (_width) { // Square_matrix * Square_matrix + case 2 : // 2x2_matrix * 2x2_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[2]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[3]); + res[2] = (Tt)((Ttdouble)_data[2]*img[0] + (Ttdouble)_data[3]*img[2]); + res[3] = (Tt)((Ttdouble)_data[2]*img[1] + (Ttdouble)_data[3]*img[3]); + return res; + case 3 : // 3x3_matrix * 3x3_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[3] + + (Ttdouble)_data[2]*img[6]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[4] + + (Ttdouble)_data[2]*img[7]); + res[2] = (Tt)((Ttdouble)_data[0]*img[2] + (Ttdouble)_data[1]*img[5] + + (Ttdouble)_data[2]*img[8]); + res[3] = (Tt)((Ttdouble)_data[3]*img[0] + (Ttdouble)_data[4]*img[3] + + (Ttdouble)_data[5]*img[6]); + res[4] = (Tt)((Ttdouble)_data[3]*img[1] + (Ttdouble)_data[4]*img[4] + + (Ttdouble)_data[5]*img[7]); + res[5] = (Tt)((Ttdouble)_data[3]*img[2] + (Ttdouble)_data[4]*img[5] + + (Ttdouble)_data[5]*img[8]); + res[6] = (Tt)((Ttdouble)_data[6]*img[0] + (Ttdouble)_data[7]*img[3] + + (Ttdouble)_data[8]*img[6]); + res[7] = (Tt)((Ttdouble)_data[6]*img[1] + (Ttdouble)_data[7]*img[4] + + (Ttdouble)_data[8]*img[7]); + res[8] = (Tt)((Ttdouble)_data[6]*img[2] + (Ttdouble)_data[7]*img[5] + + (Ttdouble)_data[8]*img[8]); + return res; + case 4 : // 4x4_matrix * 4x4_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[4] + + (Ttdouble)_data[2]*img[8] + (Ttdouble)_data[3]*img[12]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[5] + + (Ttdouble)_data[2]*img[9] + (Ttdouble)_data[3]*img[13]); + res[2] = (Tt)((Ttdouble)_data[0]*img[2] + (Ttdouble)_data[1]*img[6] + + (Ttdouble)_data[2]*img[10] + (Ttdouble)_data[3]*img[14]); + res[3] = (Tt)((Ttdouble)_data[0]*img[3] + (Ttdouble)_data[1]*img[7] + + (Ttdouble)_data[2]*img[11] + (Ttdouble)_data[3]*img[15]); + res[4] = (Tt)((Ttdouble)_data[4]*img[0] + (Ttdouble)_data[5]*img[4] + + (Ttdouble)_data[6]*img[8] + (Ttdouble)_data[7]*img[12]); + res[5] = (Tt)((Ttdouble)_data[4]*img[1] + (Ttdouble)_data[5]*img[5] + + (Ttdouble)_data[6]*img[9] + (Ttdouble)_data[7]*img[13]); + res[6] = (Tt)((Ttdouble)_data[4]*img[2] + (Ttdouble)_data[5]*img[6] + + (Ttdouble)_data[6]*img[10] + (Ttdouble)_data[7]*img[14]); + res[7] = (Tt)((Ttdouble)_data[4]*img[3] + (Ttdouble)_data[5]*img[7] + + (Ttdouble)_data[6]*img[11] + (Ttdouble)_data[7]*img[15]); + res[8] = (Tt)((Ttdouble)_data[8]*img[0] + (Ttdouble)_data[9]*img[4] + + (Ttdouble)_data[10]*img[8] + (Ttdouble)_data[11]*img[12]); + res[9] = (Tt)((Ttdouble)_data[8]*img[1] + (Ttdouble)_data[9]*img[5] + + (Ttdouble)_data[10]*img[9] + (Ttdouble)_data[11]*img[13]); + res[10] = (Tt)((Ttdouble)_data[8]*img[2] + (Ttdouble)_data[9]*img[6] + + (Ttdouble)_data[10]*img[10] + (Ttdouble)_data[11]*img[14]); + res[11] = (Tt)((Ttdouble)_data[8]*img[3] + (Ttdouble)_data[9]*img[7] + + (Ttdouble)_data[10]*img[11] + (Ttdouble)_data[11]*img[15]); + res[12] = (Tt)((Ttdouble)_data[12]*img[0] + (Ttdouble)_data[13]*img[4] + + (Ttdouble)_data[14]*img[8] + (Ttdouble)_data[15]*img[12]); + res[13] = (Tt)((Ttdouble)_data[12]*img[1] + (Ttdouble)_data[13]*img[5] + + (Ttdouble)_data[14]*img[9] + (Ttdouble)_data[15]*img[13]); + res[14] = (Tt)((Ttdouble)_data[12]*img[2] + (Ttdouble)_data[13]*img[6] + + (Ttdouble)_data[14]*img[10] + (Ttdouble)_data[15]*img[14]); + res[15] = (Tt)((Ttdouble)_data[12]*img[3] + (Ttdouble)_data[13]*img[7] + + (Ttdouble)_data[14]*img[11] + (Ttdouble)_data[15]*img[15]); + return res; + } else switch (_width) { // Square_matrix * Matrix + case 2 : { // 2x2_matrix * Matrix + const t *const ps0 = img.data(), *const ps1 = img.data(0,1); + Tt *const pd0 = res.data(), *const pd1 = res.data(0,1); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], + a2 = (Ttdouble)_data[2], a3 = (Ttdouble)_data[3]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),4096)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i]; + pd0[i] = (Tt)(a0*x + a1*y); + pd1[i] = (Tt)(a2*x + a3*y); + } + return res; + } + case 3 : { // 3x3_matrix * Matrix + const t *const ps0 = img.data(), *const ps1 = img.data(0,1), *const ps2 = img.data(0,2); + Tt *const pd0 = res.data(), *const pd1 = res.data(0,1), *const pd2 = res.data(0,2); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], a2 = (Ttdouble)_data[2], + a3 = (Ttdouble)_data[3], a4 = (Ttdouble)_data[4], a5 = (Ttdouble)_data[5], + a6 = (Ttdouble)_data[6], a7 = (Ttdouble)_data[7], a8 = (Ttdouble)_data[8]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),1024)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i], z = (Ttdouble)ps2[i]; + pd0[i] = (Tt)(a0*x + a1*y + a2*z); + pd1[i] = (Tt)(a3*x + a4*y + a5*z); + pd2[i] = (Tt)(a6*x + a7*y + a8*z); + } + return res; + } + case 4 : { // 4x4_matrix * Matrix + const t + *const ps0 = img.data(), *const ps1 = img.data(0,1), + *const ps2 = img.data(0,2), *const ps3 = img.data(0,3); + Tt + *const pd0 = res.data(), *const pd1 = res.data(0,1), + *const pd2 = res.data(0,2), *const pd3 = res.data(0,3); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], a2 = (Ttdouble)_data[2], a3 = (Ttdouble)_data[3], + a4 = (Ttdouble)_data[4], a5 = (Ttdouble)_data[5], a6 = (Ttdouble)_data[6], a7 = (Ttdouble)_data[7], + a8 = (Ttdouble)_data[8], a9 = (Ttdouble)_data[9], a10 = (Ttdouble)_data[10], a11 = (Ttdouble)_data[11], + a12 = (Ttdouble)_data[12], a13 = (Ttdouble)_data[13], a14 = (Ttdouble)_data[14], + a15 = (Ttdouble)_data[15]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),512)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i], z = (Ttdouble)ps2[i], c = (Ttdouble)ps3[i]; + pd0[i] = (Tt)(a0*x + a1*y + a2*z + a3*c); + pd1[i] = (Tt)(a4*x + a5*y + a6*z + a7*c); + pd2[i] = (Tt)(a8*x + a9*y + a10*z + a11*c); + pd3[i] = (Tt)(a12*x + a13*y + a14*z + a15*c); + } + return res; + } + } + } + + // Fallback to generic version. +#if cimg_use_openmp!=0 + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(size()>(cimg_openmp_sizefactor)*1024 && + img.size()>(cimg_openmp_sizefactor)*1024)) + cimg_forXY(res,i,j) { + Ttdouble value = 0; + cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); + res(i,j) = (Tt)value; + } +#else + Tt *ptrd = res._data; + cimg_forXY(res,i,j) { + Ttdouble value = 0; + cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); + *(ptrd++) = (Tt)value; + } +#endif + return res; + } + + //! In-place division operator. + /** + Similar to operator+=(const t), except that it performs a division instead of an addition. + **/ + template + CImg& operator/=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr / value,32768); + return *this; + } + + //! In-place division operator. + /** + Similar to operator+=(const char*), except that it performs a division instead of an addition. + **/ + CImg& operator/=(const char *const expression) { + return div((+*this)._fill(expression,true,1,0,0,"operator/=",this)); + } + + //! In-place division operator. + /** + Replace the image instance by the (right) matrix division between the image instance and the specified + matrix \c img. + \param img Second operand of the matrix division. + \note + - It does \e not compute a pointwise division between two images. For this purpose, use + div(const CImg&) instead. + - It returns the matrix operation \c A*inverse(img). + - The size of the image instance can be modified by this operator. + **/ + template + CImg& operator/=(const CImg& img) { + return (*this*img.get_invert()).move_to(*this); + } + + //! Division operator. + /** + Similar to operator/=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const t value) const { + return CImg<_cimg_Tt>(*this,false)/=value; + } + + //! Division operator. + /** + Similar to operator/=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator/(const char *const expression) const { + return CImg(*this,false)/=expression; + } + + //! Division operator. + /** + Similar to operator/=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const CImg& img) const { + return (*this)*img.get_invert(); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const t), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::mod(*ptr,(T)value),16384); + return *this; + } + + //! In-place modulo operator. + /** + Similar to operator+=(const char*), except that it performs a modulo operation instead of an addition. + **/ + CImg& operator%=(const char *const expression) { + return *this%=(+*this)._fill(expression,true,1,0,0,"operator%=",this); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const CImg&), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this%=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> operator%(const t value) const { + return CImg<_cimg_Tt>(*this,false)%=value; + } + + //! Modulo operator. + /** + Similar to operator%=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator%(const char *const expression) const { + return CImg(*this,false)%=expression; + } + + //! Modulo operator. + /** + Similar to operator%=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator%(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)%=img; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const t), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr & (ulongT)value,32768); + return *this; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise AND operation instead of an addition. + **/ + CImg& operator&=(const char *const expression) { + return *this&=(+*this)._fill(expression,true,1,0,0,"operator&=",this); + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this&=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator&(const t value) const { + return (+*this)&=value; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator&(const char *const expression) const { + return (+*this)&=expression; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator&(const CImg& img) const { + return (+*this)&=img; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr | (ulongT)value,32768); + return *this; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise OR operation instead of an addition. + **/ + CImg& operator|=(const char *const expression) { + return *this|=(+*this)._fill(expression,true,1,0,0,"operator|=",this); + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this|=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator|(const t value) const { + return (+*this)|=value; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator|(const char *const expression) const { + return (+*this)|=expression; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator|(const CImg& img) const { + return (+*this)|=img; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const t) instead. + **/ + template + CImg& operator^=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr ^ (ulongT)value,32768); + return *this; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const char*) instead. + **/ + CImg& operator^=(const char *const expression) { + return *this^=(+*this)._fill(expression,true,1,0,0,"operator^=",this); + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const CImg&) instead. + **/ + template + CImg& operator^=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator^(const t value) const { + return (+*this)^=value; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator^(const char *const expression) const { + return (+*this)^=expression; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator^(const CImg& img) const { + return (+*this)^=img; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,((longT)*ptr) << (int)value,65536); + return *this; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise left shift instead of an addition. + **/ + CImg& operator<<=(const char *const expression) { + return *this<<=(+*this)._fill(expression,true,1,0,0,"operator<<=",this); + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator<<(const t value) const { + return (+*this)<<=value; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator<<(const char *const expression) const { + return (+*this)<<=expression; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator<<(const CImg& img) const { + return (+*this)<<=img; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,((longT)*ptr) >> (int)value,65536); + return *this; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise right shift instead of an addition. + **/ + CImg& operator>>=(const char *const expression) { + return *this>>=(+*this)._fill(expression,true,1,0,0,"operator>>=",this); + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs> (int)*(ptrs++)); + for (const t *ptrs = img._data; ptrd> (int)*(ptrs++)); + } + return *this; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const t value) const { + return (+*this)>>=value; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator>>(const char *const expression) const { + return (+*this)>>=expression; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const CImg& img) const { + return (+*this)>>=img; + } + + //! Bitwise inversion operator. + /** + Similar to operator-(), except that it compute the bitwise inverse instead of the opposite value. + **/ + CImg operator~() const { + CImg res(_width,_height,_depth,_spectrum); + const T *ptrs = _data; + cimg_for(res,ptrd,T) { const ulongT value = (ulongT)*(ptrs++); *ptrd = (T)~value; } + return res; + } + + //! Test if all pixels of an image have the same value. + /** + Return \c true is all pixels of the image instance are equal to the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator==(const t value) const { + if (is_empty()) return false; + typedef _cimg_Tt Tt; + bool is_equal = true; + for (T *ptrd = _data + size(); is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)value)) {} + return is_equal; + } + + //! Test if all pixel values of an image follow a specified expression. + /** + Return \c true is all pixels of the image instance are equal to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator==(const char *const expression) const { + return *this==(+*this)._fill(expression,true,1,0,0,"operator==",this); + } + + //! Test if two images have the same size and values. + /** + Return \c true if the image instance and the input image \c img have the same pixel values, + even if the dimensions of the two images do not match. It returns \c false otherwise. + \param img Input image to compare with. + \note + - The pixel buffer pointers data() of the two compared images do not have to be the same for operator==() + to return \c true. + Only the dimensions and the pixel values matter. Thus, the comparison can be \c true even for different + pixel types \c T and \c t. + \par Example + \code + const CImg img1(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'float' pixel values) + const CImg img2(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'char' pixel values) + if (img1==img2) { // Test succeeds, image dimensions and values are the same + std::printf("'img1' and 'img2' have same dimensions and values."); + } + \endcode + **/ + template + bool operator==(const CImg& img) const { + typedef _cimg_Tt Tt; + const ulongT siz = size(); + bool is_equal = true; + if (siz!=img.size()) return false; + t *ptrs = img._data + siz; + for (T *ptrd = _data + siz; is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)*(--ptrs))) {} + return is_equal; + } + + //! Test if pixels of an image are all different from a value. + /** + Return \c true is all pixels of the image instance are different than the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator!=(const t value) const { + return !((*this)==value); + } + + //! Test if all pixel values of an image are different from a specified expression. + /** + Return \c true is all pixels of the image instance are different to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator!=(const char *const expression) const { + return !((*this)==expression); + } + + //! Test if two images have different sizes or values. + /** + Return \c true if the image instance and the input image \c img have different dimensions or pixel values, + and \c false otherwise. + \param img Input image to compare with. + \note + - Writing \c img1!=img2 is equivalent to \c !(img1==img2). + **/ + template + bool operator!=(const CImg& img) const { + return !((*this)==img); + } + + //! Construct an image list from two images. + /** + Return a new list of image (\c CImgList instance) containing exactly two elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image \c img, at position [\c 1]. + + \param img Input image that will be the second image of the resulting list. + \note + - The family of operator,() is convenient to easily create list of images, but it is also \e quite \e slow + in practice (see warning below). + - Constructed lists contain no shared images. If image instance or input image \c img are shared, they are + inserted as new non-shared copies in the resulting list. + - The pixel type of the returned list may be a superset of the initial pixel type \c T, if necessary. + \warning + - Pipelining operator,() \c N times will perform \c N copies of the entire content of a (growing) image list. + This may become very expensive in terms of speed and used memory. You should avoid using this technique to + build a new CImgList instance from several images, if you are seeking for performance. + Fast insertions of images in an image list are possible with + CImgList::insert(const CImg&,unsigned int,bool) or move_to(CImgList&,unsigned int). + \par Example + \code + const CImg + img1("reference.jpg"), + img2 = img1.get_mirror('x'), + img3 = img2.get_blur(5); + const CImgList list = (img1,img2); // Create list of two elements from 'img1' and 'img2' + (list,img3).display(); // Display image list containing copies of 'img1','img2' and 'img3' + \endcode + \image html ref_operator_comma.jpg + **/ + template + CImgList<_cimg_Tt> operator,(const CImg& img) const { + return CImgList<_cimg_Tt>(*this,img); + } + + //! Construct an image list from image instance and an input image list. + /** + Return a new list of images (\c CImgList instance) containing exactly \c list.size() \c + \c 1 elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image list \c list, from positions [\c 1] to [\c list.size()]. + + \param list Input image list that will be appended to the image instance. + \note + - Similar to operator,(const CImg&) const, except that it takes an image list as an argument. + **/ + template + CImgList<_cimg_Tt> operator,(const CImgList& list) const { + return CImgList<_cimg_Tt>(list,false).insert(*this,0); + } + + //! Split image along specified axis. + /** + Return a new list of images (\c CImgList instance) containing the split components + of the instance image along the specified axis. + \param axis Splitting axis (can be '\c x','\c y','\c z' or '\c c') + \note + - Similar to get_split(char,int) const, with default second argument. + \par Example + \code + const CImg img("reference.jpg"); // Load a RGB color image + const CImgList list = (img<'c'); // Get a list of its three R,G,B channels + (img,list).display(); + \endcode + \image html ref_operator_less.jpg + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the number of image columns. + /** + Return the image width, i.e. the image dimension along the X-axis. + \note + - The width() of an empty image is equal to \c 0. + - width() is typically equal to \c 1 when considering images as \e vectors for matrix calculations. + - width() returns an \c int, although the image width is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._width. + **/ + int width() const { + return (int)_width; + } + + //! Return the number of image rows. + /** + Return the image height, i.e. the image dimension along the Y-axis. + \note + - The height() of an empty image is equal to \c 0. + - height() returns an \c int, although the image height is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._height. + **/ + int height() const { + return (int)_height; + } + + //! Return the number of image slices. + /** + Return the image depth, i.e. the image dimension along the Z-axis. + \note + - The depth() of an empty image is equal to \c 0. + - depth() is typically equal to \c 1 when considering usual 2D images. When depth()\c > \c 1, the image + is said to be \e volumetric. + - depth() returns an \c int, although the image depth is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._depth. + **/ + int depth() const { + return (int)_depth; + } + + //! Return the number of image channels. + /** + Return the number of image channels, i.e. the image dimension along the C-axis. + \note + - The spectrum() of an empty image is equal to \c 0. + - spectrum() is typically equal to \c 1 when considering scalar-valued images, to \c 3 + for RGB-coded color images, and to \c 4 for RGBA-coded color images (with alpha-channel). + The number of channels of an image instance is not limited. The meaning of the pixel values is not linked + up to the number of channels (e.g. a 4-channel image may indifferently stands for a RGBA or CMYK color image). + - spectrum() returns an \c int, although the image spectrum is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._spectrum. + **/ + int spectrum() const { + return (int)_spectrum; + } + + //! Return the total number of pixel values. + /** + Return width()*\ref height()*\ref depth()*\ref spectrum(), + i.e. the total number of values of type \c T in the pixel buffer of the image instance. + \note + - The size() of an empty image is equal to \c 0. + - The allocated memory size for a pixel buffer of a non-shared \c CImg instance is equal to + size()*sizeof(T). + \par Example + \code + const CImg img(100,100,1,3); // Construct new 100x100 color image + if (img.size()==30000) // Test succeeds + std::printf("Pixel buffer uses %lu bytes", + img.size()*sizeof(float)); + \endcode + **/ + ulongT size() const { + return (ulongT)_width*_height*_depth*_spectrum; + } + + //! Return a pointer to the first pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the first value in the pixel buffer of the image instance, + whether the instance is \c const or not. + \note + - The data() of an empty image is equal to \c 0 (null pointer). + - The allocated pixel buffer for the image instance starts from \c data() + and goes to data()+\ref size() - 1 (included). + - To get the pointer to one particular location of the pixel buffer, use + data(unsigned int,unsigned int,unsigned int,unsigned int) instead. + **/ + T* data() { + return _data; + } + + //! Return a pointer to the first pixel value \const. + const T* data() const { + return _data; + } + + //! Return a pointer to a located pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the value located at (\c x,\c y,\c z,\c c) in the pixel buffer + of the image instance, + whether the instance is \c const or not. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)). Thus, this method has the same + properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + **/ +#if cimg_verbosity>=3 + T *data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (off>=size()) + cimg::warn(_cimg_instance + "data(): Invalid pointer request, at coordinates (%u,%u,%u,%u) [offset=%u].", + cimg_instance, + x,y,z,c,off); + return _data + off; + } + + //! Return a pointer to a located pixel value \const. + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->data(x,y,z,c); + } +#else + T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } + + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } +#endif + + //! Return the offset to a located pixel value, with respect to the beginning of the pixel buffer. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)) - img.data(). + Thus, this method has the same properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + \par Example + \code + const CImg img(100,100,1,3); // Define a 100x100 RGB-color image + const long off = img.offset(10,10,0,2); // Get the offset of the blue value of the pixel located at (10,10) + const float val = img[off]; // Get the blue value of this pixel + \endcode + **/ + longT offset(const int x, const int y=0, const int z=0, const int c=0) const { + return x + (longT)y*_width + (longT)z*_width*_height + (longT)c*_width*_height*_depth; + } + + //! Return a CImg::iterator pointing to the first pixel value. + /** + \note + - Equivalent to data(). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + iterator begin() { + return _data; + } + + //! Return a CImg::iterator pointing to the first value of the pixel buffer \const. + const_iterator begin() const { + return _data; + } + + //! Return a CImg::iterator pointing next to the last pixel value. + /** + \note + - Writing \c img.end() is equivalent to img.data() + img.size(). + - It has been mainly defined for compatibility with STL naming conventions. + \warning + - The returned iterator actually points to a value located \e outside the acceptable bounds of the pixel buffer. + Trying to read or write the content of the returned iterator will probably result in a crash. + Use it mainly as a strict upper bound for a CImg::iterator. + \par Example + \code + CImg img(100,100,1,3); // Define a 100x100 RGB color image + // 'img.end()' used below as an upper bound for the iterator. + for (CImg::iterator it = img.begin(); it::iterator pointing next to the last pixel value \const. + const_iterator end() const { + return _data + size(); + } + + //! Return a reference to the first pixel value. + /** + \note + - Writing \c img.front() is equivalent to img[0], or img(0,0,0,0). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& front() { + return *_data; + } + + //! Return a reference to the first pixel value \const. + const T& front() const { + return *_data; + } + + //! Return a reference to the last pixel value. + /** + \note + - Writing \c img.back() is equivalent to img[img.size() - 1], or + img(img.width() - 1,img.height() - 1,img.depth() - 1,img.spectrum() - 1). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& back() { + return *(_data + size() - 1); + } + + //! Return a reference to the last pixel value \const. + const T& back() const { + return *(_data + size() - 1); + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to a specified default value in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note + - Writing \c img.at(offset,out_value) is similar to img[offset], except that if \c offset + is outside bounds (e.g. \c offset<0 or \c offset>=img.size()), a reference to a value \c out_value + is safely returned instead. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + **/ + T& at(const int offset, const T& out_value) { + return (offset<0 || offset>=(int)size())?(cimg::temporary(out_value)=out_value):(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions \const. + T at(const int offset, const T& out_value) const { + return (offset<0 || offset>=(int)size())?out_value:(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to the nearest pixel location in the image instance in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \note + - Similar to at(int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified offset, i.e. + - If \c offset<0, then \c img[0] is returned. + - If \c offset>=img.size(), then \c img[img.size() - 1] is returned. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + - If you know your image instance is \e not empty, you may rather use the slightly faster method \c _at(int). + **/ + T& at(const int offset) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + T& _at(const int offset) { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions \const. + const T& at(const int offset) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + const T& _at(const int offset) const { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to a specified default value in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c x,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to operator()(), except that an out-of-bounds access along the X-axis returns the specified value + \c out_value. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || x>=width())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate \const. + T atX(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || x>=width())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to the nearest pixel location in the image instance in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to at(int,int,int,int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified X-coordinate. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _at(int,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + T& _atX(const int x, const int y=0, const int z=0, const int c=0) { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate \const. + const T& atX(const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + const T& _atX(const int x, const int y=0, const int z=0, const int c=0) const { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on X and Y-coordinates. + **/ + T& atXY(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || x>=width() || y>=height())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y coordinates \const. + T atXY(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || x>=width() || y>=height())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXY(int,int,int,int). + **/ + T& atXY(const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + T& _atXY(const int x, const int y, const int z=0, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates \const. + const T& atXY(const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + const T& _atXY(const int x, const int y, const int z=0, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on + X,Y and Z-coordinates. + **/ + T& atXYZ(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates \const. + T atXYZ(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZ(int,int,int,int). + **/ + T& atXYZ(const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + T& _atXYZ(const int x, const int y, const int z, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates \const. + const T& atXYZ(const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + const T& _atXYZ(const int x, const int y, const int z, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed on all + X,Y,Z and C-coordinates. + **/ + T& atXYZC(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions \const. + T atXYZC(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())?out_value: + (*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed on all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZC(int,int,int,int). + **/ + T& atXYZC(const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + T& _atXYZC(const int x, const int y, const int z, const int c) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Access to a pixel value, using Neumann boundary conditions \const. + const T& atXYZC(const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + const T& _atXYZC(const int x, const int y, const int z, const int c) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to atX(int,int,int,int,const T), except that the returned pixel value is approximated by + a linear interpolation along the X-axis, if corresponding coordinates are not integers. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + const Tfloat + Ic = (Tfloat)atX(x,y,z,c,out_value), In = (Tfloat)atXY(nx,y,z,c,out_value); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access along + the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that an out-of-bounds access returns + the value of the nearest pixel in the image instance, regarding the specified X-coordinate. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX(): Empty instance.", + cimg_instance); + + return _linear_atX(fx,y,z,c); + } + + Tfloat _linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = dx>0?x + 1:x; + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X-coordinate. + Tfloat linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX_p(): Empty instance.", + cimg_instance); + + return _linear_atX_p(fx,y,z,c); + } + + Tfloat _linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = cimg::mod(x + 1,_width); + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X and Y-coordinates. + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + const Tfloat + Icc = (Tfloat)atXY(x,y,z,c,out_value), Inc = (Tfloat)atXY(nx,y,z,c,out_value), + Icn = (Tfloat)atXY(x,ny,z,c,out_value), Inn = (Tfloat)atXY(nx,ny,z,c,out_value); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXY(float,float,int,int). + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY(): Empty instance.", + cimg_instance); + + return _linear_atXY(fx,fy,z,c); + } + + Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y; + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X and Y-coordinates. + Tfloat linear_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY_p(): Empty instance.", + cimg_instance); + + return _linear_atXY_p(fx,fy,z,c); + } + + Tfloat _linear_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height); + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X,Y and Z-coordinates. + **/ + Tfloat linear_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + const Tfloat + Iccc = (Tfloat)atXYZ(x,y,z,c,out_value), Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), + Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), + Iccn = (Tfloat)atXYZ(x,y,nz,c,out_value), Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), + Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZ(float,float,float,int). + **/ + Tfloat linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ(): Empty instance.", + cimg_instance); + + return _linear_atXYZ(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z; + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X,Y and Z-coordinates. + Tfloat linear_atXYZ_p(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ_p(): Empty instance.", + cimg_instance); + + return _linear_atXYZ_p(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ_p(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f), + nfz = cimg::mod(fz,_depth - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height), + nz = cimg::mod(z + 1,_depth); + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for all X,Y,Z,C-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved for all X,Y,Z and C-coordinates. + **/ + Tfloat linear_atXYZC(const float fx, const float fy, const float fz, const float fc, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1, + c = (int)fc - (fc>=0?0:1), nc = c + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z, + dc = fc - c; + const Tfloat + Icccc = (Tfloat)atXYZC(x,y,z,c,out_value), Inccc = (Tfloat)atXYZC(nx,y,z,c,out_value), + Icncc = (Tfloat)atXYZC(x,ny,z,c,out_value), Inncc = (Tfloat)atXYZC(nx,ny,z,c,out_value), + Iccnc = (Tfloat)atXYZC(x,y,nz,c,out_value), Incnc = (Tfloat)atXYZC(nx,y,nz,c,out_value), + Icnnc = (Tfloat)atXYZC(x,ny,nz,c,out_value), Innnc = (Tfloat)atXYZC(nx,ny,nz,c,out_value), + Icccn = (Tfloat)atXYZC(x,y,z,nc,out_value), Inccn = (Tfloat)atXYZC(nx,y,z,nc,out_value), + Icncn = (Tfloat)atXYZC(x,ny,z,nc,out_value), Inncn = (Tfloat)atXYZC(nx,ny,z,nc,out_value), + Iccnn = (Tfloat)atXYZC(x,y,nz,nc,out_value), Incnn = (Tfloat)atXYZC(nx,y,nz,nc,out_value), + Icnnn = (Tfloat)atXYZC(x,ny,nz,nc,out_value), Innnn = (Tfloat)atXYZC(nx,ny,nz,nc,out_value); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn -Icccc); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for all X,Y,Z and C-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved for all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZC(float,float,float,float). + **/ + Tfloat linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC(): Empty instance.", + cimg_instance); + + return _linear_atXYZC(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1), + nfc = cimg::cut(fc,0,spectrum() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z, + nc = dc>0?c + 1:c; + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for all X,Y,Z and C-coordinates. + Tfloat linear_atXYZC_p(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC_p(): Empty instance.", + cimg_instance); + + return _linear_atXYZC_p(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC_p(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f), + nfz = cimg::mod(fz,_depth - 0.5f), + nfc = cimg::mod(fc,_spectrum - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height), + nz = cimg::mod(z + 1,_depth), + nc = cimg::mod(c + 1,_spectrum); + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + The cubic interpolation uses Hermite splines. + \param fx d X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a \e cubic interpolation along the X-axis. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2; + const float + dx = fx - x; + const Tfloat + Ip = (Tfloat)atX(px,y,z,c,out_value), Ic = (Tfloat)atX(x,y,z,c,out_value), + In = (Tfloat)atX(nx,y,z,c,out_value), Ia = (Tfloat)atX(ax,y,z,c,out_value); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atX_c(const float fx, const int y, const int z, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atX(fx,y,z,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access + along the X-axis. The cubic interpolation uses Hermite splines. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to cubic_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a cubic interpolation along the X-axis. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX(): Empty instance.", + cimg_instance); + return _cubic_atX(fx,y,z,c); + } + + Tfloat _cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2; + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atX_c(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(cubic_atX(fx,y,z,c)); + } + + T _cubic_atX_c(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(_cubic_atX(fx,y,z,c)); + } + + //! Return pixel value, using cubic interpolation and periodic boundary conditions for the X-coordinate. + Tfloat cubic_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX_p(): Empty instance.", + cimg_instance); + return _cubic_atX_p(fx,y,z,c); + } + + Tfloat _cubic_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()); + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atX_pc(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(cubic_atX_p(fx,y,z,c)); + } + + T _cubic_atX_pc(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(_cubic_atX_p(fx,y,z,c)); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X and Y-coordinates. + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2; + const float dx = fx - x, dy = fy - y; + const Tfloat + Ipp = (Tfloat)atXY(px,py,z,c,out_value), Icp = (Tfloat)atXY(x,py,z,c,out_value), + Inp = (Tfloat)atXY(nx,py,z,c,out_value), Iap = (Tfloat)atXY(ax,py,z,c,out_value), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)atXY(px,y,z,c,out_value), Icc = (Tfloat)atXY(x, y,z,c,out_value), + Inc = (Tfloat)atXY(nx,y,z,c,out_value), Iac = (Tfloat)atXY(ax,y,z,c,out_value), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)atXY(px,ny,z,c,out_value), Icn = (Tfloat)atXY(x,ny,z,c,out_value), + Inn = (Tfloat)atXY(nx,ny,z,c,out_value), Ian = (Tfloat)atXY(ax,ny,z,c,out_value), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)atXY(px,ay,z,c,out_value), Ica = (Tfloat)atXY(x,ay,z,c,out_value), + Ina = (Tfloat)atXY(nx,ay,z,c,out_value), Iaa = (Tfloat)atXY(ax,ay,z,c,out_value), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int,const T) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXY_c(const float fx, const float fy, const int z, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atXY(fx,fy,z,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved for both X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXY(float,float,int,int). + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY(): Empty instance.", + cimg_instance); + return _cubic_atXY(fx,fy,z,c); + } + + Tfloat _cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1), + nfy = cimg::type::is_nan(fy)?0:cimg::cut(fy,0,height() - 1); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = x - 1<0?0:x - 1, nx = dx<=0?x:x + 1, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy<=0?y:y + 1, ay = y + 2>=height()?height() - 1:y + 2; + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXY_c(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(cubic_atXY(fx,fy,z,c)); + } + + T _cubic_atXY_c(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(_cubic_atXY(fx,fy,z,c)); + } + + //! Return pixel value, using cubic interpolation and periodic boundary conditions for the X and Y-coordinates. + Tfloat cubic_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY_p(): Empty instance.", + cimg_instance); + return _cubic_atXY_p(fx,fy,z,c); + } + + Tfloat _cubic_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f), + nfy = cimg::type::is_nan(fy)?0:cimg::mod(fy,_height - 0.5f); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()), + py = cimg::mod(y - 1,height()), ny = cimg::mod(y + 1,height()), ay = cimg::mod(y + 2,height()); + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atXY_pc(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(cubic_atXY_p(fx,fy,z,c)); + } + + T _cubic_atXY_pc(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(_cubic_atXY_p(fx,fy,z,c)); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2, + z = (int)fz - (fz>=0?0:1), pz = z - 1, nz = z + 1, az = z + 2; + const float dx = fx - x, dy = fy - y, dz = fz - z; + const Tfloat + Ippp = (Tfloat)atXYZ(px,py,pz,c,out_value), Icpp = (Tfloat)atXYZ(x,py,pz,c,out_value), + Inpp = (Tfloat)atXYZ(nx,py,pz,c,out_value), Iapp = (Tfloat)atXYZ(ax,py,pz,c,out_value), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)atXYZ(px,y,pz,c,out_value), Iccp = (Tfloat)atXYZ(x, y,pz,c,out_value), + Incp = (Tfloat)atXYZ(nx,y,pz,c,out_value), Iacp = (Tfloat)atXYZ(ax,y,pz,c,out_value), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)atXYZ(px,ny,pz,c,out_value), Icnp = (Tfloat)atXYZ(x,ny,pz,c,out_value), + Innp = (Tfloat)atXYZ(nx,ny,pz,c,out_value), Ianp = (Tfloat)atXYZ(ax,ny,pz,c,out_value), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)atXYZ(px,ay,pz,c,out_value), Icap = (Tfloat)atXYZ(x,ay,pz,c,out_value), + Inap = (Tfloat)atXYZ(nx,ay,pz,c,out_value), Iaap = (Tfloat)atXYZ(ax,ay,pz,c,out_value), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)atXYZ(px,py,z,c,out_value), Icpc = (Tfloat)atXYZ(x,py,z,c,out_value), + Inpc = (Tfloat)atXYZ(nx,py,z,c,out_value), Iapc = (Tfloat)atXYZ(ax,py,z,c,out_value), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)atXYZ(px,y,z,c,out_value), Iccc = (Tfloat)atXYZ(x, y,z,c,out_value), + Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), Iacc = (Tfloat)atXYZ(ax,y,z,c,out_value), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)atXYZ(px,ny,z,c,out_value), Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), + Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), Ianc = (Tfloat)atXYZ(ax,ny,z,c,out_value), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)atXYZ(px,ay,z,c,out_value), Icac = (Tfloat)atXYZ(x,ay,z,c,out_value), + Inac = (Tfloat)atXYZ(nx,ay,z,c,out_value), Iaac = (Tfloat)atXYZ(ax,ay,z,c,out_value), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)atXYZ(px,py,nz,c,out_value), Icpn = (Tfloat)atXYZ(x,py,nz,c,out_value), + Inpn = (Tfloat)atXYZ(nx,py,nz,c,out_value), Iapn = (Tfloat)atXYZ(ax,py,nz,c,out_value), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)atXYZ(px,y,nz,c,out_value), Iccn = (Tfloat)atXYZ(x, y,nz,c,out_value), + Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), Iacn = (Tfloat)atXYZ(ax,y,nz,c,out_value), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)atXYZ(px,ny,nz,c,out_value), Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), + Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value), Iann = (Tfloat)atXYZ(ax,ny,nz,c,out_value), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)atXYZ(px,ay,nz,c,out_value), Ican = (Tfloat)atXYZ(x,ay,nz,c,out_value), + Inan = (Tfloat)atXYZ(nx,ay,nz,c,out_value), Iaan = (Tfloat)atXYZ(ax,ay,nz,c,out_value), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)atXYZ(px,py,az,c,out_value), Icpa = (Tfloat)atXYZ(x,py,az,c,out_value), + Inpa = (Tfloat)atXYZ(nx,py,az,c,out_value), Iapa = (Tfloat)atXYZ(ax,py,az,c,out_value), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)atXYZ(px,y,az,c,out_value), Icca = (Tfloat)atXYZ(x, y,az,c,out_value), + Inca = (Tfloat)atXYZ(nx,y,az,c,out_value), Iaca = (Tfloat)atXYZ(ax,y,az,c,out_value), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)atXYZ(px,ny,az,c,out_value), Icna = (Tfloat)atXYZ(x,ny,az,c,out_value), + Inna = (Tfloat)atXYZ(nx,ny,az,c,out_value), Iana = (Tfloat)atXYZ(ax,ny,az,c,out_value), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)atXYZ(px,ay,az,c,out_value), Icaa = (Tfloat)atXYZ(x,ay,az,c,out_value), + Inaa = (Tfloat)atXYZ(nx,ay,az,c,out_value), Iaaa = (Tfloat)atXYZ(ax,ay,az,c,out_value), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int,const T) const, except that the return value is clamped to stay + in the min/max range of the datatype \c T. + **/ + T cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atXYZ(fx,fy,fz,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ(): Empty instance.", + cimg_instance); + return _cubic_atXYZ(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1), + nfy = cimg::type::is_nan(fy)?0:cimg::cut(fy,0,height() - 1), + nfz = cimg::type::is_nan(fz)?0:cimg::cut(fz,0,depth() - 1); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy>0?y + 1:y, ay = y + 2>=height()?height() - 1:y + 2, + pz = z - 1<0?0:z - 1, nz = dz>0?z + 1:z, az = z + 2>=depth()?depth() - 1:z + 2; + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(cubic_atXYZ(fx,fy,fz,c)); + } + + T _cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(_cubic_atXYZ(fx,fy,fz,c)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ_p(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ_p(): Empty instance.", + cimg_instance); + return _cubic_atXYZ_p(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ_p(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f), + nfy = cimg::type::is_nan(fy)?0:cimg::mod(fy,_height - 0.5f), + nfz = cimg::type::is_nan(fz)?0:cimg::mod(fz,_depth - 0.5f); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()), + py = cimg::mod(y - 1,height()), ny = cimg::mod(y + 1,height()), ay = cimg::mod(y + 2,height()), + pz = cimg::mod(z - 1,depth()), nz = cimg::mod(z + 1,depth()), az = cimg::mod(z + 2,depth()); + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atXYZ_pc(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(cubic_atXYZ_p(fx,fy,fz,c)); + } + + T _cubic_atXYZ_pc(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(_cubic_atXYZ_p(fx,fy,fz,c)); + } + + //! Set pixel value, using linear interpolation for the X-coordinates. + /** + Set pixel value at specified coordinates (\c fx,\c y,\c z,\c c) in the image instance, in a way that + the value is spread amongst several neighbors if the pixel coordinates are float-valued. + \param value Pixel value to set. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param is_added Tells if the pixel value is added to (\c true), or simply replace (\c false) the current image + pixel(s). + \return A reference to the current image instance. + \note + - Calling this method with out-of-bounds coordinates does nothing. + **/ + CImg& set_linear_atX(const T& value, const float fx, const int y=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + if (y>=0 && y=0 && z=0 && c=0 && x=0 && nx& set_linear_atXY(const T& value, const float fx, const float fy=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + if (z>=0 && z=0 && c=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx& set_linear_atXYZ(const T& value, const float fx, const float fy=0, const float fz=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + if (c>=0 && c=0 && z=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx=0 && nz=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx image whose buffer data() is a \c char* string describing the list of all pixel values + of the image instance (written in base 10), separated by specified \c separator character. + \param separator A \c char character which specifies the separator between values in the returned C-string. + \param max_size Maximum size of the returned image (or \c 0 if no limits are set). + \param format For float/double-values, tell the printf format used to generate the text representation + of the numbers (or \c 0 for default representation). + \note + - The returned image is never empty. + - For an empty image instance, the returned string is "". + - If \c max_size is equal to \c 0, there are no limits on the size of the returned string. + - Otherwise, if the maximum number of string characters is exceeded, the value string is cut off + and terminated by character \c '\0'. In that case, the returned image size is max_size + 1. + **/ + CImg value_string(const char separator=',', const unsigned int max_size=0, + const char *const format=0) const { + if (is_empty() || max_size==1) return CImg(1,1,1,1,0); + CImgList items; + CImg s_item(256); *s_item = 0; + const T *ptrs = _data; + unsigned int string_size = 0; + const char *const _format = format?format:cimg::type::format(); + for (ulongT off = 0, siz = size(); off::format(*(ptrs++))); + CImg item(s_item._data,printed_size); + item[printed_size - 1] = separator; + item.move_to(items); + if (max_size) string_size+=printed_size; + } + CImg res; + (items>'x').move_to(res); + if (max_size && res._width>=max_size) res.crop(0,max_size - 1); + res.back() = 0; + return res; + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Test shared state of the pixel buffer. + /** + Return \c true if image instance has a shared memory buffer, and \c false otherwise. + \note + - A shared image do not own his pixel buffer data() and will not deallocate it on destruction. + - Most of the time, a \c CImg image instance will \e not be shared. + - A shared image can only be obtained by a limited set of constructors and methods (see list below). + **/ + bool is_shared() const { + return _is_shared; + } + + //! Test if image instance is empty. + /** + Return \c true, if image instance is empty, i.e. does \e not contain any pixel values, has dimensions + \c 0 x \c 0 x \c 0 x \c 0 and a pixel buffer pointer set to \c 0 (null pointer), and \c false otherwise. + **/ + bool is_empty() const { + return !(_data && _width && _height && _depth && _spectrum); + } + + //! Test if image instance contains a 'inf' value. + /** + Return \c true, if image instance contains a 'inf' value, and \c false otherwise. + **/ + bool is_inf() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_inf((float)*p)) return true; + return false; + } + + //! Test if image instance contains a NaN value. + /** + Return \c true, if image instance contains a NaN value, and \c false otherwise. + **/ + bool is_nan() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_nan((float)*p)) return true; + return false; + } + + //! Test if image width is equal to specified value. + bool is_sameX(const unsigned int size_x) const { + return _width==size_x; + } + + //! Test if image width is equal to specified value. + template + bool is_sameX(const CImg& img) const { + return is_sameX(img._width); + } + + //! Test if image width is equal to specified value. + bool is_sameX(const CImgDisplay& disp) const { + return is_sameX(disp._width); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const unsigned int size_y) const { + return _height==size_y; + } + + //! Test if image height is equal to specified value. + template + bool is_sameY(const CImg& img) const { + return is_sameY(img._height); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const CImgDisplay& disp) const { + return is_sameY(disp._height); + } + + //! Test if image depth is equal to specified value. + bool is_sameZ(const unsigned int size_z) const { + return _depth==size_z; + } + + //! Test if image depth is equal to specified value. + template + bool is_sameZ(const CImg& img) const { + return is_sameZ(img._depth); + } + + //! Test if image spectrum is equal to specified value. + bool is_sameC(const unsigned int size_c) const { + return _spectrum==size_c; + } + + //! Test if image spectrum is equal to specified value. + template + bool is_sameC(const CImg& img) const { + return is_sameC(img._spectrum); + } + + //! Test if image width and height are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameY(unsigned int) const are both verified. + **/ + bool is_sameXY(const unsigned int size_x, const unsigned int size_y) const { + return _width==size_x && _height==size_y; + } + + //! Test if image width and height are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameY(const CImg&) const are both verified. + **/ + template + bool is_sameXY(const CImg& img) const { + return is_sameXY(img._width,img._height); + } + + //! Test if image width and height are the same as that of an existing display window. + /** + Test if is_sameX(const CImgDisplay&) const and is_sameY(const CImgDisplay&) const are both verified. + **/ + bool is_sameXY(const CImgDisplay& disp) const { + return is_sameXY(disp._width,disp._height); + } + + //! Test if image width and depth are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXZ(const unsigned int size_x, const unsigned int size_z) const { + return _width==size_x && _depth==size_z; + } + + //! Test if image width and depth are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXZ(const CImg& img) const { + return is_sameXZ(img._width,img._depth); + } + + //! Test if image width and spectrum are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXC(const unsigned int size_x, const unsigned int size_c) const { + return _width==size_x && _spectrum==size_c; + } + + //! Test if image width and spectrum are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXC(const CImg& img) const { + return is_sameXC(img._width,img._spectrum); + } + + //! Test if image height and depth are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameYZ(const unsigned int size_y, const unsigned int size_z) const { + return _height==size_y && _depth==size_z; + } + + //! Test if image height and depth are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameYZ(const CImg& img) const { + return is_sameYZ(img._height,img._depth); + } + + //! Test if image height and spectrum are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYC(const unsigned int size_y, const unsigned int size_c) const { + return _height==size_y && _spectrum==size_c; + } + + //! Test if image height and spectrum are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYC(const CImg& img) const { + return is_sameYC(img._height,img._spectrum); + } + + //! Test if image depth and spectrum are equal to specified values. + /** + Test if is_sameZ(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameZC(const unsigned int size_z, const unsigned int size_c) const { + return _depth==size_z && _spectrum==size_c; + } + + //! Test if image depth and spectrum are the same as that of another image. + /** + Test if is_sameZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameZC(const CImg& img) const { + return is_sameZC(img._depth,img._spectrum); + } + + //! Test if image width, height and depth are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXYZ(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z) const { + return is_sameXY(size_x,size_y) && _depth==size_z; + } + + //! Test if image width, height and depth are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXYZ(const CImg& img) const { + return is_sameXYZ(img._width,img._height,img._depth); + } + + //! Test if image width, height and spectrum are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXYC(const unsigned int size_x, const unsigned int size_y, const unsigned int size_c) const { + return is_sameXY(size_x,size_y) && _spectrum==size_c; + } + + //! Test if image width, height and spectrum are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYC(const CImg& img) const { + return is_sameXYC(img._width,img._height,img._spectrum); + } + + //! Test if image width, depth and spectrum are equal to specified values. + /** + Test if is_sameXZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXZC(const unsigned int size_x, const unsigned int size_z, const unsigned int size_c) const { + return is_sameXZ(size_x,size_z) && _spectrum==size_c; + } + + //! Test if image width, depth and spectrum are the same as that of another image. + /** + Test if is_sameXZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXZC(const CImg& img) const { + return is_sameXZC(img._width,img._depth,img._spectrum); + } + + //! Test if image height, depth and spectrum are equal to specified values. + /** + Test if is_sameYZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYZC(const unsigned int size_y, const unsigned int size_z, const unsigned int size_c) const { + return is_sameYZ(size_y,size_z) && _spectrum==size_c; + } + + //! Test if image height, depth and spectrum are the same as that of another image. + /** + Test if is_sameYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYZC(const CImg& img) const { + return is_sameYZC(img._height,img._depth,img._spectrum); + } + + //! Test if image width, height, depth and spectrum are equal to specified values. + /** + Test if is_sameXYZ(unsigned int,unsigned int,unsigned int) const and is_sameC(unsigned int) const are both + verified. + **/ + bool is_sameXYZC(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c) const { + return is_sameXYZ(size_x,size_y,size_z) && _spectrum==size_c; + } + + //! Test if image width, height, depth and spectrum are the same as that of another image. + /** + Test if is_sameXYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYZC(const CImg& img) const { + return is_sameXYZC(img._width,img._height,img._depth,img._spectrum); + } + + //! Test if specified coordinates are inside image bounds. + /** + Return \c true if pixel located at (\c x,\c y,\c z,\c c) is inside bounds of the image instance, + and \c false otherwise. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Return \c true only if all these conditions are verified: + - The image instance is \e not empty. + - 0<=x<=\ref width() - 1. + - 0<=y<=\ref height() - 1. + - 0<=z<=\ref depth() - 1. + - 0<=c<=\ref spectrum() - 1. + **/ + bool containsXYZC(const int x, const int y=0, const int z=0, const int c=0) const { + return !is_empty() && x>=0 && x=0 && y=0 && z=0 && c img(100,100,1,3); // Construct a 100x100 RGB color image + const unsigned long offset = 1249; // Offset to the pixel (49,12,0,0) + unsigned int x,y,z,c; + if (img.contains(img[offset],x,y,z,c)) { // Convert offset to (x,y,z,c) coordinates + std::printf("Offset %u refers to pixel located at (%u,%u,%u,%u).\n", + offset,x,y,z,c); + } + \endcode + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z, t& c) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = (ulongT)(ppixel - _data); + const ulongT nc = off/whd; + off%=whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; c = (t)nc; + return true; + } + + //! Test if pixel value is inside image bounds and get its X,Y and Z-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X,Y and Z-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((ulongT)(ppixel - _data))%whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; + return true; + } + + //! Test if pixel value is inside image bounds and get its X and Y-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X and Y-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y) const { + const ulongT wh = (ulongT)_width*_height, siz = wh*_depth*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((unsigned int)(ppixel - _data))%wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; + return true; + } + + //! Test if pixel value is inside image bounds and get its X-coordinate. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X-coordinate is set. + **/ + template + bool contains(const T& pixel, t& x) const { + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + size()) return false; + x = (t)(((ulongT)(ppixel - _data))%_width); + return true; + } + + //! Test if pixel value is inside image bounds. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that no pixel coordinates are set. + **/ + bool contains(const T& pixel) const { + const T *const ppixel = &pixel; + return !is_empty() && ppixel>=_data && ppixel<_data + size(); + } + + //! Test if pixel buffers of instance and input images overlap. + /** + Return \c true, if pixel buffers attached to image instance and input image \c img overlap, + and \c false otherwise. + \param img Input image to compare with. + \note + - Buffer overlapping may happen when manipulating \e shared images. + - If two image buffers overlap, operating on one of the image will probably modify the other one. + - Most of the time, \c CImg instances are \e non-shared and do not overlap between each others. + \par Example + \code + const CImg + img1("reference.jpg"), // Load RGB-color image + img2 = img1.get_shared_channel(1); // Get shared version of the green channel + if (img1.is_overlapped(img2)) { // Test succeeds, 'img1' and 'img2' overlaps + std::printf("Buffers overlap!\n"); + } + \endcode + **/ + template + bool is_overlapped(const CImg& img) const { + const ulongT csiz = size(), isiz = img.size(); + return !((void*)(_data + csiz)<=(void*)img._data || (void*)_data>=(void*)(img._data + isiz)); + } + + //! Test if the set {\c *this,\c primitives,\c colors,\c opacities} defines a valid 3D object. + /** + Return \c true is the 3D object represented by the set {\c *this,\c primitives,\c colors,\c opacities} defines a + valid 3D object, and \c false otherwise. The vertex coordinates are defined by the instance image. + \param primitives List of primitives of the 3D object. + \param colors List of colors of the 3D object. + \param opacities List (or image) of opacities of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_checking to \c false to speed-up the 3D object checking. In this case, only the size of + each 3D object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + template + bool is_object3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true, + char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check consistency for the particular case of an empty 3D object. + if (is_empty()) { + if (primitives || colors || opacities) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines no vertices but %u primitives, " + "%u colors and %lu opacities", + _width,primitives._width,primitives._width, + colors._width,(unsigned long)opacities.size()); + return false; + } + return true; + } + + // Check consistency of vertices. + if (_height!=3 || _depth>1 || _spectrum>1) { // Check vertices dimensions + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) has invalid vertex dimensions (%u,%u,%u,%u)", + _width,primitives._width,_width,_height,_depth,_spectrum); + return false; + } + if (colors._width>primitives._width + 1) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines %u colors", + _width,primitives._width,colors._width); + return false; + } + if (opacities.size()>primitives._width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines %lu opacities", + _width,primitives._width,(unsigned long)opacities.size()); + return false; + } + if (!full_check) return true; + + // Check consistency of primitives. + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + const unsigned int psiz = (unsigned int)primitive.size(); + switch (psiz) { + case 1 : { // Point + const unsigned int i0 = (unsigned int)primitive(0); + if (i0>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex index %u in " + "point primitive [%u]", + _width,primitives._width,i0,l); + return false; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + if (i0>=_width || i1>=_width || i2>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + _width,primitives._width,i0,i1,i2,l); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + if (i0>=_width || i1>=_width || i2>=_width || i3>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + _width,primitives._width,i0,i1,i2,i3,l); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines an invalid primitive [%u] of size %u", + _width,primitives._width,l,(unsigned int)psiz); + return false; + } + } + + // Check consistency of colors. + cimglist_for(colors,c) { + const CImg& color = colors[c]; + if (!color) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines no color for primitive [%u]", + _width,primitives._width,c); + return false; + } + } + + // Check consistency of light texture. + if (colors._width>primitives._width) { + const CImg &light = colors.back(); + if (!light || light._depth>1) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines an invalid light texture (%u,%u,%u,%u)", + _width,primitives._width,light._width, + light._height,light._depth,light._spectrum); + return false; + } + } + + return true; + } + + //! Test if image instance represents a valid serialization of a 3D object. + /** + Return \c true if the image instance represents a valid serialization of a 3D object, and \c false otherwise. + \param full_check Tells if full checking of the instance must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_check to \c false to speed-up the 3D object checking. In this case, only the size of + each 3D object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + bool is_CImg3d(const bool full_check=true, char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check instance dimension and header. + if (_width!=1 || _height<8 || _depth!=1 || _spectrum!=1) { + if (error_message) cimg_sprintf(error_message, + "CImg3d has invalid dimensions (%u,%u,%u,%u)", + _width,_height,_depth,_spectrum); + return false; + } + const T *ptrs = _data, *const ptre = end(); + if (!_is_CImg3d(*(ptrs++),'C') || !_is_CImg3d(*(ptrs++),'I') || !_is_CImg3d(*(ptrs++),'m') || + !_is_CImg3d(*(ptrs++),'g') || !_is_CImg3d(*(ptrs++),'3') || !_is_CImg3d(*(ptrs++),'d')) { + if (error_message) cimg_sprintf(error_message, + "CImg3d header not found"); + return false; + } + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + + // Check consistency of number of vertices / primitives. + if (!full_check) { + const ulongT minimal_size = 8UL + 3*nb_points + 6*nb_primitives; + if (_data + minimal_size>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has only %lu values, while at least %lu values were expected", + nb_points,nb_primitives,(unsigned long)size(),(unsigned long)minimal_size); + return false; + } + } + + // Check consistency of vertex data. + if (!nb_points) { + if (nb_primitives) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no vertices but %u primitives", + nb_points,nb_primitives,nb_primitives); + return false; + } + if (ptrs!=ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) is an empty object but contains %u value%s " + "more than expected", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs),(ptre - ptrs)>1?"s":""); + return false; + } + return true; + } + if (ptrs + 3*nb_points>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines only %u vertices data", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs)/3); + return false; + } + ptrs+=3*nb_points; + + // Check consistency of primitive data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines %u vertices but no primitive", + nb_points,nb_primitives,nb_points); + return false; + } + + if (!full_check) return true; + + for (unsigned int p = 0; p=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex index %u in point primitive [%u]", + nb_points,nb_primitives,i0,p); + return false; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + ptrs+=3; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==6) ptrs+=4; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==9) ptrs+=6; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,p); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)), + i3 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==12) ptrs+=8; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points || i3>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,i3,p); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines an invalid primitive [%u] of size %u", + nb_points,nb_primitives,p,nb_inds); + return false; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete primitive data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,p,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of color data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no color/texture data", + nb_points,nb_primitives); + return false; + } + for (unsigned int c = 0; c=c) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared sprite/texture index %u " + "for primitive [%u]", + nb_points,nb_primitives,w,c); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete color/texture data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,c,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of opacity data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no opacity data", + nb_points,nb_primitives); + return false; + } + for (unsigned int o = 0; o=o) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared opacity index %u " + "for primitive [%u]", + nb_points,nb_primitives,w,o); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete opacity data for primitive [%u]", + nb_points,nb_primitives,o); + return false; + } + } + + // Check end of data. + if (ptrs1?"s":""); + return false; + } + return true; + } + + static bool _is_CImg3d(const T val, const char c) { + return val>=(T)c && val<(T)(c + 1); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + // Define the math formula parser/compiler and expression evaluator. + struct _cimg_math_parser { + CImg mem; + CImg memtype, memmerge; + CImgList _code, &code, code_begin, code_end, + _code_begin_t, &code_begin_t, _code_end_t, &code_end_t; + CImg opcode; + const CImg *p_code_end, *p_code; + const CImg *const p_break; + + CImg expr, pexpr; + const CImg& imgin; + const CImgList& listin; + CImg &imgout; + CImgList& listout; + + CImg _img_stats, &img_stats, constcache_vals; + CImgList _list_stats, &list_stats, _list_median, &list_median, _list_norm, &list_norm; + CImg mem_img_stats, constcache_inds; + + CImg level, variable_pos, reserved_label; + CImgList variable_def, macro_def, macro_body; + CImgList macro_body_is_string; + char *user_macro; + + unsigned int mempos, mem_img_median, mem_img_norm, mem_img_index, debug_indent, result_dim, break_type, + constcache_size; + bool is_parallelizable, is_end_code, is_fill, return_new_comp, need_input_copy; + double *result; + cimg_uint64 rng; + const char *const calling_function, *s_op, *ss_op; + typedef double (*mp_func)(_cimg_math_parser&); + +#define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant value? +#define _cimg_mp_is_scalar(arg) (memtype[arg]<2) // Is scalar value? +#define _cimg_mp_is_comp(arg) (!memtype[arg]) // Is computation value? +#define _cimg_mp_is_reserved(arg) (memtype[arg]==-1) // Is scalar and reserved (e.g. variable)? +#define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector? +#define _cimg_mp_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Size (0=scalar, N>0=vectorN) +#define _cimg_mp_calling_function s_calling_function()._data +#define _cimg_mp_op(s) s_op = s; ss_op = ss +#define _cimg_mp_check_type(arg,n_arg,mode,N) check_type(arg,n_arg,mode,N,ss,se,saved_char) +#define _cimg_mp_check_constant(arg,n_arg,mode) check_constant(arg,n_arg,mode,ss,se,saved_char) +#define _cimg_mp_check_constant_index(arg) check_constant_index(arg,ss,se,saved_char) +#define _cimg_mp_check_matrix_square(arg,n_arg) check_matrix_square(arg,n_arg,ss,se,saved_char) +#define _cimg_mp_check_list(is_out) check_list(is_out,ss,se,saved_char) +#define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp) +#define _cimg_mp_return(x) { *se = saved_char; s_op = previous_s_op; ss_op = previous_ss_op; return x; } +#define _cimg_mp_return_nan() _cimg_mp_return(_cimg_mp_slot_nan) +#define _cimg_mp_constant(val) _cimg_mp_return(constant((double)(val))) +#define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op)) +#define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1)) +#define _cimg_mp_scalar2(op,i1,i2) _cimg_mp_return(scalar2(op,i1,i2)) +#define _cimg_mp_scalar3(op,i1,i2,i3) _cimg_mp_return(scalar3(op,i1,i2,i3)) +#define _cimg_mp_scalar4(op,i1,i2,i3,i4) _cimg_mp_return(scalar4(op,i1,i2,i3,i4)) +#define _cimg_mp_scalar5(op,i1,i2,i3,i4,i5) _cimg_mp_return(scalar5(op,i1,i2,i3,i4,i5)) +#define _cimg_mp_scalar6(op,i1,i2,i3,i4,i5,i6) _cimg_mp_return(scalar6(op,i1,i2,i3,i4,i5,i6)) +#define _cimg_mp_scalar7(op,i1,i2,i3,i4,i5,i6,i7) _cimg_mp_return(scalar7(op,i1,i2,i3,i4,i5,i6,i7)) +#define _cimg_mp_vector1_v(op,i1) _cimg_mp_return(vector1_v(op,i1)) +#define _cimg_mp_vector2_sv(op,i1,i2) _cimg_mp_return(vector2_sv(op,i1,i2)) +#define _cimg_mp_vector2_vs(op,i1,i2) _cimg_mp_return(vector2_vs(op,i1,i2)) +#define _cimg_mp_vector2_vv(op,i1,i2) _cimg_mp_return(vector2_vv(op,i1,i2)) +#define _cimg_mp_vector3_vss(op,i1,i2,i3) _cimg_mp_return(vector3_vss(op,i1,i2,i3)) +#define _cimg_mp_strerr \ + *se = saved_char; \ + for (s0 = ss; s0>expr._data && *s0!=';'; --s0) {} \ + if (*s0==';') ++s0; \ + while (cimg::is_blank(*s0)) ++s0; \ + cimg::strellipsize(s0,64) + + // Constructors / Destructors. + ~_cimg_math_parser() { + cimg::srand(rng); + } + + _cimg_math_parser(const char *const expression, const char *const funcname=0, + const CImg& img_input=CImg::const_empty(), CImg *const img_output=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0, + const bool _is_fill=false): + code(_code),code_begin_t(_code_begin_t),code_end_t(_code_end_t), + p_break((CImg*)(cimg_ulong)-2), + imgin(img_input),listin(list_inputs?*list_inputs:CImgList::const_empty()), + imgout(img_output?*img_output:CImg::empty()),listout(list_outputs?*list_outputs:CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),list_norm(_list_norm),user_macro(0), + mem_img_median(~0U),mem_img_norm(~0U),mem_img_index(~0U),debug_indent(0),result_dim(0),break_type(0), + constcache_size(0),is_parallelizable(true),is_fill(_is_fill),need_input_copy(false), + rng((cimg::_rand(),cimg::rng())),calling_function(funcname?funcname:"cimg_math_parser") { + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + if (!expression || !*expression) + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Empty expression.", + pixel_type(),_cimg_mp_calling_function); + const char *_expression = expression; + while (*_expression && (cimg::is_blank(*_expression) || *_expression==';')) ++_expression; + CImg::string(_expression).move_to(expr); + char *ps = &expr.back() - 1; + while (ps>expr._data && (cimg::is_blank(*ps) || *ps==';')) --ps; + *(++ps) = 0; expr._width = (unsigned int)(ps - expr._data + 1); + + // Ease the retrieval of previous non-space characters afterwards. + pexpr.assign(expr._width); + char c, *pe = pexpr._data; + for (ps = expr._data, c = ' '; *ps; ++ps) { + if (!cimg::is_blank(*ps)) c = *ps; else *ps = ' '; + *(pe++) = c; + } + *pe = 0; + level = get_level(expr); + + // Init constant values. +#define _cimg_mp_interpolation (reserved_label[30]!=~0U?reserved_label[30]:0) +#define _cimg_mp_boundary (reserved_label[31]!=~0U?reserved_label[31]:0) +#define _cimg_mp_slot_t 17 +#define _cimg_mp_slot_nan 29 +#define _cimg_mp_slot_x 30 +#define _cimg_mp_slot_y 31 +#define _cimg_mp_slot_z 32 +#define _cimg_mp_slot_c 33 + + mem.assign(96); + for (unsigned int i = 0; i<=10; ++i) mem[i] = (double)i; // mem[0-10] = 0...10 + for (unsigned int i = 1; i<=5; ++i) mem[i + 10] = -(double)i; // mem[11-15] = -1...-5 + mem[16] = 0.5; + mem[_cimg_mp_slot_t] = 0; // thread_id + mem[18] = (double)imgin._width; // w + mem[19] = (double)imgin._height; // h + mem[20] = (double)imgin._depth; // d + mem[21] = (double)imgin._spectrum; // s + mem[22] = (double)imgin._is_shared; // r + mem[23] = (double)imgin._width*imgin._height; // wh + mem[24] = (double)imgin._width*imgin._height*imgin._depth; // whd + mem[25] = (double)imgin._width*imgin._height*imgin._depth*imgin._spectrum; // whds + mem[26] = (double)listin._width; // l + mem[27] = std::exp(1.); // e + mem[28] = cimg::PI; // pi + mem[_cimg_mp_slot_nan] = cimg::type::nan(); // nan + + // Set value property : + // { -1 = reserved (e.g. variable) | 0 = computation value | + // 1 = compile-time constant | N>1 = constant ptr to vector[N-1] }. + memtype.assign(mem._width,1,1,1,0); + for (unsigned int i = 0; i<_cimg_mp_slot_x; ++i) memtype[i] = 1; + memtype[_cimg_mp_slot_t] = memtype[_cimg_mp_slot_x] = memtype[_cimg_mp_slot_y] = + memtype[_cimg_mp_slot_z] = memtype[_cimg_mp_slot_c] = -1; + mempos = _cimg_mp_slot_c + 1; + variable_pos.assign(8); + + reserved_label.assign(128,1,1,1,~0U); + // reserved_label[0-31] are used to store the memory index of these variables: + // [0] = wh, [1] = whd, [2] = whds, [3] = pi, [4] = im, [5] = iM, [6] = ia, [7] = iv, + // [8] = is, [9] = ip, [10] = ic, [11] = in, [12] = xm, [13] = ym, [14] = zm, [15] = cm, [16] = xM, + // [17] = yM, [18] = zM, [19] = cM, [20] = i0...[29] = i9, [30] = interpolation, [31] = boundary + + // Compile expression into a sequence of opcodes. + s_op = ""; ss_op = expr._data; + const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0,false); + if (!_cimg_mp_is_constant(ind_result)) { + if (_cimg_mp_is_vector(ind_result)) + CImg(&mem[ind_result] + 1,_cimg_mp_size(ind_result),1,1,1,true). + fill(cimg::type::nan()); + else if (ind_result!=_cimg_mp_slot_t) mem[ind_result] = cimg::type::nan(); + } + + // Free resources used for compiling expression and prepare evaluation. + result_dim = _cimg_mp_size(ind_result); + if (mem._width>=256 && mem._width - mempos>=mem._width/2) mem.resize(mempos,1,1,1,-1); + result = mem._data + ind_result; + memtype.assign(); + constcache_vals.assign(); + constcache_inds.assign(); + level.assign(); + variable_pos.assign(); + reserved_label.assign(); + expr.assign(); + pexpr.assign(); + opcode.assign(); + opcode._is_shared = true; + + // Execute begin() bloc if any specified. + if (code_begin) { + mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_begin.end(); + for (p_code = code_begin; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + p_code_end = code.end(); + } + + _cimg_math_parser(): + code(_code),code_begin_t(_code_begin_t),code_end_t(_code_end_t), + p_code_end(0),p_break((CImg*)(cimg_ulong)-2), + imgin(CImg::const_empty()),listin(CImgList::const_empty()), + imgout(CImg::empty()),listout(CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),list_norm(_list_norm),debug_indent(0), + result_dim(0),break_type(0),constcache_size(0),is_parallelizable(true),is_fill(false), + need_input_copy(false),rng(0),calling_function(0) { + mem.assign(1 + _cimg_mp_slot_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()() + result = mem._data; + } + + _cimg_math_parser(const _cimg_math_parser& mp): + mem(mp.mem),code(mp.code),code_begin_t(mp.code_begin_t),code_end_t(mp.code_end_t), + p_code_end(mp.p_code_end),p_break(mp.p_break), + imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout), + img_stats(mp.img_stats),list_stats(mp.list_stats),list_median(mp.list_median),list_norm(mp.list_norm), + debug_indent(0),result_dim(mp.result_dim),break_type(0),constcache_size(0), + is_parallelizable(mp.is_parallelizable),is_fill(mp.is_fill), + need_input_copy(mp.need_input_copy),result(mem._data + (mp.result - mp.mem._data)), + rng((cimg::_rand(),cimg::rng())),calling_function(0) { + +#if cimg_use_openmp!=0 + mem[_cimg_mp_slot_t] = omp_get_thread_num(); + rng+=omp_get_thread_num(); +#endif + opcode.assign(); + opcode._is_shared = true; + } + + // Compilation procedure. + unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *const p_ref, + const bool is_critical) { + if (depth>256) { + cimg::strellipsize(expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Call stack overflow (infinite recursion?), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + (ss - 4)>expr._data?"...":"", + (ss - 4)>expr._data?ss - 4:expr._data, + se<&expr.back()?"...":""); + } + char c1, c2; + + // Simplify expression when possible. + do { + c2 = 0; + if (ssss && (cimg::is_blank(c1 = *(se - 1)) || c1==';')) --se; + } + while (*ss=='(' && *(se - 1)==')' && std::strchr(ss,')')==se - 1) { + ++ss; --se; c2 = 1; + } + } while (c2 && ss::%s: %s%s Missing %s, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + *s_op=='F'?"argument":"item", + (ss_op - 4)>expr._data?"...":"", + (ss_op - 4)>expr._data?ss_op - 4:expr._data, + ss_op + std::strlen(ss_op)<&expr.back()?"...":""); + } + + static const size_t siz_ref = 7*sizeof(unsigned int); + const char *const previous_s_op = s_op, *const previous_ss_op = ss_op; + const unsigned int depth1 = depth + 1; + unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6; + char + *const se1 = se - 1, *const se2 = se - 2, *const se3 = se - 3, + *const ss1 = ss + 1, *const ss2 = ss + 2, *const ss3 = ss + 3, *const ss4 = ss + 4, + *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8, + *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0; + double val = 0, val1, val2; + mp_func op; + return_new_comp = false; + + // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value + // linked to the returned memory slot (reference that cannot be determined at compile time). + // p_ref[0] can be { 0 = scalar (unlinked) | 1 = vector value | 2 = image value (offset) | + // 3 = image value (coordinates) | 4 = image value as a vector (offsets) | + // 5 = image value as a vector (coordinates) }. + // Depending on p_ref[0], the remaining p_ref[k] have the following meaning: + // When p_ref[0]==0, p_ref is actually unlinked. + // When p_ref[0]==1, p_ref = [ 1, vector_ind, offset ]. + // When p_ref[0]==2, p_ref = [ 2, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==3, p_ref = [ 3, image_ind (or ~0U), is_relative, x, y, z, c ]. + // When p_ref[0]==4, p_ref = [ 4, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==5, p_ref = [ 5, image_ind (or ~0U), is_relative, x, y, z ]. + if (p_ref) { *p_ref = 0; p_ref[1] = p_ref[2] = p_ref[3] = p_ref[4] = p_ref[5] = p_ref[6] = ~0U; } + + const char saved_char = *se; *se = 0; + const unsigned int clevel = level[ss - expr._data], clevel1 = clevel + 1; + bool is_sth, is_relative; + CImg ref; + CImg variable_name; + CImgList l_opcode; + + // Look for a single value or a pre-defined variable. + int nb = 0; + s = ss + (*ss=='+' || *ss=='-'?1:0); + if (*s=='i' || *s=='I' || *s=='n' || *s=='N') { // Particular cases : +/-NaN and +/-Inf + is_sth = *ss=='-'; + if (!cimg::strcasecmp(s,"inf")) { val = cimg::type::inf(); nb = 1; } + else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type::nan(); nb = 1; } + if (nb==1 && is_sth) val = -val; + } else if (*s=='0' && (s[1]=='x' || s[1]=='X')) { // Hexadecimal number + is_sth = *ss=='-'; + if (cimg_sscanf(s + 2,"%x%c",&arg1,&sep)==1) { + nb = 1; + val = (double)arg1; + if (is_sth) val = -val; + } + } + if (!nb) nb = cimg_sscanf(ss,"%lf%c%c",&val,&(sep=0),&(end=0)); + if (nb==1) _cimg_mp_constant(val); + if (nb==2 && sep=='%') _cimg_mp_constant(val/100); + + if (ss1==se) switch (*ss) { // One-char reserved variable + case 'c' : _cimg_mp_return(reserved_label[(int)'c']!=~0U?reserved_label[(int)'c']:_cimg_mp_slot_c); + case 'd' : _cimg_mp_return(reserved_label[(int)'d']!=~0U?reserved_label[(int)'d']:20); + case 'e' : _cimg_mp_return(reserved_label[(int)'e']!=~0U?reserved_label[(int)'e']:27); + case 'h' : _cimg_mp_return(reserved_label[(int)'h']!=~0U?reserved_label[(int)'h']:19); + case 'k' : + if (reserved_label[(int)'k']!=~0U) _cimg_mp_return(reserved_label[(int)'k']); + pos = get_mem_img_index(); + if (pos!=~0U) _cimg_mp_return(pos); + _cimg_mp_return_nan(); + case 'l' : _cimg_mp_return(reserved_label[(int)'l']!=~0U?reserved_label[(int)'l']:26); + case 'r' : _cimg_mp_return(reserved_label[(int)'r']!=~0U?reserved_label[(int)'r']:22); + case 's' : _cimg_mp_return(reserved_label[(int)'s']!=~0U?reserved_label[(int)'s']:21); + case 't' : _cimg_mp_return(reserved_label[(int)'t']!=~0U?reserved_label[(int)'t']:_cimg_mp_slot_t); + case 'w' : _cimg_mp_return(reserved_label[(int)'w']!=~0U?reserved_label[(int)'w']:18); + case 'x' : _cimg_mp_return(reserved_label[(int)'x']!=~0U?reserved_label[(int)'x']:_cimg_mp_slot_x); + case 'y' : _cimg_mp_return(reserved_label[(int)'y']!=~0U?reserved_label[(int)'y']:_cimg_mp_slot_y); + case 'z' : _cimg_mp_return(reserved_label[(int)'z']!=~0U?reserved_label[(int)'z']:_cimg_mp_slot_z); + case 'u' : + if (reserved_label[(int)'u']!=~0U) _cimg_mp_return(reserved_label[(int)'u']); + _cimg_mp_scalar2(mp_u,0,1); + case 'g' : + if (reserved_label[(int)'g']!=~0U) _cimg_mp_return(reserved_label[(int)'g']); + _cimg_mp_scalar0(mp_g); + case 'i' : + if (reserved_label[(int)'i']!=~0U) _cimg_mp_return(reserved_label[(int)'i']); + _cimg_mp_scalar0(mp_i); + case 'I' : + _cimg_mp_op("Variable 'I'"); + if (reserved_label[(int)'I']!=~0U) _cimg_mp_return(reserved_label[(int)'I']); + if (!imgin._spectrum) _cimg_mp_return(0); + need_input_copy = true; + pos = vector(imgin._spectrum); + CImg::vector((ulongT)mp_Joff,pos,0,0,imgin._spectrum).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + case 'R' : + if (reserved_label[(int)'R']!=~0U) _cimg_mp_return(reserved_label[(int)'R']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0,0,0); + case 'G' : + if (reserved_label[(int)'G']!=~0U) _cimg_mp_return(reserved_label[(int)'G']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1,0,0); + case 'B' : + if (reserved_label[(int)'B']!=~0U) _cimg_mp_return(reserved_label[(int)'B']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2,0,0); + case 'A' : + if (reserved_label[(int)'A']!=~0U) _cimg_mp_return(reserved_label[(int)'A']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3,0,0); + } + else if (ss2==se) { // Two-chars reserved variable + arg1 = arg2 = ~0U; + if (*ss=='w' && *ss1=='h') // wh + _cimg_mp_return(reserved_label[0]!=~0U?reserved_label[0]:23); + if (*ss=='p' && *ss1=='i') // pi + _cimg_mp_return(reserved_label[3]!=~0U?reserved_label[3]:28); + if (*ss=='i') { + if (*ss1>='0' && *ss1<='9') { // i0...i9 + pos = 20 + *ss1 - '0'; + if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,pos - 20,0,0); + } + switch (*ss1) { + case 'm' : arg1 = 4; arg2 = 0; break; // im + case 'M' : arg1 = 5; arg2 = 1; break; // iM + case 'a' : arg1 = 6; arg2 = 2; break; // ia + case 'v' : arg1 = 7; arg2 = 3; break; // iv + case 's' : arg1 = 8; arg2 = 12; break; // is + case 'p' : arg1 = 9; arg2 = 13; break; // ip + case 'c' : // ic + if (reserved_label[10]!=~0U) _cimg_mp_return(reserved_label[10]); + if (mem_img_median==~0U) mem_img_median = imgin?constant(imgin.median()):0; + _cimg_mp_return(mem_img_median); + break; + case 'n' : // in + if (reserved_label[11]!=~0U) _cimg_mp_return(reserved_label[11]); + if (mem_img_norm==~0U) mem_img_norm = imgin?constant(imgin.magnitude()):0; + _cimg_mp_return(mem_img_norm); + } + } + else if (*ss1=='m') switch (*ss) { + case 'x' : arg1 = 12; arg2 = 4; break; // xm + case 'y' : arg1 = 13; arg2 = 5; break; // ym + case 'z' : arg1 = 14; arg2 = 6; break; // zm + case 'c' : arg1 = 15; arg2 = 7; break; // cm + } + else if (*ss1=='M') switch (*ss) { + case 'x' : arg1 = 16; arg2 = 8; break; // xM + case 'y' : arg1 = 17; arg2 = 9; break; // yM + case 'z' : arg1 = 18; arg2 = 10; break; // zM + case 'c' : arg1 = 19; arg2 = 11; break; // cM + } + if (arg1!=~0U) { + if (reserved_label[arg1]!=~0U) _cimg_mp_return(reserved_label[arg1]); + if (!img_stats) { + img_stats.assign(1,14,1,1,0).fill(imgin.get_stats(),false); + mem_img_stats.assign(1,14,1,1,~0U); + } + if (mem_img_stats[arg2]==~0U) mem_img_stats[arg2] = constant(img_stats[arg2]); + _cimg_mp_return(mem_img_stats[arg2]); + } + } else if (ss3==se) { // Three-chars reserved variable + if (*ss=='w' && *ss1=='h' && *ss2=='d') // whd + _cimg_mp_return(reserved_label[1]!=~0U?reserved_label[1]:24); + } else if (ss4==se) { // Four-chars reserved variable + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='s') // whds + _cimg_mp_return(reserved_label[2]!=~0U?reserved_label[2]:25); + } + + pos = ~0U; + is_sth = false; + for (s0 = ss, s = ss1; s='i'?1:3,0); + if (_cimg_mp_is_vector(arg2)) { + if (p1!=~0U) { + _cimg_mp_check_constant_index(p1); + p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + p2 = listin[p3]._spectrum; + } else p2 = imgin._spectrum; + if (!p2) _cimg_mp_return(0); + _cimg_mp_check_type(arg2,2,2,p2); + } else p2 = 0; + + if (p_ref) { + *p_ref = _cimg_mp_is_vector(arg2)?4:2; + p_ref[1] = p1; + p_ref[2] = (unsigned int)is_relative; + p_ref[3] = arg1; + if (_cimg_mp_is_vector(arg2)) + set_reserved_vector(arg2); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; + if (_cimg_mp_is_comp(arg1)) memtype[arg1] = -1; + } + + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg1,_cimg_mp_size(arg2)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg1,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value + if (!is_critical) is_parallelizable = false; + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0='i'?1:3,0); + if (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + } else if (s1='i') + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg5,p1,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg5,p1,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg5,p1,arg1,arg2,arg3,_cimg_mp_size(arg5)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg5); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg5,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg5,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg5,arg1,arg2,arg3,_cimg_mp_size(arg5)).move_to(code); + } + _cimg_mp_return(arg5); + } + } + + // Assign vector value (direct). + if (l_variable_name>3 && *ve1==']' && *ss!='[') { + s0 = ve1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss && is_varname(ss,s0 - ss)) { + variable_name[s0 - ss] = 0; // Remove brackets in variable name + get_variable_pos(variable_name,arg1,arg2); + arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U; // Vector slot + if (arg1==~0U || _cimg_mp_is_scalar(arg1)) + compile(ss,s0,depth1,0,is_critical); // Variable does not exist or is not a vector -> error + + arg2 = compile(++s0,ve1,depth1,0,is_critical); // Index + arg3 = compile(s + 1,se,depth1,0,is_critical); // Value to assign + _cimg_mp_check_type(arg3,2,1,0); + + if (_cimg_mp_is_constant(arg2)) { // Constant index -> return corresponding variable slot directly + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_size(arg1)) { + arg1+=nb + 1; + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + _cimg_mp_return(arg1); + } + compile(ss,s,depth1,0,is_critical); // Out-of-bounds reference -> error + } + + // Case of non-constant index -> return assigned value + linked reference + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -1; // Prevent from being used in further optimization + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; + } + CImg::vector((ulongT)mp_vector_set_off,arg3,arg1,(ulongT)_cimg_mp_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg3); + } + } + + // Assign user-defined macro. + if (l_variable_name>2 && *ve1==')' && *ss!='(') { + s0 = ve1; while (s0>ss && *s0!='(') --s0; + if (is_varname(ss,s0 - ss) && std::strncmp(variable_name,"debug(",6) && + std::strncmp(variable_name,"print(",6)) { // Valid macro name + s0 = variable_name._data + (s0 - ss); + *s0 = 0; + s1 = variable_name._data + l_variable_name - 1; // Pointer to closing parenthesis + CImg(variable_name._data,(unsigned int)(s0 - variable_name._data + 1)).move_to(macro_def,0); + ++s; while (*s && cimg::is_blank(*s)) ++s; + CImg(s,(unsigned int)(se - s + 1)).move_to(macro_body,0); + + p1 = 1; // Index of current parsed argument + for (s = s0 + 1; s<=s1; ++p1, s = ns + 1) { // Parse function arguments + if (p1>24) { + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Too much specified arguments (>24) in macro " + "definition '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && p1==1) break; // Function has no arguments + + s2 = s; // Start of the argument name + is_sth = true; // is_valid_argument_name? + if (*s>='0' && *s<='9') is_sth = false; + else for (ns = s; ns::%s: %s: %s name specified for argument %u when defining " + "macro '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + is_sth?"Empty":"Invalid",p1, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (ns==s1 || *ns==',') { // New argument found + *s3 = 0; + p2 = (unsigned int)(s3 - s2); // Argument length + for (ps = std::strstr(macro_body[0],s2); ps; ps = std::strstr(ps,s2)) { // Replace by arg number + if (!((ps>macro_body[0]._data && is_varchar(*(ps - 1))) || + (ps + p2macro_body[0]._data && *(ps - 1)=='#') { // Remove pre-number sign + *(ps - 1) = (char)p1; + if (ps + p26 && !std::strncmp(variable_name,"const ",6); + s0 = variable_name._data; + if (is_const) { + s0+=6; while (cimg::is_blank(*s0)) ++s0; + variable_name.resize(variable_name.end() - s0,1,1,1,0,0,1); + } + if (is_varname(variable_name)) { // Valid variable name + + // Assign variable (direct). + get_variable_pos(variable_name,arg1,arg2); + arg3 = compile(s + 1,se,depth1,0,is_critical); + is_sth = return_new_comp; // is arg3 a new blank object? + if (is_const) _cimg_mp_check_constant(arg3,2,0); + arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U; + + if (arg1==~0U) { // Create new variable + if (_cimg_mp_is_vector(arg3)) { // Vector variable + arg1 = is_sth || is_comp_vector(arg3)?arg3:vector_copy(arg3); + set_reserved_vector(arg1); // Prevent from being used in further optimization + } else { // Scalar variable + if (is_const) arg1 = arg3; + else { + arg1 = is_sth || _cimg_mp_is_comp(arg3)?arg3:scalar1(mp_copy,arg3); + memtype[arg1] = -1; + } + } + + if (arg2!=~0U) reserved_label[arg2] = arg1; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg1; + variable_name.move_to(variable_def); + } + + } else { // Variable already exists -> assign a new value + if (is_const || _cimg_mp_is_constant(arg1)) { + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid assignment of %sconst variable '%s'%s, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"already-defined ":"non-", + variable_name._data, + !_cimg_mp_is_constant(arg1) && is_const?" as a new const variable":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(arg3,2,_cimg_mp_is_vector(arg1)?3:1,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1)) { // Vector + if (_cimg_mp_is_vector(arg3)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg3,(ulongT)_cimg_mp_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_size(arg1),arg3). + move_to(code); + } else // Scalar + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + } + return_new_comp = false; + _cimg_mp_return(arg1); + } + + // Assign lvalue (variable name was not valid for a direct assignment). + arg1 = ~0U; + is_sth = (bool)std::strchr(variable_name,'?'); // Contains_ternary_operator? + if (is_sth) break; // Do nothing and make ternary operator prioritary over assignment + + if (l_variable_name>2 && (std::strchr(variable_name,'(') || std::strchr(variable_name,'['))) { + ref.assign(7); + arg1 = compile(ss,s,depth1,ref,is_critical); // Lvalue slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Value to assign + + if (*ref==1) { // Vector value (scalar): V[k] = scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)mp_vector_set_off,arg2,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(arg2); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg3).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg2,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg2,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg3).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg3,_cimg_mp_size(arg2)).move_to(code); + } + + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg3,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg2,p1,arg3,arg4,arg5).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg2,p1,arg3,arg4,arg5,_cimg_mp_size(arg2)).move_to(code); + } + + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg2,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg2,arg3,arg4,arg5,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg2)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s = scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)mp_copy,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + } + + // No assignment expressions match -> error + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1!=~0U && _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Apply unary/binary/ternary operators. The operator precedences should be the same as in C++. + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps && + level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=) + _cimg_mp_op(*ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='"); + + ref.assign(7); + arg1 = compile(ss,ns,depth1,ref,is_critical); // Vector slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Right operand + _cimg_mp_check_type(arg1,1,2,2); + _cimg_mp_check_type(arg2,2,3,2); + if (_cimg_mp_is_vector(arg2)) { // Complex **= complex + if (*ps=='*') + CImg::vector((ulongT)mp_complex_mul,arg1,arg1,arg2).move_to(code); + else if (*ps=='/') + CImg::vector((ulongT)mp_complex_div_vv,arg1,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code); + } else { // Complex **= scalar + if (*ps=='*') { + if (arg2==1) _cimg_mp_return(arg1); + self_vector_s(arg1,mp_self_mul,arg2); + } else if (*ps=='/') { + if (arg2==1) _cimg_mp_return(arg1); + self_vector_s(arg1,mp_self_div,arg2); + } else { + if (arg2==1) _cimg_mp_return(arg1); + CImg::vector((ulongT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code); + } + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + + } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + + _cimg_mp_return(arg1); + } + + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='+' || *ps=='-' || *ps=='*' || *ps=='/' || *ps=='%' || + *ps=='&' || *ps=='^' || *ps=='|' || + (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) && + level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=) + switch (*ps) { + case '+' : op = mp_self_add; _cimg_mp_op("Operator '+='"); break; + case '-' : op = mp_self_sub; _cimg_mp_op("Operator '-='"); break; + case '*' : op = mp_self_mul; _cimg_mp_op("Operator '*='"); break; + case '/' : op = mp_self_div; _cimg_mp_op("Operator '/='"); break; + case '%' : op = mp_self_modulo; _cimg_mp_op("Operator '%='"); break; + case '<' : op = mp_self_bitwise_left_shift; _cimg_mp_op("Operator '<<='"); break; + case '>' : op = mp_self_bitwise_right_shift; _cimg_mp_op("Operator '>>='"); break; + case '&' : op = mp_self_bitwise_and; _cimg_mp_op("Operator '&='"); break; + case '|' : op = mp_self_bitwise_or; _cimg_mp_op("Operator '|='"); break; + default : op = mp_self_pow; _cimg_mp_op("Operator '^='"); break; + } + s1 = *ps=='>' || *ps=='<'?ns:ps; + + ref.assign(7); + arg1 = compile(ss,s1,depth1,ref,is_critical); // Variable slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Value to apply + + // Check for particular case to be simplified. + if ((op==mp_self_add || op==mp_self_sub) && !arg2) _cimg_mp_return(arg1); + if ((op==mp_self_mul || op==mp_self_div) && arg2==1) _cimg_mp_return(arg1); + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_reserved(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k] += scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(arg1); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) += value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg2)) self_vector_v(arg1,op,arg2); // Vector += vector + else self_vector_s(arg1,op,arg2); // Vector += scalar + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s += scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + + variable_name.assign(ss,(unsigned int)(s - ss)).back() = 0; + cimg::strpare(variable_name,false,true); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + for (s = ss1; s::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||') + _cimg_mp_op("Operator '||'"); + arg1 = compile(ss,s,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,1,0); + if (arg1>0 && arg1<=16) _cimg_mp_return(1); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] || mem[arg2]); + if (!arg1) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_or,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&') + _cimg_mp_op("Operator '&&'"); + arg1 = compile(ss,s,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,1,0); + if (!arg1) _cimg_mp_return(0); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] && mem[arg2]); + if (arg1>0 && arg1<=16) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_and,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|') + _cimg_mp_op("Operator '|'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1] | (longT)mem[arg2]); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_scalar2(mp_bitwise_or,arg1,arg2); + } + + for (s = se2; s>ss; --s) + if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&') + _cimg_mp_op("Operator '&'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1] & (longT)mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_bitwise_and,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=') + _cimg_mp_op("Operator '!='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + if (arg1==arg2) _cimg_mp_return(0); + p1 = _cimg_mp_size(arg1); + p2 = _cimg_mp_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(1); + pos = scalar(); + CImg::vector((ulongT)mp_vector_neq,pos,arg1,p1,arg2,p2,11,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]!=mem[arg2]); + _cimg_mp_scalar2(mp_neq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==') + _cimg_mp_op("Operator '=='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + if (arg1==arg2) _cimg_mp_return(1); + p1 = _cimg_mp_size(arg1); + p2 = _cimg_mp_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_vector_eq,pos,arg1,p1,arg2,p2,11,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]==mem[arg2]); + _cimg_mp_scalar2(mp_eq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=') + _cimg_mp_op("Operator '<='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]<=mem[arg2]); + if (arg1==arg2) _cimg_mp_return(1); + _cimg_mp_scalar2(mp_lte,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=') + _cimg_mp_op("Operator '>='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>=mem[arg2]); + if (arg1==arg2) _cimg_mp_return(1); + _cimg_mp_scalar2(mp_gte,arg1,arg2); + } + + for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) + if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<') + _cimg_mp_op("Operator '<'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]ss; --s, --ns, --ps) + if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greater than ('>') + _cimg_mp_op("Operator '>'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>mem[arg2]); + if (arg1==arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_gt,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<') + _cimg_mp_op("Operator '<<'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_left_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]<<(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_left_shift,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>') + _cimg_mp_op("Operator '>>'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_right_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]>>(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_right_shift,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='+' && (*ns!='+' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Addition ('+') + _cimg_mp_op("Operator '+'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] + mem[arg2]); + if (code) { // Try to spot linear case 'a*b + c' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_linear_add,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_increment,arg1); + if (arg1==1) _cimg_mp_scalar1(mp_increment,arg2); + _cimg_mp_scalar2(mp_add,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='-' && (*ns!='-' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Subtraction ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_vector1_v(mp_minus,arg2); + _cimg_mp_vector2_sv(mp_sub,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] - mem[arg2]); + if (!arg1) _cimg_mp_scalar1(mp_minus,arg2); + if (code) { // Try to spot linear cases 'a*b - c' and 'c - a*b' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)(arg3==arg1?mp_linear_sub_left:mp_linear_sub_right), + arg3,arg4,arg5,arg3==arg1?arg2:arg1).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_decrement,arg1); + _cimg_mp_scalar2(mp_sub,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex multiplication ('**') + _cimg_mp_op("Operator '**'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_mul,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//') + _cimg_mp_op("Operator '//'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_vv,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_sv,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*') + _cimg_mp_op("Operator '*'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + p2 = _cimg_mp_size(arg2); + if (p2>0 && (ulongT)_cimg_mp_size(arg1)==(ulongT)p2*p2) { // Particular case of matrix multiplication + pos = vector(p2); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,p2,p2,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + + if (code) { // Try to spot double multiplication 'a*b*c' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_mul2,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/') + _cimg_mp_op("Operator '/'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2, ns = se1; s>ss; --s, --ns) + if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%') + _cimg_mp_op("Operator '%'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(cimg::mod(mem[arg1],mem[arg2])); + _cimg_mp_scalar2(mp_modulo,arg1,arg2); + } + + if (se1>ss) { + if (*ss=='+' && (*ss1!='+' || (ss2='0' && *ss2<='9'))) { // Unary plus ('+') + _cimg_mp_op("Operator '+'"); + _cimg_mp_return(compile(ss1,se,depth1,0,is_critical)); + } + + if (*ss=='-' && (*ss1!='-' || (ss2='0' && *ss2<='9'))) { // Unary minus ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]); + _cimg_mp_scalar1(mp_minus,arg1); + } + + if (*ss=='!') { // Logical not ('!') + _cimg_mp_op("Operator '!'"); + if (*ss1=='!') { // '!!expr' optimized as 'bool(expr)' + arg1 = compile(ss2,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((bool)mem[arg1]); + _cimg_mp_scalar1(mp_bool,arg1); + } + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]); + _cimg_mp_scalar1(mp_logical_not,arg1); + } + + if (*ss=='~') { // Bitwise not ('~') + _cimg_mp_op("Operator '~'"); + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned int)mem[arg1]); + _cimg_mp_scalar1(mp_bitwise_not,arg1); + } + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^') + _cimg_mp_op("Operator '^^'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + pos = vector(2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + CImg::vector((ulongT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code); + else if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)mp_complex_pow_vs,pos,arg1,arg2).move_to(code); + else if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + CImg::vector((ulongT)mp_complex_pow_sv,pos,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_ss,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^') + _cimg_mp_op("Operator '^'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(std::pow(mem[arg1],mem[arg2])); + switch (arg2) { + case 0 : _cimg_mp_return(1); + case 2 : _cimg_mp_scalar1(mp_sqr,arg1); + case 3 : _cimg_mp_scalar1(mp_pow3,arg1); + case 4 : _cimg_mp_scalar1(mp_pow4,arg1); + default : + if (_cimg_mp_is_constant(arg2)) { + if (mem[arg2]==0.5) { _cimg_mp_scalar1(mp_sqrt,arg1); } + else if (mem[arg2]==0.25) { _cimg_mp_scalar1(mp_pow0_25,arg1); } + } + _cimg_mp_scalar2(mp_pow,arg1,arg2); + } + } + + // Percentage computation. + if (*se1=='%') { + arg1 = compile(ss,se1,depth1,0,is_critical); + arg2 = _cimg_mp_is_constant(arg1)?0:constant(100); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(mem[arg1]/100); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + is_sth = ss1ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment + if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) { + _cimg_mp_op("Operator '++'"); + op = mp_self_increment; + } else { + _cimg_mp_op("Operator '--'"); + op = mp_self_decrement; + } + ref.assign(7); + arg1 = is_sth?compile(ss2,se,depth1,ref,is_critical): + compile(ss,se2,depth1,ref,is_critical); // Variable slot + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_reserved(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (is_sth) pos = arg1; // Determine return index, depending on pre/post action + else { + if (_cimg_mp_is_vector(arg1)) pos = vector_copy(arg1); + else pos = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k]++ + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,1).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(pos); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off]++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++ + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s++ + CImg::vector((ulongT)op,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (is_sth) variable_name.assign(ss2,(unsigned int)(se - ss1)); + else variable_name.assign(ss,(unsigned int)(se1 - ss)); + variable_name.back() = 0; + cimg::strpare(variable_name,false,true); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Array-like access to vectors and image values 'i/j/I/J[_#ind,offset,_boundary]' and 'vector[offset]'. + if (*se1==']') { + _cimg_mp_op("Value accessor '[]'"); + + // Find opening bracket for the offset. + s0 = se1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { s1 = s0; do { --s1; } while (cimg::is_blank(*s1)); cimg::swap(*s0,*++s1); } + is_sth=s0>ss && *(s0-1)==']'; // Particular case s.a. '..[..][..]' ? + is_relative = *ss=='j' || *ss=='J'; + + if (!is_sth && (*ss=='I' || *ss=='J') && *ss1=='[' && + (reserved_label[(int)*ss]==~0U || + !_cimg_mp_is_vector(reserved_label[(int)*ss]))) { // Image value as a vector + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0::vector((ulongT)(is_relative?mp_list_Joff:mp_list_Ioff), + pos,p1,arg1,arg2==~0U?_cimg_mp_boundary:arg2,p2).move_to(code); + } else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Joff:mp_Ioff), + pos,arg1,arg2==~0U?_cimg_mp_boundary:arg2,p2).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!is_sth && (*ss=='i' || *ss=='j') && *ss1=='[' && + (reserved_label[(int)*ss]==~0U || + !_cimg_mp_is_vector(reserved_label[(int)*ss]))) { // Image value as a scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { // Vector element + arg1 = compile(ss,s0,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Array brackets used on non-vector variable '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + s1 = s0 + 1; while (s1 sub-vector extraction + p1 = _cimg_mp_size(arg1); + arg2 = compile(++s0,s1,depth1,0,is_critical); // Starting index + s0 = ++s1; while (s0::vector((ulongT)mp_vector_crop,pos,arg1,p1,arg2,arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // One argument -> vector value reference + arg2 = compile(++s0,se1,depth1,0,is_critical); + if (_cimg_mp_is_constant(arg2)) { // Constant index + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_size(arg1)) _cimg_mp_return(arg1 + 1 + nb); + variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Out-of-bounds reference '%s[%d]' " + "(vector '%s' has dimension %u), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data,nb, + variable_name._data,_cimg_mp_size(arg1), + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; // Prevent from being used in further optimization + } + pos = scalar3(mp_vector_off,arg1,_cimg_mp_size(arg1),arg2); + memtype[pos] = -1; // Prevent from being used in further optimization + _cimg_mp_return(pos); + } + } + + // Look for a function call, an access to image value, or a parenthesis. + if (*se1==')') { + if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref,is_critical)); // Simple parentheses + _cimg_mp_op("Value accessor '()'"); + is_relative = *ss=='j' || *ss=='J'; + s0 = s1 = std::strchr(ss,'('); if (s0) { do { --s1; } while (cimg::is_blank(*s1)); cimg::swap(*s0,*++s1); } + + // I/J(_#ind,_x,_y,_z,_interpolation,_boundary_conditions) + if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + if (s1::vector((ulongT)(is_relative?mp_list_Jxyz:mp_list_Ixyz), + pos,p1,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5,p2).move_to(code); + else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Jxyz:mp_Ixyz), + pos,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5,p2).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + // i/j(_#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions) + if ((*ss=='i' || *ss=='j') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + if (s1::vector((ulongT)(*ss3=='0'?mp_arg0:mp_arg),0,0,p2,arg1,arg2).move_to(l_opcode); + for (s = ++s2; s::vector(arg3).move_to(l_opcode); + ++p3; + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (_cimg_mp_is_constant(arg1)) { + p3-=1; // Number of args + if (*ss3=='0') arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1] + 1); + else arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1]); + if (arg1::vector((ulongT)mp_break,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"breakpoint(",11)) { // Break point (for abort test) + _cimg_mp_op("Function 'breakpoint()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_breakpoint,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"bool(",5)) { // Boolean cast + _cimg_mp_op("Function 'bool()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((bool)mem[arg1]); + _cimg_mp_scalar1(mp_bool,arg1); + } + + if (!std::strncmp(ss,"begin(",6)) { // Begin + _cimg_mp_op("Function 'begin()'"); + code.swap(code_begin); + arg1 = compile(ss6,se1,depth1,p_ref,true); + code.swap(code_begin); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"begin_t(",8)) { // Begin thread + _cimg_mp_op("Function 'begin_t()'"); + code.swap(code_begin_t); + arg1 = compile(ss8,se1,depth1,p_ref,true); + code.swap(code_begin_t); + _cimg_mp_return(arg1); + } + break; + + case 'c' : + if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value + _cimg_mp_op("Function 'cabs()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_scalar2(mp_complex_abs,arg1,0); + _cimg_mp_scalar2(mp_complex_abs,arg1 + 1,arg1 + 2); + } + + if (!std::strncmp(ss,"carg(",5)) { // Complex argument + _cimg_mp_op("Function 'carg()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_scalar2(mp_atan2,0,arg1); + _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1); + } + + if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root + _cimg_mp_op("Function 'cbrt()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::cbrt(mem[arg1])); + _cimg_mp_scalar1(mp_cbrt,arg1); + } + + if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate + _cimg_mp_op("Function 'cconj()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_conj,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_conj,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ceil(",5)) { // Ceil + _cimg_mp_op("Function 'ceil()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_ceil,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::ceil(mem[arg1])); + _cimg_mp_scalar1(mp_ceil,arg1); + } + + if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential + _cimg_mp_op("Function 'cexp()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_exp,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_exp,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm + _cimg_mp_op("Function 'clog()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_log,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_log,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ccos(",5)) { // Complex cosine + _cimg_mp_op("Function 'ccos()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_cos,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_cos,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"csin(",5)) { // Complex sine + _cimg_mp_op("Function 'csin()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_sin,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_sin,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ctan(",5)) { // Complex tangent + _cimg_mp_op("Function 'ctan()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_tan,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_tan,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ccosh(",6)) { // Complex hyperbolic cosine + _cimg_mp_op("Function 'ccosh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_cosh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_cosh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"csinh(",6)) { // Complex hyperbolic sine + _cimg_mp_op("Function 'csinh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_sinh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_sinh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ctanh(",6)) { // Complex hyperbolic tangent + _cimg_mp_op("Function 'ctanh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_tanh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_tanh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"continue(",9)) { // Continue loop + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_continue,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"copy(",5)) { // Memory copy + _cimg_mp_op("Function 'copy()'"); + ref.assign(14); + s1 = ss5; while (s1=4 && arg4==~0U) arg4 = scalar1(mp_image_whd,ref[1]); + } + if (_cimg_mp_is_vector(arg2)) { + if (arg3==~0U) arg3 = constant(_cimg_mp_size(arg2)); + if (!ref[7]) ++arg2; + if (ref[7]>=4 && arg5==~0U) arg5 = scalar1(mp_image_whd,ref[8]); + } + if (arg3==~0U) arg3 = 1; + if (arg4==~0U) arg4 = 1; + if (arg5==~0U) arg5 = 1; + _cimg_mp_check_type(arg3,3,1,0); + _cimg_mp_check_type(arg4,4,1,0); + _cimg_mp_check_type(arg5,5,1,0); + _cimg_mp_check_type(arg6,5,1,0); + CImg(1,22).move_to(code); + code.back().get_shared_rows(0,7).fill((ulongT)mp_memcopy,p1,arg1,arg2,arg3,arg4,arg5,arg6); + code.back().get_shared_rows(8,21).fill(ref); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"cos(",4)) { // Cosine + _cimg_mp_op("Function 'cos()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1])); + _cimg_mp_scalar1(mp_cos,arg1); + } + + if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine + _cimg_mp_op("Function 'cosh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1])); + _cimg_mp_scalar1(mp_cosh,arg1); + } + + if (!std::strncmp(ss,"critical(",9)) { // Critical section (single thread at a time) + _cimg_mp_op("Function 'critical()'"); + p1 = code._width; + arg1 = compile(ss + 9,se1,depth1,p_ref,true); + CImg::vector((ulongT)mp_critical,arg1,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"crop(",5)) { // Image crop + _cimg_mp_op("Function 'crop()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::sequence(_cimg_mp_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_size(arg1)); + opcode.resize(1,std::min(opcode._height,4U),1,1,0).move_to(l_opcode); + is_sth = true; + } else { + _cimg_mp_check_type(arg1,pos + 1,1,0); + CImg::vector(arg1).move_to(l_opcode); + } + s = ns; + } + (l_opcode>'y').move_to(opcode); + + arg1 = 0; arg2 = (p1!=~0U); + switch (opcode._height) { + case 0 : case 1 : + CImg::vector(0,0,0,0,~0U,~0U,~0U,~0U,0).move_to(opcode); + break; + case 2 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,_cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + 2; + break; + case 3 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,opcode[2]).move_to(opcode); + arg1 = arg2 + 2; + break; + case 4 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,_cimg_mp_boundary). + move_to(opcode); + arg1 = arg2 + (is_sth?2:3); + break; + case 5 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,opcode[4]). + move_to(opcode); + arg1 = arg2 + (is_sth?2:3); + break; + case 6 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + _cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + (is_sth?2:4); + break; + case 7 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + opcode[6]).move_to(opcode); + arg1 = arg2 + (is_sth?2:4); + break; + case 8 : + CImg::vector(*opcode,opcode[1],opcode[2],opcode[3],opcode[4],opcode[5],opcode[6], + opcode[7],_cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + (is_sth?2:5); + break; + case 9 : + arg1 = arg2 + (is_sth?2:5); + break; + default : // Error -> too much arguments + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Too much arguments specified, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + _cimg_mp_check_type((unsigned int)*opcode,arg2 + 1,1,0); + _cimg_mp_check_type((unsigned int)opcode[1],arg2 + 1 + (is_sth?0:1),1,0); + _cimg_mp_check_type((unsigned int)opcode[2],arg2 + 1 + (is_sth?0:2),1,0); + _cimg_mp_check_type((unsigned int)opcode[3],arg2 + 1 + (is_sth?0:3),1,0); + if (opcode[4]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[4],arg1,3); + opcode[4] = (ulongT)mem[opcode[4]]; + } + if (opcode[5]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[5],arg1 + 1,3); + opcode[5] = (ulongT)mem[opcode[5]]; + } + if (opcode[6]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[6],arg1 + 2,3); + opcode[6] = (ulongT)mem[opcode[6]]; + } + if (opcode[7]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[7],arg1 + 3,3); + opcode[7] = (ulongT)mem[opcode[7]]; + } + _cimg_mp_check_type((unsigned int)opcode[8],arg1 + 4,1,0); + + if (opcode[4]==(ulongT)~0U || opcode[5]==(ulongT)~0U || + opcode[6]==(ulongT)~0U || opcode[7]==(ulongT)~0U) { + p2 = 0; + if (p1!=~0U) { + _cimg_mp_check_constant(p1,1,1); + p2 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + } + const CImg &img = p1!=~0U?listin[p2]:imgin; + if (!img) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Cannot crop empty image when " + "some xyzc-coordinates are unspecified, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (opcode[4]==(ulongT)~0U) opcode[4] = (ulongT)img._width; + if (opcode[5]==(ulongT)~0U) opcode[5] = (ulongT)img._height; + if (opcode[6]==(ulongT)~0U) opcode[6] = (ulongT)img._depth; + if (opcode[7]==(ulongT)~0U) opcode[7] = (ulongT)img._spectrum; + } + + pos = vector((unsigned int)(opcode[4]*opcode[5]*opcode[6]*opcode[7])); + CImg::vector((ulongT)mp_crop, + pos,p1, + *opcode,opcode[1],opcode[2],opcode[3], + opcode[4],opcode[5],opcode[6],opcode[7], + opcode[8]).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cross(",6)) { // Cross product + _cimg_mp_op("Function 'cross()'"); + s1 = ss6; while (s1::vector((ulongT)mp_cross,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cut(",4)) { // Cut + _cimg_mp_op("Function 'cut()'"); + s1 = ss4; while (s1val2?val2:val); + } + _cimg_mp_scalar3(mp_cut,arg1,arg2,arg3); + } + + if (!std::strncmp(ss,"convolve(",9) || !std::strncmp(ss,"correlate(",10)) { // Convolve & Correlate + is_sth = *ss2=='n'; // is_convolve? + _cimg_mp_op(is_sth?"Function 'convolve()'":"Function 'correlate()'"); + op = is_sth?mp_convolve:mp_correlate; + const ulongT default_params[] = { (ulongT)op,0, // [0]=function, [1]=result vector + 0,0,0,0,0, // [2]=A, [3]=wA, [4]=hA, [5]=dA, [6]=sA + 0,0,0,0,0, // [7]=M, [8]=wM, [9]=hM, [10]=dM, [11]=sM + 1,0,1, // [12]=boundary_conditions, [13]=is_normalized, [14]=chan._mode + 11,11,11, // [15]=xcenter, [16]=ycenter, [17]=zcenter (default value:-1) + 0,0,0, // [18]=xstart, [19]=ystart, [20]=zstart + 11,11,11, // [21]=xend, [22]=yend, [23]=zend (default value: -1) + 1,1,1, // [24]=xstride, [25]=ystride, [26]=zstride + 1,1,1 }; // [27]=xdilation, [28]=ydilation, [29]=zdilation + + l_opcode.assign(); // Don't use 'opcode': it could be modified by further calls to 'compile()'! + CImg(default_params,1,sizeof(default_params)/sizeof(ulongT)).move_to(l_opcode); + + arg1 = 2; + for (s = std::strchr(ss,'(') + 1; s=opcode._height) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: %s arguments provided, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1<12?"Not enough":"Too much", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(opcode[2],1,2,0); // A + _cimg_mp_check_constant(opcode[3],2,3); // wA + _cimg_mp_check_constant(opcode[4],3,3); // hA + _cimg_mp_check_constant(opcode[5],4,3); // dA + _cimg_mp_check_constant(opcode[6],5,3); // sA + _cimg_mp_check_type(opcode[7],6,2,0); // M + _cimg_mp_check_constant(opcode[8],7,3); // wM + _cimg_mp_check_constant(opcode[9],8,3); // hM + _cimg_mp_check_constant(opcode[10],9,3); // dM + _cimg_mp_check_constant(opcode[11],10,3); // sM + _cimg_mp_check_type(opcode[12],11,1,0); // boundary_conditions + _cimg_mp_check_type(opcode[13],12,1,0); // is_normalized + _cimg_mp_check_constant(opcode[14],13,1); // channel_mode + _cimg_mp_check_type(opcode[15],14,1,0); // xcenter + _cimg_mp_check_type(opcode[16],15,1,0); // ycenter + _cimg_mp_check_type(opcode[17],16,1,0); // zcenter + _cimg_mp_check_constant(opcode[18],17,1); // xstart + _cimg_mp_check_constant(opcode[19],18,1); // ystart + _cimg_mp_check_constant(opcode[20],19,1); // zstart + _cimg_mp_check_constant(opcode[21],20,1); // xend + _cimg_mp_check_constant(opcode[22],21,1); // yend + _cimg_mp_check_constant(opcode[23],22,1); // zend + _cimg_mp_check_constant(opcode[24],23,3); // xstride + _cimg_mp_check_constant(opcode[25],24,3); // ystride + _cimg_mp_check_constant(opcode[26],25,3); // zstride + _cimg_mp_check_type(opcode[27],26,1,0); // xdilation + _cimg_mp_check_type(opcode[28],27,1,0); // ydilation + _cimg_mp_check_type(opcode[29],28,1,0); // zdilation + + const unsigned int + wA = (unsigned int)mem[opcode[3]], + hA = (unsigned int)mem[opcode[4]], + dA = (unsigned int)mem[opcode[5]], + sA = (unsigned int)mem[opcode[6]], + wM = (unsigned int)mem[opcode[8]], + hM = (unsigned int)mem[opcode[9]], + dM = (unsigned int)mem[opcode[10]], + sM = (unsigned int)mem[opcode[11]], + channel_mode = (unsigned int)mem[opcode[14]], + xstart = std::min((unsigned int)mem[opcode[18]],wA - 1), + ystart = std::min((unsigned int)mem[opcode[19]],hA - 1), + zstart = std::min((unsigned int)mem[opcode[20]],dA - 1), + xend = std::min((unsigned int)mem[opcode[21]],wA - 1), + yend = std::min((unsigned int)mem[opcode[22]],hA - 1), + zend = std::min((unsigned int)mem[opcode[23]],dA - 1); + + if (xstart>xend || ystart>yend || zstart>zend) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid xyz-start/end arguments " + "(start = (%u,%u,%u), end = (%u,%u,%u)), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + xstart,ystart,zstart,xend,yend,zend, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + const float + xstride = (float)mem[opcode[24]], + ystride = (float)mem[opcode[25]], + zstride = (float)mem[opcode[26]]; + + if (xstride<=0 || ystride<=0 || zstride<=0) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid stride arguments (%g,%g,%g), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + xstride,ystride,zstride, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + arg2 = 1 + (unsigned int)std::floor((xend - xstart)/xstride); + arg3 = 1 + (unsigned int)std::floor((yend - ystart)/ystride); + arg4 = 1 + (unsigned int)std::floor((zend + zstart)/zstride); + arg5 = channel_mode==0?sM:channel_mode==1?std::max(sA,sM):sA*sM; + + opcode[1] = pos = vector(arg2*arg3*arg4*arg5); + opcode[3] = (ulongT)wA; + opcode[4] = (ulongT)hA; + opcode[5] = (ulongT)dA; + opcode[6] = (ulongT)sA; + opcode[8] = (ulongT)wM; + opcode[9] = (ulongT)hM; + opcode[10] = (ulongT)dM; + opcode[11] = (ulongT)sM; + opcode[14] = (ulongT)channel_mode; + opcode[18] = (ulongT)xstart; + opcode[19] = (ulongT)ystart; + opcode[20] = (ulongT)zstart; + opcode[21] = (ulongT)xend; + opcode[22] = (ulongT)yend; + opcode[23] = (ulongT)zend; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'd' : + if (*ss1=='(') { // Image depth + _cimg_mp_op("Function 'd()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_d,p1); + } + + if (!std::strncmp(ss,"date(",5)) { // Current date or file date + _cimg_mp_op("Function 'date()'"); + s1 = ss5; while (s1::vector((ulongT)mp_date,pos,_cimg_mp_size(pos), + arg1,arg1==~0U?~0U:_cimg_mp_size(arg1), + arg2,arg2==~0U?~0U:_cimg_mp_size(arg2)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"debug(",6)) { // Print debug info + _cimg_mp_op("Function 'debug()'"); + p1 = code._width; + arg1 = compile(ss6,se1,depth1,p_ref,is_critical); + *se1 = 0; + variable_name.assign(CImg::string(ss6,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + ((CImg::vector((ulongT)mp_debug,arg1,0,code._width - p1), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code,p1); + *se1 = ')'; + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"display(",8)) { // Display memory, vector or image + _cimg_mp_op("Function 'display()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_display_memory,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + if (*ss8!='#') { // Vector + s1 = ss8; while (s1::string(ss8,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + if (_cimg_mp_is_vector(arg1)) + ((CImg::vector((ulongT)mp_vector_print,arg1,0,(ulongT)_cimg_mp_size(arg1),0), + variable_name)>'y').move_to(opcode); + else + ((CImg::vector((ulongT)mp_print,arg1,0,0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + + ((CImg::vector((ulongT)mp_display,arg1,0,(ulongT)_cimg_mp_size(arg1), + arg2,arg3,arg4,arg5), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *s1 = c1; + _cimg_mp_return(arg1); + + } else { // Image + p1 = compile(ss8 + 1,se1,depth1,0,is_critical); + _cimg_mp_check_list(true); + CImg::vector((ulongT)mp_image_display,_cimg_mp_slot_nan,p1).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"det(",4)) { // Matrix determinant + _cimg_mp_op("Function 'det()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + _cimg_mp_scalar2(mp_det,arg1,p1); + } + + if (!std::strncmp(ss,"diag(",5)) { // Diagonal matrix + _cimg_mp_op("Function 'diag()'"); + CImg::vector((ulongT)mp_diag,0,0).move_to(l_opcode); + for (s = ss5; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + arg1 = opcode._height - 3; + pos = vector(arg1*arg1); + opcode[1] = pos; + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"dot(",4)) { // Dot product + _cimg_mp_op("Function 'dot()'"); + s1 = ss4; while (s1::vector((ulongT)mp_do,p1,p2,arg2 - arg1,code._width - arg2,_cimg_mp_size(p1), + p1>=arg6 && !_cimg_mp_is_constant(p1), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"draw(",5)) { // Draw image + if (!is_critical) is_parallelizable = false; + _cimg_mp_op("Function 'draw()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s01) { + arg3 = arg2 + 1; + if (p2>2) { + arg4 = arg3 + 1; + if (p2>3) arg5 = arg4 + 1; + } + } + ++s0; + is_sth = true; + } else { + if (s0::vector((ulongT)mp_draw,arg1,(ulongT)_cimg_mp_size(arg1),p1,arg2,arg3,arg4,arg5, + 0,0,0,0,1,(ulongT)~0U,0,1).move_to(l_opcode); + + arg2 = arg3 = arg4 = arg5 = ~0U; + p2 = p1!=~0U?0:1; + if (s0::vector((ulongT)mp_echo,_cimg_mp_slot_nan,0).move_to(l_opcode); + for (s = ss5; s::vector(arg1,_cimg_mp_size(arg1)).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"eig(",4)) { // Matrix eigenvalues/eigenvector + _cimg_mp_op("Function 'eig()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + pos = vector((p1 + 1)*p1); + CImg::vector((ulongT)mp_matrix_eig,pos,arg1,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ellipse(",8)) { // Ellipse/circle drawing + if (!is_critical) is_parallelizable = false; + _cimg_mp_op("Function 'ellipse()'"); + if (*ss8=='#') { // Index specified + s0 = ss + 9; while (s0::vector((ulongT)mp_ellipse,_cimg_mp_slot_nan,0,p1).move_to(l_opcode); + for (s = s0; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"erf(",4)) { // Error function + _cimg_mp_op("Function 'erf()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_erf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::erf(mem[arg1])); + _cimg_mp_scalar1(mp_erf,arg1); + } + + if (!std::strncmp(ss,"erfinv(",7)) { // Inverse of error function + _cimg_mp_op("Function 'erfinv()'"); + arg1 = compile(ss7,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_erfinv,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::erfinv(mem[arg1])); + _cimg_mp_scalar1(mp_erfinv,arg1); + } + + if (!std::strncmp(ss,"exp(",4)) { // Exponential + _cimg_mp_op("Function 'exp()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1])); + _cimg_mp_scalar1(mp_exp,arg1); + } + + if (!std::strncmp(ss,"expr(",5)) { // Vector from expression + _cimg_mp_op("Function 'expr()'"); + s1 = ss5; while (s1::vector((ulongT)mp_expr,pos,arg1,p1,arg2,arg3,arg4,arg5).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"eye(",4)) { // Identity matrix + _cimg_mp_op("Function 'eye()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_constant(arg1,1,3); + p1 = (unsigned int)mem[arg1]; + pos = vector(p1*p1); + CImg::vector((ulongT)mp_eye,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"end(",4)) { // End + _cimg_mp_op("Function 'end()'"); + code.swap(code_end); + compile(ss4,se1,depth1,p_ref,true); + code.swap(code_end); + is_end_code = true; + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"end_t(",6)) { // End thread + _cimg_mp_op("Function 'end_t()'"); + code.swap(code_end_t); + compile(ss6,se1,depth1,p_ref,true); + code.swap(code_end_t); + is_end_code = true; + _cimg_mp_return_nan(); + } + break; + + case 'f' : + if (!std::strncmp(ss,"f2ui(",5)) { // Special float->uint conversion + _cimg_mp_op("Function 'f2ui()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_f2ui,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((double)cimg::float2uint((float)mem[arg1])); + _cimg_mp_scalar1(mp_f2ui,arg1); + } + + if (!std::strncmp(ss,"fact(",5)) { // Factorial + _cimg_mp_op("Function 'fact()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_factorial,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::factorial((int)mem[arg1])); + _cimg_mp_scalar1(mp_factorial,arg1); + } + + if (!std::strncmp(ss,"fibo(",5)) { // Fibonacci + _cimg_mp_op("Function 'fibo()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_fibonacci,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::fibonacci((int)mem[arg1])); + _cimg_mp_scalar1(mp_fibonacci,arg1); + } + + if (!std::strncmp(ss,"fill(",5)) { // Fill + _cimg_mp_op("Function 'fill()'"); + s0 = ss5; while (s0::%s: %s: Target scalar is constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss>expr._data?"...":"",ss,se<&expr.back()?"...":""); + s1 = ++s0; while (s1::%s: %s: Invalid loop variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + get_variable_pos(variable_name,arg2,arg3); + arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot + if (arg2!=~0U && (!_cimg_mp_is_scalar(arg2) || + _cimg_mp_is_constant(arg2))) { // Variable is not a vector or is a constant -> error + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' " + "(expected 'scalar'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg2)._data,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (arg2==~0U) { // Variable does not exist -> create it + arg2 = scalar(); + if (arg3!=~0U) reserved_label[arg3] = arg2; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg2; + variable_name.move_to(variable_def); + } + memtype[arg2] = -1; + } + arg3 = compile(++s1,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg3,3,1,0); + } else { // Version with 2 arguments + arg2 = ~0U; + arg3 = compile(s0,se1,depth1,0,is_critical); + } + // arg2 = variable slot, arg3 = fill expression. + _cimg_mp_check_type(arg3,3,1,0); + CImg::vector((ulongT)mp_fill,arg1,_cimg_mp_size(arg1),arg2,arg3,code._width - p1). + move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"find(",5)) { // Find + _cimg_mp_op("Function 'find()'"); + + // First argument: data to look at. + s0 = ss5; while (s01) + _cimg_mp_scalar5(mp_list_find_seq,p1,arg2,_cimg_mp_size(arg2),arg3,arg4); + _cimg_mp_scalar4(mp_list_find,p1,arg2 + (_cimg_mp_size(arg2)?1:0),arg3,arg4); + } + if (_cimg_mp_size(arg2)>1) + _cimg_mp_scalar6(mp_find_seq,arg1,_cimg_mp_size(arg1),arg2,_cimg_mp_size(arg2),arg3,arg4); + _cimg_mp_scalar5(mp_find,arg1,_cimg_mp_size(arg1),arg2 + (_cimg_mp_size(arg2)?1:0),arg3,arg4); + } + + if (*ss1=='o' && *ss2=='r' && *ss3=='(') { // For loop + _cimg_mp_op("Function 'for()'"); + s1 = ss4; while (s1::vector((ulongT)mp_for,p3,(ulongT)_cimg_mp_size(p3),p2,arg2 - arg1,arg3 - arg2, + arg4 - arg3,code._width - arg4, + p3>=arg6 && !_cimg_mp_is_constant(p3), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p3); + } + + if (!std::strncmp(ss,"floor(",6)) { // Floor + _cimg_mp_op("Function 'floor()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_floor,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::floor(mem[arg1])); + _cimg_mp_scalar1(mp_floor,arg1); + } + + if (!std::strncmp(ss,"fsize(",6)) { // File size + _cimg_mp_op("Function 'fsize()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,2,0); + pos = scalar(); + CImg::vector((ulongT)mp_fsize,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'g' : + if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function + _cimg_mp_op("Function 'gauss()'"); + s1 = ss6; while (s1::vector((ulongT)mp_get,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + break; + + case 'h' : + if (*ss1=='(') { // Image height + _cimg_mp_op("Function 'h()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_h,p1); + } + break; + + case 'i' : + if (*ss1=='c' && *ss2=='(') { // Image median + _cimg_mp_op("Function 'ic()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + pos = scalar(); + CImg::vector((ulongT)mp_image_median,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (*ss1=='n' && *ss2=='(') { // Image norm + _cimg_mp_op("Function 'in()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + pos = scalar(); + CImg::vector((ulongT)mp_image_norm,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (*ss1=='f' && *ss2=='(') { // If..then[..else.] + _cimg_mp_op("Function 'if()'"); + s1 = ss3; while (s1::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"inrange(",8)) { // Check value range + _cimg_mp_op("Function 'inrange()'"); + s1 = ss8; while (s1=val1) + is_sth = (mem[arg4]?(val>=val1):(val>val1)) && (mem[arg5]?(val<=val2):(val=val2):(val>val2)) && (mem[arg4]?(val<=val1):(val::vector((ulongT)mp_inrange,pos,arg6,arg1,p1,arg2,p2,arg3,p3,arg4,arg5).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"int(",4)) { // Integer cast + _cimg_mp_op("Function 'int()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((longT)mem[arg1]); + _cimg_mp_scalar1(mp_int,arg1); + } + + if (!std::strncmp(ss,"invert(",7)) { // Matrix/scalar inversion + _cimg_mp_op("Function 'invert()'"); + s1 = ss7; while (s1::vector((ulongT)mp_matrix_invert,pos,arg1,p1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(1/mem[arg1]); + _cimg_mp_scalar2(mp_div,1,arg1); + } + + if (*ss1=='s') { // Family of 'is_?()' functions + + if (!std::strncmp(ss,"isbool(",7)) { // Is boolean? + _cimg_mp_op("Function 'isbool()'"); + if (ss7==se1) _cimg_mp_return(0); + try { arg1 = compile(ss7,se1,depth1,0,is_critical); } + catch(CImgException&) { _cimg_mp_return(0); } + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return(mem[arg1]==0. || mem[arg1]==1.); + _cimg_mp_scalar1(mp_isbool,arg1); + } + + if (!std::strncmp(ss,"isdir(",6)) { // Is directory? + _cimg_mp_op("Function 'isdir()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_isdir,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isfile(",7)) { // Is file? + _cimg_mp_op("Function 'isfile()'"); + arg1 = compile(ss7,se1,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_isfile,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector? + if (ss5>=se1) _cimg_mp_return(0); + _cimg_mp_op("Function 'isin()'"); + pos = scalar(); + CImg::vector((ulongT)mp_isin,pos,0).move_to(l_opcode); + for (s = ss5; s::sequence(_cimg_mp_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_size(arg1)). + move_to(l_opcode); + else CImg::vector(arg1).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isinf(",6)) { // Is infinite? + _cimg_mp_op("Function 'isinf()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_inf(mem[arg1])); + _cimg_mp_scalar1(mp_isinf,arg1); + } + + if (!std::strncmp(ss,"isint(",6)) { // Is integer? + _cimg_mp_op("Function 'isint()'"); + if (ss6==se1) _cimg_mp_return(0); + try { arg1 = compile(ss6,se1,depth1,0,is_critical); } + catch(CImgException&) { _cimg_mp_return(0); } + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)((double)(longT)mem[arg1]==mem[arg1])); + _cimg_mp_scalar1(mp_isint,arg1); + } + + if (!std::strncmp(ss,"isnan(",6)) { // Is NaN? + _cimg_mp_op("Function 'isnan()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_nan(mem[arg1])); + _cimg_mp_scalar1(mp_isnan,arg1); + } + + if (!std::strncmp(ss,"isnum(",6)) { // Is number? + _cimg_mp_op("Function 'isnum()'"); + val = 0; + if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1); + _cimg_mp_return(0); + } + + if (!std::strncmp(ss,"isexpr(",7)) { // Is valid expression? + _cimg_mp_op("Function 'isexpr()'"); + if (ss7==se1) _cimg_mp_return(0); + try { arg1 = compile(ss7,se1,depth1,0,is_critical); } + catch (CImgException&) { _cimg_mp_return(0); } + _cimg_mp_return(1); + } + } + break; + + case 'l' : + if (*ss1=='(') { // Size of image list + _cimg_mp_op("Function 'l()'"); + if (ss2!=se1) break; + _cimg_mp_scalar0(mp_list_l); + } + + if (!std::strncmp(ss,"lerp(",5)) { // Linear interpolation + _cimg_mp_op("Function 'lerp()'"); + s1 = ss5; while (s1::vector((ulongT)mp_vector_lerp,pos,p1,arg1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"log(",4)) { // Natural logarithm + _cimg_mp_op("Function 'log()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1])); + _cimg_mp_scalar1(mp_log,arg1); + } + + if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm + _cimg_mp_op("Function 'log2()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1])); + _cimg_mp_scalar1(mp_log2,arg1); + } + + if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm + _cimg_mp_op("Function 'log10()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1])); + _cimg_mp_scalar1(mp_log10,arg1); + } + + if (!std::strncmp(ss,"lowercase(",10)) { // Lower case + _cimg_mp_op("Function 'lowercase()'"); + arg1 = compile(ss + 10,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_lowercase,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::lowercase(mem[arg1])); + _cimg_mp_scalar1(mp_lowercase,arg1); + } + break; + + case 'm' : + if (!std::strncmp(ss,"mul(",4)) { // Matrix multiplication + _cimg_mp_op("Function 'mul()'"); + s1 = ss4; while (s1::%s: %s: Types of first and second arguments ('%s' and '%s') " + "do not match with third argument 'nb_colsB=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data,p3, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"mproj(",6)) { // Project matrix onto dictionary + _cimg_mp_op("Function 'mproj()'"); + s1 = ss6; while (s1::%s: %s: Type of first argument ('%s') " + "do not match with second argument 'nb_colsS=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,wS, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (wD*hD!=p2) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Type of third argument ('%s') " + "do not match with fourth argument 'nb_colsD=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg3)._data,wD, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (hS!=hD) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Type of first argument ('%s') " + "do not match with third argument ('%s'), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg3)._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(wS*wD); + CImg::vector((ulongT)mp_mproj,pos,arg1,wS,hS,arg3,wD,arg5,arg6,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"merge(",6)) { // Merge inter-thread variables + _cimg_mp_op("Function 'merge()'"); + s1 = ss6; while (s1::%s: %s: Merge has already been requested before " + "for specified variable " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (arg1==~0U) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid specified operator " + "(should be one of '=,+,-,*,/,min,max'), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + memmerge.resize(3,memmerge._height + 1,1,1,0,0); + memmerge(0,memmerge._height - 1) = (int)pos; + memmerge(1,memmerge._height - 1) = (int)_cimg_mp_size(pos); + memmerge(2,memmerge._height - 1) = (int)arg1; + _cimg_mp_return(pos); + } + break; + + case 'n' : +#ifdef cimg_mp_func_name + if (!std::strncmp(ss,"name(",5)) { // Get image name as a string vector + _cimg_mp_op("Function 'name()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::vector((ulongT)mp_name,pos,p1,arg1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + + if (!std::strncmp(ss,"narg(",5)) { // Number of arguments + _cimg_mp_op("Function 'narg()'"); + if (ss5>=se1) _cimg_mp_return(0); + arg1 = 0; + for (s = ss5; s::vector((ulongT)mp_norm0,pos,0).move_to(l_opcode); break; + case 1 : + CImg::vector((ulongT)mp_norm1,pos,0).move_to(l_opcode); break; + case 2 : + CImg::vector((ulongT)mp_norm2,pos,0).move_to(l_opcode); break; + case ~0U : + CImg::vector((ulongT)mp_norminf,pos,0).move_to(l_opcode); break; + default : + CImg::vector((ulongT)mp_normp,pos,0,(ulongT)(arg1==~0U?-1:(int)arg1)). + move_to(l_opcode); + } + for ( ; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + + (l_opcode>'y').move_to(opcode); + if (arg1>0 && opcode._height==4) // Special case with one argument and p>=1 + _cimg_mp_scalar1(mp_abs,opcode[3]); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'p' : + if (!std::strncmp(ss,"permut(",7)) { // Number of permutations + _cimg_mp_op("Function 'permut()'"); + s1 = ss7; while (s1::vector((ulongT)mp_polygon,_cimg_mp_slot_nan,0,p1).move_to(l_opcode); + for (s = s0; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"print(",6) || !std::strncmp(ss,"prints(",7)) { // Print expressions + is_sth = ss[5]=='s'; // is prints() + _cimg_mp_op(is_sth?"Function 'prints()'":"Function 'print()'"); + s0 = is_sth?ss7:ss6; + if (*s0!='#' || is_sth) { // Regular expression + for (s = s0; s::string(s,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + if (_cimg_mp_is_vector(pos)) // Vector + ((CImg::vector((ulongT)mp_vector_print,pos,0,(ulongT)_cimg_mp_size(pos),is_sth?1:0), + variable_name)>'y').move_to(opcode); + else // Scalar + ((CImg::vector((ulongT)mp_print,pos,0,is_sth?1:0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *ns = c1; s = ns; + } + _cimg_mp_return(pos); + } else { // Image + p1 = compile(ss7,se1,depth1,0,is_critical); + _cimg_mp_check_list(true); + CImg::vector((ulongT)mp_image_print,_cimg_mp_slot_nan,p1).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"pseudoinvert(",13)) { // Matrix/scalar pseudo-inversion + _cimg_mp_op("Function 'pseudoinvert()'"); + s1 = ss + 13; while (s1::%s: %s: Type of first argument ('%s') " + "does not match with second argument 'nb_colsA=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1); + CImg::vector((ulongT)mp_matrix_pseudoinvert,pos,arg1,p2,p3,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'r' : + if (!std::strncmp(ss,"ref(",4)) { // Variable declaration + _cimg_mp_op("Function 'ref()'"); + s1 = ss4; while (s1=se1 || !*s1) compile(s1,s1,depth1,0,is_critical); // Will throw missing argument error + arg3 = compile(ss4,s1++,depth1,p_ref,is_critical); + *se1 = 0; + + if (!is_varname(s1)) { // Invalid variable name + variable_name.assign(s1,(unsigned int)(se1 + 1 - s1)).back() = 0; + cimg::strellipsize(variable_name,64); + *se1 = ')'; + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid specified variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + get_variable_pos(s1,arg1,arg2); + if (arg2!=~0U) reserved_label[arg2] = arg3; + else if (arg1!=~0U) variable_pos[arg1] = arg3; + else { // New variable + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg3; + CImg::string(s1).move_to(variable_def); + } + if (_cimg_mp_is_vector(arg3)) + set_reserved_vector(arg3); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -1; + *se1 = ')'; + _cimg_mp_return(arg3); + } + + if (!std::strncmp(ss,"repeat(",7)) { // Repeat + _cimg_mp_op("Function 'repeat()'"); + s0 = ss7; while (s0::%s: %s: Invalid loop variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + get_variable_pos(variable_name,arg2,arg3); + arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot + if (arg2!=~0U && (!_cimg_mp_is_scalar(arg2) || + _cimg_mp_is_constant(arg2))) { // Variable is not a vector or is a constant -> error + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' " + "(expected 'scalar'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg2)._data,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (arg2==~0U) { // Variable does not exist -> create it + arg2 = scalar(); + if (arg3!=~0U) reserved_label[arg3] = arg2; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg2; + variable_name.move_to(variable_def); + } + memtype[arg2] = -1; + } + arg3 = compile(++s1,se1,depth1,0,is_critical); + } else { // Version with 2 arguments + arg2 = ~0U; + arg3 = compile(s0,se1,depth1,0,is_critical); + } + // arg2 = variable slot, arg3 = fill expression. + CImg::vector((ulongT)mp_repeat,arg3,arg1,arg2,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg3); + } + + if (!std::strncmp(ss,"resize(",7)) { // Vector or image resize + _cimg_mp_op("Function 'resize()'"); + if (*ss7!='#') { // Vector + s1 = ss7; while (s1::vector((ulongT)mp_vector_resize,pos,arg2,arg1,(ulongT)_cimg_mp_size(arg1), + arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + + } else { // Image + if (!is_critical) is_parallelizable = false; + s0 = ss8; while (s0::vector((ulongT)mp_image_resize,_cimg_mp_slot_nan,p1,~0U,~0U,~0U,~0U,1,0,0,0,0,0). + move_to(l_opcode); + pos = 0; + for (s = s0; s10) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: %s arguments, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + pos<1?"Missing":"Too much", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + l_opcode[0].move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"reverse(",8)) { // Vector reverse + _cimg_mp_op("Function 'reverse()'"); + arg1 = compile(ss8,se1,depth1,0,is_critical); + if (!_cimg_mp_is_vector(arg1)) _cimg_mp_return(arg1); + p1 = _cimg_mp_size(arg1); + pos = vector(p1); + CImg::vector((ulongT)mp_vector_reverse,pos,arg1,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation + _cimg_mp_op(ss[2]=='l'?"Function 'rol()'":"Function 'ror()'"); + s1 = ss4; while (s11) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + arg4 = compile(++s1,se1,depth1,0,is_critical); + } else { + s2 = s1 + 1; while (s2::vector((ulongT)mp_rot3d,pos,arg1,arg2,arg3,arg4).move_to(code); + } else { // 2D rotation + _cimg_mp_check_type(arg1,1,1,0); + pos = vector(4); + CImg::vector((ulongT)mp_rot2d,pos,arg1).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"round(",6)) { // Value rounding + _cimg_mp_op("Function 'round()'"); + s1 = ss6; while (s1::vector((ulongT)mp_run,0,0).move_to(l_opcode); + pos = 1; + for (s = ss4; s::vector(arg1,_cimg_mp_size(arg1)).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + pos = scalar(); + opcode[1] = pos; + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + break; + + case 's' : + if (*ss1=='(') { // Image spectrum + _cimg_mp_op("Function 's()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_s,p1); + } + + if (!std::strncmp(ss,"same(",5)) { // Test if operands have the same values + _cimg_mp_op("Function 'same()'"); + s1 = ss5; while (s1::vector((ulongT)mp_shift,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sign(",5)) { // Sign + _cimg_mp_op("Function 'sign()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1])); + _cimg_mp_scalar1(mp_sign,arg1); + } + + if (!std::strncmp(ss,"sin(",4)) { // Sine + _cimg_mp_op("Function 'sin()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1])); + _cimg_mp_scalar1(mp_sin,arg1); + } + + if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal + _cimg_mp_op("Function 'sinc()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1])); + _cimg_mp_scalar1(mp_sinc,arg1); + } + + if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine + _cimg_mp_op("Function 'sinh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1])); + _cimg_mp_scalar1(mp_sinh,arg1); + } + + if (!std::strncmp(ss,"size(",5)) { // Vector size + _cimg_mp_op("Function 'size()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_size(arg1)); + } + + if (!std::strncmp(ss,"solve(",6)) { // Solve square linear system + _cimg_mp_op("Function 'solve()'"); + s1 = ss6; while (s1::%s: %s: Types of first and second arguments ('%s' and '%s') " + "do not match with third argument 'nb_colsB=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data,p3, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sort(",5)) { // Sort vector + _cimg_mp_op("Function 'sort()'"); + s1 = ss5; while (s1::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sqr(",4)) { // Square + _cimg_mp_op("Function 'sqr()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1])); + _cimg_mp_scalar1(mp_sqr,arg1); + } + + if (!std::strncmp(ss,"sqrt(",5)) { // Square root + _cimg_mp_op("Function 'sqrt()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1])); + _cimg_mp_scalar1(mp_sqrt,arg1); + } + + if (!std::strncmp(ss,"srand(",6)) { // Set RNG seed + _cimg_mp_op("Function 'srand()'"); + arg1 = ss6::vector((ulongT)mp_image_stats,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + +#ifdef cimg_mp_func_store + if (!std::strncmp(ss,"store(",6)) { // Store vector to variable + _cimg_mp_op("Function 'store()'"); + s1 = ss6; while (s1::vector((ulongT)mp_store,_cimg_mp_slot_nan,arg1,p1,arg2,p2, + arg3,arg4,arg5,arg6,pos).move_to(code); + _cimg_mp_return_nan(); + } +#endif + + if (!std::strncmp(ss,"stov(",5)) { // String to double + _cimg_mp_op("Function 'stov()'"); + s1 = ss5; while (s1::vector((ulongT)mp_stov,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"string(",7)) { // Construct string from list of arguments + _cimg_mp_op("Function 'string()'"); + CImg::vector((ulongT)mp_string,0,0,0).move_to(l_opcode); + + if (*ss7=='#') { // Output vector size specified, with '#' + s0 = ss8; while (s0::vector(arg2,p2).move_to(l_opcode); + s = ns; + } + if (arg1==~0U) arg1 = p1; + pos = vector(arg1,0); + (l_opcode>'y').move_to(opcode); + opcode[1] = pos; + opcode[2] = arg1; + opcode[3] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"svd(",4)) { // Matrix SVD + _cimg_mp_op("Function 'svd()'"); + s1 = ss4; while (s1::%s: %s: Type of first argument ('%s') " + "does not match with second argument 'nb_colsA=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1 + p2 + p2*p2); + CImg::vector((ulongT)mp_matrix_svd,pos,arg1,p2,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"swap(",5)) { // Swap values + _cimg_mp_op("Function 'swap()'"); + s1 = ss5; while (s1::%s: %s: %s argument cannot be a constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"First":"Second", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + CImg::vector((ulongT)mp_swap,arg1,arg2,p1).move_to(code); + + // Write back values of linked arg1 and arg2. + const unsigned int *_ref = ref; + is_sth = true; // Is first argument? + do { + switch (*_ref) { + case 1 : // arg1: V[k] + arg3 = _ref[1]; // Vector slot + arg4 = _ref[2]; // Index + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + break; + case 2 : // arg1: i/j[_#ind,off] + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // Offset + if (p1!=~0U) { + if (listout) + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (imgout) + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + break; + case 3 : // arg1: i/j(_#ind,_x,_y,_z,_c) + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // X + arg4 = _ref[4]; // Y + arg5 = _ref[5]; // Z + arg6 = _ref[6]; // C + if (p1!=~0U) { + if (listout) + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (imgout) + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + break; + case 4: // arg1: I/J[_#ind,off] + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // Offset + if (p1!=~0U) { + if (listout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg1,p1,arg3).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + } + } else { + if (imgout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg1,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + } + break; + case 5 : // arg1: I/J(_#ind,_x,_y,_z,_c) + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // X + arg4 = _ref[4]; // Y + arg5 = _ref[5]; // Z + if (p1!=~0U) { + if (listout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg1,p1,arg3,arg4,arg5).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + } else { + if (imgout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg1,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + break; + } + + _ref+=7; + arg1 = arg2; + is_sth = !is_sth; + } while (!is_sth); + + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + _cimg_mp_return(arg1); + } + break; + + case 't' : + if (!std::strncmp(ss,"tan(",4)) { // Tangent + _cimg_mp_op("Function 'tan()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1])); + _cimg_mp_scalar1(mp_tan,arg1); + } + + if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent + _cimg_mp_op("Function 'tanh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1])); + _cimg_mp_scalar1(mp_tanh,arg1); + } + + if (!std::strncmp(ss,"trace(",6)) { // Matrix trace + _cimg_mp_op("Function 'trace()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + _cimg_mp_scalar2(mp_trace,arg1,p1); + } + + if (!std::strncmp(ss,"transpose(",10)) { // Matrix transpose + _cimg_mp_op("Function 'transpose()'"); + s1 = ss + 10; while (s1::%s: %s: Size of first argument ('%s') does not match " + "second argument 'nb_cols=%u', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p3*p2); + CImg::vector((ulongT)mp_transpose,pos,arg1,p2,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'u' : + if (*ss1=='(') { // Random value with uniform distribution + _cimg_mp_op("Function 'u()'"); + if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1); + s1 = ss2; while (s1float conversion + _cimg_mp_op("Function 'ui2f()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_ui2f,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((double)cimg::uint2float((unsigned int)mem[arg1])); + _cimg_mp_scalar1(mp_ui2f,arg1); + } + + if (!std::strncmp(ss,"unref(",6)) { // Un-reference variable + _cimg_mp_op("Function 'unref()'"); + arg1=~0U; + for (s0 = ss6; s0ss6 && *s0==',') ++s0; + s1 = s0; while (s1s0) { + *s1 = 0; + get_variable_pos(s0,arg1,arg2); + if (arg2!=~0U) reserved_label[arg2] = ~0U; + else if (arg1!=~0U) { + variable_def.remove(arg1); + if (arg10) || + !std::strncmp(ss,"vector(",7) || + (!std::strncmp(ss,"vector",6) && ss7::sequence(arg4,arg3 + 1,arg3 + arg4).move_to(l_opcode); + arg2+=arg4; + } else { CImg::vector(arg3).move_to(l_opcode); ++arg2; } + s = ns; + } + if (arg1==~0U) arg1 = arg2; + if (!arg1) _cimg_mp_return(0); + pos = vector(arg1); + l_opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"vmax(",5) || !std::strncmp(ss,"vmin(",5) || + !std::strncmp(ss,"vmaxabs(",8) || !std::strncmp(ss,"vminabs(",8) || + !std::strncmp(ss,"vmed(",5) || !std::strncmp(ss,"vkth(",5) || + !std::strncmp(ss,"vsum(",5) || !std::strncmp(ss,"vavg(",5) || + !std::strncmp(ss,"vstd(",5) || !std::strncmp(ss,"vvar(",5) || + !std::strncmp(ss,"vprod(",6) || + !std::strncmp(ss,"vargmin(",8) || !std::strncmp(ss,"vargmax(",8) || + !std::strncmp(ss,"vargminabs(",11) || !std::strncmp(ss,"vargmaxabs(",11) || + !std::strncmp(ss,"vargkth(",8)) { // Multi-argument vector functions + _cimg_mp_op(ss[1]=='a'?(ss[2]=='v'?"Function 'vavg()'": + ss[4]=='k'?"Function 'vargkth()'": + ss[5]=='i' && ss[7]=='('?"Function 'vargmin()'": + ss[5]=='i'?"Function vargminabs()'": + ss[7]=='('?"Function 'vargmax()'": + "Function 'vargmaxabs()'"): + ss[1]=='s'?(ss[2]=='u'?"Function 'vsum()'":"Function 'vstd()'"): + ss[1]=='k'?"Function 'vkth()'": + ss[1]=='p'?"Function 'vprod()'": + ss[1]=='v'?"Function 'vvar()'": + ss[2]=='i'?(ss[4]=='('?"Function 'vmin()'": + "Function 'vminabs()'"): + ss[2]=='a'?(ss[4]=='('?"Function 'vmax()'": + "Function 'vmaxabs()'"): + "Function 'vmed()'"); + op = ss[1]=='a'?(ss[2]=='v'?mp_vavg: + ss[4]=='k'?mp_vargkth: + ss[5]=='i' && ss[7]=='('?mp_vargmin: + ss[5]=='i'?mp_vargminabs: + ss[7]=='('?mp_vargmax:mp_vargmaxabs): + ss[1]=='s'?(ss[2]=='u'?mp_vsum:mp_vstd): + ss[1]=='k'?mp_vkth: + ss[1]=='p'?mp_vprod: + ss[1]=='v'?mp_vvar: + ss[2]=='i'?(ss[4]=='('?mp_vmin:mp_vminabs): + ss[2]=='a'?(ss[4]=='('?mp_vmax:mp_vmaxabs): + mp_vmedian; + CImg::vector((ulongT)op,0,0,0).move_to(l_opcode); + p1 = ~0U; + p3 = 1; + for (s = std::strchr(ss,'(') + 1; s::vector(arg2,p2).move_to(l_opcode); + s = ns; + ++p3; + } + (l_opcode>'y').move_to(opcode); + if (p1==~0U) { pos = scalar(); p1 = 0; } else pos = vector(p1); + opcode[1] = pos; + opcode[2] = p1; + opcode[3] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"vtos(",5)) { // Double(s) to string + _cimg_mp_op("Function 'vtos()'"); + s1 = ss5; while (s1::vector((ulongT)mp_vtos,pos,p1,arg1,_cimg_mp_size(arg1),arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'w' : + if (*ss1=='(') { // Image width + _cimg_mp_op("Function 'w()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_w,p1); + } + + if (*ss1=='h' && *ss2=='(') { // Image width*height + _cimg_mp_op("Function 'wh()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_wh,p1); + } + + if (*ss1=='h' && *ss2=='d' && *ss3=='(') { // Image width*height*depth + _cimg_mp_op("Function 'whd()'"); + if (*ss4=='#') { // Index specified + p1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss4!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_whd,p1); + } + + if (*ss1=='h' && *ss2=='d' && *ss3=='s' && *ss4=='(') { // Image width*height*depth*spectrum + _cimg_mp_op("Function 'whds()'"); + if (*ss5=='#') { // Index specified + p1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss5!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_whds,p1); + } + + if (!std::strncmp(ss,"while(",6)) { // While...do + _cimg_mp_op("Function 'while()'"); + s0 = *ss5=='('?ss6:ss8; + s1 = s0; while (s1::vector((ulongT)mp_while,pos,arg1,p2 - p1,code._width - p2,arg2, + pos>=arg6 && !_cimg_mp_is_constant(pos), + arg1>=arg6 && !_cimg_mp_is_constant(arg1)).move_to(code,p1); + _cimg_mp_return(pos); + } + break; + + case 'x' : + if (!std::strncmp(ss,"xor(",4)) { // Xor + _cimg_mp_op("Function 'xor()'"); + s1 = ss4; while (s1::vector((ulongT)op,pos,0).move_to(l_opcode); + for (s = std::strchr(ss,'(') + 1; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + is_sth&=_cimg_mp_is_constant(arg2); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (is_sth) _cimg_mp_constant(op(*this)); + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // No corresponding built-in function -> Look for a user-defined macro call. + s0 = strchr(ss,'('); + if (s0) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + + // Count number of specified arguments. + p1 = 0; + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && !p1) break; + ns = s; while (ns _expr = macro_body[l]; // Expression to be substituted + + p1 = 1; // Index of current parsed argument + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { // Parse function arguments + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && p1==1) break; // Function has no arguments + if (p1>p2) { ++p1; break; } + ns = s; while (ns _pexpr(_expr._width); + ns = _pexpr._data; + for (ps = _expr._data, c1 = ' '; *ps; ++ps) { + if (!cimg::is_blank(*ps)) c1 = *ps; + *(ns++) = c1; + } + *ns = 0; + + CImg _level = get_level(_expr); + expr.swap(_expr); + pexpr.swap(_pexpr); + level.swap(_level); + s0 = user_macro; + user_macro = macro_def[l]; + pos = compile(expr._data,expr._data + expr._width - 1,depth1,p_ref,is_critical); + user_macro = s0; + level.swap(_level); + pexpr.swap(_pexpr); + expr.swap(_expr); + _cimg_mp_return(pos); + } + + if (arg3) { // Macro name matched but number of arguments does not + CImg sig_nargs(arg3); + arg1 = 0; + cimglist_for(macro_def,l) if (!std::strcmp(macro_def[l],variable_name)) + sig_nargs[arg1++] = (unsigned int)macro_def[l].back(); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + if (sig_nargs._width>1) { + sig_nargs.sort(); + arg1 = sig_nargs.back(); + --sig_nargs._width; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %s or %u arguments), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,sig_nargs.value_string()._data,arg1, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %u argument%s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,*sig_nargs,*sig_nargs!=1?"s":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + } // if (se1==')') + + // Char / string initializer. + if (*se1=='\'' && + ((se1>ss && *ss=='\'') || + (se1>ss1 && *ss=='_' && *ss1=='\''))) { + if (*ss=='_') { _cimg_mp_op("Char initializer"); s1 = ss2; } + else { _cimg_mp_op("String initializer"); s1 = ss1; } + arg1 = (unsigned int)(se1 - s1); // Original string length + if (arg1) { + CImg(s1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + if (*ss=='_') { + if (arg1==1) _cimg_mp_constant((unsigned char)*variable_name); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Literal %s contains more than one byte, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss1, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode); + std::memcpy((char*)l_opcode[1]._data,variable_name,arg1); + (l_opcode>'y').move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // Vector initializer [ ... ]. + if (*ss=='[' && *se1==']') { + _cimg_mp_op("Vector initializer"); + s1 = ss1; while (s1s1 && cimg::is_blank(*s2)) --s2; + if (s2>s1 && *s1=='\'' && *s2=='\'') { // Vector values provided as a string + arg1 = (unsigned int)(s2 - s1 - 1); // Original string length + if (arg1) { + CImg(s1 + 1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode); + std::memcpy((char*)l_opcode[1]._data,variable_name,arg1); + (l_opcode>'y').move_to(code); + } else { // Vector values provided as list of items + arg1 = 0; // Number of specified values + if (*ss1!=']') for (s = ss1; s::sequence(arg3,arg2 + 1,arg2 + arg3).move_to(l_opcode); + arg1+=arg3; + } else { CImg::vector(arg2).move_to(l_opcode); ++arg1; } + s = ns; + } + if (!arg1) _cimg_mp_return(0); + pos = vector(arg1); + l_opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + // Variables related to the input list of images. + if (*ss1=='#' && ss2::vector((ulongT)mp_list_Joff,pos,p1,0,0,p2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + case 'R' : // R#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0, + 0,_cimg_mp_boundary); + case 'G' : // G#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1, + 0,_cimg_mp_boundary); + case 'B' : // B#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2, + 0,_cimg_mp_boundary); + case 'A' : // A#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3, + 0,_cimg_mp_boundary); + } + } + + if (*ss1 && *ss2=='#' && ss3='0' && *ss1<='9') { // i0#ind...i9#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,*ss1 - '0', + 0,_cimg_mp_boundary); + } + + if (*ss1=='c') { // ic#ind + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_median) list_median.assign(listin._width); + if (!list_median[p1]) CImg::vector(listin[p1].median()).move_to(list_median[p1]); + _cimg_mp_constant(*list_median[p1]); + } + _cimg_mp_scalar1(mp_list_median,arg1); + } + + if (*ss1=='n') { // in#ind + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_norm) list_norm.assign(listin._width); + if (!list_norm[p1]) CImg::vector(listin[p1].magnitude()).move_to(list_norm[p1]); + _cimg_mp_constant(*list_norm[p1]); + } + _cimg_mp_scalar1(mp_list_norm,arg1); + } + + switch (*ss1) { + case 'm' : arg2 = 0; break; // im#ind + case 'M' : arg2 = 1; break; // iM#ind + case 'a' : arg2 = 2; break; // ia#ind + case 'v' : arg2 = 3; break; // iv#ind + case 's' : arg2 = 12; break; // is#ind + case 'p' : arg2 = 13; break; // ip#ind + } + } else if (*ss1=='m') switch (*ss) { + case 'x' : arg2 = 4; break; // xm#ind + case 'y' : arg2 = 5; break; // ym#ind + case 'z' : arg2 = 6; break; // zm#ind + case 'c' : arg2 = 7; break; // cm#ind + } else if (*ss1=='M') switch (*ss) { + case 'x' : arg2 = 8; break; // xM#ind + case 'y' : arg2 = 9; break; // yM#ind + case 'z' : arg2 = 10; break; // zM#ind + case 'c' : arg2 = 11; break; // cM#ind + } + if (arg2!=~0U) { + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_stats) list_stats.assign(listin._width); + if (!list_stats[p1]) list_stats[p1].assign(1,14,1,1,0).fill(listin[p1].get_stats(),false); + _cimg_mp_constant(list_stats(p1,arg2)); + } + _cimg_mp_scalar2(mp_list_stats,arg1,arg2); + } + } + + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='#' && ss4 error. + c1 = *se1; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + if (is_sth) + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Undefined variable '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + s1 = std::strchr(ss,'('); + s_op = s1 && c1==')'?"function call":"item"; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unrecognized %s '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + s_op,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Evaluation procedure. + double operator()(const double x, const double y, const double z, const double c) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = code; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + return *result; + } + + // Evaluation procedure (return output values in vector 'output'). + template + void operator()(const double x, const double y, const double z, const double c, t *const output) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = code; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + if (result_dim) { + const double *ptrs = result + 1; + t *ptrd = output; + for (unsigned int k = 0; k_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + p_code_end = code.end(); + } + + // Evaluation procedure for end_t() bloc. + void end_t() { + if (!code_end_t) return; + if (imgin) { + mem[_cimg_mp_slot_x] = imgin._width - 1.; + mem[_cimg_mp_slot_y] = imgin._height - 1.; + mem[_cimg_mp_slot_z] = imgin._depth - 1.; + mem[_cimg_mp_slot_c] = imgin._spectrum - 1.; + } else mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_end_t.end(); + for (p_code = code_end_t; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + + // Evaluation procedure the end() bloc. + void end() { + if (!code_end) return; + if (imgin) { + mem[_cimg_mp_slot_x] = imgin._width - 1.; + mem[_cimg_mp_slot_y] = imgin._height - 1.; + mem[_cimg_mp_slot_z] = imgin._depth - 1.; + mem[_cimg_mp_slot_c] = imgin._spectrum - 1.; + } else mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_end.end(); + for (p_code = code_end; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + + // Merge inter-thread variables. + // (argument 'mp' is the master instance). + void merge(_cimg_math_parser& mp) { + if (&mp==this) return; + cimg_rofY(mp.memmerge,k) { + const unsigned int + pos = (unsigned int)mp.memmerge(0,k), + siz = (unsigned int)mp.memmerge(1,k), + iop = (unsigned int)mp.memmerge(2,k); + if (!siz) switch (iop) { // Scalar value + case 0 : mp.mem[pos] = mem[pos]; break; // Assignment + case 1 : mp.mem[pos]+=mem[pos]; break; // Operator+ + case 2 : mp.mem[pos]-=mem[pos]; break; // Operator- + case 3 : mp.mem[pos]*=mem[pos]; break; // Operator* + case 4 : mp.mem[pos]/=mem[pos]; break; // Operator/ + case 5 : mp.mem[pos] = std::min(mp.mem[pos],mem[pos]); break; // Operator 'min' + case 6 : mp.mem[pos] = std::max(mp.mem[pos],mem[pos]); break; // Operator 'max' + } else switch (iop) { // Vector value + case 0 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true) = CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 1 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)+=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 2 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)-=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 3 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)*=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 4 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)/=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 5 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true).min(CImg(&mem[pos + 1],siz,1,1,1,true)); + break; + case 6 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true).max(CImg(&mem[pos + 1],siz,1,1,1,true)); + break; + } + } + } + + // Return specified argument number as a string. + static const char *s_argth(const unsigned int n_arg) { + const char + *_s_arg[] = { "", "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth","Ninth", + "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", + "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "One of the" }; + return _s_arg[n_arg s_calling_function() const { + CImg res; + const unsigned int + l1 = calling_function?(unsigned int)std::strlen(calling_function):0U, + l2 = user_macro?(unsigned int)std::strlen(user_macro):0U; + if (l2) { + res.assign(l1 + l2 + 48); + cimg_snprintf(res,res._width,"%s(): When substituting function '%s()'",calling_function,user_macro); + } else { + res.assign(l1 + l2 + 4); + cimg_snprintf(res,res._width,"%s()",calling_function); + } + return res; + } + + // Return type of a memory element as a string. + CImg s_type(const unsigned int arg) const { + CImg res; + if (_cimg_mp_is_vector(arg)) { // Vector + CImg::string("vectorXXXXXXXXXXXXXXXX").move_to(res); + cimg_sprintf(res._data + 6,"%u",_cimg_mp_size(arg)); + } else if (_cimg_mp_is_constant(arg)) CImg::string("const scalar").move_to(res); // Const scalar + else CImg::string("scalar").move_to(res); // Scalar + return res; + } + + // Count parentheses/brackets level of each character of the expression. + CImg get_level(CImg& _expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res(_expr._width - 1); + unsigned int *pd = res._data; + int _level = 0; + for (const char *ps = _expr._data; *ps && _level>=0; ++ps) { + if (!is_escaped && !next_is_escaped && *ps=='\\') next_is_escaped = true; + if (!is_escaped && *ps=='\'') { // Non-escaped character + if (!mode && ps>_expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string + else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string + else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string + } + *(pd++) = (unsigned int)(mode>=1 || is_escaped?_level + (mode==1): + *ps=='(' || *ps=='['?_level++: + *ps==')' || *ps==']'?--_level: + _level); + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + if (mode) { + cimg::strellipsize(_expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unterminated string literal, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + _expr._data); + } + if (_level) { + cimg::strellipsize(_expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unbalanced parentheses/brackets, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + _expr._data); + } + return res; + } + + // Find and return index of current image 'imgin' within image list 'listin'. + unsigned int get_mem_img_index() { + if (mem_img_index==~0U) { + if (&imgout>listout.data() && &imgout='0' && c2<='9') rp = 20 + c2 - '0'; // i0...i9 + else if (c2=='m') rp = 4; // im + else if (c2=='M') rp = 5; // iM + else if (c2=='a') rp = 6; // ia + else if (c2=='v') rp = 7; // iv + else if (c2=='s') rp = 8; // is + else if (c2=='p') rp = 9; // ip + else if (c2=='c') rp = 10; // ic + else if (c2=='n') rp = 11; // in + } else if (c2=='m') { + if (c1=='x') rp = 12; // xm + else if (c1=='y') rp = 13; // ym + else if (c1=='z') rp = 14; // zm + else if (c1=='c') rp = 15; // cm + } else if (c2=='M') { + if (c1=='x') rp = 16; // xM + else if (c1=='y') rp = 17; // yM + else if (c1=='z') rp = 18; // zM + else if (c1=='c') rp = 19; // cM + } + } else if (variable_name[1] && variable_name[2] && !variable_name[3]) { // Three-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + if (c1=='w' && c2=='h' && c3=='d') rp = 1; // whd + } else if (variable_name[1] && variable_name[2] && variable_name[3] && + !variable_name[4]) { // Four-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + c4 = variable_name[3]; + if (c1=='w' && c2=='h' && c3=='d' && c4=='s') rp = 2; // whds + } else if (!std::strcmp(variable_name,"interpolation")) rp = 30; // interpolation + else if (!std::strcmp(variable_name,"boundary")) rp = 31; // boundary + + if (rp!=~0U) { rpos = rp; return; } // One of the reserved labels + + // Multi-char variable name : check for existing variable with same name + cimglist_for(variable_def,i) + if (!std::strcmp(variable_name,variable_def[i])) { pos = i; break; } + } + + // Tell for each character of an expression if it is inside a string or not. + CImg is_inside_string(CImg& _expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res = CImg::string(_expr); + bool *pd = res._data; + for (const char *ps = _expr._data; *ps; ++ps) { + if (!next_is_escaped && *ps=='\\') next_is_escaped = true; + if (!is_escaped && *ps=='\'') { // Non-escaped character + if (!mode && ps>_expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string + else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string + else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string + } + *(pd++) = mode>=1 || is_escaped; + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + return res; + } + + // Return true if specified argument can be a part of an allowed variable name. + bool is_varchar(const char c) const { + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; + } + + // Return true if specified argument can be considered as a variable name. + bool is_varname(const char *const str, const unsigned int length=~0U) const { + if (*str>='0' && *str<='9') return false; + for (unsigned int l = 0; l128) return false; + const int *ptr = memtype.data(arg + 1); + bool is_tmp = true; + while (siz-->0) if (*(ptr++)) { is_tmp = false; break; } + return is_tmp; + } + + // Check if a memory slot is a positive integer constant scalar value. + // 'mode' can be: + // { 0=constant | 1=integer constant | 2=positive integer constant | 3=strictly-positive integer constant } + void check_constant(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,1,0); + if (!(_cimg_mp_is_constant(arg) && + (!mode || (double)(int)mem[arg]==mem[arg]) && + (mode<2 || mem[arg]>=(mode==3)))) { + const char *const s_arg = s_argth(n_arg); + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') is not a%s constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_arg?" argument":" Argument",s_type(arg)._data, + !mode?"":mode==1?"n integer": + mode==2?" positive integer":" strictly positive integer", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check if an image index is a constant value. + void check_constant_index(const unsigned int arg, + char *const ss, char *const se, const char saved_char) { + if (arg!=~0U && !_cimg_mp_is_constant(arg)) { + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s Specified image index is not a constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check a matrix is square. + void check_matrix_square(const unsigned int arg, const unsigned int n_arg, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,2,0); + const unsigned int + siz = _cimg_mp_size(arg), + n = (unsigned int)cimg::round(std::sqrt((float)siz)); + if (n*n!=siz) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand":"Right-hand"; + else s_arg = !n_arg?"":n_arg==1?"First":n_arg==2?"Second":n_arg==3?"Third":"One"; + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') " + "cannot be considered as a square matrix, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?" argument":" Argument"):(*s_arg?" operand":" Operand"), + s_type(arg)._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check type compatibility for one argument. + // Bits of 'mode' tells what types are allowed: + // { 1 = scalar | 2 = vectorN }. + // If 'N' is not zero, it also restricts the vectors to be of size N only. + void check_type(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, const unsigned int N, + char *const ss, char *const se, const char saved_char) { + const bool + is_scalar = _cimg_mp_is_scalar(arg), + is_vector = _cimg_mp_is_vector(arg) && (!N || _cimg_mp_size(arg)==N); + bool cond = false; + if (mode&1) cond|=is_scalar; + if (mode&2) cond|=is_vector; + if (!cond) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand":"Right-hand"; + else s_arg = s_argth(n_arg); + CImg sb_type(32); + if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'"); + else if (mode==2) { + if (N) cimg_snprintf(sb_type,sb_type._width,"'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'vector'"); + } else { + if (N) cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector'"); + } + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s has invalid type '%s' (should be %s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?" argument":" Argument"):(*s_arg?" operand":" Operand"), + s_type(arg)._data,sb_type._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check that listin or listout are not empty. + void check_list(const bool is_out, + char *const ss, char *const se, const char saved_char) { + if ((!is_out && !listin) || (is_out && !listout)) { + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s Invalid call with an empty image list, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Insert constant value in memory. + unsigned int constant(const double val) { + + // Search for built-in constant. + if (cimg::type::is_nan(val)) return _cimg_mp_slot_nan; + if (val==(double)(int)val) { + if (val>=0 && val<=10) return (unsigned int)val; + if (val<0 && val>=-5) return (unsigned int)(10 - val); + } + if (val==0.5) return 16; + + // Search for constant already requested before (in const cache). + unsigned int ind = ~0U; + if (constcache_size<1024) { + if (!constcache_size) { + constcache_vals.assign(16,1,1,1,0); + constcache_inds.assign(16,1,1,1,0); + *constcache_vals = val; + constcache_size = 1; + ind = 0; + } else { // Dichotomic search + const double val_beg = *constcache_vals, val_end = constcache_vals[constcache_size - 1]; + if (val_beg>=val) ind = 0; + else if (val_end==val) ind = constcache_size - 1; + else if (val_end=constcache_size || constcache_vals[ind]!=val) { + ++constcache_size; + if (constcache_size>constcache_vals._width) { + constcache_vals.resize(-200,1,1,1,0); + constcache_inds.resize(-200,1,1,1,0); + } + const int l = constcache_size - (int)ind - 1; + if (l>0) { + std::memmove(&constcache_vals[ind + 1],&constcache_vals[ind],l*sizeof(double)); + std::memmove(&constcache_inds[ind + 1],&constcache_inds[ind],l*sizeof(unsigned int)); + } + constcache_vals[ind] = val; + constcache_inds[ind] = 0; + } + } + if (constcache_inds[ind]) return constcache_inds[ind]; + } + + // Insert new constant in memory if necessary. + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(-200,1,1,1,0); } + const unsigned int pos = mempos++; + mem[pos] = val; + memtype[pos] = 1; // Set constant property + if (ind!=~0U) constcache_inds[ind] = pos; + return pos; + } + + // Insert new scalar in memory. + unsigned int scalar() { + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(mem._width,1,1,1,0); } + return mempos++; + } + + // Insert new vector of specified size in memory. + unsigned int vector(const unsigned int siz) { + if (mempos + siz>=mem._width) { + mem.resize(2*mem._width + siz,1,1,1,0); + memtype.resize(mem._width,1,1,1,0); + } + const unsigned int pos = mempos++; + mem[pos] = cimg::type::nan(); + memtype[pos] = siz + 1; + mempos+=siz; + return pos; + } + + // Insert new initialized vector. + unsigned int vector(const unsigned int siz, const double value) { + const unsigned int pos = vector(siz); + double *ptr = &mem[pos] + 1; + for (unsigned int i = 0; i::vector((ulongT)mp_vector_copy,pos,arg,siz).move_to(code); + return pos; + } + + // Set reserved status to all values of a vector. + void set_reserved_vector(const unsigned int arg) { + unsigned int siz = _cimg_mp_size(arg); + int *ptr = memtype.data(arg + 1); + while (siz-->0) *(ptr++) = -1; + } + + unsigned int scalar0(const mp_func op) { + const unsigned int pos = scalar(); + CImg::vector((ulongT)op,pos).move_to(code); + return_new_comp = true; + return pos; + } + + unsigned int scalar1(const mp_func op, const unsigned int arg1) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1) && op!=mp_copy?arg1: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1).move_to(code); + return pos; + } + + unsigned int scalar2(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2).move_to(code); + return pos; + } + + unsigned int scalar3(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3).move_to(code); + return pos; + } + + unsigned int scalar4(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4).move_to(code); + return pos; + } + + unsigned int scalar5(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5).move_to(code); + return pos; + } + + unsigned int scalar6(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code); + return pos; + } + + unsigned int scalar7(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6, + const unsigned int arg7) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + arg7!=~0U && arg7>_cimg_mp_slot_c && _cimg_mp_is_comp(arg7)?arg7: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6,arg7).move_to(code); + return pos; + } + + void self_vector_s(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_s,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1).move_to(code[code._width - 1 - siz + k]); + } + } + + void self_vector_v(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + } + + unsigned int vector1_v(const mp_func op, const unsigned int arg1) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_vv(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1:is_comp_vector(arg2)?arg2: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_vs(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vs,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_sv(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg2), + pos = is_comp_vector(arg2)?arg2: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_sv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector3_vss(const mp_func op, const unsigned int arg1, const unsigned int arg2, + const unsigned int arg3) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vss,pos,siz,(ulongT)op,arg1,arg2,arg3).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2,arg3).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + // Evaluation functions, known by the parser. + // Defining these functions 'static' ensures that sizeof(mp_func)==sizeof(ulongT), + // so we can store pointers to them directly in the opcode vectors. +#ifdef _mp_arg +#undef _mp_arg +#endif +#define _mp_arg(x) mp.mem[mp.opcode[x]] + + static double mp_abs(_cimg_math_parser& mp) { + return cimg::abs(_mp_arg(2)); + } + + static double mp_add(_cimg_math_parser& mp) { + return _mp_arg(2) + _mp_arg(3); + } + + static double mp_acos(_cimg_math_parser& mp) { + return std::acos(_mp_arg(2)); + } + + static double mp_acosh(_cimg_math_parser& mp) { + return cimg::acosh(_mp_arg(2)); + } + + static double mp_asinh(_cimg_math_parser& mp) { + return cimg::asinh(_mp_arg(2)); + } + + static double mp_atanh(_cimg_math_parser& mp) { + return cimg::atanh(_mp_arg(2)); + } + + static double mp_arg(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:(unsigned int)_ind, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_arg0(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:_ind + 1U, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_argkth(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = mp_kth(mp); + for (unsigned int i = 4; ival) { val = _val; argval = i - 3; } + } + return (double)argval; + } + + static double mp_argmaxabs(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3), absval = cimg::abs(val); + unsigned int argval = 0; + for (unsigned int i = 4; iabsval) { val = _val; absval = _absval; argval = i - 3; } + } + return (double)argval; + } + + static double mp_asin(_cimg_math_parser& mp) { + return std::asin(_mp_arg(2)); + } + + static double mp_atan(_cimg_math_parser& mp) { + return std::atan(_mp_arg(2)); + } + + static double mp_atan2(_cimg_math_parser& mp) { + return std::atan2(_mp_arg(2),_mp_arg(3)); + } + + static double mp_avg(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i>(unsigned int)_mp_arg(3)); + } + + static double mp_bitwise_xor(_cimg_math_parser& mp) { + return (double)((longT)_mp_arg(2) ^ (longT)_mp_arg(3)); + } + + static double mp_bool(_cimg_math_parser& mp) { + return (double)(bool)_mp_arg(2); + } + + static double mp_break(_cimg_math_parser& mp) { + mp.break_type = 1; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_breakpoint(_cimg_math_parser& mp) { + cimg_abort_init; + cimg_abort_test; + cimg::unused(mp); + return cimg::type::nan(); + } + +#ifdef cimg_mp_func_run + static double mp_run(_cimg_math_parser& mp) { + const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2; + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(3 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + CImg(1,1,1,1,0).move_to(_str); + CImg str = _str>'x'; + cimg_mp_func_run(str._data); + return cimg::type::nan(); + } +#endif + + static double mp_cbrt(_cimg_math_parser& mp) { + return cimg::cbrt(_mp_arg(2)); + } + + static double mp_ceil(_cimg_math_parser& mp) { + return std::ceil(_mp_arg(2)); + } + + static double mp_complex_abs(_cimg_math_parser& mp) { + return cimg::_hypot(_mp_arg(2),_mp_arg(3)); + } + + static double mp_complex_conj(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = real; + ptrd[1] = -imag; + return cimg::type::nan(); + } + + static double mp_complex_div_sv(_cimg_math_parser& mp) { + const double + *ptr2 = &_mp_arg(3) + 1, + r1 = _mp_arg(2), + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = r1*r2/denom; + *ptrd = -r1*i2/denom; + return cimg::type::nan(); + } + + static double mp_complex_div_vv(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = (r1*r2 + i1*i2)/denom; + *ptrd = (r2*i1 - r1*i2)/denom; + return cimg::type::nan(); + } + + static double mp_complex_exp(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), exp_real = std::exp(real); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = exp_real*std::cos(imag); + ptrd[1] = exp_real*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_log(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = 0.5*std::log(real*real + imag*imag); + ptrd[1] = std::atan2(imag,real); + return cimg::type::nan(); + } + + static double mp_complex_mul(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + *(ptrd++) = r1*r2 - i1*i2; + *(ptrd++) = r1*i2 + r2*i1; + return cimg::type::nan(); + } + + static void _mp_complex_pow(const double r1, const double i1, + const double r2, const double i2, + double *ptrd) { + double ro, io; + if (cimg::abs(i2)<1e-15) { // Exponent is real + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) { + if (cimg::abs(r2)<1e-15) { ro = 1; io = 0; } + else ro = io = 0; + } else { + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2), + phio = r2*phi1; + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + } else { // Exponent is complex + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) ro = io = 0; + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2)*std::exp(-i2*phi1), + phio = r2*phi1 + 0.5*i2*std::log(mod1_2); + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + *(ptrd++) = ro; + *ptrd = io; + } + + static double mp_complex_pow_ss(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_sv(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vs(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vv(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_cos(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::cos(real)*std::cosh(imag); + ptrd[1] = -std::sin(real)*std::sinh(imag); + return cimg::type::nan(); + } + + static double mp_complex_sin(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sin(real)*std::cosh(imag); + ptrd[1] = std::cos(real)*std::sinh(imag); + return cimg::type::nan(); + } + + static double mp_complex_tan(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), denom = std::cos(2*real) + std::cosh(2*imag); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sin(2*real)/denom; + ptrd[1] = std::sinh(2*imag)/denom; + return cimg::type::nan(); + } + + static double mp_complex_cosh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::cosh(real)*std::cos(imag); + ptrd[1] = std::sinh(real)*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_sinh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sinh(real)*std::cos(imag); + ptrd[1] = std::cosh(real)*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_tanh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), denom = std::cosh(2*real) + std::cos(2*imag); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sinh(2*real)/denom; + ptrd[1] = std::sin(2*imag)/denom; + return cimg::type::nan(); + } + + static double mp_continue(_cimg_math_parser& mp) { + mp.break_type = 2; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_convolve(_cimg_math_parser &mp) { + return _mp_correlate(mp,true); + } + + static double mp_copy(_cimg_math_parser& mp) { + return _mp_arg(2); + } + + static double mp_correlate(_cimg_math_parser &mp) { + return _mp_correlate(mp,false); + } + + static double _mp_correlate(_cimg_math_parser &mp, bool is_convolve) { + double *ptrd = &_mp_arg(1) + 1; + const double *const ptrA = &_mp_arg(2) + 1, *const ptrM = &_mp_arg(7) + 1; + const unsigned int + wA = (unsigned int)mp.opcode[3], + hA = (unsigned int)mp.opcode[4], + dA = (unsigned int)mp.opcode[5], + sA = (unsigned int)mp.opcode[6], + wM = (unsigned int)mp.opcode[8], + hM = (unsigned int)mp.opcode[9], + dM = (unsigned int)mp.opcode[10], + sM = (unsigned int)mp.opcode[11], + boundary_conditions = (unsigned int)_mp_arg(12), + channel_mode = (unsigned int)mp.opcode[14], + xcenter = (unsigned int)_mp_arg(15), + ycenter = (unsigned int)_mp_arg(16), + zcenter = (unsigned int)_mp_arg(17), + xstart = (unsigned int)mp.opcode[18], + ystart = (unsigned int)mp.opcode[19], + zstart = (unsigned int)mp.opcode[20], + xend = (unsigned int)mp.opcode[21], + yend = (unsigned int)mp.opcode[22], + zend = (unsigned int)mp.opcode[23]; + const bool + is_normalized = (bool)_mp_arg(13); + const float + xstride = (float)_mp_arg(24), + ystride = (float)_mp_arg(25), + zstride = (float)_mp_arg(26), + xdilation = (float)_mp_arg(27), + ydilation = (float)_mp_arg(28), + zdilation = (float)_mp_arg(29); + CImg res; + if (is_convolve) res = CImg(ptrA,wA,hA,dA,sA,true). + get_convolve(CImg(ptrM,wM,hM,dM,sM,true), + boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter, + xstart,ystart,zstart, + xend,yend,zend, + xstride,ystride,zstride, + xdilation,ydilation,zdilation); + else res = CImg(ptrA,wA,hA,dA,sA,true). + get_correlate(CImg(ptrM,wM,hM,dM,sM,true), + boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter, + xstart,ystart,zstart, + xend,yend,zend, + xstride,ystride,zstride, + xdilation,ydilation,zdilation); + CImg(ptrd,res._width,res._height,res._depth,res._spectrum,true) = res; + return cimg::type::nan(); + } + + static double mp_cos(_cimg_math_parser& mp) { + return std::cos(_mp_arg(2)); + } + + static double mp_cosh(_cimg_math_parser& mp) { + return std::cosh(_mp_arg(2)); + } + + static double mp_critical(_cimg_math_parser& mp) { + const ulongT g_target = mp.opcode[1]; + cimg_pragma_openmp(critical(mp_critical)) + { + for (const CImg *const p_end = ++mp.p_code + mp.opcode[2]; + mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const unsigned int + dx = (unsigned int)mp.opcode[7], + dy = (unsigned int)mp.opcode[8], + dz = (unsigned int)mp.opcode[9], + dc = (unsigned int)mp.opcode[10]; + const unsigned int boundary_conditions = (unsigned int)_mp_arg(11); + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgin:mp.listin[ind]; + if (!img) std::memset(ptrd,0,dx*dy*dz*dc*sizeof(double)); + else CImg(ptrd,dx,dy,dz,dc,true) = img.get_crop(x,y,z,c, + x + dx - 1,y + dy - 1, + z + dz - 1,c + dc - 1, + boundary_conditions); + return cimg::type::nan(); + } + + static double mp_cross(_cimg_math_parser& mp) { + CImg + vout(&_mp_arg(1) + 1,1,3,1,1,true), + v1(&_mp_arg(2) + 1,1,3,1,1,true), + v2(&_mp_arg(3) + 1,1,3,1,1,true); + (vout = v1).cross(v2); + return cimg::type::nan(); + } + + static double mp_cut(_cimg_math_parser& mp) { + double val = _mp_arg(2), cmin = _mp_arg(3), cmax = _mp_arg(4); + return valcmax?cmax:val; + } + + static double mp_date(_cimg_math_parser& mp) { + const unsigned int + siz_out = (unsigned int)mp.opcode[2], + siz_arg1 = (unsigned int)mp.opcode[4], + siz_arg2 = (unsigned int)mp.opcode[6]; + double *ptr_out = &_mp_arg(1) + (siz_out?1:0); + const double + *ptr_arg1 = siz_arg1==~0U?0:&_mp_arg(3) + (siz_arg1?1:0), + *ptr_arg2 = siz_arg2==~0U?0:&_mp_arg(5) + 1; + + if (!ptr_arg2) { // No filename specified + if (!siz_arg1) return cimg::date((unsigned int)*ptr_arg1); + if (siz_arg1==~0U) for (unsigned int k = 0; k::nan(); + } + + // Filename specified. + CImg ss(siz_arg2 + 1); + cimg_forX(ss,i) ss[i] = (char)ptr_arg2[i]; + ss.back() = 0; + if (!siz_arg1) return cimg::fdate(ss,(unsigned int)*ptr_arg1); + for (unsigned int k = 0; k::nan(); + } + + static double mp_debug(_cimg_math_parser& mp) { + CImg expr(mp.opcode[2] - 4); + { + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + } + cimg::strellipsize(expr); + const ulongT g_target = mp.opcode[1]; + +#if cimg_use_openmp==0 + const unsigned int n_thread = 0; +#else + const unsigned int n_thread = omp_get_thread_num(); +#endif + cimg_pragma_openmp(critical(mp_debug)) + { + std::fprintf(cimg::output(), + "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c" + "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)mp.opcode[3],(unsigned int)g_target,mp.mem._width); + std::fflush(cimg::output()); + mp.debug_indent+=3; + } + const CImg *const p_end = ++mp.p_code + mp.opcode[3]; + CImg _op; + for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + + _op.assign(1,op._height - 1); + const ulongT *ptrs = op._data + 1; + for (ulongT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd mem[%u] = %.17g", + (void*)&mp,n_thread,mp.debug_indent,' ', + (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(), + (unsigned int)target,mp.mem[target]); + std::fflush(cimg::output()); + } + } + cimg_pragma_openmp(critical(mp_debug)) + { + mp.debug_indent-=3; + std::fprintf(cimg::output(), + "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c" + "End debugging expression '%s' -> mem[%u] = %.17g (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width); + std::fflush(cimg::output()); + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_decrement(_cimg_math_parser& mp) { + return _mp_arg(2) - 1; + } + + static double mp_det(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + return CImg(ptrs,k,k,1,1,true).det(); + } + + static double mp_diag(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2], siz = mp.opcode[2] - 3; + double *ptrd = &_mp_arg(1) + 1; + std::memset(ptrd,0,siz*siz*sizeof(double)); + for (unsigned int i = 3; i::nan(); + } + + static double mp_display_memory(_cimg_math_parser& mp) { + cimg::unused(mp); + std::fputc('\n',cimg::output()); + CImg title(128); + cimg_snprintf(title,title._width,"%s (%u)","[" cimg_appname "_math_parser] Memory snapshot",mp.mem._width); + mp.mem.display(title); + return cimg::type::nan(); + } + + static double mp_display(_cimg_math_parser& mp) { + const unsigned int + _siz = (unsigned int)mp.opcode[3], + siz = _siz?_siz:1; + const double *const ptr = &_mp_arg(1) + (_siz?1:0); + const int + w = (int)_mp_arg(4), + h = (int)_mp_arg(5), + d = (int)_mp_arg(6), + s = (int)_mp_arg(7); + CImg img; + if (w>0 && h>0 && d>0 && s>0) { + if ((unsigned int)w*h*d*s<=siz) img.assign(ptr,w,h,d,s,true); + else img.assign(ptr,siz).resize(w,h,d,s,-1); + } else img.assign(ptr,1,siz,1,1,true); + + CImg expr(mp.opcode[2] - 8); + const ulongT *ptrs = mp.opcode._data + 8; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + ((CImg::string("[" cimg_appname "_math_parser] ",false,true),expr)>'x').move_to(expr); + cimg::strellipsize(expr); + std::fputc('\n',cimg::output()); + img.display(expr._data); + return cimg::type::nan(); + } + + static double mp_div(_cimg_math_parser& mp) { + return _mp_arg(2)/_mp_arg(3); + } + + static double mp_dot(_cimg_math_parser& mp) { + const unsigned int siz = (unsigned int)mp.opcode[4]; + return CImg(&_mp_arg(2) + 1,1,siz,1,1,true). + dot(CImg(&_mp_arg(3) + 1,1,siz,1,1,true)); + } + + static double mp_do(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_body = ++mp.p_code, + *const p_cond = p_body + mp.opcode[3], + *const p_end = p_cond + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (mp.mem[mem_cond]); + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_draw(_cimg_math_parser& mp) { + const int x = (int)_mp_arg(4), y = (int)_mp_arg(5), z = (int)_mp_arg(6), c = (int)_mp_arg(7); + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + unsigned int + dx = (unsigned int)mp.opcode[8], + dy = (unsigned int)mp.opcode[9], + dz = (unsigned int)mp.opcode[10], + dc = (unsigned int)mp.opcode[11]; + dx = dx==~0U?img._width:(unsigned int)_mp_arg(8); + dy = dy==~0U?img._height:(unsigned int)_mp_arg(9); + dz = dz==~0U?img._depth:(unsigned int)_mp_arg(10); + dc = dc==~0U?img._spectrum:(unsigned int)_mp_arg(11); + + const ulongT sizS = mp.opcode[2]; + if (sizS<(ulongT)dx*dy*dz*dc) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': " + "Sprite dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + CImg S(&_mp_arg(1) + 1,dx,dy,dz,dc,true); + const float opacity = (float)_mp_arg(12); + + if (img._data) { + if (mp.opcode[13]!=~0U) { // Opacity mask specified + const ulongT sizM = mp.opcode[14]; + if (sizM<(ulongT)dx*dy*dz) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': " + "Mask dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + const CImg M(&_mp_arg(13) + 1,dx,dy,dz,(unsigned int)(sizM/(dx*dy*dz)),true); + img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(15)); + } else img.draw_image(x,y,z,c,S,opacity); + } + return cimg::type::nan(); + } + + static double mp_echo(_cimg_math_parser& mp) { + const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2; + if (!nb_args) { std::fputc('\n',cimg::output()); return cimg::type::nan(); } // No arguments + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(3 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + CImg(1,1,1,1,0).move_to(_str); + const CImg str = _str>'x'; + std::fprintf(cimg::output(),"\n%s",str._data); + return cimg::type::nan(); + } + + static double mp_ellipse(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + CImg color(img._spectrum,1,1,1,0); + bool is_invalid_arguments = false, is_outlined = false; + float r1 = 0, r2 = 0, angle = 0, opacity = 1; + unsigned int i = 4, pattern = ~0U; + int x0 = 0, y0 = 0; + if (i>=i_end) is_invalid_arguments = true; + else { + x0 = (int)cimg::round(_mp_arg(i++)); + if (i>=i_end) is_invalid_arguments = true; + else { + y0 = (int)cimg::round(_mp_arg(i++)); + if (i>=i_end) is_invalid_arguments = true; + else { + r1 = (float)_mp_arg(i++); + if (i>=i_end) r2 = r1; + else { + r2 = (float)_mp_arg(i++); + if (i args(i_end - 4); + cimg_forX(args,k) args[k] = _mp_arg(4 + k); + if (ind==~0U) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'ellipse()': " + "Invalid arguments '%s'. ", + mp.imgin.pixel_type(),args.value_string()._data); + else + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'ellipse()': " + "Invalid arguments '#%u%s%s'. ", + mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data); + } + return cimg::type::nan(); + } + + static double mp_eq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)==_mp_arg(3)); + } + + static double mp_erf(_cimg_math_parser& mp) { + return std::erf(_mp_arg(2)); + } + + static double mp_erfinv(_cimg_math_parser& mp) { + return cimg::erfinv(_mp_arg(2)); + } + + static double mp_exp(_cimg_math_parser& mp) { + return std::exp(_mp_arg(2)); + } + + static double mp_expr(_cimg_math_parser& mp) { + const unsigned int + sizs = (unsigned int)mp.opcode[3], + w = (unsigned int)mp.opcode[4], + h = (unsigned int)mp.opcode[5], + d = (unsigned int)mp.opcode[6], + s = (unsigned int)mp.opcode[7], + sizd = w*h*d*s; + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1); + CImg ss(sizs + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + if (!sizd) return CImg(w,h,d,s,0).eval(ss,0,0,0,0,&mp.listin,&mp.listout); // Scalar result + CImg(++ptrd,w,h,d,s,true) = CImg(w,h,d,s,0).fill(ss,true,true,&mp.listin,&mp.listout); + return cimg::type::nan(); + } + + static double mp_eye(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int k = (unsigned int)mp.opcode[2]; + CImg(ptrd,k,k,1,1,true).identity_matrix(); + return cimg::type::nan(); + } + + static double mp_f2ui(_cimg_math_parser& mp) { + return (double)cimg::float2uint((float)_mp_arg(2)); + } + + static double mp_factorial(_cimg_math_parser& mp) { + return cimg::factorial((int)_mp_arg(2)); + } + + static double mp_fibonacci(_cimg_math_parser& mp) { + return cimg::fibonacci((int)_mp_arg(2)); + } + + static double mp_fill(_cimg_math_parser& mp) { + unsigned int siz = (unsigned int)mp.opcode[2]; + double + *ptrd = &_mp_arg(1), + *const ptrc = mp.opcode[3]!=~0U?&_mp_arg(3):0, + *const ptrs = &_mp_arg(4); + if (siz) ++ptrd; else ++siz; // Fill vector-valued slot + const CImg + *const p_body = ++mp.p_code, + *const p_end = p_body + mp.opcode[5]; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + unsigned int it = 0; + if (ptrc) { // Version with loop variable (3 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + else ptrd[it] = *ptrs; + ++it; + } + *ptrc = (double)it; + } else // Version without loop variable (2 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + else ptrd[it] = *ptrs; + ++it; + } + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return *ptrd; + } + + static double mp_find(_cimg_math_parser& mp) { + const int _step = (int)_mp_arg(6), step = _step?_step:-1; + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):step>0?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const double + *const ptrb = &_mp_arg(2) + 1, + *const ptre = ptrb + siz, + val = _mp_arg(4), + *ptr = ptrb + ind; + + // Forward search + if (step>0) { + while (ptr=ptre?-1.:(double)(ptr - ptrb); + } + + // Backward search. + while (ptr>=ptrb && *ptr!=val) ptr+=step; + return ptr0?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const double + *const ptr1b = &_mp_arg(2) + 1, + *const ptr1e = ptr1b + siz1, + *const ptr2b = &_mp_arg(4) + 1, + *const ptr2e = ptr2b + siz2, + *ptr1 = ptr1b + ind, + *p1 = 0, + *p2 = 0; + + // Forward search. + if (step>0) { + do { + while (ptr1=ptr1e) return -1.; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b && *ptr1!=*ptr2b) ptr1+=step; + if (ptr1=ptr1b); + return p2 + *const p_init = ++mp.p_code, + *const p_cond = p_init + mp.opcode[4], + *const p_body = p_cond + mp.opcode[5], + *const p_post = p_body + mp.opcode[6], + *const p_end = p_post + mp.opcode[7]; + const unsigned int vsiz = (unsigned int)mp.opcode[2]; + bool is_cond = false; + if (mp.opcode[8]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[9]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + for (mp.p_code = p_init; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + + if (!mp.break_type) do { + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) { + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + + for (mp.p_code = p_post; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_fsize(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const ulongT siz = (ulongT)mp.opcode[3]; + CImg ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::fsize(ss); + } + + static double mp_g(_cimg_math_parser& mp) { + cimg::unused(mp); + return cimg::grand(&mp.rng); + } + + static double mp_gauss(_cimg_math_parser& mp) { + const double x = _mp_arg(2), s = _mp_arg(3); + return std::exp(-x*x/(2*s*s))/(_mp_arg(4)?std::sqrt(2*s*s*cimg::PI):1); + } + +#ifdef cimg_mp_func_get + static double mp_get(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1); + const unsigned int + sizs = (unsigned int)mp.opcode[3], + sizd = (unsigned int)mp.opcode[4]; + const bool to_string = (bool)mp.opcode[5]; + CImg ss(sizs + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + if (sizd) cimg_mp_func_get(ptrd + 1,sizd,to_string,ss._data); + else cimg_mp_func_get(ptrd,0,to_string,ss._data); + return cimg::type::nan(); + } +#endif + + static double mp_gcd(_cimg_math_parser& mp) { + return cimg::gcd((long)_mp_arg(2),(long)_mp_arg(3)); + } + +#ifdef cimg_mp_func_name + static double mp_name(_cimg_math_parser& mp) { + double *const ptr = &_mp_arg(1) + 1; + const unsigned int siz = (unsigned int)mp.opcode[3]; + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind==~0U) std::memset(ptr,0,siz*sizeof(double)); + else { + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + cimg_mp_func_name(ind,ptr,siz); + } + return cimg::type::nan(); + } +#endif + + static double mp_gt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>_mp_arg(3)); + } + + static double mp_gte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>=_mp_arg(3)); + } + + static double mp_i(_cimg_math_parser& mp) { + return (double)mp.imgin.atXYZC((int)mp.mem[_cimg_mp_slot_x],(int)mp.mem[_cimg_mp_slot_y], + (int)mp.mem[_cimg_mp_slot_z],(int)mp.mem[_cimg_mp_slot_c],(T)0); + } + + static double mp_if(_cimg_math_parser& mp) { + const bool is_cond = (bool)_mp_arg(2); + const ulongT + mem_left = mp.opcode[3], + mem_right = mp.opcode[4]; + const CImg + *const p_right = ++mp.p_code + mp.opcode[5], + *const p_end = p_right + mp.opcode[6]; + const unsigned int vtarget = (unsigned int)mp.opcode[1], vsiz = (unsigned int)mp.opcode[7]; + if (is_cond) for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + else for (mp.p_code = p_right; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.p_code==mp.p_break) --mp.p_code; + else mp.p_code = p_end - 1; + if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[is_cond?mem_left:mem_right] + 1,sizeof(double)*vsiz); + return mp.mem[is_cond?mem_left:mem_right]; + } + + static double mp_image_d(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.depth(); + } + + static double mp_image_display(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + CImg title(256); + std::fputc('\n',cimg::output()); + cimg_snprintf(title,title._width,"[ Image #%u ]",ind); + img.display(title); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_h(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.height(); + } + + static double mp_image_median(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.median(); + } + + static double mp_image_norm(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.magnitude(); + } + + static double mp_image_print(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + CImg title(256); + std::fputc('\n',cimg::output()); + cimg_snprintf(title,title._width,"[ Image #%u ]",ind); + img.print(title); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_resize(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + const double + _w = mp.opcode[3]==~0U?-100:_mp_arg(3), + _h = mp.opcode[4]==~0U?-100:_mp_arg(4), + _d = mp.opcode[5]==~0U?-100:_mp_arg(5), + _s = mp.opcode[6]==~0U?-100:_mp_arg(6); + const unsigned int + w = (unsigned int)(_w>=0?_w:-_w*img.width()/100), + h = (unsigned int)(_h>=0?_h:-_h*img.height()/100), + d = (unsigned int)(_d>=0?_d:-_d*img.depth()/100), + s = (unsigned int)(_s>=0?_s:-_s*img.spectrum()/100), + interp = (int)_mp_arg(7); + if (mp.is_fill && img._data==mp.imgout._data) { + cimg::mutex(6,0); + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'resize()': " + "Cannot both fill and resize image (%u,%u,%u,%u) " + "to new dimensions (%u,%u,%u,%u).", + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,w,h,d,s); + } + const unsigned int + boundary = (int)_mp_arg(8); + const float + cx = (float)_mp_arg(9), + cy = (float)_mp_arg(10), + cz = (float)_mp_arg(11), + cc = (float)_mp_arg(12); + img.resize(w,h,d,s,interp,boundary,cx,cy,cz,cc); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_s(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.spectrum(); + } + + static double mp_image_sort(_cimg_math_parser& mp) { + const bool is_increasing = (bool)_mp_arg(3); + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()), + axis = (unsigned int)_mp_arg(4); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + img.sort(is_increasing, + axis==0 || axis=='x'?'x': + axis==1 || axis=='y'?'y': + axis==2 || axis=='z'?'z': + axis==3 || axis=='c'?'c':0); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_stats(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind==~0U) CImg(ptrd,14,1,1,1,true) = mp.imgout.get_stats(); + else { + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg(ptrd,14,1,1,1,true) = mp.listout[ind].get_stats(); + } + return cimg::type::nan(); + } + + static double mp_image_w(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width(); + } + + static double mp_image_wh(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height(); + } + + static double mp_image_whd(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height()*img.depth(); + } + + static double mp_image_whds(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height()*img.depth()*img.spectrum(); + } + + static double mp_increment(_cimg_math_parser& mp) { + return _mp_arg(2) + 1; + } + + static double mp_inrange(_cimg_math_parser& mp) { + const unsigned int sizd = (unsigned int)mp.opcode[2]; + const bool + include_m = (bool)_mp_arg(9), + include_M = (bool)_mp_arg(10); + if (!sizd) { // Scalar result + const double val = _mp_arg(3); + const double m = _mp_arg(5), M = _mp_arg(7); + if (M>=m) return (double)((include_m?(val>=m):(val>m)) && (include_M?(val<=M):(val=M):(val>M)) && (include_m?(val<=m):(val=m) + ptrd[k] = (double)((include_m?(val>=m):(val>m)) && (include_M?(val<=M):(val=M):(val>M)) && (include_m?(val<=m):(val::nan(); + } + + static double mp_int(_cimg_math_parser& mp) { + return (double)(longT)_mp_arg(2); + } + + static double mp_ioff(_cimg_math_parser& mp) { + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3); + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off>=0 && off ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::is_directory(ss); + } + + static double mp_isin(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = _mp_arg(3); + for (unsigned int i = 4; i::is_inf(_mp_arg(2)); + } + + static double mp_isint(_cimg_math_parser& mp) { + return (double)((double)(longT)_mp_arg(2)==_mp_arg(2)); + } + + static double mp_isfile(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const ulongT siz = (ulongT)mp.opcode[3]; + CImg ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::is_file(ss); + } + + static double mp_isnan(_cimg_math_parser& mp) { + return (double)cimg::type::is_nan(_mp_arg(2)); + } + + static double mp_ixyzc(_cimg_math_parser& mp) { + const unsigned int + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.imgin; + const double + x = _mp_arg(2), y = _mp_arg(3), + z = _mp_arg(4), c = _mp_arg(5); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx &img = mp.imgin; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), + z = oz + _mp_arg(4), c = oc + _mp_arg(5); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx vals(i_end - 4); + double *p = vals.data(); + for (unsigned int i = 4; i &img = mp.listin[indi]; + const int _step = (int)_mp_arg(5), step = _step?_step:-1; + const ulongT siz = (ulongT)img.size(); + longT ind = (longT)(mp.opcode[4]!=_cimg_mp_slot_nan?_mp_arg(4):step>0?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const T + *const ptrb = img.data(), + *const ptre = img.end(), + *ptr = ptrb + ind; + const double val = _mp_arg(3); + + // Forward search + if (step>0) { + while (ptr=ptre?-1.:(double)(ptr - ptrb); + } + + // Backward search. + while (ptr>=ptrb && (double)*ptr!=val) ptr+=step; + return ptr &img = mp.listin[indi]; + const int _step = (bool)_mp_arg(6), step = _step?_step:-1; + const ulongT + siz1 = (ulongT)img.size(), + siz2 = (ulongT)mp.opcode[4]; + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):step>0?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const T + *const ptr1b = img.data(), + *const ptr1e = ptr1b + siz1, + *ptr1 = ptr1b + ind, + *p1 = 0; + const double + *const ptr2b = &_mp_arg(3) + 1, + *const ptr2e = ptr2b + siz2, + *p2 = 0; + + // Forward search. + if (step>0) { + do { + while (ptr1=ptr1e) return -1.; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b && *ptr1!=*ptr2b) ptr1+=step; + if (ptr1=ptr1b); + return p2 &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.listin[ind]; + const double + x = _mp_arg(3), y = _mp_arg(4), + z = _mp_arg(5), c = _mp_arg(6); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), + z = oz + _mp_arg(5), c = oc + _mp_arg(6); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx::vector(mp.listin[ind].median()).move_to(mp.list_median[ind]); + return *mp.list_median[ind]; + } + + static double mp_list_norm(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + if (!mp.list_norm) mp.list_norm.assign(mp.listin._width); + if (!mp.list_norm[ind]) CImg::vector(mp.listin[ind].magnitude()).move_to(mp.list_norm[ind]); + return *mp.list_norm[ind]; + } + + static double mp_list_set_ioff(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), y = (int)_mp_arg(4), + z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Ixyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_set_Joff_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Jxyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_spectrum(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._spectrum; + } + + static double mp_list_stats(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + k = (unsigned int)mp.opcode[3]; + if (!mp.list_stats) mp.list_stats.assign(mp.listin._width); + if (!mp.list_stats[ind]) mp.list_stats[ind].assign(1,14,1,1,0).fill(mp.listin[ind].get_stats(),false); + return mp.list_stats(ind,k); + } + + static double mp_list_wh(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height; + } + + static double mp_list_whd(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth; + } + + static double mp_list_whds(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth*mp.listin[ind]._spectrum; + } + + static double mp_list_width(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width; + } + + static double mp_list_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4), + vsiz = (unsigned int)mp.opcode[5]; + const CImg &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_list_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7), + vsiz = (unsigned int)mp.opcode[8]; + const CImg &img = mp.listin[ind]; + const double x = _mp_arg(3), y = _mp_arg(4), z = _mp_arg(5); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_list_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4), + vsiz = (unsigned int)mp.opcode[5]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], oz = (int)mp.mem[_cimg_mp_slot_z]; + const CImg &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_list_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7), + vsiz = (unsigned int)mp.opcode[8]; + const CImg &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), z = oz + _mp_arg(5); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_log(_cimg_math_parser& mp) { + return std::log(_mp_arg(2)); + } + + static double mp_log10(_cimg_math_parser& mp) { + return std::log10(_mp_arg(2)); + } + + static double mp_log2(_cimg_math_parser& mp) { + return cimg::log2(_mp_arg(2)); + } + + static double mp_logical_and(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (!val_left) { mp.p_code = p_end - 1; return 0; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_logical_not(_cimg_math_parser& mp) { + return (double)!_mp_arg(2); + } + + static double mp_logical_or(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (val_left) { mp.p_code = p_end - 1; return 1; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_lowercase(_cimg_math_parser& mp) { + return cimg::lowercase(_mp_arg(2)); + } + + static double mp_lt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<_mp_arg(3)); + } + + static double mp_lte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<=_mp_arg(3)); + } + + static double mp_matrix_eig(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + CImg val, vec; + CImg(ptr1,k,k,1,1,true).symmetric_eigen(val,vec); + CImg(ptrd,1,k,1,1,true) = val; + CImg(ptrd + k,k,k,1,1,true) = vec.get_transpose(); + return cimg::type::nan(); + } + + static double mp_matrix_invert(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptr1 = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + const bool use_LU = (bool)_mp_arg(4); + CImg(ptrd,k,k,1,1,true) = CImg(ptr1,k,k,1,1,true).get_invert(use_LU); + return cimg::type::nan(); + } + + static double mp_matrix_mul(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr1,l,k,1,1,true)*CImg(ptr2,m,l,1,1,true); + return cimg::type::nan(); + } + + static double mp_matrix_pseudoinvert(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + const bool use_LU = (bool)_mp_arg(5); + CImg(ptrd,l,k,1,1,true) = CImg(ptr1,k,l,1,1,true).get_pseudoinvert(use_LU); + return cimg::type::nan(); + } + + static double mp_matrix_svd(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg U, S, V; + CImg(ptr1,k,l,1,1,true).SVD(U,S,V); + CImg(ptrd,k,l,1,1,true) = U; + CImg(ptrd + k*l,1,k,1,1,true) = S; + CImg(ptrd + k*l + k,k,k,1,1,true) = V; + return cimg::type::nan(); + } + + static double mp_max(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; iabsval) { val = _val; absval = _absval; } + } + return val; + } + + static double* _mp_memcopy_double(_cimg_math_parser& mp, const unsigned int ind, const ulongT *const p_ref, + const longT siz, const long inc) { + const longT + off = *p_ref?p_ref[1] + (longT)mp.mem[(longT)p_ref[2]] + 1:ind, + eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=mp.mem.width()) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds variable pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %u).", + mp.imgin.pixel_type(),siz,inc,off,eoff,mp.mem._width - 1); + return &mp.mem[off]; + } + + static float* _mp_memcopy_float(_cimg_math_parser& mp, const ulongT *const p_ref, + const longT siz, const long inc, const bool is_out) { + const unsigned ind = (unsigned int)p_ref[1]; + const CImg &img = is_out? + (ind==~0U?mp.imgout:mp.listout[cimg::mod((int)mp.mem[ind],mp.listout.width())]): + (ind==~0U?mp.imgin:mp.listin[cimg::mod((int)mp.mem[ind],mp.listin.width())]); + const bool is_relative = (bool)p_ref[2]; + int ox, oy, oz, oc; + longT off = 0; + if (is_relative) { + ox = (int)mp.mem[_cimg_mp_slot_x]; + oy = (int)mp.mem[_cimg_mp_slot_y]; + oz = (int)mp.mem[_cimg_mp_slot_z]; + oc = (int)mp.mem[_cimg_mp_slot_c]; + off = img.offset(ox,oy,oz,oc); + } + if ((*p_ref)%2) { + const int + x = (int)mp.mem[p_ref[3]], + y = (int)mp.mem[p_ref[4]], + z = (int)mp.mem[p_ref[5]], + c = *p_ref==5?0:(int)mp.mem[p_ref[6]]; + off+=img.offset(x,y,z,c); + } else off+=(longT)mp.mem[p_ref[3]]; + const longT eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=(longT)img.size()) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds image pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %lu).", + mp.imgin.pixel_type(),siz,inc,off,eoff,img.size() - 1); + return (float*)&img[off]; + } + + static double mp_memcopy(_cimg_math_parser& mp) { + longT siz = (longT)_mp_arg(4); + const longT inc_d = (longT)_mp_arg(5), inc_s = (longT)_mp_arg(6); + const float + _opacity = (float)_mp_arg(7), + opacity = (float)cimg::abs(_opacity), + omopacity = 1 - std::max(_opacity,0.f); + if (siz>0) { + const bool + is_doubled = mp.opcode[8]<=1, + is_doubles = mp.opcode[15]<=1; + if (is_doubled && is_doubles) { // (double*) <- (double*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(double)); + else std::memmove(ptrd,ptrs,siz*sizeof(double)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,double) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } else if (is_doubled && !is_doubles) { // (double*) <- (float*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s,false); + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + _opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else if (!is_doubled && is_doubles) { // (float*) <- (double*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d,true); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (_opacity>=1) while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = (float)(omopacity**ptrd + opacity**ptrs); ptrd+=inc_d; ptrs+=inc_s; } + } else { // (float*) <- (float*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d,true); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s,false); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(float)); + else std::memmove(ptrd,ptrs,siz*sizeof(float)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,float) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } + } + return _mp_arg(1); + } + + static double mp_min(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i(ptrd,wS,wD,1,1,true) = CImg(ptrS,wS,hS,1,1,false). + project_matrix(CImg(ptrD,wD,hS,1,1,true),method,max_iter,max_residual); + return cimg::type::nan(); + } + + static double mp_mul(_cimg_math_parser& mp) { + return _mp_arg(2)*_mp_arg(3); + } + + static double mp_mul2(_cimg_math_parser& mp) { + return _mp_arg(2)*_mp_arg(3)*_mp_arg(4); + } + + static double mp_neq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)!=_mp_arg(3)); + } + + static double mp_norm0(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + switch (i_end - 3) { + case 1 : return _mp_arg(3)!=0; + case 2 : return (_mp_arg(3)!=0) + (_mp_arg(4)!=0); + } + double res = 0; + for (unsigned int i = 3; ires) res = val; + } + return res; + } + + static double mp_normp(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + if (i_end==4) return cimg::abs(_mp_arg(3)); + const double p = (double)mp.opcode[3]; + double res = 0; + for (unsigned int i = 4; i0?res:0.; + } + + static double mp_permutations(_cimg_math_parser& mp) { + return cimg::permutations((int)_mp_arg(2),(int)_mp_arg(3),(bool)_mp_arg(4)); + } + + static double mp_polygon(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + bool is_invalid_arguments = i_end<=4, is_outlined = false; + if (!is_invalid_arguments) { + int nbv = (int)_mp_arg(4); + if (!nbv) is_invalid_arguments = true; + else { + if (nbv<0) { nbv = -nbv; is_outlined = true; } + CImg points(nbv,2,1,1,0); + CImg color(img._spectrum,1,1,1,0); + float opacity = 1; + unsigned int i = 5, pattern=~0U; + cimg_foroff(points,k) if (i args(i_end - 4); + cimg_forX(args,k) args[k] = _mp_arg(4 + k); + if (ind==~0U) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': " + "Invalid arguments '%s'. ", + mp.imgin.pixel_type(),args.value_string()._data); + else + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': " + "Invalid arguments '#%u%s%s'. ", + mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data); + } + return cimg::type::nan(); + } + + static double mp_pow(_cimg_math_parser& mp) { + const double v = _mp_arg(2), p = _mp_arg(3); + return std::pow(v,p); + } + + static double mp_pow0_25(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return std::sqrt(std::sqrt(val)); + } + + static double mp_pow3(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val; + } + + static double mp_pow4(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val*val; + } + + static double mp_print(_cimg_math_parser& mp) { + const double val = _mp_arg(1); + const bool print_char = (bool)mp.opcode[3]; + cimg_pragma_openmp(critical(mp_print)) + { + CImg _expr(mp.opcode[2] - 4); + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(_expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(_expr); + cimg::mutex(6); + if (print_char) + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = %.17g = '%c'", + _expr._data,val,(int)val); + else + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = %.17g", + _expr._data,val); + std::fflush(cimg::output()); + cimg::mutex(6,0); + } + return val; + } + + static double mp_prod(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i + *const p_body = ++mp.p_code, + *const p_end = p_body + mp.opcode[4]; + + if (nb_it>0) { + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + double it = 0; + if (ptrc) { // Version with loop variable (3 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + ++it; + } + *ptrc = it; + } else // Version without loop variable (2 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + ++it; + } + mp.break_type = _break_type; + } + + mp.p_code = p_end - 1; + return *ptrs; + } + + static double mp_rol(_cimg_math_parser& mp) { + return cimg::rol(_mp_arg(2),(unsigned int)_mp_arg(3)); + } + + static double mp_ror(_cimg_math_parser& mp) { + return cimg::ror(_mp_arg(2),(unsigned int)_mp_arg(3)); + } + + static double mp_rot2d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float + theta = (float)_mp_arg(2)*cimg::PI/180, + ca = std::cos(theta), + sa = std::sin(theta); + *(ptrd++) = ca; + *(ptrd++) = -sa; + *(ptrd++) = sa; + *ptrd = ca; + return cimg::type::nan(); + } + + static double mp_rot3d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5); + CImg(ptrd,3,3,1,1,true) = CImg::rotation_matrix(x,y,z,theta); + return cimg::type::nan(); + } + + static double mp_round(_cimg_math_parser& mp) { + return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4)); + } + + static double mp_self_add(_cimg_math_parser& mp) { + return _mp_arg(1)+=_mp_arg(2); + } + + static double mp_self_bitwise_and(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val & (longT)_mp_arg(2)); + } + + static double mp_self_bitwise_left_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val<<(unsigned int)_mp_arg(2)); + } + + static double mp_self_bitwise_or(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val | (longT)_mp_arg(2)); + } + + static double mp_self_bitwise_right_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val>>(unsigned int)_mp_arg(2)); + } + + static double mp_self_decrement(_cimg_math_parser& mp) { + return --_mp_arg(1); + } + + static double mp_self_increment(_cimg_math_parser& mp) { + return ++_mp_arg(1); + } + + static double mp_self_map_vector_s(_cimg_math_parser& mp) { // Vector += scalar + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2]; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode[2] = mp.opcode[4]; // Scalar argument + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1]; + while (siz-->0) { target = ptrd++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_map_vector_v(_cimg_math_parser& mp) { // Vector += vector + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1], &argument = mp.opcode[2]; + while (siz-->0) { target = ptrd++; argument = ptrs++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_mul(_cimg_math_parser& mp) { + return _mp_arg(1)*=_mp_arg(2); + } + + static double mp_self_div(_cimg_math_parser& mp) { + return _mp_arg(1)/=_mp_arg(2); + } + + static double mp_self_modulo(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = cimg::mod(val,_mp_arg(2)); + } + + static double mp_self_pow(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = std::pow(val,_mp_arg(2)); + } + + static double mp_self_sub(_cimg_math_parser& mp) { + return _mp_arg(1)-=_mp_arg(2); + } + + static double mp_set_ioff(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + x = (int)_mp_arg(2), y = (int)_mp_arg(3), + z = (int)_mp_arg(4), c = (int)_mp_arg(5); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Ixyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_set_Joff_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Jxyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_shift(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int siz = (unsigned int)mp.opcode[3]; + const int + shift = (int)_mp_arg(4), + boundary_conditions = (int)_mp_arg(5); + CImg(ptrd,siz,1,1,1,true) = CImg(ptrs,siz,1,1,1,true).shift(shift,0,0,0,boundary_conditions); + return cimg::type::nan(); + } + + static double mp_sign(_cimg_math_parser& mp) { + return cimg::sign(_mp_arg(2)); + } + + static double mp_sin(_cimg_math_parser& mp) { + return std::sin(_mp_arg(2)); + } + + static double mp_sinc(_cimg_math_parser& mp) { + return cimg::sinc(_mp_arg(2)); + } + + static double mp_sinh(_cimg_math_parser& mp) { + return std::sinh(_mp_arg(2)); + } + + static double mp_solve(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr2,m,l,1,1,false).solve(CImg(ptr1,k,l,1,1,true)); + return cimg::type::nan(); + } + + static double mp_sort(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const bool is_increasing = (bool)_mp_arg(4); + const unsigned int + siz = (unsigned int)mp.opcode[3], + nb_elts = mp.opcode[5]==~0U?siz:(unsigned int)_mp_arg(5), + siz_elt = (unsigned int)_mp_arg(6); + const ulongT sn = siz_elt*nb_elts; + if (sn>siz || siz_elt<1) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'sort()': " + "Arguments 'nb_elts=%g' and 'siz_elt=%g' are invalid " + "for sorting a vector of size %u.", + mp.imgin.pixel_type(),_mp_arg(5),_mp_arg(6),siz); + CImg(ptrd,siz_elt,nb_elts,1,1,true) = CImg(ptrs,siz_elt,nb_elts,1,1,true). + get_sort(is_increasing,siz_elt>1?'y':0); + if (sn(ptrd + sn,siz - sn,1,1,1,true) = CImg(ptrs + sn,siz - sn,1,1,1,true); + return cimg::type::nan(); + } + + static double mp_sqr(_cimg_math_parser& mp) { + return cimg::sqr(_mp_arg(2)); + } + + static double mp_sqrt(_cimg_math_parser& mp) { + return std::sqrt(_mp_arg(2)); + } + + static double mp_srand(_cimg_math_parser& mp) { + mp.rng = (cimg_uint64)_mp_arg(2); + return cimg::type::nan(); + } + + static double mp_srand0(_cimg_math_parser& mp) { + cimg::srand(&mp.rng); + +#if cimg_use_openmp!=0 + mp.rng+=omp_get_thread_num(); +#endif + return cimg::type::nan(); + } + + static double mp_std(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i0) mp.mem[ptrd++] = (double)*(ptrs++); + return cimg::type::nan(); + } + +#ifdef cimg_mp_func_store + static double mp_store(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2), + *ptr2 = &_mp_arg(4) + 1; + const unsigned int + siz1 = (unsigned int)mp.opcode[3], + siz2 = (unsigned int)mp.opcode[5]; + const int + w = (int)_mp_arg(6), + h = (int)_mp_arg(7), + d = (int)_mp_arg(8), + s = (int)_mp_arg(9); + + const bool is_compressed = (bool)_mp_arg(10); + if (w<0 || h<0 || d<0 || s<0) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'store()': " + "Specified image dimensions (%d,%d,%d,%d) are invalid.", + pixel_type(),w,h,d,s); + CImg ss(siz2 + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptr2[i]; + ss.back() = 0; + if (siz1) cimg_mp_func_store(ptr1 + 1,siz1, + (unsigned int)w,(unsigned int)h,(unsigned int)d,(unsigned int)s, + is_compressed,ss._data); + else cimg_mp_func_store(ptr1,1,(unsigned int)w,(unsigned int)h,(unsigned int)d,(unsigned int)s, + is_compressed,ss._data); + return cimg::type::nan(); + } +#endif + + static double mp_stov(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2); + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)_mp_arg(4); + const bool is_strict = (bool)_mp_arg(5); + double val = cimg::type::nan(); + if (ind<0 || ind>=(longT)siz) return val; + if (!siz) return *ptrs>='0' && *ptrs<='9'?*ptrs - '0':val; + + CImg ss(siz + 1 - ind); + ptrs+=1 + ind; + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + + const char *s = ss._data; + while (*s && *s<=32) ++s; + const bool is_negative = *s=='-'; + if (is_negative || *s=='+') ++s; + int err = 0; + char sep; + + if (*s=='0' && (s[1]=='x' || s[1]=='X') && s[2]>32) { // Hexadecimal number + unsigned int ival; + err = cimg_sscanf(s + 2,"%x%c",&ival,&sep); + if (err>0) val = (double)ival; + } else if (*s>32) { // Decimal number + err = cimg_sscanf(s,"%lf%c",&val,&sep); +#if cimg_OS==2 + // Check for +/-NaN and +/-inf as Microsoft's sscanf() version is not able + // to read those particular values. + if (!err && (*s=='i' || *s=='I' || *s=='n' || *s=='N')) { + if (!cimg::strncasecmp(s,"inf",3)) { val = cimg::type::inf(); err = 1 + (s[3]!=0); } + else if (!cimg::strncasecmp(s,"nan",3)) { val = cimg::type::nan(); err = 1 + (s[3]!=0); } + } +#endif + } + if (err<=0 || (is_strict && err!=1)) return cimg::type::nan(); + if (is_negative) val = -val; + return val; + } + + static double mp_string(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int nb_args = (unsigned int)(mp.opcode[3] - 3)/2; + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(4 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(4 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + const CImg str = _str>'x'; + const unsigned int sizd = std::min(str._width,(unsigned int)mp.opcode[2]); + std::memset(ptrd,0,mp.opcode[2]*sizeof(double)); + for (unsigned int k = 0; k::nan(); + } + + static double mp_sub(_cimg_math_parser& mp) { + return _mp_arg(2) - _mp_arg(3); + } + + static double mp_sum(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i(ptrs,k,k,1,1,true).trace(); + } + + static double mp_transpose(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg(ptrd,l,k,1,1,true) = CImg(ptrs,k,l,1,1,true).get_transpose(); + return cimg::type::nan(); + } + + static double mp_u(_cimg_math_parser& mp) { + return cimg::rand(_mp_arg(2),_mp_arg(3),&mp.rng); + } + + static double mp_ui2f(_cimg_math_parser& mp) { + return (double)cimg::uint2float((unsigned int)_mp_arg(2)); + } + + static double mp_uppercase(_cimg_math_parser& mp) { + return cimg::uppercase(_mp_arg(2)); + } + + static double mp_var(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i::nan(); + } + + static double mp_vector_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const longT + length = (longT)mp.opcode[3], + start = (longT)_mp_arg(4), + sublength = (longT)mp.opcode[5], + step = (longT)_mp_arg(6); + if (start<0 || start + step*(sublength-1)>=length) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Value accessor '[]': " + "Out-of-bounds sub-vector request " + "(length: %ld, start: %ld, sub-length: %ld, step: %ld).", + mp.imgin.pixel_type(),length,start,sublength,step); + ptrs+=start; + if (step==1) std::memcpy(ptrd,ptrs,sublength*sizeof(double)); + else for (longT k = 0; k::nan(); + } + + static double mp_vector_init(_cimg_math_parser& mp) { + unsigned int + ptrs = 4U, + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[3]; + switch (mp.opcode[2] - 4) { + case 0 : std::memset(mp.mem._data + ptrd,0,siz*sizeof(double)); break; // 0 values given + case 1 : { const double val = _mp_arg(ptrs); while (siz-->0) mp.mem[ptrd++] = val; } break; + default : while (siz-->0) { mp.mem[ptrd++] = _mp_arg(ptrs++); if (ptrs>=mp.opcode[2]) ptrs = 4U; } + } + return cimg::type::nan(); + } + + static double mp_vector_eq(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(4) + 1; + unsigned int p1 = (unsigned int)mp.opcode[3], p2 = (unsigned int)mp.opcode[5], n; + const int N = (int)_mp_arg(6); + const bool case_sensitive = (bool)_mp_arg(7); + bool still_equal = true; + double value; + if (!N) return true; + + // Compare all values. + if (N<0) { + if (p1>0 && p2>0) { // Vector == vector + if (p1!=p2) return false; + if (case_sensitive) + while (still_equal && p1--) still_equal = *(ptr1++)==*(ptr2++); + else + while (still_equal && p1--) + still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p1--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p2--) still_equal = *(ptr2++)==value; + return still_equal; + } else { // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + else return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + } + + // Compare only first N values. + if (p1>0 && p2>0) { // Vector == vector + n = cimg::min((unsigned int)N,p1,p2); + if (case_sensitive) + while (still_equal && n--) still_equal = *(ptr1++)==(*ptr2++); + else + while (still_equal && n--) still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + n = std::min((unsigned int)N,p1); + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + n = std::min((unsigned int)N,p2); + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr2++)==value; + return still_equal; + } // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + + static double mp_vector_lerp(_cimg_math_parser& mp) { + unsigned int siz = (unsigned int)mp.opcode[2]; + double *ptrd = &_mp_arg(1) + 1; + const double + *ptrs1 = &_mp_arg(3) + 1, + *ptrs2 = &_mp_arg(4) + 1, + t = _mp_arg(5); + for (unsigned int k = 0; k::nan(); + } + + static double mp_vector_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + return off>=0 && off<(int)siz?mp.mem[ptr + off]:cimg::type::nan(); + } + + static double mp_vector_map_sv(_cimg_math_parser& mp) { // Operator(scalar,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(4); + l_opcode[2] = mp.opcode[4]; // Scalar argument1 + l_opcode.swap(mp.opcode); + ulongT &argument2 = mp.opcode[3]; + while (siz-->0) { argument2 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_v(_cimg_math_parser& mp) { // Operator(vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode.swap(mp.opcode); + ulongT &argument = mp.opcode[2]; + while (siz-->0) { argument = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vs(_cimg_math_parser& mp) { // Operator(vector,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vss(_cimg_math_parser& mp) { // Operator(vector,scalar,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,5); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode[4] = mp.opcode[6]; // Scalar argument3 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vv(_cimg_math_parser& mp) { // Operator(vector,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs1 = (unsigned int)mp.opcode[4] + 1, + ptrs2 = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2], &argument2 = mp.opcode[3]; + while (siz-->0) { argument1 = ptrs1++; argument2 = ptrs2++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_neq(_cimg_math_parser& mp) { + return !mp_vector_eq(mp); + } + + static double mp_vector_print(_cimg_math_parser& mp) { + const bool print_string = (bool)mp.opcode[4]; + cimg_pragma_openmp(critical(mp_vector_print)) + { + CImg _expr(mp.opcode[2] - 5); + const ulongT *ptrs = mp.opcode._data + 5; + cimg_for(_expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(_expr); + unsigned int + ptr = (unsigned int)mp.opcode[1] + 1, + siz0 = (unsigned int)mp.opcode[3], + siz = siz0; + cimg::mutex(6); + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = [ ",_expr._data); + unsigned int count = 0; + while (siz-->0) { + if (count>=64 && siz>=64) { + std::fprintf(cimg::output(),"...,"); + ptr = (unsigned int)mp.opcode[1] + 1 + siz0 - 64; + siz = 64; + } else std::fprintf(cimg::output(),"%.17g%s",mp.mem[ptr++],siz?",":""); + ++count; + } + if (print_string) { + CImg str(siz0 + 1); + ptr = (unsigned int)mp.opcode[1] + 1; + for (unsigned int k = 0; k::nan(); + } + + static double mp_vector_resize(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[2], p2 = (unsigned int)mp.opcode[4]; + const int + interpolation = (int)_mp_arg(5), + boundary_conditions = (int)_mp_arg(6); + if (p2) { // Resize vector + const double *const ptrs = &_mp_arg(3) + 1; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p2,1,1,1,true). + get_resize(p1,1,1,1,interpolation,boundary_conditions); + } else { // Resize scalar + const double value = _mp_arg(3); + CImg(ptrd,p1,1,1,1,true) = CImg(1,1,1,1,value).resize(p1,1,1,1,interpolation, + boundary_conditions); + } + return cimg::type::nan(); + } + + static double mp_vector_reverse(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[3]; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p1,1,1,1,true).get_mirror('x'); + return cimg::type::nan(); + } + + static double mp_vector_set_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + if (off>=0 && off<(int)siz) mp.mem[ptr + off] = _mp_arg(1); + return _mp_arg(1); + } + +#define _cimg_mp_vfunc(func) \ + const longT sizd = (longT)mp.opcode[2];\ + const unsigned int nbargs = (unsigned int)(mp.opcode[3] - 4)/2; \ + double *const ptrd = &_mp_arg(1) + (sizd?1:0); \ + cimg_pragma_openmp(parallel cimg_openmp_if_size(sizd,256)) \ + { CImg vec(nbargs); double res; \ + cimg_pragma_openmp(for) for (longT k = sizd?sizd - 1:0; k>=0; --k) { \ + cimg_forX(vec,n) vec[n] = *(&_mp_arg(4 + 2*n) + (k+1)*(mp.opcode[4 + 2*n + 1]?1:0)); \ + func; ptrd[k] = res; \ + }} \ + return sizd?cimg::type::nan():*ptrd; + + static double _mp_vargkth(CImg& vec) { + const double val = (+vec).get_shared_points(1,vec.width() - 1). + kth_smallest((ulongT)cimg::cut((longT)*vec - 1,(longT)0,(longT)vec.width() - 2)); + cimg_for_inX(vec,1,vec.width()-1,ind) if (vec[ind]==val) return ind - 1.; + return 1.; + } + + static double mp_vargkth(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = _mp_vargkth(vec)); + } + + static double mp_vargmax(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.max() - vec.data())); + } + + static double mp_vargmaxabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.maxabs() - vec.data())); + } + + static double mp_vargmin(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.min() - vec.data())); + } + + static double mp_vargminabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.minabs() - vec.data())); + } + + static double mp_vavg(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.mean()); + } + + static double mp_vkth(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.get_shared_points(1,vec.width() - 1). + kth_smallest((ulongT)cimg::cut((longT)*vec - 1,(longT)0,(longT)vec.width() - 2))); + } + + static double mp_vmax(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.max()); + } + + static double mp_vmaxabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.maxabs()); + } + + static double mp_vmedian(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.median()); + } + + static double mp_vmin(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.min()); + } + + static double mp_vminabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.minabs()); + } + + static double mp_vprod(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.product()); + } + + static double mp_vstd(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = std::sqrt(vec.get_stats()[3])); + } + + static double mp_vsum(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.sum()); + } + + static double mp_vvar(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.get_stats()[3]); + } + + static double mp_vtos(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + sizd = (unsigned int)mp.opcode[2], + sizs = (unsigned int)mp.opcode[4]; + std::memset(ptrd,0,sizd*sizeof(double)); + const int nb_digits = (int)_mp_arg(5); + CImg format(8); + switch (nb_digits) { + case -1 : std::strcpy(format,"%g"); break; + case 0 : std::strcpy(format,"%.17g"); break; + default : cimg_snprintf(format,format._width,"%%.%dg",nb_digits); + } + CImg str; + if (sizs) { // Vector expression + const double *ptrs = &_mp_arg(3) + 1; + CImg(ptrs,sizs,1,1,1,true).value_string(',',sizd + 1,format).move_to(str); + } else { // Scalar expression + str.assign(sizd + 1); + cimg_snprintf(str,sizd + 1,format,_mp_arg(3)); + } + const unsigned int l = std::min(sizd,(unsigned int)std::strlen(str) + 1); + CImg(ptrd,l,1,1,1,true) = str.get_shared_points(0,l - 1); + return cimg::type::nan(); + } + + static double mp_while(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_cond = ++mp.p_code, + *const p_body = p_cond + mp.opcode[3], + *const p_end = p_body + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + bool is_cond = false; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) // Evaluate body + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3), + vsiz = (unsigned int)mp.opcode[4]; + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6), + vsiz = (unsigned int)mp.opcode[7]; + const CImg &img = mp.imgin; + const double x = _mp_arg(2), y = _mp_arg(3), z = _mp_arg(4); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3), + vsiz = (unsigned int)mp.opcode[4]; + const CImg &img = mp.imgin; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], + oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6), + vsiz = (unsigned int)mp.opcode[7]; + const CImg &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), z = oz + _mp_arg(4); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + +#undef _mp_arg + + }; // struct _cimg_math_parser {} + +#define _cimg_create_pointwise_functions(name,func,min_size) \ + CImg& name() { \ + if (is_empty()) return *this; \ + cimg_openmp_for(*this,func((double)*ptr),min_size); \ + return *this; \ + } \ + CImg get_##name() const { \ + return CImg(*this,false).name(); \ + } + + //! Compute the square value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square value \f$I_{(x,y,z,c)}^2\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqr().normalize(0,255)).display(); + \endcode + \image html ref_sqr.jpg + **/ + _cimg_create_pointwise_functions(sqr,cimg::sqr,524288) + + //! Compute the square root of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square root \f$\sqrt{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqrt().normalize(0,255)).display(); + \endcode + \image html ref_sqrt.jpg + **/ + _cimg_create_pointwise_functions(sqrt,std::sqrt,8192) + + //! Compute the exponential of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its exponential \f$e^{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(exp,std::exp,4096) + + //! Compute the logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its logarithm + \f$\mathrm{log}_{e}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log,std::log,262144) + + //! Compute the base-2 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-2 logarithm + \f$\mathrm{log}_{2}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log2,cimg::log2,4096) + + //! Compute the base-10 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-10 logarithm + \f$\mathrm{log}_{10}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log10,std::log10,4096) + + //! Compute the absolute value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its absolute value \f$|I_{(x,y,z,c)}|\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(abs,cimg::abs,524288) + + //! Compute the sign of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sign + \f$\mathrm{sign}(I_{(x,y,z,c)})\f$. + \note + - The sign is set to: + - \c 1 if pixel value is strictly positive. + - \c -1 if pixel value is strictly negative. + - \c 0 if pixel value is equal to \c 0. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sign,cimg::sign,32768) + + //! Compute the cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its cosine \f$\cos(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(cos,std::cos,8192) + + //! Compute the sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sine \f$\sin(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sin,std::sin,8192) + + //! Compute the sinc of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sinc + \f$\mathrm{sinc}(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sinc,cimg::sinc,2048) + + //! Compute the tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its tangent \f$\tan(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(tan,std::tan,2048) + + //! Compute the hyperbolic cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic cosine + \f$\mathrm{cosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(cosh,std::cosh,2048) + + //! Compute the hyperbolic sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic sine + \f$\mathrm{sinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sinh,std::sinh,2048) + + //! Compute the hyperbolic tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic tangent + \f$\mathrm{tanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(tanh,std::tanh,2048) + + //! Compute the arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosine + \f$\mathrm{acos}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(acos,std::acos,8192) + + //! Compute the arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arcsine + \f$\mathrm{asin}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(asin,std::asin,8192) + + //! Compute the arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent + \f$\mathrm{atan}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(atan,std::atan,8192) + + //! Compute the arctangent2 of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent2 + \f$\mathrm{atan2}(I_{(x,y,z,c)})\f$. + \param img Image whose pixel values specify the second argument of the \c atan2() function. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img_x(100,100,1,1,"x-w/2",false), // Define an horizontal centered gradient, from '-width/2' to 'width/2' + img_y(100,100,1,1,"y-h/2",false), // Define a vertical centered gradient, from '-height/2' to 'height/2' + img_atan2 = img_y.get_atan2(img_x); // Compute atan2(y,x) for each pixel value + (img_x,img_y,img_atan2).display(); + \endcode + **/ + template + CImg& atan2(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return atan2(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_atan2(const CImg& img) const { + return CImg(*this,false).atan2(img); + } + + //! Compute the hyperbolic arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosineh + \f$\mathrm{acosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(acosh,cimg::acosh,8192) + + //! Compute the hyperbolic arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic arcsine + \f$\mathrm{asinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(asinh,cimg::asinh,8192) + + //! Compute the hyperbolic arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic arctangent + \f$\mathrm{atanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(atanh,cimg::atanh,8192) + + //! In-place pointwise multiplication. + /** + Compute the pointwise multiplication between the image instance and the specified input image \c img. + \param img Input image, as the second operand of the multiplication. + \note + - Similar to operator+=(const CImg&), except that it performs a pointwise multiplication + instead of an addition. + - It does \e not perform a \e matrix multiplication. For this purpose, use operator*=(const CImg&) instead. + \par Example + \code + CImg + img("reference.jpg"), + shade(img.width,img.height(),1,1,"-(x-w/2)^2-(y-h/2)^2",false); + shade.normalize(0,1); + (img,shade,img.get_mul(shade)).display(); + \endcode + **/ + template + CImg& mul(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return mul(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_mul(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).mul(img); + } + + //! In-place pointwise division. + /** + Similar to mul(const CImg&), except that it performs a pointwise division instead of a multiplication. + **/ + template + CImg& div(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return div(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_div(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).div(img); + } + + //! Raise each pixel value to a specified power. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its power \f$I_{(x,y,z,c)}^p\f$. + \param p Exponent value. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img0("reference.jpg"), // Load reference color image + img1 = (img0/255).pow(1.8)*=255, // Compute gamma correction, with gamma = 1.8 + img2 = (img0/255).pow(0.5)*=255; // Compute gamma correction, with gamma = 0.5 + (img0,img1,img2).display(); + \endcode + **/ + CImg& pow(const double p) { + if (is_empty()) return *this; + if (p==-4) { cimg_openmp_for(*this,1/(Tfloat)cimg::pow4(*ptr),32768); return *this; } + if (p==-3) { cimg_openmp_for(*this,1/(Tfloat)cimg::pow3(*ptr),32768); return *this; } + if (p==-2) { cimg_openmp_for(*this,1/(Tfloat)cimg::sqr(*ptr),32768); return *this; } + if (p==-1) { cimg_openmp_for(*this,1/(Tfloat)*ptr,32768); return *this; } + if (p==-0.5) { cimg_openmp_for(*this,1/std::sqrt((Tfloat)*ptr),8192); return *this; } + if (p==0) return fill((T)1); + if (p==0.5) return sqrt(); + if (p==1) return *this; + if (p==2) return sqr(); + if (p==3) { cimg_openmp_for(*this,cimg::pow3(*ptr),262144); return *this; } + if (p==4) { cimg_openmp_for(*this,cimg::pow4(*ptr),131072); return *this; } + cimg_openmp_for(*this,std::pow((Tfloat)*ptr,(Tfloat)p),1024); + return *this; + } + + //! Raise each pixel value to a specified power \newinstance. + CImg get_pow(const double p) const { + return CImg(*this,false).pow(p); + } + + //! Raise each pixel value to a power, specified from an expression. + /** + Similar to operator+=(const char*), except it performs a pointwise exponentiation instead of an addition. + **/ + CImg& pow(const char *const expression) { + return pow((+*this)._fill(expression,true,1,0,0,"pow",this)); + } + + //! Raise each pixel value to a power, specified from an expression \newinstance. + CImg get_pow(const char *const expression) const { + return CImg(*this,false).pow(expression); + } + + //! Raise each pixel value to a power, pointwisely specified from another image. + /** + Similar to operator+=(const CImg& img), except that it performs an exponentiation instead of an addition. + **/ + template + CImg& pow(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return pow(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_pow(const CImg& img) const { + return CImg(*this,false).pow(img); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(unsigned int), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::rol(*ptr,n),32768); + return *this; + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const unsigned int n=1) const { + return (+*this).rol(n); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const char*), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const char *const expression) { + return rol((+*this)._fill(expression,true,1,0,0,"rol",this)); + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const char *const expression) const { + return (+*this).rol(expression); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const CImg&), except that it performs a left rotation instead of a left shift. + **/ + template + CImg& rol(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return rol(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_rol(const CImg& img) const { + return (+*this).rol(img); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(unsigned int), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::ror(*ptr,n),32768); + return *this; + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const unsigned int n=1) const { + return (+*this).ror(n); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const char*), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const char *const expression) { + return ror((+*this)._fill(expression,true,1,0,0,"ror",this)); + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const char *const expression) const { + return (+*this).ror(expression); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const CImg&), except that it performs a right rotation instead of a right shift. + **/ + template + CImg& ror(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return ror(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_ror(const CImg& img) const { + return (+*this).ror(img); + } + + //! Pointwise min operator between instance image and a value. + /** + \param val Value used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& min(const T& value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,std::min(*ptr,value),65536); + return *this; + } + + //! Pointwise min operator between instance image and a value \newinstance. + CImg get_min(const T& value) const { + return (+*this).min(value); + } + + //! Pointwise min operator between two images. + /** + \param img Image used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& min(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return min(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_min(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).min(img); + } + + //! Pointwise min operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& min(const char *const expression) { + return min((+*this)._fill(expression,true,1,0,0,"min",this)); + } + + //! Pointwise min operator between an image and an expression \newinstance. + CImg get_min(const char *const expression) const { + return CImg(*this,false).min(expression); + } + + //! Pointwise max operator between instance image and a value. + /** + \param val Value used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& max(const T& value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,std::max(*ptr,value),65536); + return *this; + } + + //! Pointwise max operator between instance image and a value \newinstance. + CImg get_max(const T& value) const { + return (+*this).max(value); + } + + //! Pointwise max operator between two images. + /** + \param img Image used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& max(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return max(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_max(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).max(img); + } + + //! Pointwise max operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& max(const char *const expression) { + return max((+*this)._fill(expression,true,1,0,0,"max",this)); + } + + //! Pointwise max operator between an image and an expression \newinstance. + CImg get_max(const char *const expression) const { + return CImg(*this,false).max(expression); + } + + //! Pointwise minabs operator between instance image and a value. + /** + \param val Value used as the reference argument of the minabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& minabs(const T& value) { + if (is_empty()) return *this; + const T absvalue = cimg::abs(value); + cimg_openmp_for(*this,cimg::minabs(*ptr,value,absvalue),65536); + return *this; + } + + //! Pointwise minabs operator between instance image and a value \newinstance. + CImg get_minabs(const T& value) const { + return (+*this).minabs(value); + } + + //! Pointwise minabs operator between two images. + /** + \param img Image used as the reference argument of the minabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& minabs(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return minabs(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_minabs(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).minabs(img); + } + + //! Pointwise minabs operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& minabs(const char *const expression) { + return minabs((+*this)._fill(expression,true,1,0,0,"minabs",this)); + } + + //! Pointwise minabs operator between an image and an expression \newinstance. + CImg get_minabs(const char *const expression) const { + return CImg(*this,false).minabs(expression); + } + + //! Pointwise maxabs operator between instance image and a value. + /** + \param val Value used as the reference argument of the maxabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& maxabs(const T& value) { + if (is_empty()) return *this; + const T absvalue = cimg::abs(value); + cimg_openmp_for(*this,cimg::maxabs(*ptr,value,absvalue),65536); + return *this; + } + + //! Pointwise maxabs operator between instance image and a value \newinstance. + CImg get_maxabs(const T& value) const { + return (+*this).maxabs(value); + } + + //! Pointwise maxabs operator between two images. + /** + \param img Image used as the reference argument of the maxabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& maxabs(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return maxabs(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_maxabs(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).maxabs(img); + } + + //! Pointwise maxabs operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& maxabs(const char *const expression) { + return maxabs((+*this)._fill(expression,true,1,0,0,"maxabs",this)); + } + + //! Pointwise maxabs operator between an image and an expression \newinstance. + CImg get_maxabs(const char *const expression) const { + return CImg(*this,false).maxabs(expression); + } + + //! Return a reference to the minimum pixel value. + /** + **/ + T& min() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min; + cimg_for(*this,ptrs,T) if (*ptrsmax_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value \const. + const T& max() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max; + cimg_for(*this,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value in absolute value. + /** + **/ + T& maxabs() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "maxabs(): Empty instance.", + cimg_instance); + T *ptr_maxabs = _data; + T maxabs_value = *ptr_maxabs; + cimg_for(*this,ptrs,T) { + const T ma = cimg::abs(*ptrs); + if (ma>maxabs_value) { maxabs_value = ma; ptr_maxabs = ptrs; } + } + return *ptr_maxabs; + } + + //! Return a reference to the maximum pixel value in absolute value \const. + const T& maxabs() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "maxabs(): Empty instance.", + cimg_instance); + const T *ptr_maxabs = _data; + T maxabs_value = *ptr_maxabs; + cimg_for(*this,ptrs,T) { + const T ma = cimg::abs(*ptrs); + if (ma>maxabs_value) { maxabs_value = ma; ptr_maxabs = ptrs; } + } + return *ptr_maxabs; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value. + /** + \param[out] max_val Maximum pixel value. + **/ + template + T& min_max(t& max_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value \const. + template + const T& min_max(t& max_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + const T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the maximum pixel value as well as the minimum pixel value. + /** + \param[out] min_val Minimum pixel value. + **/ + template + T& max_min(t& min_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val=size()) return max(); + CImg arr(*this,false); + ulongT l = 0, ir = size() - 1; + for ( ; ; ) { + if (ir<=l + 1) { + if (ir==l + 1 && arr[ir]>1; + cimg::swap(arr[mid],arr[l + 1]); + if (arr[l]>arr[ir]) cimg::swap(arr[l],arr[ir]); + if (arr[l + 1]>arr[ir]) cimg::swap(arr[l + 1],arr[ir]); + if (arr[l]>arr[l + 1]) cimg::swap(arr[l],arr[l + 1]); + ulongT i = l + 1, j = ir; + const T pivot = arr[l + 1]; + for ( ; ; ) { + do ++i; while (arr[i]pivot); + if (j=k) ir = j - 1; + if (j<=k) l = i; + } + } + } + + //! Return the median pixel value. + /** + **/ + T median() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "median(): Empty instance.", + cimg_instance); + const ulongT s = size(); + switch (s) { + case 1 : return _data[0]; + case 2 : return cimg::median(_data[0],_data[1]); + case 3 : return cimg::median(_data[0],_data[1],_data[2]); + case 5 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4]); + case 7 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6]); + case 9 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8]); + case 13 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8], + _data[9],_data[10],_data[11],_data[12]); + } + const T res = kth_smallest(s>>1); + return (s%2)?res:(T)((res + kth_smallest((s>>1) - 1))/2); + } + + //! Return the product of all the pixel values. + /** + **/ + double product() const { + if (is_empty()) return 0; + double res = 1; + cimg_for(*this,ptrs,T) res*=(double)*ptrs; + return res; + } + + //! Return the sum of all the pixel values. + /** + **/ + double sum() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res; + } + + //! Return the average pixel value. + /** + **/ + double mean() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res/size(); + } + + //! Return the variance of the pixel values. + /** + \param variance_method Method used to estimate the variance. Can be: + - \c 0: Second moment, computed as + \f$1/N \sum\limits_{k=1}^{N} (x_k - \bar x)^2 = + 1/N \left( \sum\limits_{k=1}^N x_k^2 - \left( \sum\limits_{k=1}^N x_k \right)^2 / N \right)\f$ + with \f$ \bar x = 1/N \sum\limits_{k=1}^N x_k \f$. + - \c 1: Best unbiased estimator, computed as \f$\frac{1}{N - 1} \sum\limits_{k=1}^{N} (x_k - \bar x)^2 \f$. + - \c 2: Least median of squares. + - \c 3: Least trimmed of squares. + **/ + double variance(const unsigned int variance_method=1) const { + double foo; + return variance_mean(variance_method,foo); + } + + //! Return the variance as well as the average of the pixel values. + /** + \param variance_method Method used to estimate the variance (see variance(const unsigned int) const). + \param[out] mean Average pixel value. + **/ + template + double variance_mean(const unsigned int variance_method, t& mean) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_mean(): Empty instance.", + cimg_instance); + + double variance = 0, average = 0; + const ulongT siz = size(); + switch (variance_method) { + case 0 : { // Least mean square (standard definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = (S2 - S*S/siz)/siz; + average = S; + } break; + case 1 : { // Least mean square (robust definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + average = S; + } break; + case 2 : { // Least Median of Squares (MAD) + CImg buf(*this,false); + buf.sort(); + const ulongT siz2 = siz>>1; + const double med_i = (double)buf[siz2]; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; *ptrs = (Tfloat)cimg::abs(val - med_i); average+=val; + } + buf.sort(); + const double sig = (double)(1.4828*buf[siz2]); + variance = sig*sig; + } break; + default : { // Least trimmed of Squares + CImg buf(*this,false); + const ulongT siz2 = siz>>1; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; (*ptrs)=(Tfloat)((*ptrs)*val); average+=val; + } + buf.sort(); + double a = 0; + const Tfloat *ptrs = buf._data; + for (ulongT j = 0; j0?variance:0; + } + + //! Return estimated variance of the noise. + /** + \param variance_method Method used to compute the variance (see variance(const unsigned int) const). + \note Because of structures such as edges in images it is + recommended to use a robust variance estimation. The variance of the + noise is estimated by computing the variance of the Laplacian \f$(\Delta + I)^2 \f$ scaled by a factor \f$c\f$ insuring \f$ c E[(\Delta I)^2]= + \sigma^2\f$ where \f$\sigma\f$ is the noise variance. + **/ + double variance_noise(const unsigned int variance_method=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_noise(): Empty instance.", + cimg_instance); + + const ulongT siz = size(); + if (!siz || !_data) return 0; + if (variance_method>1) { // Compute a scaled version of the Laplacian + CImg tmp(*this,false); + if (_depth==1) { + const double cste = 1./std::sqrt(20.); // Depends on how the Laplacian is computed + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*262144 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3(I,T); + cimg_for3x3(*this,x,y,0,c,I,T) { + tmp(x,y,c) = cste*((double)Inc + (double)Ipc + (double)Icn + + (double)Icp - 4*(double)Icc); + } + } + } else { + const double cste = 1./std::sqrt(42.); // Depends on how the Laplacian is computed + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*262144 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,T); + cimg_for3x3x3(*this,x,y,z,c,I,T) { + tmp(x,y,z,c) = cste*( + (double)Incc + (double)Ipcc + (double)Icnc + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + } + } + } + return tmp.variance(variance_method); + } + + // Version that doesn't need intermediate images. + double variance = 0, S = 0, S2 = 0; + if (_depth==1) { + const double cste = 1./std::sqrt(20.); + CImg_3x3(I,T); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,T) { + const double val = cste*((double)Inc + (double)Ipc + + (double)Icn + (double)Icp - 4*(double)Icc); + S+=val; S2+=val*val; + } + } else { + const double cste = 1./std::sqrt(42.); + CImg_3x3x3(I,T); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,T) { + const double val = cste * + ((double)Incc + (double)Ipcc + (double)Icnc + + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + S+=val; S2+=val*val; + } + } + if (variance_method) variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + else variance = (S2 - S*S/siz)/siz; + return variance>0?variance:0; + } + + //! Compute the MSE (Mean-Squared Error) between two images. + /** + \param img Image used as the second argument of the MSE operator. + **/ + template + double MSE(const CImg& img) const { + if (img.size()!=size()) + throw CImgArgumentException(_cimg_instance + "MSE(): Instance and specified image (%u,%u,%u,%u,%p) have different dimensions.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + double vMSE = 0; + const t* ptr2 = img._data; + cimg_for(*this,ptr1,T) { + const double diff = (double)*ptr1 - (double)*(ptr2++); + vMSE+=diff*diff; + } + const ulongT siz = img.size(); + if (siz) vMSE/=siz; + return vMSE; + } + + //! Compute the PSNR (Peak Signal-to-Noise Ratio) between two images. + /** + \param img Image used as the second argument of the PSNR operator. + \param max_value Maximum theoretical value of the signal. + **/ + template + double PSNR(const CImg& img, const double max_value=255) const { + const double vMSE = (double)std::sqrt(MSE(img)); + return (vMSE!=0)?(double)(20*std::log10(max_value/vMSE)):(double)(cimg::type::max()); + } + + //! Evaluate math formula. + /** + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,x,y,z,c,list_inputs,list_outputs); + } + + // Fast function to pre-evaluate common expressions. + // (return 'true' in case of success, and set value of 'res'). + template + bool __eval(const char *const expression, t &res) const { + if (!expression || !*expression) { res = (t)0; return true; } + const char c = *expression; + bool is_success = false; + char c1, end; + double val; + if (c>='0' && c<='9') { // Possible value + if (!expression[1]) { // Single digit + res = (t)(c - '0'); + is_success = true; + } else if (std::sscanf(expression,"%lf%c",&val,&end)==1) { // Single value + res = (t)val; + is_success = true; + } + } else if ((c=='+' || c=='-' || c=='!') && // +Value, -Value or !Value + (c1=expression[1])>='0' && c1<='0') { + if (!expression[2]) { // [+-!] + Single digit + const int ival = c1 - '0'; + res = (t)(c=='+'?ival:c=='-'?-ival:!ival); + is_success = true; + } else if (std::sscanf(expression + 1,"%lf%c",&val,&end)==1) { // [+-!] Single value + res = (t)(c=='+'?val:c=='-'?-val:(double)!val); + is_success = true; + } + } else if (!expression[1]) switch (*expression) { // Other common single-char expressions + case 'w' : res = (t)_width; is_success = true; break; + case 'h' : res = (t)_height; is_success = true; break; + case 'd' : res = (t)_depth; is_success = true; break; + case 's' : res = (t)_spectrum; is_success = true; break; + case 'r' : res = (t)_is_shared; is_success = true; break; + } + return is_success; + } + + double _eval(CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression || !*expression) return 0; + double _val = 0; + if (__eval(expression,_val)) return _val; + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs,false); + mp.begin_t(); + const double val = mp(x,y,z,c); + mp.end_t(); + mp.end(); + return val; + } + + //! Evaluate math formula. + /** + \param[out] output Contains values of output vector returned by the evaluated expression + (or is empty if the returned type is scalar). + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + void eval(CImg &output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + _eval(output,this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + template + void eval(CImg& output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + _eval(output,0,expression,x,y,z,c,list_inputs,list_outputs); + } + + template + void _eval(CImg& output, CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression || !*expression) { output.assign(1); *output = 0; return; } + double _val = 0; + if (__eval(expression,_val)) { output.assign(1); *output = _val; return; } + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs,false); + output.assign(1,std::max(1U,mp.result_dim)); + mp.begin_t(); + mp(x,y,z,c,output._data); + mp.end_t(); + mp.end(); + } + + //! Evaluate math formula on a set of variables. + /** + \param expression Math formula, as a C-string. + \param xyzc Set of values (x,y,z,c) used for the evaluation. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,xyzc,list_inputs,list_outputs); + } + + //! Evaluate math formula on a set of variables \const. + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,xyzc,list_inputs,list_outputs); + } + + template + CImg _eval(CImg *const output, const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + CImg res(1,xyzc.size()/4); + if (!expression || !*expression) return res.fill(0); + _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs,false); + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel if (res._height>=512)) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_eval)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + cimg_pragma_openmp(for) + for (int i = 0; i[min, max, mean, variance, xmin, ymin, zmin, cmin, xmax, ymax, zmax, cmax, sum, product]. + **/ + CImg get_stats(const unsigned int variance_method=1) const { + if (is_empty()) return CImg(); + const ulongT siz = size(); + const longT off_end = (longT)siz; + double S = 0, S2 = 0, P = 1; + longT offm = 0, offM = 0; + T m = *_data, M = m; + + cimg_pragma_openmp(parallel reduction(+:S,S2) reduction(*:P) cimg_openmp_if_size(siz,131072)) { + longT loffm = 0, loffM = 0; + T lm = *_data, lM = lm; + cimg_pragma_openmp(for) + for (longT off = 0; offlM) { lM = val; loffM = off; } + S+=_val; + S2+=_val*_val; + P*=_val; + } + cimg_pragma_openmp(critical(get_stats)) { + if (lmM || (lM==M && loffM1?(S2 - S*S/siz)/(siz - 1):0): + variance(variance_method)), + variance_value = _variance_value>0?_variance_value:0; + int + xm = 0, ym = 0, zm = 0, cm = 0, + xM = 0, yM = 0, zM = 0, cM = 0; + contains(_data[offm],xm,ym,zm,cm); + contains(_data[offM],xM,yM,zM,cM); + return CImg(1,14).fill((double)m,(double)M,mean_value,variance_value, + (double)xm,(double)ym,(double)zm,(double)cm, + (double)xM,(double)yM,(double)zM,(double)cM, + S,P); + } + + //! Compute statistics vector from the pixel values \inplace. + CImg& stats(const unsigned int variance_method=1) { + return get_stats(variance_method).move_to(*this); + } + + //@} + //------------------------------------- + // + //! \name Vector / Matrix Operations + //@{ + //------------------------------------- + + //! Compute norm of the image, viewed as a matrix. + /** + \param magnitude_type Norm type. Can be: + - \c -1: Linf-norm + - \c 0: L0-norm + - \c 1: L1-norm + - \c 2: L2-norm + **/ + double magnitude(const int magnitude_type=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "magnitude(): Empty instance.", + cimg_instance); + const ulongT siz = size(); + double res = 0; + switch (magnitude_type) { + case -1 : { + cimg_for(*this,ptrs,T) { const double val = (double)cimg::abs(*ptrs); if (val>res) res = val; } + } break; + case 1 : { + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(size(),8192)) + for (longT off = 0; off<(longT)siz; ++off) res+=(double)cimg::abs(_data[off]); + } break; + default : { + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(size(),8192)) + for (longT off = 0; off<(longT)siz; ++off) res+=(double)cimg::sqr(_data[off]); + res = (double)std::sqrt(res); + } + } + return res; + } + + //! Compute the trace of the image, viewed as a matrix. + /** + **/ + double trace() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "trace(): Empty instance.", + cimg_instance); + double res = 0; + cimg_forX(*this,k) res+=(double)(*this)(k,k); + return res; + } + + //! Compute the determinant of the image, viewed as a matrix. + /** + **/ + double det() const { + if (is_empty() || _width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "det(): Instance is not a square matrix.", + cimg_instance); + + switch (_width) { + case 1 : return (double)((*this)(0,0)); + case 2 : return (double)((*this)(0,0))*(double)((*this)(1,1)) - (double)((*this)(0,1))*(double)((*this)(1,0)); + case 3 : { + const double + a = (double)_data[0], d = (double)_data[1], g = (double)_data[2], + b = (double)_data[3], e = (double)_data[4], h = (double)_data[5], + c = (double)_data[6], f = (double)_data[7], i = (double)_data[8]; + return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e; + } + default : { + CImg lu(*this,false); + CImg indx; + bool d; + lu._LU(indx,d); + double res = d?(double)1:(double)-1; + cimg_forX(lu,i) res*=lu(i,i); + return res; + } + } + } + + //! Compute the dot product between instance and argument, viewed as matrices. + /** + \param img Image used as a second argument of the dot product. + **/ + template + double dot(const CImg& img) const { + const ulongT nb = std::min(size(),img.size()); + double res = 0; + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(nb,8192)) + for (longT off = 0; off<(longT)nb; ++off) res+=(double)_data[off]*(double)img[off]; + return res; + } + + //! Get vector-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + CImg res; + if (res._height!=_spectrum) res.assign(1,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + const T *ptrs = data(x,y,z); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get (square) matrix-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \note - The spectrum() of the image must be a square. + **/ + CImg get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const { + const int n = (int)cimg::round(std::sqrt((double)_spectrum)); + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(n,n); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get tensor-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + if (_spectrum==6) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd),*(ptrs + 3*whd),*(ptrs + 4*whd),*(ptrs + 5*whd)); + if (_spectrum==3) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd)); + return tensor(*ptrs); + } + + //! Set vector-valued pixel at specified position. + /** + \param vec Vector to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_vector_at(const CImg& vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0) { + if (x<_width && y<_height && z<_depth) { + const t *ptrs = vec._data; + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = data(x,y,z); + for (unsigned int k = std::min((unsigned int)vec.size(),_spectrum); k; --k) { + *ptrd = (T)*(ptrs++); ptrd+=whd; + } + } + return *this; + } + + //! Set (square) matrix-valued pixel at specified position. + /** + \param mat Matrix to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_matrix_at(const CImg& mat, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + return set_vector_at(mat,x,y,z); + } + + //! Set tensor-valued pixel at specified position. + /** + \param ten Tensor to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_tensor_at(const CImg& ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + T *ptrd = data(x,y,z,0); + const ulongT siz = (ulongT)_width*_height*_depth; + if (ten._height==2) { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[3]; + } + else { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[2]; ptrd+=siz; + *ptrd = (T)ten[4]; ptrd+=siz; + *ptrd = (T)ten[5]; ptrd+=siz; + *ptrd = (T)ten[8]; + } + return *this; + } + + //! Resize image to become a diagonal matrix. + /** + \note Transform the image as a diagonal matrix so that each of its initial value becomes a diagonal coefficient. + **/ + CImg& diagonal() { + return get_diagonal().move_to(*this); + } + + //! Resize image to become a diagonal matrix \newinstance. + CImg get_diagonal() const { + if (is_empty()) return *this; + const unsigned int siz = (unsigned int)size(); + CImg res(siz,siz,1,1,0); + cimg_foroff(*this,off) res((unsigned int)off,(unsigned int)off) = (*this)[off]; + return res; + } + + //! Replace the image by an identity matrix. + /** + \note If the instance image is not square, it is resized to a square matrix using its maximum + dimension as a reference. + **/ + CImg& identity_matrix() { + return identity_matrix(std::max(_width,_height)).move_to(*this); + } + + //! Replace the image by an identity matrix \newinstance. + CImg get_identity_matrix() const { + return identity_matrix(std::max(_width,_height)); + } + + //! Fill image with a linear sequence of values. + /** + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + CImg& sequence(const T& a0, const T& a1) { + if (is_empty()) return *this; + const ulongT siz = size() - 1; + T* ptr = _data; + if (siz) { + const double delta = (double)a1 - (double)a0; + cimg_foroff(*this,l) *(ptr++) = (T)(a0 + delta*l/siz); + } else *ptr = a0; + return *this; + } + + //! Fill image with a linear sequence of values \newinstance. + CImg get_sequence(const T& a0, const T& a1) const { + return (+*this).sequence(a0,a1); + } + + //! Transpose the image, viewed as a matrix. + /** + \note Equivalent to \code permute_axes("yxzc"); \endcode. + **/ + CImg& transpose() { + if (_width==1) { _width = _height; _height = 1; return *this; } + if (_height==1) { _height = _width; _width = 1; return *this; } + if (_width==_height) { + cimg_forYZC(*this,y,z,c) for (int x = y; x get_transpose() const { + return get_permute_axes("yxzc"); + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors. + /** + \param img Image used as the second argument of the cross product. + \note The first argument of the cross product is \c *this. + **/ + template + CImg& cross(const CImg& img) { + if (_width!=1 || _height<3 || img._width!=1 || img._height<3) + throw CImgInstanceException(_cimg_instance + "cross(): Instance and/or specified image (%u,%u,%u,%u,%p) are not 3D vectors.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + + const T x = (*this)[0], y = (*this)[1], z = (*this)[2]; + (*this)[0] = (T)(y*img[2] - z*img[1]); + (*this)[1] = (T)(z*img[0] - x*img[2]); + (*this)[2] = (T)(x*img[1] - y*img[0]); + return *this; + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors \newinstance. + template + CImg<_cimg_Tt> get_cross(const CImg& img) const { + return CImg<_cimg_Tt>(*this).cross(img); + } + + //! Invert the instance image, viewed as a matrix. + /** + \param use_LU Choose the inverting algorithm. Can be: + - \c true: LU-based matrix inversion. + - \c false: SVD-based matrix inversion. + **/ + CImg& invert(const bool use_LU=true) { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "invert(): Instance is not a square matrix.", + cimg_instance); + const double dete = _width>3?-1.:det(); + if (dete!=0. && _width==2) { + const double + a = _data[0], c = _data[1], + b = _data[2], d = _data[3]; + _data[0] = (T)(d/dete); _data[1] = (T)(-c/dete); + _data[2] = (T)(-b/dete); _data[3] = (T)(a/dete); + } else if (dete!=0. && _width==3) { + const double + a = _data[0], d = _data[1], g = _data[2], + b = _data[3], e = _data[4], h = _data[5], + c = _data[6], f = _data[7], i = _data[8]; + _data[0] = (T)((i*e - f*h)/dete), _data[1] = (T)((g*f - i*d)/dete), _data[2] = (T)((d*h - g*e)/dete); + _data[3] = (T)((h*c - i*b)/dete), _data[4] = (T)((i*a - c*g)/dete), _data[5] = (T)((g*b - a*h)/dete); + _data[6] = (T)((b*f - e*c)/dete), _data[7] = (T)((d*c - a*f)/dete), _data[8] = (T)((a*e - d*b)/dete); + } else { + +#ifdef cimg_use_lapack + int INFO = (int)use_LU, N = _width, LWORK = 4*N, *const IPIV = new int[N]; + Tfloat + *const lapA = new Tfloat[N*N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetri_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)(lapA[k*N + l]); else fill(0); + delete[] IPIV; delete[] lapA; delete[] WORK; +#else + if (use_LU) { // LU-based + CImg A(*this,false), indx; + bool d; + A._LU(indx,d); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16*16)) + cimg_forX(*this,j) { + CImg col(1,_width,1,1,0); + col(j) = 1; + col._solve(A,indx); + cimg_forX(*this,i) (*this)(j,i) = (T)col(i); + } + } else pseudoinvert(false); // SVD-based +#endif + } + return *this; + } + + //! Invert the instance image, viewed as a matrix \newinstance. + CImg get_invert(const bool use_LU=true) const { + return CImg(*this,false).invert(use_LU); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix. + /** + **/ + CImg& pseudoinvert(const bool use_LU=false) { + return get_pseudoinvert(use_LU).move_to(*this); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix \newinstance. + CImg get_pseudoinvert(const bool use_LU=false) const { + + // LU-based method. + if (use_LU) { + CImg AtA(width(),width()); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,128*128)) + cimg_forY(AtA,i) + for (int j = 0; j<=i; ++j) { + double res = 0; + cimg_forY(*this,k) res+=(*this)(i,k)*(*this)(j,k); + AtA(j,i) = AtA(i,j) = (Tfloat)res; + } + AtA.invert(true); + return AtA*get_transpose(); + } + + // SVD-based method. + CImg U, S, V; + SVD(U,S,V,false); + const Tfloat epsilon = (sizeof(Tfloat)<=4?5.96e-8f:1.11e-16f)*std::max(_width,_height)*S.max(); + cimg_forX(V,x) { + const Tfloat s = S(x), invs = s>epsilon?1/s:0; + cimg_forY(V,y) V(x,y)*=invs; + } + return V*U.transpose(); + } + + //! Solve a system of linear equations. + /** + \param A Matrix of the linear system. + \param use_LU In case of non square system (least-square solution), + choose between SVD-based (\c false) or LU-based (\c true) method. + LU method is faster for large matrices, but numerically less stable. + \note Solve \c AX = B where \c B=*this. + **/ + template + CImg& solve(const CImg& A, const bool use_LU=false) { + if (_depth!=1 || _spectrum!=1 || _height!=A._height || A._depth!=1 || A._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "solve(): Instance and specified matrix (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + + if (A.size()==1) return (*this)/=A[0]; + if (A._width==2 && A._height==2 && _height==2) { // 2x2 linear system + const double a = (double)A[0], b = (double)A[1], c = (double)A[2], d = (double)A[3], + fa = std::fabs(a), fb = std::fabs(b), fc = std::fabs(c), fd = std::fabs(d), + det = a*d - b*c, fM = cimg::max(fa,fb,fc,fd); + if (fM==fa) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), y = (a*v - c*u)/det; + (*this)(k,0) = (T)((u - b*y)/a); (*this)(k,1) = (T)y; + } else if (fM==fc) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), y = (a*v - c*u)/det; + (*this)(k,0) = (T)((v - d*y)/c); (*this)(k,1) = (T)y; + } else if (fM==fb) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), x = (d*u - b*v)/det; + (*this)(k,0) = (T)x; (*this)(k,1) = (T)((u - a*x)/b); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), x = (d*u - b*v)/det; + (*this)(k,0) = (T)x; (*this)(k,1) = (T)((v - c*x)/d); + } + return *this; + } + + if (A._width==A._height) { // Square linear system +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N]; + Ttfloat + *const lapA = new Ttfloat[N*N], + *const lapB = new Ttfloat[N], + *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*N + l] = (Ttfloat)(A(k,l)); + cimg_forX(*this,i) { + cimg_forY(*this,j) lapB[j] = (Ttfloat)((*this)(i,j)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getrs(TRANS,N,lapA,IPIV,lapB,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrs_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forY(*this,j) (*this)(i,j) = (T)(lapB[j]); else cimg_forY(*this,j) (*this)(i,j) = (T)0; + } + delete[] IPIV; delete[] lapA; delete[] lapB; delete[] WORK; +#else + CImg lu(A,false); + CImg indx; + bool d; + lu._LU(indx,d); + CImg res(_width,A._width); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16)) + cimg_forX(*this,i) res.draw_image(i,get_column(i)._solve(lu,indx)); + res.move_to(*this); +#endif + } else { // Least-square solution for non-square systems + +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width; + Ttfloat WORK_QUERY; + Ttfloat + * const lapA = new Ttfloat[M*N], + * const lapB = new Ttfloat[M*NRHS]; + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, &WORK_QUERY, LWORK, INFO); + LWORK = (int) WORK_QUERY; + Ttfloat *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*M + l] = (Ttfloat)(A(k,l)); + cimg_forXY(*this,k,l) lapB[k*M + l] = (Ttfloat)((*this)(k,l)); + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, WORK, LWORK, INFO); + if (INFO != 0) + cimg::warn(_cimg_instance + "solve(): LAPACK library function sgels() returned error code %d.", + cimg_instance, + INFO); + assign(NRHS, N); + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)lapB[k*M + l]; + else (A.get_pseudoinvert(use_LU)*(*this)).move_to(*this); + delete[] lapA; delete[] lapB; delete[] WORK; +#else + (A.get_pseudoinvert(use_LU)*(*this)).move_to(*this); +#endif + } + return *this; + } + + //! Solve a system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve(const CImg& A, const bool use_LU=false) const { + typedef _cimg_Ttfloat Ttfloat; + return CImg(*this,false).solve(A,use_LU); + } + + template + CImg& _solve(const CImg& A, const CImg& indx) { + typedef _cimg_Ttfloat Ttfloat; + const int N = height(); + int ii = -1; + Ttfloat sum; + for (int i = 0; i=0) for (int j = ii; j<=i - 1; ++j) sum-=A(j,i)*(*this)(j); + else if (sum!=0) ii = i; + (*this)(i) = (T)sum; + } + for (int i = N - 1; i>=0; --i) { + sum = (*this)(i); + for (int j = i + 1; j + CImg& solve_tridiagonal(const CImg& A) { + const unsigned int siz = (unsigned int)size(); + if (A._width!=3 || A._height!=siz) + throw CImgArgumentException(_cimg_instance + "solve_tridiagonal(): Instance and tridiagonal matrix " + "(%u,%u,%u,%u,%p) have incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = 1e-4f; + CImg B = A.get_column(1), V(*this,false); + for (int i = 1; i<(int)siz; ++i) { + const Ttfloat m = A(0,i)/(B[i - 1]?B[i - 1]:epsilon); + B[i] -= m*A(2,i - 1); + V[i] -= m*V[i - 1]; + } + (*this)[siz - 1] = (T)(V[siz - 1]/(B[siz - 1]?B[siz - 1]:epsilon)); + for (int i = (int)siz - 2; i>=0; --i) (*this)[i] = (T)((V[i] - A(2,i)*(*this)[i + 1])/(B[i]?B[i]:epsilon)); + return *this; + } + + //! Solve a tridiagonal system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve_tridiagonal(const CImg& A) const { + return CImg<_cimg_Ttfloat>(*this,false).solve_tridiagonal(A); + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& eigen(CImg& val, CImg &vec) const { + if (is_empty()) { val.assign(); vec.assign(); } + else { + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + + if (val.size()<(ulongT)_width) val.assign(1,_width); + if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width); + switch (_width) { + case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break; + case 2 : { + const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d; + double f = e*e - 4*(a*d - b*c); + if (f<0) cimg::warn(_cimg_instance + "eigen(): Complex eigenvalues found.", + cimg_instance); + f = std::sqrt(f); + const double + l1 = 0.5*(e - f), + l2 = 0.5*(e + f), + b2 = b*b, + norm1 = std::sqrt(cimg::sqr(l2 - a) + b2), + norm2 = std::sqrt(cimg::sqr(l1 - a) + b2); + val[0] = (t)l2; + val[1] = (t)l1; + if (norm1>0) { vec(0,0) = (t)(b/norm1); vec(0,1) = (t)((l2 - a)/norm1); } else { vec(0,0) = 1; vec(0,1) = 0; } + if (norm2>0) { vec(1,0) = (t)(b/norm2); vec(1,1) = (t)((l1 - a)/norm2); } else { vec(1,0) = 1; vec(1,1) = 0; } + } break; + default : + throw CImgInstanceException(_cimg_instance + "eigen(): Eigenvalues computation of general matrices is limited " + "to 2x2 matrices.", + cimg_instance); + } + } + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \return A list of two images [val; vec], whose meaning is similar as in eigen(CImg&,CImg&) const. + **/ + CImgList get_eigen() const { + CImgList res(2); + eigen(res[0],res[1]); + return res; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& symmetric_eigen(CImg& val, CImg& vec) const { + if (is_empty()) { val.assign(); vec.assign(); return *this; } + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + val.assign(1,_width); + vec.assign(_width,_width); + + if (_width==1) { val[0] = cimg::abs((*this)[0]); vec[0] = 1; return *this; } + if (_width==2) { + const double + a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], + e = a + d, f = std::sqrt(std::max(e*e - 4*(a*d - b*c),0.0)), + l1 = 0.5*(e - f), l2 = 0.5*(e + f), + n = std::sqrt(cimg::sqr(l2 - a) + b*b); + val[0] = (t)l2; + val[1] = (t)l1; + if (n>0) { vec[0] = (t)(b/n); vec[2] = (t)((l2 - a)/n); } else { vec[0] = 1; vec[2] = 0; } + vec[1] = -vec[2]; + vec[3] = vec[0]; + return *this; + } + +#ifdef cimg_use_lapack + char JOB = 'V', UPLO = 'U'; + int N = _width, LWORK = 4*N, INFO; + Tfloat + *const lapA = new Tfloat[N*N], + *const lapW = new Tfloat[N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.", + cimg_instance, + INFO); + if (!INFO) { + cimg_forY(val,i) val(i) = (T)lapW[N - 1 -i]; + cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N - 1 - k)*N + l]); + } else { val.fill(0); vec.fill(0); } + delete[] lapA; delete[] lapW; delete[] WORK; + +#else + CImg V(_width,_width); + Tfloat M = 0, m = (Tfloat)min_max(M), maxabs = cimg::max((Tfloat)1,cimg::abs(m),cimg::abs(M)); + (CImg(*this,false)/=maxabs).SVD(vec,val,V,false); + if (maxabs!=1) val*=maxabs; + + bool is_ambiguous = false; + float eig = 0; + cimg_forY(val,p) { // Check for ambiguous cases + if (val[p]>eig) eig = (float)val[p]; + t scal = 0; + cimg_forY(vec,y) scal+=vec(p,y)*V(p,y); + if (cimg::abs(scal)<0.9f) is_ambiguous = true; + if (scal<0) val[p] = -val[p]; + } + if (is_ambiguous) { + ++(eig*=2); + SVD(vec,val,V,false,40,eig); + val-=eig; + } + + CImg permutations; // Sort eigenvalues in decreasing order + CImg tmp(_width); + val.sort(permutations,false); + cimg_forY(vec,k) { + cimg_forY(permutations,y) tmp(y) = vec(permutations(y),k); + std::memcpy(vec.data(0,k),tmp._data,sizeof(t)*_width); + } +#endif + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \return A list of two images [val; vec], whose meaning are similar as in + symmetric_eigen(CImg&,CImg&) const. + **/ + CImgList get_symmetric_eigen() const { + CImgList res(2); + symmetric_eigen(res[0],res[1]); + return res; + } + + //! Sort pixel values and get sorting permutations. + /** + \param[out] permutations Permutation map used for the sorting. + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + **/ + template + CImg& sort(CImg& permutations, const bool is_increasing=true) { + permutations.assign(_width,_height,_depth,_spectrum); + if (is_empty()) return *this; + cimg_foroff(permutations,off) permutations[off] = (t)off; + return _quicksort(0,size() - 1,permutations,is_increasing,true); + } + + //! Sort pixel values and get sorting permutations \newinstance. + template + CImg get_sort(CImg& permutations, const bool is_increasing=true) const { + return (+*this).sort(permutations,is_increasing); + } + + //! Sort pixel values. + /** + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + \param axis Tells if the value sorting must be done along a specific axis. Can be: + - \c 0: All pixel values are sorted, independently on their initial position. + - \c 'x': Image columns are sorted, according to the first value in each column. + - \c 'y': Image rows are sorted, according to the first value in each row. + - \c 'z': Image slices are sorted, according to the first value in each slice. + - \c 'c': Image channels are sorted, according to the first value in each channel. + **/ + CImg& sort(const bool is_increasing=true, const char axis=0) { + if (is_empty()) return *this; + CImg perm; + switch (cimg::lowercase(axis)) { + case 0 : + _quicksort(0,size() - 1,perm,is_increasing,false); + break; + case 'x' : { + perm.assign(_width); + get_crop(0,0,0,0,_width - 1,0,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(perm[x],y,z,c); + } break; + case 'y' : { + perm.assign(_height); + get_crop(0,0,0,0,0,_height - 1,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,perm[y],z,c); + } break; + case 'z' : { + perm.assign(_depth); + get_crop(0,0,0,0,0,0,_depth - 1,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,perm[z],c); + } break; + case 'c' : { + perm.assign(_spectrum); + get_crop(0,0,0,0,0,0,0,_spectrum - 1).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,z,perm[c]); + } break; + default : + throw CImgArgumentException(_cimg_instance + "sort(): Invalid specified axis '%c' " + "(should be { x | y | z | c }).", + cimg_instance,axis); + } + return *this; + } + + //! Sort pixel values \newinstance. + CImg get_sort(const bool is_increasing=true, const char axis=0) const { + return (+*this).sort(is_increasing,axis); + } + + template + CImg& _quicksort(const long indm, const long indM, CImg& permutations, + const bool is_increasing, const bool is_permutations) { + if (indm(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]>(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]>(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } else { + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]<(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } + if (indM - indm>=3) { + const T pivot = (*this)[mid]; + long i = indm, j = indM; + if (is_increasing) { + do { + while ((*this)[i]pivot) --j; + if (i<=j) { + if (is_permutations) cimg::swap(permutations[i],permutations[j]); + cimg::swap((*this)[i++],(*this)[j--]); + } + } while (i<=j); + } else { + do { + while ((*this)[i]>pivot) ++i; + while ((*this)[j] A; // Input matrix (assumed to contain some values) + CImg<> U,S,V; + A.SVD(U,S,V) + \endcode + **/ + template + const CImg& SVD(CImg& U, CImg& S, CImg& V, const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = (Ttfloat)1e-25; + + if (is_empty()) { U.assign(); S.assign(); V.assign(); } + else if (_depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "SVD(): Instance has invalid dimensions (depth or channels different from 1).", + cimg_instance); + else { + U = *this; + if (lambda!=0) { + const unsigned int delta = std::min(U._width,U._height); + for (unsigned int i = 0; i rv1(_width); + Ttfloat anorm = 0, c, f, g = 0, h, s, scale = 0; + int l = 0; + + cimg_forX(U,i) { + l = i + 1; + rv1[i] = scale*g; + g = s = scale = 0; + if (i=0?-1:1)*std::sqrt(s)); + h = f*g - s; + U(i,i) = f - g; + for (int j = l; j=0?-1:1)*std::sqrt(s)); + h = f*g - s; + U(l,i) = f - g; + for (int k = l; k=0; --i) { + if (i=0; --i) { + l = i + 1; + g = S[i]; + for (int j = l; j=0; --k) { + int nm = 0; + for (unsigned int its = 0; its=1; --l) { + nm = l - 1; + if ((cimg::abs(rv1[l]) + anorm)==anorm) { flag = false; break; } + if ((cimg::abs(S[nm]) + anorm)==anorm) break; + } + if (flag) { + c = 0; + s = 1; + for (int i = l; i<=k; ++i) { + f = s*rv1[i]; + rv1[i] = c*rv1[i]; + if ((cimg::abs(f) + anorm)==anorm) break; + g = S[i]; + h = cimg::_hypot(f,g); + S[i] = h; + h = 1/h; + c = g*h; + s = -f*h; + cimg_forY(U,j) { + const t y = U(nm,j), z = U(i,j); + U(nm,j) = y*c + z*s; + U(i,j) = z*c - y*s; + } + } + } + + const t z = S[k]; + if (l==k) { if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); } break; } + nm = k - 1; + t x = S[l], y = S[nm]; + g = rv1[nm]; + h = rv1[k]; + f = ((y - z)*(y + z) + (g - h)*(g + h))/std::max(epsilon,(Ttfloat)2*h*y); + g = cimg::_hypot(f,(Ttfloat)1); + f = ((x - z)*(x + z) + h*((y/(f + (f>=0?g:-g))) - h))/std::max(epsilon,(Ttfloat)x); + c = s = 1; + for (int j = l; j<=nm; ++j) { + const int i = j + 1; + g = rv1[i]; + h = s*g; + g = c*g; + t y1 = S[i], z1 = cimg::_hypot(f,h); + rv1[j] = z1; + c = f/std::max(epsilon,(Ttfloat)z1); + s = h/std::max(epsilon,(Ttfloat)z1); + f = x*c + g*s; + g = g*c - x*s; + h = y1*s; + y1*=c; + cimg_forX(U,jj) { + const t x2 = V(j,jj), z2 = V(i,jj); + V(j,jj) = x2*c + z2*s; + V(i,jj) = z2*c - x2*s; + } + z1 = cimg::_hypot(f,h); + S[j] = z1; + if (z1) { + z1 = 1/std::max(epsilon,(Ttfloat)z1); + c = f*z1; + s = h*z1; + } + f = c*g + s*y1; + x = c*y1 - s*g; + cimg_forY(U,jj) { + const t y2 = U(j,jj), z2 = U(i,jj); + U(j,jj) = y2*c + z2*s; + U(i,jj) = z2*c - y2*s; + } + } + rv1[l] = 0; + rv1[k] = f; + S[k] = x; + } + } + + if (sorting) { + CImg permutations; + CImg tmp(_width); + S.sort(permutations,false); + cimg_forY(U,k) { + cimg_forY(permutations,y) tmp(y) = U(permutations(y),k); + std::memcpy(U.data(0,k),tmp._data,sizeof(t)*_width); + } + cimg_forY(V,k) { + cimg_forY(permutations,y) tmp(y) = V(permutations(y),k); + std::memcpy(V.data(0,k),tmp._data,sizeof(t)*_width); + } + } + } + return *this; + } + + //! Compute the SVD of the instance image, viewed as a general matrix. + /** + \return A list of three images [U; S; V], whose meaning is similar as in + SVD(CImg&,CImg&,CImg&,bool,unsigned int,float) const. + **/ + CImgList get_SVD(const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + CImgList res(3); + SVD(res[0],res[1],res[2],sorting,max_iteration,lambda); + return res; + } + + // [internal] Compute the LU decomposition of a permuted matrix. + template + CImg& _LU(CImg& indx, bool& d) { + const int N = width(); + int imax = 0; + CImg vv(N); + indx.assign(N); + d = true; + + bool return0 = false; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=512)) + cimg_forX(*this,i) { + Tfloat vmax = 0; + cimg_forX(*this,j) { + const Tfloat tmp = cimg::abs((*this)(j,i)); + if (tmp>vmax) vmax = tmp; + } + if (vmax==0) return0 = true; else vv[i] = 1/vmax; + } + if (return0) { indx.fill(0); return fill(0); } + + cimg_forX(*this,j) { + for (int i = 0; i=vmax) { vmax = tmp; imax = i; } + } + if (j!=imax) { + cimg_forX(*this,k) cimg::swap((*this)(k,imax),(*this)(k,j)); + d = !d; + vv[imax] = vv[j]; + } + indx[j] = (t)imax; + if ((*this)(j,j)==0) (*this)(j,j) = (T)1e-20; + if (j=3 = orthogonal matching pursuit where an orthogonal projection step is performed + every 'method-2' iterations. + \param max_iter Sets the max number of iterations processed for each signal. + If set to '0' (default), 'max_iter' is set to the number of dictionary columns. + (only meaningful for matching pursuit and its variants). + \param max_residual Gives a stopping criterion on signal reconstruction accuracy. + (only meaningful for matching pursuit and its variants). + \return A matrix W whose columns correspond to the sparse weights of associated to each input matrix column. + Thus, the matrix product D*W is an approximation of the input matrix. + **/ + template + CImg& project_matrix(const CImg& dictionary, const unsigned int method=0, + const unsigned int max_iter=0, const double max_residual=1e-6) { + return get_project_matrix(dictionary,method,max_iter,max_residual).move_to(*this); + } + + template + CImg get_project_matrix(const CImg& dictionary, const unsigned int method=0, + const unsigned int max_iter=0, const double max_residual=1e-6) const { + if (_depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "project_matrix(): Instance image is not a matrix.", + cimg_instance); + if (dictionary._height!=_height || dictionary._depth!=1 || dictionary._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "project_matrix(): Specified dictionary (%u,%u,%u,%u) has an invalid size.", + cimg_instance, + dictionary._width,dictionary._height,dictionary._depth,dictionary._spectrum); + + if (!method) return get_solve(dictionary,true); + CImg W(_width,dictionary._width,1,1,0); + + // Compute dictionary norm and normalize it. + CImg D(dictionary,false), Dnorm(D._width); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=2 && _width*_height>=32)) + cimg_forX(Dnorm,d) { + Tfloat norm = 0; + cimg_forY(D,y) norm+=cimg::sqr(D(d,y)); + Dnorm[d] = std::max((Tfloat)1e-8,std::sqrt(norm)); + } + cimg_forXY(D,d,y) D(d,y)/=Dnorm[d]; + + // Matching pursuit. + const unsigned int proj_step = method<3?1:method - 2; + bool is_orthoproj = false; + + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=2 && _width*_height>=32)) + cimg_forX(*this,x) { + CImg S = get_column(x); + const CImg S0 = method<2?CImg():S; + Tfloat residual = S.magnitude()/S._height; + const unsigned int nmax = max_iter?max_iter:D._width; + + for (unsigned int n = 0; nmax_residual; ++n) { + + // Find best matching column in D. + int dmax = 0; + Tfloat absdotmax = 0, dotmax = 0; + cimg_pragma_openmp(parallel for cimg_openmp_if(D._width>=2 && D._width*D._height>=32)) + cimg_forX(D,d) { + Tfloat _dot = 0; + cimg_forY(D,y) _dot+=S[y]*D(d,y); + Tfloat absdot = cimg::abs(_dot); + cimg_pragma_openmp(critical(get_project_matrix)) { + if (absdot>absdotmax) { + absdotmax = absdot; + dotmax = _dot; + dmax = d; + } + } + } + + if (!n || method<3 || n%proj_step) { + // Matching Pursuit: Subtract component to signal. + W(x,dmax)+=dotmax; + residual = 0; + cimg_forY(S,y) { + S[y]-=dotmax*D(dmax,y); + residual+=cimg::sqr(S[y]); + } + residual = std::sqrt(residual)/S._height; + is_orthoproj = false; + + } else { + // Orthogonal Matching Pursuit: Orthogonal projection step. + W(x,dmax) = 1; // Used as a marker only. + unsigned int nbW = 0; + cimg_forY(W,d) if (W(x,d)) ++nbW; + CImg sD(nbW,D._height); + CImg inds(nbW); + int sd = 0; + cimg_forY(W,d) if (W(x,d)) { + cimg_forY(sD,y) sD(sd,y) = D(d,y); + inds[sd++] = d; + } + S0.get_solve(sD,true).move_to(sD); // sD is now a one-column vector of weights + + // Recompute residual signal. + S = S0; + cimg_forY(sD,k) { + const Tfloat weight = sD[k]; + const unsigned int ind = inds[k]; + W(x,ind) = weight; + cimg_forY(S,y) S[y]-=weight*D(ind,y); + } + residual = S.magnitude()/S._height; + is_orthoproj = true; + } + } + + // Perform last orthoprojection step if needed. + if (method>=2 && !is_orthoproj) { + unsigned int nbW = 0; + cimg_forY(W,d) if (W(x,d)) ++nbW; + if (nbW) { // Avoid degenerated case where 0 coefs are used + CImg sD(nbW,D._height); + CImg inds(nbW); + int sd = 0; + cimg_forY(W,d) if (W(x,d)) { + cimg_forY(sD,y) sD(sd,y) = D(d,y); + inds[sd++] = d; + } + S0.get_solve(sD,true).move_to(sD); + cimg_forY(sD,k) W(x,inds[k]) = sD[k]; + } + } + } + + // Normalize resulting coefficients according to initial (non-normalized) dictionary. + cimg_forXY(W,x,y) W(x,y)/=Dnorm[y]; + return W; + } + + //! Compute minimal path in a graph, using the Dijkstra algorithm. + /** + \param distance An object having operator()(unsigned int i, unsigned int j) which returns distance + between two nodes (i,j). + \param nb_nodes Number of graph nodes. + \param starting_node Index of the starting node. + \param ending_node Index of the ending node (set to ~0U to ignore ending node). + \param previous_node Array that gives the previous node index in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + **/ + template + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + if (starting_node>=nb_nodes) + throw CImgArgumentException("CImg<%s>::dijkstra(): Specified index of starting node %u is higher " + "than number of nodes %u.", + pixel_type(),starting_node,nb_nodes); + CImg dist(1,nb_nodes,1,1,cimg::type::max()); + dist(starting_node) = 0; + previous_node.assign(1,nb_nodes,1,1,(t)-1); + previous_node(starting_node) = (t)starting_node; + CImg Q(nb_nodes); + cimg_forX(Q,u) Q(u) = (unsigned int)u; + cimg::swap(Q(starting_node),Q(0)); + unsigned int sizeQ = nb_nodes; + while (sizeQ) { + // Update neighbors from minimal vertex + const unsigned int umin = Q(0); + if (umin==ending_node) sizeQ = 0; + else { + const T dmin = dist(umin); + const T infty = cimg::type::max(); + for (unsigned int q = 1; qdist(Q(left))) || + (rightdist(Q(right)));) { + if (right + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node=~0U) { + CImg foo; + return dijkstra(distance,nb_nodes,starting_node,ending_node,foo); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + /** + \param starting_node Index of the starting node. + \param ending_node Index of the ending node. + \param previous_node Array that gives the previous node index in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + \note image instance corresponds to the adjacency matrix of the graph. + **/ + template + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + return get_dijkstra(starting_node,ending_node,previous_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + template + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) const { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "dijkstra(): Instance is not a graph adjacency matrix.", + cimg_instance); + + return dijkstra(*this,_width,starting_node,ending_node,previous_node); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) { + return get_dijkstra(starting_node,ending_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) const { + CImg foo; + return get_dijkstra(starting_node,ending_node,foo); + } + + //! Return an image containing the character codes of specified string. + /** + \param str input C-string to encode as an image. + \param is_last_zero Tells if the ending \c '0' character appear in the resulting image. + \param is_shared Return result that shares its buffer with \p str. + **/ + static CImg string(const char *const str, const bool is_last_zero=true, const bool is_shared=false) { + if (!str) return CImg(); + return CImg(str,(unsigned int)std::strlen(str) + (is_last_zero?1:0),1,1,1,is_shared); + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg row_vector(const T& a0) { + return vector(a0); + } + + //! Return a \c 2x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg row_vector(const T& a0, const T& a1) { + CImg r(2,1); + r[0] = a0; r[1] = a1; + return r; + } + + //! Return a \c 3x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg row_vector(const T& a0, const T& a1, const T& a2) { + CImg r(3,1); + r[0] = a0; r[1] = a1; r[2] = a2; + return r; + } + + //! Return a \c 4x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(4,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; + return r; + } + + //! Return a \c 5x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(5,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; + return r; + } + + //! Return a \c 6x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(6,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; + return r; + } + + //! Return a \c 7x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(7,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; + return r; + } + + //! Return a \c 8x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(8,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; + return r; + } + + //! Return a \c 9x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(9,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; + return r; + } + + //! Return a \c 10x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(10,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + return r; + } + + //! Return a \c 11x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(11,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; + return r; + } + + //! Return a \c 12x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(12,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; + return r; + } + + //! Return a \c 13x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(13,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; + return r; + } + + //! Return a \c 14x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(14,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; + return r; + } + + //! Return a \c 15x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(15,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; + return r; + } + + //! Return a \c 16x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(16,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; r[15] = a15; + return r; + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg vector(const T& a0) { + CImg r(1,1); + r[0] = a0; + return r; + } + + //! Return a \c 1x2 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg vector(const T& a0, const T& a1) { + CImg r(1,2); + r[0] = a0; r[1] = a1; + return r; + } + + //! Return a \c 1x3 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2) { + CImg r(1,3); + r[0] = a0; r[1] = a1; r[2] = a2; + return r; + } + + //! Return a \c 1x4 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(1,4); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; + return r; + } + + //! Return a \c 1x5 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(1,5); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; + return r; + } + + //! Return a \c 1x6 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(1,6); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; + return r; + } + + //! Return a \c 1x7 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(1,7); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; + return r; + } + + //! Return a \c 1x8 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(1,8); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; + return r; + } + + //! Return a \c 1x9 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(1,9); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; + return r; + } + + //! Return a \c 1x10 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(1,10); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + return r; + } + + //! Return a \c 1x11 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(1,11); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; + return r; + } + + //! Return a \c 1x12 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(1,12); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; + return r; + } + + //! Return a \c 1x13 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(1,13); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; + return r; + } + + //! Return a \c 1x14 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(1,14); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; + return r; + } + + //! Return a \c 1x15 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(1,15); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; + return r; + } + + //! Return a \c 1x16 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(1,16); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; r[15] = a15; + return r; + } + + //! Return a 1x1 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg matrix(const T& a0) { + return vector(a0); + } + + //! Return a 2x2 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, + const T& a2, const T& a3) { + CImg r(2,2); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; + *(ptr++) = a2; *(ptr++) = a3; + return r; + } + + //! Return a 3x3 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + \param a4 Fifth matrix value. + \param a5 Sixth matrix value. + \param a6 Seventh matrix value. + \param a7 Eighth matrix value. + \param a8 Ninth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, const T& a2, + const T& a3, const T& a4, const T& a5, + const T& a6, const T& a7, const T& a8) { + CImg r(3,3); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; + *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; + *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; + return r; + } + + //! Return a 4x4 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(4,4); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; + return r; + } + + //! Return a 5x5 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, + const T& a5, const T& a6, const T& a7, const T& a8, const T& a9, + const T& a10, const T& a11, const T& a12, const T& a13, const T& a14, + const T& a15, const T& a16, const T& a17, const T& a18, const T& a19, + const T& a20, const T& a21, const T& a22, const T& a23, const T& a24) { + CImg r(5,5); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; + *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; *(ptr++) = a9; + *(ptr++) = a10; *(ptr++) = a11; *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; + *(ptr++) = a15; *(ptr++) = a16; *(ptr++) = a17; *(ptr++) = a18; *(ptr++) = a19; + *(ptr++) = a20; *(ptr++) = a21; *(ptr++) = a22; *(ptr++) = a23; *(ptr++) = a24; + return r; + } + + //! Return a 1x1 symmetric matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg tensor(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 symmetric matrix tensor containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2) { + return matrix(a0,a1,a1,a2); + } + + //! Return a 3x3 symmetric matrix containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + return matrix(a0,a1,a2,a1,a3,a4,a2,a4,a5); + } + + //! Return a 1x1 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1) { + return matrix(a0,0,0,a1); + } + + //! Return a 3x3 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2) { + return matrix(a0,0,0,0,a1,0,0,0,a2); + } + + //! Return a 4x4 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3) { + return matrix(a0,0,0,0,0,a1,0,0,0,0,a2,0,0,0,0,a3); + } + + //! Return a 5x5 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + return matrix(a0,0,0,0,0,0,a1,0,0,0,0,0,a2,0,0,0,0,0,a3,0,0,0,0,0,a4); + } + + //! Return a NxN identity matrix. + /** + \param N Dimension of the matrix. + **/ + static CImg identity_matrix(const unsigned int N) { + CImg res(N,N,1,1,0); + cimg_forX(res,x) res(x,x) = 1; + return res; + } + + //! Return a N-numbered sequence vector from \p a0 to \p a1. + /** + \param N Size of the resulting vector. + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + static CImg sequence(const unsigned int N, const T& a0, const T& a1) { + if (N) return CImg(1,N).sequence(a0,a1); + return CImg(); + } + + //! Return a 3x3 rotation matrix from an { axis + angle } or a quaternion. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or third quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + static CImg rotation_matrix(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + double X, Y, Z, W, N; + if (is_quaternion) { + N = std::sqrt((double)x*x + (double)y*y + (double)z*z + (double)w*w); + if (N>0) { X = x/N; Y = y/N; Z = z/N; W = w/N; } + else { X = Y = Z = 0; W = 1; } + return CImg::matrix((T)(X*X + Y*Y - Z*Z - W*W),(T)(2*Y*Z - 2*X*W),(T)(2*X*Z + 2*Y*W), + (T)(2*X*W + 2*Y*Z),(T)(X*X - Y*Y + Z*Z - W*W),(T)(2*Z*W - 2*X*Y), + (T)(2*Y*W - 2*X*Z),(T)(2*X*Y + 2*Z*W),(T)(X*X - Y*Y - Z*Z + W*W)); + } + N = cimg::hypot((double)x,(double)y,(double)z); + if (N>0) { X = x/N; Y = y/N; Z = z/N; } + else { X = Y = 0; Z = 1; } + const double ang = w*cimg::PI/180, c = std::cos(ang), omc = 1 - c, s = std::sin(ang); + return CImg::matrix((T)(X*X*omc + c),(T)(X*Y*omc - Z*s),(T)(X*Z*omc + Y*s), + (T)(X*Y*omc + Z*s),(T)(Y*Y*omc + c),(T)(Y*Z*omc - X*s), + (T)(X*Z*omc - Y*s),(T)(Y*Z*omc + X*s),(T)(Z*Z*omc + c)); + } + + //@} + //----------------------------------- + // + //! \name Value Manipulation + //@{ + //----------------------------------- + + //! Fill all pixel values with specified value. + /** + \param val Fill value. + **/ + CImg& fill(const T& val) { + if (is_empty()) return *this; + if (val && sizeof(T)!=1) cimg_for(*this,ptrd,T) *ptrd = val; + else std::memset(_data,(int)(ulongT)val,sizeof(T)*size()); // Double cast to allow val to be (void*) + return *this; + } + + //! Fill all pixel values with specified value \newinstance. + CImg get_fill(const T& val) const { + return CImg(_width,_height,_depth,_spectrum).fill(val); + } + + //! Fill sequentially all pixel values with specified values. + /** + \param val0 First fill value. + \param val1 Second fill value. + **/ + CImg& fill(const T& val0, const T& val1) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 1; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 2; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 3; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 4; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 5; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 6; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 7; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 8; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 9; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 10; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 11; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 12; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 13; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 14; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 15; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14,val15); + } + + //! Fill sequentially pixel values according to a given expression. + /** + \param expression C-string describing a math formula, or a sequence of values. + \param repeat_values In case a list of values is provided, tells if this list must be repeated for the filling. + \param allow_formula Tells that mathematical formulas are authorized for the filling. + \param list_inputs In case of a mathematical expression, attach a list of images to the specified expression. + \param[out] list_outputs In case of a math expression, list of images atatched to the specified expression. + **/ + CImg& fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _fill(expression,repeat_values,allow_formula?1:0,list_inputs,list_outputs,"fill",0); + } + + // 'formula_mode' = { 0 = does not allow formula | 1 = allow formula | + // 2 = allow formula and do not fill image values }. + CImg& _fill(const char *const expression, const bool repeat_values, const unsigned int formula_mode, + const CImgList *const list_inputs, CImgList *const list_outputs, + const char *const calling_function, const CImg *provides_copy) { + if (is_empty() || !expression || !*expression) return *this; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + CImg is_error; + bool is_value_sequence = false; + cimg_abort_init; + + if (formula_mode) { + + // Try to pre-detect regular value sequence to avoid exception thrown by _cimg_math_parser. + double value; + char sep; + const int err = cimg_sscanf(expression,"%lf %c",&value,&sep); + if (err==1 || (err==2 && sep==',')) { + if (err==1) { if (formula_mode==2) return *this; return fill((T)value); } + else is_value_sequence = true; + } + + // Try to fill values according to a formula. + _cimg_abort_init_openmp; + if (!is_value_sequence) try { + CImg base = provides_copy?provides_copy->get_shared():get_shared(); + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'), + calling_function,base,this,list_inputs,list_outputs,true); + if (!provides_copy && expression && *expression!='>' && *expression!='<' && *expression!=':' && + mp.need_input_copy) + base.assign().assign(*this,false); // Needs input copy + + // Determine 2nd largest image dimension (used as axis for inner loop in parallelized evaluation). + unsigned int M; + if (mp.result_dim) { + M = cimg::max(_width,_height,_depth); + M = M==_width?std::max(_height,_depth):M==_height?std::max(_width,_depth):std::max(_width,_height); + } else { + M = cimg::max(_width,_height,_depth,_spectrum); + M = M==_width?cimg::max(_height,_depth,_spectrum): + M==_height?cimg::max(_width,_depth,_spectrum): + M==_depth?cimg::max(_width,_height,_spectrum):cimg::max(_width,_height,_depth); + } + + bool do_in_parallel = false; +#if cimg_use_openmp!=0 + cimg_openmp_if(*expression=='*' || *expression==':' || + (mp.is_parallelizable && M>=(cimg_openmp_sizefactor)*320 && size()/M>=2)) + do_in_parallel = true; +#endif + if (mp.result_dim) { // Vector-valued expression + const unsigned int N = std::min(mp.result_dim,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = *expression=='<'?_data + _width*_height*_depth - 1:_data; + if (*expression=='<') { + CImg res(1,mp.result_dim); + mp.begin_t(); + cimg_rofYZ(*this,y,z) { + cimg_abort_test; + if (formula_mode==2) cimg_rofX(*this,x) mp(x,y,z,0); + else cimg_rofX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd--; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + mp.end_t(); + + } else if (*expression=='>' || !do_in_parallel) { + CImg res(1,mp.result_dim); + mp.begin_t(); + cimg_forYZ(*this,y,z) { + cimg_abort_test; + if (formula_mode==2) cimg_forX(*this,x) mp(x,y,z,0); + else cimg_forX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + mp.end_t(); + + } else { + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_fill)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + lmp.is_fill = true; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + +#define _cimg_fill_openmp_vector(_YZ,_y,_z,_X,_x,_sx,_sy,_sz,_off) \ + cimg_pragma_openmp(for cimg_openmp_collapse(2)) \ + cimg_for##_YZ(*this,_y,_z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + if (formula_mode==2) cimg_for##_X(*this,_x) lmp(x,y,z,0); \ + else { \ + CImg res(1,lmp.result_dim); \ + T *__ptrd = data(_sx,_sy,_sz,0); \ + const ulongT off = (ulongT)_off; \ + cimg_for##_X(*this,_x) { \ + lmp(x,y,z,0,res._data); \ + const double *ptrs = res._data; \ + T *_ptrd = __ptrd; \ + for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } \ + __ptrd+=off; \ + } \ + } \ + } _cimg_abort_catch_openmp _cimg_abort_catch_fill_openmp + + if (M==_width) { _cimg_fill_openmp_vector(YZ,y,z,X,x,0,y,z,1) } + else if (M==_height) { _cimg_fill_openmp_vector(XZ,x,z,Y,y,x,0,z,_width) } + else { _cimg_fill_openmp_vector(XY,x,y,Z,z,x,y,0,_width*_height) } + + lmp.end_t(); + cimg_pragma_openmp(barrier) cimg_pragma_openmp(critical) { lmp.merge(mp); } + if (&lmp!=&mp) delete &lmp; + } +#endif + } + + } else { // Scalar-valued expression + T *ptrd = *expression=='<'?end() - 1:_data; + if (*expression=='<') { + mp.begin_t(); + if (formula_mode==2) cimg_rofYZC(*this,y,z,c) { cimg_abort_test; cimg_rofX(*this,x) mp(x,y,z,c); } + else cimg_rofYZC(*this,y,z,c) { cimg_abort_test; cimg_rofX(*this,x) *(ptrd--) = (T)mp(x,y,z,c); } + mp.end_t(); + + } else if (*expression=='>' || !do_in_parallel) { + mp.begin_t(); + if (formula_mode==2) cimg_forYZC(*this,y,z,c) { cimg_abort_test; cimg_forX(*this,x) mp(x,y,z,c); } + else cimg_forYZC(*this,y,z,c) { cimg_abort_test; cimg_forX(*this,x) *(ptrd++) = (T)mp(x,y,z,c); } + mp.end_t(); + + } else { + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_fill)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + lmp.is_fill = true; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + +#define _cimg_fill_openmp_scalar(_YZC,_y,_z,_c,_X,_x,_sx,_sy,_sz,_sc,_off) \ + cimg_pragma_openmp(for cimg_openmp_collapse(3)) \ + cimg_for##_YZC(*this,_y,_z,_c) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + if (formula_mode==2) cimg_for##_X(*this,_x) lmp(x,y,z,c); \ + else { \ + T *_ptrd = data(_sx,_sy,_sz,_sc); \ + const ulongT off = (ulongT)_off; \ + cimg_for##_X(*this,_x) { *_ptrd = (T)lmp(x,y,z,c); _ptrd+=off; } \ + } \ + } _cimg_abort_catch_openmp _cimg_abort_catch_fill_openmp + + if (M==_width) { _cimg_fill_openmp_scalar(YZC,y,z,c,X,x,0,y,z,c,1) } + else if (M==_height) { _cimg_fill_openmp_scalar(XZC,x,z,c,Y,y,x,0,z,c,_width) } + else if (M==_depth) { _cimg_fill_openmp_scalar(XYC,x,y,c,Z,z,x,y,0,c,_width*_height) } + else { _cimg_fill_openmp_scalar(XYZ,x,y,z,C,c,x,y,z,0,_width*_height*_depth) } + + lmp.end_t(); + cimg_pragma_openmp(barrier) cimg_pragma_openmp(critical) { lmp.merge(mp); } + if (&lmp!=&mp) delete &lmp; + } +#endif + } + } + mp.end(); + } catch (CImgException& e) { CImg::string(e._message).move_to(is_error); } + } + + // Try to fill values according to a value sequence. + if (!formula_mode || is_value_sequence || is_error) { + CImg item(256); + char sep = 0; + const char *nexpression = expression; + ulongT nb = 0; + const ulongT siz = size(); + T *ptrd = _data; + for (double val = 0; *nexpression && nb0 && cimg_sscanf(item,"%lf",&val)==1 && (sep==',' || sep==';' || err==1)) { + nexpression+=std::strlen(item) + (err>1); + *(ptrd++) = (T)val; + } else break; + } + cimg::exception_mode(omode); + if (nb get_fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return (+*this).fill(expression,repeat_values,allow_formula?1:0,list_inputs,list_outputs); + } + + //! Fill sequentially pixel values according to the values found in another image. + /** + \param values Image containing the values used for the filling. + \param repeat_values In case there are less values than necessary in \c values, tells if these values must be + repeated for the filling. + **/ + template + CImg& fill(const CImg& values, const bool repeat_values=true) { + if (is_empty() || !values) return *this; + T *ptrd = _data, *ptre = ptrd + size(); + for (t *ptrs = values._data, *ptrs_end = ptrs + values.size(); ptrs + CImg get_fill(const CImg& values, const bool repeat_values=true) const { + return repeat_values?CImg(_width,_height,_depth,_spectrum).fill(values,repeat_values): + (+*this).fill(values,repeat_values); + } + + //! Fill pixel values along the X-axis at a specified pixel position. + /** + \param y Y-coordinate of the filled column. + \param z Z-coordinate of the filled column. + \param c C-coordinate of the filled column. + \param a0 First fill value. + **/ + CImg& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const int a0, ...) { +#define _cimg_fill1(x,y,z,c,off,siz,t) { \ + va_list ap; va_start(ap,a0); T *ptrd = data(x,y,z,c); *ptrd = (T)a0; \ + for (unsigned int k = 1; k& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const double a0, ...) { + if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,double); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position. + /** + \param x X-coordinate of the filled row. + \param z Z-coordinate of the filled row. + \param c C-coordinate of the filled row. + \param a0 First fill value. + **/ + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const int a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,int); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position \overloading. + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const double a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,double); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position. + /** + \param x X-coordinate of the filled slice. + \param y Y-coordinate of the filled slice. + \param c C-coordinate of the filled slice. + \param a0 First fill value. + **/ + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,int); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position \overloading. + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const double a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,double); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position. + /** + \param x X-coordinate of the filled channel. + \param y Y-coordinate of the filled channel. + \param z Z-coordinate of the filled channel. + \param a0 First filling value. + **/ + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const int a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,int); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position \overloading. + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const double a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,double); + return *this; + } + + //! Discard specified sequence of values in the image buffer, along a specific axis. + /** + \param values Sequence of values to discard. + \param axis Axis along which the values are discarded. If set to \c 0 (default value) + the method does it for all the buffer values and returns a one-column vector. + \note Discarded values will change the image geometry, so the resulting image + is returned as a one-column vector. + **/ + template + CImg& discard(const CImg& values, const char axis=0) { + if (is_empty() || !values) return *this; + return get_discard(values,axis).move_to(*this); + } + + template + CImg get_discard(const CImg& values, const char axis=0) const { + if (!values) return +*this; + CImg res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + ulongT j = 0; + unsigned int k = 0; + int i0 = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) { + if ((*this)(i)!=(T)values[j]) { + if (j) --i; + res.draw_image(k,get_columns(i0,i)); + k+=i - i0 + 1; i0 = i + 1; j = 0; + } else { ++j; if (j>=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = (int)i + 1; }} + } + if ((ulongT)i0& discard(const char axis=0) { + return get_discard(axis).move_to(*this); + } + + //! Discard neighboring duplicates in the image buffer, along the specified axis \newinstance. + CImg get_discard(const char axis=0) const { + CImg res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + T current = *_data?(T)0:(T)1; + int j = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) + if ((*this)(i)!=current) { res.draw_image(j++,get_column(i)); current = (*this)(i); } + res.resize(j,-100,-100,-100,0); + } break; + case 'y' : { + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { res.draw_image(0,j++,get_row(i)); current = (*this)(0,i); } + res.resize(-100,j,-100,-100,0); + } break; + case 'z' : { + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { res.draw_image(0,0,j++,get_slice(i)); current = (*this)(0,0,i); } + res.resize(-100,-100,j,-100,0); + } break; + case 'c' : { + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { res.draw_image(0,0,0,j++,get_channel(i)); current = (*this)(0,0,0,i); } + res.resize(-100,-100,-100,j,0); + } break; + default : { + res.unroll('y'); + cimg_foroff(*this,i) { + const T val = (*this)[i]; + if (val!=current) res[j++] = current = val; + } + res.resize(-100,j,-100,-100,0); + } + } + return res; + } + + //! Invert endianness of all pixel values. + /** + **/ + CImg& invert_endianness() { + cimg::invert_endianness(_data,size()); + return *this; + } + + //! Invert endianness of all pixel values \newinstance. + CImg get_invert_endianness() const { + return (+*this).invert_endianness(); + } + + //! Fill image with random values in specified range. + /** + \param val_min Minimal authorized random value. + \param val_max Maximal authorized random value. + \note Random variables are uniformly distributed in [val_min,val_max]. + **/ + CImg& rand(const T& val_min, const T& val_max) { + const float delta = (float)val_max - (float)val_min + (cimg::type::is_float()?0:1); + if (cimg::type::is_float()) cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),524288)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) _data[off] = (T)(val_min + delta*cimg::rand(1,&rng)); + cimg::srand(rng); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),524288)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) _data[off] = std::min(val_max,(T)(val_min + delta*cimg::rand(1,&rng))); + cimg::srand(rng); + } + return *this; + } + + //! Fill image with random values in specified range \newinstance. + CImg get_rand(const T& val_min, const T& val_max) const { + return (+*this).rand(val_min,val_max); + } + + //! Round pixel values. + /** + \param y Rounding precision. + \param rounding_type Rounding type. Can be: + - \c -1: Backward. + - \c 0: Nearest. + - \c 1: Forward. + **/ + CImg& round(const double y=1, const int rounding_type=0) { + if (y>0) cimg_openmp_for(*this,cimg::round(*ptr,y,rounding_type),8192); + return *this; + } + + //! Round pixel values \newinstance. + CImg get_round(const double y=1, const unsigned int rounding_type=0) const { + return (+*this).round(y,rounding_type); + } + + //! Add random noise to pixel values. + /** + \param sigma Amplitude of the random additive noise. If \p sigma<0, it stands for a percentage of the + global value range. + \param noise_type Type of additive noise (can be \p 0=gaussian, \p 1=uniform, \p 2=Salt and Pepper, + \p 3=Poisson or \p 4=Rician). + \return A reference to the modified image instance. + \note + - For Poisson noise (\p noise_type=3), parameter \p sigma is ignored, as Poisson noise only depends on + the image value itself. + - Function \p CImg::get_noise() is also defined. It returns a non-shared modified copy of the image instance. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_noise(40); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_noise.jpg + **/ + CImg& noise(const double sigma, const unsigned int noise_type=0) { + if (is_empty()) return *this; + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + Tfloat nsigma = (Tfloat)sigma, m = 0, M = 0; + if (nsigma==0 && noise_type!=3) return *this; + if (nsigma<0 || noise_type==2) m = (Tfloat)min_max(M); + if (nsigma<0) nsigma = (Tfloat)(-nsigma*(M-m)/100.); + switch (noise_type) { + case 0 : { // Gaussian noise + cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) { + Tfloat val = (Tfloat)(_data[off] + nsigma*cimg::grand(&rng)); + if (val>vmax) val = vmax; + if (valvmax) val = vmax; + if (val::is_float()) { --m; ++M; } + else { m = (Tfloat)cimg::type::min(); M = (Tfloat)cimg::type::max(); } + } + cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) if (cimg::rand(100,&rng)vmax) val = vmax; + if (val get_noise(const double sigma, const unsigned int noise_type=0) const { + return (+*this).noise(sigma,noise_type); + } + + //! Linearly normalize pixel values. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \param constant_case_ratio In case of instance image having a constant value, tell what ratio + of [min_value,max_value] is used to fill the normalized image + (=0 for min_value, =1 for max_value, =0.5 for (min_value + max_value)/2). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(160,220); + (img,res).display(); + \endcode + \image html ref_normalize2.jpg + **/ + CImg& normalize(const T& min_value, const T& max_value, + const float constant_case_ratio=0) { + if (is_empty()) return *this; + const T a = min_value get_normalize(const T& min_value, const T& max_value, + const float ratio_if_constant_image=0) const { + return CImg(*this,false).normalize((Tfloat)min_value,(Tfloat)max_value,ratio_if_constant_image); + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm. + /** + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_normalize.jpg + **/ + CImg& normalize() { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + T *ptrd = data(0,y,z,0); + cimg_forX(*this,x) { + const T *ptrs = ptrd; + float n = 0; + cimg_forC(*this,c) { n+=cimg::sqr((float)*ptrs); ptrs+=whd; } + n = (float)std::sqrt(n); + T *_ptrd = ptrd++; + if (n>0) cimg_forC(*this,c) { *_ptrd = (T)(*_ptrd/n); _ptrd+=whd; } + else cimg_forC(*this,c) { *_ptrd = (T)0; _ptrd+=whd; } + } + } + return *this; + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm \newinstance. + CImg get_normalize() const { + return CImg(*this,false).normalize(); + } + + //! Compute Lp-norm of each multi-valued pixel of the image instance. + /** + \param norm_type Type of computed vector norm (can be \p -1=Linf, or \p greater or equal than 0). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_norm(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_norm.jpg + **/ + CImg& norm(const int norm_type=2) { + if (_spectrum==1 && norm_type) return abs(); + return get_norm(norm_type).move_to(*this); + } + + //! Compute L2-norm of each multi-valued pixel of the image instance \newinstance. + CImg get_norm(const int norm_type=2) const { + if (is_empty()) return *this; + if (_spectrum==1 && norm_type) return get_abs(); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(_width,_height,_depth); + switch (norm_type) { + case -1 : { // Linf-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { const Tfloat val = (Tfloat)cimg::abs(*_ptrs); if (val>n) n = val; _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 0 : { // L0-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + unsigned int n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=*_ptrs==0?0:1; _ptrs+=whd; } + *(ptrd++) = (Tfloat)n; + } + } + } break; + case 1 : { // L1-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::abs(*_ptrs); _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 2 : { // L2-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::sqr((Tfloat)*_ptrs); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::sqrt((Tfloat)n); + } + } + } break; + default : { // Linf-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=std::pow(cimg::abs((Tfloat)*_ptrs),(Tfloat)norm_type); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::pow((Tfloat)n,1/(Tfloat)norm_type); + } + } + } + } + return res; + } + + //! Cut pixel values in specified range. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_cut(160,220); + (img,res).display(); + \endcode + \image html ref_cut.jpg + **/ + CImg& cut(const T& min_value, const T& max_value) { + if (is_empty()) return *this; + const T a = min_value get_cut(const T& min_value, const T& max_value) const { + return (+*this).cut(min_value,max_value); + } + + //! Uniformly quantize pixel values. + /** + \param nb_levels Number of quantization levels. + \param keep_range Tells if resulting values keep the same range as the original ones. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_quantize(4); + (img,res).display(); + \endcode + \image html ref_quantize.jpg + **/ + CImg& quantize(const unsigned int nb_levels, const bool keep_range=true) { + if (!nb_levels) + throw CImgArgumentException(_cimg_instance + "quantize(): Invalid quantization request with 0 values.", + cimg_instance); + + if (is_empty()) return *this; + Tfloat m, M = (Tfloat)max_min(m), range = M - m; + if (range>0) { + if (keep_range) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range); + _data[off] = (T)(m + std::min(val,nb_levels - 1)*range/nb_levels); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range); + _data[off] = (T)std::min(val,nb_levels - 1); + } + } + return *this; + } + + //! Uniformly quantize pixel values \newinstance. + CImg get_quantize(const unsigned int n, const bool keep_range=true) const { + return (+*this).quantize(n,keep_range); + } + + //! Threshold pixel values. + /** + \param value Threshold value + \param soft_threshold Tells if soft thresholding must be applied (instead of hard one). + \param strict_threshold Tells if threshold value is strict. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_threshold(128); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_threshold.jpg + **/ + CImg& threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) { + if (is_empty()) return *this; + if (strict_threshold) { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const T v = _data[off]; + _data[off] = v>value?(T)(v-value):v<-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),65536)) + cimg_rofoff(*this,off) _data[off] = _data[off]>value?(T)1:(T)0; + } else { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const T v = _data[off]; + _data[off] = v>=value?(T)(v-value):v<=-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),65536)) + cimg_rofoff(*this,off) _data[off] = _data[off]>=value?(T)1:(T)0; + } + return *this; + } + + //! Threshold pixel values \newinstance. + CImg get_threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) const { + return (+*this).threshold(value,soft_threshold,strict_threshold); + } + + //! Compute the histogram of pixel values. + /** + \param nb_levels Number of desired histogram levels. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \note + - The histogram H of an image I is the 1D function where H(x) counts the number of occurrences of the value x + in the image I. + - The resulting histogram is always defined in 1D. Histograms of multi-valued images are not multi-dimensional. + \par Example + \code + const CImg img = CImg("reference.jpg").histogram(256); + img.display_graph(0,3); + \endcode + \image html ref_histogram.jpg + **/ + CImg& histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) { + return get_histogram(nb_levels,min_value,max_value).move_to(*this); + } + + //! Compute the histogram of pixel values \overloading. + CImg& histogram(const unsigned int nb_levels) { + return get_histogram(nb_levels).move_to(*this); + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) const { + if (!nb_levels || is_empty()) return CImg(); + const double + vmin = (double)(min_value res(nb_levels,1,1,1,0); + cimg_rof(*this,ptrs,T) { + const T val = *ptrs; + if (val>=vmin && val<=vmax) ++res[val==vmax?nb_levels - 1:(unsigned int)((val - vmin)*nb_levels/(vmax - vmin))]; + } + return res; + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels) const { + if (!nb_levels || is_empty()) return CImg(); + T vmax = 0, vmin = min_max(vmax); + return get_histogram(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values. + /** + \param nb_levels Number of histogram levels used for the equalization. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_equalize(256); + (img,res).display(); + \endcode + \image html ref_equalize.jpg + **/ + CImg& equalize(const unsigned int nb_levels, const T& min_value, const T& max_value) { + if (!nb_levels || is_empty()) return *this; + const T + vmin = min_value hist = get_histogram(nb_levels,vmin,vmax); + ulongT cumul = 0; + cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; } + if (!cumul) cumul = 1; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),1048576)) + cimg_rofoff(*this,off) { + const int pos = (int)((_data[off] - vmin)*(nb_levels - 1.)/(vmax - vmin)); + if (pos>=0 && pos<(int)nb_levels) _data[off] = (T)(vmin + (vmax - vmin)*hist[pos]/cumul); + } + return *this; + } + + //! Equalize histogram of pixel values \overloading. + CImg& equalize(const unsigned int nb_levels) { + if (!nb_levels || is_empty()) return *this; + T vmax = 0, vmin = min_max(vmax); + return equalize(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels, const T& val_min, const T& val_max) const { + return (+*this).equalize(nblevels,val_min,val_max); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels) const { + return (+*this).equalize(nblevels); + } + + //! Index multi-valued pixels regarding to a specified colormap. + /** + \param colormap Multi-valued colormap used as the basis for multi-valued pixel indexing. + \param dithering Level of dithering (0=disable, 1=standard level). + \param map_indexes Tell if the values of the resulting image are the colormap indices or the colormap vectors. + \note + - \p img.index(colormap,dithering,1) is equivalent to img.index(colormap,dithering,0).map(colormap). + \par Example + \code + const CImg img("reference.jpg"), colormap(3,1,1,3, 0,128,255, 0,128,255, 0,128,255); + const CImg res = img.get_index(colormap,1,true); + (img,res).display(); + \endcode + \image html ref_index.jpg + **/ + template + CImg& index(const CImg& colormap, const float dithering=1, const bool map_indexes=false) { + return get_index(colormap,dithering,map_indexes).move_to(*this); + } + + //! Index multi-valued pixels regarding to a specified colormap \newinstance. + template + CImg::Tuint> + get_index(const CImg& colormap, const float dithering=1, const bool map_indexes=true) const { + if (colormap._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "index(): Instance and specified colormap (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + typedef typename CImg::Tuint tuint; + if (is_empty()) return CImg(); + const ulongT + whd = (ulongT)_width*_height*_depth, + pwhd = (ulongT)colormap._width*colormap._height*colormap._depth; + CImg res(_width,_height,_depth,map_indexes?_spectrum:1); + if (dithering>0) { // Dithered versions + tuint *ptrd = res._data; + const float ndithering = cimg::cut(dithering,0,1)/16; + Tfloat valm = 0, valM = (Tfloat)max_min(valm); + if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; } + CImg cache = get_crop(-1,0,0,0,_width,1,0,_spectrum - 1); + Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0); + const ulongT cwhd = (ulongT)cache._width*cache._height*cache._depth; + switch (_spectrum) { + case 1 : { // Optimized for scalars + cimg_forYZ(*this,y,z) { + if (yvalM?valM:_val0; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1, + _val2 = (Tfloat)*ptrs2, val2 = _val2valM?valM:_val2; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrpvalM?valM:_val; + dist+=cimg::sqr((*_ptrs=val) - (Tfloat)*_ptrp); _ptrs+=cwhd; _ptrp+=pwhd; + } + if (dist=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs0 = data(0,y,z), *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd, + *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs = data(0,y,z), *ptrs_end = ptrs + _width; ptrs::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp img("reference.jpg"), + colormap1(3,1,1,3, 0,128,255, 0,128,255, 0,128,255), + colormap2(3,1,1,3, 255,0,0, 0,255,0, 0,0,255), + res = img.get_index(colormap1,0).map(colormap2); + (img,res).display(); + \endcode + \image html ref_map.jpg + **/ + template + CImg& map(const CImg& colormap, const unsigned int boundary_conditions=0) { + return get_map(colormap,boundary_conditions).move_to(*this); + } + + //! Map predefined colormap on the scalar (indexed) image instance \newinstance. + template + CImg get_map(const CImg& colormap, const unsigned int boundary_conditions=0) const { + const ulongT + whd = (ulongT)_width*_height*_depth, siz = size(), + cwhd = (ulongT)colormap._width*colormap._height*colormap._depth, + cwhd2 = 2*cwhd; + CImg res(_width,_height,_depth,_spectrum*colormap._spectrum); + switch (colormap._spectrum) { + + case 1 : { // Optimized for scalars + switch (boundary_conditions) { + case 3 : // Mirror + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),256)) + for (longT off = 0; off<(longT)siz; ++off) { + const ulongT ind = ((ulongT)_data[off])%cwhd2; + res[off] = colormap[ind& label(const bool is_high_connectivity=false, const Tfloat tolerance=0, + const bool is_L2_norm=true) { + if (is_empty()) return *this; + return get_label(is_high_connectivity,tolerance,is_L2_norm).move_to(*this); + } + + //! Label connected components \newinstance. + CImg get_label(const bool is_high_connectivity=false, const Tfloat tolerance=0, + const bool is_L2_norm=true) const { + if (is_empty()) return CImg(); + + // Create neighborhood tables. + int dx[13], dy[13], dz[13], nb = 0; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 0; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 0; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 0; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 0; + } + if (_depth>1) { // 3D version + dx[nb] = 0; dy[nb] = 0; dz[nb++]=1; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = -1; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = -1; + + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 1; + } + } + return _label(nb,dx,dy,dz,tolerance,is_L2_norm); + } + + //! Label connected components \overloading. + /** + \param connectivity_mask Mask of the neighboring pixels. + \param tolerance Tolerance used to determine if two neighboring pixels belong to the same region. + \param is_L2_norm If true, tolerance is compared against L2 difference, otherwise L1 is used. + **/ + template + CImg& label(const CImg& connectivity_mask, const Tfloat tolerance=0, + const bool is_L2_norm=true) { + if (is_empty()) return *this; + return get_label(connectivity_mask,tolerance,is_L2_norm).move_to(*this); + } + + //! Label connected components \newinstance. + template + CImg get_label(const CImg& connectivity_mask, const Tfloat tolerance=0, + const bool is_L2_norm=true) const { + if (is_empty()) return CImg(); + int nb = 0; + cimg_for(connectivity_mask,ptr,t) if (*ptr) ++nb; + CImg dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0); + nb = 0; + cimg_forXYZ(connectivity_mask,x,y,z) if ((x || y || z) && + connectivity_mask(x,y,z)) { + dx[nb] = x; dy[nb] = y; dz[nb++] = z; + } + return _label(nb,dx,dy,dz,tolerance,is_L2_norm); + } + + CImg _label(const unsigned int nb, const int *const dx, + const int *const dy, const int *const dz, + const Tfloat tolerance, const bool is_L2_norm) const { + CImg res(_width,_height,_depth); + const Tfloat _tolerance = _spectrum>1 && is_L2_norm?cimg::sqr(tolerance):tolerance; + + // Init label numbers. + ulongT *ptr = res.data(); + cimg_foroff(res,p) *(ptr++) = p; + + // For each neighbour-direction, label. + for (unsigned int n = 0; n& _system_strescape() { +#define cimg_system_strescape(c,s) case c : if (p!=ptrs) CImg(ptrs,(unsigned int)(p-ptrs),1,1,1,false).\ + move_to(list); \ + CImg(s,(unsigned int)std::strlen(s),1,1,1,false).move_to(list); ptrs = p + 1; break + CImgList list; + const T *ptrs = _data; + cimg_for(*this,p,T) switch ((int)*p) { + cimg_system_strescape('\\',"\\\\"); + cimg_system_strescape('\"',"\\\""); + cimg_system_strescape('!',"\"\\!\""); + cimg_system_strescape('`',"\\`"); + cimg_system_strescape('$',"\\$"); + } + if (ptrs(ptrs,(unsigned int)(end()-ptrs),1,1,1,false).move_to(list); + return (list>'x').move_to(*this); + } + + //@} + //--------------------------------- + // + //! \name Color Base Management + //@{ + //--------------------------------- + + //! Return colormap \e "default", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_default.jpg + **/ + static const CImg& default_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,256,1,3); + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap(0,index,0) = (Tuchar)r; + colormap(0,index,1) = (Tuchar)g; + colormap(0,index++,2) = (Tuchar)b; + } + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "HSV", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hsv.jpg + **/ + static const CImg& HSV_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + CImg tmp(1,256,1,3,1); + tmp.get_shared_channel(0).sequence(0,359); + colormap = tmp.HSVtoRGB(); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "lines", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_lines.jpg + **/ + static const CImg& lines_LUT256() { + static const unsigned char pal[] = { + 0,255,255,0,0,28,125,125,235,210,186,182,36,0,125,255, + 53,32,255,210,89,186,65,45,125,210,210,97,130,194,0,125, + 206,53,190,89,255,146,20,190,154,73,255,36,130,215,0,138, + 101,210,61,194,206,0,77,45,255,154,174,0,190,239,89,125, + 16,36,158,223,117,0,97,69,223,255,40,239,0,0,255,0, + 97,170,93,255,138,40,117,210,0,170,53,158,186,255,0,121, + 227,121,186,40,20,190,89,255,77,57,130,142,255,73,186,85, + 210,8,32,166,243,130,210,40,255,45,61,142,223,49,121,255, + 20,162,158,73,89,255,53,138,210,190,57,235,36,73,255,49, + 210,0,210,85,57,97,255,121,85,174,40,255,162,178,0,121, + 166,125,53,146,166,255,97,121,65,89,235,231,12,170,36,190, + 85,255,166,97,198,77,20,146,109,166,255,28,40,202,121,81, + 247,0,210,255,49,0,65,255,36,166,93,77,255,85,251,0, + 170,178,0,182,255,0,162,16,154,142,162,223,223,0,0,81, + 215,4,215,162,215,125,77,206,121,36,125,231,101,16,255,121, + 0,57,190,215,65,125,89,142,255,101,73,53,146,223,125,125, + 0,255,0,255,0,206,93,138,49,255,0,202,154,85,45,219, + 251,53,0,255,40,130,219,158,16,117,186,130,202,49,65,239, + 89,202,49,28,247,134,150,0,255,117,202,4,215,81,186,57, + 202,89,73,210,40,93,45,251,206,28,223,142,40,134,162,125, + 32,247,97,170,0,255,57,134,73,247,162,0,251,40,142,142, + 8,166,206,81,154,194,93,89,125,243,28,109,227,0,190,65, + 194,186,0,255,53,45,109,186,186,0,255,130,49,170,69,210, + 154,0,109,227,45,255,125,105,81,81,255,0,219,134,170,85, + 146,28,170,89,223,97,8,210,255,158,49,40,125,174,174,125, + 0,227,166,28,219,130,0,93,239,0,85,255,81,178,125,49, + 89,255,53,206,73,113,146,255,0,150,36,219,162,0,210,125, + 69,134,255,85,40,89,235,49,215,121,0,206,36,223,174,69, + 40,182,178,130,69,45,255,210,85,77,215,0,231,146,0,194, + 125,174,0,255,40,89,121,206,57,0,206,170,231,150,81,0, + 125,255,4,174,4,190,121,255,4,166,109,130,49,239,170,93, + 16,174,210,0,255,16,105,158,93,255,0,125,0,255,158,85, + 0,255,0,0,255,170,166,61,121,28,198,215,45,243,61,97, + 255,53,81,130,109,255,8,117,235,121,40,178,174,0,182,49, + 162,121,255,69,206,0,219,125,0,101,255,239,121,32,210,130, + 36,231,32,125,81,142,215,158,4,178,255,0,40,251,125,125, + 219,89,130,0,166,255,24,65,194,125,255,125,77,125,93,125, + 202,24,138,174,178,32,255,85,194,40,85,36,174,174,125,210, + 85,255,53,16,93,206,40,130,170,202,93,255,0,24,117,255, + 97,113,105,81,255,186,194,57,69,206,57,53,223,190,4,255, + 85,97,130,255,85,0,125,223,85,219,0,215,146,77,40,239, + 89,36,142,154,227,0,255,85,162,0,162,0,235,178,45,166, + 0,247,255,20,69,210,89,142,53,255,40,146,166,255,69,0, + 174,154,142,130,162,0,215,255,0,89,40,255,166,61,146,69, + 162,40,255,32,121,255,117,178,0,186,206,0,57,215,215,81, + 158,77,166,210,77,89,210,0,24,202,150,186,0,255,20,97, + 57,170,235,251,16,73,142,251,93,0,202,0,255,121,219,4, + 73,219,8,162,206,16,219,93,117,0,255,8,130,174,223,45 }; + static const CImg colormap(pal,1,256,1,3,false); + return colormap; + } + + //! Return colormap \e "hot", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hot.jpg + **/ + static const CImg& hot_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[1] = colormap[2] = colormap[3] = colormap[6] = colormap[7] = colormap[11] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cool", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cool.jpg + **/ + static const CImg& cool_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) colormap.assign(1,2,1,3).fill((T)0,(T)255,(T)255,(T)0,(T)255,(T)255).resize(1,256,1,3,3); + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "jet", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_jet.jpg + **/ + static const CImg& jet_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[2] = colormap[3] = colormap[5] = colormap[6] = colormap[8] = colormap[9] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "flag", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_flag.jpg + **/ + static const CImg& flag_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[0] = colormap[1] = colormap[5] = colormap[9] = colormap[10] = 255; + colormap.resize(1,256,1,3,0,2); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cube", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cube.jpg + **/ + static const CImg& cube_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,8,1,3,(T)0); + colormap[1] = colormap[3] = colormap[5] = colormap[7] = + colormap[10] = colormap[11] = colormap[12] = colormap[13] = + colormap[20] = colormap[21] = colormap[22] = colormap[23] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Convert pixel values from sRGB to RGB color spaces. + CImg& sRGBtoRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32)) + cimg_rofoff(*this,off) { + const Tfloat + sval = (Tfloat)_data[off]/255, + val = (Tfloat)(sval<=0.04045f?sval/12.92f:std::pow((sval + 0.055f)/(1.055f),2.4f)); + _data[off] = (T)cimg::cut(val*255,0,255); + } + return *this; + } + + //! Convert pixel values from sRGB to RGB color spaces \newinstance. + CImg get_sRGBtoRGB() const { + return CImg(*this,false).sRGBtoRGB(); + } + + //! Convert pixel values from RGB to sRGB color spaces. + CImg& RGBtosRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32)) + cimg_rofoff(*this,off) { + const Tfloat + val = (Tfloat)_data[off]/255, + sval = (Tfloat)(val<=0.0031308f?val*12.92f:1.055f*std::pow(val,0.416667f) - 0.055f); + _data[off] = (T)cimg::cut(sval*255,0,255); + } + return *this; + } + + //! Convert pixel values from RGB to sRGB color spaces \newinstance. + CImg get_RGBtosRGB() const { + return CImg(*this,false).RGBtosRGB(); + } + + //! Convert pixel values from RGB to HSI color spaces. + CImg& RGBtoHSI() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSI(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSI() const { + return CImg(*this,false).RGBtoHSI(); + } + + //! Convert pixel values from HSI to RGB color spaces. + CImg& HSItoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSItoRGB(): Instance is not a HSI image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSItoRGB() const { + return CImg< Tuchar>(*this,false).HSItoRGB(); + } + + //! Convert pixel values from RGB to HSL color spaces. + CImg& RGBtoHSL() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSL(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSL() const { + return CImg(*this,false).RGBtoHSL(); + } + + //! Convert pixel values from HSL to RGB color spaces. + CImg& HSLtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSLtoRGB(): Instance is not a HSL image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSLtoRGB() const { + return CImg(*this,false).HSLtoRGB(); + } + + //! Convert pixel values from RGB to HSV color spaces. + CImg& RGBtoHSV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSV(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSV() const { + return CImg(*this,false).RGBtoHSV(); + } + + //! Convert pixel values from HSV to RGB color spaces. + CImg& HSVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSVtoRGB(): Instance is not a HSV image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSVtoRGB() const { + return CImg(*this,false).HSVtoRGB(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& RGBtoYCbCr() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYCbCr(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,512)) + for (longT N = 0; N get_RGBtoYCbCr() const { + return CImg(*this,false).RGBtoYCbCr(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& YCbCrtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YCbCrtoRGB(): Instance is not a YCbCr image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,512)) + for (longT N = 0; N get_YCbCrtoRGB() const { + return CImg(*this,false).YCbCrtoRGB(); + } + + //! Convert pixel values from RGB to YUV color spaces. + CImg& RGBtoYUV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYUV(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,16384)) + for (longT N = 0; N get_RGBtoYUV() const { + return CImg(*this,false).RGBtoYUV(); + } + + //! Convert pixel values from YUV to RGB color spaces. + CImg& YUVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YUVtoRGB(): Instance is not a YUV image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,16384)) + for (longT N = 0; N get_YUVtoRGB() const { + return CImg< Tuchar>(*this,false).YUVtoRGB(); + } + + //! Convert pixel values from RGB to CMY color spaces. + CImg& RGBtoCMY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoCMY(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_RGBtoCMY() const { + return CImg(*this,false).RGBtoCMY(); + } + + //! Convert pixel values from CMY to RGB color spaces. + CImg& CMYtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoRGB(): Instance is not a CMY image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_CMYtoRGB() const { + return CImg(*this,false).CMYtoRGB(); + } + + //! Convert pixel values from CMY to CMYK color spaces. + CImg& CMYtoCMYK() { + return get_CMYtoCMYK().move_to(*this); + } + + //! Convert pixel values from CMY to CMYK color spaces \newinstance. + CImg get_CMYtoCMYK() const { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoCMYK(): Instance is not a CMY image.", + cimg_instance); + + CImg res(_width,_height,_depth,4); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024)) + for (longT N = 0; N=255) C = M = Y = 0; + else { const Tfloat K1 = 255 - K; C = 255*(C - K)/K1; M = 255*(M - K)/K1; Y = 255*(Y - K)/K1; } + pd1[N] = (Tfloat)cimg::cut(C,0,255), + pd2[N] = (Tfloat)cimg::cut(M,0,255), + pd3[N] = (Tfloat)cimg::cut(Y,0,255), + pd4[N] = (Tfloat)cimg::cut(K,0,255); + } + return res; + } + + //! Convert pixel values from CMYK to CMY color spaces. + CImg& CMYKtoCMY() { + return get_CMYKtoCMY().move_to(*this); + } + + //! Convert pixel values from CMYK to CMY color spaces \newinstance. + CImg get_CMYKtoCMY() const { + if (_spectrum!=4) + throw CImgInstanceException(_cimg_instance + "CMYKtoCMY(): Instance is not a CMYK image.", + cimg_instance); + + CImg res(_width,_height,_depth,3); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2), *ps4 = data(0,0,0,3); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024)) + for (longT N = 0; N& RGBtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoXYZ(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_RGBtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).RGBtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to RGB color spaces. + /** + \param use_D65 Tell to use the D65 illuminant (D50 otherwise). + **/ + CImg& XYZtoRGB(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoRGB(): Instance is not a XYZ image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_XYZtoRGB(const bool use_D65=true) const { + return CImg(*this,false).XYZtoRGB(use_D65); + } + + //! Convert pixel values from XYZ to Lab color spaces. + CImg& XYZtoLab(const bool use_D65=true) { +#define _cimg_Labf(x) (24389*(x)>216?cimg::cbrt(x):(24389*(x)/27 + 16)/116) + + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoLab(): Instance is not a XYZ image.", + cimg_instance); + const CImg white = CImg(1,1,1,3,255).RGBtoXYZ(use_D65); + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128)) + for (longT N = 0; N get_XYZtoLab(const bool use_D65=true) const { + return CImg(*this,false).XYZtoLab(use_D65); + } + + //! Convert pixel values from Lab to XYZ color spaces. + CImg& LabtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "LabtoXYZ(): Instance is not a Lab image.", + cimg_instance); + const CImg white = CImg(1,1,1,3,255).RGBtoXYZ(use_D65); + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128)) + for (longT N = 0; N216?cX*cX*cX:(116*cX - 16)*27/24389), + Y = (Tfloat)(27*L>216?cY*cY*cY:27*L/24389), + Z = (Tfloat)(24389*cZ>216?cZ*cZ*cZ:(116*cZ - 16)*27/24389); + p1[N] = (T)(X*white[0]); + p2[N] = (T)(Y*white[1]); + p3[N] = (T)(Z*white[2]); + } + return *this; + } + + //! Convert pixel values from Lab to XYZ color spaces \newinstance. + CImg get_LabtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).LabtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to xyY color spaces. + CImg& XYZtoxyY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoxyY(): Instance is not a XYZ image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096)) + for (longT N = 0; N0?sum:1; + p1[N] = (T)(X/nsum); + p2[N] = (T)(Y/nsum); + p3[N] = (T)Y; + } + return *this; + } + + //! Convert pixel values from XYZ to xyY color spaces \newinstance. + CImg get_XYZtoxyY() const { + return CImg(*this,false).XYZtoxyY(); + } + + //! Convert pixel values from xyY pixels to XYZ color spaces. + CImg& xyYtoXYZ() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "xyYtoXYZ(): Instance is not a xyY image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096)) + for (longT N = 0; N0?py:1; + p1[N] = (T)(px*Y/ny); + p2[N] = (T)Y; + p3[N] = (T)((1 - px - py)*Y/ny); + } + return *this; + } + + //! Convert pixel values from xyY pixels to XYZ color spaces \newinstance. + CImg get_xyYtoXYZ() const { + return CImg(*this,false).xyYtoXYZ(); + } + + //! Convert pixel values from RGB to Lab color spaces. + CImg& RGBtoLab(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoLab(use_D65); + } + + //! Convert pixel values from RGB to Lab color spaces \newinstance. + CImg get_RGBtoLab(const bool use_D65=true) const { + return CImg(*this,false).RGBtoLab(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces. + CImg& LabtoRGB(const bool use_D65=true) { + return LabtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces \newinstance. + CImg get_LabtoRGB(const bool use_D65=true) const { + return CImg(*this,false).LabtoRGB(use_D65); + } + + //! Convert pixel values from RGB to xyY color spaces. + CImg& RGBtoxyY(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoxyY(); + } + + //! Convert pixel values from RGB to xyY color spaces \newinstance. + CImg get_RGBtoxyY(const bool use_D65=true) const { + return CImg(*this,false).RGBtoxyY(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces. + CImg& xyYtoRGB(const bool use_D65=true) { + return xyYtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces \newinstance. + CImg get_xyYtoRGB(const bool use_D65=true) const { + return CImg(*this,false).xyYtoRGB(use_D65); + } + + //! Convert pixel values from RGB to CMYK color spaces. + CImg& RGBtoCMYK() { + return RGBtoCMY().CMYtoCMYK(); + } + + //! Convert pixel values from RGB to CMYK color spaces \newinstance. + CImg get_RGBtoCMYK() const { + return CImg(*this,false).RGBtoCMYK(); + } + + //! Convert pixel values from CMYK to RGB color spaces. + CImg& CMYKtoRGB() { + return CMYKtoCMY().CMYtoRGB(); + } + + //! Convert pixel values from CMYK to RGB color spaces \newinstance. + CImg get_CMYKtoRGB() const { + return CImg(*this,false).CMYKtoRGB(); + } + + //@} + //------------------------------------------ + // + //! \name Geometric / Spatial Manipulation + //@{ + //------------------------------------------ + + static float _cimg_lanczos(const float x) { + if (x<=-2 || x>=2) return 0; + const float a = (float)cimg::PI*x, b = 0.5f*a; + return (float)(x?std::sin(a)*std::sin(b)/(a*b):1); + } + + //! Resize image to new dimensions. + /** + \param size_x Number of columns (new size along the X-axis). + \param size_y Number of rows (new size along the Y-axis). + \param size_z Number of slices (new size along the Z-axis). + \param size_c Number of vector-channels (new size along the C-axis). + \param interpolation_type Method of interpolation: + - -1 = no interpolation: raw memory resizing. + - 0 = no interpolation: additional space is filled according to \p boundary_conditions. + - 1 = nearest-neighbor interpolation. + - 2 = moving average interpolation. + - 3 = linear interpolation. + - 4 = grid interpolation. + - 5 = cubic interpolation. + - 6 = lanczos interpolation. + \param boundary_conditions Type of boundary conditions used if necessary. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). + **/ + CImg& resize(const int size_x, const int size_y=-100, + const int size_z=-100, const int size_c=-100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + if (!size_x || !size_y || !size_z || !size_c) return assign(); + const unsigned int + _sx = (unsigned int)(size_x<0?-size_x*width()/100:size_x), + _sy = (unsigned int)(size_y<0?-size_y*height()/100:size_y), + _sz = (unsigned int)(size_z<0?-size_z*depth()/100:size_z), + _sc = (unsigned int)(size_c<0?-size_c*spectrum()/100:size_c), + sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1; + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return *this; + if (is_empty()) return assign(sx,sy,sz,sc,(T)0); + if (interpolation_type==-1 && sx*sy*sz*sc==size()) { + _width = sx; _height = sy; _depth = sz; _spectrum = sc; + return *this; + } + return get_resize(sx,sy,sz,sc,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c).move_to(*this); + } + + //! Resize image to new dimensions \newinstance. + CImg get_resize(const int size_x, const int size_y = -100, + const int size_z = -100, const int size_c = -100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + if (centering_x<0 || centering_x>1 || centering_y<0 || centering_y>1 || + centering_z<0 || centering_z>1 || centering_c<0 || centering_c>1) + throw CImgArgumentException(_cimg_instance + "resize(): Specified centering arguments (%g,%g,%g,%g) are outside range [0,1].", + cimg_instance, + centering_x,centering_y,centering_z,centering_c); + + if (!size_x || !size_y || !size_z || !size_c) return CImg(); + const unsigned int + sx = std::max(1U,(unsigned int)(size_x>=0?size_x:-size_x*width()/100)), + sy = std::max(1U,(unsigned int)(size_y>=0?size_y:-size_y*height()/100)), + sz = std::max(1U,(unsigned int)(size_z>=0?size_z:-size_z*depth()/100)), + sc = std::max(1U,(unsigned int)(size_c>=0?size_c:-size_c*spectrum()/100)); + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return +*this; + if (is_empty()) return CImg(sx,sy,sz,sc,(T)0); + CImg res; + switch (interpolation_type) { + + // Raw resizing. + // + case -1 : + std::memcpy(res.assign(sx,sy,sz,sc,(T)0)._data,_data,sizeof(T)*std::min(size(),(ulongT)sx*sy*sz*sc)); + break; + + // No interpolation. + // + case 0 : { + const int + xc = (int)(centering_x*((int)sx - width())), + yc = (int)(centering_y*((int)sy - height())), + zc = (int)(centering_z*((int)sz - depth())), + cc = (int)(centering_c*((int)sc - spectrum())); + + switch (boundary_conditions) { + case 3 : { // Mirror + res.assign(sx,sy,sz,sc); + const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1024*1024)) + cimg_forXYZC(res,x,y,z,c) { + const int + mx = cimg::mod(x - xc,w2), my = cimg::mod(y - yc,h2), + mz = cimg::mod(z - zc,d2), mc = cimg::mod(c - cc,s2); + res(x,y,z,c) = (*this)(mx sprite; + if (xc>0) { // X-backward + res.get_crop(xc,yc,zc,cc,xc,yc + height() - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc - 1; x>=0; --x) res.draw_image(x,yc,zc,cc,sprite); + } + if (xc + width()<(int)sx) { // X-forward + res.get_crop(xc + width() - 1,yc,zc,cc,xc + width() - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc + width(); x<(int)sx; ++x) res.draw_image(x,yc,zc,cc,sprite); + } + if (yc>0) { // Y-backward + res.get_crop(0,yc,zc,cc,sx - 1,yc,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc - 1; y>=0; --y) res.draw_image(0,y,zc,cc,sprite); + } + if (yc + height()<(int)sy) { // Y-forward + res.get_crop(0,yc + height() - 1,zc,cc,sx - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc + height(); y<(int)sy; ++y) res.draw_image(0,y,zc,cc,sprite); + } + if (zc>0) { // Z-backward + res.get_crop(0,0,zc,cc,sx - 1,sy - 1,zc,cc + spectrum() - 1).move_to(sprite); + for (int z = zc - 1; z>=0; --z) res.draw_image(0,0,z,cc,sprite); + } + if (zc + depth()<(int)sz) { // Z-forward + res.get_crop(0,0,zc +depth() - 1,cc,sx - 1,sy - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int z = zc + depth(); z<(int)sz; ++z) res.draw_image(0,0,z,cc,sprite); + } + if (cc>0) { // C-backward + res.get_crop(0,0,0,cc,sx - 1,sy - 1,sz - 1,cc).move_to(sprite); + for (int c = cc - 1; c>=0; --c) res.draw_image(0,0,0,c,sprite); + } + if (cc + spectrum()<(int)sc) { // C-forward + res.get_crop(0,0,0,cc + spectrum() - 1,sx - 1,sy - 1,sz - 1,cc + spectrum() - 1).move_to(sprite); + for (int c = cc + spectrum(); c<(int)sc; ++c) res.draw_image(0,0,0,c,sprite); + } + } break; + default : // Dirichlet + res.assign(sx,sy,sz,sc,(T)0).draw_image(xc,yc,zc,cc,*this); + } + break; + } break; + + // Nearest neighbor interpolation. + // + case 1 : { + res.assign(sx,sy,sz,sc); + CImg off_x(sx), off_y(sy + 1), off_z(sz + 1), off_c(sc + 1); + const ulongT + wh = (ulongT)_width*_height, + whd = (ulongT)_width*_height*_depth, + sxy = (ulongT)sx*sy, + sxyz = (ulongT)sx*sy*sz, + one = (ulongT)1; + if (sx==_width) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + cimg_forX(res,x) { + const ulongT old = curr; + curr = (x + one)*_width/sx; + *(poff_x++) = curr - old; + } + } + if (sy==_height) off_y.fill(_width); + else { + ulongT *poff_y = off_y._data, curr = 0; + cimg_forY(res,y) { + const ulongT old = curr; + curr = (y + one)*_height/sy; + *(poff_y++) = _width*(curr - old); + } + *poff_y = 0; + } + if (sz==_depth) off_z.fill(wh); + else { + ulongT *poff_z = off_z._data, curr = 0; + cimg_forZ(res,z) { + const ulongT old = curr; + curr = (z + one)*_depth/sz; + *(poff_z++) = wh*(curr - old); + } + *poff_z = 0; + } + if (sc==_spectrum) off_c.fill(whd); + else { + ulongT *poff_c = off_c._data, curr = 0; + cimg_forC(res,c) { + const ulongT old = curr; + curr = (c + one)*_spectrum/sc; + *(poff_c++) = whd*(curr - old); + } + *poff_c = 0; + } + + T *ptrd = res._data; + const T* ptrc = _data; + const ulongT *poff_c = off_c._data; + for (unsigned int c = 0; c_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(res); + else { + CImg tmp(sx,_height,_depth,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sx>=256 && _height*_depth*_spectrum>=256)) + cimg_forYZC(tmp,y,z,v) { + for (unsigned int a = _width*sx, b = _width, c = sx, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + tmp(t,y,z,v)+=(Tfloat)(*this)(s,y,z,v)*d; + if (!b) { tmp(t++,y,z,v)/=_width; b = _width; } + if (!c) { ++s; c = sx; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sy!=_height) { + if (sy>_height) get_resize(sx,sy,_depth,_spectrum,1).move_to(res); + else { + CImg tmp(sx,sy,_depth,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sy>=256 && _width*_depth*_spectrum>=256)) + cimg_forXZC(tmp,x,z,v) { + for (unsigned int a = _height*sy, b = _height, c = sy, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,t,z,v)+=(Tfloat)(*this)(x,s,z,v)*d; + else tmp(x,t,z,v)+=(Tfloat)res(x,s,z,v)*d; + if (!b) { tmp(x,t++,z,v)/=_height; b = _height; } + if (!c) { ++s; c = sy; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sz!=_depth) { + if (sz>_depth) get_resize(sx,sy,sz,_spectrum,1).move_to(res); + else { + CImg tmp(sx,sy,sz,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sz>=256 && _width*_height*_spectrum>=256)) + cimg_forXYC(tmp,x,y,v) { + for (unsigned int a = _depth*sz, b = _depth, c = sz, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,y,t,v)+=(Tfloat)(*this)(x,y,s,v)*d; + else tmp(x,y,t,v)+=(Tfloat)res(x,y,s,v)*d; + if (!b) { tmp(x,y,t++,v)/=_depth; b = _depth; } + if (!c) { ++s; c = sz; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sc!=_spectrum) { + if (sc>_spectrum) get_resize(sx,sy,sz,sc,1).move_to(res); + else { + CImg tmp(sx,sy,sz,sc,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sc>=256 && _width*_height*_depth>=256)) + cimg_forXYZ(tmp,x,y,z) { + for (unsigned int a = _spectrum*sc, b = _spectrum, c = sc, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,y,z,t)+=(Tfloat)(*this)(x,y,z,s)*d; + else tmp(x,y,z,t)+=(Tfloat)res(x,y,z,s)*d; + if (!b) { tmp(x,y,z,t++)/=_spectrum; b = _spectrum; } + if (!c) { ++s; c = sc; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + } break; + + // Linear interpolation. + // + case 3 : { + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *ptrs = data(0,y,z,c), *const ptrsmax = ptrs + _width - 1; + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *ptrs = resx.data(x,0,z,c), *const ptrsmax = ptrs + (_height - 1)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *ptrs = resy.data(x,y,0,c), *const ptrsmax = ptrs + (_depth - 1)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *ptrs = resz.data(x,y,z,0), *const ptrsmax = ptrs + (_spectrum - 1)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrs resx, resy, resz, resc; + if (sx!=_width) { + if (sx<_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + resx.assign(sx,_height,_depth,_spectrum,(T)0); + const int dx = (int)(2*sx), dy = 2*width(); + int err = (int)(dy + centering_x*(sx*dy/width() - dy)), xs = 0; + cimg_forX(resx,x) if ((err-=dy)<=0) { + cimg_forYZC(resx,y,z,c) resx(x,y,z,c) = (*this)(xs,y,z,c); + ++xs; + err+=dx; + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (sy<_height) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + resy.assign(sx,sy,_depth,_spectrum,(T)0); + const int dx = (int)(2*sy), dy = 2*height(); + int err = (int)(dy + centering_y*(sy*dy/height() - dy)), ys = 0; + cimg_forY(resy,y) if ((err-=dy)<=0) { + cimg_forXZC(resy,x,z,c) resy(x,y,z,c) = resx(x,ys,z,c); + ++ys; + err+=dx; + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (sz<_depth) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + resz.assign(sx,sy,sz,_spectrum,(T)0); + const int dx = (int)(2*sz), dy = 2*depth(); + int err = (int)(dy + centering_z*(sz*dy/depth() - dy)), zs = 0; + cimg_forZ(resz,z) if ((err-=dy)<=0) { + cimg_forXYC(resz,x,y,c) resz(x,y,z,c) = resy(x,y,zs,c); + ++zs; + err+=dx; + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (sc<_spectrum) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + resc.assign(sx,sy,sz,sc,(T)0); + const int dx = (int)(2*sc), dy = 2*spectrum(); + int err = (int)(dy + centering_c*(sc*dy/spectrum() - dy)), cs = 0; + cimg_forC(resc,c) if ((err-=dy)<=0) { + cimg_forXYZ(resc,x,y,z) resc(x,y,z,c) = resz(x,y,z,cs); + ++cs; + err+=dx; + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Cubic interpolation. + // + case 5 : { + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_width - 2); + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - 1):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + 1):val1, + val3 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sx):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sx):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxy):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxyz):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Lanczos interpolation. + // + case 6 : { + const double vmin = (double)cimg::type::min(), vmax = (double)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + 1, + *const ptrsmax = ptrs0 + (_width - 2); + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - 1):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + 1):val2, + val4 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sx, + *const ptrsmax = ptrs0 + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sx):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sx):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sx):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxy, + *const ptrsmax = ptrs0 + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sxy):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxy):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxyz, + *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sxyz):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxyz):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Unknown interpolation. + // + default : + throw CImgArgumentException(_cimg_instance + "resize(): Invalid specified interpolation %d " + "(should be { -1=raw | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | " + "5=cubic | 6=lanczos }).", + cimg_instance, + interpolation_type); + } + return res; + } + + //! Resize image to dimensions of another image. + /** + \param src Reference image used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + template + CImg& resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of another image \newinstance. + template + CImg get_resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window. + /** + \param disp Reference display window used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + CImg& resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window \newinstance. + CImg get_resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to half-size along XY axes, using an optimized filter. + CImg& resize_halfXY() { + return get_resize_halfXY().move_to(*this); + } + + //! Resize image to half-size along XY axes, using an optimized filter \newinstance. + CImg get_resize_halfXY() const { + if (is_empty()) return *this; + static const Tfloat kernel[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f, + 0.1231940459f, 0.1935127547f, 0.1231940459f, + 0.07842776544f, 0.1231940459f, 0.07842776544f }; + CImg I(9), res(_width/2,_height/2,_depth,_spectrum); + T *ptrd = res._data; + cimg_forZC(*this,z,c) cimg_for3x3(*this,x,y,z,c,I,T) + if (x%2 && y%2) *(ptrd++) = (T) + (I[0]*kernel[0] + I[1]*kernel[1] + I[2]*kernel[2] + + I[3]*kernel[3] + I[4]*kernel[4] + I[5]*kernel[5] + + I[6]*kernel[6] + I[7]*kernel[7] + I[8]*kernel[8]); + return res; + } + + //! Resize image to double-size, using the Scale2X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_doubleXY() { + return get_resize_doubleXY().move_to(*this); + } + + //! Resize image to double-size, using the Scale2X algorithm \newinstance. + CImg get_resize_doubleXY() const { +#define _cimg_gs2x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=(res)._width, ptrd2+=(res)._width) + +#define _cimg_gs2x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs2x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(_width<<1,_height<<1,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width; + _cimg_gs2x_for3x3(*this,x,y,z,c,I,T) { + if (Icp!=Icn && Ipc!=Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = Ipc==Icn?Ipc:Icc; + *(ptrd2++) = Icn==Inc?Inc:Icc; + } else { *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; } + } + } + return res; + } + + //! Resize image to triple-size, using the Scale3X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_tripleXY() { + return get_resize_tripleXY().move_to(*this); + } + + //! Resize image to triple-size, using the Scale3X algorithm \newinstance. + CImg get_resize_tripleXY() const { +#define _cimg_gs3x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=2*(res)._width, ptrd2+=2*(res)._width, ptrd3+=2*(res)._width) + +#define _cimg_gs3x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs3x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(3*_width,3*_height,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width, + *ptrd3 = ptrd2 + res._width; + _cimg_gs3x_for3x3(*this,x,y,z,c,I,T) { + if (Icp != Icn && Ipc != Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = (Ipc==Icp && Icc!=Inp) || (Icp==Inc && Icc!=Ipp)?Icp:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = (Ipc==Icp && Icc!=Ipn) || (Ipc==Icn && Icc!=Ipp)?Ipc:Icc; + *(ptrd2++) = Icc; + *(ptrd2++) = (Icp==Inc && Icc!=Inn) || (Icn==Inc && Icc!=Inp)?Inc:Icc; + *(ptrd3++) = Ipc==Icn?Ipc:Icc; + *(ptrd3++) = (Ipc==Icn && Icc!=Inn) || (Icn==Inc && Icc!=Ipn)?Icn:Icc; + *(ptrd3++) = Icn==Inc?Inc:Icc; + } else { + *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd1++) = Icc; + *(ptrd2++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; + *(ptrd3++) = Icc; *(ptrd3++) = Icc; *(ptrd3++) = Icc; + } + } + } + return res; + } + + //! Mirror image content along specified axis. + /** + \param axis Mirror axis + **/ + CImg& mirror(const char axis) { + if (is_empty()) return *this; + T *pf, *pb, *buf = 0; + switch (cimg::lowercase(axis)) { + case 'x' : { + pf = _data; pb = data(_width - 1); + const unsigned int width2 = _width/2; + for (unsigned int yzv = 0; yzv<_height*_depth*_spectrum; ++yzv) { + for (unsigned int x = 0; x get_mirror(const char axis) const { + return (+*this).mirror(axis); + } + + //! Mirror image content along specified axes. + /** + \param axes Mirror axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& mirror(const char *const axes) { + for (const char *s = axes; *s; ++s) mirror(*s); + return *this; + } + + //! Mirror image content along specified axes \newinstance. + CImg get_mirror(const char *const axes) const { + return (+*this).mirror(axes); + } + + //! Shift image content. + /** + \param delta_x Amount of displacement along the X-axis. + \param delta_y Amount of displacement along the Y-axis. + \param delta_z Amount of displacement along the Z-axis. + \param delta_c Amount of displacement along the C-axis. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const unsigned int boundary_conditions=0) { + if (is_empty()) return *this; + if (boundary_conditions==3) + return get_crop(-delta_x,-delta_y,-delta_z,-delta_c, + width() - delta_x - 1, + height() - delta_y - 1, + depth() - delta_z - 1, + spectrum() - delta_c - 1,3).move_to(*this); + if (delta_x) // Shift along X-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_x,width()), ndelta_x = (ml<=width()/2)?ml:(ml-width()); + if (!ndelta_x) return *this; + CImg buf(cimg::abs(ndelta_x)); + if (ndelta_x>0) cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(0,y,z,c),ndelta_x*sizeof(T)); + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + std::memcpy(data(_width-ndelta_x,y,z,c),buf,ndelta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(_width + ndelta_x,y,z,c),-ndelta_x*sizeof(T)); + std::memmove(data(-ndelta_x,y,z,c),data(0,y,z,c),(_width + ndelta_x)*sizeof(T)); + std::memcpy(data(0,y,z,c),buf,-ndelta_x*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_x<0) { + const int ndelta_x = (-delta_x>=width())?width() - 1:-delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(_width - 1,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width())?width() - 1:delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(ndelta_x,y,z,c),data(0,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(0,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width()) return fill((T)0); + if (delta_x<0) cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(-delta_x,y,z,c),(_width + delta_x)*sizeof(T)); + std::memset(data(_width + delta_x,y,z,c),0,-delta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memmove(data(delta_x,y,z,c),data(0,y,z,c),(_width-delta_x)*sizeof(T)); + std::memset(data(0,y,z,c),0,delta_x*sizeof(T)); + } + } + + if (delta_y) // Shift along Y-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_y,height()), ndelta_y = (ml<=height()/2)?ml:(ml-height()); + if (!ndelta_y) return *this; + CImg buf(width(),cimg::abs(ndelta_y)); + if (ndelta_y>0) cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,0,z,c),_width*ndelta_y*sizeof(T)); + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + std::memcpy(data(0,_height-ndelta_y,z,c),buf,_width*ndelta_y*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,_height + ndelta_y,z,c),-ndelta_y*_width*sizeof(T)); + std::memmove(data(0,-ndelta_y,z,c),data(0,0,z,c),_width*(_height + ndelta_y)*sizeof(T)); + std::memcpy(data(0,0,z,c),buf,-ndelta_y*_width*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_y<0) { + const int ndelta_y = (-delta_y>=height())?height() - 1:-delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,_height-ndelta_y,z,c), *ptrs = data(0,_height - 1,z,c); + for (int l = 0; l=height())?height() - 1:delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,ndelta_y,z,c),data(0,0,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,1,z,c), *ptrs = data(0,0,z,c); + for (int l = 0; l=height()) return fill((T)0); + if (delta_y<0) cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,-delta_y,z,c),_width*(_height + delta_y)*sizeof(T)); + std::memset(data(0,_height + delta_y,z,c),0,-delta_y*_width*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memmove(data(0,delta_y,z,c),data(0,0,z,c),_width*(_height-delta_y)*sizeof(T)); + std::memset(data(0,0,z,c),0,delta_y*_width*sizeof(T)); + } + } + + if (delta_z) // Shift along Z-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_z,depth()), ndelta_z = (ml<=depth()/2)?ml:(ml-depth()); + if (!ndelta_z) return *this; + CImg buf(width(),height(),cimg::abs(ndelta_z)); + if (ndelta_z>0) cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,0,c),_width*_height*ndelta_z*sizeof(T)); + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,_depth-ndelta_z,c),buf,_width*_height*ndelta_z*sizeof(T)); + } else cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,_depth + ndelta_z,c),-ndelta_z*_width*_height*sizeof(T)); + std::memmove(data(0,0,-ndelta_z,c),data(0,0,0,c),_width*_height*(_depth + ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,0,c),buf,-ndelta_z*_width*_height*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_z<0) { + const int ndelta_z = (-delta_z>=depth())?depth() - 1:-delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,_depth-ndelta_z,c), *ptrs = data(0,0,_depth - 1,c); + for (int l = 0; l=depth())?depth() - 1:delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,ndelta_z,c),data(0,0,0,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,1,c), *ptrs = data(0,0,0,c); + for (int l = 0; l=depth()) return fill((T)0); + if (delta_z<0) cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,-delta_z,c),_width*_height*(_depth + delta_z)*sizeof(T)); + std::memset(data(0,0,_depth + delta_z,c),0,_width*_height*(-delta_z)*sizeof(T)); + } else cimg_forC(*this,c) { + std::memmove(data(0,0,delta_z,c),data(0,0,0,c),_width*_height*(_depth-delta_z)*sizeof(T)); + std::memset(data(0,0,0,c),0,delta_z*_width*_height*sizeof(T)); + } + } + + if (delta_c) // Shift along C-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_c,spectrum()), ndelta_c = (ml<=spectrum()/2)?ml:(ml-spectrum()); + if (!ndelta_c) return *this; + CImg buf(width(),height(),depth(),cimg::abs(ndelta_c)); + if (ndelta_c>0) { + std::memcpy(buf,_data,_width*_height*_depth*ndelta_c*sizeof(T)); + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + std::memcpy(data(0,0,0,_spectrum-ndelta_c),buf,_width*_height*_depth*ndelta_c*sizeof(T)); + } else { + std::memcpy(buf,data(0,0,0,_spectrum + ndelta_c),-ndelta_c*_width*_height*_depth*sizeof(T)); + std::memmove(data(0,0,0,-ndelta_c),_data,_width*_height*_depth*(_spectrum + ndelta_c)*sizeof(T)); + std::memcpy(_data,buf,-ndelta_c*_width*_height*_depth*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_c<0) { + const int ndelta_c = (-delta_c>=spectrum())?spectrum() - 1:-delta_c; + if (!ndelta_c) return *this; + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,_spectrum-ndelta_c), *ptrs = data(0,0,0,_spectrum - 1); + for (int l = 0; l=spectrum())?spectrum() - 1:delta_c; + if (!ndelta_c) return *this; + std::memmove(data(0,0,0,ndelta_c),_data,_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,1); + for (int l = 0; l=spectrum()) return fill((T)0); + if (delta_c<0) { + std::memmove(_data,data(0,0,0,-delta_c),_width*_height*_depth*(_spectrum + delta_c)*sizeof(T)); + std::memset(data(0,0,0,_spectrum + delta_c),0,_width*_height*_depth*(-delta_c)*sizeof(T)); + } else { + std::memmove(data(0,0,0,delta_c),_data,_width*_height*_depth*(_spectrum-delta_c)*sizeof(T)); + std::memset(_data,0,delta_c*_width*_height*_depth*sizeof(T)); + } + } + return *this; + } + + //! Shift image content \newinstance. + CImg get_shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const unsigned int boundary_conditions=0) const { + return (+*this).shift(delta_x,delta_y,delta_z,delta_c,boundary_conditions); + } + + //! Permute axes order. + /** + \param axes_order Axes permutations, as a C-string of 4 characters. + This function permutes image content regarding the specified axes permutation. + **/ + CImg& permute_axes(const char *const axes_order) { + return get_permute_axes(axes_order).move_to(*this); + } + + //! Permute axes order \newinstance. + CImg get_permute_axes(const char *const axes_order) const { + const T foo = (T)0; + return _permute_axes(axes_order,foo); + } + + template + CImg _permute_axes(const char *const axes_order, const t&) const { + if (is_empty() || !axes_order) return CImg(*this,false); + CImg res; + const T* ptrs = _data; + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = (unsigned char)c; } + } + if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { + const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + ulongT wh, whd; + switch (code) { + case 0x0123 : // xyzc + return +*this; + case 0x0132 : // xycz + res.assign(_width,_height,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0213 : // xzyc + res.assign(_width,_depth,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x0231 : // xzcy + res.assign(_width,_depth,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x0312 : // xcyz + res.assign(_width,_spectrum,_height,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0321 : // xczy + res.assign(_width,_spectrum,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x1023 : // yxzc + res.assign(_height,_width,_depth,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1032 : // yxcz + res.assign(_height,_width,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1203 : // yzxc + res.assign(_height,_depth,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1230 : // yzcx + res.assign(_height,_depth,_spectrum,_width); + switch (_width) { + case 1 : { + t *ptr_r = res.data(0,0,0,0); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)*(ptrs++); + } + } break; + case 2 : { + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + ptrs+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + ptrs+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA + t + *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), + *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + *(ptr_a++) = (t)ptrs[3]; + ptrs+=4; + } + } break; + default : { + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++); + return res; + } + } + break; + case 0x1302 : // ycxz + res.assign(_height,_spectrum,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1320 : // yczx + res.assign(_height,_spectrum,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2013 : // zxyc + res.assign(_depth,_width,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2031 : // zxcy + res.assign(_depth,_width,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2103 : // zyxc + res.assign(_depth,_height,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2130 : // zycx + res.assign(_depth,_height,_spectrum,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2301 : // zcxy + res.assign(_depth,_spectrum,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2310 : // zcyx + res.assign(_depth,_spectrum,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3012 : // cxyz + res.assign(_spectrum,_width,_height,_depth); + switch (_spectrum) { + case 1 : { + const T *ptr_r = data(0,0,0,0); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++); + } break; + case 2 : { + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd[3] = (t)*(ptr_a++); + ptrd+=4; + } + } break; + default : { + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++); + } + } + break; + case 0x3021 : // cxzy + res.assign(_spectrum,_width,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3102 : // cyxz + res.assign(_spectrum,_height,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x3120 : // cyzx + res.assign(_spectrum,_height,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3201 : // czxy + res.assign(_spectrum,_depth,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3210 : // czyx + res.assign(_spectrum,_depth,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++); + break; + } + } + if (!res) + throw CImgArgumentException(_cimg_instance + "permute_axes(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + return res; + } + + //! Unroll pixel values along specified axis. + /** + \param axis Unroll axis (can be \c 'x', \c 'y', \c 'z' or c 'c'). + **/ + CImg& unroll(const char axis) { + const unsigned int siz = (unsigned int)size(); + if (siz) switch (cimg::lowercase(axis)) { + case 'x' : _width = siz; _height = _depth = _spectrum = 1; break; + case 'y' : _height = siz; _width = _depth = _spectrum = 1; break; + case 'z' : _depth = siz; _width = _height = _spectrum = 1; break; + case 'c' : _spectrum = siz; _width = _height = _depth = 1; break; + } + return *this; + } + + //! Unroll pixel values along specified axis \newinstance. + CImg get_unroll(const char axis) const { + return (+*this).unroll(axis); + } + + //! Rotate image with arbitrary angle. + /** + \param angle Rotation angle, in degrees. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. + Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \note The size of the image is modified. + **/ + CImg& rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle \newinstance. + CImg get_rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res; + const float nangle = cimg::mod(angle,360.f); + if (boundary_conditions!=1 && cimg::mod(nangle,90.f)==0) { // Optimized version for orthogonal angles + const int wm1 = width() - 1, hm1 = height() - 1; + const int iangle = (int)nangle/90; + switch (iangle) { + case 1 : { // 90 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(y,hm1 - x,z,c); + } break; + case 2 : { // 180 deg + res.assign(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - x,hm1 - y,z,c); + } break; + case 3 : { // 270 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - y,x,z,c); + } break; + default : // 0 deg + return *this; + } + } else { // Generic angle + const float + rad = (float)(nangle*cimg::PI/180.), + ca = (float)std::cos(rad), sa = (float)std::sin(rad), + ux = cimg::abs((_width - 1)*ca), uy = cimg::abs((_width - 1)*sa), + vx = cimg::abs((_height - 1)*sa), vy = cimg::abs((_height - 1)*ca), + w2 = 0.5f*(_width - 1), h2 = 0.5f*(_height - 1); + res.assign((int)cimg::round(1 + ux + vx),(int)cimg::round(1 + uy + vy),_depth,_spectrum); + const float rw2 = 0.5f*(res._width - 1), rh2 = 0.5f*(res._height - 1); + _rotate(res,nangle,interpolation,boundary_conditions,w2,h2,rw2,rh2); + } + return res; + } + + //! Rotate image with arbitrary angle, around a center point. + /** + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param interpolation Type of interpolation, { 0=nearest | 1=linear | 2=cubic | 3=mirror }. + \param boundary_conditions Boundary conditions, { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) { + return get_rotate(angle,cx,cy,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle, around a center point \newinstance. + CImg get_rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + _rotate(res,angle,interpolation,boundary_conditions,cx,cy,cx,cy); + return res; + } + + // [internal] Perform 2D rotation with arbitrary angle. + void _rotate(CImg& res, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, + const float rw2, const float rh2) const { + const float + rad = (float)(angle*cimg::PI/180.), + ca = (float)std::cos(rad), sa = (float)std::sin(rad); + + switch (boundary_conditions) { + case 3 : { // Mirror + + switch (interpolation) { + case 2 : { // Cubic interpolation + const float ww = 2.f*width(), hh = 2.f*height(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2, + mx = cimg::mod(w2 + xc*ca + yc*sa,ww), + my = cimg::mod(h2 - xc*sa + yc*ca,hh); + res(x,y,z,c) = _cubic_atXY_c(mx{ 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. + Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(u,v,w,nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) const { + if (is_empty()) return *this; + CImg res; + const float + w1 = _width - 1, h1 = _height - 1, d1 = _depth -1, + w2 = 0.5f*w1, h2 = 0.5f*h1, d2 = 0.5f*d1; + CImg R = CImg::rotation_matrix(u,v,w,angle); + const CImg + X = R*CImg(8,3,1,1, + 0.f,w1,w1,0.f,0.f,w1,w1,0.f, + 0.f,0.f,h1,h1,0.f,0.f,h1,h1, + 0.f,0.f,0.f,0.f,d1,d1,d1,d1); + float + xm, xM = X.get_shared_row(0).max_min(xm), + ym, yM = X.get_shared_row(1).max_min(ym), + zm, zM = X.get_shared_row(2).max_min(zm); + const int + dx = (int)cimg::round(xM - xm), + dy = (int)cimg::round(yM - ym), + dz = (int)cimg::round(zM - zm); + R.transpose(); + res.assign(1 + dx,1 + dy,1 + dz,_spectrum); + const float rw2 = 0.5f*dx, rh2 = 0.5f*dy, rd2 = 0.5f*dz; + _rotate(res,R,interpolation,boundary_conditions,w2,h2,d2,rw2,rh2,rd2); + return res; + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point. + /** + \param u X-coordinate of the 3D rotation axis. + \param v Y-coordinate of the 3D rotation axis. + \param w Z-coordinate of the 3D rotation axis. + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param cz Z-coordinate of the rotation center. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic | 3=mirror }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(u,v,w,nangle,cx,cy,cz,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + CImg R = CImg::rotation_matrix(u,v,w,-angle); + _rotate(res,R,interpolation,boundary_conditions,cx,cy,cz,cx,cy,cz); + return res; + } + + // [internal] Perform 3D rotation with arbitrary axis and angle. + void _rotate(CImg& res, const CImg& R, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, const float d2, + const float rw2, const float rh2, const float rd2) const { + switch (boundary_conditions) { + case 3 : // Mirror + switch (interpolation) { + case 2 : { // Cubic interpolation + const float ww = 2.f*width(), hh = 2.f*height(), dd = 2.f*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(res.size(),2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = cimg::mod((float)(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc),ww), + Y = cimg::mod((float)(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc),hh), + Z = cimg::mod((float)(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc),dd); + cimg_forC(res,c) res(x,y,z,c) = _cubic_atXYZ_c(X{ 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + template + CImg& warp(const CImg& p_warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + return get_warp(p_warp,mode,interpolation,boundary_conditions).move_to(*this); + } + + //! Warp image content by a warping field \newinstance + template + CImg get_warp(const CImg& p_warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty() || !p_warp) return *this; + if (mode && !is_sameXYZ(p_warp)) + throw CImgArgumentException(_cimg_instance + "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) " + "have different XYZ dimensions.", + cimg_instance, + p_warp._width,p_warp._height,p_warp._depth,p_warp._spectrum,p_warp._data); + + CImg res(p_warp._width,p_warp._height,p_warp._depth,_spectrum); + + if (p_warp._spectrum==1) { // 1D warping + if (mode>=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),x + (float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),(float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)), Y = y + (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)), Y = (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++), + z + (float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = x + (int)cimg::round(*(ptrs0++)), + Y = y + (int)cimg::round(*(ptrs1++)), + Z = z + (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = (int)cimg::round(*(ptrs0++)), + Y = (int)cimg::round(*(ptrs1++)), + Z = (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) const { + if (is_empty() || _depth<2) return +*this; + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + const CImg + img_xy = get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1), + img_zy = get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).permute_axes("xzyc"). + resize(_depth,_height,1,-100,-1), + img_xz = get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1); + return CImg(_width + _depth,_height + _depth,1,_spectrum,cimg::min(img_xy.min(),img_zy.min(),img_xz.min())). + draw_image(0,0,img_xy).draw_image(img_xy._width,0,img_zy). + draw_image(0,img_xy._height,img_xz); + } + + //! Construct a 2D representation of a 3D image, with XY,XZ and YZ views \inplace. + CImg& projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) { + if (_depth<2) return *this; + return get_projections2d(x0,y0,z0).move_to(*this); + } + + //! Crop image region. + /** + \param x0 = X-coordinate of the upper-left crop rectangle corner. + \param y0 = Y-coordinate of the upper-left crop rectangle corner. + \param z0 = Z-coordinate of the upper-left crop rectangle corner. + \param c0 = C-coordinate of the upper-left crop rectangle corner. + \param x1 = X-coordinate of the lower-right crop rectangle corner. + \param y1 = Y-coordinate of the lower-right crop rectangle corner. + \param z1 = Z-coordinate of the lower-right crop rectangle corner. + \param c1 = C-coordinate of the lower-right crop rectangle corner. + \param boundary_conditions = Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const unsigned int boundary_conditions=0) { + return get_crop(x0,y0,z0,c0,x1,y1,z1,c1,boundary_conditions).move_to(*this); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "crop(): Empty instance.", + cimg_instance); + const int + nx0 = x0=0 && nx1=0 && ny1=0 && nz1=0 && nc1 res(1U + nx1 - nx0,1U + ny1 - ny0,1U + nz1 - nz0,1U + nc1 - nc0); + if (nx0<0 || nx1>=width() || ny0<0 || ny1>=height() || nz0<0 || nz1>=depth() || nc0<0 || nc1>=spectrum()) + switch (_boundary_conditions) { + case 3 : { // Mirror + const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) { + const int + mx = cimg::mod(nx0 + x,w2), + my = cimg::mod(ny0 + y,h2), + mz = cimg::mod(nz0 + z,d2), + mc = cimg::mod(nc0 + c,s2); + res(x,y,z,c) = (*this)(mx=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) { + res(x,y,z,c) = (*this)(cimg::mod(nx0 + x,width()),cimg::mod(ny0 + y,height()), + cimg::mod(nz0 + z,depth()),cimg::mod(nc0 + c,spectrum())); + } + } break; + case 1 : // Neumann + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) res(x,y,z,c) = _atXYZC(nx0 + x,ny0 + y,nz0 + z,nc0 + c); + break; + default : // Dirichlet + res.fill((T)0).draw_image(-nx0,-ny0,-nz0,-nc0,*this); + } + else res.draw_image(-nx0,-ny0,-nz0,-nc0,*this); + return res; + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const unsigned int boundary_conditions=0) { + return crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const unsigned int boundary_conditions=0) const { + return get_crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, + const int x1, const int y1, + const unsigned int boundary_conditions=0) { + return crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, + const int x1, const int y1, + const unsigned int boundary_conditions=0) const { + return get_crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int x1, const unsigned int boundary_conditions=0) { + return crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int x1, const unsigned int boundary_conditions=0) const { + return get_crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Autocrop image region, regarding the specified background value. + CImg& autocrop(const T& value, const char *const axes="czyx") { + if (is_empty()) return *this; + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + const CImg coords = _autocrop(value,axis); + if (coords[0]==-1 && coords[1]==-1) return assign(); // Image has only 'value' pixels + else switch (axis) { + case 'x' : { + const int x0 = coords[0], x1 = coords[1]; + if (x0>=0 && x1>=0) crop(x0,x1); + } break; + case 'y' : { + const int y0 = coords[0], y1 = coords[1]; + if (y0>=0 && y1>=0) crop(0,y0,_width - 1,y1); + } break; + case 'z' : { + const int z0 = coords[0], z1 = coords[1]; + if (z0>=0 && z1>=0) crop(0,0,z0,_width - 1,_height - 1,z1); + } break; + default : { + const int c0 = coords[0], c1 = coords[1]; + if (c0>=0 && c1>=0) crop(0,0,0,c0,_width - 1,_height - 1,_depth - 1,c1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background value \newinstance. + CImg get_autocrop(const T& value, const char *const axes="czyx") const { + return (+*this).autocrop(value,axes); + } + + //! Autocrop image region, regarding the specified background color. + /** + \param color Color used for the crop. If \c 0, color is guessed. + \param axes Axes used for the crop. + **/ + CImg& autocrop(const T *const color=0, const char *const axes="zyx") { + if (is_empty()) return *this; + if (!color) { // Guess color + const CImg col1 = get_vector_at(0,0,0); + const unsigned int w = _width, h = _height, d = _depth, s = _spectrum; + autocrop(col1,axes); + if (_width==w && _height==h && _depth==d && _spectrum==s) { + const CImg col2 = get_vector_at(w - 1,h - 1,d - 1); + autocrop(col2,axes); + } + return *this; + } + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + switch (axis) { + case 'x' : { + int x0 = width(), x1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'x'); + const int nx0 = coords[0], nx1 = coords[1]; + if (nx0>=0 && nx1>=0) { x0 = std::min(x0,nx0); x1 = std::max(x1,nx1); } + } + if (x0==width() && x1==-1) return assign(); else crop(x0,x1); + } break; + case 'y' : { + int y0 = height(), y1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'y'); + const int ny0 = coords[0], ny1 = coords[1]; + if (ny0>=0 && ny1>=0) { y0 = std::min(y0,ny0); y1 = std::max(y1,ny1); } + } + if (y0==height() && y1==-1) return assign(); else crop(0,y0,_width - 1,y1); + } break; + default : { + int z0 = depth(), z1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'z'); + const int nz0 = coords[0], nz1 = coords[1]; + if (nz0>=0 && nz1>=0) { z0 = std::min(z0,nz0); z1 = std::max(z1,nz1); } + } + if (z0==depth() && z1==-1) return assign(); else crop(0,0,z0,_width - 1,_height - 1,z1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background color \newinstance. + CImg get_autocrop(const T *const color=0, const char *const axes="zyx") const { + return (+*this).autocrop(color,axes); + } + + CImg _autocrop(const T& value, const char axis) const { + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { + int x0 = -1, x1 = -1; + cimg_forX(*this,x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x0 = x; x = width(); y = height(); z = depth(); c = spectrum(); } + if (x0>=0) { + for (int x = width() - 1; x>=0; --x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x1 = x; x = 0; y = height(); z = depth(); c = spectrum(); } + } + res = CImg::vector(x0,x1); + } break; + case 'y' : { + int y0 = -1, y1 = -1; + cimg_forY(*this,y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y0 = y; x = width(); y = height(); z = depth(); c = spectrum(); } + if (y0>=0) { + for (int y = height() - 1; y>=0; --y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y1 = y; x = width(); y = 0; z = depth(); c = spectrum(); } + } + res = CImg::vector(y0,y1); + } break; + case 'z' : { + int z0 = -1, z1 = -1; + cimg_forZ(*this,z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z0 = z; x = width(); y = height(); z = depth(); c = spectrum(); } + if (z0>=0) { + for (int z = depth() - 1; z>=0; --z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z1 = z; x = width(); y = height(); z = 0; c = spectrum(); } + } + res = CImg::vector(z0,z1); + } break; + default : { + int c0 = -1, c1 = -1; + cimg_forC(*this,c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c0 = c; x = width(); y = height(); z = depth(); c = spectrum(); } + if (c0>=0) { + for (int c = spectrum() - 1; c>=0; --c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c1 = c; x = width(); y = height(); z = depth(); c = 0; } + } + res = CImg::vector(c0,c1); + } + } + return res; + } + + //! Return specified image column. + /** + \param x0 Image column. + **/ + CImg get_column(const int x0) const { + return get_columns(x0,x0); + } + + //! Return specified image column \inplace. + CImg& column(const int x0) { + return columns(x0,x0); + } + + //! Return specified range of image columns. + /** + \param x0 Starting image column. + \param x1 Ending image column. + **/ + CImg& columns(const int x0, const int x1) { + return get_columns(x0,x1).move_to(*this); + } + + //! Return specified range of image columns \inplace. + CImg get_columns(const int x0, const int x1) const { + return get_crop(x0,0,0,0,x1,height() - 1,depth() - 1,spectrum() - 1); + } + + //! Return specified image row. + CImg get_row(const int y0) const { + return get_rows(y0,y0); + } + + //! Return specified image row \inplace. + /** + \param y0 Image row. + **/ + CImg& row(const int y0) { + return rows(y0,y0); + } + + //! Return specified range of image rows. + /** + \param y0 Starting image row. + \param y1 Ending image row. + **/ + CImg get_rows(const int y0, const int y1) const { + return get_crop(0,y0,0,0,width() - 1,y1,depth() - 1,spectrum() - 1); + } + + //! Return specified range of image rows \inplace. + CImg& rows(const int y0, const int y1) { + return get_rows(y0,y1).move_to(*this); + } + + //! Return specified image slice. + /** + \param z0 Image slice. + **/ + CImg get_slice(const int z0) const { + return get_slices(z0,z0); + } + + //! Return specified image slice \inplace. + CImg& slice(const int z0) { + return slices(z0,z0); + } + + //! Return specified range of image slices. + /** + \param z0 Starting image slice. + \param z1 Ending image slice. + **/ + CImg get_slices(const int z0, const int z1) const { + return get_crop(0,0,z0,0,width() - 1,height() - 1,z1,spectrum() - 1); + } + + //! Return specified range of image slices \inplace. + CImg& slices(const int z0, const int z1) { + return get_slices(z0,z1).move_to(*this); + } + + //! Return specified image channel. + /** + \param c0 Image channel. + **/ + CImg get_channel(const int c0) const { + return get_channels(c0,c0); + } + + //! Return specified image channel \inplace. + CImg& channel(const int c0) { + return channels(c0,c0); + } + + //! Return specified range of image channels. + /** + \param c0 Starting image channel. + \param c1 Ending image channel. + **/ + CImg get_channels(const int c0, const int c1) const { + return get_crop(0,0,0,c0,width() - 1,height() - 1,depth() - 1,c1); + } + + //! Return specified range of image channels \inplace. + CImg& channels(const int c0, const int c1) { + return get_channels(c0,c1).move_to(*this); + } + + //! Return stream line of a 2D or 3D vector field. + CImg get_streamline(const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false) const { + if (_spectrum!=2 && _spectrum!=3) + throw CImgInstanceException(_cimg_instance + "streamline(): Instance is not a 2D or 3D vector field.", + cimg_instance); + if (_spectrum==2) { + if (is_oriented_only) { + typename CImg::_functor4d_streamline2d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.f,_height - 1.f,0.f); + } else { + typename CImg::_functor4d_streamline2d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.f,_height - 1.f,0.f); + } + } + if (is_oriented_only) { + typename CImg::_functor4d_streamline3d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.f,_height - 1.f,_depth - 1.f); + } + typename CImg::_functor4d_streamline3d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.f,_height - 1.f,_depth - 1.f); + } + + //! Return stream line of a 3D vector field. + /** + \param func Vector field function. + \param x X-coordinate of the starting point of the streamline. + \param y Y-coordinate of the starting point of the streamline. + \param z Z-coordinate of the starting point of the streamline. + \param L Streamline length. + \param dl Streamline length increment. + \param interpolation_type Type of interpolation. + Can be { 0=nearest int | 1=linear | 2=2nd-order RK | 3=4th-order RK. }. + \param is_backward_tracking Tells if the streamline is estimated forward or backward. + \param is_oriented_only Tells if the direction of the vectors must be ignored. + \param x0 X-coordinate of the first bounding-box vertex. + \param y0 Y-coordinate of the first bounding-box vertex. + \param z0 Z-coordinate of the first bounding-box vertex. + \param x1 X-coordinate of the second bounding-box vertex. + \param y1 Y-coordinate of the second bounding-box vertex. + \param z1 Z-coordinate of the second bounding-box vertex. + **/ + template + static CImg streamline(const tfunc& func, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + if (dl<=0) + throw CImgArgumentException("CImg<%s>::streamline(): Invalid specified integration length %g " + "(should be >0).", + pixel_type(), + dl); + + const bool is_bounded = (x0!=x1 || y0!=y1 || z0!=z1); + if (L<=0 || (is_bounded && (xx1 || yy1 || zz1))) return CImg(); + const unsigned int size_L = (unsigned int)cimg::round(L/dl + 1); + CImg coordinates(size_L,3); + const float dl2 = dl/2; + float + *ptr_x = coordinates.data(0,0), + *ptr_y = coordinates.data(0,1), + *ptr_z = coordinates.data(0,2), + pu = (float)(dl*func(x,y,z,0)), + pv = (float)(dl*func(x,y,z,1)), + pw = (float)(dl*func(x,y,z,2)), + X = x, Y = y, Z = z; + + switch (interpolation_type) { + case 0 : { // Nearest integer interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + const int + xi = (int)(X>0?X + 0.5f:X - 0.5f), + yi = (int)(Y>0?Y + 0.5f:Y - 0.5f), + zi = (int)(Z>0?Z + 0.5f:Z - 0.5f); + float + u = (float)(dl*func((float)xi,(float)yi,(float)zi,0)), + v = (float)(dl*func((float)xi,(float)yi,(float)zi,1)), + w = (float)(dl*func((float)xi,(float)yi,(float)zi,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 1 : { // First-order interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u = (float)(dl*func(X,Y,Z,0)), + v = (float)(dl*func(X,Y,Z,1)), + w = (float)(dl*func(X,Y,Z,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 2 : { // Second order interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u = (float)(dl*func(X + u0,Y + v0,Z + w0,0)), + v = (float)(dl*func(X + u0,Y + v0,Z + w0,1)), + w = (float)(dl*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + default : { // Fourth order interpolation + cimg_forX(coordinates,k) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,0)), + v1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,1)), + w1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u1*pu + v1*pv + w1*pw<0) { u1 = -u1; v1 = -v1; w1 = -w1; } + float + u2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,0)), + v2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,1)), + w2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u2 = -u2; v2 = -v2; w2 = -w2; } + float + u3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,0)), + v3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,1)), + w3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u3 = -u3; v3 = -v3; w3 = -w3; } + const float + u = (u0 + u3)/3 + (u1 + u2)/1.5f, + v = (v0 + v3)/3 + (v1 + v2)/1.5f, + w = (w0 + w3)/3 + (w1 + w2)/1.5f; + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } + } + if (ptr_x!=coordinates.data(0,1)) coordinates.resize((int)(ptr_x-coordinates.data()),3,1,1,0); + return coordinates; + } + + //! Return stream line of a 3D vector field \overloading. + static CImg streamline(const char *const expression, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=true, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + _functor4d_streamline_expr func(expression); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,is_oriented_only,x0,y0,z0,x1,y1,z1); + } + + struct _functor4d_streamline2d_directed { + const CImg& ref; + _functor4d_streamline2d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return c<2?(float)ref._linear_atXY(x,y,(int)z,c):0; + } + }; + + struct _functor4d_streamline3d_directed { + const CImg& ref; + _functor4d_streamline3d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref._linear_atXYZ(x,y,z,c); + } + }; + + struct _functor4d_streamline2d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline2d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,1,2); } + ~_functor4d_streamline2d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign2d(i,j) \ + if (I(i,j,0)*I(0,0,0) + I(i,j,1)*I(0,0,1)<0) { I(i,j,0) = -I(i,j,0); I(i,j,1) = -I(i,j,1); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z; + const float + dx = x - xi, + dy = y - yi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + I(0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,1) = (float)ref(xi,yi,zi,1); + I(1,0,0) = (float)ref(nxi,yi,zi,0); I(1,0,1) = (float)ref(nxi,yi,zi,1); + I(1,1,0) = (float)ref(nxi,nyi,zi,0); I(1,1,1) = (float)ref(nxi,nyi,zi,1); + I(0,1,0) = (float)ref(xi,nyi,zi,0); I(0,1,1) = (float)ref(xi,nyi,zi,1); + _cimg_vecalign2d(1,0); _cimg_vecalign2d(1,1); _cimg_vecalign2d(0,1); + } + return c<2?(float)pI->_linear_atXY(dx,dy,0,c):0; + } + }; + + struct _functor4d_streamline3d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline3d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,2,3); } + ~_functor4d_streamline3d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign3d(i,j,k) if (I(i,j,k,0)*I(0,0,0,0) + I(i,j,k,1)*I(0,0,0,1) + I(i,j,k,2)*I(0,0,0,2)<0) { \ + I(i,j,k,0) = -I(i,j,k,0); I(i,j,k,1) = -I(i,j,k,1); I(i,j,k,2) = -I(i,j,k,2); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z - (z>=0?0:1), nzi = zi + 1; + const float + dx = x - xi, + dy = y - yi, + dz = z - zi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + if (zi<0) zi = 0; + if (nzi<0) nzi = 0; + if (zi>=ref.depth()) zi = ref.depth() - 1; + if (nzi>=ref.depth()) nzi = ref.depth() - 1; + I(0,0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,0,1) = (float)ref(xi,yi,zi,1); + I(0,0,0,2) = (float)ref(xi,yi,zi,2); I(1,0,0,0) = (float)ref(nxi,yi,zi,0); + I(1,0,0,1) = (float)ref(nxi,yi,zi,1); I(1,0,0,2) = (float)ref(nxi,yi,zi,2); + I(1,1,0,0) = (float)ref(nxi,nyi,zi,0); I(1,1,0,1) = (float)ref(nxi,nyi,zi,1); + I(1,1,0,2) = (float)ref(nxi,nyi,zi,2); I(0,1,0,0) = (float)ref(xi,nyi,zi,0); + I(0,1,0,1) = (float)ref(xi,nyi,zi,1); I(0,1,0,2) = (float)ref(xi,nyi,zi,2); + I(0,0,1,0) = (float)ref(xi,yi,nzi,0); I(0,0,1,1) = (float)ref(xi,yi,nzi,1); + I(0,0,1,2) = (float)ref(xi,yi,nzi,2); I(1,0,1,0) = (float)ref(nxi,yi,nzi,0); + I(1,0,1,1) = (float)ref(nxi,yi,nzi,1); I(1,0,1,2) = (float)ref(nxi,yi,nzi,2); + I(1,1,1,0) = (float)ref(nxi,nyi,nzi,0); I(1,1,1,1) = (float)ref(nxi,nyi,nzi,1); + I(1,1,1,2) = (float)ref(nxi,nyi,nzi,2); I(0,1,1,0) = (float)ref(xi,nyi,nzi,0); + I(0,1,1,1) = (float)ref(xi,nyi,nzi,1); I(0,1,1,2) = (float)ref(xi,nyi,nzi,2); + _cimg_vecalign3d(1,0,0); _cimg_vecalign3d(1,1,0); _cimg_vecalign3d(0,1,0); + _cimg_vecalign3d(0,0,1); _cimg_vecalign3d(1,0,1); _cimg_vecalign3d(1,1,1); _cimg_vecalign3d(0,1,1); + } + return (float)pI->_linear_atXYZ(dx,dy,dz,c); + } + }; + + struct _functor4d_streamline_expr { + _cimg_math_parser *mp; + ~_functor4d_streamline_expr() { mp->end(); delete mp; } + _functor4d_streamline_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,"streamline",CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)(*mp)(x,y,z,c); + } + }; + + //! Return a shared-memory image referencing a range of pixels of the image instance. + /** + \param x0 X-coordinate of the starting pixel. + \param x1 X-coordinate of the ending pixel. + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(x0,y0,z0,c0), + end = (ulongT)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of pixels of the image instance \const. + const CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(x0,y0,z0,c0), + end = (ulongT)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance. + /** + \param y0 Y-coordinate of the starting row. + \param y1 Y-coordinate of the ending row. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(0,y0,z0,c0), + end = (ulongT)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance \const. + const CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(0,y0,z0,c0), + end = (ulongT)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing one row of the image instance. + /** + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared-memory image referencing one row of the image instance \const. + const CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) const { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared memory image referencing a range of slices of the image instance. + /** + \param z0 Z-coordinate of the starting slice. + \param z1 Z-coordinate of the ending slice. + \param c0 C-coordinate. + **/ + CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(0,0,z0,c0), + end = (ulongT)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared memory image referencing a range of slices of the image instance \const. + const CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(0,0,z0,c0), + end = (ulongT)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared-memory image referencing one slice of the image instance. + /** + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing one slice of the image instance \const. + const CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) const { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing a range of channels of the image instance. + /** + \param c0 C-coordinate of the starting channel. + \param c1 C-coordinate of the ending channel. + **/ + CImg get_shared_channels(const unsigned int c0, const unsigned int c1) { + const ulongT + beg = (ulongT)offset(0,0,0,c0), + end = (ulongT)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing a range of channels of the image instance \const. + const CImg get_shared_channels(const unsigned int c0, const unsigned int c1) const { + const ulongT + beg = (ulongT)offset(0,0,0,c0), + end = (ulongT)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing one channel of the image instance. + /** + \param c0 C-coordinate. + **/ + CImg get_shared_channel(const unsigned int c0) { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory image referencing one channel of the image instance \const. + const CImg get_shared_channel(const unsigned int c0) const { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory version of the image instance. + CImg get_shared() { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Return a shared-memory version of the image instance \const. + const CImg get_shared() const { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Split image into a list along specified axis. + /** + \param axis Splitting axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param nb Number of split parts. + \note + - If \c nb==0, instance image is split into blocs of egal values along the specified axis. + - If \c nb<=0, instance image is split into blocs of -\c nb pixel wide. + - If \c nb>0, instance image is split into \c nb blocs. + **/ + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + + if (nb<0) { // Split by bloc size + const unsigned int dp = (unsigned int)(nb?-nb:1); + switch (_axis) { + case 'x': { + if (_width>dp) { + res.assign(_width/dp + (_width%dp?1:0),1,1); + const unsigned int pe = _width - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _height*_depth*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(p,0,0,0,p + dp - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop((res._width - 1)*dp,0,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'y': { + if (_height>dp) { + res.assign(_height/dp + (_height%dp?1:0),1,1); + const unsigned int pe = _height - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_depth*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,p,0,0,_width - 1,p + dp - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop(0,(res._width - 1)*dp,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'z': { + if (_depth>dp) { + res.assign(_depth/dp + (_depth%dp?1:0),1,1); + const unsigned int pe = _depth - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_height*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,0,p,0,_width - 1,_height - 1,p + dp - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop(0,0,(res._width - 1)*dp,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'c' : { + if (_spectrum>dp) { + res.assign(_spectrum/dp + (_spectrum%dp?1:0),1,1); + const unsigned int pe = _spectrum - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_height*_depth>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,0,0,p,_width - 1,_height - 1,_depth - 1,p + dp - 1).move_to(res[p/dp]); + get_crop(0,0,0,(res._width - 1)*dp,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } + } + } else if (nb>0) { // Split by number of (non-homogeneous) blocs + const unsigned int siz = _axis=='x'?_width:_axis=='y'?_height:_axis=='z'?_depth:_axis=='c'?_spectrum:0; + if ((unsigned int)nb>siz) + throw CImgArgumentException(_cimg_instance + "get_split(): Instance cannot be split along %c-axis into %u blocs.", + cimg_instance, + axis,nb); + if (nb==1) res.assign(*this); + else { + int err = (int)siz; + unsigned int _p = 0; + switch (_axis) { + case 'x' : { + cimg_forX(*this,p) if ((err-=nb)<=0) { + get_crop(_p,0,0,0,p,_height - 1,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'y' : { + cimg_forY(*this,p) if ((err-=nb)<=0) { + get_crop(0,_p,0,0,_width - 1,p,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'z' : { + cimg_forZ(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,_p,0,_width - 1,_height - 1,p,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'c' : { + cimg_forC(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,0,_p,_width - 1,_height - 1,_depth - 1,p).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } + } + } + } else { // Split by egal values according to specified axis + T current = *_data; + switch (_axis) { + case 'x' : { + int i0 = 0; + cimg_forX(*this,i) + if ((*this)(i)!=current) { get_columns(i0,i - 1).move_to(res); i0 = i; current = (*this)(i); } + get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + int i0 = 0; + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { get_rows(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,i); } + get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + int i0 = 0; + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { get_slices(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,i); } + get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + int i0 = 0; + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { get_channels(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,0,i); } + get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + longT i0 = 0; + cimg_foroff(*this,i) + if ((*this)[i]!=current) { + CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = (longT)i; current = (*this)[i]; + } + CImg(_data + i0,1,(unsigned int)(size() - i0)).move_to(res); + } + } + } + return res; + } + + //! Split image into a list of sub-images, according to a specified splitting value sequence and optionally axis. + /** + \param values Splitting value sequence. + \param axis Axis along which the splitting is performed. Can be '0' to ignore axis. + \param keep_values Tells if the splitting sequence must be kept in the split blocs. + **/ + template + CImgList get_split(const CImg& values, const char axis=0, const bool keep_values=true) const { + typedef _cimg_Tt Tt; + + CImgList res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + if (!vsiz) return CImgList(*this); + if (vsiz==1) { // Split according to a single value + const T value = (T)*values; + switch (_axis) { + case 'x' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_width && (*this)(i)==value) ++i; + if (i>i0) { if (keep_values) get_columns(i0,i - 1).move_to(res); i0 = i; } + while (i<_width && (*this)(i)!=value) ++i; + if (i>i0) { get_columns(i0,i - 1).move_to(res); i0 = i; } + } while (i<_width); + } break; + case 'y' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_height && (*this)(0,i)==value) ++i; + if (i>i0) { if (keep_values) get_rows(i0,i - 1).move_to(res); i0 = i; } + while (i<_height && (*this)(0,i)!=value) ++i; + if (i>i0) { get_rows(i0,i - 1).move_to(res); i0 = i; } + } while (i<_height); + } break; + case 'z' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_depth && (*this)(0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_slices(i0,i - 1).move_to(res); i0 = i; } + while (i<_depth && (*this)(0,0,i)!=value) ++i; + if (i>i0) { get_slices(i0,i - 1).move_to(res); i0 = i; } + } while (i<_depth); + } break; + case 'c' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_spectrum && (*this)(0,0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_channels(i0,i - 1).move_to(res); i0 = i; } + while (i<_spectrum && (*this)(0,0,0,i)!=value) ++i; + if (i>i0) { get_channels(i0,i - 1).move_to(res); i0 = i; } + } while (i<_spectrum); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i = 0; + do { + while (ii0) { + if (keep_values) CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = i; + } + while (ii0) { CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; } + } while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_columns(i0,i1 - 1).move_to(res); + if (keep_values) get_columns(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_width); + if (i0<_width) get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_height && (Tt)(*this)(0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_rows(i0,i1 - 1).move_to(res); + if (keep_values) get_rows(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_height); + if (i0<_height) get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_depth && (Tt)(*this)(0,0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_slices(i0,i1 - 1).move_to(res); + if (keep_values) get_slices(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_depth); + if (i0<_depth) get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,0,0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_spectrum && (Tt)(*this)(0,0,0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_channels(i0,i1 - 1).move_to(res); + if (keep_values) get_channels(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_spectrum); + if (i0<_spectrum) get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)[i]==(Tt)*values) { + i1 = i; j = 0; + while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) CImg(_data + i0,1,(unsigned int)(i1 - i0)).move_to(res); + if (keep_values) CImg(_data + i1,1,(unsigned int)(i - i1)).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i(_data + i0,1,(unsigned int)(siz - i0)).move_to(res); + } break; + } + } + return res; + } + + //! Append two images along specified axis. + /** + \param img Image to append with instance image. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Append alignment in \c [0,1]. + **/ + template + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,true).insert(img).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \specialization. + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,img,true).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \const. + template + CImg<_cimg_Tt> get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList<_cimg_Tt>(*this,true).insert(img).get_append(axis,align); + } + + //! Append two images along specified axis \specialization. + CImg get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList(*this,img,true).get_append(axis,align); + } + + //@} + //--------------------------------------- + // + //! \name Filtering / Transforms + //@{ + //--------------------------------------- + + //! Correlate image by a kernel. + /** + \param kernel = the correlation kernel. + \param boundary_conditions Boundary condition. Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \param is_normalized = enable local normalization. + \param channel mode Channel processing mode. Can be { 0=sum inputs | 1=one-for-one | 2=expand } + \param xcenter X-coordinate of the kernel center (~0U means 'centered'). + \param xstart Starting X-coordinate of the instance image. + \param xend Ending X-coordinate of the instance image. + \param xstride Stride along the X-axis. + \param xdilation Dilation along the X-axis. + \param ycenter Y-coordinate of the kernel center (~0U means 'centered'). + \param ystart Starting Y-coordinate of the instance image. + \param yend Ending Y-coordinate of the instance image. + \param ystride Stride along the Y-axis. + \param ydilation Dilation along the Y-axis. + \param zcenter Z-coordinate of the kernel center (~0U means 'centered'). + \param zstart Starting Z-coordinate of the instance image. + \param zend Ending Z-coordinate of the instance image. + \param zstride Stride along the Z-axis. + \param zdilation Dilation along the Z-axis. + \note + - The correlation of the image instance \p *this by the kernel \p kernel is defined to be: + res(x,y,z) = sum_{i,j,k} (*this)(\alpha_x\;x + \beta_x\;(i - c_x),\alpha_y\;y + \beta_y\;(j - + c_y),\alpha_z\;z + \beta_z\;(k - c_z))*kernel(i,j,k). + **/ + template + CImg& correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) { + if (is_empty() || !kernel) return *this; + return get_correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation).move_to(*this); + } + + template + CImg<_cimg_Ttfloat> get_correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, + const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, + const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) const { + return _correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation,false); + } + + //! Correlate image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> _correlate(const CImg& kernel, const unsigned int boundary_conditions, + const bool is_normalized, const unsigned int channel_mode, + const unsigned int xcenter, const unsigned int ycenter, const unsigned int zcenter, + const unsigned int xstart, const unsigned int ystart, const unsigned zstart, + const unsigned int xend, const unsigned int yend, const unsigned int zend, + const float xstride, const float ystride, const float zstride, + const float xdilation, const float ydilation, const float zdilation, + const bool is_convolve) const { + if (is_empty() || !kernel) return *this; + typedef _cimg_Ttfloat Ttfloat; + CImg res; + _cimg_abort_init_openmp; + cimg_abort_init; + + if (xstart>xend || ystart>yend || zstart>zend) + throw CImgArgumentException(_cimg_instance + "%s(): Invalid xyz-start/end arguments (start = (%u,%u,%u), end = (%u,%u,%u)).", + cimg_instance, + is_convolve?"convolve":"correlate", + xstart,ystart,zstart,xend,yend,zend); + if (xstride<=0 || ystride<=0 || zstride<=0) + throw CImgArgumentException(_cimg_instance + "%s(): Invalid stride arguments (%g,%g,%g).", + cimg_instance, + is_convolve?"convolve":"correlate", + xstride,ystride,zstride); + const int + _xstart = (int)std::min(xstart,_width - 1), + _ystart = (int)std::min(ystart,_height - 1), + _zstart = (int)std::min(zstart,_depth - 1), + _xend = (int)std::min(xend,_width - 1), + _yend = (int)std::min(yend,_height - 1), + _zend = (int)std::min(zend,_depth - 1), + nwidth = 1 + (int)std::floor((_xend - _xstart)/xstride), + nheight = 1 + (int)std::floor((_yend - _ystart)/ystride), + ndepth = 1 + (int)std::floor((_zend + _zstart)/zstride), + _xstride = (int)cimg::round(xstride), + _ystride = (int)cimg::round(ystride), + _zstride = (int)cimg::round(zstride); + + const ulongT + res_whd = (ulongT)nwidth*nheight*ndepth, + res_size = res_whd*res._spectrum; + const bool + is_inner_parallel = res_whd>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res_size>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + + int + _xcenter = xcenter==~0U?kernel.width()/2 - 1 + (kernel.width()%2):(int)std::min(xcenter,kernel._width - 1), + _ycenter = ycenter==~0U?kernel.height()/2 - 1 + (kernel.height()%2):(int)std::min(ycenter,kernel._height - 1), + _zcenter = zcenter==~0U?kernel.depth()/2 - 1 + (kernel.depth()%2):(int)std::min(zcenter,kernel._depth - 1), + _xdilation = (int)cimg::round(xdilation), + _ydilation = (int)cimg::round(ydilation), + _zdilation = (int)cimg::round(zdilation); + + const bool is_int_stride_dilation = + xstride==_xstride && ystride==_ystride && zstride==_zstride && + xdilation==_xdilation && ydilation==_ydilation && zdilation==_zdilation; + + CImg _kernel; + if (is_convolve) { // If convolution, go back to correlation + _kernel = CImg(kernel._data,kernel.size()/kernel._spectrum,1,1,kernel._spectrum,true). + get_mirror('x').resize(kernel,-1); + _xcenter = kernel.width() - 1 - _xcenter; + _ycenter = kernel.height() - 1 - _ycenter; + _zcenter = kernel.depth() - 1 - _zcenter; + } else _kernel = kernel.get_shared(); + + if (_kernel._width==_kernel._height && _kernel._width>1 && _kernel._height>1 && + ((_kernel._depth==1 && _kernel._width<=5) || (_kernel._depth==_kernel._width && _kernel._width<=3)) && + boundary_conditions<=1 && channel_mode && + _xcenter==_kernel.width()/2 - 1 + (_kernel.width()%2) && + _ycenter==_kernel.height()/2 - 1 + (_kernel.height()%2) && + _zcenter==_kernel.depth()/2 - 1 + (_kernel.depth()%2) && + is_int_stride_dilation && _xdilation>=0 && _ydilation>=0 && _zdilation>=0) { + + // Optimized versions for centered 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 kernels. + const int dw = 1 - (_kernel.width()%2), dh = 1 - (_kernel.height()%2), dd = 1 - (_kernel.depth()%2); + if (dw || dh || dd) // Force kernel size to be odd + _kernel.get_resize(_kernel.width() + dw,_kernel.height() + dh,_kernel.depth() + dd,_kernel.spectrum(), + 0,0,1,1,1).move_to(_kernel.assign()); + + if (!boundary_conditions) { // Dirichlet -> Add a 1px zero border, then use _correlate() with Neumann + const int + dx = _kernel._width==1?0:1, + dy = _kernel._height==1?0:1, + dz = _kernel._depth==1?0:1; + return get_crop(-dx,-dy,-dz,width() - 1 + dx,height() - 1 + dy,depth() - 1 + dz). + _correlate(_kernel,true,is_normalized,channel_mode,_xcenter,_ycenter,_zcenter, + _xstart + dx,_ystart + dy,_zstart + dz,_xend + dx,_yend + dy,_zend + dz, + xstride,ystride,zstride,xdilation,ydilation,zdilation,false); + + } else { // Neumann boundaries + res.assign(nwidth,nheight,ndepth,std::max(_spectrum,_kernel._spectrum)); + + switch (_kernel._depth) { + case 3 : { // 3x3x3 centered kernel + cimg_forC(res,c) { + cimg_abort_test; + const CImg I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + const int w1 = I.width() - 1, h1 = I.height() - 1, d1 = I.depth() - 1; + CImg _res = res.get_shared_channel(c); + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,Z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, z = _zstart + _zstride*Z, + px = x - _xdilation>0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?z - _zdilation:0, nz = z + _zdilation0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?z - _zdilation:0, nz = z + _zdilation I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + const int w1 = I.width() - 1, h1 = I.height() - 1; + CImg _res = res.get_shared_channel(c); + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, + px = x - _xdilation>0?x - _xdilation:0, bx = px - _xdilation>0?px - _xdilation:0, + nx = x + _xdilation0?y - _ydilation:0, by = py - _ydilation>0?py - _ydilation:0, + ny = y + _ydilation0?x - _xdilation:0, bx = px - _xdilation>0?px - _xdilation:0, + nx = x + _xdilation0?y - _ydilation:0, by = py - _ydilation>0?py - _ydilation:0, + ny = y + _ydilation I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + CImg _res = res.get_shared_channel(c); + const int w1 = I.width() - 1, h1 = I.height() - 1; + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, + px = x - _xdilation>0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation res0 = res.get_shared_channel(0); + for (int c = 1; c K = _kernel.get_shared_channel(kc%_kernel._spectrum); + int w2 = 0, h2 = 0, d2 = 0; + Ttfloat M = 0, M2 = 0; + if (is_normalized) { M = (Ttfloat)K.magnitude(2); M2 = M*M; } + if (boundary_conditions>=3) { w2 = 2*width(); h2 = 2*height(); d2 = 2*depth(); } + res.fill(0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + cimg_forXYZC(res,x,y,z,c) { + Ttfloat _val, val = 0, N = 0; + + if (is_int_stride_dilation) + cimg_forXYZ(_kernel,p,q,r) { + const int + ix = (int)xstart + _xstride*x + _xdilation*(p - _xcenter), + iy = (int)ystart + _ystride*y + _ydilation*(q - _ycenter), + iz = (int)zstart + _zstride*z + _zdilation*(r - _zcenter); + switch (boundary_conditions) { + case 0 : _val = atXYZ(ix,iy,iz,c,0); break; // Dirichlet + case 1 : _val = _atXYZ(ix,iy,iz,c); break; // Neumann + case 2 : _val = (*this)(cimg::mod(ix,width()),cimg::mod(iy,height()), // Periodic + cimg::mod(iz,depth()),c); break; + default : { // Mirror + const int mx = cimg::mod(ix,w2), my = cimg::mod(iy,h2), mz = cimg::mod(iz,d2); + _val = (*this)(mx I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(channel_mode==1?c%_kernel._spectrum:c/_spectrum); + int w2 = 0, h2 = 0, d2 = 0; + Ttfloat M = 0, M2 = 0; + if (is_normalized) { M = (Ttfloat)K.magnitude(2); M2 = M*M; } + if (boundary_conditions>=3) { w2 = 2*I.width(); h2 = 2*I.height(); d2 = 2*I.depth(); } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + cimg_forXYZ(res,x,y,z) { + Ttfloat _val, val = 0, N = 0; + + if (is_int_stride_dilation) + cimg_forXYZ(_kernel,p,q,r) { + const int + ix = (int)xstart + _xstride*x + _xdilation*(p - _xcenter), + iy = (int)ystart + _ystride*y + _ydilation*(q - _ycenter), + iz = (int)zstart + _zstride*z + _zdilation*(r - _zcenter); + switch (boundary_conditions) { + case 0 : _val = I.atXYZ(ix,iy,iz,0,0); break; // Dirichlet + case 1 : _val = I._atXYZ(ix,iy,iz); break; // Neumann + case 2 : _val = I(cimg::mod(ix,I.width()),cimg::mod(iy,I.height()), // Periodic + cimg::mod(iz,I.depth())); break; + default : { // Mirror + const int mx = cimg::mod(ix,w2), my = cimg::mod(iy,h2), mz = cimg::mod(iz,d2); + _val = I(mx + CImg& convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) { + if (is_empty() || !kernel) return *this; + return get_convolve(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation).move_to(*this); + } + + //! Convolve image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> get_convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, + const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, + const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) const { + return _correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation,true); + } + + //! Cumulate image values, optionally along specified axis. + /** + \param axis Cumulation axis. Set it to 0 to cumulate all values globally without taking axes into account. + **/ + CImg& cumulate(const char axis=0) { + switch (cimg::lowercase(axis)) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { + T *ptrd = data(0,y,z,c); + Tlong cumul = (Tlong)0; + cimg_forX(*this,x) { cumul+=(Tlong)*ptrd; *(ptrd++) = (T)cumul; } + } + break; + case 'y' : { + const ulongT w = (ulongT)_width; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 && + _width*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { + T *ptrd = data(x,0,z,c); + Tlong cumul = (Tlong)0; + cimg_forY(*this,y) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=w; } + } + } break; + case 'z' : { + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 && + _width*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { + T *ptrd = data(x,y,0,c); + Tlong cumul = (Tlong)0; + cimg_forZ(*this,z) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=wh; } + } + } break; + case 'c' : { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(_spectrum>=(cimg_openmp_sizefactor)*512 && _width*_height*_depth>=16)) + cimg_forXYZ(*this,x,y,z) { + T *ptrd = data(x,y,z,0); + Tlong cumul = (Tlong)0; + cimg_forC(*this,c) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=whd; } + } + } break; + default : { // Global cumulation + Tlong cumul = (Tlong)0; + cimg_for(*this,ptrd,T) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; } + } + } + return *this; + } + + //! Cumulate image values, optionally along specified axis \newinstance. + CImg get_cumulate(const char axis=0) const { + return CImg(*this,false).cumulate(axis); + } + + //! Cumulate image values, along specified axes. + /** + \param axes Cumulation axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& cumulate(const char *const axes) { + for (const char *s = axes; *s; ++s) cumulate(*s); + return *this; + } + + //! Cumulate image values, along specified axes \newinstance. + CImg get_cumulate(const char *const axes) const { + return CImg(*this,false).cumulate(axes); + } + + //! Erode image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the erosion in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& erode(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_erode(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Erode image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_erode(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) const { + if (is_empty() || !kernel) return *this; + if (!is_real && kernel==0) return CImg(width(),height(),depth(),spectrum(),0); + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = kernel.depth()/2, + mx1 = kernel.width() - mx2 - 1, my1 = kernel.height() - my2 - 1, mz1 = kernel.depth() - mz2 - 1, + mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2; + const bool + is_inner_parallel = _width*_height*_depth>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res.size()>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + _cimg_abort_init_openmp; + cimg_abort_init; + cimg_pragma_openmp(parallel for cimg_openmp_if(!is_inner_parallel && is_outer_parallel)) + cimg_forC(res,c) _cimg_abort_try_openmp { + cimg_abort_test; + const CImg img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real erosion + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img(x + xm,y + ym,z + zm) - mval); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img._atXYZ(x + xm,y + ym,z + zm) - mval); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) - mval); + if (cval::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img(x + xm,y + ym,z + zm); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img._atXYZ(x + xm,y + ym,z + zm); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval& erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) { + if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this; + if (sx>1 && _width>1) { // Along X-axis + const int L = width(), off = 1, s = (int)sx, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = buf._data, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; }} + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _height>1) { // Along Y-axis + const int L = height(), off = width(), s = (int)sy, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _depth>1) { // Along Z-axis + const int L = depth(), off = width()*height(), s = (int)sz, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val get_erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).erode(sx,sy,sz); + } + + //! Erode the image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& erode(const unsigned int s) { + return erode(s,s,s); + } + + //! Erode the image by a square structuring element of specified size \newinstance. + CImg get_erode(const unsigned int s) const { + return (+*this).erode(s); + } + + //! Dilate image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the dilation in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& dilate(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_dilate(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Dilate image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_dilate(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) const { + if (is_empty() || !kernel || (!is_real && kernel==0)) return *this; + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx1 = kernel.width()/2, my1 = kernel.height()/2, mz1 = kernel.depth()/2, + mx2 = kernel.width() - mx1 - 1, my2 = kernel.height() - my1 - 1, mz2 = kernel.depth() - mz1 - 1, + mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2; + const bool + is_inner_parallel = _width*_height*_depth>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res.size()>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + _cimg_abort_init_openmp; + cimg_abort_init; + cimg_pragma_openmp(parallel for cimg_openmp_if(!is_inner_parallel && is_outer_parallel)) + cimg_forC(res,c) _cimg_abort_try_openmp { + cimg_abort_test; + const CImg img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real dilation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } _cimg_abort_catch_openmp2 + if (boundary_conditions) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img._atXYZ(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(*this,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + } else { // Binary dilation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } _cimg_abort_catch_openmp2 + if (boundary_conditions) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img._atXYZ(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + } + } _cimg_abort_catch_openmp + cimg_abort_test; + return res; + } + + //! Dilate image by a rectangular structuring element of specified size. + /** + \param sx Width of the structuring element. + \param sy Height of the structuring element. + \param sz Depth of the structuring element. + **/ + CImg& dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) { + if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this; + if (sx>1 && _width>1) { // Along X-axis + const int L = width(), off = 1, s = (int)sx, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(0,y,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + if (sy>1 && _height>1) { // Along Y-axis + const int L = height(), off = width(), s = (int)sy, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,0,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + if (sz>1 && _depth>1) { // Along Z-axis + const int L = depth(), off = width()*height(), s = (int)sz, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,y,0,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + return *this; + } + + //! Dilate image by a rectangular structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).dilate(sx,sy,sz); + } + + //! Dilate image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& dilate(const unsigned int s) { + return dilate(s,s,s); + } + + //! Dilate image by a square structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int s) const { + return (+*this).dilate(s); + } + + //! Compute watershed transform. + /** + \param priority Priority map. + \param is_high_connectivity Boolean that choose between 4(false)- or 8(true)-connectivity + in 2D case, and between 6(false)- or 26(true)-connectivity in 3D case. + \note Non-zero values of the instance instance are propagated to zero-valued ones according to + specified the priority map. + **/ + template + CImg& watershed(const CImg& priority, const bool is_high_connectivity=false) { +#define _cimg_watershed_init(cond,X,Y,Z) \ + if (cond && !(*this)(X,Y,Z)) Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,nb_seeds) + +#define _cimg_watershed_propagate(cond,X,Y,Z) \ + if (cond) { \ + if ((*this)(X,Y,Z)) { \ + ns = labels(X,Y,Z) - 1; xs = seeds(ns,0); ys = seeds(ns,1); zs = seeds(ns,2); \ + d = cimg::sqr((float)x - xs) + cimg::sqr((float)y - ys) + cimg::sqr((float)z - zs); \ + if (d labels(_width,_height,_depth,1,0), seeds(64,3); + CImg::type> Q; + unsigned int sizeQ = 0; + int px, nx, py, ny, pz, nz; + bool is_px, is_nx, is_py, is_ny, is_pz, is_nz; + const bool is_3d = _depth>1; + + // Find seed points and insert them in priority queue. + unsigned int nb_seeds = 0; + const T *ptrs = _data; + cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) { // 3D version + if (nb_seeds>=seeds._width) seeds.resize(2*seeds._width,3,1,1,0); + seeds(nb_seeds,0) = x; seeds(nb_seeds,1) = y; seeds(nb_seeds++,2) = z; + px = x - 1; nx = x + 1; + py = y - 1; ny = y + 1; + pz = z - 1; nz = z + 1; + is_px = px>=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz::inf(); + T nlabel = (T)0; + _cimg_watershed_propagate(is_px,px,y,z); + _cimg_watershed_propagate(is_nx,nx,y,z); + _cimg_watershed_propagate(is_py,x,py,z); + _cimg_watershed_propagate(is_ny,x,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_pz,x,y,pz); + _cimg_watershed_propagate(is_nz,x,y,nz); + } + if (is_high_connectivity) { + _cimg_watershed_propagate(is_px && is_py,px,py,z); + _cimg_watershed_propagate(is_nx && is_py,nx,py,z); + _cimg_watershed_propagate(is_px && is_ny,px,ny,z); + _cimg_watershed_propagate(is_nx && is_ny,nx,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_px && is_pz,px,y,pz); + _cimg_watershed_propagate(is_nx && is_pz,nx,y,pz); + _cimg_watershed_propagate(is_px && is_nz,px,y,nz); + _cimg_watershed_propagate(is_nx && is_nz,nx,y,nz); + _cimg_watershed_propagate(is_py && is_pz,x,py,pz); + _cimg_watershed_propagate(is_ny && is_pz,x,ny,pz); + _cimg_watershed_propagate(is_py && is_nz,x,py,nz); + _cimg_watershed_propagate(is_ny && is_nz,x,ny,nz); + _cimg_watershed_propagate(is_px && is_py && is_pz,px,py,pz); + _cimg_watershed_propagate(is_nx && is_py && is_pz,nx,py,pz); + _cimg_watershed_propagate(is_px && is_ny && is_pz,px,ny,pz); + _cimg_watershed_propagate(is_nx && is_ny && is_pz,nx,ny,pz); + _cimg_watershed_propagate(is_px && is_py && is_nz,px,py,nz); + _cimg_watershed_propagate(is_nx && is_py && is_nz,nx,py,nz); + _cimg_watershed_propagate(is_px && is_ny && is_nz,px,ny,nz); + _cimg_watershed_propagate(is_nx && is_ny && is_nz,nx,ny,nz); + } + } + (*this)(x,y,z) = nlabel; + labels(x,y,z) = ++nmin; + } + return *this; + } + + //! Compute watershed transform \newinstance. + template + CImg get_watershed(const CImg& priority, const bool is_high_connectivity=false) const { + return (+*this).watershed(priority,is_high_connectivity); + } + + // [internal] Insert/Remove items in priority queue, for watershed/distance transforms. + template + bool _priority_queue_insert(CImg& is_queued, unsigned int& siz, const tv value, + const unsigned int x, const unsigned int y, const unsigned int z, + const unsigned int n=1) { + if (is_queued(x,y,z)) return false; + is_queued(x,y,z) = (tq)n; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; + (*this)(siz - 1,1) = (T)x; + (*this)(siz - 1,2) = (T)y; + (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(tv)(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); + cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); + cimg::swap((*this)(pos,3),(*this)(par,3)); + } + return true; + } + + CImg& _priority_queue_remove(unsigned int& siz) { + (*this)(0,0) = (*this)(--siz,0); + (*this)(0,1) = (*this)(siz,1); + (*this)(0,2) = (*this)(siz,2); + (*this)(0,3) = (*this)(siz,3); + const float value = (*this)(0,0); + unsigned int pos = 0, swap = 0; + do { + const unsigned int left = 2*pos + 1, right = left + 1; + if (right(*this)(right,0)?left:right; + else if (left{ 0=smooth-filter | 1=1st-derivative | 2=2nd-derivative }. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + **/ + CImg& deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) { +#define _cimg_deriche_apply \ + CImg Y(N); \ + double *ptrY = Y._data, yb = 0, yp = 0; \ + T xp = (T)0; \ + if (boundary_conditions) { xp = *ptrX; yb = yp = (double)(coefp*xp); } \ + for (int m = 0; m=0; --n) { \ + const T xc = *(ptrX-=off); \ + const double yc = (double)(a2*xn + a3*xa - b1*yn - b2*ya); \ + xa = xn; xn = xc; ya = yn; yn = yc; \ + *ptrX = (T)(*(--ptrY)+yc); \ + } + const char naxis = cimg::lowercase(axis); + const double nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width: + naxis=='y'?_height: + naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.1f && !order)) return *this; + const double + nnsigma = nsigma<0.1f?0.1f:nsigma, + alpha = 1.695f/nnsigma, + ema = std::exp(-alpha), + ema2 = std::exp(-2*alpha), + b1 = -2*ema, + b2 = ema2; + double a0 = 0, a1 = 0, a2 = 0, a3 = 0, coefp = 0, coefn = 0; + switch (order) { + case 0 : { + const double k = (1-ema)*(1-ema)/(1 + 2*alpha*ema-ema2); + a0 = k; + a1 = k*(alpha - 1)*ema; + a2 = k*(alpha + 1)*ema; + a3 = -k*ema2; + } break; + case 1 : { + const double k = -(1-ema)*(1-ema)*(1-ema)/(2*(ema + 1)*ema); + a0 = a3 = 0; + a1 = k*ema; + a2 = -a1; + } break; + case 2 : { + const double + ea = std::exp(-alpha), + k = -(ema2 - 1)/(2*alpha*ema), + kn = (-2*(-1 + 3*ea - 3*ea*ea + ea*ea*ea)/(3*ea + 1 + 3*ea*ea + ea*ea*ea)); + a0 = kn; + a1 = -kn*(1 + k*alpha)*ema; + a2 = kn*(1 - k*alpha)*ema; + a3 = -kn*ema2; + } break; + default : + throw CImgArgumentException(_cimg_instance + "deriche(): Invalid specified filter order %u " + "(should be { 0=smoothing | 1=1st-derivative | 2=2nd-derivative }).", + cimg_instance, + order); + } + coefp = (a0 + a1)/(1 + b1 + b2); + coefn = (a2 + a3)/(1 + b1 + b2); + switch (naxis) { + case 'x' : { + const int N = width(); + const ulongT off = 1U; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { T *ptrX = data(0,y,z,c); _cimg_deriche_apply; } + } break; + case 'y' : { + const int N = height(); + const ulongT off = (ulongT)_width; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { T *ptrX = data(x,0,z,c); _cimg_deriche_apply; } + } break; + case 'z' : { + const int N = depth(); + const ulongT off = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { T *ptrX = data(x,y,0,c); _cimg_deriche_apply; } + } break; + default : { + const int N = spectrum(); + const ulongT off = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) { T *ptrX = data(x,y,z,0); _cimg_deriche_apply; } + } + } + return *this; + } + + //! Apply recursive Deriche filter \newinstance. + CImg get_deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).deriche(sigma,order,axis,boundary_conditions); + } + + // [internal] Apply a recursive filter (used by CImg::vanvliet()). + /* + \param ptr the pointer of the data + \param filter the coefficient of the filter in the following order [n,n - 1,n - 2,n - 3]. + \param N size of the data + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivative, 2nd derivative, 3rd derivative + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note Boundary condition using B. Triggs method (IEEE trans on Sig Proc 2005). + */ + static void _cimg_recursive_apply(T *data, const double filter[], const int N, const ulongT off, + const unsigned int order, const bool boundary_conditions) { + double val[4] = { 0 }; // res[n,n - 1,n - 2,n - 3,..] or res[n,n + 1,n + 2,n + 3,..] + const double + sumsq = filter[0], sum = sumsq * sumsq, + a1 = filter[1], a2 = filter[2], a3 = filter[3], + scaleM = 1. / ( (1. + a1 - a2 + a3) * (1. - a1 - a2 - a3) * (1. + a2 + (a1 - a3) * a3) ); + double M[9]; // Triggs matrix + M[0] = scaleM * (-a3 * a1 + 1. - a3 * a3 - a2); + M[1] = scaleM * (a3 + a1) * (a2 + a3 * a1); + M[2] = scaleM * a3 * (a1 + a3 * a2); + M[3] = scaleM * (a1 + a3 * a2); + M[4] = -scaleM * (a2 - 1.) * (a2 + a3 * a1); + M[5] = -scaleM * a3 * (a3 * a1 + a3 * a3 + a2 - 1.); + M[6] = scaleM * (a3 * a1 + a2 + a1 * a1 - a2 * a2); + M[7] = scaleM * (a1 * a2 + a3 * a2 * a2 - a1 * a3 * a3 - a3 * a3 * a3 - a3 * a2 + a3); + M[8] = scaleM * a3 * (a1 + a3 * a2); + switch (order) { + case 0 : { + const double iplus = (boundary_conditions?data[(N - 1)*off]:(T)0); + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 1; k<4; ++k) val[k] = (boundary_conditions?*data/sumsq:0); + } else { + // Apply Triggs boundary conditions + const double + uplus = iplus/(1. - a1 - a2 - a3), vplus = uplus/(1. - a1 - a2 - a3), + unp = val[1] - uplus, unp1 = val[2] - uplus, unp2 = val[3] - uplus; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2 + vplus) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2 + vplus) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2 + vplus) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) val[k] = val[k - 1]; + } + if (!pass) data -= off; + } + } break; + case 1 : { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + } else { data-=off;} + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 2: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 3: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + } + } + + //! Van Vliet recursive Gaussian filter. + /** + \param sigma standard deviation of the Gaussian filter + \param order the order of the filter 0,1,2,3 + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note dirichlet boundary condition has a strange behavior + + I.T. Young, L.J. van Vliet, M. van Ginkel, Recursive Gabor filtering. + IEEE Trans. Sig. Proc., vol. 50, pp. 2799-2805, 2002. + + (this is an improvement over Young-Van Vliet, Sig. Proc. 44, 1995) + + Boundary conditions (only for order 0) using Triggs matrix, from + B. Triggs and M. Sdika. Boundary conditions for Young-van Vliet + recursive filtering. IEEE Trans. Signal Processing, + vol. 54, pp. 2365-2367, 2006. + **/ + CImg& vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) { + if (is_empty()) return *this; + if (!cimg::type::is_float()) + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions).move_to(*this); + const char naxis = cimg::lowercase(axis); + const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.5f && !order)) return *this; + const double + nnsigma = nsigma<0.5f?0.5f:nsigma, + m0 = 1.16680, m1 = 1.10783, m2 = 1.40586, + m1sq = m1 * m1, m2sq = m2 * m2, + q = (nnsigma<3.556?-0.2568 + 0.5784*nnsigma + 0.0561*nnsigma*nnsigma:2.5091 + 0.9804*(nnsigma - 3.556)), + qsq = q * q, + scale = (m0 + q) * (m1sq + m2sq + 2 * m1 * q + qsq), + b1 = -q * (2 * m0 * m1 + m1sq + m2sq + (2 * m0 + 4 * m1) * q + 3 * qsq) / scale, + b2 = qsq * (m0 + 2 * m1 + 3 * q) / scale, + b3 = -qsq * q / scale, + B = ( m0 * (m1sq + m2sq) ) / scale; + double filter[4]; + filter[0] = B; filter[1] = -b1; filter[2] = -b2; filter[3] = -b3; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_recursive_apply(data(0,y,z,c),filter,_width,1U,order,boundary_conditions); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_recursive_apply(data(x,0,z,c),filter,_height,(ulongT)_width,order,boundary_conditions); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(ulongT)_width*_height, + order,boundary_conditions); + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions); + } + } + return *this; + } + + //! Blur image using Van Vliet recursive Gaussian filter. \newinstance. + CImg get_vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions); + } + + //! Blur image. + /** + \param sigma_x Standard deviation of the blur, along the X-axis. + \param sigma_y Standard deviation of the blur, along the Y-axis. + \param sigma_z Standard deviation of the blur, along the Z-axis. + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param is_gaussian Tells if the blur uses a gaussian (\c true) or quasi-gaussian (\c false) kernel. + \note + - The blur is computed as a 0-order Vanvliet (gaussian) or Deriche filter (quasi-gaussian). + - This is a recursive algorithm, not depending on the values of the standard deviations. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=true) { + if (is_empty()) return *this; + if (is_gaussian) { + if (_width>1) vanvliet(sigma_x,0,'x',boundary_conditions); + if (_height>1) vanvliet(sigma_y,0,'y',boundary_conditions); + if (_depth>1) vanvliet(sigma_z,0,'z',boundary_conditions); + } else { + if (_width>1) deriche(sigma_x,0,'x',boundary_conditions); + if (_height>1) deriche(sigma_y,0,'y',boundary_conditions); + if (_depth>1) deriche(sigma_z,0,'z',boundary_conditions); + } + return *this; + } + + //! Blur image \newinstance. + CImg get_blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=true) const { + return CImg(*this,false).blur(sigma_x,sigma_y,sigma_z,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically. + /** + \param sigma Standard deviation of the blur. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \param is_gaussian Use a gaussian kernel (VanVliet) is set, a quasi-gaussian (Deriche) otherwise. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=true) { + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur(nsigma,nsigma,nsigma,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically \newinstance. + CImg get_blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=true) const { + return CImg(*this,false).blur(sigma,boundary_conditions,is_gaussian); + } + + //! Blur image anisotropically, directed by a field of diffusion tensors. + /** + \param G Field of square roots of diffusion tensors/vectors used to drive the smoothing. + \param amplitude Amplitude of the smoothing. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=1) { + + // Check arguments and init variables + if (!is_sameXYZ(G) || (G._spectrum!=3 && G._spectrum!=6)) + throw CImgArgumentException(_cimg_instance + "blur_anisotropic(): Invalid specified diffusion tensor field (%u,%u,%u,%u,%p).", + cimg_instance, + G._width,G._height,G._depth,G._spectrum,G._data); + if (is_empty() || dl<0) return *this; + const float namplitude = amplitude>=0?amplitude:-amplitude*cimg::max(_width,_height,_depth)/100; + unsigned int iamplitude = cimg::round(namplitude); + const bool is_3d = (G._spectrum==6); + T val_min, val_max = max_min(val_min); + _cimg_abort_init_openmp; + cimg_abort_init; + + if (da<=0) { // Iterated oriented Laplacians + CImg velocity(_width,_height,_depth,_spectrum); + for (unsigned int iteration = 0; iterationveloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + else // 2D version + cimg_forZC(*this,z,c) { + cimg_abort_test; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + veloc = (Tfloat)(G(x,y,0,0)*ixx + 2*G(x,y,0,1)*ixy + G(x,y,0,2)*iyy); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + if (veloc_max>0) *this+=(velocity*=dl/veloc_max); + } + } else { // LIC-based smoothing + const ulongT whd = (ulongT)_width*_height*_depth; + const float sqrt2amplitude = (float)std::sqrt(2*namplitude); + const int dx1 = width() - 1, dy1 = height() - 1, dz1 = depth() - 1; + CImg res(_width,_height,_depth,_spectrum,0), W(_width,_height,_depth,is_3d?4:3), val(_spectrum,1,1,1,0); + int N = 0; + if (is_3d) { // 3D version + for (float phi = cimg::mod(180.f,da)/2.f; phi<=180; phi+=da) { + const float phir = (float)(phi*cimg::PI/180), datmp = (float)(da/std::cos(phir)), + da2 = datmp<1?360.f:datmp; + for (float theta = 0; theta<360; (theta+=da2),++N) { + const float + thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)*std::cos(phir)), + vy = (float)(std::sin(thetar)*std::cos(phir)), + vz = (float)std::sin(phir); + const t + *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2), + *pd = G.data(0,0,0,3), *pe = G.data(0,0,0,4), *pf = G.data(0,0,0,5); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2), *pd3 = W.data(0,0,0,3); + cimg_forXYZ(G,xg,yg,zg) { + const t a = *(pa++), b = *(pb++), c = *(pc++), d = *(pd++), e = *(pe++), f = *(pf++); + const float + u = (float)(a*vx + b*vy + c*vz), + v = (float)(b*vx + d*vy + e*vz), + w = (float)(c*vx + e*vy + f*vz), + n = 1e-5f + cimg::hypot(u,v,w), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)(w*dln); + *(pd3++) = (Tfloat)n; + } + + cimg_abort_test; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && _height*_depth>=2) + firstprivate(val)) + cimg_forYZ(*this,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,z,3), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y, + Z = (float)z; + switch (interpolation_type) { + case 0 : { // Nearest neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f), + cz = (int)(Z + 0.5f); + const float + u = (float)W(cx,cy,cz,0), + v = (float)W(cx,cy,cz,1), + w = (float)W(cx,cy,cz,2); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,cz,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,cz,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u = (float)(W._linear_atXYZ(X,Y,Z,0)), + v = (float)(W._linear_atXYZ(X,Y,Z,1)), + w = (float)(W._linear_atXYZ(X,Y,Z,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + default : { // 2nd order Runge Kutta + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)), + v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)), + w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)), + u = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,0)), + v = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,1)), + w = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + } + Tfloat *ptrd = res.data(x,y,z); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,z,c)); ptrd+=whd; } + } + } _cimg_abort_catch_openmp2 + } + } + } else { // 2D LIC algorithm + for (float theta = cimg::mod(360.f,da)/2.f; theta<360; (theta+=da),++N) { + const float thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar)); + const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2); + cimg_forXY(G,xg,yg) { + const t a = *(pa++), b = *(pb++), c = *(pc++); + const float + u = (float)(a*vx + b*vy), + v = (float)(b*vx + c*vy), + n = std::max(1e-5f,cimg::hypot(u,v)), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)n; + } + + cimg_abort_test; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && _height>=2) + firstprivate(val)) + cimg_forY(*this,y) _cimg_abort_try_openmp2 { + cimg_abort_test2; + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,0,2), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y; + switch (interpolation_type) { + case 0 : { // Nearest-neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f); + const float + u = (float)W(cx,cy,0,0), + v = (float)W(cx,cy,0,1); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u = (float)(W._linear_atXY(X,Y,0,0)), + v = (float)(W._linear_atXY(X,Y,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + default : { // 2nd-order Runge-kutta interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)), + v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)), + u = (float)(W._linear_atXY(X + u0,Y + v0,0,0)), + v = (float)(W._linear_atXY(X + u0,Y + v0,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } + } + Tfloat *ptrd = res.data(x,y); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,0,c)); ptrd+=whd; } + } + } _cimg_abort_catch_openmp2 + } + } + const Tfloat *ptrs = res._data; + cimg_for(*this,ptrd,T) { + const Tfloat _val = *(ptrs++)/N; + *ptrd = _valval_max?val_max:(T)_val); + } + } + cimg_abort_test; + return *this; + } + + //! Blur image anisotropically, directed by a field of diffusion tensors \newinstance. + template + CImg get_blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way. + /** + \param amplitude Amplitude of the smoothing. + \param sharpness Sharpness. + \param anisotropy Anisotropy. + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + CImg& blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) { + const float nalpha = alpha>=0?alpha:-alpha*cimg::max(_width,_height,_depth)/100; + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur_anisotropic(get_diffusion_tensors(sharpness,anisotropy,nalpha,nsigma,interpolation_type!=3), + amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way \newinstance. + CImg get_blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, + const float da=30, const float gauss_prec=2, + const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec, + interpolation_type,is_fast_approx); + } + + //! Blur image, with the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_x Amount of blur along the X-axis. + \param sigma_y Amount of blur along the Y-axis. + \param sigma_z Amount of blur along the Z-axis. + \param sigma_r Amount of blur along the value axis. + \param sampling_x Amount of downsampling along the X-axis used for the approximation. + Defaults (0) to sigma_x. + \param sampling_y Amount of downsampling along the Y-axis used for the approximation. + Defaults (0) to sigma_y. + \param sampling_z Amount of downsampling along the Z-axis used for the approximation. + Defaults (0) to sigma_z. + \param sampling_r Amount of downsampling along the value axis used for the approximation. + Defaults (0) to sigma_r. + \note This algorithm uses the optimisation technique proposed by S. Paris and F. Durand, in ECCV'2006 + (extended for 3D volumetric images). + It is based on the reference implementation http://people.csail.mit.edu/jiawen/software/bilateralFilter.m + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_bilateral(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || (!sigma_x && !sigma_y && !sigma_z)) return *this; + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return blur(sigma_x,sigma_y,sigma_z); + const float + edge_delta = (float)(edge_max - edge_min), + _sigma_x = sigma_x>=0?sigma_x:-sigma_x*_width/100, + _sigma_y = sigma_y>=0?sigma_y:-sigma_y*_height/100, + _sigma_z = sigma_z>=0?sigma_z:-sigma_z*_depth/100, + _sigma_r = sigma_r>=0?sigma_r:-sigma_r*edge_delta/100, + _sampling_x = sampling_x?sampling_x:std::max(_sigma_x,1.f), + _sampling_y = sampling_y?sampling_y:std::max(_sigma_y,1.f), + _sampling_z = sampling_z?sampling_z:std::max(_sigma_z,1.f), + _sampling_r = sampling_r?sampling_r:std::max(_sigma_r,edge_delta/256), + derived_sigma_x = _sigma_x / _sampling_x, + derived_sigma_y = _sigma_y / _sampling_y, + derived_sigma_z = _sigma_z / _sampling_z, + derived_sigma_r = _sigma_r / _sampling_r; + const int + padding_x = (int)(2*derived_sigma_x) + 1, + padding_y = (int)(2*derived_sigma_y) + 1, + padding_z = (int)(2*derived_sigma_z) + 1, + padding_r = (int)(2*derived_sigma_r) + 1; + const unsigned int + bx = (unsigned int)((_width - 1)/_sampling_x + 1 + 2*padding_x), + by = (unsigned int)((_height - 1)/_sampling_y + 1 + 2*padding_y), + bz = (unsigned int)((_depth - 1)/_sampling_z + 1 + 2*padding_z), + br = (unsigned int)(edge_delta/_sampling_r + 1 + 2*padding_r); + if (bx>0 || by>0 || bz>0 || br>0) { + const bool is_3d = (_depth>1); + if (is_3d) { // 3D version of the algorithm + CImg bgrid(bx,by,bz,br), bgridw(bx,by,bz,br); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); bgridw.fill(0); + cimg_forXYZ(*this,x,y,z) { + const T val = (*this)(x,y,z,c); + const float edge = (float)_guide(x,y,z); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + Z = (int)cimg::round(z/_sampling_z) + padding_z, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,Z,R)+=(float)val; + bgridw(X,Y,Z,R)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + bgridw.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),4096)) + cimg_forXYZ(*this,x,y,z) { + const float edge = (float)_guide(x,y,z); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + Z = z/_sampling_z + padding_z, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid._linear_atXYZC(X,Y,Z,R), bval1 = bgridw._linear_atXYZC(X,Y,Z,R); + (*this)(x,y,z,c) = (T)(bval0/bval1); + } + } + } else { // 2D version of the algorithm + CImg bgrid(bx,by,br,2); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); + cimg_forXY(*this,x,y) { + const T val = (*this)(x,y,c); + const float edge = (float)_guide(x,y); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,R,0)+=(float)val; + bgrid(X,Y,R,1)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,0,true).blur(0,0,derived_sigma_r,false); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(size(),4096)) + cimg_forXY(*this,x,y) { + const float edge = (float)_guide(x,y); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid._linear_atXYZ(X,Y,R,0), bval1 = bgrid._linear_atXYZ(X,Y,R,1); + (*this)(x,y,c) = (T)(bval0/bval1); + } + } + } + } + return *this; + } + + //! Blur image, with the joint bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) const { + return CImg(*this,false).blur_bilateral(guide,sigma_x,sigma_y,sigma_z,sigma_r, + sampling_x,sampling_y,sampling_z,sampling_r); + } + + //! Blur image using the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param sampling_s Amount of downsampling along the XYZ-axes used for the approximation. Defaults to sigma_s. + \param sampling_r Amount of downsampling along the value axis used for the approximation. Defaults to sigma_r. + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) { + const float _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100; + return blur_bilateral(guide,_sigma_s,_sigma_s,_sigma_s,sigma_r,sampling_s,sampling_s,sampling_s,sampling_r); + } + + //! Blur image using the bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) const { + return CImg(*this,false).blur_bilateral(guide,sigma_s,sigma_r,sampling_s,sampling_r); + } + + // [internal] Apply a box filter (used by CImg::boxfilter() and CImg::blur_box()). + /* + \param ptr the pointer of the data + \param N size of the data + \param boxsize Size of the box filter (can be subpixel). + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivative and 2nd derivative. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + */ + static void _cimg_blur_box_apply(T *ptr, const float boxsize, const int N, const ulongT off, + const int order, const bool boundary_conditions, + const unsigned int nb_iter) { + // Smooth. + if (boxsize>1 && nb_iter) { + const int w2 = (int)(boxsize - 1)/2; + const unsigned int winsize = 2*w2 + 1U; + const double frac = (boxsize - winsize)/2.; + CImg win(winsize); + for (unsigned int iter = 0; iter=N) return boundary_conditions?ptr[(N - 1)*off]:T(); + return ptr[x*off]; + } + + // Apply box filter of order 0,1,2. + /** + \param boxsize Size of the box window (can be subpixel) + \param order the order of the filter 0,1 or 2. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \param nb_iter Number of filter iterations. + **/ + CImg& boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true, + const unsigned int nb_iter=1) { + if (is_empty() || !boxsize || (boxsize<=1 && !order)) return *this; + const char naxis = cimg::lowercase(axis); + const float nboxsize = boxsize>=0?boxsize:-boxsize* + (naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_blur_box_apply(data(0,y,z,c),nboxsize,_width,1U,order,boundary_conditions,nb_iter); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_blur_box_apply(data(x,0,z,c),nboxsize,_height,(ulongT)_width,order,boundary_conditions,nb_iter); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_blur_box_apply(data(x,y,0,c),nboxsize,_depth,(ulongT)_width*_height,order,boundary_conditions,nb_iter); + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_blur_box_apply(data(x,y,z,0),nboxsize,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions,nb_iter); + } + } + return *this; + } + + // Apply box filter of order 0,1 or 2 \newinstance. + CImg get_boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true, + const unsigned int nb_iter=1) const { + return CImg(*this,false).boxfilter(boxsize,order,axis,boundary_conditions,nb_iter); + } + + //! Blur image with a box filter. + /** + \param boxsize_x Size of the box window, along the X-axis (can be subpixel). + \param boxsize_y Size of the box window, along the Y-axis (can be subpixel). + \param boxsize_z Size of the box window, along the Z-axis (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param nb_iter Number of filter iterations. + \note + - This is a recursive algorithm, not depending on the values of the box kernel size. + \see blur(). + **/ + CImg& blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true, + const unsigned int nb_iter=1) { + if (is_empty()) return *this; + if (_width>1) boxfilter(boxsize_x,0,'x',boundary_conditions,nb_iter); + if (_height>1) boxfilter(boxsize_y,0,'y',boundary_conditions,nb_iter); + if (_depth>1) boxfilter(boxsize_z,0,'z',boundary_conditions,nb_iter); + return *this; + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize_x,boxsize_y,boxsize_z,boundary_conditions); + } + + //! Blur image with a box filter. + /** + \param boxsize Size of the box window (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \see deriche(), vanvliet(). + **/ + CImg& blur_box(const float boxsize, const bool boundary_conditions=true) { + const float nboxsize = boxsize>=0?boxsize:-boxsize*cimg::max(_width,_height,_depth)/100; + return blur_box(nboxsize,nboxsize,nboxsize,boundary_conditions); + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize, const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize,boundary_conditions); + } + + //! Blur image, with the image guided filter. + /** + \param guide Image used to guide the smoothing process. + \param radius Spatial radius. If negative, it is expressed as a percentage of the largest image size. + \param regularization Regularization parameter. + If negative, it is expressed as a percentage of the guide value range. + \note This method implements the filtering algorithm described in: + He, Kaiming; Sun, Jian; Tang, Xiaoou, "Guided Image Filtering," Pattern Analysis and Machine Intelligence, + IEEE Transactions on , vol.35, no.6, pp.1397,1409, June 2013 + **/ + template + CImg& blur_guided(const CImg& guide, const float radius, const float regularization) { + return get_blur_guided(guide,radius,regularization).move_to(*this); + } + + //! Blur image, with the image guided filter \newinstance. + template + CImg get_blur_guided(const CImg& guide, const float radius, const float regularization) const { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_guided(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !radius) return *this; + const int _radius = radius>=0?(int)radius:(int)(-radius*cimg::max(_width,_height,_depth)/100); + float _regularization = regularization; + if (regularization<0) { + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return *this; + _regularization = -regularization*(edge_max - edge_min)/100; + } + _regularization = std::max(_regularization,0.01f); + const unsigned int psize = (unsigned int)(1 + 2*_radius); + CImg + mean_p = get_blur_box(psize,true), + mean_I = guide.get_blur_box(psize,true).resize(mean_p), + cov_Ip = get_mul(guide).blur_box(psize,true)-=mean_p.get_mul(mean_I), + var_I = guide.get_sqr().blur_box(psize,true)-=mean_I.get_sqr(), + &a = cov_Ip.div(var_I+=_regularization), + &b = mean_p-=a.get_mul(mean_I); + a.blur_box(psize,true); + b.blur_box(psize,true); + return a.mul(guide)+=b; + } + + //! Blur image using patch-based space. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param patch_size Size of the patches. + \param lookup_size Size of the window to search similar patches. + \param smoothness Smoothness for the patch comparison. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_patch(const CImg& guide, + const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + if (is_empty() || !patch_size || !lookup_size) return *this; + return get_blur_patch(guide,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx).move_to(*this); + } + + //! Blur image using patch-based space \newinstance. + template + CImg get_blur_patch(const CImg& guide, + const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + +#define _cimg_blur_patch3d_fast(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) \ + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) \ + firstprivate(P,Q)) \ + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N##x##N(res,x,y,z); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,x,y,z,c,pP,tfloat); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + tfloat sum_weights = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) \ + if (cimg::abs(_guide(x,y,z,0) - _guide(p,q,r,0))3?0:1; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); \ + } \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch3d(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) \ + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) \ + firstprivate(P,Q)) \ + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N##x##N(res,x,y,z); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,x,y,z,c,pP,tfloat); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + tfloat sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { \ + tfloat *pQ = Q._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,p,q,r,c,pQ,tfloat); pQ+=N3; } \ + tfloat distance2 = 0; \ + pQ = Q._data; cimg_for(P,_pP,tfloat) { const tfloat dI = *_pP - *(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const tfloat dx = (tfloat)p - x, dy = (tfloat)q - y, dz = (tfloat)r - z, \ + alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight_max*(*this)(x,y,z,c); \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch2d_fast(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) \ + firstprivate(P,Q)) \ + cimg_forXY(res,x,y) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N(res,x,y); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,x,y,0,c,pP,tfloat); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + tfloat sum_weights = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) \ + if (cimg::abs(_guide(x,y,0,0) - _guide(p,q,0,0))3?0:1; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); \ + } \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch2d(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) \ + firstprivate(P,Q)) \ + cimg_forXY(res,x,y) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N(res,x,y); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,x,y,0,c,pP,tfloat); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + tfloat sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { \ + tfloat *pQ = Q._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,p,q,0,c,pQ,tfloat); pQ+=N2; } \ + tfloat distance2 = 0; \ + pQ = Q._data; cimg_for(P,_pP,tfloat) { const tfloat dI = *_pP - *(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const tfloat dx = (tfloat)p - x, dy = (tfloat)q - y, \ + alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight_max*(*this)(x,y,c); \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } _cimg_abort_catch_openmp } + + typedef _cimg_tfloat tfloat; + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_patch(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !patch_size || !lookup_size) return +*this; + Tfloat val_min, val_max = (Tfloat)max_min(val_min); + _cimg_abort_init_openmp; + cimg_abort_init; + + CImg res(_width,_height,_depth,_spectrum,0); + const CImg + __guide = guide?CImg(guide,guide.pixel_type()==cimg::type::string()): + CImg(*this,pixel_type()==cimg::type::string()), + _guide = smoothness>0?__guide.get_blur(smoothness):__guide.get_shared(); + CImg P(_guide._spectrum*patch_size*patch_size*(_depth>1?patch_size:1)), Q(P); + + t guide_min = (t)0, guide_max = (t)0; + if (sigma_r<0) guide_max = guide.max_min(guide_min); + const float + guide_delta = (float)(guide_max - guide_min), + _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100, + _sigma_r = sigma_r>=0?sigma_r:-sigma_r*guide_delta/100, + sigma_s2 = _sigma_s*_sigma_s, + sigma_r2 = _sigma_r*_sigma_r, + sigma_r3 = 3*_sigma_r, + Pnorm = P.size()*sigma_r2; + const int rsize2 = (int)lookup_size/2, rsize1 = (int)lookup_size - rsize2 - 1; + const unsigned int N2 = patch_size*patch_size, N3 = N2*patch_size; + cimg::unused(N2,N3); + if (_depth>1) switch (patch_size) { // 3D + case 2 : if (is_fast_approx) _cimg_blur_patch3d_fast(2) else _cimg_blur_patch3d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch3d_fast(3) else _cimg_blur_patch3d(3) break; + default : { + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) + firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { // Fast + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + tfloat sum_weights = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) + if (cimg::abs(_guide(x,y,z,0) - _guide(p,q,r,0))3?0:1; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); + } + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } _cimg_abort_catch_openmp + } else { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) + firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { // Exact + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + tfloat sum_weights = 0, weight_max = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { + (Q = _guide.get_crop(p - psize1,q - psize1,r - psize1,p + psize2,q + psize2,r + psize2,true))-=P; + const tfloat + dx = (tfloat)x - p, dy = (tfloat)y - q, dz = (tfloat)z - r, + distance2 = (tfloat)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2), + weight = std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight_max*(*this)(x,y,z,c); + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } _cimg_abort_catch_openmp + } + } + } else switch (patch_size) { // 2D + case 2 : if (is_fast_approx) _cimg_blur_patch2d_fast(2) else _cimg_blur_patch2d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch2d_fast(3) else _cimg_blur_patch2d(3) break; + case 4 : if (is_fast_approx) _cimg_blur_patch2d_fast(4) else _cimg_blur_patch2d(4) break; + case 5 : if (is_fast_approx) _cimg_blur_patch2d_fast(5) else _cimg_blur_patch2d(5) break; + case 6 : if (is_fast_approx) _cimg_blur_patch2d_fast(6) else _cimg_blur_patch2d(6) break; + case 7 : if (is_fast_approx) _cimg_blur_patch2d_fast(7) else _cimg_blur_patch2d(7) break; + case 8 : if (is_fast_approx) _cimg_blur_patch2d_fast(8) else _cimg_blur_patch2d(8) break; + case 9 : if (is_fast_approx) _cimg_blur_patch2d_fast(9) else _cimg_blur_patch2d(9) break; + default : { // Fast + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) { + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) + firstprivate(P,Q)) + cimg_forXY(res,x,y) _cimg_abort_try_openmp { // Fast + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + tfloat sum_weights = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) + if (cimg::abs(_guide(x,y,0) - _guide(p,q,0))3?0:1; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); + } + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } _cimg_abort_catch_openmp + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) + firstprivate(P,Q)) + cimg_forXY(res,x,y) _cimg_abort_try_openmp { // Exact + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + tfloat sum_weights = 0, weight_max = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { + (Q = _guide.get_crop(p - psize1,q - psize1,p + psize2,q + psize2,true))-=P; + const tfloat + dx = (tfloat)x - p, dy = (tfloat)y - q, + distance2 = (tfloat)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2), + weight = std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight_max*(*this)(x,y,c); + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } _cimg_abort_catch_openmp + } + } + } + return res.cut(val_min,val_max); + } + + //! Blur image using patch-based space \simplification. + CImg& blur_patch(const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + return blur_patch(*this,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx); + } + + //! Blur image using patch-based space \simplification \newinstance. + CImg get_blur_patch(const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + return get_blur_patch(*this,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx); + } + + //! Blur image with the median filter. + /** + \param n Size of the median filter. + \param threshold Threshold used to discard pixels too far from the current pixel value in the median computation. + **/ + CImg& blur_median(const unsigned int n, const float threshold=0) { + if (!n) return *this; + return get_blur_median(n,threshold).move_to(*this); + } + + //! Blur image with the median filter \newinstance. + CImg get_blur_median(const unsigned int n, const float threshold=0) const { + if (is_empty() || n<=1) return +*this; + CImg res(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg::unused(ptrd); + const int hr = (int)n/2, hl = n - hr - 1; + if (res._depth!=1) { // 3D + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // With threshold + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + const Tfloat val0 = (Tfloat)(*this)(x,y,z,c); + CImg values(n*n*n); + unsigned int nb_values = 0; + T *_ptrd = values.data(); + cimg_for_inXYZ(*this,nx0,ny0,nz0,nx1,ny1,nz1,p,q,r) + if (cimg::abs((*this)(p,q,r,c) - val0)<=threshold) { *(_ptrd++) = (*this)(p,q,r,c); ++nb_values; } + res(x,y,z,c) = nb_values?values.get_shared_points(0,nb_values - 1).median():(*this)(x,y,z,c); + } + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // Without threshold + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + res(x,y,z,c) = get_crop(nx0,ny0,nz0,c,nx1,ny1,nz1,c).median(); + } + } else { + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { // With threshold + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + const Tfloat val0 = (Tfloat)(*this)(x,y,c); + CImg values(n*n); + unsigned int nb_values = 0; + T *_ptrd = values.data(); + cimg_for_inXY(*this,nx0,ny0,nx1,ny1,p,q) + if (cimg::abs((*this)(p,q,c) - val0)<=threshold) { *(_ptrd++) = (*this)(p,q,c); ++nb_values; } + res(x,y,c) = nb_values?values.get_shared_points(0,nb_values - 1).median():(*this)(x,y,c); + } + else { + const int + w1 = width() - 1, h1 = height() - 1, + w2 = width() - 2, h2 = height() - 2, + w3 = width() - 3, h3 = height() - 3, + w4 = width() - 4, h4 = height() - 4; + switch (n) { // Without threshold + case 3 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(9); + cimg_for_in3x3(*this,1,1,w2,h2,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6],I[7],I[8]); + cimg_for_borderXY(*this,x,y,1) + res(x,y,c) = get_crop(std::max(0,x - 1),std::max(0,y - 1),0,c, + std::min(w1,x + 1),std::min(h1,y + 1),0,c).median(); + } + } break; + case 5 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(25); + cimg_for_in5x5(*this,2,2,w3,h3,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4], + I[5],I[6],I[7],I[8],I[9], + I[10],I[11],I[12],I[13],I[14], + I[15],I[16],I[17],I[18],I[19], + I[20],I[21],I[22],I[23],I[24]); + cimg_for_borderXY(*this,x,y,2) + res(x,y,c) = get_crop(std::max(0,x - 2),std::max(0,y - 2),0,c, + std::min(w1,x + 2),std::min(h1,y + 2),0,c).median(); + } + } break; + case 7 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(49); + cimg_for_in7x7(*this,3,3,w4,h4,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6], + I[7],I[8],I[9],I[10],I[11],I[12],I[13], + I[14],I[15],I[16],I[17],I[18],I[19],I[20], + I[21],I[22],I[23],I[24],I[25],I[26],I[27], + I[28],I[29],I[30],I[31],I[32],I[33],I[34], + I[35],I[36],I[37],I[38],I[39],I[40],I[41], + I[42],I[43],I[44],I[45],I[46],I[47],I[48]); + cimg_for_borderXY(*this,x,y,3) + res(x,y,c) = get_crop(std::max(0,x - 3),std::max(0,y - 3),0,c, + std::min(w1,x + 3),std::min(h1,y + 3),0,c).median(); + } + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + res(x,y,c) = get_crop(nx0,ny0,0,c,nx1,ny1,0,c).median(); + } + } + } + } + } + return res; + } + + //! Sharpen image. + /** + \param amplitude Sharpening amplitude + \param sharpen_type Select sharpening method. Can be { false=inverse diffusion | true=shock filters }. + \param edge Edge threshold (shock filters only). + \param alpha Gradient smoothness (shock filters only). + \param sigma Tensor smoothness (shock filters only). + **/ + CImg& sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) { + if (is_empty()) return *this; + T val_min, val_max = max_min(val_min); + const float nedge = edge/2; + CImg velocity(_width,_height,_depth,_spectrum), _veloc_max(_spectrum); + + if (_depth>1) { // 3D + if (sharpen_type) { // Shock filters + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*32 && + _height*_depth>=16)) + cimg_forYZ(G,y,z) { + Tfloat *ptrG0 = G.data(0,y,z,0), *ptrG1 = G.data(0,y,z,1), + *ptrG2 = G.data(0,y,z,2), *ptrG3 = G.data(0,y,z,3); + CImg val, vec; + cimg_forX(G,x) { + G.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + if (val[2]<0) val[2] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = vec(0,2); + *(ptrG3++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1] + val[2],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + u = G(x,y,z,0), + v = G(x,y,z,1), + w = G(x,y,z,2), + amp = G(x,y,z,3), + ixx = Incc + Ipcc - 2*Iccc, + ixy = (Innc + Ippc - Inpc - Ipnc)/4, + ixz = (Incn + Ipcp - Incp - Ipcn)/4, + iyy = Icnc + Icpc - 2*Iccc, + iyz = (Icnn + Icpp - Icnp - Icpn)/4, + izz = Iccn + Iccp - 2*Iccc, + ixf = Incc - Iccc, + ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, + iyb = Iccc - Icpc, + izf = Iccn - Iccc, + izb = Iccc - Iccp, + itt = u*u*ixx + v*v*iyy + w*w*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb) + w*cimg::minmod(izf,izb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat veloc = -Ipcc - Incc - Icpc - Icnc - Iccp - Iccn + 6*Iccc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else { // 2D + if (sharpen_type) { // Shock filters + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*32 && + _height>=(cimg_openmp_sizefactor)*16)) + cimg_forY(G,y) { + CImg val, vec; + Tfloat *ptrG0 = G.data(0,y,0,0), *ptrG1 = G.data(0,y,0,1), *ptrG2 = G.data(0,y,0,2); + cimg_forX(G,x) { + G.get_tensor_at(x,y).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + u = G(x,y,0), + v = G(x,y,1), + amp = G(x,y,2), + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + ixf = Inc - Icc, + ixb = Icc - Ipc, + iyf = Icn - Icc, + iyb = Icc - Icp, + itt = u*u*ixx + v*v*iyy + 2*u*v*ixy, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat veloc = -Ipc - Inc - Icp - Icn + 4*Icc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } + const Tfloat veloc_max = _veloc_max.max(); + if (veloc_max<=0) return *this; + return ((velocity*=amplitude/veloc_max)+=*this).cut(val_min,val_max).move_to(*this); + } + + //! Sharpen image \newinstance. + CImg get_sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) const { + return (+*this).sharpen(amplitude,sharpen_type,edge,alpha,sigma); + } + + //! Return image gradient. + /** + \param axes Axes considered for the gradient computation, as a C-string (e.g "xy"). + \param scheme = Numerical scheme used for the gradient computation: + - -1 = Backward finite differences + - 0 = Centered finite differences (default) + - 1 = Forward finite differences + - 2 = Using Sobel kernels + - 3 = Using rotation invariant kernels + - 4 = Using Deriche recursive filter. + - 5 = Using Van Vliet recursive filter. + **/ + CImgList get_gradient(const char *const axes=0, const int scheme=0) const { + CImgList res; + char __axes[4] = { 0 }; + const char *_axes = axes?axes:__axes; + if (!axes) { + unsigned int k = 0; + if (_width>1) __axes[k++] = 'x'; + if (_height>1) __axes[k++] = 'y'; + if (_depth>1) __axes[k++] = 'z'; + } + + CImg grad; + while (*_axes) { + const char axis = cimg::lowercase(*(_axes++)); + if (axis!='x' && axis!='y' && axis!='z') + throw CImgArgumentException(_cimg_instance + "get_gradient(): Invalid specified axes '%s'.", + cimg_instance, + axes); + const longT off = axis=='x'?1:axis=='y'?_width:_width*_height; + if ((axis=='x' && _width==1) || (axis=='y' && _height==1) || (axis=='z' && _depth==1)) { + grad.assign(_width,_height,_depth,_spectrum,0).move_to(res); + continue; + } + + const int _scheme = axis=='z' && (scheme==2 || scheme==3)?0:scheme; + switch (_scheme) { + case -1 : { // Backward finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && !x) || (axis=='y' && !y) || (axis=='z' && !z)) + grad[pos] = 0; + else + grad[pos] = (Tfloat)_data[pos] - _data[pos - off]; + } + grad.move_to(res); + } break; + case 1 : { // Forward finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && x==width() - 1) || (axis=='y' && y==height() - 1) || (axis=='z' && z==depth() - 1)) + grad[pos] = 0; + else + grad[pos] = (Tfloat)_data[pos + off] - _data[pos]; + } + grad.move_to(res); + } break; + case 2 : { // Sobel scheme + grad.assign(_width,_height,_depth,_spectrum); + if (axis=='x') // X-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = - Ipp + Inp - 2*Ipc + 2*Inc - Ipn + Inn; + } + else // Y-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = - Ipp - 2*Icp - Inp + Ipn + 2*Icn + Inn; + } + grad.move_to(res); + } break; + case 3 : { // Rotation invariant scheme + const Tfloat a = (Tfloat)(0.25f*(2 - std::sqrt(2.f))), b = (Tfloat)(0.5f*(std::sqrt(2.f) - 1)); + grad.assign(_width,_height,_depth,_spectrum); + if (axis=='x') // X-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn; + } + else // Y-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn; + } + grad.move_to(res); + } break; + case 4 : // Deriche filter + get_deriche(0,1,axis).move_to(res); + break; + case 5 : // Van Vliet filter + get_vanvliet(0,1,axis).move_to(res); + break; + default : { // Central finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && !x) || (axis=='y' && !y) || (axis=='z' && !z)) + grad[pos] = ((Tfloat)_data[pos + off] - _data[pos])/2; + else if ((axis=='x' && x==width() - 1) || (axis=='y' && y==height() - 1) || (axis=='z' && z==depth() - 1)) + grad[pos] = ((Tfloat)_data[pos] - _data[pos - off])/2; + else + grad[pos] = ((Tfloat)_data[pos + off] - _data[pos - off])/2; + } + grad.move_to(res); + } break; + } + } + return res; + } + + //! Return image hessian. + /** + \param axes Axes considered for the hessian computation, as a C-string (e.g "xy"). + **/ + CImgList get_hessian(const char *const axes=0) const { + CImgList res; + char __axes[12] = { 0 }; + const char *_axes = axes?axes:__axes; + if (!axes) { + unsigned int k = 0; + if (_width>1) { __axes[k++] = 'x'; __axes[k++] = 'x'; } + if (_width>1 && _height>1) { __axes[k++] = 'x'; __axes[k++] = 'y'; } + if (_width>1 && _depth>1) { __axes[k++] = 'x'; __axes[k++] = 'z'; } + if (_height>1) { __axes[k++] = 'y'; __axes[k++] = 'y'; } + if (_height>1 && _depth>1) { __axes[k++] = 'y'; __axes[k++] = 'z'; } + if (_depth>1) { __axes[k++] = 'z'; __axes[k++] = 'z'; } + } + const unsigned int len = (unsigned int)std::strlen(_axes); + if (len%2) + throw CImgArgumentException(_cimg_instance + "get_hessian(): Invalid specified axes '%s'.", + cimg_instance, + axes); + CImg hess; + for (unsigned int k = 0; k=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Inn + Ipp - Inp - Ipn)/4; + } + else if (axis1=='x' && axis2=='z') // Ixz + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*16384 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Incn + Ipcp - Incp - Ipcn)/4; + } + else // Iyz + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*16384 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Icnn + Icpp - Icnp - Icpn)/4; + } + hess.move_to(res); + } + return res; + } + + //! Compute image Laplacian. + CImg& laplacian() { + return get_laplacian().move_to(*this); + } + + //! Compute image Laplacian \newinstance. + CImg get_laplacian() const { + if (is_empty()) return CImg(); + CImg res(_width,_height,_depth,_spectrum); + if (_depth>1) { // 3D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Incc + Ipcc + Icnc + Icpc + Iccn + Iccp - 6*Iccc; + } + } else if (_height>1) { // 2D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc + Icn + Icp - 4*Icc; + } + } else { // 1D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*1048576 && + _height*_depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc - 2*Icc; + } + } + return res; + } + + //! Compute the structure tensor field of an image. + /** + \param is_fwbw_scheme scheme. Can be { false=centered | true=forward-backward } + **/ + CImg& structure_tensors(const bool is_fwbw_scheme=false) { + return get_structure_tensors(is_fwbw_scheme).move_to(*this); + } + + //! Compute the structure tensor field of an image \newinstance. + CImg get_structure_tensors(const bool is_fwbw_scheme=false) const { + if (is_empty()) return *this; + CImg res; + if (_depth>1) { // 3D + res.assign(_width,_height,_depth,6,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ix = (Incc - Ipcc)/2, + iy = (Icnc - Icpc)/2, + iz = (Iccn - Iccp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=ix*iz; + *(ptrd3++)+=iy*iy; + *(ptrd4++)+=iy*iz; + *(ptrd5++)+=iz*iz; + } + } + } else { // Forward/backward finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixf = Incc - Iccc, ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, iyb = Iccc - Icpc, + izf = Iccn - Iccc, izb = Iccc - Iccp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4; + *(ptrd3++)+=(iyf*iyf + iyb*iyb)/2; + *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4; + *(ptrd5++)+=(izf*izf + izb*izb)/2; + } + } + } + } else { // 2D + res.assign(_width,_height,_depth,3,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ix = (Inc - Ipc)/2, + iy = (Icn - Icp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=iy*iy; + } + } + } else { // Forward/backward finite differences (version 2) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ixf = Inc - Icc, ixb = Icc - Ipc, + iyf = Icn - Icc, iyb = Icc - Icp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2; + } + } + } + } + return res; + } + + //! Compute field of diffusion tensors for edge-preserving smoothing. + /** + \param sharpness Sharpness + \param anisotropy Anisotropy + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param is_sqrt Tells if the square root of the tensor field is computed instead. + **/ + CImg& diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) { + CImg res; + const float + nsharpness = std::max(sharpness,1e-5f), + power1 = (is_sqrt?0.5f:1)*nsharpness, + power2 = power1/(1e-7f + 1 - anisotropy); + blur(alpha).normalize(0,(T)255); + + if (_depth>1) { // 3D + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth>=(cimg_openmp_sizefactor)*256)) + cimg_forYZ(*this,y,z) { + Tfloat + *ptrd0 = res.data(0,y,z,0), *ptrd1 = res.data(0,y,z,1), *ptrd2 = res.data(0,y,z,2), + *ptrd3 = res.data(0,y,z,3), *ptrd4 = res.data(0,y,z,4), *ptrd5 = res.data(0,y,z,5); + CImg val(3), vec(3,3); + cimg_forX(*this,x) { + res.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + const float + _l1 = val[2], _l2 = val[1], _l3 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, l3 = _l3>0?_l3:0, + ux = vec(0,0), uy = vec(0,1), uz = vec(0,2), + vx = vec(1,0), vy = vec(1,1), vz = vec(1,2), + wx = vec(2,0), wy = vec(2,1), wz = vec(2,2), + n1 = (float)std::pow(1 + l1 + l2 + l3,-power1), + n2 = (float)std::pow(1 + l1 + l2 + l3,-power2); + *(ptrd0++) = n1*(ux*ux + vx*vx) + n2*wx*wx; + *(ptrd1++) = n1*(ux*uy + vx*vy) + n2*wx*wy; + *(ptrd2++) = n1*(ux*uz + vx*vz) + n2*wx*wz; + *(ptrd3++) = n1*(uy*uy + vy*vy) + n2*wy*wy; + *(ptrd4++) = n1*(uy*uz + vy*vz) + n2*wy*wz; + *(ptrd5++) = n1*(uz*uz + vz*vz) + n2*wz*wz; + } + } + } else { // for 2D images + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height>=(cimg_openmp_sizefactor)*256)) + cimg_forY(*this,y) { + Tfloat *ptrd0 = res.data(0,y,0,0), *ptrd1 = res.data(0,y,0,1), *ptrd2 = res.data(0,y,0,2); + CImg val(2), vec(2,2); + cimg_forX(*this,x) { + res.get_tensor_at(x,y).symmetric_eigen(val,vec); + const float + _l1 = val[1], _l2 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, + ux = vec(1,0), uy = vec(1,1), + vx = vec(0,0), vy = vec(0,1), + n1 = (float)std::pow(1 + l1 + l2,-power1), + n2 = (float)std::pow(1 + l1 + l2,-power2); + *(ptrd0++) = n1*ux*ux + n2*vx*vx; + *(ptrd1++) = n1*ux*uy + n2*vx*vy; + *(ptrd2++) = n1*uy*uy + n2*vy*vy; + } + } + } + return res.move_to(*this); + } + + //! Compute field of diffusion tensors for edge-preserving smoothing \newinstance. + CImg get_diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) const { + return CImg(*this,false).diffusion_tensors(sharpness,anisotropy,alpha,sigma,is_sqrt); + } + + //! Estimate displacement field between two images. + /** + \param source Reference image. + \param smoothness Smoothness of estimated displacement field. + \param precision Precision required for algorithm convergence. + \param nb_scales Number of scales used to estimate the displacement field. + \param iteration_max Maximum number of iterations allowed for one scale. + \param is_backward If false, match I2(X + U(X)) = I1(X), else match I2(X) = I1(X - U(X)). + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + **/ + CImg& displacement(const CImg& source, const float smoothness=0.1f, const float precision=5.f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) { + return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward,guide). + move_to(*this); + } + + //! Estimate displacement field between two images \newinstance. + CImg get_displacement(const CImg& source, + const float smoothness=0.1f, const float precision=5.f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) const { + if (is_empty() || !source) return +*this; + if (!is_sameXYZC(source)) + throw CImgArgumentException(_cimg_instance + "displacement(): Instance and source image (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + source._width,source._height,source._depth,source._spectrum,source._data); + if (precision<0) + throw CImgArgumentException(_cimg_instance + "displacement(): Invalid specified precision %g " + "(should be >=0)", + cimg_instance, + precision); + + const bool is_3d = source._depth>1; + const unsigned int constraint = is_3d?3:2; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum0?nb_scales: + (unsigned int)cimg::round(std::log(mins/8.)/std::log(1.5),1,1); + + const float _precision = (float)std::pow(10.,-(double)precision); + float sm, sM = source.max_min(sm), tm, tM = max_min(tm); + const float sdelta = sm==sM?1:(sM - sm), tdelta = tm==tM?1:(tM - tm); + + CImg U, V; + floatT bound = 0; + for (int scale = (int)_nb_scales - 1; scale>=0; --scale) { + const float factor = (float)std::pow(1.5,(double)scale); + const unsigned int + _sw = (unsigned int)(_width/factor), sw = _sw?_sw:1, + _sh = (unsigned int)(_height/factor), sh = _sh?_sh:1, + _sd = (unsigned int)(_depth/factor), sd = _sd?_sd:1; + if (sw<5 && sh<5 && (!is_3d || sd<5)) continue; // Skip too small scales + const CImg + I1 = (source.get_resize(sw,sh,sd,-100,2)-=sm)/=sdelta, + I2 = (get_resize(I1,2)-=tm)/=tdelta; + if (guide._spectrum>constraint) guide.get_resize(I2._width,I2._height,I2._depth,-100,1).move_to(V); + if (U) (U*=1.5f).resize(I2._width,I2._height,I2._depth,-100,3); + else { + if (guide) + guide.get_shared_channels(0,is_3d?2:1).get_resize(I2._width,I2._height,I2._depth,-100,2).move_to(U); + else U.assign(I2._width,I2._height,I2._depth,is_3d?3:2,0); + } + + float dt = 2, energy = cimg::type::max(); + const CImgList dI = is_backward?I1.get_gradient():I2.get_gradient(); + cimg_abort_init; + + for (unsigned int iteration = 0; iteration=0) // Isotropic regularization + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height*_depth>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,_x,_y,_z) if (V(_x,_y,_z,3)) { // Apply constraints + U(_x,_y,_z,0) = V(_x,_y,_z,0)/factor; + U(_x,_y,_z,1) = V(_x,_y,_z,1)/factor; + U(_x,_y,_z,2) = V(_x,_y,_z,2)/factor; + } + } else { // Anisotropic regularization + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height*_depth>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,_x,_y,_z) if (V(_x,_y,_z,3)) { // Apply constraints + U(_x,_y,_z,0) = V(_x,_y,_z,0)/factor; + U(_x,_y,_z,1) = V(_x,_y,_z,1)/factor; + U(_x,_y,_z,2) = V(_x,_y,_z,2)/factor; + } + } + } + } else { // 2D version + if (smoothness>=0) // Isotropic regularization + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXY(V,_x,_y) if (V(_x,_y,2)) { // Apply constraints + U(_x,_y,0) = V(_x,_y,0)/factor; + U(_x,_y,1) = V(_x,_y,1)/factor; + } + } else { // Anisotropic regularization + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXY(V,_x,_y) if (V(_x,_y,2)) { // Apply constraints + U(_x,_y,0) = V(_x,_y,0)/factor; + U(_x,_y,1) = V(_x,_y,1)/factor; + } + } + } + } + const float d_energy = (_energy - energy)/(sw*sh*sd); + if (d_energy<=0 && -d_energy<_precision) break; + if (d_energy>0) dt*=0.5f; + energy = _energy; + } + } + return U; + } + + //! Compute correspondence map between two images, using a patch-matching algorithm. + /** + \param patch_image The image containing the reference patches to match with the instance image. + \param patch_width Width of the patch used for matching. + \param patch_height Height of the patch used for matching. + \param patch_depth Depth of the patch used for matching. + \param nb_iterations Number of patch-match iterations. + \param nb_randoms Number of randomization attempts (per pixel). + \param patch_penalization Penalization factor in score related patch occurrences. + if negative, also tells that identity result is not avoided. + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + \param[out] matching_score Returned as the image of matching scores. + **/ + template + CImg& matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + CImg &matching_score) { + return get_matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide,matching_score).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \newinstance. + template + CImg get_matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + CImg &matching_score) const { + return _matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization, + guide,true,matching_score); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg& matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5, + const float patch_penalization=0, + const CImg &guide=CImg::const_empty()) { + return get_matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg get_matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5, + const float patch_penalization=0, + const CImg &guide=CImg::const_empty()) const { + CImg matching_score; + return _matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide,false,matching_score); + } + + template + CImg _matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + const bool is_matching_score, + CImg &matching_score) const { + if (is_empty()) return CImg::const_empty(); + if (patch_image._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Instance image and specified patch image (%u,%u,%u,%u,%p) " + "have different spectrums.", + cimg_instance, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + if (patch_width>_width || patch_height>_height || patch_depth>_depth) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the instance image.", + cimg_instance,patch_width,patch_height,patch_depth); + if (patch_width>patch_image._width || patch_height>patch_image._height || patch_depth>patch_image._depth) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the patch image image (%u,%u,%u,%u,%p).", + cimg_instance,patch_width,patch_height,patch_depth, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + const unsigned int + _constraint = patch_image._depth>1?3:2, + constraint = guide._spectrum>_constraint?_constraint:0; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum<_constraint)) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified guide (%u,%u,%u,%u,%p) has invalid dimensions " + "considering instance and patch image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + + CImg a_map(_width,_height,_depth,patch_image._depth>1?3:2); + CImg is_updated(_width,_height,_depth,1,3); + CImg score(_width,_height,_depth); + CImg occ; + const float _patch_penalization = cimg::abs(patch_penalization); + const bool allow_identity = patch_penalization>=0; + if (_patch_penalization!=0) occ.assign(patch_image._width,patch_image._height,patch_image._depth,1,0); + const int + psizew = (int)patch_width, psizew1 = psizew/2, psizew2 = psizew - psizew1 - 1, + psizeh = (int)patch_height, psizeh1 = psizeh/2, psizeh2 = psizeh - psizeh1 - 1, + psized = (int)patch_depth, psized1 = psized/2, psized2 = psized - psized1 - 1; + + // Interleave image buffers to speed up patch comparison (cache-friendly). + CImg in_this = get_permute_axes("cxyz"); + in_this._width = _width*_spectrum; + in_this._height = _height; + in_this._depth = _depth; + in_this._spectrum = 1; + CImg in_patch = patch_image.get_permute_axes("cxyz"); + in_patch._width = patch_image._width*patch_image._spectrum; + in_patch._height = patch_image._height; + in_patch._depth = patch_image._depth; + in_patch._spectrum = 1; + + if (_depth>1 || patch_image._depth>1) { // 3D version + + // Initialize correspondence map. + if (guide) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(_width,64)) + cimg_forXYZ(*this,x,y,z) { // User-defined initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(_width,64)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for cimg_openmp_collapse(2)) + cimg_forXYZ(*this,x,y,z) { // Random initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } + cimg::srand(rng); + } + + // Start iteration loop. + cimg_abort_init; + for (unsigned int iter = 0; iter=(cimg_openmp_sizefactor)*64 && + iter0 && (is_updated(x - 1,y,z)&cmask)) { // Compare with left neighbor + u = a_map(x - 1,y,z,0); + v = a_map(x - 1,y,z,1); + w = a_map(x - 1,y,z,2); + if (u>=cx1 - 1 && u=cy1 && v=cz1 && w0 && (is_updated(x,y - 1,z)&cmask)) { // Compare with up neighbor + u = a_map(x,y - 1,z,0); + v = a_map(x,y - 1,z,1); + w = a_map(x,y - 1,z,2); + if (u>=cx1 && u=cy1 - 1 && v=cz1 && w0 && (is_updated(x,y,z - 1)&cmask)) { // Compare with backward neighbor + u = a_map(x,y,z - 1,0); + v = a_map(x,y,z - 1,1); + w = a_map(x,y,z - 1,2); + if (u>=cx1 && u=cy1 && v=cz1 - 1 && w=cx1 + 1 && u=cy1 && v=cz1 && w=cx1 && u=cy1 + 1 && v=cz1 && w=cx1 && u=cy1 && v=cz1 + 1 && w::inf()); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(_width,64)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_forXY(*this,x,y) { // Random initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } + cimg::srand(rng); + } + + // Start iteration loop. + cimg_abort_init; + for (unsigned int iter = 0; iter=(cimg_openmp_sizefactor)*64 && + iter0 && (is_updated(x - 1,y)&cmask)) { // Compare with left neighbor + u = a_map(x - 1,y,0); + v = a_map(x - 1,y,1); + if (u>=cx1 - 1 && u=cy1 && v0 && (is_updated(x,y - 1)&cmask)) { // Compare with up neighbor + u = a_map(x,y - 1,0); + v = a_map(x,y - 1,1); + if (u>=cx1 && u=cy1 - 1 && v=cx1 + 1 && u=cy1 && v=cx1 && u=cy1 + 1 && v& img1, const CImg& img2, const CImg& occ, + const unsigned int psizew, const unsigned int psizeh, + const unsigned int psized, const unsigned int psizec, + const int x1, const int y1, const int z1, + const int x2, const int y2, const int z2, + const int xc, const int yc, const int zc, + const float patch_penalization, + const bool allow_identity, + const float max_score) { // 3D version + if (!allow_identity && cimg::hypot((float)x1-x2,(float)y1-y2,(float)z1-z2)::inf(); + const T *p1 = img1.data(x1*psizec,y1,z1), *p2 = img2.data(x2*psizec,y2,z2); + const unsigned int psizewc = psizew*psizec; + const ulongT + offx1 = (ulongT)img1._width - psizewc, + offx2 = (ulongT)img2._width - psizewc, + offy1 = (ulongT)img1._width*img1._height - (ulongT)psizeh*img1._width, + offy2 = (ulongT)img2._width*img2._height - (ulongT)psizeh*img2._width; + float ssd = 0; + for (unsigned int k = 0; kmax_score) return max_score; + p1+=offx1; p2+=offx2; + } + p1+=offy1; p2+=offy2; + } + return patch_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + + patch_penalization*psizewc*psizeh*psized*occ(xc,yc,zc)/100); + } + + static float _matchpatch(const CImg& img1, const CImg& img2, const CImg& occ, + const unsigned int psizew, const unsigned int psizeh, const unsigned int psizec, + const int x1, const int y1, + const int x2, const int y2, + const int xc, const int yc, + const float patch_penalization, + const bool allow_identity, + const float max_score) { // 2D version + if (!allow_identity && cimg::hypot((float)x1-x2,(float)y1-y2)::inf(); + const T *p1 = img1.data(x1*psizec,y1), *p2 = img2.data(x2*psizec,y2); + const unsigned int psizewc = psizew*psizec; + const ulongT + offx1 = (ulongT)img1._width - psizewc, + offx2 = (ulongT)img2._width - psizewc; + float ssd = 0; + for (unsigned int j = 0; jmax_score) return max_score; + p1+=offx1; p2+=offx2; + } + return patch_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + + patch_penalization*psizewc*psizeh*occ(xc,yc)/100); + } + + //! Compute Euclidean distance function to a specified value. + /** + \param value Reference value. + \param metric Type of metric. Can be { 0=Chebyshev | 1=Manhattan | 2=Euclidean | 3=Squared-euclidean }. + \note + The distance transform implementation has been submitted by A. Meijster, and implements + the article 'W.H. Hesselink, A. Meijster, J.B.T.M. Roerdink, + "A general algorithm for computing distance transforms in linear time.", + In: Mathematical Morphology and its Applications to Image and Signal Processing, + J. Goutsias, L. Vincent, and D.S. Bloomberg (eds.), Kluwer, 2000, pp. 331-340.' + The submitted code has then been modified to fit CImg coding style and constraints. + **/ + CImg& distance(const T& value, const unsigned int metric=2) { + if (is_empty()) return *this; + if (cimg::type::string()!=pixel_type()) // For datatype < int + return CImg(*this,false).distance((Tint)value,metric). + cut((Tint)cimg::type::min(),(Tint)cimg::type::max()).move_to(*this); + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,(T)0:(T)std::max(0,99999999); // (avoid VC++ warning) + if (!is_value) return fill(cimg::type::max()); + switch (metric) { + case 0 : return _distance_core(_distance_sep_cdt,_distance_dist_cdt); // Chebyshev + case 1 : return _distance_core(_distance_sep_mdt,_distance_dist_mdt); // Manhattan + case 3 : return _distance_core(_distance_sep_edt,_distance_dist_edt); // Squared Euclidean + default : return _distance_core(_distance_sep_edt,_distance_dist_edt).sqrt(); // Euclidean + } + return *this; + } + + //! Compute distance to a specified value \newinstance. + CImg get_distance(const T& value, const unsigned int metric=2) const { + return CImg(*this,false).distance((Tfloat)value,metric); + } + + static longT _distance_sep_edt(const longT i, const longT u, const longT *const g) { + return (u*u - i*i + g[u] - g[i])/(2*(u - i)); + } + + static longT _distance_dist_edt(const longT x, const longT i, const longT *const g) { + return (x - i)*(x - i) + g[i]; + } + + static longT _distance_sep_mdt(const longT i, const longT u, const longT *const g) { + return (u - i<=g[u] - g[i]?999999999:(g[u] - g[i] + u + i)/2); + } + + static longT _distance_dist_mdt(const longT x, const longT i, const longT *const g) { + return (x=0) && f(t[q],s[q],g)>f(t[q],u,g)) { --q; } + if (q<0) { q = 0; s[0] = u; } + else { const longT w = 1 + sep(s[q], u, g); if (w<(longT)len) { ++q; s[q] = u; t[q] = w; }} + } + for (int u = (int)len - 1; u>=0; --u) { dt[u] = f(u,s[q],g); if (u==t[q]) --q; } // Backward scan + } + + CImg& _distance_core(longT (*const sep)(const longT, const longT, const longT *const), + longT (*const f)(const longT, const longT, const longT *const)) { + // Check for g++ 4.9.X, as OpenMP seems to crash for this particular function. I have no clues why. +#define cimg_is_gcc49x (__GNUC__==4 && __GNUC_MINOR__==9) + + const ulongT wh = (ulongT)_width*_height; +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) +#endif + cimg_forC(*this,c) { + CImg g(_width), dt(_width), s(_width), t(_width); + CImg img = get_shared_channel(c); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forYZ(*this,y,z) { // Over X-direction + cimg_forX(*this,x) g[x] = (longT)img(x,y,z,0,wh); + _distance_scan(_width,g,sep,f,s,t,dt); + cimg_forX(*this,x) img(x,y,z,0,wh) = (T)dt[x]; + } + if (_height>1) { + g.assign(_height); dt.assign(_height); s.assign(_height); t.assign(_height); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 && _width*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXZ(*this,x,z) { // Over Y-direction + cimg_forY(*this,y) g[y] = (longT)img(x,y,z,0,wh); + _distance_scan(_height,g,sep,f,s,t,dt); + cimg_forY(*this,y) img(x,y,z,0,wh) = (T)dt[y]; + } + } + if (_depth>1) { + g.assign(_depth); dt.assign(_depth); s.assign(_depth); t.assign(_depth); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 && _width*_height>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXY(*this,x,y) { // Over Z-direction + cimg_forZ(*this,z) g[z] = (longT)img(x,y,z,0,wh); + _distance_scan(_depth,g,sep,f,s,t,dt); + cimg_forZ(*this,z) img(x,y,z,0,wh) = (T)dt[z]; + } + } + } + return *this; + } + + //! Compute chamfer distance to a specified value, with a custom metric. + /** + \param value Reference value. + \param metric_mask Metric mask. + \note The algorithm code has been initially proposed by A. Meijster, and modified by D. Tschumperlé. + **/ + template + CImg& distance(const T& value, const CImg& metric_mask) { + if (is_empty()) return *this; + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,0:(T)999999999; + if (!is_value) return fill(cimg::type::max()); + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg img = get_shared_channel(c); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1024)) + cimg_forXYZ(metric_mask,dx,dy,dz) { + const t weight = metric_mask(dx,dy,dz); + if (weight) { + for (int z = dz, nz = 0; z=0; --z,--nz) { // Backward scan + for (int y = height() - 1 - dy, ny = height() - 1; y>=0; --y,--ny) { + for (int x = width() - 1 - dx, nx = width() - 1; x>=0; --x,--nx) { + const T dd = img(nx,ny,nz,0,wh) + weight; + if (dd + CImg get_distance(const T& value, const CImg& metric_mask) const { + return CImg(*this,false).distance(value,metric_mask); + } + + //! Compute distance to a specified value, according to a custom metric (use dijkstra algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + \param is_high_connectivity Tells if the algorithm uses low or high connectivity. + \param[out] return_path An image containing the nodes of the minimal path. + **/ + template + CImg& distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) { + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm) \newinstance. + template + CImg::type> + get_distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) const { + if (is_empty()) return return_path.assign(); + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_dijkstra(): image instance and metric map (%u,%u,%u,%u) " + "have incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + typedef typename cimg::superset::type td; // Type used for computing cumulative distances + CImg result(_width,_height,_depth,_spectrum), Q; + CImg is_queued(_width,_height,_depth,1); + if (return_path) return_path.assign(_width,_height,_depth,_spectrum); + + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + CImg path = return_path?return_path.get_shared_channel(c):CImg(); + unsigned int sizeQ = 0; + + // Detect initial seeds. + is_queued.fill(0); + cimg_forXYZ(img,x,y,z) if (img(x,y,z)==value) { + Q._priority_queue_insert(is_queued,sizeQ,0,x,y,z); + res(x,y,z) = 0; + if (path) path(x,y,z) = (to)0; + } + + // Start distance propagation. + while (sizeQ) { + + // Get and remove point with minimal potential from the queue. + const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3); + const td P = (td)-Q(0,0); + Q._priority_queue_remove(sizeQ); + + // Update neighbors. + td npot = 0; + if (x - 1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x - 1,y,z) + P),x - 1,y,z)) { + res(x - 1,y,z) = npot; if (path) path(x - 1,y,z) = (to)2; + } + if (x + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y - 1,z) + P),x,y - 1,z)) { + res(x,y - 1,z) = npot; if (path) path(x,y - 1,z) = (to)8; + } + if (y + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y,z - 1) + P),x,y,z - 1)) { + res(x,y,z - 1) = npot; if (path) path(x,y,z - 1) = (to)32; + } + if (z + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y - 1,z) + P)),x - 1,y - 1,z)) { + res(x - 1,y - 1,z) = npot; if (path) path(x - 1,y - 1,z) = (to)10; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x + 1,y - 1,z) + P)),x + 1,y - 1,z)) { + res(x + 1,y - 1,z) = npot; if (path) path(x + 1,y - 1,z) = (to)9; + } + if (x - 1>=0 && y + 1=0) { // Diagonal neighbors on slice z - 1 + if (x - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z - 1) + P)),x - 1,y,z - 1)) { + res(x - 1,y,z - 1) = npot; if (path) path(x - 1,y,z - 1) = (to)34; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z - 1) + P)),x,y - 1,z - 1)) { + res(x,y - 1,z - 1) = npot; if (path) path(x,y - 1,z - 1) = (to)40; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z - 1) + P)), + x - 1,y - 1,z - 1)) { + res(x - 1,y - 1,z - 1) = npot; if (path) path(x - 1,y - 1,z - 1) = (to)42; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z - 1) + P)), + x + 1,y - 1,z - 1)) { + res(x + 1,y - 1,z - 1) = npot; if (path) path(x + 1,y - 1,z - 1) = (to)41; + } + if (x - 1>=0 && y + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z + 1) + P)),x - 1,y,z + 1)) { + res(x - 1,y,z + 1) = npot; if (path) path(x - 1,y,z + 1) = (to)18; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z + 1) + P)),x,y - 1,z + 1)) { + res(x,y - 1,z + 1) = npot; if (path) path(x,y - 1,z + 1) = (to)24; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z + 1) + P)), + x - 1,y - 1,z + 1)) { + res(x - 1,y - 1,z + 1) = npot; if (path) path(x - 1,y - 1,z + 1) = (to)26; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z + 1) + P)), + x + 1,y - 1,z + 1)) { + res(x + 1,y - 1,z + 1) = npot; if (path) path(x + 1,y - 1,z + 1) = (to)25; + } + if (x - 1>=0 && y + 1 + CImg& distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) { + return get_distance_dijkstra(value,metric,is_high_connectivity).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm). \newinstance. + template + CImg get_distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) const { + CImg return_path; + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + **/ + template + CImg& distance_eikonal(const T& value, const CImg& metric) { + return get_distance_eikonal(value,metric).move_to(*this); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + template + CImg get_distance_eikonal(const T& value, const CImg& metric) const { + if (is_empty()) return *this; + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have " + "incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + CImg result(_width,_height,_depth,_spectrum,cimg::type::max()), Q; + CImg state(_width,_height,_depth); // -1=far away, 0=narrow, 1=frozen + + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2) firstprivate(Q,state)) + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + unsigned int sizeQ = 0; + state.fill(-1); + + // Detect initial seeds. + Tfloat *ptr1 = res._data; char *ptr2 = state._data; + cimg_for(img,ptr0,T) { if (*ptr0==value) { *ptr1 = 0; *ptr2 = 1; } ++ptr1; ++ptr2; } + + // Initialize seeds neighbors. + ptr2 = state._data; + cimg_forXYZ(img,x,y,z) if (*(ptr2++)==1) { + if (x - 1>=0 && state(x - 1,y,z)==-1) { + const Tfloat dist = res(x - 1,y,z) = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x - 1,y,z); + } + if (x + 1=0 && state(x,y - 1,z)==-1) { + const Tfloat dist = res(x,y - 1,z) = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y - 1,z); + } + if (y + 1=0 && state(x,y,z - 1)==-1) { + const Tfloat dist = res(x,y,z - 1) = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z - 1); + } + if (z + 1=0) { + if (x - 1>=0 && state(x - 1,y,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + if (dist=0 && state(x,y - 1,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + if (dist=0 && state(x,y,z - 1)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + if (dist& res, const Tfloat P, + const int x=0, const int y=0, const int z=0) const { + const Tfloat M = (Tfloat)cimg::type::max(); + T T1 = (T)std::min(x - 1>=0?res(x - 1,y,z):M,x + 11) { // 3D + T + T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1=0?res(x,y,z - 1):M,z + 1T2) cimg::swap(T1,T2); + if (T2>T3) cimg::swap(T2,T3); + if (T1>T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T31) { // 2D + T T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T2 + void _eik_priority_queue_insert(CImg& state, unsigned int& siz, const t value, + const unsigned int x, const unsigned int y, const unsigned int z) { + if (state(x,y,z)>0) return; + state(x,y,z) = 0; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(t)(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3)); + } + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE. + /** + \param nb_iterations Number of PDE iterations. + \param band_size Size of the narrow band. + \param time_step Time step of the PDE iterations. + **/ + CImg& distance_eikonal(const unsigned int nb_iterations, const float band_size=0, const float time_step=0.5f) { + if (is_empty()) return *this; + CImg velocity(*this,false); + for (unsigned int iteration = 0; iteration1) { // 3D + CImg_3x3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) if (band_size<=0 || cimg::abs(Iccc)0?(Incc - Iccc):(Iccc - Ipcc), + iy = gy*sgn>0?(Icnc - Iccc):(Iccc - Icpc), + iz = gz*sgn>0?(Iccn - Iccc):(Iccc - Iccp), + ng = 1e-5f + cimg::hypot(gx,gy,gz), + ngx = gx/ng, + ngy = gy/ng, + ngz = gz/ng, + veloc = sgn*(ngx*ix + ngy*iy + ngz*iz - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } else { // 2D version + CImg_3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,Tfloat) if (band_size<=0 || cimg::abs(Icc)0?(Inc - Icc):(Icc - Ipc), + iy = gy*sgn>0?(Icn - Icc):(Icc - Icp), + ng = std::max((Tfloat)1e-5,cimg::hypot(gx,gy)), + ngx = gx/ng, + ngy = gy/ng, + veloc = sgn*(ngx*ix + ngy*iy - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } + if (veloc_max>0) *this+=(velocity*=time_step/veloc_max); + } + return *this; + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE \newinstance. + CImg get_distance_eikonal(const unsigned int nb_iterations, const float band_size=0, + const float time_step=0.5f) const { + return CImg(*this,false).distance_eikonal(nb_iterations,band_size,time_step); + } + + //! Compute Haar multiscale wavelet transform. + /** + \param axis Axis considered for the transform. + \param invert Set inverse of direct transform. + \param nb_scales Number of scales used for the transform. + **/ + CImg& haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(axis,invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const { + if (is_empty() || !nb_scales) return +*this; + CImg res; + const Tfloat sqrt2 = std::sqrt(2.f); + if (nb_scales==1) { + switch (cimg::lowercase(axis)) { // Single scale transform + case 'x' : { + const unsigned int w = _width/2; + if (w) { + if ((w%2) && w!=1) + throw CImgInstanceException(_cimg_instance + "haar(): Sub-image width %u is not even.", + cimg_instance, + w); + + res.assign(_width,_height,_depth,_spectrum); + if (invert) cimg_forYZC(*this,y,z,c) { // Inverse transform along X + for (unsigned int x = 0, xw = w, x2 = 0; x& haar(const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const bool invert=false, const unsigned int nb_scales=1) const { + CImg res; + if (nb_scales==1) { // Single scale transform + if (_width>1) get_haar('x',invert,1).move_to(res); + if (_height>1) { if (res) res.haar('y',invert,1); else get_haar('y',invert,1).move_to(res); } + if (_depth>1) { if (res) res.haar('z',invert,1); else get_haar('z',invert,1).move_to(res); } + if (res) return res; + } else { // Multi-scale transform + if (invert) { // Inverse transform + res.assign(*this,false); + if (_width>1) { + if (_height>1) { + if (_depth>1) { + unsigned int w = _width, h = _height, d = _depth; + for (unsigned int s = 1; w && h && d && s1) { + unsigned int w = _width, d = _depth; + for (unsigned int s = 1; w && d && s1) { + if (_depth>1) { + unsigned int h = _height, d = _depth; + for (unsigned int s = 1; h && d && s1) { + unsigned int d = _depth; + for (unsigned int s = 1; d && s1) { + if (_height>1) { + if (_depth>1) + for (unsigned int s = 1, w = _width/2, h = _height/2, d = _depth/2; w && h && d && s1) for (unsigned int s = 1, w = _width/2, d = _depth/2; w && d && s1) { + if (_depth>1) + for (unsigned int s = 1, h = _height/2, d = _depth/2; h && d && s1) for (unsigned int s = 1, d = _depth/2; d && s get_FFT(const char axis, const bool is_inverse=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],axis,is_inverse); + return res; + } + + //! Compute n-D Fast Fourier Transform. + /* + \param is_inverse Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + CImgList get_FFT(const bool is_inverse=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],is_inverse); + return res; + } + + //! Compute 1D Fast Fourier Transform, along a specified axis. + /** + \param[in,out] real Real part of the pixel values. + \param[in,out] imag Imaginary part of the pixel values. + \param axis Axis along which the FFT is computed. + \param is_inverse Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + static void FFT(CImg& real, CImg& imag, const char axis, const bool is_inverse=false, + const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part is empty.", + pixel_type()); + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + const char _axis = cimg::lowercase(axis); + if (_axis!='x' && _axis!='y' && _axis!='z') + throw CImgArgumentException("CImgList<%s>::FFT(): Invalid specified axis '%c' for real and imaginary parts " + "(%u,%u,%u,%u) " + "(should be { x | y | z }).", + pixel_type(),axis, + real._width,real._height,real._depth,real._spectrum); + cimg::unused(nb_threads); +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus()); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) + throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u) along the X-axis.", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width*real._height*real._depth), + real._width,real._height,real._depth,real._spectrum); + double *const ptrf = (double*)data_in; + fftw_plan data_plan = + _axis=='x'?fftw_plan_many_dft(1,(int*)&real._width,real.height()*real.depth(), + data_in,0,1,real.width(), + data_in,0,1,real.width(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + _axis=='y'?fftw_plan_many_dft(1,(int*)&real._height,real.width()*real.depth(), + data_in,0,1,real.height(), + data_in,0,1,real.height(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + fftw_plan_many_dft(1,(int*)&real._depth,real.width()*real.height(), + data_in,0,1,real.depth(), + data_in,0,1,real.depth(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + CImg realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c); + switch (_axis) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(x + (ulongT)y*realc._width + (ulongT)z*realc._width*realc._height); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + break; + case 'y' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(y + (ulongT)x*realc._height + (ulongT)z*realc._width*realc._height); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + break; + default : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(z + (ulongT)x*realc._depth + (ulongT)y*realc._width*realc._depth); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + } + + fftw_execute(data_plan); + + const double a = is_inverse?1.0/(_axis=='x'?real.width():_axis=='y'?real.height():real.depth()):1.0; + switch (_axis) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(x + (ulongT)y*realc._width + (ulongT)z*realc._width*realc._height), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + break; + case 'y' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(y + (ulongT)x*realc._height + (ulongT)z*realc._width*realc._height), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + break; + default : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(z + (ulongT)x*realc._depth + (ulongT)y*realc._width*realc._depth), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + } + } + + fftw_destroy_plan(data_plan); + fftw_free(data_in); +#ifndef cimg_use_fftw3_singlethread + fftw_cleanup_threads(); +#endif + cimg::mutex(12,0); +#else + switch (_axis) { + case 'x' : { // Fourier along X, using built-in functions + const unsigned int N = real._width, N2 = N>>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the X-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forYZC(real,y,z,c) { + cimg::swap(real(i,y,z,c),real(j,y,z,c)); + cimg::swap(imag(i,y,z,c),imag(j,y,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = delta>>1; + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Y-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXZC(real,x,z,c) { + cimg::swap(real(x,i,z,c),real(x,j,z,c)); + cimg::swap(imag(x,i,z,c),imag(x,j,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Z-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXYC(real,x,y,c) { + cimg::swap(real(x,y,i,c),real(x,y,j,c)); + cimg::swap(imag(x,y,i,c),imag(x,y,j,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i& real, CImg& imag, const bool is_inverse=false, + const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImgList<%s>::FFT(): Empty specified real part.", + pixel_type()); + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + cimg::unused(nb_threads); +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus()); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) + throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u).", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width* + real._height*real._depth*real._spectrum), + real._width,real._height,real._depth,real._spectrum); + double *const ptrf = (double*)data_in; + fftw_plan data_plan = + real._depth>1?fftw_plan_dft_3d(real._depth,real._height,real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + real._height>1?fftw_plan_dft_2d(real._height,real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + fftw_plan_dft_1d(real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + CImg realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; ptrf[i2] = (double)realc[i]; ptrf[i2 + 1] = (double)imagc[i]; } + fftw_execute(data_plan); + if (is_inverse) { + const double a = 1.0/(real.width()*real.height()*real.depth()); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)(a*ptrf[i2]); imagc[i] = (T)(a*ptrf[i2 + 1]); } + } else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)ptrf[i2]; imagc[i] = (T)ptrf[i2 + 1]; } + } + fftw_destroy_plan(data_plan); + fftw_free(data_in); +#ifndef cimg_use_fftw3_singlethread + fftw_cleanup_threads(); +#endif + cimg::mutex(12,0); +#else + if (real._depth>1) FFT(real,imag,'z',is_inverse); + if (real._height>1) FFT(real,imag,'y',is_inverse); + if (real._width>1) FFT(real,imag,'x',is_inverse); +#endif + } + + //@} + //------------------------------------- + // + //! \name 3D Objects Management + //@{ + //------------------------------------- + + //! Rotate 3D object's vertices. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or second quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + CImg& rotate_object3d(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + return get_rotate_object3d(x,y,z,w,is_quaternion).move_to(*this); + } + + CImg get_rotate_object3d(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) const { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "rotate_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + return CImg::rotation_matrix(x,y,z,w,is_quaternion)**this; + } + + //! Shift 3D object's vertices. + /** + \param tx X-coordinate of the 3D displacement vector. + \param ty Y-coordinate of the 3D displacement vector. + \param tz Z-coordinate of the 3D displacement vector. + **/ + CImg& shift_object3d(const float tx, const float ty=0, const float tz=0) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + get_shared_row(0)+=tx; get_shared_row(1)+=ty; get_shared_row(2)+=tz; + return *this; + } + + //! Shift 3D object's vertices \newinstance. + CImg get_shift_object3d(const float tx, const float ty=0, const float tz=0) const { + return CImg(*this,false).shift_object3d(tx,ty,tz); + } + + //! Shift 3D object's vertices, so that it becomes centered. + /** + \note The object center is computed as its barycenter. + **/ + CImg& shift_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + xcoords-=(xm + xM)/2; ycoords-=(ym + yM)/2; zcoords-=(zm + zM)/2; + return *this; + } + + //! Shift 3D object's vertices, so that it becomes centered \newinstance. + CImg get_shift_object3d() const { + return CImg(*this,false).shift_object3d(); + } + + //! Resize 3D object. + /** + \param sx Width of the 3D object's bounding box. + \param sy Height of the 3D object's bounding box. + \param sz Depth of the 3D object's bounding box. + **/ + CImg& resize_object3d(const float sx, const float sy=-100, const float sz=-100) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + if (xm0) xcoords*=sx/(xM-xm); else xcoords*=-sx/100; } + if (ym0) ycoords*=sy/(yM-ym); else ycoords*=-sy/100; } + if (zm0) zcoords*=sz/(zM-zm); else zcoords*=-sz/100; } + return *this; + } + + //! Resize 3D object \newinstance. + CImg get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const { + return CImg(*this,false).resize_object3d(sx,sy,sz); + } + + //! Resize 3D object to unit size. + CImg resize_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + const float dx = xM - xm, dy = yM - ym, dz = zM - zm, dmax = cimg::max(dx,dy,dz); + if (dmax>0) { xcoords/=dmax; ycoords/=dmax; zcoords/=dmax; } + return *this; + } + + //! Resize 3D object to unit size \newinstance. + CImg get_resize_object3d() const { + return CImg(*this,false).resize_object3d(); + } + + //! Merge two 3D objects together. + /** + \param[in,out] primitives Primitives data of the current 3D object. + \param obj_vertices Vertices data of the additional 3D object. + \param obj_primitives Primitives data of the additional 3D object. + **/ + template + CImg& append_object3d(CImgList& primitives, const CImg& obj_vertices, + const CImgList& obj_primitives) { + if (!obj_vertices || !obj_primitives) return *this; + if (obj_vertices._height!=3 || obj_vertices._depth>1 || obj_vertices._spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Specified vertice image (%u,%u,%u,%u,%p) is not a " + "set of 3D vertices.", + cimg_instance, + obj_vertices._width,obj_vertices._height, + obj_vertices._depth,obj_vertices._spectrum,obj_vertices._data); + + if (is_empty()) { primitives.assign(obj_primitives); return assign(obj_vertices); } + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + const unsigned int P = _width; + append(obj_vertices,'x'); + const unsigned int N = primitives._width; + primitives.insert(obj_primitives); + for (unsigned int i = N; i &p = primitives[i]; + switch (p.size()) { + case 1 : p[0]+=P; break; // Point + case 5 : p[0]+=P; p[1]+=P; break; // Sphere + case 2 : case 6 : p[0]+=P; p[1]+=P; break; // Segment + case 3 : case 9 : p[0]+=P; p[1]+=P; p[2]+=P; break; // Triangle + case 4 : case 12 : p[0]+=P; p[1]+=P; p[2]+=P; p[3]+=P; break; // Rectangle + } + } + return *this; + } + + //! Texturize primitives of a 3D object. + /** + \param[in,out] primitives Primitives data of the 3D object. + \param[in,out] colors Colors data of the 3D object. + \param texture Texture image to map to 3D object. + \param coords Texture-mapping coordinates. + **/ + template + const CImg& texturize_object3d(CImgList& primitives, CImgList& colors, + const CImg& texture, const CImg& coords=CImg::const_empty()) const { + if (is_empty()) return *this; + if (_height!=3) + throw CImgInstanceException(_cimg_instance + "texturize_object3d(): image instance is not a set of 3D points.", + cimg_instance); + if (coords && (coords._width!=_width || coords._height!=2)) + throw CImgArgumentException(_cimg_instance + "texturize_object3d(): Invalid specified texture coordinates (%u,%u,%u,%u,%p).", + cimg_instance, + coords._width,coords._height,coords._depth,coords._spectrum,coords._data); + CImg _coords; + if (!coords) { // If no texture coordinates specified, do a default XY-projection + _coords.assign(_width,2); + float + xmin, xmax = (float)get_shared_row(0).max_min(xmin), + ymin, ymax = (float)get_shared_row(1).max_min(ymin), + dx = xmax>xmin?xmax-xmin:1, + dy = ymax>ymin?ymax-ymin:1; + cimg_forX(*this,p) { + _coords(p,0) = (int)(((*this)(p,0) - xmin)*texture._width/dx); + _coords(p,1) = (int)(((*this)(p,1) - ymin)*texture._height/dy); + } + } else _coords = coords; + + int texture_ind = -1; + cimglist_for(primitives,l) { + CImg &p = primitives[l]; + const unsigned int siz = p.size(); + switch (siz) { + case 1 : { // Point + const unsigned int i0 = (unsigned int)p[0]; + const int x0 = _coords(i0,0), y0 = _coords(i0,1); + texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).move_to(colors[l]); + } break; + case 2 : case 6 : { // Line + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,x0,y0,x1,y1).move_to(p); + } break; + case 3 : case 9 : { // Triangle + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,x0,y0,x1,y1,x2,y2).move_to(p); + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2], i3 = (unsigned int)p[3]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1), + x3 = _coords(i3,0), y3 = _coords(i3,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,i3,x0,y0,x1,y1,x2,y2,x3,y3).move_to(p); + } break; + } + } + return *this; + } + + //! Generate a 3D elevation of the image instance. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param[out] colors The returned list of the 3D object colors. + \param elevation The input elevation map. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + CImgList colors3d; + const CImg points3d = img.get_elevation3d(faces3d,colors3d,img.get_norm()*0.2); + CImg().display_object3d("Elevation3d",points3d,faces3d,colors3d); + \endcode + \image html ref_elevation3d.jpg + **/ + template + CImg get_elevation3d(CImgList& primitives, CImgList& colors, const CImg& elevation) const { + if (!is_sameXY(elevation) || elevation._depth>1 || elevation._spectrum>1) + throw CImgArgumentException(_cimg_instance + "get_elevation3d(): Instance and specified elevation (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + elevation._width,elevation._height,elevation._depth, + elevation._spectrum,elevation._data); + if (is_empty()) return *this; + float m, M = (float)max_min(m); + if (M==m) ++M; + colors.assign(); + const unsigned int size_x1 = _width - 1, size_y1 = _height - 1; + for (unsigned int y = 0; y1?((*this)(x,y,1) - m)*255/(M-m):r), + b = (unsigned char)(_spectrum>2?((*this)(x,y,2) - m)*255/(M-m):_spectrum>1?0:r); + CImg::vector((tc)r,(tc)g,(tc)b).move_to(colors); + } + const typename CImg::_functor2d_int func(elevation); + return elevation3d(primitives,func,0,0,_width - 1.f,_height - 1.f,_width,_height); + } + + //! Generate the 3D projection planes of the image instance. + /** + \param[out] primitives Primitives data of the returned 3D object. + \param[out] colors Colors data of the returned 3D object. + \param x0 X-coordinate of the projection point. + \param y0 Y-coordinate of the projection point. + \param z0 Z-coordinate of the projection point. + \param normalize_colors Tells if the created textures have normalized colors. + **/ + template + CImg get_projections3d(CImgList& primitives, CImgList& colors, + const unsigned int x0, const unsigned int y0, const unsigned int z0, + const bool normalize_colors=false) const { + float m = 0, M = 0, delta = 1; + if (normalize_colors) { m = (float)min_max(M); delta = 255/(m==M?1:M-m); } + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + CImg img_xy, img_xz, img_yz; + if (normalize_colors) { + ((get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1)-=m)*=delta).move_to(img_xy); + ((get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_width,_depth,1,-100,-1). + move_to(img_xz); + ((get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_height,_depth,1,-100,-1). + move_to(img_yz); + } else { + get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1).move_to(img_xy); + get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1).move_to(img_xz); + get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).resize(_height,_depth,1,-100,-1).move_to(img_yz); + } + CImg points(12,3,1,1, + 0,_width - 1,_width - 1,0, 0,_width - 1,_width - 1,0, _x0,_x0,_x0,_x0, + 0,0,_height - 1,_height - 1, _y0,_y0,_y0,_y0, 0,_height - 1,_height - 1,0, + _z0,_z0,_z0,_z0, 0,0,_depth - 1,_depth - 1, 0,0,_depth - 1,_depth - 1); + primitives.assign(); + CImg::vector(0,1,2,3,0,0,img_xy._width - 1,0,img_xy._width - 1,img_xy._height - 1,0,img_xy._height - 1). + move_to(primitives); + CImg::vector(4,5,6,7,0,0,img_xz._width - 1,0,img_xz._width - 1,img_xz._height - 1,0,img_xz._height - 1). + move_to(primitives); + CImg::vector(8,9,10,11,0,0,img_yz._width - 1,0,img_yz._width - 1,img_yz._height - 1,0,img_yz._height - 1). + move_to(primitives); + colors.assign(); + img_xy.move_to(colors); + img_xz.move_to(colors); + img_yz.move_to(colors); + return points; + } + + //! Generate a isoline of the image instance as a 3D object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3D object colors. + \param size_x The number of subdivisions along the X-axis. + \param size_y The number of subdisivions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + const CImg points3d = img.get_isoline3d(faces3d,100); + CImg().display_object3d("Isoline3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isoline3d.jpg + **/ + template + CImg get_isoline3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a scalar image.", + cimg_instance); + if (_depth>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a 2D image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100) || (size_x==width() && size_y==height())) { + const _functor2d_int func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.f,height() - 1.f,width(),height()); + } else { + const _functor2d_float func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.f,height() - 1.f,size_x,size_y); + } + return vertices; + } + + //! Compute isolines of a function, as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Elevation functor. Must have operator()(x,y) defined. + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static CImg isoline3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + CImgList vertices; + primitives.assign(); + typename CImg::_functor_isoline3d add_vertex(vertices); + typename CImg::_functor_isoline3d add_segment(primitives); + isoline3d(add_vertex,add_segment,func,isovalue,x0,y0,x1,y1,size_x,size_y); + return vertices>'x'; + } + + //! Compute isolines of a function, as a 3D object. + /** + \param[out] add_vertex : Functor with operator()(x,y,z) defined for adding new vertex. + \param[out] add_segment : Functor with operator()(i,j) defined for adding new segment. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static void isoline3d(tv& add_vertex, tf& add_segment, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x, const int size_y) { + static const unsigned int edges[16] = { 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc, + 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 }; + static const int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 }, + { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 }, + { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 }, + { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } }; + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nxm1 = nx - 1, + nym1 = ny - 1; + + if (!nxm1 || !nym1) return; + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1; + CImg indices1(nx,1,1,2,-1), indices2(nx,1,1,2); + CImg values1(nx), values2(nx); + float X = x0, Y = y0, nX = X + dx, nY = Y + dy; + int nb_vertices = 0; + + // Fill first line with values + cimg_forX(values1,x) { values1(x) = (float)func(X,Y); X+=dx; } + + // Run the marching squares algorithm + for (unsigned int yi = 0, nyi = 1; yi + static CImg isoline3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return isoline3d(primitives,func,isovalue,x0,y0,x1,y1,size_x,size_y); + } + + template + static int _isoline3d_index(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int nx) { + switch (edge) { + case 0 : return (int)indices1(x,0); + case 1 : return (int)indices1(nx,1); + case 2 : return (int)indices2(x,0); + case 3 : return (int)indices1(x,1); + } + return 0; + } + + //! Generate an isosurface of the image instance as a 3D object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3D object colors. + \param size_x Number of subdivisions along the X-axis. + \param size_y Number of subdisivions along the Y-axis. + \param size_z Number of subdisivions along the Z-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img = CImg("reference.jpg").resize(-100,-100,20); + CImgList faces3d; + const CImg points3d = img.get_isosurface3d(faces3d,100); + CImg().display_object3d("Isosurface3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isosurface3d.jpg + **/ + template + CImg get_isosurface3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100, const int size_z=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isosurface3d(): Instance is not a scalar image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100 && size_z==-100) || (size_x==width() && size_y==height() && size_z==depth())) { + const _functor3d_int func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f, + width(),height(),depth()); + } else { + const _functor3d_float func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f, + size_x,size_y,size_z); + } + return vertices; + } + + //! Compute isosurface of a function, as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static CImg isosurface3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x=32, const int size_y=32, const int size_z=32) { + CImgList vertices; + primitives.assign(); + typename CImg::_functor_isosurface3d add_vertex(vertices); + typename CImg::_functor_isosurface3d add_triangle(primitives); + isosurface3d(add_vertex,add_triangle,func,isovalue,x0,y0,z0,x1,y1,z1,size_x,size_y,size_z); + return vertices>'x'; + } + + //! Compute isosurface of a function, as a 3D object. + /** + \param[out] add_vertex : Functor with operator()(x,y,z) defined for adding new vertex. + \param[out] add_triangle : Functor with operator()(i,j) defined for adding new segment. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static void isosurface3d(tv& add_vertex, tf& add_triangle, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x, const int size_y, const int size_z) { + static const unsigned int edges[256] = { + 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, + 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, + 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, + 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, + 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, + 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, + 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, + 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, + 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, + 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, + 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, + 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, + 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, + 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 + }; + + static const int triangles[256][16] = { + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, + { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, + { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, + { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, + { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, + { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, + { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, + { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, + { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, + { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, + { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, + { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, + { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, + { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, + { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, + { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, + { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, + { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, + { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, + { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, + { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, + { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, + { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, + { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, + { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, + { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, + { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, + { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, + { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, + { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, + { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, + { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, + { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, + { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, + { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, + { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, + { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, + { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, + { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, + { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, + { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, + { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, + { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, + { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, + { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, + { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, + { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, + { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, + { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, + { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, + { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, + { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, + { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, + { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, + { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, + { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, + { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, + { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, + { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, + { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, + { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, + { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, + { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, + { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, + { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, + { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, + { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, + { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, + { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, + { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, + { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, + { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, + { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, + { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, + { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, + { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, + { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, + { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, + { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, + { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, + { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, + { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, + { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, + { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, + { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, + { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, + { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, + { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, + { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, + { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, + { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, + { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, + { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } + }; + + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + _nz = (unsigned int)(size_z>=0?size_z:cimg::round((z1-z0)*-size_z/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nz = _nz?_nz:1, + nxm1 = nx - 1, + nym1 = ny - 1, + nzm1 = nz - 1; + if (!nxm1 || !nym1 || !nzm1) return; + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1, dz = (z1 - z0)/nzm1; + CImg indices1(nx,ny,1,3,-1), indices2(indices1); + CImg values1(nx,ny), values2(nx,ny); + float X = 0, Y = 0, Z = 0, nX = 0, nY = 0, nZ = 0; + int nb_vertices = 0; + + // Fill the first plane with function values + Y = y0; + cimg_forY(values1,y) { + X = x0; + cimg_forX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=dx; } + Y+=dy; + } + + // Run Marching Cubes algorithm + Z = z0; nZ = Z + dz; + for (unsigned int zi = 0; zi + static CImg isosurface3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int dx=32, const int dy=32, const int dz=32) { + const _functor3d_expr func(expression); + return isosurface3d(primitives,func,isovalue,x0,y0,z0,x1,y1,z1,dx,dy,dz); + } + + template + static int _isosurface3d_index(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int y, + const unsigned int nx, const unsigned int ny) { + switch (edge) { + case 0 : return indices1(x,y,0); + case 1 : return indices1(nx,y,1); + case 2 : return indices1(x,ny,0); + case 3 : return indices1(x,y,1); + case 4 : return indices2(x,y,0); + case 5 : return indices2(nx,y,1); + case 6 : return indices2(x,ny,0); + case 7 : return indices2(x,y,1); + case 8 : return indices1(x,y,2); + case 9 : return indices1(nx,y,2); + case 10 : return indices1(nx,ny,2); + case 11 : return indices1(x,ny,2); + } + return 0; + } + + // Define functors for accessing image values (used in previous functions). + struct _functor2d_int { + const CImg& ref; + _functor2d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref((int)x,(int)y); + } + }; + + struct _functor2d_float { + const CImg& ref; + _functor2d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref._linear_atXY(x,y); + } + }; + + struct _functor2d_expr { + _cimg_math_parser *mp; + ~_functor2d_expr() { mp->end(); delete mp; } + _functor2d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y) const { + return (float)(*mp)(x,y,0,0); + } + }; + + struct _functor3d_int { + const CImg& ref; + _functor3d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref((int)x,(int)y,(int)z); + } + }; + + struct _functor3d_float { + const CImg& ref; + _functor3d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref._linear_atXYZ(x,y,z); + } + }; + + struct _functor3d_expr { + _cimg_math_parser *mp; + ~_functor3d_expr() { mp->end(); delete mp; } + _functor3d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z) const { + return (float)(*mp)(x,y,z,0); + } + }; + + struct _functor4d_int { + const CImg& ref; + _functor4d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref((int)x,(int)y,(int)z,c); + } + }; + + struct _functor_isoline3d { + CImgList& list; + _functor_isoline3d(CImgList& _list):list(_list) {} + template + void operator()(const t x, const t y, const t z) { CImg::vector((T)x,(T)y,(T)z).move_to(list); } + template + void operator()(const t i, const t j) { CImg::vector((T)i,(T)j).move_to(list); } + }; + + struct _functor_isosurface3d { + CImgList& list; + _functor_isosurface3d(CImgList& _list):list(_list) {} + template + void operator()(const t x, const t y, const t z) { CImg::vector((T)x,(T)y,(T)z).move_to(list); } + }; + + //! Compute 3D elevation of a function as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + **/ + template + static CImg elevation3d(CImgList& primitives, const tfunc& func, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const float + nx0 = x0=0?size_x:(nx1-nx0)*-size_x/100), + nsize_x = _nsize_x?_nsize_x:1, nsize_x1 = nsize_x - 1, + _nsize_y = (unsigned int)(size_y>=0?size_y:(ny1-ny0)*-size_y/100), + nsize_y = _nsize_y?_nsize_y:1, nsize_y1 = nsize_y - 1; + if (nsize_x<2 || nsize_y<2) + throw CImgArgumentException("CImg<%s>::elevation3d(): Invalid specified size (%d,%d).", + pixel_type(), + nsize_x,nsize_y); + + CImg vertices(nsize_x*nsize_y,3); + floatT *ptr_x = vertices.data(0,0), *ptr_y = vertices.data(0,1), *ptr_z = vertices.data(0,2); + for (unsigned int y = 0; y + static CImg elevation3d(CImgList& primitives, const char *const expression, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return elevation3d(primitives,func,x0,y0,x1,y1,size_x,size_y); + } + + //! Generate a 3D box object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the box (dimension along the X-axis). + \param size_y The height of the box (dimension along the Y-axis). + \param size_z The depth of the box (dimension along the Z-axis). + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::box3d(faces3d,10,20,30); + CImg().display_object3d("Box3d",points3d,faces3d); + \endcode + \image html ref_box3d.jpg + **/ + template + static CImg box3d(CImgList& primitives, + const float size_x=200, const float size_y=100, const float size_z=100) { + primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 0,1,5,4, 3,7,6,2, 0,4,7,3, 1,2,6,5); + return CImg(8,3,1,1, + 0.,size_x,size_x, 0., 0.,size_x,size_x, 0., + 0., 0.,size_y,size_y, 0., 0.,size_y,size_y, + 0., 0., 0., 0.,size_z,size_z,size_z,size_z); + } + + //! Generate a 3D cone. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cone basis. + \param size_z The cone's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cone3d(faces3d,50); + CImg().display_object3d("Cone3d",points3d,faces3d); + \endcode + \image html ref_cone3d.jpg + **/ + template + static CImg cone3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,size_z, + 0.,0.,0.); + for (float delta = 360.f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0).move_to(vertices); + } + const unsigned int nbr = vertices._width - 2; + for (unsigned int p = 0; p::vector(1,next,curr).move_to(primitives); + CImg::vector(0,curr,next).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D cylinder. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cylinder basis. + \param size_z The cylinder's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cylinder3d(faces3d,50); + CImg().display_object3d("Cylinder3d",points3d,faces3d); + \endcode + \image html ref_cylinder3d.jpg + **/ + template + static CImg cylinder3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,0., + 0.,0.,size_z); + for (float delta = 360.f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0.f).move_to(vertices); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),size_z).move_to(vertices); + } + const unsigned int nbr = (vertices._width - 2)/2; + for (unsigned int p = 0; p::vector(0,next,curr).move_to(primitives); + CImg::vector(1,curr + 1,next + 1).move_to(primitives); + CImg::vector(curr,next,next + 1,curr + 1).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D torus. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius1 The large radius. + \param radius2 The small radius. + \param subdivisions1 The number of angular subdivisions for the large radius. + \param subdivisions2 The number of angular subdivisions for the small radius. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::torus3d(faces3d,20,4); + CImg().display_object3d("Torus3d",points3d,faces3d); + \endcode + \image html ref_torus3d.jpg + **/ + template + static CImg torus3d(CImgList& primitives, + const float radius1=100, const float radius2=30, + const unsigned int subdivisions1=24, const unsigned int subdivisions2=12) { + primitives.assign(); + if (!subdivisions1 || !subdivisions2) return CImg(); + CImgList vertices; + for (unsigned int v = 0; v::vector(x,y,z).move_to(vertices); + } + } + for (unsigned int vv = 0; vv::vector(svv + nu,svv + uu,snv + uu,snv + nu).move_to(primitives); + } + } + return vertices>'x'; + } + + //! Generate a 3D XY-plane. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the plane (dimension along the X-axis). + \param size_y The height of the plane (dimensions along the Y-axis). + \param subdivisions_x The number of planar subdivisions along the X-axis. + \param subdivisions_y The number of planar subdivisions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::plane3d(faces3d,100,50); + CImg().display_object3d("Plane3d",points3d,faces3d); + \endcode + \image html ref_plane3d.jpg + **/ + template + static CImg plane3d(CImgList& primitives, + const float size_x=100, const float size_y=100, + const unsigned int subdivisions_x=10, const unsigned int subdivisions_y=10) { + primitives.assign(); + if (!subdivisions_x || !subdivisions_y) return CImg(); + CImgList vertices; + const unsigned int w = subdivisions_x + 1, h = subdivisions_y + 1; + const float fx = (float)size_x/w, fy = (float)size_y/h; + for (unsigned int y = 0; y::vector(fx*x,fy*y,0).move_to(vertices); + for (unsigned int y = 0; y::vector(off1,off4,off3,off2).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D sphere. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the sphere (dimension along the X-axis). + \param subdivisions The number of recursive subdivisions from an initial icosahedron. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::sphere3d(faces3d,100,4); + CImg().display_object3d("Sphere3d",points3d,faces3d); + \endcode + \image html ref_sphere3d.jpg + **/ + template + static CImg sphere3d(CImgList& primitives, + const float radius=50, const unsigned int subdivisions=3) { + + // Create initial icosahedron + primitives.assign(); + const double tmp = (1 + std::sqrt(5.f))/2, a = 1./std::sqrt(1 + tmp*tmp), b = tmp*a; + CImgList vertices(12,1,3,1,1, b,a,0., -b,a,0., -b,-a,0., b,-a,0., a,0.,b, a,0.,-b, + -a,0.,-b, -a,0.,b, 0.,b,a, 0.,-b,a, 0.,-b,-a, 0.,b,-a); + primitives.assign(20,1,3,1,1, 4,8,7, 4,7,9, 5,6,11, 5,10,6, 0,4,3, 0,3,5, 2,7,1, 2,1,6, + 8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3, + 5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2); + // edge - length/2 + float he = (float)a; + + // Recurse subdivisions + for (unsigned int i = 0; i::vector(nx0,ny0,nz0).move_to(vertices); i0 = vertices.width() - 1; } + if (i1<0) { CImg::vector(nx1,ny1,nz1).move_to(vertices); i1 = vertices.width() - 1; } + if (i2<0) { CImg::vector(nx2,ny2,nz2).move_to(vertices); i2 = vertices.width() - 1; } + primitives.remove(0); + CImg::vector(p0,i0,i1).move_to(primitives); + CImg::vector((tf)i0,(tf)p1,(tf)i2).move_to(primitives); + CImg::vector((tf)i1,(tf)i2,(tf)p2).move_to(primitives); + CImg::vector((tf)i1,(tf)i0,(tf)i2).move_to(primitives); + } + } + return (vertices>'x')*=radius; + } + + //! Generate a 3D ellipsoid. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param tensor The tensor which gives the shape and size of the ellipsoid. + \param subdivisions The number of recursive subdivisions from an initial stretched icosahedron. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg tensor = CImg::diagonal(10,7,3), + points3d = CImg::ellipsoid3d(faces3d,tensor,4); + CImg().display_object3d("Ellipsoid3d",points3d,faces3d); + \endcode + \image html ref_ellipsoid3d.jpg + **/ + template + static CImg ellipsoid3d(CImgList& primitives, + const CImg& tensor, const unsigned int subdivisions=3) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImg S, V; + tensor.symmetric_eigen(S,V); + const float orient = + (V(0,1)*V(1,2) - V(0,2)*V(1,1))*V(2,0) + + (V(0,2)*V(1,0) - V(0,0)*V(1,2))*V(2,1) + + (V(0,0)*V(1,1) - V(0,1)*V(1,0))*V(2,2); + if (orient<0) { V(2,0) = -V(2,0); V(2,1) = -V(2,1); V(2,2) = -V(2,2); } + const float l0 = S[0], l1 = S[1], l2 = S[2]; + CImg vertices = sphere3d(primitives,1.,subdivisions); + vertices.get_shared_row(0)*=l0; + vertices.get_shared_row(1)*=l1; + vertices.get_shared_row(2)*=l2; + return V*vertices; + } + + //! Convert 3D object into a CImg3d representation. + /** + \param primitives Primitives data of the 3D object. + \param colors Colors data of the 3D object. + \param opacities Opacities data of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + **/ + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + CImg& object3dtoCImg3d(const bool full_check=true) { + return get_object3dtoCImg3d(full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \newinstance. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "object3dtoCImg3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,_width,primitives._width,error_message.data()); + CImg res(1,_size_object3dtoCImg3d(primitives,colors,opacities)); + float *ptrd = res._data; + + // Put magick number. + *(ptrd++) = 'C' + 0.5f; *(ptrd++) = 'I' + 0.5f; *(ptrd++) = 'm' + 0.5f; + *(ptrd++) = 'g' + 0.5f; *(ptrd++) = '3' + 0.5f; *(ptrd++) = 'd' + 0.5f; + + // Put number of vertices and primitives. + *(ptrd++) = cimg::uint2float(_width); + *(ptrd++) = cimg::uint2float(primitives._width); + + // Put vertex data. + if (is_empty() || !primitives) return res; + const T *ptrx = data(0,0), *ptry = data(0,1), *ptrz = data(0,2); + cimg_forX(*this,p) { + *(ptrd++) = (float)*(ptrx++); + *(ptrd++) = (float)*(ptry++); + *(ptrd++) = (float)*(ptrz++); + } + + // Put primitive data. + cimglist_for(primitives,p) { + *(ptrd++) = (float)primitives[p].size(); + const tp *ptrp = primitives[p]._data; + cimg_foroff(primitives[p],i) *(ptrd++) = cimg::uint2float((unsigned int)*(ptrp++)); + } + + // Put color/texture data. + const unsigned int csiz = std::min(colors._width,primitives._width); + for (int c = 0; c<(int)csiz; ++c) { + const CImg& color = colors[c]; + const tc *ptrc = color._data; + if (color.size()==3) { *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*ptrc; } + else { + *(ptrd++) = -128.f; + int shared_ind = -1; + if (color.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImgList& opacities, float *ptrd) const { + cimglist_for(opacities,o) { + const CImg& opacity = opacities[o]; + const to *ptro = opacity._data; + if (opacity.size()==1) *(ptrd++) = (float)*ptro; + else { + *(ptrd++) = -128.f; + int shared_ind = -1; + if (opacity.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImg& opacities, float *ptrd) const { + const to *ptro = opacities._data; + cimg_foroff(opacities,o) *(ptrd++) = (float)*(ptro++); + return ptrd; + } + + template + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImgList& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + if (colors[c].is_shared()) siz+=4; + else { const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; } + } + if (colors._width + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImg& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; + } + if (colors._width + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) const { + CImgList opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) const { + CImgList colors, opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3D object into a CImg3d representation \overloading. + CImg get_object3dtoCImg3d(const bool full_check=true) const { + CImgList opacities, colors; + CImgList primitives(width(),1,1,1,1); + cimglist_for(primitives,p) primitives(p,0) = p; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert CImg3d representation into a 3D object. + /** + \param[out] primitives Primitives data of the 3D object. + \param[out] colors Colors data of the 3D object. + \param[out] opacities Opacities data of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + **/ + template + CImg& CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) { + return get_CImg3dtoobject3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert CImg3d representation into a 3D object \newinstance. + template + CImg get_CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_CImg3d(full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "CImg3dtoobject3d(): image instance is not a CImg3d (%s).", + cimg_instance,error_message.data()); + const T *ptrs = _data + 6; + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + const CImg points = CImg(ptrs,3,nb_points,1,1,true).get_transpose(); + ptrs+=3*nb_points; + primitives.assign(nb_primitives); + cimglist_for(primitives,p) { + const unsigned int nb_inds = (unsigned int)*(ptrs++); + primitives[p].assign(1,nb_inds); + tp *ptrp = primitives[p]._data; + for (unsigned int i = 0; i::max(),(T)cimg::type::max()); \ + const float _sc_nopacity = cimg::abs((float)opacity), _sc_copacity = 1 - std::max((float)opacity,0.f); \ + const ulongT _sc_whd = (ulongT)_width*_height*_depth; \ + cimg::unused(_sc_maxval); + +#define cimg_draw_scanline(x0,x1,y,color,opacity,brightness) \ + _draw_scanline(x0,x1,y,color,opacity,brightness,_sc_nopacity,_sc_copacity,_sc_whd,_sc_maxval) + + // [internal] The following _draw_scanline() routines are *non user-friendly functions*, + // used only for internal purpose. + // Pre-requisites: x0<=x1, y-coordinate is valid, col is valid. + template + CImg& _draw_scanline(const int x0, const int x1, const int y, + const tc *const color, const float opacity, + const float brightness, + const float nopacity, const float copacity, const ulongT whd, const T _sc_maxval) { + const int nx0 = x0>0?x0:0, nx1 = x1=0) { + const tc *col = color; + const ulongT off = whd - dx - 1; + T *ptrd = data(nx0,y); + if (opacity>=1) { // ** Opaque drawing ** + if (brightness==1) { // Brightness==1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)*(col++); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)*(col++); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else if (brightness<1) { // Brightness<1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else { // Brightness>1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*_sc_maxval); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*_sc_maxval); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } + } else { // ** Transparent drawing ** + if (brightness==1) { // Brightness==1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else if (brightness<=1) { // Brightness<1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*brightness*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else { // Brightness>1 + cimg_forC(*this,c) { + const Tfloat val = ((2-brightness)**(col++) + (brightness - 1)*_sc_maxval)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } + } + } + return *this; + } + + //! Draw a 3D point. + /** + \param x0 X-coordinate of the point. + \param y0 Y-coordinate of the point. + \param z0 Z-coordinate of the point. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - To set pixel values without clipping needs, you should use the faster CImg::operator()() function. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_point(50,50,color); + \endcode + **/ + template + CImg& draw_point(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_point(): Specified color is (null).", + cimg_instance); + if (x0>=0 && y0>=0 && z0>=0 && x0=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } + } + return *this; + } + + //! Draw a 2D point \simplification. + template + CImg& draw_point(const int x0, const int y0, + const tc *const color, const float opacity=1) { + return draw_point(x0,y0,0,color,opacity); + } + + // Draw a points cloud. + /** + \param points Image of vertices coordinates. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_point(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_point(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),color,opacity); + } break; + default : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),(int)points(i,2),color,opacity); + } + } + return *this; + } + + //! Draw a 2D line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + \note + - Line routine uses Bresenham's algorithm. + - Set \p init_hatch = false to draw consecutive hatched segments without breaking the line pattern. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,color); + \endcode + **/ + template + CImg& draw_line(int x0, int y0, + int x1, int y1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !opacity || !pattern || + std::min(y0,y1)>=height() || std::max(y0,y1)<0 || + std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1); + dx01*=-1; dy01*=-1; + } + + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + const int + step = y0<=y1?1:-1,hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + T *const ptrd = is_horizontal?data(y,x):data(x,y); + cimg_forC(*this,c) { + const T val = color[c]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a 2D line, with z-buffering. + /** + \param zbuffer Zbuffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + **/ + template + CImg& draw_line(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_line(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float diz01 = iz1 - iz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1); + dx01*=-1; dy01*=-1; diz01*=-1; + } + + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float iz = iz0 + diz01*yy0/dy01; + tz *const ptrz = is_horizontal?zbuffer.data(y,x):zbuffer.data(x,y); + + if (x>=0 && x<=w1 && pattern&hatch && iz>=*ptrz) { + *ptrz = (tz)iz; + T *const ptrd = is_horizontal?data(y,x):data(x,y); + cimg_forC(*this,c) { + const T val = color[c]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + \note + - Line routine uses the well known Bresenham's algorithm. + \par Example: + \code + CImg img(100,100,1,3,0), texture("texture256x256.ppm"); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,texture,0,0,255,255); + \endcode + **/ + template + CImg& draw_line(int x0, int y0, + int x1, int y1, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + + if (is_empty() || !opacity || !pattern) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_line(x0,y0,x1,y1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + int + dtx01 = tx1 - tx0, dty01 = ty1 - ty0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1); + dx01*=-1; dy01*=-1; dtx01*=-1; dty01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy01ty = dy01*cimg::sign(dty01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01, + tx = tx0 + (dtx01*yy0 + hdy01tx)/dy01, + ty = ty0 + (dty01*yy0 + hdy01ty)/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line, with perspective correction. + /** + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(int x0, int y0, const float z0, + int x1, int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float + diz01 = iz1 - iz0, + txz0 = tx0*iz0, txz1 = tx1*iz1, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, + dtxz01 = txz1 - txz0, dtyz01 = tyz1 - tyz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1,txz0,txz1,tyz0,tyz1); + dx01*=-1; dy01*=-1; diz01*=-1; dtxz01*=-1; dtyz01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float + iz = iz0 + diz01*yy0/dy01, + txz = txz0 + dtxz01*yy0/dy01, + tyz = tyz0 + dtyz01*yy0/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line, with perspective correction and z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float + diz01 = iz1 - iz0, + txz0 = tx0*iz0, txz1 = tx1*iz1, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, + dtxz01 = txz1 - txz0, dtyz01 = tyz1 - tyz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1,txz0,txz1,tyz0,tyz1); + dx01*=-1; dy01*=-1; diz01*=-1; dtxz01*=-1; dtyz01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float + iz = iz0 + diz01*yy0/dy01, + txz = txz0 + dtxz01*yy0/dy01, + tyz = tyz0 + dtyz01*yy0/dy01; + tz *const ptrz = is_horizontal?zbuffer.data(y,x):zbuffer.data(x,y); + + if (x>=0 && x<=w1 && pattern&hatch && iz>=*ptrz) { + *ptrz = (tz)iz; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a set of consecutive lines. + /** + \param points Coordinates of vertices, stored as a list of vectors. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If set to true, init hatch motif. + \note + - This function uses several call to the single CImg::draw_line() procedure, + depending on the vectors size in \p points. + **/ + template + CImg& draw_line(const CImg& points, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + default : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + int ox = x0, oy = y0; + for (unsigned int i = 1; i + CImg& draw_arrow(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1, + const float angle=30, const float length=-10, + const unsigned int pattern=~0U) { + if (is_empty()) return *this; + const float u = (float)(x0 - x1), v = (float)(y0 - y1), sq = u*u + v*v, + deg = (float)(angle*cimg::PI/180), ang = (sq>0)?(float)std::atan2(v,u):0.f, + l = (length>=0)?length:-length*(float)std::sqrt(sq)/100; + if (sq>0) { + const float + cl = (float)std::cos(ang - deg), sl = (float)std::sin(ang - deg), + cr = (float)std::cos(ang + deg), sr = (float)std::sin(ang + deg); + const int + xl = x1 + (int)(l*cl), yl = y1 + (int)(l*sl), + xr = x1 + (int)(l*cr), yr = y1 + (int)(l*sr), + xc = x1 + (int)((l + 1)*(cl + cr))/2, yc = y1 + (int)((l + 1)*(sl + sr))/2; + draw_line(x0,y0,xc,yc,color,opacity,pattern).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity); + } else draw_point(x0,y0,color,opacity); + return *this; + } + + //! Draw a 2D spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + \note + - The curve is a 2D cubic Bezier spline, from the set of specified starting/ending points + and corresponding velocity vectors. + - The spline is drawn as a sequence of connected segments. The \p precision parameter sets the + average number of pixels in each drawn segment. + - A cubic Bezier curve is sometimes defined by a set of 4 points { (\p x0,\p y0), (\p xa,\p ya), + (\p xb,\p yb), (\p x1,\p y1) } where (\p x0,\p y0) is the starting point, (\p x1,\p y1) is the ending point + and (\p xa,\p ya), (\p xb,\p yb) are two + \e control points. + The starting and ending velocities (\p u0,\p v0) and (\p u1,\p v1) can be deduced easily from + the control points as + \p u0 = (\p xa - \p x0), \p v0 = (\p ya - \p y0), \p u1 = (\p x1 - \p xb) and \p v1 = (\p y1 - \p yb). + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,255,255 }; + img.draw_spline(30,30,0,100,90,40,0,-100,color); + \endcode + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const tc *const color, const float opacity=1, + const float precision=0.25, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Specified color is (null).", + cimg_instance); + if (x0==x1 && y0==y1) return draw_point(x0,y0,color,opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0; + for (float t = 0; t<1; t+=_precision) { + const float t2 = t*t, t3 = t2*t; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), + ny = (int)(ay*t3 + by*t2 + v0*t + y0); + draw_line(ox,oy,nx,ny,color,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; + } + return draw_line(ox,oy,x1,y1,color,opacity,pattern,false); + } + + //! Draw a textured 2D spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param texture Texture image defining line pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch if \c true, reinit hatch motif. + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const CImg& texture, + const int tx0, const int ty0, const int tx1, const int ty1, + const float opacity=1, + const float precision=4, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_empty()) return *this; + if (is_overlapped(texture)) + return draw_spline(x0,y0,u0,v0,x1,y1,u1,v1,+texture,tx0,ty0,tx1,ty1,precision,opacity,pattern,init_hatch); + if (x0==x1 && y0==y1) + return draw_point(x0,y0,texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).data(), + opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0, otx = tx0, oty = ty0; + for (float t1 = 0; t1<1; t1+=_precision) { + const float t2 = t1*t1, t3 = t2*t1; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t1 + x0), + ny = (int)(ay*t3 + by*t2 + v0*t1 + y0), + ntx = tx0 + (int)((tx1 - tx0)*t1), + nty = ty0 + (int)((ty1 - ty0)*t1); + draw_line(ox,oy,nx,ny,texture,otx,oty,ntx,nty,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; otx = ntx; oty = nty; + } + return draw_line(ox,oy,x1,y1,texture,otx,oty,tx1,ty1,opacity,pattern,false); + } + + //! Draw a set of consecutive splines. + /** + \param points Vertices data. + \param tangents Tangents data. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param is_closed_set Tells if the drawn spline set is closed. + \param precision Precision of the drawing. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + **/ + template + CImg& draw_spline(const CImg& points, const CImg& tangents, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || !tangents || points._width<2 || tangents._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + default : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1); + int ox = x0, oy = y0; + float ou = u0, ov = v0; + for (unsigned int i = 1; i + CImg& draw_spline(const CImg& points, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + CImg tangents; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + tangents.assign(points._width,points._height); + cimg_forX(points,p) { + const unsigned int + p0 = is_closed_set?(p + points.width() - 1)%points.width():(p?p - 1:0), + p1 = is_closed_set?(p + 1)%points.width():(p + 1 + CImg& _draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, const float opacity, + const float brightness) { + if (y0>y1) cimg::swap(x0,x1,y0,y1); + if (y0>y2) cimg::swap(x0,x2,y0,y2); + if (y1>y2) cimg::swap(x1,x2,y1,y2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM); + cimg_draw_scanline(xm,xM,y,color,opacity,cbs); + } + return *this; + } + + //! Draw a filled 2D triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + _draw_triangle(x0,y0,x1,y1,x2,y2,color,opacity,1); + return *this; + } + + //! Draw a outlined 2D triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + draw_line(x0,y0,x1,y1,color,opacity,pattern,true). + draw_line(x1,y1,x2,y2,color,opacity,pattern,false). + draw_line(x2,y2,x0,y0,color,opacity,pattern,false); + return *this; + } + + //! Draw a filled 2D triangle, with z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param z0 Z-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param z1 Z-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param z2 Z-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param brightness Brightness factor. + **/ + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1; + + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param bs0 Brightness factor of the first vertex (in [0,2]). + \param bs1 brightness factor of the second vertex (in [0,2]). + \param bs2 brightness factor of the third vertex (in [0,2]). + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2D triangle, with z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, + float bs0, + float bs1, + float bs2, + float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a color-interpolated 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color1 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the first vertex. + \param color2 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the second vertex. + \param color3 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc1 *const color1, + const tc2 *const color2, + const tc3 *const color3, + const float opacity=1) { + const unsigned char one = 1; + cimg_forC(*this,c) + get_shared_channel(c).draw_triangle(x0,y0,x1,y1,x2,y2,&one,color1[c],color2[c],color3[c],opacity); + return *this; + } + + //! Draw a textured 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param opacity Drawing opacity. + \param brightness Brightness factor of the drawing (in [0,2]). + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,ty1,tx2,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2; + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM; + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a 2D textured triangle, with perspective correction. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured 2D triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a Phong-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + + const ulongT lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,lxm,lxM,lym,lyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dlxmM = lxM - lxm, dlymM = lyM - lym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a Phong-shaded 2D triangle, with z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (is_overlapped(light)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + const float diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1; + + const ulongT lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,lxm,lxM,lym,lyM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dlxmM = lxM - lxm, dlymM = lyM - lym; + const float dizmM = izM - izm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const int + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const tc col = color[c]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param bs0 Brightness factor of the first vertex. + \param bs1 Brightness factor of the second vertex. + \param bs2 Brightness factor of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + bs0,bs1,bs2,opacity); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2; + const float dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym; + const float dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle, with perspective correction \overloading. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + bs0,bs1,bs2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle, with perspective correction and z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,bs0,bs1,bs2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM,lxm,lxM,lym,lyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym, + dlxmM = lxM - lxm, dlymM = lyM - lym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM, + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle, with perspective correction. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2, + lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2, + dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1, + dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float + dizmM = izM - izm, + dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, + dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + lxz = lxzm + dlxzmM*xxm/dxmM, + lyz = lyzm + dlyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz), + lx = (int)cimg::round(lxz/iz), + ly = (int)cimg::round(lyz/iz); + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + +texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2, + lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2, + dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1, + dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float + dizmM = izM - izm, + dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, + dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + lxz = lxzm + dlxzmM*xxm/dxmM, + lyz = lyzm + dlyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz), + lx = (int)cimg::round(lxz/iz), + ly = (int)cimg::round(lyz/iz); + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a filled 4D rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param z0 Z-coordinate of the upper-left rectangle corner. + \param c0 C-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param z1 Z-coordinate of the lower-right rectangle corner. + \param c1 C-coordinate of the lower-right rectangle corner. + \param val Scalar value used to fill the rectangle area. + \param opacity Drawing opacity. + **/ + CImg& draw_rectangle(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const T val, const float opacity=1) { + if (is_empty()) return *this; + const int + nx0 = x0=width()?width() - 1 - nx1:0) + (nx0<0?nx0:0), + ly = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0), + lz = (1 + nz1 - nz0) + (nz1>=depth()?depth() - 1 - nz1:0) + (nz0<0?nz0:0), + lc = (1 + nc1 - nc0) + (nc1>=spectrum()?spectrum() - 1 - nc1:0) + (nc0<0?nc0:0); + const ulongT + offX = (ulongT)_width - lx, + offY = (ulongT)_width*(_height - ly), + offZ = (ulongT)_width*_height*(_depth - lz); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + T *ptrd = data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0); + if (lx>0 && ly>0 && lz>0 && lc>0) + for (int v = 0; v=1) { + if (sizeof(T)!=1) { for (int x = 0; x + CImg& draw_rectangle(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_rectangle(): Specified color is (null).", + cimg_instance); + cimg_forC(*this,c) draw_rectangle(x0,y0,z0,c,x1,y1,z1,c,(T)color[c],opacity); + return *this; + } + + //! Draw a filled 2D rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1) { + return draw_rectangle(x0,y0,0,x1,y1,_depth - 1,color,opacity); + } + + //! Draw a outlined 2D rectangle \overloading. + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (y0==y1) return draw_line(x0,y0,x1,y0,color,opacity,pattern,true); + if (x0==x1) return draw_line(x0,y0,x0,y1,color,opacity,pattern,true); + const int + nx0 = x0 + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points.height()!=2) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set (%u,%u,%u,%u).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum); + if (points._width==1) return draw_point(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)),color,opacity); + if (points._width==2) return draw_line(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)), + cimg::uiround(points(1,0)),cimg::uiround(points(1,1)),color,opacity); + if (points._width==3) return draw_triangle(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)), + cimg::uiround(points(1,0)),cimg::uiround(points(1,1)), + cimg::uiround(points(2,0)),cimg::uiround(points(2,1)),color,opacity); + cimg_init_scanline(opacity); + int + xmin = 0, ymin = 0, + xmax = points.get_shared_row(0).max_min(xmin), + ymax = points.get_shared_row(1).max_min(ymin); + if (xmax<0 || xmin>=width() || ymax<0 || ymin>=height()) return *this; + if (ymin==ymax) return draw_line(xmin,ymin,xmax,ymax,color,opacity); + + ymin = std::max(0,ymin); + ymax = std::min(height() - 1,ymax); + CImg Xs(points._width,ymax - ymin + 1); + CImg count(Xs._height,1,1,1,0); + unsigned int n = 0, nn = 1; + bool go_on = true; + + while (go_on) { + unsigned int an = (nn + 1)%points._width; + const int + x0 = cimg::uiround(points(n,0)), + y0 = cimg::uiround(points(n,1)); + if (points(nn,1)==y0) while (points(an,1)==y0) { nn = an; (an+=1)%=points._width; } + const int + x1 = cimg::uiround(points(nn,0)), + y1 = cimg::uiround(points(nn,1)); + unsigned int tn = an; + while (points(tn,1)==y1) (tn+=1)%=points._width; + + if (y0!=y1) { + const int + y2 = cimg::uiround(points(tn,1)), + x01 = x1 - x0, y01 = y1 - y0, y12 = y2 - y1, + step = cimg::sign(y01), + tmax = std::max(1,cimg::abs(y01)), htmax = tmax*cimg::sign(x01)/2, + tend = tmax - (step==cimg::sign(y12)); + unsigned int y = (unsigned int)y0 - ymin; + for (int t = 0; t<=tend; ++t, y+=step) + if (yn; + n = nn; + nn = an; + } + + cimg_pragma_openmp(parallel for cimg_openmp_if(Xs._height>=(cimg_openmp_sizefactor)*512)) + cimg_forY(Xs,y) { + const CImg Xsy = Xs.get_shared_points(0,count[y] - 1,y).sort(); + int px = width(); + for (unsigned int k = 0; k + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity, const unsigned int pattern) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points._width==1) return draw_point((int)points(0,0),(int)points(0,1),color,opacity); + if (points._width==2) return draw_line((int)points(0,0),(int)points(0,1), + (int)points(1,0),(int)points(1,1),color,opacity,pattern); + bool ninit_hatch = true; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set (%u,%u,%u,%u).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum); + default : { + CImg npoints(points._width,2); + int x = npoints(0,0) = (int)points(0,0), y = npoints(0,1) = (int)points(0,1); + unsigned int nb_points = 1; + for (unsigned int p = 1; p + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity=1) { + return _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,0U,true); + } + + //! Draw a filled 2D ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity=1) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity); + } + + //! Draw an outlined 2D ellipse. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param r1 First radius of the ellipse. + \param r2 Second radius of the ellipse. + \param angle Angle of the first radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity, const unsigned int pattern) { + if (pattern) _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,pattern,false); + return *this; + } + + //! Draw an outlined 2D ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity, + const unsigned int pattern) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity,pattern); + } + + template + CImg& _draw_ellipse(const int x0, const int y0, const float radius1, const float radius2, const float angle, + const tc *const color, const float opacity, + const unsigned int pattern, const bool is_filled) { + if (is_empty() || (!is_filled && !pattern)) return *this; + const float radiusM = std::max(radius1,radius2); + if (radius1<0 || radius2<0 || x0 - radiusM>=width() || y0 + radiusM<0 || y0 - radiusM>=height()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_ellipse(): Specified color is (null).", + cimg_instance); + const int iradius1 = (int)cimg::round(radius1), iradius2 = (int)cimg::round(radius2); + if (!iradius1 && !iradius2) return draw_point(x0,y0,color,opacity); + if (iradius1==iradius2) { + if (is_filled) return draw_circle(x0,y0,iradius1,color,opacity); + else if (pattern==~0U) return draw_circle(x0,y0,iradius1,color,opacity,pattern); + } + const float ang = (float)(angle*cimg::PI/180); + + if (!is_filled) { // Outlined + const float ca = std::cos(ang), sa = std::sin(ang); + CImg points((unsigned int)cimg::round(6*radiusM),2); + cimg_forX(points,k) { + const float + _ang = (float)(2*cimg::PI*k/points._width), + X = (float)(radius1*std::cos(_ang)), + Y = (float)(radius2*std::sin(_ang)); + points(k,0) = (int)cimg::round(x0 + (X*ca - Y*sa)); + points(k,1) = (int)cimg::round(y0 + (X*sa + Y*ca)); + } + draw_polygon(points,color,opacity,pattern); + } else { // Filled + cimg_init_scanline(opacity); + const float + ca = std::cos(ang), + sa = -std::sin(ang), + ca2 = ca*ca, + sa2 = sa*sa, + casa = ca*sa, + i1 = 1/cimg::sqr(radius1), + i2 = 1/cimg::sqr(radius2), + t1 = i1*ca2 + i2*sa2, + t2 = (i2 - i1)*casa, + t3 = i2*ca2 + i1*sa2, + t12 = t1*2; + const int + _ymin = (int)std::floor(y0 - radiusM), + _ymax = (int)std::ceil(y0 + radiusM), + ymin = _ymin<0?0:_ymin, + ymax = _ymax>=height()?height() - 1:_ymax; + for (int y = ymin; y<=ymax; ++y) { + const float + Y = y - y0 + 0.5f, + B = 2*t2*Y, + C = t3*Y*Y - 1, + D = B*B - 4*t1*C; + if (D>=0) { + const float sD = std::sqrt(D); + const int + xmin = (int)(x0 + cimg::round((-B - sD)/t12)), + xmax = (int)(x0 + cimg::round((-B + sD)/t12)); + cimg_draw_scanline(xmin,xmax,y,color,opacity,1); + } + } + } + return *this; + } + + //! Draw a filled 2D circle. + /** + \param x0 X-coordinate of the circle center. + \param y0 Y-coordinate of the circle center. + \param radius Circle radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - Circle version of the Bresenham's algorithm is used. + **/ + template + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (!radius) return draw_point(x0,y0,color,opacity); + cimg_init_scanline(opacity); + if (y0>=0 && y0=0) { + const int x1 = x0 - x, x2 = x0 + x, y1 = y0 - y, y2 = y0 + y; + if (y1>=0 && y1=0 && y2=0 && y1=0 && y2 + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (pattern!=~0U) return draw_ellipse(x0,y0,radius,radius,0,color,opacity,pattern); + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!radius) return draw_point(x0,y0,color,opacity); + + draw_point(x0 - radius,y0,color,opacity).draw_point(x0 + radius,y0,color,opacity). + draw_point(x0,y0 - radius,color,opacity).draw_point(x0,y0 + radius,color,opacity); + if (radius==1) return *this; + for (int f = 1 - radius, ddFx = 0, ddFy = -(radius<<1), x = 0, y = radius; x=0) { f+=(ddFy+=2); --y; } + ++x; ++(f+=(ddFx+=2)); + if (x!=y + 1) { + const int x1 = x0 - y, x2 = x0 + y, y1 = y0 - x, y2 = y0 + x, + x3 = x0 - x, x4 = x0 + x, y3 = y0 - y, y4 = y0 + y; + draw_point(x1,y1,color,opacity).draw_point(x1,y2,color,opacity). + draw_point(x2,y1,color,opacity).draw_point(x2,y2,color,opacity); + if (x!=y) + draw_point(x3,y3,color,opacity).draw_point(x4,y4,color,opacity). + draw_point(x4,y3,color,opacity).draw_point(x3,y4,color,opacity); + } + } + return *this; + } + + //! Draw an image. + /** + \param sprite Sprite image. + \param x0 X-coordinate of the sprite position. + \param y0 Y-coordinate of the sprite position. + \param z0 Z-coordinate of the sprite position. + \param c0 C-coordinate of the sprite position. + \param opacity Drawing opacity. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c=1) for (int x = 0; x& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + const ulongT slx = lx*sizeof(T); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c=1) std::memcpy(ptrd,ptrs,slx); + else for (int x = 0; x + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,z0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const CImg& sprite, const float opacity=1) { + return draw_image(0,sprite,opacity); + } + + //! Draw a masked image. + /** + \param sprite Sprite image. + \param mask Mask image. + \param x0 X-coordinate of the sprite position in the image instance. + \param y0 Y-coordinate of the sprite position in the image instance. + \param z0 Z-coordinate of the sprite position in the image instance. + \param c0 C-coordinate of the sprite position in the image instance. + \param mask_max_value Maximum pixel value of the mask image \c mask. + \param opacity Drawing opacity. + \note + - Pixel values of \c mask set the opacity of the corresponding pixels in \c sprite. + - Dimensions along x,y and z of \p sprite and \p mask must be the same. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + if (is_empty() || !sprite || !mask) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,mask,opacity,mask_max_value); + if (is_overlapped(mask)) return draw_image(x0,y0,z0,c0,sprite,+mask,opacity,mask_max_value); + if (mask._width!=sprite._width || mask._height!=sprite._height || mask._depth!=sprite._depth) + throw CImgArgumentException(_cimg_instance + "draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + sprite._width,sprite._height,sprite._depth,sprite._spectrum,sprite._data, + mask._width,mask._height,mask._depth,mask._spectrum,mask._data); + + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + const ulongT msize = mask.size(); + + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,z0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw an image. + template + CImg& draw_image(const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a text string. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Pointer to \c spectrum() consecutive values, defining the foreground drawing color. + \param background_color Pointer to \c spectrum() consecutive values, defining the background drawing color. + \param opacity Drawing opacity. + \param font Font used for drawing text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent background is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,(tc*)0,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent foreground is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,(tc*)0,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Array of spectrum() values of type \c T, + defining the foreground color (0 means 'transparent'). + \param background_color Array of spectrum() values of type \c T, + defining the background color (0 means 'transparent'). + \param opacity Drawing opacity. + \param font_height Height of the text font (exact match for 13,23,53,103, interpolated otherwise). + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + const CImgList& font = CImgList::font(font_height,true); + _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,true); + return *this; + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int background_color=0, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + cimg::unused(background_color); + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",foreground_color,(const tc*)0,opacity,font_height,tmp._data); + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",(tc*)0,background_color,opacity,font_height,tmp._data); + } + + template + CImg& _draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, + const bool is_native_font) { + if (!text) return *this; + if (!font) + throw CImgArgumentException(_cimg_instance + "draw_text(): Empty specified font.", + cimg_instance); + + const unsigned int text_length = (unsigned int)std::strlen(text); + const int padding_x = font[0]._height<48?1:font[0]._height<128?(int)std::ceil(font[0]._height/51.0f + 0.745f):4; + unsigned char o_ch, ch = 0; + int x, y, w; + CImg left_paddings(text_length,1,1,1,0); + const CImg empty = CImg::empty(); + + if (is_empty() || is_native_font) { + // Pre-compute necessary size of the image as well as left paddings of each character. + x = y = w = 0; + o_ch = 0; + for (unsigned int i = 0; iw) w = x; x = 0; break; + case '\t' : x+=4*font[(int)' ']._width; break; + case ' ' : x+=font[(int)' ']._width; break; + default : if (ch'9')) || o_ch==';' || o_ch==':' || o_ch=='!') + left_padding = 4*padding_x; + else if (((o_ch=='i' || o_ch=='l' || o_ch=='I' || o_ch=='J' || o_ch=='M' || o_ch=='N') && + ((ch>='0' && ch<='9') || + (ch>='a' && ch<='z' && ch!='v' && ch!='x' && ch!='y') || + (ch>='B' && ch<='Z' && ch!='J' && ch!='T' && ch!='V' && ch!='X' && ch!='Y'))) || + o_ch=='.' || o_ch=='\'' || ch=='\'') + left_padding = padding_x; + else if ((o_ch<'0' || o_ch>'9') && ch!='-') { + const CImg &mask = ch + 256U' ' && o_ch>' ' && mask._height>13) { + const CImg &o_mask = o_ch + 256U13) { + const int w1 = mask.width()>0?o_mask.width() - 1:0, w2 = w1>1?w1 - 1:0, w3 = w2>1?w2 - 1:0; + left_padding = -10; + cimg_forY(mask,k) { + const int + lpad = o_mask(w1,k)>=8?0: + o_mask._width<=2 || o_mask(w2,k)>=8?-1: + o_mask._width<=3 || o_mask(w3,k)>=8?-2:-3, + rpad = mask(0,k)>=8?0: + mask._width<=2 || mask(1,k)>=8?-1: + mask._width<=3 || mask(2,k)>=8?-2:-3; + left_padding = std::max(left_padding,lpad + rpad); + } + } + } + } + left_paddings[i] = left_padding; + } + x+=left_padding + font[ch]._width + padding_x; + o_ch = ch; + } + } + } + if (x!=0 || ch=='\n') { if (x>w) w = x; y+=font[0]._height; } + if (is_empty()) assign(x0 + w,y0 + y,1,is_native_font?1:font[0]._spectrum,(T)0); + } + + // Draw font characters on image. + x = x0; y = y0; + for (unsigned int i = 0; i letter = font[ch]; + if (letter) { + const CImg &mask = ch + 256Uletter._spectrum) + letter.assign(letter.get_resize(-100,-100,1,_spectrum,0,2),false); + const unsigned int cmin = std::min(_spectrum,letter._spectrum); + if (foreground_color) + for (unsigned int c = 0; c& __draw_text(const char *const text, unsigned int &font_size, const int is_down, ...) { + CImg tmp(2048); + std::va_list ap; + va_start(ap,is_down); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + CImg a_label, a_labelmask; + const unsigned char a_labelcolor = 255; + unsigned int ofs = font_size, fs = ofs; + do { // Determine best font size + a_label.assign().draw_text(0,0,"%s",&a_labelcolor,0,1,fs,tmp._data); + if (a_label._width<7*_width/10 && a_label._height>_height/20 && a_label._height<_height/5) { + font_size = fs; break; + } else if ((a_label._width>7*_width/10 || a_label._height>_height/5) && fs>13 && ofs>=fs) { + ofs = fs; fs = std::max(13U,(unsigned int)cimg::round(fs/1.25f)); + } else if (a_label._width<3*_width/10 && a_label._height<_height/20 && fs<64 && ofs<=fs) { + ofs = fs; fs = std::min(64U,(unsigned int)cimg::round(fs*1.25f)); + } else { font_size = fs; break; } + } while (true); + a_label.normalize(0,255); + a_label+=(255 - a_label.get_dilate(3)).normalize(0,80); + a_label.resize(-100,-100,1,3,1); + return draw_image(0,is_down?height() - a_label.height():0,a_label,0.85f); + } + + //! Draw a 2D vector field. + /** + \param flow Image of 2D vectors used as input data. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const t2 *const color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + return draw_quiver(flow,CImg(color,_spectrum,1,1,1,true),opacity,sampling,factor,is_arrow,pattern); + } + + //! Draw a 2D vector field, using a field of colors. + /** + \param flow Image of 2D vectors used as input data. + \param color Image of spectrum()-D vectors corresponding to the color of each arrow. + \param opacity Opacity of the drawing. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const CImg& color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + if (is_empty()) return *this; + if (!flow || flow._spectrum!=2) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).", + cimg_instance, + flow._width,flow._height,flow._depth,flow._spectrum,flow._data); + if (sampling<=0) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid sampling value %g " + "(should be >0)", + cimg_instance, + sampling); + const bool colorfield = (color._width==flow._width && color._height==flow._height && + color._depth==1 && color._spectrum==_spectrum); + if (is_overlapped(flow)) return draw_quiver(+flow,color,opacity,sampling,factor,is_arrow,pattern); + float vmax,fact; + if (factor<=0) { + float m, M = (float)flow.get_norm(2).max_min(m); + vmax = (float)std::max(cimg::abs(m),cimg::abs(M)); + if (!vmax) vmax = 1; + fact = -factor; + } else { fact = factor; vmax = 1; } + + for (unsigned int y = sampling/2; y<_height; y+=sampling) + for (unsigned int x = sampling/2; x<_width; x+=sampling) { + const unsigned int X = x*flow._width/_width, Y = y*flow._height/_height; + float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax; + if (is_arrow) { + const int xx = (int)(x + u), yy = (int)(y + v); + if (colorfield) draw_arrow(x,y,xx,yy,color.get_vector_at(X,Y)._data,opacity,45,sampling/5.f,pattern); + else draw_arrow(x,y,xx,yy,color._data,opacity,45,sampling/5.f,pattern); + } else { + if (colorfield) + draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color.get_vector_at(X,Y)._data,opacity,pattern); + else draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color._data,opacity,pattern); + } + } + return *this; + } + + //! Draw a labeled horizontal axis. + /** + \param values_x Values along the horizontal axis. + \param y Y-coordinate of the horizontal axis in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const CImg& values_x, const int y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true, const float round_x=0) { + if (is_empty()) return *this; + const int yt = (y + 3 + font_height)<_height?y + 3:y - 2 - (int)font_height; + const int siz = (int)values_x.size() - 1; + CImg txt(32); + CImg a_label; + if (siz<=0) { // Degenerated case + draw_line(0,y,_width - 1,y,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",round_x?cimg::round((double)*values_x,round_x):(double)*values_x); + a_label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _xt = (width() - a_label.width())/2, + xt = _xt<3?3:_xt + a_label.width()>=width() - 2?width() - 3 - a_label.width():_xt; + draw_point(width()/2,y - 1,color,opacity).draw_point(width()/2,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case + if (values_x[0]=width() - 2?width() - 3 - a_label.width():_xt; + draw_point(xi,y - 1,color,opacity).draw_point(xi,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw a labeled vertical axis. + /** + \param x X-coordinate of the vertical axis in the image instance. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const int x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true, const float round_y=0) { + if (is_empty()) return *this; + int siz = (int)values_y.size() - 1; + CImg txt(32); + CImg a_label; + if (siz<=0) { // Degenerated case + draw_line(x,0,x,_height - 1,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",round_y?cimg::round((double)*values_y,round_y):(double)*values_y); + a_label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _yt = (height() - a_label.height())/2, + yt = _yt<0?0:_yt + a_label.height()>=height()?height() - 1 - a_label.height():_yt, + _xt = x - 2 - a_label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,height()/2,color,opacity).draw_point(x + 1,height()/2,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case + if (values_y[0]=height()?height() - 1 - a_label.height():_yt, + _xt = x - 2 - a_label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,yi,color,opacity).draw_point(x + 1,yi,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes. + /** + \param values_x Values along the X-axis. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for the X-axis. + \param pattern_y Drawing pattern for the Y-axis. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axes(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13, const bool allow_zero=true, + const float round_x=0, const float round_y=0) { + if (is_empty()) return *this; + const CImg nvalues_x(values_x._data,values_x.size(),1,1,1,true); + const int sizx = (int)values_x.size() - 1, wm1 = width() - 1; + if (sizx>=0) { + float ox = (float)*nvalues_x; + for (unsigned int x = sizx?1U:0U; x<_width; ++x) { + const float nx = (float)nvalues_x._linear_atX((float)x*sizx/wm1); + if (nx*ox<=0) { + draw_axis(nx==0?x:x - 1,values_y,color,opacity,pattern_y,font_height,allow_zero,round_y); + break; + } + ox = nx; + } + } + const CImg nvalues_y(values_y._data,values_y.size(),1,1,1,true); + const int sizy = (int)values_y.size() - 1, hm1 = height() - 1; + if (sizy>0) { + float oy = (float)nvalues_y[0]; + for (unsigned int y = sizy?1U:0U; y<_height; ++y) { + const float ny = (float)nvalues_y._linear_atX((float)y*sizy/hm1); + if (ny*oy<=0) { + draw_axis(values_x,ny==0?y:y - 1,color,opacity,pattern_x,font_height,allow_zero,round_x); + break; + } + oy = ny; + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes \overloading. + template + CImg& draw_axes(const float x0, const float x1, const float y0, const float y1, + const tc *const color, const float opacity=1, + const int subdivisionx=-60, const int subdivisiony=-60, + const float precisionx=0, const float precisiony=0, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13) { + if (is_empty()) return *this; + const bool allow_zero = (x0*x1>0) || (y0*y1>0); + const float + dx = cimg::abs(x1 - x0), dy = cimg::abs(y1 - y0), + px = dx<=0?1:precisionx==0?(float)std::pow(10.,(int)std::log10(dx) - 2.):precisionx, + py = dy<=0?1:precisiony==0?(float)std::pow(10.,(int)std::log10(dy) - 2.):precisiony; + if (x0!=x1 && y0!=y1) + draw_axes(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1), + CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1), + color,opacity,pattern_x,pattern_y,font_height,allow_zero,px,py); + else if (x0==x1 && y0!=y1) + draw_axis((int)x0,CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1), + color,opacity,pattern_y,font_height,py); + else if (x0!=x1 && y0==y1) + draw_axis(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1),(int)y0, + color,opacity,pattern_x,font_height,px); + return *this; + } + + //! Draw 2D grid. + /** + \param values_x X-coordinates of the vertical lines. + \param values_y Y-coordinates of the horizontal lines. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for vertical lines. + \param pattern_y Drawing pattern for horizontal lines. + **/ + template + CImg& draw_grid(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + if (values_x) cimg_foroff(values_x,x) { + const int xi = (int)values_x[x]; + if (xi>=0 && xi=0 && yi + CImg& draw_grid(const float delta_x, const float delta_y, + const float offsetx, const float offsety, + const bool invertx, const bool inverty, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + CImg seqx, seqy; + if (delta_x!=0) { + const float dx = delta_x>0?delta_x:_width*-delta_x/100; + const unsigned int nx = (unsigned int)(_width/dx); + seqx = CImg::sequence(1 + nx,0,(unsigned int)(dx*nx)); + if (offsetx) cimg_foroff(seqx,x) seqx(x) = (unsigned int)cimg::mod(seqx(x) + offsetx,(float)_width); + if (invertx) cimg_foroff(seqx,x) seqx(x) = _width - 1 - seqx(x); + } + if (delta_y!=0) { + const float dy = delta_y>0?delta_y:_height*-delta_y/100; + const unsigned int ny = (unsigned int)(_height/dy); + seqy = CImg::sequence(1 + ny,0,(unsigned int)(dy*ny)); + if (offsety) cimg_foroff(seqy,y) seqy(y) = (unsigned int)cimg::mod(seqy(y) + offsety,(float)_height); + if (inverty) cimg_foroff(seqy,y) seqy(y) = _height - 1 - seqy(y); + } + return draw_grid(seqx,seqy,color,opacity,pattern_x,pattern_y); + } + + //! Draw 1D graph. + /** + \param data Image containing the graph values I = f(x). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + + \param plot_type Define the type of the plot: + - 0 = No plot. + - 1 = Plot using segments. + - 2 = Plot using cubic splines. + - 3 = Plot with bars. + \param vertex_type Define the type of points: + - 0 = No points. + - 1 = Point. + - 2 = Straight cross. + - 3 = Diagonal cross. + - 4 = Filled circle. + - 5 = Outlined circle. + - 6 = Square. + - 7 = Diamond. + \param ymin Lower bound of the y-range. + \param ymax Upper bound of the y-range. + \param pattern Drawing pattern. + \note + - if \c ymin==ymax==0, the y-range is computed automatically from the input samples. + **/ + template + CImg& draw_graph(const CImg& data, + const tc *const color, const float opacity=1, + const unsigned int plot_type=1, const int vertex_type=1, + const double ymin=0, const double ymax=0, const unsigned int pattern=~0U) { + if (is_empty() || _height<=1) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_graph(): Specified color is (null).", + cimg_instance); + + // Create shaded colors for displaying bar plots. + CImg color1, color2; + if (plot_type==3) { + color1.assign(_spectrum); color2.assign(_spectrum); + cimg_forC(*this,c) { + color1[c] = (tc)std::min((float)cimg::type::max(),(float)color[c]*1.2f); + color2[c] = (tc)(color[c]*0.4f); + } + } + + // Compute min/max and normalization factors. + const ulongT + siz = data.size(), + _siz1 = siz - (plot_type!=3), + siz1 = _siz1?_siz1:1; + const unsigned int + _width1 = _width - (plot_type!=3), + width1 = _width1?_width1:1; + double m = ymin, M = ymax; + if (ymin==ymax) m = (double)data.max_min(M); + if (m==M) { --m; ++M; } + const float ca = (float)(M-m)/(_height - 1); + bool init_hatch = true; + + // Draw graph edges + switch (plot_type%4) { + case 1 : { // Segments + int oX = 0, oY = (int)cimg::round((data[0] - m)/ca); + if (siz==1) { + const int Y = (int)cimg::round((*data - m)/ca); + draw_line(0,Y,width() - 1,Y,color,opacity,pattern); + } else { + const float fx = (float)_width/siz1; + for (ulongT off = 1; off ndata(data._data,siz,1,1,1,true); + int oY = (int)cimg::round((data[0] - m)/ca); + cimg_forX(*this,x) { + const int Y = (int)cimg::round((ndata._cubic_atX((float)x*siz1/width1)-m)/ca); + if (x>0) draw_line(x,oY,x + 1,Y,color,opacity,pattern,init_hatch); + init_hatch = false; + oY = Y; + } + } break; + case 3 : { // Bars + const int Y0 = (int)cimg::round(-m/ca); + const float fx = (float)_width/siz1; + int oX = 0; + cimg_foroff(data,off) { + const int + X = (int)cimg::round((off + 1)*fx) - 1, + Y = (int)cimg::round((data[off] - m)/ca); + draw_rectangle(oX,Y0,X,Y,color,opacity). + draw_line(oX,Y,oX,Y0,color2.data(),opacity). + draw_line(oX,Y0,X,Y0,Y<=Y0?color2.data():color1.data(),opacity). + draw_line(X,Y,X,Y0,color1.data(),opacity). + draw_line(oX,Y,X,Y,Y<=Y0?color1.data():color2.data(),opacity); + oX = X + 1; + } + } break; + default : break; // No edges + } + + // Draw graph points + const unsigned int wb2 = plot_type==3?_width1/(2*siz):0; + const float fx = (float)_width1/siz1; + switch (vertex_type%8) { + case 1 : { // Point + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_point(X,Y,color,opacity); + } + } break; + case 2 : { // Straight Cross + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X - 3,Y,X + 3,Y,color,opacity).draw_line(X,Y - 3,X,Y + 3,color,opacity); + } + } break; + case 3 : { // Diagonal Cross + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X - 3,Y - 3,X + 3,Y + 3,color,opacity).draw_line(X - 3,Y + 3,X + 3,Y - 3,color,opacity); + } + } break; + case 4 : { // Filled Circle + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity); + } + } break; + case 5 : { // Outlined circle + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity,~0U); + } + } break; + case 6 : { // Square + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_rectangle(X - 3,Y - 3,X + 3,Y + 3,color,opacity,~0U); + } + } break; + case 7 : { // Diamond + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X,Y - 4,X + 4,Y,color,opacity). + draw_line(X + 4,Y,X,Y + 4,color,opacity). + draw_line(X,Y + 4,X - 4,Y,color,opacity). + draw_line(X - 4,Y,X,Y - 4,color,opacity); + } + } break; + default : break; // No points + } + return *this; + } + + bool _draw_fill(const int x, const int y, const int z, + const CImg& ref, const float tolerance2) const { + const T *ptr1 = data(x,y,z), *ptr2 = ref._data; + const ulongT off = _width*_height*_depth; + float diff = 0; + cimg_forC(*this,c) { diff += cimg::sqr(*ptr1 - *(ptr2++)); ptr1+=off; } + return diff<=tolerance2; + } + + //! Draw filled 3D region with the flood fill algorithm. + /** + \param x0 X-coordinate of the starting point of the region to fill. + \param y0 Y-coordinate of the starting point of the region to fill. + \param z0 Z-coordinate of the starting point of the region to fill. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param[out] region Image that will contain the mask of the filled region mask, as an output. + \param tolerance Tolerance concerning neighborhood values. + \param opacity Opacity of the drawing. + \param is_high_connectivity Tells if 8-connexity must be used. + \return \c region is initialized with the binary mask of the filled region. + **/ + template + CImg& draw_fill(const int x0, const int y0, const int z0, + const tc *const color, const float opacity, + CImg ®ion, + const float tolerance = 0, + const bool is_high_connectivity = false) { +#define _draw_fill_push(x,y,z) if (N>=stack._width) stack.resize(2*N + 1,1,1,3,0); \ + stack[N] = x; stack(N,1) = y; stack(N++,2) = z +#define _draw_fill_pop(x,y,z) x = stack[--N]; y = stack(N,1); z = stack(N,2) +#define _draw_fill_is_inside(x,y,z) !_region(x,y,z) && _draw_fill(x,y,z,ref,tolerance2) + + if (!containsXYZC(x0,y0,z0,0)) return *this; + const float nopacity = cimg::abs((float)opacity), copacity = 1 - std::max((float)opacity,0.f); + const float tolerance2 = cimg::sqr(tolerance); + const CImg ref = get_vector_at(x0,y0,z0); + CImg stack(256,1,1,3); + CImg _region(_width,_height,_depth,1,0); + unsigned int N = 0; + int x, y, z; + + _draw_fill_push(x0,y0,z0); + while (N>0) { + _draw_fill_pop(x,y,z); + if (!_region(x,y,z)) { + const int yp = y - 1, yn = y + 1, zp = z - 1, zn = z + 1; + int xl = x, xr = x; + + // Using these booleans reduces the number of pushes drastically. + bool is_yp = false, is_yn = false, is_zp = false, is_zn = false; + for (int step = -1; step<2; step+=2) { + while (x>=0 && x=0 && _draw_fill_is_inside(x,yp,z)) { + if (!is_yp) { _draw_fill_push(x,yp,z); is_yp = true; } + } else is_yp = false; + if (yn1) { + if (zp>=0 && _draw_fill_is_inside(x,y,zp)) { + if (!is_zp) { _draw_fill_push(x,y,zp); is_zp = true; } + } else is_zp = false; + if (zn=0 && !is_yp) { + if (xp>=0 && _draw_fill_is_inside(xp,yp,z)) { + _draw_fill_push(xp,yp,z); if (step<0) is_yp = true; + } + if (xn0) is_yp = true; + } + } + if (yn=0 && _draw_fill_is_inside(xp,yn,z)) { + _draw_fill_push(xp,yn,z); if (step<0) is_yn = true; + } + if (xn0) is_yn = true; + } + } + if (depth()>1) { + if (zp>=0 && !is_zp) { + if (xp>=0 && _draw_fill_is_inside(xp,y,zp)) { + _draw_fill_push(xp,y,zp); if (step<0) is_zp = true; + } + if (xn0) is_zp = true; + } + + if (yp>=0 && !is_yp) { + if (_draw_fill_is_inside(x,yp,zp)) { _draw_fill_push(x,yp,zp); } + if (xp>=0 && _draw_fill_is_inside(xp,yp,zp)) { _draw_fill_push(xp,yp,zp); } + if (xn=0 && _draw_fill_is_inside(xp,yn,zp)) { _draw_fill_push(xp,yn,zp); } + if (xn=0 && _draw_fill_is_inside(xp,y,zn)) { + _draw_fill_push(xp,y,zn); if (step<0) is_zn = true; + } + if (xn0) is_zn = true; + } + + if (yp>=0 && !is_yp) { + if (_draw_fill_is_inside(x,yp,zn)) { _draw_fill_push(x,yp,zn); } + if (xp>=0 && _draw_fill_is_inside(xp,yp,zn)) { _draw_fill_push(xp,yp,zn); } + if (xn=0 && _draw_fill_is_inside(xp,yn,zn)) { _draw_fill_push(xp,yn,zn); } + if (xn + CImg& draw_fill(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1, + const float tolerance=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x0,y0,z0,color,opacity,tmp,tolerance,is_high_connexity); + } + + //! Draw filled 2D region with the flood fill algorithm \simplification. + template + CImg& draw_fill(const int x0, const int y0, + const tc *const color, const float opacity=1, + const float tolerance=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x0,y0,0,color,opacity,tmp,tolerance,is_high_connexity); + } + + //! Draw a random plasma texture. + /** + \param alpha Alpha-parameter. + \param beta Beta-parameter. + \param scale Scale-parameter. + \note Use the mid-point algorithm to render. + **/ + CImg& draw_plasma(const float alpha=1, const float beta=0, const unsigned int scale=8) { + if (is_empty()) return *this; + const int w = width(), h = height(); + const Tfloat m = (Tfloat)cimg::type::min(), M = (Tfloat)cimg::type::max(); + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + cimg_forZC(*this,z,c) { + CImg ref = get_shared_slice(z,c); + for (int delta = 1<1; delta>>=1) { + const int delta2 = delta>>1; + const float r = alpha*delta + beta; + + // Square step. + for (int y0 = 0; y0M?M:val); + } + + // Diamond steps. + for (int y = -delta2; yM?M:val); + } + for (int y0 = 0; y0M?M:val); + } + for (int y = -delta2; yM?M:val); + } + } + } + cimg::srand(rng); + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2D fractal. + /** + \param x0 X-coordinate of the upper-left pixel. + \param y0 Y-coordinate of the upper-left pixel. + \param x1 X-coordinate of the lower-right pixel. + \param y1 Y-coordinate of the lower-right pixel. + \param colormap Colormap. + \param opacity Drawing opacity. + \param z0r Real part of the upper-left fractal vertex. + \param z0i Imaginary part of the upper-left fractal vertex. + \param z1r Real part of the lower-right fractal vertex. + \param z1i Imaginary part of the lower-right fractal vertex. + \param iteration_max Maximum number of iterations for each estimated point. + \param is_normalized_iteration Tells if iterations are normalized. + \param is_julia_set Tells if the Mandelbrot or Julia set is rendered. + \param param_r Real part of the Julia set parameter. + \param param_i Imaginary part of the Julia set parameter. + \note Fractal rendering is done by the Escape Time Algorithm. + **/ + template + CImg& draw_mandelbrot(const int x0, const int y0, const int x1, const int y1, + const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + if (is_empty()) return *this; + CImg palette; + if (colormap) palette.assign(colormap._data,colormap.size()/colormap._spectrum,1,1,colormap._spectrum,true); + if (palette && palette._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_mandelbrot(): Instance and specified colormap (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f), ln2 = (float)std::log(2.); + const int + _x0 = cimg::cut(x0,0,width() - 1), + _y0 = cimg::cut(y0,0,height() - 1), + _x1 = cimg::cut(x1,0,width() - 1), + _y1 = cimg::cut(y1,0,height() - 1); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if((1 + _x1 - _x0)*(1 + _y1 - _y0)>=(cimg_openmp_sizefactor)*2048)) + for (int q = _y0; q<=_y1; ++q) + for (int p = _x0; p<=_x1; ++p) { + unsigned int iteration = 0; + const double x = z0r + p*(z1r-z0r)/_width, y = z0i + q*(z1i-z0i)/_height; + double zr, zi, cr, ci; + if (is_julia_set) { zr = x; zi = y; cr = param_r; ci = param_i; } + else { zr = param_r; zi = param_i; cr = x; ci = y; } + for (iteration=1; zr*zr + zi*zi<=4 && iteration<=iteration_max; ++iteration) { + const double temp = zr*zr - zi*zi + cr; + zi = 2*zr*zi + ci; + zr = temp; + } + if (iteration>iteration_max) { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette(0,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(0,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)0; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)((*this)(p,q,0,c)*copacity); + } + } else if (is_normalized_iteration) { + const float + normz = (float)cimg::abs(zr*zr + zi*zi), + niteration = (float)(iteration + 1 - std::log(std::log(normz))/ln2); + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._linear_atX(niteration,c); + else cimg_forC(*this,c) + (*this)(p,q,0,c) = (T)(palette._linear_atX(niteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)niteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(niteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } else { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._atX(iteration,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(iteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)iteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(iteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } + } + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2D fractal \overloading. + template + CImg& draw_mandelbrot(const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + return draw_mandelbrot(0,0,_width - 1,_height - 1,colormap,opacity, + z0r,z0i,z1r,z1i,iteration_max,is_normalized_iteration,is_julia_set,param_r,param_i); + } + + //! Draw a 1D gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param sigma Standard variation of the gaussian distribution. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float sigma, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + const float sigma2 = 2*sigma*sigma, nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forX(*this,x) { + const float dx = (x - xc), val = (float)std::exp(-dx*dx/sigma2); + T *ptrd = data(x,0,0,0); + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 2D gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param yc Y-coordinate of the gaussian center. + \param tensor Covariance matrix (must be 2x2). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float yc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (tensor._width!=2 || tensor._height!=2 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 2x2 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + typedef typename CImg::Tfloat tfloat; + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/=-2.; + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + float dy = -yc; + cimg_forY(*this,y) { + float dx = -xc; + cimg_forX(*this,x) { + const float val = (float)std::exp(a*dx*dx + b*dx*dy + c*dy*dy); + T *ptrd = data(x,y,0,0); + if (opacity>=1) cimg_forC(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + ++dx; + } + ++dy; + } + return *this; + } + + //! Draw a 2D gaussian function \overloading. + template + CImg& draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, + const tc *const color, const float opacity=1) { + const double + a = r1*ru*ru + r2*rv*rv, + b = (r1-r2)*ru*rv, + c = r1*rv*rv + r2*ru*ru; + const CImg tensor(2,2,1,1, a,b,b,c); + return draw_gaussian(xc,yc,tensor,color,opacity); + } + + //! Draw a 2D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,CImg::diagonal(sigma,sigma),color,opacity); + } + + //! Draw a 3D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + typedef typename CImg::Tfloat tfloat; + if (tensor._width!=3 || tensor._height!=3 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 3x3 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/=-2.; + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = 2*invT2(2,0), d = invT2(1,1), e = 2*invT2(2,1), f = invT2(2,2); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forXYZ(*this,x,y,z) { + const float + dx = (x - xc), dy = (y - yc), dz = (z - zc), + val = (float)std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz); + T *ptrd = data(x,y,z,0); + if (opacity>=1) cimg_forC(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 3D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,zc,CImg::diagonal(sigma,sigma,sigma),color,opacity); + } + + //! Draw a 3D object. + /** + \param x0 X-coordinate of the 3D object position + \param y0 Y-coordinate of the 3D object position + \param z0 Z-coordinate of the 3D object position + \param vertices Image Nx3 describing 3D point coordinates + \param primitives List of P primitives + \param colors List of P color (or textures) + \param opacities Image or list of P opacities + \param render_type d Render type (0=Points, 1=Lines, 2=Faces (no light), 3=Faces (flat), 4=Faces(Gouraud) + \param is_double_sided Tells if object faces have two sides or are oriented. + \param focale length of the focale (0 for parallel projection) + \param lightx X-coordinate of the light + \param lighty Y-coordinate of the light + \param lightz Z-coordinate of the light + \param specular_lightness Amount of specular light. + \param specular_shininess Shininess of the object + \param g_opacity Global opacity of the object. + **/ + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } +#endif + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } +#endif + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,zbuffer); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,zbuffer); + } +#endif + + template + static float __draw_object3d(const CImgList& opacities, const unsigned int n_primitive, CImg& opacity) { + if (n_primitive>=opacities._width || opacities[n_primitive].is_empty()) { opacity.assign(); return 1; } + if (opacities[n_primitive].size()==1) { opacity.assign(); return opacities(n_primitive,0); } + opacity.assign(opacities[n_primitive],true); + return 1.f; + } + + template + static float __draw_object3d(const CImg& opacities, const unsigned int n_primitive, CImg& opacity) { + opacity.assign(); + return n_primitive>=opacities._width?1.f:(float)opacities[n_primitive]; + } + + template + static float ___draw_object3d(const CImgList& opacities, const unsigned int n_primitive) { + return n_primitive + static float ___draw_object3d(const CImg& opacities, const unsigned int n_primitive) { + return n_primitive + CImg& _draw_object3d(void *const pboard, CImg& zbuffer, + const float X, const float Y, const float Z, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, const float sprite_scale) { + typedef typename cimg::superset2::type tpfloat; + typedef typename to::value_type _to; + if (is_empty() || !vertices || !primitives) return *this; + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,false,error_message)) + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); +#ifndef cimg_use_board + if (pboard) return *this; +#endif + if (render_type==5) cimg::mutex(10); // Static variable used in this case, breaks thread-safety + + const float + nspec = 1 - (specular_lightness<0.f?0.f:(specular_lightness>1.f?1.f:specular_lightness)), + nspec2 = 1 + (specular_shininess<0.f?0.f:specular_shininess), + nsl1 = (nspec2 - 1)/cimg::sqr(nspec - 1), + nsl2 = 1 - 2*nsl1*nspec, + nsl3 = nspec2 - nsl1 - nsl2; + + // Create light texture for phong-like rendering. + CImg light_texture; + if (render_type==5) { + if (colors._width>primitives._width) { + static CImg default_light_texture; + static const tc *lptr = 0; + static tc ref_values[64] = { 0 }; + const CImg& img = colors.back(); + bool is_same_texture = (lptr==img._data); + if (is_same_texture) + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + if (ref_values[r++]!=img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum)) { + is_same_texture = false; break; + } + if (!is_same_texture || default_light_texture._spectrum<_spectrum) { + (default_light_texture.assign(img,false)/=255).resize(-100,-100,1,_spectrum); + lptr = colors.back().data(); + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + ref_values[r++] = img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum); + } + light_texture.assign(default_light_texture,true); + } else { + static CImg default_light_texture; + static float olightx = 0, olighty = 0, olightz = 0, ospecular_shininess = 0; + if (!default_light_texture || + lightx!=olightx || lighty!=olighty || lightz!=olightz || + specular_shininess!=ospecular_shininess || default_light_texture._spectrum<_spectrum) { + default_light_texture.assign(512,512); + const float + dlx = lightx - X, + dly = lighty - Y, + dlz = lightz - Z, + nl = cimg::hypot(dlx,dly,dlz), + nlx = (default_light_texture._width - 1)/2*(1 + dlx/nl), + nly = (default_light_texture._height - 1)/2*(1 + dly/nl), + white[] = { 1 }; + default_light_texture.draw_gaussian(nlx,nly,default_light_texture._width/3.f,white); + cimg_forXY(default_light_texture,x,y) { + const float factor = default_light_texture(x,y); + if (factor>nspec) default_light_texture(x,y) = std::min(2.f,nsl1*factor*factor + nsl2*factor + nsl3); + } + default_light_texture.resize(-100,-100,1,_spectrum); + olightx = lightx; olighty = lighty; olightz = lightz; ospecular_shininess = specular_shininess; + } + light_texture.assign(default_light_texture,true); + } + } + + // Compute 3D to 2D projection. + CImg projections(vertices._width,2); + tpfloat parallzmin = cimg::type::max(); + const float absfocale = focale?cimg::abs(focale):0; + if (absfocale) { + cimg_pragma_openmp(parallel for cimg_openmp_if_size(projections.size(),4096)) + cimg_forX(projections,l) { // Perspective projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + const tpfloat projectedz = z + Z + absfocale; + projections(l,1) = Y + absfocale*y/projectedz; + projections(l,0) = X + absfocale*x/projectedz; + } + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if_size(projections.size(),4096)) + cimg_forX(projections,l) { // Parallel projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + if (z visibles(primitives._width,1,1,1,~0U); + CImg zrange(primitives._width); + const tpfloat zmin = absfocale?(tpfloat)(1.5f - absfocale):cimg::type::min(); + bool is_forward = zbuffer?true:false; + + cimg_pragma_openmp(parallel for cimg_openmp_if_size(primitives.size(),4096)) + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + switch (primitive.size()) { + case 1 : { // Point + CImg<_to> _opacity; + __draw_object3d(opacities,l,_opacity); + if (l<=colors.width() && (colors[l].size()!=_spectrum || _opacity)) is_forward = false; + const unsigned int i0 = (unsigned int)primitive(0); + const tpfloat z0 = Z + vertices(i0,2); + if (z0>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = z0; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + Xc = 0.5f*((float)vertices(i0,0) + (float)vertices(i1,0)), + Yc = 0.5f*((float)vertices(i0,1) + (float)vertices(i1,1)), + Zc = 0.5f*((float)vertices(i0,2) + (float)vertices(i1,2)), + _zc = Z + Zc, + zc = _zc + _focale, + xc = X + Xc*(absfocale?absfocale/zc:1), + yc = Y + Yc*(absfocale?absfocale/zc:1), + radius = 0.5f*cimg::hypot(vertices(i1,0) - vertices(i0,0), + vertices(i1,1) - vertices(i0,1), + vertices(i1,2) - vertices(i0,2))*(absfocale?absfocale/zc:1), + xm = xc - radius, + ym = yc - radius, + xM = xc + radius, + yM = yc + radius; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && _zc>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = _zc; + } + is_forward = false; + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2); + tpfloat xm, xM, ym, yM; + if (x0=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1)/2; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (y0yM) yM = y2; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) { + const tpfloat d = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2)/3; + } + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2), + x3 = projections(i3,0), y3 = projections(i3,1), z3 = Z + vertices(i3,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (x3xM) xM = x3; + if (y0yM) yM = y2; + if (y3yM) yM = y3; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin && z3>zmin) { + const float d = (x1 - x0)*(y2 - y0) - (x2 - x0)*(y1 - y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2 + z3)/4; + } + } + } break; + default : + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid primitive[%u] with size %u " + "(should have size 1,2,3,4,5,6,9 or 12).", + cimg_instance, + l,primitive.size()); + } + } + + // Force transparent primitives to be drawn last when zbuffer is activated + // (and if object contains no spheres or sprites). + if (is_forward) + cimglist_for(primitives,l) + if (___draw_object3d(opacities,l)!=1) zrange(l) = 2*zmax - zrange(l); + + // Sort only visibles primitives. + unsigned int *p_visibles = visibles._data; + tpfloat *p_zrange = zrange._data; + const tpfloat *ptrz = p_zrange; + cimg_for(visibles,ptr,unsigned int) { + if (*ptr!=~0U) { *(p_visibles++) = *ptr; *(p_zrange++) = *ptrz; } + ++ptrz; + } + const unsigned int nb_visibles = (unsigned int)(p_zrange - zrange._data); + if (!nb_visibles) { + if (render_type==5) cimg::mutex(10,0); + return *this; + } + CImg permutations; + CImg(zrange._data,nb_visibles,1,1,1,true).sort(permutations,is_forward); + + // Compute light properties + CImg lightprops; + switch (render_type) { + case 3 : { // Flat Shading + lightprops.assign(nb_visibles); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const CImg& primitive = primitives(visibles(permutations(l))); + const unsigned int psize = (unsigned int)primitive.size(); + if (psize==3 || psize==4 || psize==9 || psize==12) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nx = dy1*dz2 - dz1*dy2, + ny = dz1*dx2 - dx1*dz2, + nz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + (x0 + x1 + x2)/3 - lightx, + ly = Y + (y0 + y1 + y2)/3 - lighty, + lz = Z + (z0 + z1 + z2)/3 - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max(cimg::abs(-lx*nx - ly*ny - lz*nz)/(norm*nl),(tpfloat)0); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } else lightprops[l] = 1; + } + } break; + + case 4 : // Gouraud Shading + case 5 : { // Phong-Shading + CImg vertices_normals(vertices._width,6,1,1,0); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + for (int l = 0; l<(int)nb_visibles; ++l) { + const CImg& primitive = primitives[visibles(l)]; + const unsigned int psize = (unsigned int)primitive.size(); + const bool + triangle_flag = (psize==3) || (psize==9), + quadrangle_flag = (psize==4) || (psize==12); + if (triangle_flag || quadrangle_flag) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = quadrangle_flag?(unsigned int)primitive(3):0; + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nnx = dy1*dz2 - dz1*dy2, + nny = dz1*dx2 - dx1*dz2, + nnz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nnx,nny,nnz), + nx = nnx/norm, + ny = nny/norm, + nz = nnz/norm; + unsigned int ix = 0, iy = 1, iz = 2; + if (is_double_sided && nz>0) { ix = 3; iy = 4; iz = 5; } + vertices_normals(i0,ix)+=nx; vertices_normals(i0,iy)+=ny; vertices_normals(i0,iz)+=nz; + vertices_normals(i1,ix)+=nx; vertices_normals(i1,iy)+=ny; vertices_normals(i1,iz)+=nz; + vertices_normals(i2,ix)+=nx; vertices_normals(i2,iy)+=ny; vertices_normals(i2,iz)+=nz; + if (quadrangle_flag) { + vertices_normals(i3,ix)+=nx; vertices_normals(i3,iy)+=ny; vertices_normals(i3,iz)+=nz; + } + } + } + + if (is_double_sided) cimg_forX(vertices_normals,p) { + const float + nx0 = vertices_normals(p,0), ny0 = vertices_normals(p,1), nz0 = vertices_normals(p,2), + nx1 = vertices_normals(p,3), ny1 = vertices_normals(p,4), nz1 = vertices_normals(p,5), + n0 = nx0*nx0 + ny0*ny0 + nz0*nz0, n1 = nx1*nx1 + ny1*ny1 + nz1*nz1; + if (n1>n0) { + vertices_normals(p,0) = -nx1; + vertices_normals(p,1) = -ny1; + vertices_normals(p,2) = -nz1; + } + } + + if (render_type==4) { + lightprops.assign(vertices._width); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + vertices(l,0) - lightx, + ly = Y + vertices(l,1) - lighty, + lz = Z + vertices(l,2) - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max((-lx*nx - ly*ny - lz*nz)/(norm*nl),(tpfloat)0); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } + } else { + const unsigned int + lw2 = light_texture._width/2 - 1, + lh2 = light_texture._height/2 - 1; + lightprops.assign(vertices._width,2); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + nnx = nx/norm, + nny = ny/norm; + lightprops(l,0) = lw2*(1 + nnx); + lightprops(l,1) = lh2*(1 + nny); + } + } + } break; + } + + // Draw visible primitives + const CImg default_color(1,_spectrum,1,1,(tc)200); + CImg<_to> _opacity; + + for (unsigned int l = 0; l& primitive = primitives[n_primitive]; + const CImg + &__color = n_primitive(), + _color = (__color && __color.size()!=_spectrum && __color._spectrum<_spectrum)? + __color.get_resize(-100,-100,-100,_spectrum,0):CImg(), + &color = _color?_color:(__color?__color:default_color); + const tc *const pcolor = color._data; + float opacity = __draw_object3d(opacities,n_primitive,_opacity); + if (_opacity.is_empty()) opacity*=g_opacity; + +#ifdef cimg_use_board + LibBoard::Board &board = *(LibBoard::Board*)pboard; +#endif + + switch (primitive.size()) { + case 1 : { // Colored point or sprite + const unsigned int n0 = (unsigned int)primitive[0]; + const int x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)); + + if (_opacity.is_empty()) { // Scalar opacity + + if (color.size()==_spectrum) { // Colored point + draw_point(x0,y0,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height()-(float)y0); + } +#endif + } else { // Sprite + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(color._width*factor), + _sh = (unsigned int)(color._height*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + draw_image(nx0,ny0,sprite,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } else { // Opacity mask + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(std::max(color._width,_opacity._width)*factor), + _sh = (unsigned int)(std::max(color._height,_opacity._height)*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + const CImg<_to> + _nopacity = (sw!=_opacity._width || sh!=_opacity._height)? + _opacity.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<_to>(), + &nopacity = _nopacity?_nopacity:_opacity; + draw_image(nx0,ny0,sprite,nopacity,g_opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } break; + case 2 : { // Colored line + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity); + else draw_line(x0,y0,x1,y1,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 5 : { // Colored sphere + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + is_wireframe = (unsigned int)primitive[2], + is_radius = (unsigned int)primitive[3]; + float Xc,Yc,Zc,radius; + if (is_radius) { + Xc = (float)vertices(n0,0); + Yc = (float)vertices(n0,1); + Zc = (float)vertices(n0,2); + radius = cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2)); + } else { + Xc = 0.5f*((float)vertices(n0,0) + (float)vertices(n1,0)); + Yc = 0.5f*((float)vertices(n0,1) + (float)vertices(n1,1)); + Zc = 0.5f*((float)vertices(n0,2) + (float)vertices(n1,2)); + radius = 0.5f*cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2)); + } + const float + zc = Z + Zc + _focale, + af = absfocale?absfocale/zc:1, + xc = X + Xc*af, + yc = Y + Yc*af; + radius*=af; + + switch (render_type) { + case 0 : + draw_point((int)xc,(int)yc,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot(xc,height() - yc); + } +#endif + break; + case 1 : + draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } +#endif + break; + default : + if (is_wireframe) draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + else draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + if (!is_wireframe) board.fillCircle(xc,height() - yc,radius); + else { + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } + } +#endif + break; + } + } break; + case 6 : { // Textured line + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for line primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + tx0 = (int)primitive[2], ty0 = (int)primitive[3], + tx1 = (int)primitive[4], ty1 = (int)primitive[5], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + else draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 3 : { // Colored triangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity).draw_point(x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x0,y0,z0,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x0,y0,x2,y2,pcolor,opacity). + draw_line(x1,y1,x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)); + else _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprops(n0),lightprops(n1),lightprops(n2),opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + } break; + } + } break; + case 4 : { // Colored quadrangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)), + x3 = cimg::uiround(projections(n3,0)), y3 = cimg::uiround(projections(n3,1)), + xc = (x0 + x1 + x2 + x3)/4, yc = (y0 + y1 + y2 + y3)/4; + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale, + zc = (z0 + z1 + z2 + z3)/4; + + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity). + draw_point(x2,y2,pcolor,opacity).draw_point(x3,y3,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,pcolor,opacity).draw_line(zbuffer,x3,y3,z3,x0,y0,z0,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x1,y1,x2,y2,pcolor,opacity). + draw_line(x2,y2,x3,y3,pcolor,opacity).draw_line(x3,y3,x0,y0,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity); + else + draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity).draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity,lightprops(l)); + else + _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)). + _draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp),(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3), + lightpropc = (lightprop0 + lightprop1 + lightprop2 + lightprop2)/4; + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,xc,yc,zc,pcolor,lightprop0,lightprop1,lightpropc,opacity). + draw_triangle(zbuffer,x1,y1,z1,x2,y2,z2,xc,yc,zc,pcolor,lightprop1,lightprop2,lightpropc,opacity). + draw_triangle(zbuffer,x2,y2,z2,x3,y3,z3,xc,yc,zc,pcolor,lightprop2,lightprop3,lightpropc,opacity). + draw_triangle(zbuffer,x3,y3,z3,x0,y0,z0,xc,yc,zc,pcolor,lightprop3,lightprop0,lightpropc,opacity); + else + draw_triangle(x0,y0,x1,y1,xc,yc,pcolor,lightprop0,lightprop1,lightpropc,opacity). + draw_triangle(x1,y1,x2,y2,xc,yc,pcolor,lightprop1,lightprop2,lightpropc,opacity). + draw_triangle(x2,y2,x3,y3,xc,yc,pcolor,lightprop2,lightprop3,lightpropc,opacity). + draw_triangle(x3,y3,x0,y0,xc,yc,pcolor,lightprop3,lightprop0,lightpropc,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)), + lx3 = (unsigned int)cimg::uiround(lightprops(n3,0)), ly3 = (unsigned int)cimg::uiround(lightprops(n3,1)), + lxc = (lx0 + lx1 + lx2 + lx3)/4, lyc = (ly0 + ly1 + ly2 + ly3)/4; + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,xc,yc,zc,pcolor,light_texture,lx0,ly0,lx1,ly1,lxc,lyc,opacity). + draw_triangle(zbuffer,x1,y1,z1,x2,y2,z2,xc,yc,zc,pcolor,light_texture,lx1,ly1,lx2,ly2,lxc,lyc,opacity). + draw_triangle(zbuffer,x2,y2,z2,x3,y3,z3,xc,yc,zc,pcolor,light_texture,lx2,ly2,lx3,ly3,lxc,lyc,opacity). + draw_triangle(zbuffer,x3,y3,z3,x0,y0,z0,xc,yc,zc,pcolor,light_texture,lx3,ly3,lx0,ly0,lxc,lyc,opacity); + else + draw_triangle(x0,y0,x1,y1,xc,yc,pcolor,light_texture,lx0,ly0,lx1,ly1,lxc,lyc,opacity). + draw_triangle(x1,y1,x2,y2,xc,yc,pcolor,light_texture,lx1,ly1,lx2,ly2,lxc,lyc,opacity). + draw_triangle(x2,y2,x3,y3,xc,yc,pcolor,light_texture,lx2,ly2,lx3,ly3,lxc,lyc,opacity). + draw_triangle(x3,y3,x0,y0,xc,yc,pcolor,light_texture,lx3,ly3,lx0,ly0,lxc,lyc,opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + case 9 : { // Textured triangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for triangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + tx0 = (int)primitive[3], ty0 = (int)primitive[4], + tx1 = (int)primitive[5], ty1 = (int)primitive[6], + tx2 = (int)primitive[7], ty2 = (int)primitive[8], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + break; + } + } break; + case 12 : { // Textured quadrangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for quadrangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + tx0 = (int)primitive[4], ty0 = (int)primitive[5], + tx1 = (int)primitive[6], ty1 = (int)primitive[7], + tx2 = (int)primitive[8], ty2 = (int)primitive[9], + tx3 = (int)primitive[10], ty3 = (int)primitive[11], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)), + x3 = cimg::uiround(projections(n3,0)), y3 = cimg::uiround(projections(n3,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale; + + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity). + draw_point(x3,y3,color.get_vector_at(tx3<=0?0:tx3>=color.width()?color.width() - 1:tx3, + ty3<=0?0:ty3>=color.height()?color.height() - 1:ty3)._data,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)), + lx3 = (unsigned int)cimg::uiround(lightprops(n3,0)), ly3 = (unsigned int)cimg::uiround(lightprops(n3,1)); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + } + } + if (render_type==5) cimg::mutex(10,0); + return *this; + } + + //@} + //--------------------------- + // + //! \name Data Input + //@{ + //--------------------------- + + //! Launch simple interface to select a shape from an image. + /** + \param disp Display window to use. + \param feature_type Type of feature to select. Can be { 0=point | 1=line | 2=rectangle | 3=ellipse }. + \param XYZ Pointer to 3 values X,Y,Z which tells about the projection point coordinates, for volumetric images. + \param exit_on_anykey Exit function when any key is pressed. + **/ + CImg& select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) { + return get_select(disp,feature_type,XYZ,exit_on_anykey,is_deep_selection_default).move_to(*this); + } + + //! Simple interface to select a shape from an image \overloading. + CImg& select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) { + return get_select(title,feature_type,XYZ,exit_on_anykey,is_deep_selection_default).move_to(*this); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) const { + return _select(disp,0,feature_type,XYZ,0,0,0,exit_on_anykey,true,false,is_deep_selection_default); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false,is_deep_selection_default); + } + + CImg _select(CImgDisplay &disp, const char *const title, + const unsigned int feature_type, unsigned int *const XYZ, + const int origX, const int origY, const int origZ, + const bool exit_on_anykey, + const bool reset_view3d, + const bool force_display_z_coord, + const bool is_deep_selection_default) const { + if (is_empty()) return CImg(1,feature_type==0?3:6,1,1,-1); + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + } else { + if (title) disp.set_title("%s",title); + disp.move_inside_screen(); + } + + CImg thumb; + if (width()>disp.screen_width() || height()>disp.screen_height()) + get_resize(cimg_fitscreen(width(),height(),depth()),depth(),-100).move_to(thumb); + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).set_wheel().show_mouse(); + + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + int area = 0, area_started = 0, area_clicked = 0, phase = 0, + X0 = (int)((XYZ?XYZ[0]:_width/2)%_width), + Y0 = (int)((XYZ?XYZ[1]:_height/2)%_height), + Z0 = (int)((XYZ?XYZ[2]:_depth/2)%_depth), + X1 =-1, Y1 = -1, Z1 = -1, + X3d = -1, Y3d = -1, + oX3d = X3d, oY3d = -1, + omx = -1, omy = -1; + float X = -1, Y = -1, Z = -1; + unsigned int key = 0, font_size = 32; + + bool is_deep_selection = is_deep_selection_default, + shape_selected = false, text_down = false, visible_cursor = true; + static CImg pose3d; + static bool is_view3d = false, is_axes = true; + if (reset_view3d) { pose3d.assign(); is_view3d = false; } + CImg points3d, opacities3d, sel_opacities3d; + CImgList primitives3d, sel_primitives3d; + CImgList colors3d, sel_colors3d; + CImg visu, visu0, view3d; + CImg text(1024); *text = 0; + + while (!key && !disp.is_closed() && !shape_selected) { + + // Handle mouse motion and selection + int + mx = disp.mouse_x(), + my = disp.mouse_y(); + + const float + mX = mx<0?-1.f:(float)mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my<0?-1.f:(float)my*(height() + (depth()>1?depth():0))/disp.height(); + + area = 0; + if (mX>=0 && mY>=0 && mX=0 && mX=height()) { area = 2; X = mX; Z = mY - _height; Y = (float)(phase?Y1:Y0); } + if (mY>=0 && mX>=width() && mY=width() && mY>=height()) area = 4; + if (disp.button()) { if (!area_clicked) area_clicked = area; } else area_clicked = 0; + + CImg filename(32); + + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(1); key = 0; } break; + case cimg::keyPAGEDOWN : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(-1); key = 0; } break; + case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_axes = !is_axes; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_view3d = !is_view3d; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).__draw_text(" Saving snapshot...",font_size,(int)text_down).display(disp); + visu0.save(filename); + (+visu0).__draw_text(" Snapshot '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + } + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).__draw_text(" Saving instance... ",font_size,(int)text_down).display(disp); + save(filename); + (+visu0).__draw_text(" Instance '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + } + + switch (area) { + + case 0 : // When mouse is out of image range + mx = my = -1; X = Y = Z = -1; + break; + + case 1 : case 2 : case 3 : { // When mouse is over the XY,XZ or YZ projections + const unsigned int but = disp.button(); + const bool b1 = (bool)(but&1), b2 = (bool)(but&2), b3 = (bool)(but&4); + + if (b1 && phase==1 && area_clicked==area) { // When selection has been started (1st step) + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } + if (!b1 && phase==2 && area_clicked!=area) { // When selection is at 2nd step (for volumes) + switch (area_started) { + case 1 : if (Z1!=(int)Z) visu0.assign(); Z1 = (int)Z; break; + case 2 : if (Y1!=(int)Y) visu0.assign(); Y1 = (int)Y; break; + case 3 : if (X1!=(int)X) visu0.assign(); X1 = (int)X; break; + } + } + if (b2 && area_clicked==area) { // When moving through the image/volume + if (phase) { + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } else { + if (_depth>1 && (X0!=(int)X || Y0!=(int)Y || Z0!=(int)Z)) visu0.assign(); + X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z; + } + } + if (b3) { // Reset selection + X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = area_clicked = area_started = 0; + visu0.assign(); + } + if (disp.wheel()) { // When moving through the slices of the volume (with mouse wheel) + if (_depth>1 && !disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT() && + !disp.is_keySHIFTLEFT() && !disp.is_keySHIFTRIGHT()) { + switch (area) { + case 1 : + if (phase) Z = (float)(Z1+=disp.wheel()); else Z = (float)(Z0+=disp.wheel()); + visu0.assign(); break; + case 2 : + if (phase) Y = (float)(Y1+=disp.wheel()); else Y = (float)(Y0+=disp.wheel()); + visu0.assign(); break; + case 3 : + if (phase) X = (float)(X1+=disp.wheel()); else X = (float)(X0+=disp.wheel()); + visu0.assign(); break; + } + disp.set_wheel(); + } else key = ~0U; + } + + if ((phase==0 && b1) || + (phase==1 && !b1) || + (phase==2 && b1)) switch (phase) { // Detect change of phase + case 0 : + if (area==area_clicked) { + X0 = X1 = (int)X; Y0 = Y1 = (int)Y; Z0 = Z1 = (int)Z; area_started = area; ++phase; + } break; + case 1 : + if (area==area_started) { + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; ++phase; + if (_depth>1) { + if (disp.is_keyCTRLLEFT()) is_deep_selection = !is_deep_selection_default; + if (is_deep_selection) ++phase; + } + } else if (!b1) { X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = 0; visu0.assign(); } + break; + case 2 : ++phase; break; + } + } break; + + case 4 : // When mouse is over the 3D view + if (is_view3d && points3d) { + X3d = mx - width()*disp.width()/(width() + (depth()>1?depth():0)); + Y3d = my - height()*disp.height()/(height() + (depth()>1?depth():0)); + if (oX3d<0) { oX3d = X3d; oY3d = Y3d; } + // Left + right buttons: reset. + if ((disp.button()&3)==3) { pose3d.assign(); view3d.assign(); oX3d = oY3d = X3d = Y3d = -1; } + else if (disp.button()&1 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Left button: rotate + const float + R = 0.45f*std::min(view3d._width,view3d._height), + R2 = R*R, + u0 = (float)(oX3d - view3d.width()/2), + v0 = (float)(oY3d - view3d.height()/2), + u1 = (float)(X3d - view3d.width()/2), + v1 = (float)(Y3d - view3d.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + pose3d.draw_image(CImg::rotation_matrix(u,v,w,-alpha)*pose3d.get_crop(0,0,2,2)); + view3d.assign(); + } else if (disp.button()&2 && pose3d && oY3d!=Y3d) { // Right button: zoom + pose3d(3,2)+=(Y3d - oY3d)*1.5f; view3d.assign(); + } + if (disp.wheel()) { // Wheel: zoom + pose3d(3,2)-=disp.wheel()*15; view3d.assign(); disp.set_wheel(); + } + if (disp.button()&4 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Middle button: shift + pose3d(3,0)-=oX3d - X3d; pose3d(3,1)-=oY3d - Y3d; view3d.assign(); + } + oX3d = X3d; oY3d = Y3d; + } + mx = my = -1; X = Y = Z = -1; + break; + } + + if (phase) { + if (!feature_type) shape_selected = phase?true:false; + else { + if (_depth>1) shape_selected = (phase==3)?true:false; + else shape_selected = (phase==2)?true:false; + } + } + + if (X0<0) X0 = 0; + if (X0>=width()) X0 = width() - 1; + if (Y0<0) Y0 = 0; + if (Y0>=height()) Y0 = height() - 1; + if (Z0<0) Z0 = 0; + if (Z0>=depth()) Z0 = depth() - 1; + if (X1<1) X1 = 0; + if (X1>=width()) X1 = width() - 1; + if (Y1<0) Y1 = 0; + if (Y1>=height()) Y1 = height() - 1; + if (Z1<0) Z1 = 0; + if (Z1>=depth()) Z1 = depth() - 1; + + // Draw visualization image on the display + if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) { + + if (!visu0) { // Create image of projected planes + if (thumb) thumb._get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + else _get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + visu0.resize(disp); + view3d.assign(); + points3d.assign(); + } + + if (is_view3d && _depth>1 && !view3d) { // Create 3D view for volumetric images + const unsigned int + _x3d = (unsigned int)cimg::round((float)_width*visu0._width/(_width + _depth),1,1), + _y3d = (unsigned int)cimg::round((float)_height*visu0._height/(_height + _depth),1,1), + x3d = _x3d>=visu0._width?visu0._width - 1:_x3d, + y3d = _y3d>=visu0._height?visu0._height - 1:_y3d; + CImg(1,2,1,1,64,128).resize(visu0._width - x3d,visu0._height - y3d,1,visu0._spectrum,3). + move_to(view3d); + if (!points3d) { + get_projections3d(primitives3d,colors3d,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0,true).move_to(points3d); + points3d.append(CImg(8,3,1,1, + 0,_width - 1,_width - 1,0,0,_width - 1,_width - 1,0, + 0,0,_height - 1,_height - 1,0,0,_height - 1,_height - 1, + 0,0,0,0,_depth - 1,_depth - 1,_depth - 1,_depth - 1),'x'); + CImg::vector(12,13).move_to(primitives3d); CImg::vector(13,14).move_to(primitives3d); + CImg::vector(14,15).move_to(primitives3d); CImg::vector(15,12).move_to(primitives3d); + CImg::vector(16,17).move_to(primitives3d); CImg::vector(17,18).move_to(primitives3d); + CImg::vector(18,19).move_to(primitives3d); CImg::vector(19,16).move_to(primitives3d); + CImg::vector(12,16).move_to(primitives3d); CImg::vector(13,17).move_to(primitives3d); + CImg::vector(14,18).move_to(primitives3d); CImg::vector(15,19).move_to(primitives3d); + colors3d.insert(12,CImg::vector(255,255,255)); + opacities3d.assign(primitives3d.width(),1,1,1,0.5f); + if (!phase) { + opacities3d[0] = opacities3d[1] = opacities3d[2] = 0.8f; + sel_primitives3d.assign(); + sel_colors3d.assign(); + sel_opacities3d.assign(); + } else { + if (feature_type==2) { + points3d.append(CImg(8,3,1,1, + X0,X1,X1,X0,X0,X1,X1,X0, + Y0,Y0,Y1,Y1,Y0,Y0,Y1,Y1, + Z0,Z0,Z0,Z0,Z1,Z1,Z1,Z1),'x'); + sel_primitives3d.assign(); + CImg::vector(20,21).move_to(sel_primitives3d); + CImg::vector(21,22).move_to(sel_primitives3d); + CImg::vector(22,23).move_to(sel_primitives3d); + CImg::vector(23,20).move_to(sel_primitives3d); + CImg::vector(24,25).move_to(sel_primitives3d); + CImg::vector(25,26).move_to(sel_primitives3d); + CImg::vector(26,27).move_to(sel_primitives3d); + CImg::vector(27,24).move_to(sel_primitives3d); + CImg::vector(20,24).move_to(sel_primitives3d); + CImg::vector(21,25).move_to(sel_primitives3d); + CImg::vector(22,26).move_to(sel_primitives3d); + CImg::vector(23,27).move_to(sel_primitives3d); + } else { + points3d.append(CImg(2,3,1,1, + X0,X1, + Y0,Y1, + Z0,Z1),'x'); + sel_primitives3d.assign(CImg::vector(20,21)); + } + sel_colors3d.assign(sel_primitives3d._width,CImg::vector(255,255,255)); + sel_opacities3d.assign(sel_primitives3d._width,1,1,1,0.8f); + } + points3d.shift_object3d(-0.5f*(_width - 1),-0.5f*(_height - 1),-0.5f*(_depth - 1)).resize_object3d(); + points3d*=0.75f*std::min(view3d._width,view3d._height); + } + + if (!pose3d) CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose3d); + CImg zbuffer3d(view3d._width,view3d._height,1,1,0); + const CImg rotated_points3d = pose3d.get_crop(0,0,2,2)*points3d; + if (sel_primitives3d) + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,sel_primitives3d,sel_colors3d,sel_opacities3d, + 2,true,500,0,0,0,0,0,1,zbuffer3d); + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,primitives3d,colors3d,opacities3d, + 2,true,500,0,0,0,0,0,1,zbuffer3d); + visu0.draw_image(x3d,y3d,view3d); + } + visu = visu0; + + if (X<0 || Y<0 || Z<0) { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + else { + if (is_axes) { if (visible_cursor) { disp.hide_mouse(); visible_cursor = false; }} + else { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + const int d = (depth()>1)?depth():0; + int _vX = (int)X, _vY = (int)Y, _vZ = (int)Z; + if (phase>=2) { _vX = X1; _vY = Y1; _vZ = Z1; } + int + w = disp.width(), W = width() + d, + h = disp.height(), H = height() + d, + _xp = (int)(_vX*(float)w/W), xp = _xp + ((int)(_xp*(float)W/w)!=_vX), + _yp = (int)(_vY*(float)h/H), yp = _yp + ((int)(_yp*(float)H/h)!=_vY), + _xn = (int)((_vX + 1.f)*w/W - 1), xn = _xn + ((int)((_xn + 1.f)*W/w)!=_vX + 1), + _yn = (int)((_vY + 1.f)*h/H - 1), yn = _yn + ((int)((_yn + 1.f)*H/h)!=_vY + 1), + _zxp = (int)((_vZ + width())*(float)w/W), zxp = _zxp + ((int)(_zxp*(float)W/w)!=_vZ + width()), + _zyp = (int)((_vZ + height())*(float)h/H), zyp = _zyp + ((int)(_zyp*(float)H/h)!=_vZ + height()), + _zxn = (int)((_vZ + width() + 1.f)*w/W - 1), + zxn = _zxn + ((int)((_zxn + 1.f)*W/w)!=_vZ + width() + 1), + _zyn = (int)((_vZ + height() + 1.f)*h/H - 1), + zyn = _zyn + ((int)((_zyn + 1.f)*H/h)!=_vZ + height() + 1), + _xM = (int)(width()*(float)w/W - 1), xM = _xM + ((int)((_xM + 1.f)*W/w)!=width()), + _yM = (int)(height()*(float)h/H - 1), yM = _yM + ((int)((_yM + 1.f)*H/h)!=height()), + xc = (xp + xn)/2, + yc = (yp + yn)/2, + zxc = (zxp + zxn)/2, + zyc = (zyp + zyn)/2, + xf = (int)(X*w/W), + yf = (int)(Y*h/H), + zxf = (int)((Z + width())*w/W), + zyf = (int)((Z + height())*h/H); + + if (is_axes) { // Draw axes + visu.draw_line(0,yf,visu.width() - 1,yf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,yf,visu.width() - 1,yf,background_color,0.7f,0x00FF00FF). + draw_line(xf,0,xf,visu.height() - 1,foreground_color,0.7f,0xFF00FF00). + draw_line(xf,0,xf,visu.height() - 1,background_color,0.7f,0x00FF00FF); + if (_depth>1) + visu.draw_line(zxf,0,zxf,yM,foreground_color,0.7f,0xFF00FF00). + draw_line(zxf,0,zxf,yM,background_color,0.7f,0x00FF00FF). + draw_line(0,zyf,xM,zyf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,zyf,xM,zyf,background_color,0.7f,0x00FF00FF); + } + + // Draw box cursor. + if (xn - xp>=4 && yn - yp>=4) + visu.draw_rectangle(xp,yp,xn,yn,foreground_color,0.2f). + draw_rectangle(xp,yp,xn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,yp,xn,yn,background_color,1,0x55555555); + if (_depth>1) { + if (yn - yp>=4 && zxn - zxp>=4) + visu.draw_rectangle(zxp,yp,zxn,yn,background_color,0.2f). + draw_rectangle(zxp,yp,zxn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(zxp,yp,zxn,yn,background_color,1,0x55555555); + if (xn - xp>=4 && zyn - zyp>=4) + visu.draw_rectangle(xp,zyp,xn,zyn,background_color,0.2f). + draw_rectangle(xp,zyp,xn,zyn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,zyp,xn,zyn,background_color,1,0x55555555); + } + + // Draw selection. + if (phase && (phase!=1 || area_started==area)) { + const int + _xp0 = (int)(X0*(float)w/W), xp0 = _xp0 + ((int)(_xp0*(float)W/w)!=X0), + _yp0 = (int)(Y0*(float)h/H), yp0 = _yp0 + ((int)(_yp0*(float)H/h)!=Y0), + _xn0 = (int)((X0 + 1.f)*w/W - 1), xn0 = _xn0 + ((int)((_xn0 + 1.f)*W/w)!=X0 + 1), + _yn0 = (int)((Y0 + 1.f)*h/H - 1), yn0 = _yn0 + ((int)((_yn0 + 1.f)*H/h)!=Y0 + 1), + _zxp0 = (int)((Z0 + width())*(float)w/W), zxp0 = _zxp0 + ((int)(_zxp0*(float)W/w)!=Z0 + width()), + _zyp0 = (int)((Z0 + height())*(float)h/H), zyp0 = _zyp0 + ((int)(_zyp0*(float)H/h)!=Z0 + height()), + _zxn0 = (int)((Z0 + width() + 1.f)*w/W - 1), + zxn0 = _zxn0 + ((int)((_zxn0 + 1.f)*W/w)!=Z0 + width() + 1), + _zyn0 = (int)((Z0 + height() + 1.f)*h/H - 1), + zyn0 = _zyn0 + ((int)((_zyn0 + 1.f)*H/h)!=Z0 + height() + 1), + xc0 = (xp0 + xn0)/2, + yc0 = (yp0 + yn0)/2, + zxc0 = (zxp0 + zxn0)/2, + zyc0 = (zyp0 + zyn0)/2; + + switch (feature_type) { + case 1 : { // Vector + visu.draw_arrow(xc0,yc0,xc,yc,background_color,0.9f,30,5,0x33333333). + draw_arrow(xc0,yc0,xc,yc,foreground_color,0.9f,30,5,0xCCCCCCCC); + if (d) { + visu.draw_arrow(zxc0,yc0,zxc,yc,background_color,0.9f,30,5,0x33333333). + draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.9f,30,5,0xCCCCCCCC). + draw_arrow(xc0,zyc0,xc,zyc,background_color,0.9f,30,5,0x33333333). + draw_arrow(xc0,zyc0,xc,zyc,foreground_color,0.9f,30,5,0xCCCCCCCC); + } + } break; + case 2 : { // Box + visu.draw_rectangle(X0=0 && my<13) text_down = true; else if (my>=visu.height() - 13) text_down = false; + if (!feature_type || !phase) { + if (X>=0 && Y>=0 && Z>=0 && X1 || force_display_z_coord) + cimg_snprintf(text,text._width," Point (%d,%d,%d) = [ ",origX + (int)X,origY + (int)Y,origZ + (int)Z); + else cimg_snprintf(text,text._width," Point (%d,%d) = [ ",origX + (int)X,origY + (int)Y); + CImg values = get_vector_at((int)X,(int)Y,(int)Z); + const bool is_large_spectrum = values._height>8; + if (is_large_spectrum) + values.draw_image(0,4,values.get_rows(values._height - 4,values._height - 1)).resize(1,8,1,1,0); + char *ctext = text._data + std::strlen(text), *const ltext = text._data + 512; + for (unsigned int c = 0; c::format_s(), + cimg::type::format(values[c])); + ctext += std::strlen(ctext); + if (c==3 && is_large_spectrum) { + cimg_snprintf(ctext,24," ..."); + ctext += std::strlen(ctext); + } + *(ctext++) = ' '; *ctext = 0; + } + std::strcpy(text._data + std::strlen(text),"] "); + } + } else switch (feature_type) { + case 1 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + length = cimg::round(cimg::hypot(dX,dY,dZ),0.1); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width," Vect (%d,%d,%d)-(%d,%d,%d), Length = %g ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1,length); + else if (_width!=1 && _height!=1) + cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g, Angle = %g\260 ", + origX + X0,origY + Y0,origX + X1,origY + Y1,length, + cimg::round(cimg::mod(180*std::atan2(-dY,-dX)/cimg::PI,360.),0.1)); + else + cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g ", + origX + X0,origY + Y0,origX + X1,origY + Y1,length); + } break; + case 2 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + length = cimg::round(cimg::hypot(dX,dY,dZ),0.1); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width, + " Box ( %d,%d,%d ) - ( %d,%d,%d )\n Size = ( %d,%d,%d ), Length = %g ", + origX + (X01 || force_display_z_coord) + cimg_snprintf(text,text._width," Ellipse ( %d,%d,%d ) - ( %d,%d,%d ), Radii = ( %d,%d,%d ) ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),1 + cimg::abs(Z0 - Z1)); + else cimg_snprintf(text,text._width," Ellipse ( %d,%d ) - ( %d,%d ), Radii = ( %d,%d ) ", + origX + X0,origY + Y0,origX + X1,origY + Y1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1)); + } + if (phase || (mx>=0 && my>=0)) visu.__draw_text("%s",font_size,(int)text_down,text._data); + } + + disp.display(visu); + } + if (!shape_selected) disp.wait(); + if (disp.is_resized()) { disp.resize(false)._is_resized = false; old_is_resized = true; visu0.assign(); } + omx = mx; omy = my; + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + + // Return result. + CImg res(1,feature_type==0?3:6,1,1,-1); + if (XYZ) { XYZ[0] = (unsigned int)X0; XYZ[1] = (unsigned int)Y0; XYZ[2] = (unsigned int)Z0; } + if (shape_selected) { + if (feature_type==2) { + if (is_deep_selection) switch (area_started) { + case 1 : Z0 = 0; Z1 = _depth - 1; break; + case 2 : Y0 = 0; Y1 = _height - 1; break; + case 3 : X0 = 0; X1 = _width - 1; break; + } + if (X0>X1) cimg::swap(X0,X1); + if (Y0>Y1) cimg::swap(Y0,Y1); + if (Z0>Z1) cimg::swap(Z0,Z1); + } + if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1; + switch (feature_type) { + case 1 : case 2 : res[0] = X0; res[1] = Y0; res[2] = Z0; res[3] = X1; res[4] = Y1; res[5] = Z1; break; + case 3 : + res[3] = cimg::abs(X1 - X0); res[4] = cimg::abs(Y1 - Y0); res[5] = cimg::abs(Z1 - Z0); + res[0] = X0; res[1] = Y0; res[2] = Z0; + break; + default : res[0] = X0; res[1] = Y0; res[2] = Z0; + } + } + if (!exit_on_anykey || !(disp.button()&4)) disp.set_button(); + if (!visible_cursor) disp.show_mouse(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + if (key!=~0U) disp.set_key(key); + return res; + } + + // Return a visualizable uchar8 image for display routines. + CImg _get_select(const CImgDisplay& disp, const int normalization, + const int x, const int y, const int z) const { + if (is_empty()) return CImg(1,1,1,1,0); + const CImg crop = get_shared_channels(0,std::min(2,spectrum() - 1)); + CImg img2d; + if (_depth>1) { + const int mdisp = std::min(disp.screen_width(),disp.screen_height()); + if (depth()>mdisp) { + crop.get_resize(-100,-100,mdisp,-100,0).move_to(img2d); + img2d.projections2d(x,y,z*img2d._depth/_depth); + } else crop.get_projections2d(x,y,z).move_to(img2d); + } else CImg(crop,false).move_to(img2d); + + // Check for inf and NaN values. + if (cimg::type::is_float() && normalization) { + bool is_inf = false, is_nan = false; + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) { is_inf = true; break; } + else if (cimg::type::is_nan(*ptr)) { is_nan = true; break; } + if (is_inf || is_nan) { + Tint m0 = (Tint)cimg::type::max(), M0 = (Tint)cimg::type::min(); + if (!normalization) { m0 = 0; M0 = 255; } + else if (normalization==2) { m0 = (Tint)disp._min; M0 = (Tint)disp._max; } + else + cimg_for(img2d,ptr,Tuchar) + if (!cimg::type::is_inf(*ptr) && !cimg::type::is_nan(*ptr)) { + if (*ptr<(Tuchar)m0) m0 = *ptr; + if (*ptr>(Tuchar)M0) M0 = *ptr; + } + const T + val_minf = (T)(normalization==1 || normalization==3?m0 - (M0 - m0)*20 - 1:m0), + val_pinf = (T)(normalization==1 || normalization==3?M0 + (M0 - m0)*20 + 1:M0); + if (is_nan) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_nan(*ptr)) *ptr = val_minf; // Replace NaN values + if (is_inf) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) *ptr = (float)*ptr<0?val_minf:val_pinf; // Replace +-inf values + } + } + + switch (normalization) { + case 1 : img2d.normalize((ucharT)0,(ucharT)255); break; + case 2 : { + const float m = disp._min, M = disp._max; + (img2d-=m)*=255.f/(M - m>0?M - m:1); + } break; + case 3 : + if (cimg::type::is_float()) img2d.normalize((ucharT)0,(ucharT)255); + else { + const float + m = (float)cimg::type::min(), + M = (float)cimg::type::max(); + (img2d-=m)*=255.f/(M - m>0?M - m:1); + } break; + } + if (img2d.spectrum()==2) img2d.channels(0,2); + return img2d; + } + + //! Select sub-graph in a graph. + CImg get_select_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "select_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title("CImg<%s>",pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth; + const unsigned int old_normalization = disp.normalization(); + disp.show().set_button().set_wheel()._normalization = 0; + + double nymin = ymin, nymax = ymax, nxmin = xmin, nxmax = xmax; + if (nymin==nymax) { nymin = (Tfloat)min_max(nymax); const double dy = nymax - nymin; nymin-=dy/20; nymax+=dy/20; } + if (nymin==nymax) { --nymin; ++nymax; } + if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.; } + + static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 }; + static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 }; + + CImg colormap(3,_spectrum); + if (_spectrum==1) { colormap[0] = colormap[1] = 120; colormap[2] = 200; } + else { + colormap(0,0) = 220; colormap(1,0) = 10; colormap(2,0) = 10; + if (_spectrum>1) { colormap(0,1) = 10; colormap(1,1) = 220; colormap(2,1) = 10; } + if (_spectrum>2) { colormap(0,2) = 10; colormap(1,2) = 10; colormap(2,2) = 220; } + if (_spectrum>3) { colormap(0,3) = 220; colormap(1,3) = 220; colormap(2,3) = 10; } + if (_spectrum>4) { colormap(0,4) = 220; colormap(1,4) = 10; colormap(2,4) = 220; } + if (_spectrum>5) { colormap(0,5) = 10; colormap(1,5) = 220; colormap(2,5) = 220; } + if (_spectrum>6) { + cimg_uint64 rng = 10; + cimg_for_inY(colormap,6,colormap.height()-1,k) { + colormap(0,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + colormap(1,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + colormap(2,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + } + } + } + + CImg visu0, visu, graph, text, axes; + int x0 = -1, x1 = -1, y0 = -1, y1 = -1, omouse_x = -2, omouse_y = -2; + const unsigned int one = plot_type==3?0U:1U; + unsigned int okey = 0, obutton = 0, font_size = 32; + CImg message(1024); + CImg_3x3(I,unsigned char); + + for (bool selected = false; !selected && !disp.is_closed() && !okey && !disp.wheel(); ) { + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + const unsigned int key = disp.key(), button = disp.button(); + + // Generate graph representation. + if (!visu0) { + visu0.assign(disp.width(),disp.height(),1,3,220); + const int gdimx = disp.width() - 32, gdimy = disp.height() - 32; + if (gdimx>0 && gdimy>0) { + graph.assign(gdimx,gdimy,1,3,255); + if (siz<32) { + if (siz>1) graph.draw_grid(gdimx/(float)(siz - one),gdimy/(float)(siz - one),0,0, + false,true,black,0.2f,0x33333333,0x33333333); + } else graph.draw_grid(-10,-10,0,0,false,true,black,0.2f,0x33333333,0x33333333); + cimg_forC(*this,c) + graph.draw_graph(get_shared_channel(c),&colormap(0,c),(plot_type!=3 || _spectrum==1)?1:0.6f, + plot_type,vertex_type,nymax,nymin); + + axes.assign(gdimx,gdimy,1,1,0); + const float + dx = (float)cimg::abs(nxmax - nxmin), dy = (float)cimg::abs(nymax - nymin), + px = (float)std::pow(10.,(int)std::log10(dx?dx:1) - 2.), + py = (float)std::pow(10.,(int)std::log10(dy?dy:1) - 2.); + const CImg + seqx = dx<=0?CImg::vector(nxmin): + CImg::sequence(1 + gdimx/60,nxmin,one?nxmax:nxmin + (nxmax - nxmin)*(siz + 1)/siz), + seqy = CImg::sequence(1 + gdimy/60,nymax,nymin); + + const bool allow_zero = (nxmin*nxmax>0) || (nymin*nymax>0); + axes.draw_axes(seqx,seqy,white,1,~0U,~0U,13,allow_zero,px,py); + if (nymin>0) axes.draw_axis(seqx,gdimy - 1,gray,1,~0U,13,allow_zero,px); + if (nymax<0) axes.draw_axis(seqx,0,gray,1,~0U,13,allow_zero,px); + if (nxmin>0) axes.draw_axis(0,seqy,gray,1,~0U,13,allow_zero,py); + if (nxmax<0) axes.draw_axis(gdimx - 1,seqy,gray,1,~0U,13,allow_zero,py); + + cimg_for3x3(axes,x,y,0,0,I,unsigned char) + if (Icc) { + if (Icc==255) cimg_forC(graph,c) graph(x,y,c) = 0; + else cimg_forC(graph,c) graph(x,y,c) = (unsigned char)(2*graph(x,y,c)/3); + } + else if (Ipc || Inc || Icp || Icn || Ipp || Inn || Ipn || Inp) + cimg_forC(graph,c) graph(x,y,c) = (unsigned char)((graph(x,y,c) + 511)/3); + + visu0.draw_image(16,16,graph); + visu0.draw_line(15,15,16 + gdimx,15,gray2).draw_line(16 + gdimx,15,16 + gdimx,16 + gdimy,gray2). + draw_line(16 + gdimx,16 + gdimy,15,16 + gdimy,white).draw_line(15,16 + gdimy,15,15,white); + } else graph.assign(); + text.assign().draw_text(0,0,labelx?labelx:"X-axis",white,ngray,1,13).resize(-100,-100,1,3); + visu0.draw_image((visu0.width() - text.width())/2,visu0.height() - 14,~text); + text.assign().draw_text(0,0,labely?labely:"Y-axis",white,ngray,1,13).rotate(-90).resize(-100,-100,1,3); + visu0.draw_image(1,(visu0.height() - text.height())/2,~text); + visu.assign(); + } + + // Generate and display current view. + if (!visu) { + visu.assign(visu0); + if (graph && x0>=0 && x1>=0) { + const int + nx0 = x0<=x1?x0:x1, + nx1 = x0<=x1?x1:x0, + ny0 = y0<=y1?y0:y1, + ny1 = y0<=y1?y1:y0, + sx0 = (int)(16 + nx0*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sx1 = (int)(15 + (nx1 + 1)*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sy0 = 16 + ny0, + sy1 = 16 + ny1; + if (y0>=0 && y1>=0) + visu.draw_rectangle(sx0,sy0,sx1,sy1,gray,0.5f).draw_rectangle(sx0,sy0,sx1,sy1,black,0.5f,0xCCCCCCCCU); + else visu.draw_rectangle(sx0,0,sx1,visu.height() - 17,gray,0.5f). + draw_line(sx0,16,sx0,visu.height() - 17,black,0.5f,0xCCCCCCCCU). + draw_line(sx1,16,sx1,visu.height() - 17,black,0.5f,0xCCCCCCCCU); + } + if (mouse_x>=16 && mouse_y>=16 && mouse_x=7) + cimg_snprintf(message,message._width,"Value[%u:%g] = ( %g %g %g ... %g %g %g )",x,cx, + (double)(*this)(x,0,0,0),(double)(*this)(x,0,0,1),(double)(*this)(x,0,0,2), + (double)(*this)(x,0,0,_spectrum - 4),(double)(*this)(x,0,0,_spectrum - 3), + (double)(*this)(x,0,0,_spectrum - 1)); + else { + cimg_snprintf(message,message._width,"Value[%u:%g] = ( ",x,cx); + cimg_forC(*this,c) cimg_sprintf(message._data + std::strlen(message),"%g ",(double)(*this)(x,0,0,c)); + cimg_sprintf(message._data + std::strlen(message),")"); + } + if (x0>=0 && x1>=0) { + const unsigned int + nx0 = (unsigned int)(x0<=x1?x0:x1), + nx1 = (unsigned int)(x0<=x1?x1:x0), + ny0 = (unsigned int)(y0<=y1?y0:y1), + ny1 = (unsigned int)(y0<=y1?y1:y0); + const double + cx0 = nxmin + nx0*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cx1 = nxmin + (nx1 + one)*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cy0 = nymax - ny0*(nymax - nymin)/(visu._height - 32), + cy1 = nymax - ny1*(nymax - nymin)/(visu._height - 32); + if (y0>=0 && y1>=0) + cimg_sprintf(message._data + std::strlen(message)," - Range ( %u:%g, %g ) - ( %u:%g, %g )", + x0,cx0,cy0,x1 + one,cx1,cy1); + else + cimg_sprintf(message._data + std::strlen(message)," - Range [ %u:%g - %u:%g ]", + x0,cx0,x1 + one,cx1); + } + text.assign().draw_text(0,0,message,white,ngray,1,13).resize(-100,-100,1,3); + visu.draw_image((visu.width() - text.width())/2,1,~text); + } + visu.display(disp); + } + + // Test keys. + CImg filename(32); + switch (okey = key) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : okey = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).__draw_text(" Saving snapshot... ",font_size,0).display(disp); + screen.save(filename); + (+screen).__draw_text(" Snapshot '%s' saved. ",font_size,0,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).__draw_text(" Saving instance... ",font_size,0).display(disp); + save(filename); + (+screen).__draw_text(" Instance '%s' saved. ",font_size,0,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + } + + // Handle mouse motion and mouse buttons. + if (obutton!=button || omouse_x!=mouse_x || omouse_y!=mouse_y) { + visu.assign(); + if (disp.mouse_x()>=0 && disp.mouse_y()>=0) { + const int + mx = (mouse_x - 16)*(int)(siz - one)/(disp.width() - 32), + cx = cimg::cut(mx,0,(int)(siz - 1 - one)), + my = mouse_y - 16, + cy = cimg::cut(my,0,disp.height() - 32); + if (button&1) { + if (!obutton) { x0 = cx; y0 = -1; } else { x1 = cx; y1 = -1; } + } + else if (button&2) { + if (!obutton) { x0 = cx; y0 = cy; } else { x1 = cx; y1 = cy; } + } + else if (obutton) { x1 = x1>=0?cx:-1; y1 = y1>=0?cy:-1; selected = true; } + } else if (!button && obutton) selected = true; + obutton = button; omouse_x = mouse_x; omouse_y = mouse_y; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (visu && visu0) disp.wait(); + if (!exit_on_anykey && okey && okey!=cimg::keyESC && + (okey!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + okey = 0; + } + } + + disp._normalization = old_normalization; + if (x1>=0 && x1(4,1,1,1,x0,y0,x1>=0?x1 + (int)one:-1,y1); + } + + //! Load image from a file. + /** + \param filename Filename, as a C-string. + \note The extension of \c filename defines the file format. If no filename + extension is provided, CImg::get_load() will try to load the file as a .cimg or .cimgz file. + **/ + CImg& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load(): Specified filename is (null).", + cimg_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimg_load_plugin + cimg_load_plugin(filename); +#endif +#ifdef cimg_load_plugin1 + cimg_load_plugin1(filename); +#endif +#ifdef cimg_load_plugin2 + cimg_load_plugin2(filename); +#endif +#ifdef cimg_load_plugin3 + cimg_load_plugin3(filename); +#endif +#ifdef cimg_load_plugin4 + cimg_load_plugin4(filename); +#endif +#ifdef cimg_load_plugin5 + cimg_load_plugin5(filename); +#endif +#ifdef cimg_load_plugin6 + cimg_load_plugin6(filename); +#endif +#ifdef cimg_load_plugin7 + cimg_load_plugin7(filename); +#endif +#ifdef cimg_load_plugin8 + cimg_load_plugin8(filename); +#endif + // Text formats + if (!cimg::strcasecmp(ext,"asc")) load_ascii(filename); + else if (!cimg::strcasecmp(ext,"csv") || + !cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) load_dlm(filename); + else if (!cimg::strcasecmp(ext,"pdf")) load_pdf_external(filename); + + // 2D binary formats + else if (!cimg::strcasecmp(ext,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) load_jpeg(filename); + else if (!cimg::strcasecmp(ext,"png")) load_png(filename); + else if (!cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"pnm") || + !cimg::strcasecmp(ext,"pbm") || + !cimg::strcasecmp(ext,"pnk")) load_pnm(filename); + else if (!cimg::strcasecmp(ext,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"exr")) load_exr(filename); + else if (!cimg::strcasecmp(ext,"cr2") || + !cimg::strcasecmp(ext,"crw") || + !cimg::strcasecmp(ext,"dcr") || + !cimg::strcasecmp(ext,"mrw") || + !cimg::strcasecmp(ext,"nef") || + !cimg::strcasecmp(ext,"orf") || + !cimg::strcasecmp(ext,"pix") || + !cimg::strcasecmp(ext,"ptx") || + !cimg::strcasecmp(ext,"raf") || + !cimg::strcasecmp(ext,"srf")) load_dcraw_external(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"heic") || + !cimg::strcasecmp(ext,"avif")) load_heif(filename); + + // 3D binary formats + else if (!cimg::strcasecmp(ext,"dcm") || + !cimg::strcasecmp(ext,"dicom")) load_medcon_external(filename); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) load_analyze(filename); + else if (!cimg::strcasecmp(ext,"par") || + !cimg::strcasecmp(ext,"rec")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"mnc")) load_minc2(filename); + else if (!cimg::strcasecmp(ext,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(ext,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) return load_cimg(filename); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + + // Image sequences + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded) { + std::FILE *file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to open file '%s'.", + cimg_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + cimg::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"pnm")) load_pnm(filename); + else if (!cimg::strcasecmp(f_type,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(f_type,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(f_type,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(f_type,"jpg")) load_jpeg(filename); + else if (!cimg::strcasecmp(f_type,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(f_type,"png")) load_png(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"dcm")) load_medcon_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file with other means. + if (!is_loaded) { + try { + load_other(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image from a file \newinstance. + static CImg get_load(const char *const filename) { + return CImg().load(filename); + } + + //! Load image from an ascii file. + /** + \param filename Filename, as a C -string. + **/ + CImg& load_ascii(const char *const filename) { + return _load_ascii(0,filename); + } + + //! Load image from an ascii file \inplace. + static CImg get_load_ascii(const char *const filename) { + return CImg().load_ascii(filename); + } + + //! Load image from an ascii file \overloading. + CImg& load_ascii(std::FILE *const file) { + return _load_ascii(file,0); + } + + //! Loadimage from an ascii file \newinstance. + static CImg get_load_ascii(std::FILE *const file) { + return CImg().load_ascii(file); + } + + CImg& _load_ascii(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_ascii(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg line(256); *line = 0; + int err = std::fscanf(nfile,"%255[^\n]",line._data); + unsigned int dx = 0, dy = 1, dz = 1, dc = 1; + cimg_sscanf(line,"%u%*c%u%*c%u%*c%u",&dx,&dy,&dz,&dc); + err = std::fscanf(nfile,"%*[^0-9.eEinfa+-]"); + if (!dx || !dy || !dz || !dc) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_ascii(): Invalid ascii header in file '%s', image dimensions are set " + "to (%u,%u,%u,%u).", + cimg_instance, + filename?filename:"(FILE*)",dx,dy,dz,dc); + } + assign(dx,dy,dz,dc); + const ulongT siz = size(); + ulongT off = 0; + double val; + T *ptr = _data; + for (err = 1, off = 0; off& load_dlm(const char *const filename) { + return _load_dlm(0,filename); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(const char *const filename) { + return CImg().load_dlm(filename); + } + + //! Load image from a DLM file \overloading. + CImg& load_dlm(std::FILE *const file) { + return _load_dlm(file,0); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(std::FILE *const file) { + return CImg().load_dlm(file); + } + + CImg& _load_dlm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_dlm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + CImg delimiter(256), tmp(256); *delimiter = *tmp = 0; + unsigned int cdx = 0, dx = 0, dy = 0; + int err = 0; + double val; + assign(256,256,1,1,(T)0); + while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) { + if (err>0) (*this)(cdx++,dy) = (T)val; + if (cdx>=_width) resize(3*_width/2,_height,1,1,0); + char c = 0; + if (!cimg_sscanf(delimiter,"%255[^\n]%c",tmp._data,&c) || c=='\n') { + dx = std::max(cdx,dx); + if (++dy>=_height) resize(_width,3*_height/2,1,1,0); + cdx = 0; + } + } + if (cdx && err==1) { dx = cdx; ++dy; } + if (!dx || !dy) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_dlm(): Invalid DLM file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + resize(dx,dy,1,1,0); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a BMP file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_bmp(const char *const filename) { + return _load_bmp(0,filename); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(const char *const filename) { + return CImg().load_bmp(filename); + } + + //! Load image from a BMP file \overloading. + CImg& load_bmp(std::FILE *const file) { + return _load_bmp(file,0); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(std::FILE *const file) { + return CImg().load_bmp(file); + } + + CImg& _load_bmp(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_bmp(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(54); + cimg::fread(header._data,54,nfile); + if (*header!='B' || header[1]!='M') { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_bmp(): Invalid BMP file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read header and pixel buffer + int + file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24), + offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24), + header_size = header[0x0E] + (header[0x0F]<<8) + (header[0x10]<<16) + (header[0x11]<<24), + dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24), + dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24), + compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24), + nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24), + bpp = header[0x1C] + (header[0x1D]<<8); + + if (!file_size || file_size==offset) { + cimg::fseek(nfile,0,SEEK_END); + file_size = (int)cimg::ftell(nfile); + cimg::fseek(nfile,54,SEEK_SET); + } + if (header_size>40) cimg::fseek(nfile,header_size - 40,SEEK_CUR); + + const int + dx_bytes = (bpp==1)?(dx/8 + (dx%8?1:0)):((bpp==4)?(dx/2 + (dx%2)):(int)((longT)dx*bpp/8)), + align_bytes = (4 - dx_bytes%4)%4; + const ulongT + cimg_iobuffer = (ulongT)24*1024*1024, + buf_size = (ulongT)cimg::abs(dy)*(dx_bytes + align_bytes); + + CImg colormap; + if (bpp<16) { if (!nb_colors) nb_colors = 1<0) cimg::fseek(nfile,xoffset,SEEK_CUR); + + CImg buffer; + if (buf_size=2) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0x80, val = 0; + cimg_forX(*this,x) { + if (mask==0x80) val = *(ptrs++); + const unsigned char *col = (unsigned char*)(colormap._data + (val&mask?1:0)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask); + } + ptrs+=align_bytes; + } + } break; + case 4 : { // 16 colors + if (colormap._width>=16) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0xF0, val = 0; + cimg_forX(*this,x) { + if (mask==0xF0) val = *(ptrs++); + const unsigned char color = (unsigned char)((mask<16)?(val&mask):((val&mask)>>4)); + const unsigned char *col = (unsigned char*)(colormap._data + color); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask,4); + } + ptrs+=align_bytes; + } + } break; + case 8 : { // 256 colors + if (colormap._width>=256) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char *col = (unsigned char*)(colormap._data + *(ptrs++)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + } + ptrs+=align_bytes; + } + } break; + case 16 : { // 16 bits colors (RGB565) + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char c1 = *(ptrs++), c2 = *(ptrs++); + const unsigned short col = (unsigned short)c2<<8 | c1; + (*this)(x,y,2) = (T)((col&0x1F)<<3); + (*this)(x,y,1) = (T)(((col>>5)&0x3F)<<3); + (*this)(x,y,0) = (T)(((col>>11)&0x1F)<<3); + } + ptrs+=align_bytes; + } + } break; + case 24 : { // 24 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + } + ptrs+=align_bytes; + } + } break; + case 32 : { // 32 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + ++ptrs; + } + ptrs+=align_bytes; + } + } break; + } + if (dy<0) mirror('y'); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a JPEG file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_jpeg(const char *const filename) { + return _load_jpeg(0,filename); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(const char *const filename) { + return CImg().load_jpeg(filename); + } + + //! Load image from a JPEG file \overloading. + CImg& load_jpeg(std::FILE *const file) { + return _load_jpeg(file,0); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(std::FILE *const file) { + return CImg().load_jpeg(file); + } + + // Custom error handler for libjpeg. +#ifdef cimg_use_jpeg + struct _cimg_error_mgr { + struct jpeg_error_mgr original; + jmp_buf setjmp_buffer; + char message[JMSG_LENGTH_MAX]; + }; + + typedef struct _cimg_error_mgr *_cimg_error_ptr; + + METHODDEF(void) _cimg_jpeg_error_exit(j_common_ptr cinfo) { + _cimg_error_ptr c_err = (_cimg_error_ptr) cinfo->err; // Return control to the setjmp point + (*cinfo->err->format_message)(cinfo,c_err->message); + jpeg_destroy(cinfo); // Clean memory and temp files + longjmp(c_err->setjmp_buffer,1); + } +#endif + + CImg& _load_jpeg(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_jpeg(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_jpeg + if (file) + throw CImgIOException(_cimg_instance + "load_jpeg(): Unable to load data from '(FILE*)' unless libjpeg is enabled.", + cimg_instance); + else return load_other(filename); +#else + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + struct jpeg_decompress_struct cinfo; + struct _cimg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.original); + jerr.original.error_exit = _cimg_jpeg_error_exit; + if (setjmp(jerr.setjmp_buffer)) { // JPEG error + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_jpeg(): Error message returned by libjpeg: %s.", + cimg_instance,jerr.message); + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo,nfile); + jpeg_read_header(&cinfo,TRUE); + jpeg_start_decompress(&cinfo); + + if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) { + if (!file) { + cimg::fclose(nfile); + return load_other(filename); + } else + throw CImgIOException(_cimg_instance + "load_jpeg(): Failed to load JPEG data from file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + } + CImg buffer(cinfo.output_width*cinfo.output_components); + JSAMPROW row_pointer[1]; + try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); } + catch (...) { if (!file) cimg::fclose(nfile); throw; } + T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height, + *ptr_a = _data + 3UL*_width*_height; + while (cinfo.output_scanline + // This is experimental code, not much tested, use with care. + CImg& load_magick(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_magick(): Specified filename is (null).", + cimg_instance); + +#ifdef cimg_use_magick + Magick::Image image(filename); + const unsigned int W = image.size().width(), H = image.size().height(); + switch (image.type()) { + case Magick::PaletteMatteType : + case Magick::TrueColorMatteType : + case Magick::ColorSeparationType : { + assign(W,H,1,4); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + case Magick::PaletteType : + case Magick::TrueColorType : { + assign(W,H,1,3); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + ++pixels; + } + } break; + case Magick::GrayscaleMatteType : { + assign(W,H,1,2); + T *ptr_r = data(0,0,0,0), *ptr_a = data(0,0,0,1); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + default : { + assign(W,H,1,1); + T *ptr_r = data(0,0,0,0); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + ++pixels; + } + } + } + return *this; +#else + throw CImgIOException(_cimg_instance + "load_magick(): Unable to load file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Load image from a file, using Magick++ library \newinstance. + static CImg get_load_magick(const char *const filename) { + return CImg().load_magick(filename); + } + + //! Load image from a PNG file. + /** + \param filename Filename, as a C-string. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + **/ + CImg& load_png(const char *const filename, unsigned int *const bits_per_value=0) { + return _load_png(0,filename,bits_per_value); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(const char *const filename, unsigned int *const bits_per_value=0) { + return CImg().load_png(filename,bits_per_value); + } + + //! Load image from a PNG file \overloading. + CImg& load_png(std::FILE *const file, unsigned int *const bits_per_value=0) { + return _load_png(file,0,bits_per_value); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(std::FILE *const file, unsigned int *const bits_per_value=0) { + return CImg().load_png(file,bits_per_value); + } + + // (Note: Most of this function has been written by Eric Fausett) + CImg& _load_png(std::FILE *const file, const char *const filename, unsigned int *const bits_per_value) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_png(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_png + cimg::unused(bits_per_value); + if (file) + throw CImgIOException(_cimg_instance + "load_png(): Unable to load data from '(FILE*)' unless libpng is enabled.", + cimg_instance); + + else return load_other(filename); +#else + // Open file and check for PNG validity +#if defined __GNUC__ + const char *volatile nfilename = filename; // Use 'volatile' to avoid (wrong) g++ warning + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb"); +#else + const char *nfilename = filename; + std::FILE *nfile = file?file:cimg::fopen(nfilename,"rb"); +#endif + unsigned char pngCheck[8] = { 0 }; + cimg::fread(pngCheck,8,(std::FILE*)nfile); + if (png_sig_cmp(pngCheck,0,8)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Invalid PNG file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Setup PNG structures for read + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn); + if (!png_ptr) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'png_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,(png_infopp)0,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'info_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'end_info' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Error handling callback for png file reading + if (setjmp(png_jmpbuf(png_ptr))) { + if (!file) cimg::fclose((std::FILE*)nfile); + png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Encountered unknown fatal error in libpng for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + png_set_sig_bytes(png_ptr, 8); + + // Get PNG Header Info up to data block + png_read_info(png_ptr,info_ptr); + png_uint_32 W, H; + int bit_depth, color_type, interlace_type; + bool is_gray = false; + png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,(int*)0,(int*)0); + if (bits_per_value) *bits_per_value = (unsigned int)bit_depth; + + // Transforms to unify image data + if (color_type==PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + color_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + } + if (color_type==PNG_COLOR_TYPE_GRAY && bit_depth<8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + is_gray = true; + bit_depth = 8; + } + if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_ptr); + color_type |= PNG_COLOR_MASK_ALPHA; + } + if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + color_type |= PNG_COLOR_MASK_COLOR; + is_gray = true; + } + if (color_type==PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr,0xffffU,PNG_FILLER_AFTER); + + png_read_update_info(png_ptr,info_ptr); + if (bit_depth!=8 && bit_depth!=16) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Invalid bit depth %u in file '%s'.", + cimg_instance, + bit_depth,nfilename?nfilename:"(FILE*)"); + } + const int byte_depth = bit_depth>>3; + + // Allocate memory for image reading + png_bytep *const imgData = new png_bytep[H]; + for (unsigned int row = 0; row& load_pnm(const char *const filename) { + return _load_pnm(0,filename); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(const char *const filename) { + return CImg().load_pnm(filename); + } + + //! Load image from a PNM file \overloading. + CImg& load_pnm(std::FILE *const file) { + return _load_pnm(file,0); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(std::FILE *const file) { + return CImg().load_pnm(file); + } + + CImg& _load_pnm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pnm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + unsigned int ppm_type, W, H, D = 1, colormax = 255; + CImg item(16384,1,1,1,0); + int err, rval, gval, bval; + const longT cimg_iobuffer = (longT)24*1024*1024; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%u",&ppm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %u %u %u %u",&W,&H,&D,&colormax))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): WIDTH and HEIGHT fields undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (ppm_type!=1 && ppm_type!=4) { + if (err==2 || (err==3 && (ppm_type==5 || ppm_type==7 || ppm_type==8 || ppm_type==9))) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%u",&colormax)!=1) + cimg::warn(_cimg_instance + "load_pnm(): COLORMAX field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else { colormax = D; D = 1; } + } + std::fgetc(nfile); + + if (filename) { // Check that dimensions specified in file does not exceed the buffer dimension + const cimg_int64 siz = cimg::fsize(filename); + if (W*H*D>siz) + throw CImgIOException(_cimg_instance + "load_pnm(): Specified image dimensions in file '%s' exceed file size.", + cimg_instance, + filename); + } + + switch (ppm_type) { + case 1 : { // 2D B&W ascii + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)(rval?0:255); else break; } + } break; + case 2 : { // 2D grey ascii + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)rval; else break; } + } break; + case 3 : { // 2D color ascii + assign(W,H,1,3); + T *ptrd = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forXY(*this,x,y) { + if (std::fscanf(nfile,"%d %d %d",&rval,&gval,&bval)==3) { + *(ptrd++) = (T)rval; *(ptr_g++) = (T)gval; *(ptr_b++) = (T)bval; + } else break; + } + } break; + case 4 : { // 2D b&w binary (support 3D PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + unsigned int w = 0, h = 0, d = 0; + for (longT to_read = (longT)((W/8 + (W%8?1:0))*H*D); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + unsigned char mask = 0, val = 0; + for (ulongT off = (ulongT)raw._width; off || mask; mask>>=1) { + if (!mask) { if (off--) val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?0:255); + if (++w==W) { w = 0; mask = 0; if (++h==H) { h = 0; if (++d==D) break; }} + } + } + } break; + case 5 : case 7 : { // 2D/3D grey binary (support 3D PINK extension) + if (colormax<256) { // 8 bits + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } else { // 16 bits + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } + } break; + case 6 : { // 2D color binary + if (colormax<256) { // 8 bits + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { // 16 bits + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } + } break; + case 8 : { // 2D/3D grey binary with int32 integers (PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const int *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + case 9 : { // 2D/3D grey binary with float values (PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const float *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + default : + assign(); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM type 'P%d' found, but type is not supported.", + cimg_instance, + filename?filename:"(FILE*)",ppm_type); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PFM file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pfm(const char *const filename) { + return _load_pfm(0,filename); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(const char *const filename) { + return CImg().load_pfm(filename); + } + + //! Load image from a PFM file \overloading. + CImg& load_pfm(std::FILE *const file) { + return _load_pfm(file,0); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(std::FILE *const file) { + return CImg().load_pfm(file); + } + + CImg& _load_pfm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pfm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + char pfm_type; + CImg item(16384,1,1,1,0); + int W = 0, H = 0, err = 0; + double scale = 0; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%c",&pfm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): PFM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %d %d",&W,&H))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH and HEIGHT fields are undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else if (W<=0 || H<=0) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH (%d) and HEIGHT (%d) fields are invalid in file '%s'.", + cimg_instance,W,H, + filename?filename:"(FILE*)"); + } + if (err==2) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%lf",&scale)!=1) + cimg::warn(_cimg_instance + "load_pfm(): SCALE field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + std::fgetc(nfile); + const bool is_color = (pfm_type=='F'), is_inverted = (scale>0)!=cimg::endianness(); + if (is_color) { + assign(W,H,1,3,(T)0); + CImg buf(3*W); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forY(*this,y) { + cimg::fread(buf._data,3*W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,3*W); + const float *ptrs = buf._data; + cimg_forX(*this,x) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { + assign(W,H,1,1,(T)0); + CImg buf(W); + T *ptrd = data(0,0,0,0); + cimg_forY(*this,y) { + cimg::fread(buf._data,W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,W); + const float *ptrs = buf._data; + cimg_forX(*this,x) *(ptrd++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return mirror('y'); // Most of the .pfm files are flipped along the y-axis + } + + //! Load image from a RGB file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(0,filename,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(filename,dimw,dimh); + } + + //! Load image from a RGB file \overloading. + CImg& load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(file,0,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(file,dimw,dimh); + } + + CImg& _load_rgb(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgb(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/3UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a RGBA file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(0,filename,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(filename,dimw,dimh); + } + + //! Load image from a RGBA file \overloading. + CImg& load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(file,0,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(file,dimw,dimh); + } + + CImg& _load_rgba(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgba(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,4); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2), + *ptr_a = data(0,0,0,3); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/4UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a TIFF file. + /** + \param filename Filename, as a C-string. + \param first_frame First frame to read (for multi-pages tiff). + \param last_frame Last frame to read (for multi-pages tiff). + \param step_frame Step value of frame reading. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + \param[out] voxel_size Voxel size, as stored in the filename. + \param[out] description Description, as stored in the filename. + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tiff is not defined at compile time the + function uses CImg& load_other(const char*). + **/ + CImg& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Specified filename is (null).", + cimg_instance); + + const unsigned int + nfirst_frame = first_frame1) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.", + cimg_instance, + filename); + return load_other(filename); +#else +#if cimg_verbosity<3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimg_instance + "load_tiff(): File '%s' contains %u image(s) while specified frame range is [%u,%u] (step %u).", + cimg_instance, + filename,nb_images,nfirst_frame,nlast_frame,nstep_frame); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + TIFFSetDirectory(tif,0); + CImg frame; + for (unsigned int l = nfirst_frame; l<=nlast_frame; l+=nstep_frame) { + frame._load_tiff(tif,l,bits_per_value,voxel_size,description); + if (l==nfirst_frame) + assign(frame._width,frame._height,1 + (nlast_frame - nfirst_frame)/nstep_frame,frame._spectrum); + if (frame._width>_width || frame._height>_height || frame._spectrum>_spectrum) + resize(std::max(frame._width,_width), + std::max(frame._height,_height),-100, + std::max(frame._spectrum,_spectrum),0); + draw_image(0,0,(l - nfirst_frame)/nstep_frame,frame); + } + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "load_tiff(): Failed to open file '%s'.", + cimg_instance, + filename); + return *this; +#endif + } + + //! Load image from a TIFF file \newinstance. + static CImg get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + return CImg().load_tiff(filename,first_frame,last_frame,step_frame,bits_per_value,voxel_size,description); + } + + // (Original contribution by Jerome Boulanger). +#ifdef cimg_use_tiff + template + void _load_tiff_tiled_contig(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int row = 0; row + void _load_tiff_tiled_separate(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int vv = 0; vv + void _load_tiff_contig(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (row = 0; rowny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, 0); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0; rr + void _load_tiff_separate(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (unsigned int vv = 0; vvny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, vv); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0;rr& _load_tiff(TIFF *const tif, const unsigned int directory, unsigned int *const bits_per_value, + float *const voxel_size, CImg *const description) { + if (!TIFFSetDirectory(tif,directory)) return assign(); + uint16 samplesperpixel = 1, bitspersample = 8, photo = 0; + uint16 sampleformat = 1; + uint32 nx = 1, ny = 1; + const char *const filename = TIFFFileName(tif); + const bool is_spp = (bool)TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel); + TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx); + TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleformat); + TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample); + TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo); + if (bits_per_value) *bits_per_value = (unsigned int)bitspersample; + if (voxel_size) { + const char *s_description = 0; + float vx = 0, vy = 0, vz = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) { + const char *s_desc = std::strstr(s_description,"VX="); + if (s_desc && cimg_sscanf(s_desc,"VX=%f VY=%f VZ=%f",&vx,&vy,&vz)==3) { // CImg format + voxel_size[0] = vx; voxel_size[1] = vy; voxel_size[2] = vz; + } + s_desc = std::strstr(s_description,"spacing="); + if (s_desc && cimg_sscanf(s_desc,"spacing=%f",&vz)==1) { // Fiji format + voxel_size[2] = vz; + } + } + TIFFGetField(tif,TIFFTAG_XRESOLUTION,voxel_size); + TIFFGetField(tif,TIFFTAG_YRESOLUTION,voxel_size + 1); + voxel_size[0] = 1.f/voxel_size[0]; + voxel_size[1] = 1.f/voxel_size[1]; + } + if (description) { + const char *s_description = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) + CImg::string(s_description).move_to(*description); + } + const unsigned int spectrum = !is_spp || photo>=3?(photo>1?3:1):samplesperpixel; + assign(nx,ny,1,spectrum); + + if ((photo>=3 && sampleformat==1 && + (bitspersample==4 || bitspersample==8) && + (samplesperpixel==1 || samplesperpixel==3 || samplesperpixel==4)) || + (bitspersample==1 && samplesperpixel==1)) { + // Special case for unsigned color images. + uint32 *const raster = (uint32*)_TIFFmalloc(nx*ny*sizeof(uint32)); + if (!raster) { + _TIFFfree(raster); TIFFClose(tif); + throw CImgException(_cimg_instance + "load_tiff(): Failed to allocate memory (%s) for file '%s'.", + cimg_instance, + cimg::strbuffersize(nx*ny*sizeof(uint32)),filename); + } + TIFFReadRGBAImage(tif,nx,ny,raster,0); + switch (spectrum) { + case 1 : + cimg_forXY(*this,x,y) + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]); + break; + case 3 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + } + break; + case 4 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny - 1 - y) + x]); + } + break; + } + _TIFFfree(raster); + } else { // Other cases + uint16 config; + TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config); + if (TIFFIsTiled(tif)) { + uint32 tw = 1, th = 1; + TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw); + TIFFGetField(tif,TIFFTAG_TILELENGTH,&th); + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + } + } else { + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + } + } + } + return *this; + } +#endif + + //! Load image from a MINC2 file. + /** + \param filename Filename, as a C-string. + **/ + // (Original code by Haz-Edine Assemlal). + CImg& load_minc2(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_minc2(): Specified filename is (null).", + cimg_instance); +#ifndef cimg_use_minc2 + return load_other(filename); +#else + minc::minc_1_reader rdr; + rdr.open(filename); + assign(rdr.ndim(1)?rdr.ndim(1):1, + rdr.ndim(2)?rdr.ndim(2):1, + rdr.ndim(3)?rdr.ndim(3):1, + rdr.ndim(4)?rdr.ndim(4):1); + if (pixel_type()==cimg::type::string()) + rdr.setup_read_byte(); + else if (pixel_type()==cimg::type::string()) + rdr.setup_read_int(); + else if (pixel_type()==cimg::type::string()) + rdr.setup_read_double(); + else + rdr.setup_read_float(); + minc::load_standard_volume(rdr,this->_data); + return *this; +#endif + } + + //! Load image from a MINC2 file \newinstance. + static CImg get_load_minc2(const char *const filename) { + return CImg().load_analyze(filename); + } + + //! Load image from an ANALYZE7.5/NIFTI file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_analyze(const char *const filename, float *const voxel_size=0) { + return _load_analyze(0,filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(const char *const filename, float *const voxel_size=0) { + return CImg().load_analyze(filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \overloading. + CImg& load_analyze(std::FILE *const file, float *const voxel_size=0) { + return _load_analyze(file,0,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(std::FILE *const file, float *const voxel_size=0) { + return CImg().load_analyze(file,voxel_size); + } + + CImg& _load_analyze(std::FILE *const file, const char *const filename, float *const voxel_size=0) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_analyze(): Specified filename is (null).", + cimg_instance); + + std::FILE *nfile_header = 0, *nfile = 0; + if (!file) { + CImg body(1024); + const char *const ext = cimg::split_filename(filename,body); + if (!cimg::strcasecmp(ext,"hdr")) { // File is an Analyze header file + nfile_header = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".img"); + nfile = cimg::fopen(body,"rb"); + } else if (!cimg::strcasecmp(ext,"img")) { // File is an Analyze data file + nfile = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".hdr"); + nfile_header = cimg::fopen(body,"rb"); + } else nfile_header = nfile = cimg::fopen(filename,"rb"); // File is a Niftii file + } else nfile_header = nfile = file; // File is a Niftii file + if (!nfile || !nfile_header) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid Analyze7.5 or NIFTI header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + // Read header. + bool endian = false; + unsigned int header_size; + cimg::fread(&header_size,1,nfile_header); + if (!header_size) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid zero-size header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (header_size>=4096) { endian = true; cimg::invert_endianness(header_size); } + + unsigned char *const header = new unsigned char[header_size]; + cimg::fread(header + 4,header_size - 4,nfile_header); + if (!file && nfile_header!=nfile) cimg::fclose(nfile_header); + if (endian) { + cimg::invert_endianness((short*)(header + 40),5); + cimg::invert_endianness((short*)(header + 70),1); + cimg::invert_endianness((short*)(header + 72),1); + cimg::invert_endianness((float*)(header + 76),4); + cimg::invert_endianness((float*)(header + 108),1); + cimg::invert_endianness((float*)(header + 112),1); + } + + if (nfile_header==nfile) { + const unsigned int vox_offset = (unsigned int)*(float*)(header + 108); + std::fseek(nfile,vox_offset,SEEK_SET); + } + + unsigned short *dim = (unsigned short*)(header + 40), dimx = 1, dimy = 1, dimz = 1, dimv = 1; + if (!dim[0]) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with zero dimensions.", + cimg_instance, + filename?filename:"(FILE*)"); + + if (dim[0]>4) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with %u dimensions, reading only the 4 first.", + cimg_instance, + filename?filename:"(FILE*)",dim[0]); + + if (dim[0]>=1) dimx = dim[1]; + if (dim[0]>=2) dimy = dim[2]; + if (dim[0]>=3) dimz = dim[3]; + if (dim[0]>=4) dimv = dim[4]; + float scalefactor = *(float*)(header + 112); if (scalefactor==0) scalefactor = 1; + const unsigned short datatype = *(unsigned short*)(header + 70); + if (voxel_size) { + const float *vsize = (float*)(header + 76); + voxel_size[0] = vsize[1]; voxel_size[1] = vsize[2]; voxel_size[2] = vsize[3]; + } + delete[] header; + + // Read pixel data. + assign(dimx,dimy,dimz,dimv); + const size_t pdim = (size_t)dimx*dimy*dimz*dimv; + switch (datatype) { + case 2 : { + unsigned char *const buffer = new unsigned char[pdim]; + cimg::fread(buffer,pdim,nfile); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 4 : { + short *const buffer = new short[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 8 : { + int *const buffer = new int[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 16 : { + float *const buffer = new float[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 64 : { + double *const buffer = new double[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_analyze(): Unable to load datatype %d in file '%s'", + cimg_instance, + datatype,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a .cimg[z] file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(const char *const filename, const char axis='z', const float align=0) { + return CImg().load_cimg(filename,axis,align); + } + + //! Load image from a .cimg[z] file \overloading. + CImg& load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + return CImg().load_cimg(file,axis,align); + } + + //! Load sub-images of a .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Starting frame. + \param n1 Ending frame (~0U for max). + \param x0 X-coordinate of the starting sub-image vertex. + \param y0 Y-coordinate of the starting sub-image vertex. + \param z0 Z-coordinate of the starting sub-image vertex. + \param c0 C-coordinate of the starting sub-image vertex. + \param x1 X-coordinate of the ending sub-image vertex (~0U for max). + \param y1 Y-coordinate of the ending sub-image vertex (~0U for max). + \param z1 Z-coordinate of the ending sub-image vertex (~0U for max). + \param c1 C-coordinate of the ending sub-image vertex (~0U for max). + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load sub-images of a .cimg file \overloading. + CImg& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load image from an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_inr(const char *const filename, float *const voxel_size=0) { + return _load_inr(0,filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(const char *const filename, float *const voxel_size=0) { + return CImg().load_inr(filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \overloading. + CImg& load_inr(std::FILE *const file, float *const voxel_size=0) { + return _load_inr(file,0,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(std::FILE *const file, float *voxel_size=0) { + return CImg().load_inr(file,voxel_size); + } + + static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) { + CImg item(1024), tmp1(64), tmp2(64); + *item = *tmp1 = *tmp2 = 0; + out[0] = std::fscanf(file,"%63s",item._data); + out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1; + if (cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0) + throw CImgIOException("CImg<%s>::load_inr(): INRIMAGE-4 header not found.", + pixel_type()); + + while (std::fscanf(file," %63[^\n]%*c",item._data)!=EOF && std::strncmp(item,"##}",3)) { + cimg_sscanf(item," XDIM%*[^0-9]%d",out); + cimg_sscanf(item," YDIM%*[^0-9]%d",out + 1); + cimg_sscanf(item," ZDIM%*[^0-9]%d",out + 2); + cimg_sscanf(item," VDIM%*[^0-9]%d",out + 3); + cimg_sscanf(item," PIXSIZE%*[^0-9]%d",out + 6); + if (voxel_size) { + cimg_sscanf(item," VX%*[^0-9.+-]%f",voxel_size); + cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1); + cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2); + } + if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1; + switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) { + case 0 : break; + case 2 : + out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; + std::strncpy(tmp1,tmp2,tmp1._width - 1); // fallthrough + case 1 : + if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5)) out[4] = 0; + if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1; + if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2; + if (out[4]>=0) break; // fallthrough + default : + throw CImgIOException("CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.", + pixel_type(), + tmp2._data); + } + } + if (out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0) + throw CImgIOException("CImg<%s>::load_inr(): Invalid dimensions (%d,%d,%d,%d) defined in header.", + pixel_type(), + out[0],out[1],out[2],out[3]); + if (out[4]<0 || out[5]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete pixel type defined in header.", + pixel_type()); + if (out[6]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete PIXSIZE field defined in header.", + pixel_type()); + if (out[7]<0) + throw CImgIOException("CImg<%s>::load_inr(): Big/Little Endian coding type undefined in header.", + pixel_type()); + } + + CImg& _load_inr(std::FILE *const file, const char *const filename, float *const voxel_size) { +#define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \ + if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \ + Ts *xval, *const val = new Ts[(size_t)fopt[0]*fopt[3]]; \ + cimg_forYZ(*this,y,z) { \ + cimg::fread(val,fopt[0]*fopt[3],nfile); \ + if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \ + xval = val; cimg_forX(*this,x) cimg_forC(*this,c) (*this)(x,y,z,c) = (T)*(xval++); \ + } \ + delete[] val; \ + loaded = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_inr(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + int fopt[8], endian = cimg::endianness()?1:0; + bool loaded = false; + if (voxel_size) voxel_size[0] = voxel_size[1] = voxel_size[2] = 1; + _load_inr_header(nfile,fopt,voxel_size); + assign(fopt[0],fopt[1],fopt[2],fopt[3]); + _cimg_load_inr_case(0,0,8,unsigned char); + _cimg_load_inr_case(0,1,8,char); + _cimg_load_inr_case(0,0,16,unsigned short); + _cimg_load_inr_case(0,1,16,short); + _cimg_load_inr_case(0,0,32,unsigned int); + _cimg_load_inr_case(0,1,32,int); + _cimg_load_inr_case(1,0,32,float); + _cimg_load_inr_case(1,1,32,float); + _cimg_load_inr_case(1,0,64,double); + _cimg_load_inr_case(1,1,64,double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_inr(): Unknown pixel type defined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a EXR file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_exr(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_exr(): Specified filename is (null).", + cimg_instance); +#if defined(cimg_use_openexr) + Imf::RgbaInputFile file(filename); + Imath::Box2i dw = file.dataWindow(); + const int + inwidth = dw.max.x - dw.min.x + 1, + inheight = dw.max.y - dw.min.y + 1; + Imf::Array2D pixels; + pixels.resizeErase(inheight,inwidth); + file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y*inwidth, 1, inwidth); + file.readPixels(dw.min.y, dw.max.y); + assign(inwidth,inheight,1,4); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + cimg_forXY(*this,x,y) { + *(ptr_r++) = (T)pixels[y][x].r; + *(ptr_g++) = (T)pixels[y][x].g; + *(ptr_b++) = (T)pixels[y][x].b; + *(ptr_a++) = (T)pixels[y][x].a; + } + return *this; +#elif defined(cimg_use_tinyexr) + float *res; + const char *err = 0; + int width = 0, height = 0; + const int ret = LoadEXR(&res,&width,&height,filename,&err); + if (ret) throw CImgIOException(_cimg_instance + "load_exr(): Unable to load EXR file '%s'.", + cimg_instance,filename); + CImg(res,4,width,height,1,true).get_permute_axes("yzcx").move_to(*this); + std::free(res); + return *this; +#else + return load_other(filename); +#endif + } + + //! Load image from a EXR file \newinstance. + static CImg get_load_exr(const char *const filename) { + return CImg().load_exr(filename); + } + + //! Load image from a PANDORE-5 file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pandore(const char *const filename) { + return _load_pandore(0,filename); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(const char *const filename) { + return CImg().load_pandore(filename); + } + + //! Load image from a PANDORE-5 file \overloading. + CImg& load_pandore(std::FILE *const file) { + return _load_pandore(file,0); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(std::FILE *const file) { + return CImg().load_pandore(file); + } + + CImg& _load_pandore(std::FILE *const file, const char *const filename) { +#define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \ + cimg::fread(dims,nbdim,nfile); \ + if (endian) cimg::invert_endianness(dims,nbdim); \ + assign(nwidth,nheight,ndepth,ndim); \ + const size_t siz = size(); \ + stype *buffer = new stype[siz]; \ + cimg::fread(buffer,siz,nfile); \ + if (endian) cimg::invert_endianness(buffer,siz); \ + T *ptrd = _data; \ + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \ + buffer-=siz; \ + delete[] buffer + +#define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \ + if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \ + else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \ + else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \ + else throw CImgIOException(_cimg_instance \ + "load_pandore(): Unknown pixel datatype in file '%s'.", \ + cimg_instance, \ + filename?filename:"(FILE*)"); } + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pandore(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(32); + cimg::fread(header._data,12,nfile); + if (cimg::strncasecmp("PANDORE",header,7)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): PANDORE header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + unsigned int imageid, dims[8] = { 0 }; + int ptbuf[4] = { 0 }; + cimg::fread(&imageid,1,nfile); + const bool endian = imageid>255; + if (endian) cimg::invert_endianness(imageid); + cimg::fread(header._data,20,nfile); + + switch (imageid) { + case 2 : _cimg_load_pandore_case(2,dims[1],1,1,1,unsigned char,unsigned char,unsigned char,1); break; + case 3 : _cimg_load_pandore_case(2,dims[1],1,1,1,long,int,short,4); break; + case 4 : _cimg_load_pandore_case(2,dims[1],1,1,1,double,float,float,4); break; + case 5 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,unsigned char,unsigned char,unsigned char,1); break; + case 6 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,long,int,short,4); break; + case 7 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,double,float,float,4); break; + case 8 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,unsigned char,unsigned char,unsigned char,1); break; + case 9 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,long,int,short,4); break; + case 10 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,double,float,float,4); break; + case 11 : { // Region 1D + cimg::fread(dims,3,nfile); + if (endian) cimg::invert_endianness(dims,3); + assign(dims[1],1,1,1); + const unsigned siz = size(); + if (dims[2]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[2]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 12 : { // Region 2D + cimg::fread(dims,4,nfile); + if (endian) cimg::invert_endianness(dims,4); + assign(dims[2],dims[1],1,1); + const size_t siz = size(); + if (dims[3]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[3]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 13 : { // Region 3D + cimg::fread(dims,5,nfile); + if (endian) cimg::invert_endianness(dims,5); + assign(dims[3],dims[2],dims[1],1); + const size_t siz = size(); + if (dims[4]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[4]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 16 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,unsigned char,unsigned char,unsigned char,1); break; + case 17 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,long,int,short,4); break; + case 18 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,double,float,float,4); break; + case 19 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,unsigned char,unsigned char,unsigned char,1); break; + case 20 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,long,int,short,4); break; + case 21 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,double,float,float,4); break; + case 22 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 23 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],long,int,short,4); break; + case 24 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 25 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],double,float,float,4); break; + case 26 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 27 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],long,int,short,4); break; + case 28 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 29 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],double,float,float,4); break; + case 30 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned char,unsigned char,unsigned char,1); + break; + case 31 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],long,int,short,4); break; + case 32 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned long,unsigned int,unsigned short,4); + break; + case 33 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break; + case 34 : { // Points 1D + cimg::fread(ptbuf,1,nfile); + if (endian) cimg::invert_endianness(ptbuf,1); + assign(1); (*this)(0) = (T)ptbuf[0]; + } break; + case 35 : { // Points 2D + cimg::fread(ptbuf,2,nfile); + if (endian) cimg::invert_endianness(ptbuf,2); + assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0]; + } break; + case 36 : { // Points 3D + cimg::fread(ptbuf,3,nfile); + if (endian) cimg::invert_endianness(ptbuf,3); + assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0]; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): Unable to load data with ID_type %u in file '%s'.", + cimg_instance, + imageid,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PAR-REC (Philips) file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_parrec(const char *const filename, const char axis='c', const float align=0) { + CImgList list; + list.load_parrec(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a PAR-REC (Philips) file \newinstance. + static CImg get_load_parrec(const char *const filename, const char axis='c', const float align=0) { + return CImg().load_parrec(filename,axis,align); + } + + //! Load image from a raw binary file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the image buffer. + \param size_y Height of the image buffer. + \param size_z Depth of the image buffer. + \param size_c Spectrum of the image buffer. + \param is_multiplexed Tells if the image values are multiplexed along the C-axis. + \param invert_endianness Tells if the endianness of the image buffer must be inverted. + \param offset Starting offset of the read in the specified file. + **/ + CImg& load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(0,filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \overloading. + CImg& load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(file,0,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(file,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + CImg& _load_raw(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const bool is_multiplexed, const bool invert_endianness, + const ulongT offset) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename is (null).", + cimg_instance); + if (cimg::is_directory(filename)) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename '%s' is a directory.", + cimg_instance,filename); + const bool is_bool = pixel_type()==cimg::type::string(); + ulongT siz = (ulongT)size_x*size_y*size_z*size_c; + unsigned int + _size_x = size_x, + _size_y = size_y, + _size_z = size_z, + _size_c = size_c; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + if (!siz) { // Retrieve file size + const longT fpos = cimg::ftell(nfile); + if (fpos<0) throw CImgArgumentException(_cimg_instance + "load_raw(): Cannot determine size of input file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + cimg::fseek(nfile,0,SEEK_END); + siz = (ulongT)cimg::ftell(nfile); + if (!is_bool) { siz/=sizeof(T); _size_y = (unsigned int)siz; } + else _size_y = (unsigned int)(siz*8); + _size_x = _size_z = _size_c = 1; + cimg::fseek(nfile,fpos,SEEK_SET); + } + cimg::fseek(nfile,(longT)offset,SEEK_SET); + assign(_size_x,_size_y,_size_z,_size_c,0); + + if (is_bool) { // Boolean data (bitwise) + unsigned char *const buf = new unsigned char[siz]; + cimg::fread(buf,siz,nfile); + _uchar2bool(buf,siz,is_multiplexed); + delete[] buf; + } else { // Non-boolean data + if (siz && (!is_multiplexed || size_c==1)) { // Non-multiplexed + cimg::fread(_data,siz,nfile); + if (invert_endianness) cimg::invert_endianness(_data,siz); + } else if (siz) { // Multiplexed + CImg buf(1,1,1,_size_c); + cimg_forXYZ(*this,x,y,z) { + cimg::fread(buf._data,_size_c,nfile); + if (invert_endianness) cimg::invert_endianness(buf._data,_size_c); + set_vector_at(buf,x,y,z); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image sequence from a YUV file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the frames. + \param size_y Height of the frames. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param yuv2rgb Tells if the YUV to RGB transform must be applied. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + **/ + CImg& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load image sequence from a YUV file \overloading. + CImg& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load 3D object from a .OFF file. + /** + \param[out] primitives Primitives data of the 3D object. + \param[out] colors Colors data of the 3D object. + \param filename Filename, as a C-string. + **/ + template + CImg& load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return _load_off(primitives,colors,0,filename); + } + + //! Load 3D object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return CImg().load_off(primitives,colors,filename); + } + + //! Load 3D object from a .OFF file \overloading. + template + CImg& load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return _load_off(primitives,colors,file,0); + } + + //! Load 3D object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return CImg().load_off(primitives,colors,file); + } + + template + CImg& _load_off(CImgList& primitives, CImgList& colors, + std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_off(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + unsigned int nb_points = 0, nb_primitives = 0, nb_read = 0; + CImg line(256); *line = 0; + int err; + + // Skip comments, and read magic string OFF + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if (cimg::strncasecmp(line,"OFF",3) && cimg::strncasecmp(line,"COFF",4)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): OFF header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%u%u%*[^\n] ",&nb_points,&nb_primitives))!=2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Invalid number of vertices or primitives specified in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read points data + assign(nb_points,3); + float X = 0, Y = 0, Z = 0; + cimg_forX(*this,l) { + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%f%f%f%*[^\n] ",&X,&Y,&Z))!=3) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Failed to read vertex %u/%u in file '%s'.", + cimg_instance, + l + 1,nb_points,filename?filename:"(FILE*)"); + } + (*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z; + } + + // Read primitive data + primitives.assign(); + colors.assign(); + bool stop_flag = false; + while (!stop_flag) { + float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f; + unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0; + *line = 0; + if ((err = std::fscanf(nfile,"%u",&prim))!=1) stop_flag = true; + else { + ++nb_read; + switch (prim) { + case 1 : { + if ((err = std::fscanf(nfile,"%u%255[^\n] ",&i0,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 2 : { + if ((err = std::fscanf(nfile,"%u%u%255[^\n] ",&i0,&i1,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 3 : { + if ((err = std::fscanf(nfile,"%u%u%u%255[^\n] ",&i0,&i1,&i2,line._data))<3) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 4 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,line._data))<4) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 5 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,line._data))<5) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 6 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,line._data))<6) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 7 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i4,i3,i1).move_to(primitives); + CImg::vector(i0,i6,i5,i4).move_to(primitives); + CImg::vector(i3,i2,i1).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + case 8 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + CImg::vector(i0,i7,i6,i5).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + default : + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.", + cimg_instance, + nb_read,nb_primitives,prim,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } + } + } + if (!file) cimg::fclose(nfile); + if (primitives._width!=nb_primitives) + cimg::warn(_cimg_instance + "load_off(): Only %u/%u primitives read from file '%s'.", + cimg_instance, + primitives._width,nb_primitives,filename?filename:"(FILE*)"); + return *this; + } + + //! Load image sequence from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param axis Alignment axis. + \param align Appending alignment. + **/ + CImg& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return get_load_video(filename,first_frame,last_frame,step_frame,axis,align).move_to(*this); + } + + //! Load image sequence from a video file, using OpenCV library \newinstance. + static CImg get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame).get_append(axis,align); + } + + //! Load image sequence using custom's external tool 'custom'. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_custom_external(const char *const filename, const char axis='z', const float align=0) { + return get_load_custom_external(filename,axis,align).move_to(*this); + } + + //! Load image sequence using custom's external tool 'custom' \newinstance. + static CImg get_load_custom_external(const char *const filename, const char axis='z', const float align=0) { + return CImgList().load_custom_external(filename).get_append(axis,align); + } + + //! Load gif file, using Imagemagick or GraphicsMagicks's external tools. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return get_load_gif_external(filename,axis,align).move_to(*this); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tool 'convert' \newinstance. + static CImg get_load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return CImgList().load_gif_external(filename).get_append(axis,align); + } + + //! Load image from a HEIC file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_heif(const char *const filename) { + return _load_heif(filename); + } + + //! Load image from a HEIC file \newinstance. + static CImg get_load_heif(const char *const filename) { + return CImg().load_heif(filename); + } + + CImg& _load_heif(const char *const filename) { +#ifndef cimg_use_heif + return load_other(filename); +#else + try { + heif::Context ctx; + ctx.read_from_file(filename); + + heif::ImageHandle handle = ctx.get_primary_image_handle(); + const heif::Image image = + handle.decode_image(heif_colorspace_RGB,handle.has_alpha_channel()?heif_chroma_interleaved_RGBA: + heif_chroma_interleaved_RGB); + const int + W = image.get_width(heif_channel_interleaved), + H = image.get_height(heif_channel_interleaved), + S = handle.has_alpha_channel()?4:3; + assign(W,H,1,S); + + int stride; + const unsigned char *const buffer = image.get_plane(heif_channel_interleaved,&stride); + T *ptr_r = _data, *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = S>3?data(0,0,0,3):0; + cimg_forY(*this,y) { + const unsigned char *ptrs = buffer + y*stride; + if (ptr_a) cimg_forX(*this,x) { // RGBA + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + else cimg_forX(*this,x) { // RGB + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } catch (const heif::Error& e) { + throw CImgInstanceException(_cimg_instance + "load_heif(): Unable to decode image: %s", + cimg_instance, + e.get_message().c_str()); + } catch (...) { + throw; + } + return *this; +#endif + } + + //! Load image using GraphicsMagick's external tool 'gm'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_graphicsmagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + if (!cimg::system("which gm")) { + cimg_snprintf(command,command._width,"%s convert \"%s\" %s:-", + cimg::graphicsmagick_path(), + s_filename.data(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { +#ifdef cimg_use_png + load_png(file); +#else + load_pnm(file); +#endif + } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' " + "with external command 'gm'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(), + cimg_file_separator, + cimg::filenamerand(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" convert \"%s\" \"%s\"", + cimg::graphicsmagick_path(), + s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::graphicsmagick_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.", + cimg_instance, + filename); + + } else cimg::fclose(file); +#ifdef cimg_use_png + load_png(filename_tmp); +#else + load_pnm(filename_tmp); +#endif + std::remove(filename_tmp); + return *this; + } + + //! Load image using GraphicsMagick's external tool 'gm' \newinstance. + static CImg get_load_graphicsmagick_external(const char *const filename) { + return CImg().load_graphicsmagick_external(filename); + } + + //! Load gzipped image file, using external tool 'gunzip'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimg_instance + "load_gzip_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + const char + *const ext = cimg::split_filename(filename,body), + *const ext2 = cimg::split_filename(body,0); + + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_gzip_external(): Failed to load file '%s' with external command 'gunzip'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load gzipped image file, using external tool 'gunzip' \newinstance. + static CImg get_load_gzip_external(const char *const filename) { + return CImg().load_gzip_external(filename); + } + + //! Load image using ImageMagick's external tool 'convert'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_imagemagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_imagemagick_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + if (!cimg::system("which convert")) { + cimg_snprintf(command,command._width,"%s%s \"%s\" %s:-", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { +#ifdef cimg_use_png + load_png(file); +#else + load_pnm(file); +#endif + } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(), + cimg_file_separator, + cimg::filenamerand(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\"%s \"%s\" \"%s\"", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::imagemagick_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + + } else cimg::fclose(file); +#ifdef cimg_use_png + load_png(filename_tmp); +#else + load_pnm(filename_tmp); +#endif + std::remove(filename_tmp); + return *this; + } + + //! Load image using ImageMagick's external tool 'convert' \newinstance. + static CImg get_load_imagemagick_external(const char *const filename) { + return CImg().load_imagemagick_external(filename); + } + + //! Load image from a DICOM file, using Medcon's external tool 'medcon'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_medcon_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_medcon_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + cimg::fclose(cimg::fopen(filename,"r")); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -w -c anlz -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::medcon_path()); + cimg::split_filename(filename_tmp,body); + + cimg_snprintf(command,command._width,"%s.hdr",body._data); + file = cimg::std_fopen(command,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s.hdr",body._data); + file = cimg::std_fopen(command,"rb"); + if (!file) { + throw CImgIOException(_cimg_instance + "load_medcon_external(): Failed to load file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + load_analyze(command); + std::remove(command); + cimg::split_filename(command,body); + cimg_snprintf(command,command._width,"%s.img",body._data); + std::remove(command); + return *this; + } + + //! Load image from a DICOM file, using Medcon's external tool 'medcon' \newinstance. + static CImg get_load_medcon_external(const char *const filename) { + return CImg().load_medcon_external(filename); + } + + //! Load image from a .pdf file. + /** + \param filename Filename, as a C-string. + \param resolution Image resolution. + **/ + CImg& load_pdf_external(const char *const filename, const unsigned int resolution=400) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_pdf_external(): Specified filename is (null).", + cimg_instance); + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o - -r%u \"%s\"", + resolution,s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_pdf_external(): Failed to load file '%s' with external command 'gs'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o \"%s\" -r%u \"%s\"", + CImg::string(filename_tmp)._system_strescape().data(),resolution,s_filename.data()); + cimg::system(command,"gs"); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_pdf_external(): Failed to load file '%s' with external command 'gs'.", + cimg_instance, + filename); + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a .pdf file \newinstance. + static CImg get_load_pdf_external(const char *const filename, const unsigned int resolution=400) { + return CImg().load_pdf_external(filename,resolution); + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_dcraw_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_dcraw_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"%s -w -4 -c \"%s\"", + cimg::dcraw_path(),s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -w -4 -c \"%s\" > \"%s\"", + cimg::dcraw_path(),s_filename.data(),CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::dcraw_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw' \newinstance. + static CImg get_load_dcraw_external(const char *const filename) { + return CImg().load_dcraw_external(filename); + } + +#ifdef cimg_use_opencv + + // Convert a continuous cv::Mat to a CImg. + static CImg _cvmat2cimg(const cv::Mat &src) { + if (src.channels()==1) return CImg(src.ptr(),src.cols,src.rows,1,1); + else if (src.channels()==3) { // BGR + CImg res(src.cols,src.rows,1,src.channels()); + const unsigned char *ptrs = src.ptr(); + unsigned char *pR = res.data(), *pG = res.data(0,0,0,1), *pB = res.data(0,0,0,2); + cimg_forXY(res,x,y) { *(pB++) = *(ptrs++); *(pG++) = *(ptrs++); *(pR++) = *(ptrs++); } + return res; + } + return CImg(src.ptr(),src.channels(),src.cols,src.rows,1,true).get_permute_axes("yzcx"); + } + + // Convert a CImg to a cv::Mat. + cv::Mat _cimg2cvmat() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Instance image is empty.", + cimg_instance); + if (_spectrum==2) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Invalid number of channels (should be '1' or '3+').", + cimg_instance); + if (_depth!=1) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Invalid number of slices (should be '1').", + cimg_instance); + int mat_type = -1; + if (pixel_type()==cimg::type::string()) mat_type = CV_8UC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_8SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_16UC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_16SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_32SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_32FC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_64FC1; + if (mat_type<0) + throw CImgInstanceException(_cimg_instance + "_cvmat2cimg() : pixel type '%s' is not supported.", + cimg_instance,pixel_type()); + cv::Mat res; + std::vector channels(_spectrum); + if (_spectrum>1) { + cimg_forC(*this,c) + channels[c] = cv::Mat(_height,_width,mat_type,_data + _width*_height*(_spectrum - 1 - c)); + cv::merge(channels,res); + } else res = cv::Mat(_height,_width,mat_type,_data).clone(); + return res; + } + +#endif + + //! Load image from a camera stream, using OpenCV. + /** + \param index Index of the camera to capture images from (from 0 to 63). + \param capture_width Width of the desired image ('0' stands for default value). + \param capture_height Height of the desired image ('0' stands for default value). + \param skip_frames Number of frames to skip before the capture. + \param release_camera Tells if the camera resource must be released at the end of the method. + **/ + CImg& load_camera(const unsigned int camera_index=0, + const unsigned int capture_width=0, const unsigned int capture_height=0, + const unsigned int skip_frames=0, const bool release_camera=true) { +#ifdef cimg_use_opencv + if (camera_index>=64) + throw CImgArgumentException(_cimg_instance + "load_camera(): Invalid request for camera #%u " + "(no more than 100 cameras can be managed simultaneously).", + cimg_instance, + camera_index); + static cv::VideoCapture *captures[64] = { 0 }; + static unsigned int captures_w[64], captures_h[64]; + if (release_camera) { + cimg::mutex(9); + if (captures[camera_index]) captures[camera_index]->release(); + delete captures[camera_index]; + captures[camera_index] = 0; + captures_w[camera_index] = captures_h[camera_index] = 0; + cimg::mutex(9,0); + return *this; + } + if (!captures[camera_index]) { + cimg::mutex(9); + captures[camera_index] = new cv::VideoCapture(camera_index); + captures_w[camera_index] = captures_h[camera_index] = 0; + if (!captures[camera_index]->isOpened()) { + delete captures[camera_index]; + captures[camera_index] = 0; + cimg::mutex(9,0); + throw CImgIOException(_cimg_instance + "load_camera(): Failed to initialize camera #%u.", + cimg_instance, + camera_index); + } + cimg::mutex(9,0); + } + cimg::mutex(9); + if (capture_width!=captures_w[camera_index]) { + captures[camera_index]->set(_cimg_cap_prop_frame_width,capture_width); + captures_w[camera_index] = capture_width; + } + if (capture_height!=captures_h[camera_index]) { + captures[camera_index]->set(_cimg_cap_prop_frame_height,capture_height); + captures_h[camera_index] = capture_height; + } + for (unsigned int i = 0; igrab(); + cv::Mat cvimg; + captures[camera_index]->read(cvimg); + if (cvimg.empty()) assign(); else _cvmat2cimg(cvimg).move_to(*this); + cimg::mutex(9,0); + return *this; +#else + cimg::unused(camera_index,skip_frames,release_camera,capture_width,capture_height); + throw CImgIOException(_cimg_instance + "load_camera(): This function requires features from the OpenCV library " + "('-Dcimg_use_opencv' must be defined).", + cimg_instance); +#endif + } + + //! Load image from a camera stream, using OpenCV \newinstance. + static CImg get_load_camera(const unsigned int camera_index=0, + const unsigned int capture_width=0, const unsigned int capture_height=0, + const unsigned int skip_frames=0, const bool release_camera=true) { + return CImg().load_camera(camera_index,capture_width,capture_height,skip_frames,release_camera); + } + + //! Load image using various non-native ways. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_other(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_other(): Specified filename is (null).", + cimg_instance); + + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_magick(filename); } + catch (CImgException&) { + try { load_imagemagick_external(filename); } + catch (CImgException&) { + try { load_graphicsmagick_external(filename); } + catch (CImgException&) { + try { load_cimg(filename); } + catch (CImgException&) { + try { + cimg::fclose(cimg::fopen(filename,"rb")); + } catch (CImgException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to open file '%s'.", + cimg_instance, + filename); + } + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image using various non-native ways \newinstance. + static CImg get_load_other(const char *const filename) { + return CImg().load_other(filename); + } + + //@} + //--------------------------- + // + //! \name Data Output + //@{ + //--------------------------- + + //! Display information about the image data. + /** + \param title Name for the considered image. + \param display_stats Tells to compute and display image statistics. + **/ + const CImg& print(const char *const title=0, const bool display_stats=true) const { + + int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0; + CImg st; + if (!is_empty() && display_stats) { + st = get_stats(); + xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7]; + xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11]; + } + + const ulongT siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1, + mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U, width1 = _width - 1; + + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImg<%s>",pixel_type()); + + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p", + cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal, + cimg::t_bold,cimg::t_normal,(void*)this, + cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum, + (unsigned long)(mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20))), + mdisp==0?"b":(mdisp==1?"Kio":"Mio"), + cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin()); + if (_data) + std::fprintf(cimg::output(),"..%p (%s) = [ ",(void*)((char*)end() - 1),_is_shared?"shared":"non-shared"); + else std::fprintf(cimg::output()," (%s) = [ ",_is_shared?"shared":"non-shared"); + + if (!is_empty()) cimg_foroff(*this,off) { + std::fprintf(cimg::output(),"%g",(double)_data[off]); + if (off!=siz1) std::fprintf(cimg::output(),"%s",off%_width==width1?" ; ":" "); + if (off==7 && siz>16) { off = siz1 - 8; std::fprintf(cimg::output(),"... "); } + } + if (!is_empty() && display_stats) + std::fprintf(cimg::output(), + " ], %smin%s = %g, %smax%s = %g, %smean%s = %g, %sstd%s = %g, %scoords_min%s = (%u,%u,%u,%u), " + "%scoords_max%s = (%u,%u,%u,%u).\n", + cimg::t_bold,cimg::t_normal,st[0], + cimg::t_bold,cimg::t_normal,st[1], + cimg::t_bold,cimg::t_normal,st[2], + cimg::t_bold,cimg::t_normal,std::sqrt(st[3]), + cimg::t_bold,cimg::t_normal,xm,ym,zm,vm, + cimg::t_bold,cimg::t_normal,xM,yM,zM,vM); + else std::fprintf(cimg::output(),"%s].\n",is_empty()?"":" "); + std::fflush(cimg::output()); + return *this; + } + + //! Display image into a CImgDisplay window. + /** + \param disp Display window. + **/ + const CImg& display(CImgDisplay& disp) const { + disp.display(*this); + return *this; + } + + //! Display image into a CImgDisplay window, in an interactive way. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + return _display(disp,0,display_info,XYZ,exit_on_anykey,false); + } + + //! Display image into an interactive window. + /** + \param title Window title + \param display_info Tells if image information are displayed on the standard output. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display(disp,title,display_info,XYZ,exit_on_anykey,false); + } + + const CImg& _display(CImgDisplay &disp, const char *const title, const bool display_info, + unsigned int *const XYZ, const bool exit_on_anykey, + const bool exit_on_singleclick) const { + unsigned int oldw = 0, oldh = 0, _XYZ[3] = { 0 }, key = 0; + int x0 = 0, y0 = 0, z0 = 0, x1 = width() - 1, y1 = height() - 1, z1 = depth() - 1, + old_mouse_x = -1, old_mouse_y = -1; + + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + else disp.set_title("%s",title); + } else if (title) disp.set_title("%s",title); + disp.show().flush(); + + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(dtitle); + + CImg zoom; + for (bool reset_view = true, resize_disp = false, is_first_select = true; !key && !disp.is_closed(); ) { + if (reset_view) { + if (XYZ) { _XYZ[0] = XYZ[0]; _XYZ[1] = XYZ[1]; _XYZ[2] = XYZ[2]; } + else { + _XYZ[0] = (unsigned int)(x0 + x1 + 1)/2; + _XYZ[1] = (unsigned int)(y0 + y1 + 1)/2; + _XYZ[2] = (unsigned int)(z0 + z1 + 1)/2; + } + x0 = 0; y0 = 0; z0 = 0; x1 = width() - 1; y1 = height() - 1; z1 = depth() - 1; + disp.resize(cimg_fitscreen(_width,_height,_depth),false); + oldw = disp._width; oldh = disp._height; + resize_disp = true; + reset_view = false; + } + if (!x0 && !y0 && !z0 && x1==width() - 1 && y1==height() - 1 && z1==depth() - 1) { + if (is_empty()) zoom.assign(1,1,1,1,(T)0); else zoom.assign(); + } else zoom = get_crop(x0,y0,z0,x1,y1,z1); + + const CImg& visu = zoom?zoom:*this; + const unsigned int + dx = 1U + x1 - x0, dy = 1U + y1 - y0, dz = 1U + z1 - z0, + tw = dx + (dz>1?dz:0U), th = dy + (dz>1?dz:0U); + if (!is_empty() && !disp.is_fullscreen() && resize_disp) { + const float + ttw = (float)tw*disp.width()/oldw, tth = (float)th*disp.height()/oldh, + dM = std::max(ttw,tth), diM = (float)std::max(disp.width(),disp.height()); + const unsigned int + imgw = (unsigned int)(ttw*diM/dM), imgh = (unsigned int)(tth*diM/dM); + disp.set_fullscreen(false).resize(cimg_fitscreen(imgw,imgh,1),false); + resize_disp = false; + } + oldw = tw; oldh = th; + + bool + go_up = false, go_down = false, go_left = false, go_right = false, + go_inc = false, go_dec = false, go_in = false, go_out = false, + go_in_center = false; + + disp.set_title("%s",dtitle._data); + if (_width>1 && visu._width==1) disp.set_title("%s | x=%u",disp._title,x0); + if (_height>1 && visu._height==1) disp.set_title("%s | y=%u",disp._title,y0); + if (_depth>1 && visu._depth==1) disp.set_title("%s | z=%u",disp._title,z0); + + disp._mouse_x = old_mouse_x; disp._mouse_y = old_mouse_y; + CImg selection = visu._select(disp,0,2,_XYZ,x0,y0,z0,true,is_first_select,_depth>1,true); + old_mouse_x = disp._mouse_x; old_mouse_y = disp._mouse_y; + is_first_select = false; + + if (disp.wheel()) { + if ((disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) && + (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT())) { + go_left = !(go_right = disp.wheel()>0); + } else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) { + go_down = !(go_up = disp.wheel()>0); + } else if (depth()==1 || disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + go_out = !(go_in = disp.wheel()>0); go_in_center = false; + } + disp.set_wheel(); + } + + const int + sx0 = selection(0), sy0 = selection(1), sz0 = selection(2), + sx1 = selection(3), sy1 = selection(4), sz1 = selection(5); + if (sx0>=0 && sy0>=0 && sz0>=0 && sx1>=0 && sy1>=0 && sz1>=0) { + x1 = x0 + sx1; y1 = y0 + sy1; z1 = z0 + sz1; + x0+=sx0; y0+=sy0; z0+=sz0; + if ((sx0==sx1 && sy0==sy1) || (_depth>1 && sx0==sx1 && sz0==sz1) || (_depth>1 && sy0==sy1 && sz0==sz1)) { + if (exit_on_singleclick && (!zoom || is_empty())) break; else reset_view = true; + } + resize_disp = true; + } else switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : key = 0; break; + case cimg::keyP : if (visu._depth>1 && (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT())) { + // Special mode: play stack of frames + const unsigned int + w1 = visu._width*disp.width()/(visu._width + (visu._depth>1?visu._depth:0)), + h1 = visu._height*disp.height()/(visu._height + (visu._depth>1?visu._depth:0)); + float frame_timing = 5; + bool is_stopped = false; + disp.set_key(key,false).set_wheel().resize(cimg_fitscreen(w1,h1,1),false); key = 0; + for (unsigned int timer = 0; !key && !disp.is_closed() && !disp.button(); ) { + if (disp.is_resized()) disp.resize(false); + if (!timer) { + visu.get_slice((int)_XYZ[2]).display(disp.set_title("%s | z=%d",dtitle.data(),_XYZ[2])); + (++_XYZ[2])%=visu._depth; + } + if (!is_stopped) { if (++timer>(unsigned int)frame_timing) timer = 0; } else timer = ~0U; + if (disp.wheel()) { frame_timing-=disp.wheel()/3.f; disp.set_wheel(); } + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : frame_timing-=0.3f; key = 0; break; + case cimg::keyPAGEDOWN : frame_timing+=0.3f; key = 0; break; + case cimg::keySPACE : is_stopped = !is_stopped; disp.set_key(key,false); key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyARROWUP : is_stopped = true; timer = 0; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyARROWDOWN : is_stopped = true; + (_XYZ[2]+=visu._depth - 2)%=visu._depth; timer = 0; key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false).set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(_width,_height,_depth),false).set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false). + toggle_fullscreen().set_key(key,false); key = 0; + } break; + } + frame_timing = frame_timing<1?1:(frame_timing>39?39:frame_timing); + disp.wait(20); + } + const unsigned int + w2 = (visu._width + (visu._depth>1?visu._depth:0))*disp.width()/visu._width, + h2 = (visu._height + (visu._depth>1?visu._depth:0))*disp.height()/visu._height; + disp.resize(cimg_fitscreen(w2,h2,1),false).set_title(dtitle.data()).set_key().set_button().set_wheel(); + key = 0; + } break; + case cimg::keyHOME : reset_view = resize_disp = true; key = 0; break; + case cimg::keyPADADD : go_in = true; go_in_center = true; key = 0; break; + case cimg::keyPADSUB : go_out = true; key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyPAD4: go_left = true; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6: go_right = true; key = 0; break; + case cimg::keyARROWUP : case cimg::keyPAD8: go_up = true; key = 0; break; + case cimg::keyARROWDOWN : case cimg::keyPAD2: go_down = true; key = 0; break; + case cimg::keyPAD7 : go_up = go_left = true; key = 0; break; + case cimg::keyPAD9 : go_up = go_right = true; key = 0; break; + case cimg::keyPAD1 : go_down = go_left = true; key = 0; break; + case cimg::keyPAD3 : go_down = go_right = true; key = 0; break; + case cimg::keyPAGEUP : go_inc = true; key = 0; break; + case cimg::keyPAGEDOWN : go_dec = true; key = 0; break; + } + if (go_in) { + const int + mx = go_in_center?disp.width()/2:disp.mouse_x(), + my = go_in_center?disp.height()/2:disp.mouse_y(), + mX = mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my*(height() + (depth()>1?depth():0))/disp.height(); + int X = (int)_XYZ[0], Y = (int)_XYZ[1], Z = (int)_XYZ[2]; + if (mX=height()) { + X = x0 + mX*(1 + x1 - x0)/width(); Z = z0 + (mY - height())*(1 + z1 - z0)/depth(); + } + if (mX>=width() && mY4) { x0 = X - 3*(X - x0)/4; x1 = X + 3*(x1 - X)/4; } + if (y1 - y0>4) { y0 = Y - 3*(Y - y0)/4; y1 = Y + 3*(y1 - Y)/4; } + if (z1 - z0>4) { z0 = Z - 3*(Z - z0)/4; z1 = Z + 3*(z1 - Z)/4; } + } + if (go_out) { + const int + delta_x = (x1 - x0)/8, delta_y = (y1 - y0)/8, delta_z = (z1 - z0)/8, + ndelta_x = delta_x?delta_x:(_width>1), + ndelta_y = delta_y?delta_y:(_height>1), + ndelta_z = delta_z?delta_z:(_depth>1); + x0-=ndelta_x; y0-=ndelta_y; z0-=ndelta_z; + x1+=ndelta_x; y1+=ndelta_y; z1+=ndelta_z; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=width()) x1 = width() - 1; } + if (y0<0) { y1-=y0; y0 = 0; if (y1>=height()) y1 = height() - 1; } + if (z0<0) { z1-=z0; z0 = 0; if (z1>=depth()) z1 = depth() - 1; } + if (x1>=width()) { x0-=(x1 - width() + 1); x1 = width() - 1; if (x0<0) x0 = 0; } + if (y1>=height()) { y0-=(y1 - height() + 1); y1 = height() - 1; if (y0<0) y0 = 0; } + if (z1>=depth()) { z0-=(z1 - depth() + 1); z1 = depth() - 1; if (z0<0) z0 = 0; } + const float + ratio = (float)(x1-x0)/(y1-y0), + ratiow = (float)disp._width/disp._height, + sub = std::min(cimg::abs(ratio - ratiow),cimg::abs(1/ratio-1/ratiow)); + if (sub>0.01) resize_disp = true; + } + if (go_left) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + } + if (go_right) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x1+ndelta1); + if (y0 - ndelta>=0) { y0-=ndelta; y1-=ndelta; } + else { y1-=y0; y0 = 0; } + } + if (go_down) { + const int delta = (y1 - y0)/4, ndelta = delta?delta:(_height>1); + if (y1+ndelta1); + if (z0 - ndelta>=0) { z0-=ndelta; z1-=ndelta; } + else { z1-=z0; z0 = 0; } + } + if (go_dec) { + const int delta = (z1 - z0)/4, ndelta = delta?delta:(_depth>1); + if (z1+ndelta + const CImg& display_object3d(CImgDisplay& disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return _display_object3d(disp,0,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + template + const CImg& _display_object3d(CImgDisplay& disp, const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering, + const int render_static, const int render_motion, + const bool is_double_sided, const float focale, + const float light_x, const float light_y, const float light_z, + const float specular_lightness, const float specular_shininess, + const bool display_axes, float *const pose_matrix, + const bool exit_on_anykey) const { + typedef typename cimg::superset::type tpfloat; + + // Check input arguments + if (is_empty()) { + CImg background; + if (colors && colors[0].size()==1) background.assign(1,2,1,1,64,128); + else background.assign(1,2,1,3,32,64,32,116,64,96); + if (disp) background.resize(disp.width(),disp.height(),1,-100,3); + else background.resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),1,-100,3); + return background._display_object3d(disp,title,vertices,primitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } else { if (disp) disp.resize(*this,false); } + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgArgumentException(_cimg_instance + "display_object3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); + if (vertices._width && !primitives) { + CImgList nprimitives(vertices._width,1,1,1,1); + cimglist_for(nprimitives,l) nprimitives(l,0) = (tf)l; + return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3); + if (!title) disp.set_title("CImg<%s> (%u vertices, %u primitives)", + pixel_type(),vertices._width,primitives._width); + } else if (title) disp.set_title("%s",title); + + // Init 3D objects and compute object statistics + CImg + pose, + rotated_vertices(vertices._width,3), + bbox_vertices, rotated_bbox_vertices, + axes_vertices, rotated_axes_vertices, + bbox_opacities, axes_opacities; + CImgList bbox_primitives, axes_primitives; + CImgList reverse_primitives; + CImgList bbox_colors, bbox_colors2, axes_colors; + unsigned int ns_width = 0, ns_height = 0; + int _is_double_sided = (int)is_double_sided; + bool ndisplay_axes = display_axes; + const CImg + background_color(1,1,1,_spectrum,0), + foreground_color(1,1,1,_spectrum,(T)std::min((int)cimg::type::max(),255)); + float + Xoff = 0, Yoff = 0, Zoff = 0, sprite_scale = 1, + xm = 0, xM = vertices?vertices.get_shared_row(0).max_min(xm):0, + ym = 0, yM = vertices?vertices.get_shared_row(1).max_min(ym):0, + zm = 0, zM = vertices?vertices.get_shared_row(2).max_min(zm):0; + const float delta = cimg::max(xM - xm,yM - ym,zM - zm); + + rotated_bbox_vertices = bbox_vertices.assign(8,3,1,1, + xm,xM,xM,xm,xm,xM,xM,xm, + ym,ym,yM,yM,ym,ym,yM,yM, + zm,zm,zm,zm,zM,zM,zM,zM); + bbox_primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 1,2,6,5, 0,4,7,3, 0,1,5,4, 2,3,7,6); + bbox_colors.assign(6,_spectrum,1,1,1,background_color[0]); + bbox_colors2.assign(6,_spectrum,1,1,1,foreground_color[0]); + bbox_opacities.assign(bbox_colors._width,1,1,1,0.3f); + + rotated_axes_vertices = axes_vertices.assign(7,3,1,1, + 0,20,0,0,22,-6,-6, + 0,0,20,0,-6,22,-6, + 0,0,0,20,0,0,22); + axes_opacities.assign(3,1,1,1,1); + axes_colors.assign(3,_spectrum,1,1,1,foreground_color[0]); + axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3); + + // Begin user interaction loop + CImg visu0(*this,false), visu; + CImg zbuffer(visu0.width(),visu0.height(),1,1,0); + bool init_pose = true, clicked = false, redraw = true; + unsigned int key = 0, font_size = 32; + int + x0 = 0, y0 = 0, x1 = 0, y1 = 0, + nrender_static = render_static, + nrender_motion = render_motion; + disp.show().flush(); + + while (!disp.is_closed() && !key) { + + // Init object pose + if (init_pose) { + const float + ratio = delta>0?(2.f*std::min(disp.width(),disp.height())/(3.f*delta)):1, + dx = (xM + xm)/2, dy = (yM + ym)/2, dz = (zM + zm)/2; + if (centering) + CImg(4,3,1,1, ratio,0.,0.,-ratio*dx, 0.,ratio,0.,-ratio*dy, 0.,0.,ratio,-ratio*dz).move_to(pose); + else CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose); + if (pose_matrix) { + CImg pose0(pose_matrix,4,3,1,1,false); + pose0.resize(4,4,1,1,0); pose.resize(4,4,1,1,0); + pose0(3,3) = pose(3,3) = 1; + (pose0*pose).get_crop(0,0,3,2).move_to(pose); + Xoff = pose_matrix[12]; Yoff = pose_matrix[13]; Zoff = pose_matrix[14]; sprite_scale = pose_matrix[15]; + } else { Xoff = Yoff = Zoff = 0; sprite_scale = 1; } + init_pose = false; + redraw = true; + } + + // Rotate and draw 3D object + if (redraw) { + const float + r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0), + r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1), + r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2); + if ((clicked && nrender_motion>=0) || (!clicked && nrender_static>=0)) { + const tp *const pv0 = vertices.data(), *const pv1 = vertices.data(0,1), *const pv2 = vertices.data(0,2); + float + *const prv0 = rotated_vertices.data(), + *const prv1 = rotated_vertices.data(0,1), + *const prv2 = rotated_vertices.data(0,2); + cimg_pragma_openmp(parallel for cimg_openmp_if(vertices.width()>(cimg_openmp_sizefactor)*1024)) + cimg_forX(vertices,l) { + const float x = (float)pv0[l], y = (float)pv1[l], z = (float)pv2[l]; + prv0[l] = r00*x + r10*y + r20*z + r30; + prv1[l] = r01*x + r11*y + r21*z + r31; + prv2[l] = r02*x + r12*y + r22*z + r32; + } + } + else cimg_forX(bbox_vertices,l) { + const float x = bbox_vertices(l,0), y = bbox_vertices(l,1), z = bbox_vertices(l,2); + rotated_bbox_vertices(l,0) = r00*x + r10*y + r20*z + r30; + rotated_bbox_vertices(l,1) = r01*x + r11*y + r21*z + r31; + rotated_bbox_vertices(l,2) = r02*x + r12*y + r22*z + r32; + } + + // Draw objects + const bool render_with_zbuffer = !clicked && nrender_static>0; + visu = visu0; + if ((clicked && nrender_motion<0) || (!clicked && nrender_static<0)) + visu.draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors,bbox_opacities,2,false,focale). + draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors2,1,false,focale); + else visu._draw_object3d((void*)0,render_with_zbuffer?zbuffer.fill(0):CImg::empty(), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static,_is_double_sided==1,focale, + width()/2.f + light_x,height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1,sprite_scale); + // Draw axes + if (ndisplay_axes) { + const float + n = 1e-8f + cimg::hypot(r00,r01,r02), + _r00 = r00/n, _r10 = r10/n, _r20 = r20/n, + _r01 = r01/n, _r11 = r11/n, _r21 = r21/n, + _r02 = r01/n, _r12 = r12/n, _r22 = r22/n, + Xaxes = 25, Yaxes = visu._height - 38.f; + cimg_forX(axes_vertices,l) { + const float + x = axes_vertices(l,0), + y = axes_vertices(l,1), + z = axes_vertices(l,2); + rotated_axes_vertices(l,0) = _r00*x + _r10*y + _r20*z; + rotated_axes_vertices(l,1) = _r01*x + _r11*y + _r21*z; + rotated_axes_vertices(l,2) = _r02*x + _r12*y + _r22*z; + } + axes_opacities(0,0) = (rotated_axes_vertices(1,2)>0)?0.5f:1.f; + axes_opacities(1,0) = (rotated_axes_vertices(2,2)>0)?0.5f:1.f; + axes_opacities(2,0) = (rotated_axes_vertices(3,2)>0)?0.5f:1.f; + visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_vertices,axes_primitives, + axes_colors,axes_opacities,1,false,focale). + draw_text((int)(Xaxes + rotated_axes_vertices(4,0)), + (int)(Yaxes + rotated_axes_vertices(4,1)), + "X",axes_colors[0]._data,0,axes_opacities(0,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(5,0)), + (int)(Yaxes + rotated_axes_vertices(5,1)), + "Y",axes_colors[1]._data,0,axes_opacities(1,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(6,0)), + (int)(Yaxes + rotated_axes_vertices(6,1)), + "Z",axes_colors[2]._data,0,axes_opacities(2,0),13); + } + visu.display(disp); + if (!clicked || nrender_motion==nrender_static) redraw = false; + } + + // Handle user interaction + if (!redraw) disp.wait(); + if ((disp.button() || disp.wheel()) && disp.mouse_x()>=0 && disp.mouse_y()>=0) { + redraw = true; + if (!clicked) { x0 = x1 = disp.mouse_x(); y0 = y1 = disp.mouse_y(); if (!disp.wheel()) clicked = true; } + else { x1 = disp.mouse_x(); y1 = disp.mouse_y(); } + const bool is_keyCTRL = disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT(); + if (disp.button()&1 && !is_keyCTRL) { + const float + R = 0.45f*std::min(disp.width(),disp.height()), + R2 = R*R, + u0 = (float)(x0 - disp.width()/2), + v0 = (float)(y0 - disp.height()/2), + u1 = (float)(x1 - disp.width()/2), + v1 = (float)(y1 - disp.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + (CImg::rotation_matrix(u,v,w,-alpha)*pose).move_to(pose); + x0 = x1; y0 = y1; + } + if (disp.button()&2 && !is_keyCTRL) { + if (focale>0) Zoff-=(y0 - y1)*focale/400; + else { const float s = std::exp((y0 - y1)/400.f); pose*=s; sprite_scale*=s; } + x0 = x1; y0 = y1; + } + if (disp.wheel()) { + if (focale>0) Zoff-=disp.wheel()*focale/20; + else { const float s = std::exp(disp.wheel()/20.f); pose*=s; sprite_scale*=s; } + disp.set_wheel(); + } + if (disp.button()&4 || (disp.button()&1 && is_keyCTRL)) { + Xoff+=(x1 - x0); Yoff+=(y1 - y0); x0 = x1; y0 = y1; + } + if ((disp.button()&1) && (disp.button()&2) && !is_keyCTRL) { + init_pose = true; disp.set_button(); x0 = x1; y0 = y1; + pose = CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0); + } + } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; } + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD: if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + if (!ns_width || !ns_height || + ns_width>(unsigned int)disp.screen_width() || ns_height>(unsigned int)disp.screen_height()) { + ns_width = disp.screen_width()*3U/4; + ns_height = disp.screen_height()*3U/4; + } + if (disp.is_fullscreen()) disp.resize(ns_width,ns_height,false); + else { + ns_width = disp._width; ns_height = disp._height; + disp.resize(disp.screen_width(),disp.screen_height(),false); + } + disp.toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyT : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Switch single/double-sided primitives. + if (--_is_double_sided==-2) _is_double_sided = 1; + if (_is_double_sided>=0) reverse_primitives.assign(); + else primitives.get_reverse_object3d().move_to(reverse_primitives); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyZ : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Enable/disable Z-buffer + if (zbuffer) zbuffer.assign(); + else zbuffer.assign(visu0.width(),visu0.height(),1,1,0); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Show/hide 3D axes + ndisplay_axes = !ndisplay_axes; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF1 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to points + nrender_motion = (nrender_static==0 && nrender_motion!=0)?0:-1; nrender_static = 0; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF2 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to lines + nrender_motion = (nrender_static==1 && nrender_motion!=1)?1:-1; nrender_static = 1; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF3 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat + nrender_motion = (nrender_static==2 && nrender_motion!=2)?2:-1; nrender_static = 2; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF4 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat-shaded + nrender_motion = (nrender_static==3 && nrender_motion!=3)?3:-1; nrender_static = 3; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF5 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Set rendering mode to gouraud-shaded. + nrender_motion = (nrender_static==4 && nrender_motion!=4)?4:-1; nrender_static = 4; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF6 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to phong-shaded + nrender_motion = (nrender_static==5 && nrender_motion!=5)?5:-1; nrender_static = 5; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save snapshot + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving snapshot... ",font_size,0).display(disp); + visu.save(filename); + (+visu).__draw_text(" Snapshot '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyG : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .off file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.off",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving object... ",font_size,0).display(disp); + vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .cimg file + static unsigned int snap_number = 0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving object... ",font_size,0).display(disp); + vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities). + save(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + +#ifdef cimg_use_board + case cimg::keyP : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .EPS file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.eps",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving EPS snapshot... ",font_size,0).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1, + sprite_scale); + board.saveEPS(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .SVG file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.svg",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving SVG snapshot... ",font_size,0).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1, + sprite_scale); + board.saveSVG(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; +#endif + } + if (disp.is_resized()) { + disp.resize(false); visu0 = get_resize(disp,1); + if (zbuffer) zbuffer.assign(disp.width(),disp.height()); + redraw = true; + } + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + if (pose_matrix) { + std::memcpy(pose_matrix,pose._data,12*sizeof(float)); + pose_matrix[12] = Xoff; pose_matrix[13] = Yoff; pose_matrix[14] = Zoff; pose_matrix[15] = sprite_scale; + } + disp.set_button().set_key(key); + return *this; + } + + //! Display 1D graph in an interactive window. + /** + \param disp Display window. + \param plot_type Plot type. Can be { 0=points | 1=segments | 2=splines | 3=bars }. + \param vertex_type Vertex type. + \param labelx Title for the horizontal axis, as a C-string. + \param xmin Minimum value along the X-axis. + \param xmax Maximum value along the X-axis. + \param labely Title for the vertical axis, as a C-string. + \param ymin Minimum value along the X-axis. + \param ymax Maximum value along the X-axis. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + //! Display 1D graph in an interactive window \overloading. + const CImg& display_graph(const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + const CImg& _display_graph(CImgDisplay &disp, const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "display_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title(title?"%s":"CImg<%s>",title?title:pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth, siz1 = std::max((ulongT)1,siz - 1); + const unsigned int old_normalization = disp.normalization(); + disp.show().flush()._normalization = 0; + + double y0 = ymin, y1 = ymax, nxmin = xmin, nxmax = xmax; + if (nxmin==nxmax) { nxmin = 0; nxmax = siz1; } + int x0 = 0, x1 = width()*height()*depth() - 1, key = 0; + + for (bool reset_view = true; !key && !disp.is_closed(); ) { + if (reset_view) { x0 = 0; x1 = width()*height()*depth() - 1; y0 = ymin; y1 = ymax; reset_view = false; } + CImg zoom(x1 - x0 + 1,1,1,spectrum()); + cimg_forC(*this,c) zoom.get_shared_channel(c) = CImg(data(x0,0,0,c),x1 - x0 + 1,1,1,1,true); + if (y0==y1) { y0 = zoom.min_max(y1); const double dy = y1 - y0; y0-=dy/20; y1+=dy/20; } + if (y0==y1) { --y0; ++y1; } + + const CImg selection = zoom.get_select_graph(disp,plot_type,vertex_type, + labelx, + nxmin + x0*(nxmax - nxmin)/siz1, + nxmin + x1*(nxmax - nxmin)/siz1, + labely,y0,y1,true); + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + if (selection[0]>=0) { + if (selection[2]<0) reset_view = true; + else { + x1 = x0 + selection[2]; x0+=selection[0]; + if (selection[1]>=0 && selection[3]>=0) { + y0 = y1 - selection[3]*(y1 - y0)/(disp.height() - 32); + y1-=selection[1]*(y1 - y0)/(disp.height() - 32); + } + } + } else { + bool go_in = false, go_out = false, go_left = false, go_right = false, go_up = false, go_down = false; + switch (key = (int)disp.key()) { + case cimg::keyHOME : reset_view = true; key = 0; disp.set_key(); break; + case cimg::keyPADADD : go_in = true; go_out = false; key = 0; disp.set_key(); break; + case cimg::keyPADSUB : go_out = true; go_in = false; key = 0; disp.set_key(); break; + case cimg::keyARROWLEFT : case cimg::keyPAD4 : go_left = true; go_right = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6 : go_right = true; go_left = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWUP : case cimg::keyPAD8 : go_up = true; go_down = false; key = 0; disp.set_key(); break; + case cimg::keyARROWDOWN : case cimg::keyPAD2 : go_down = true; go_up = false; key = 0; disp.set_key(); break; + case cimg::keyPAD7 : go_left = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD9 : go_right = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD1 : go_left = true; go_down = true; key = 0; disp.set_key(); break; + case cimg::keyPAD3 : go_right = true; go_down = true; key = 0; disp.set_key(); break; + } + if (disp.wheel()) { + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_up = !(go_down = disp.wheel()<0); + else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) go_left = !(go_right = disp.wheel()>0); + else go_out = !(go_in = disp.wheel()>0); + key = 0; + } + + if (go_in) { + const int + xsiz = x1 - x0, + mx = (mouse_x - 16)*xsiz/(disp.width() - 32), + cx = x0 + cimg::cut(mx,0,xsiz); + if (x1 - x0>4) { + x0 = cx - 7*(cx - x0)/8; x1 = cx + 7*(x1 - cx)/8; + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + const double + ysiz = y1 - y0, + my = (mouse_y - 16)*ysiz/(disp.height() - 32), + cy = y1 - cimg::cut(my,0.,ysiz); + y0 = cy - 7*(cy - y0)/8; y1 = cy + 7*(y1 - cy)/8; + } else y0 = y1 = 0; + } + } + if (go_out) { + if (x0>0 || x1<(int)siz1) { + const int delta_x = (x1 - x0)/8, ndelta_x = delta_x?delta_x:(siz>1); + const double ndelta_y = (y1 - y0)/8; + x0-=ndelta_x; x1+=ndelta_x; + y0-=ndelta_y; y1+=ndelta_y; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=(int)siz) x1 = (int)siz1; } + if (x1>=(int)siz) { x0-=(x1 - siz1); x1 = (int)siz1; if (x0<0) x0 = 0; } + } + } + if (go_left) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + go_left = false; + } + if (go_right) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x1 + ndelta<(int)siz) { x0+=ndelta; x1+=ndelta; } + else { x0+=(siz1 - x1); x1 = (int)siz1; } + go_right = false; + } + if (go_up) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0+=ndelta; y1+=ndelta; + go_up = false; + } + if (go_down) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0-=ndelta; y1-=ndelta; + go_down = false; + } + } + if (!exit_on_anykey && key && key!=(int)cimg::keyESC && + (key!=(int)cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + key = 0; + } + } + disp._normalization = old_normalization; + return *this; + } + + //! Save image as a file. + /** + \param filename Filename, as a C-string. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + \note + - The used file format is defined by the file extension in the filename \p filename. + - Parameter \p number can be used to add a 6-digit number to the filename before saving. + + **/ + const CImg& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save(): Specified filename is (null).", + cimg_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:(number>=0)?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimg_save_plugin + cimg_save_plugin(fn); +#endif +#ifdef cimg_save_plugin1 + cimg_save_plugin1(fn); +#endif +#ifdef cimg_save_plugin2 + cimg_save_plugin2(fn); +#endif +#ifdef cimg_save_plugin3 + cimg_save_plugin3(fn); +#endif +#ifdef cimg_save_plugin4 + cimg_save_plugin4(fn); +#endif +#ifdef cimg_save_plugin5 + cimg_save_plugin5(fn); +#endif +#ifdef cimg_save_plugin6 + cimg_save_plugin6(fn); +#endif +#ifdef cimg_save_plugin7 + cimg_save_plugin7(fn); +#endif +#ifdef cimg_save_plugin8 + cimg_save_plugin8(fn); +#endif + // Text formats + if (!cimg::strcasecmp(ext,"asc")) return save_ascii(fn); + else if (!cimg::strcasecmp(ext,"csv") || + !cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) return save_dlm(fn); + else if (!cimg::strcasecmp(ext,"cpp") || + !cimg::strcasecmp(ext,"hpp") || + !cimg::strcasecmp(ext,"h") || + !cimg::strcasecmp(ext,"c")) return save_cpp(fn); + + // 2D binary formats + else if (!cimg::strcasecmp(ext,"bmp")) return save_bmp(fn); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) return save_jpeg(fn); + else if (!cimg::strcasecmp(ext,"rgb")) return save_rgb(fn); + else if (!cimg::strcasecmp(ext,"rgba")) return save_rgba(fn); + else if (!cimg::strcasecmp(ext,"png")) return save_png(fn); + else if (!cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pnm")) return save_pnm(fn); + else if (!cimg::strcasecmp(ext,"pnk")) return save_pnk(fn); + else if (!cimg::strcasecmp(ext,"pfm")) return save_pfm(fn); + else if (!cimg::strcasecmp(ext,"exr")) return save_exr(fn); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); + + // 3D binary formats + else if (!*ext) { +#ifdef cimg_use_zlib + return save_cimg(fn,true); +#else + return save_cimg(fn,false); +#endif + } else if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg")) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"dcm")) return save_medcon_external(fn); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) return save_analyze(fn); + else if (!cimg::strcasecmp(ext,"inr")) return save_inr(fn); + else if (!cimg::strcasecmp(ext,"mnc")) return save_minc2(fn); + else if (!cimg::strcasecmp(ext,"pan")) return save_pandore(fn); + else if (!cimg::strcasecmp(ext,"raw")) return save_raw(fn); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + + // Image sequences + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,444,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); + return save_other(fn); + } + + //! Save image as an ascii file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_ascii(const char *const filename) const { + return _save_ascii(0,filename); + } + + //! Save image as an Ascii file \overloading. + const CImg& save_ascii(std::FILE *const file) const { + return _save_ascii(file,0); + } + + const CImg& _save_ascii(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_ascii(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + std::fprintf(nfile,"%u %u %u %u\n",_width,_height,_depth,_spectrum); + const T* ptrs = _data; + cimg_forYZC(*this,y,z,c) { + cimg_forX(*this,x) std::fprintf(nfile,"%.17g ",(double)*(ptrs++)); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a .cpp source file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_cpp(const char *const filename) const { + return _save_cpp(0,filename); + } + + //! Save image as a .cpp source file \overloading. + const CImg& save_cpp(std::FILE *const file) const { + return _save_cpp(file,0); + } + + const CImg& _save_cpp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_cpp(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + CImg varname(1024); *varname = 0; + if (filename) cimg_sscanf(cimg::basename(filename),"%1023[a-zA-Z0-9_]",varname._data); + if (!*varname) cimg_snprintf(varname,varname._width,"unnamed"); + std::fprintf(nfile, + "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n" + "%s data_%s[] = { %s\n ", + varname._data,_width,_height,_depth,_spectrum,pixel_type(),pixel_type(),varname._data, + is_empty()?"};":""); + if (!is_empty()) for (ulongT off = 0, siz = size() - 1; off<=siz; ++off) { + std::fprintf(nfile,cimg::type::format(),cimg::type::format((*this)[off])); + if (off==siz) std::fprintf(nfile," };\n"); + else if (!((off + 1)%16)) std::fprintf(nfile,",\n "); + else std::fprintf(nfile,", "); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a DLM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_dlm(const char *const filename) const { + return _save_dlm(0,filename); + } + + //! Save image as a DLM file \overloading. + const CImg& save_dlm(std::FILE *const file) const { + return _save_dlm(file,0); + } + + const CImg& _save_dlm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_dlm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is volumetric, values along Z will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + const T* ptrs = _data; + cimg_forYZC(*this,y,z,c) { + cimg_forX(*this,x) std::fprintf(nfile,"%.17g%s",(double)*(ptrs++),(x==width() - 1)?"":","); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a BMP file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_bmp(const char *const filename) const { + return _save_bmp(0,filename); + } + + //! Save image as a BMP file \overloading. + const CImg& save_bmp(std::FILE *const file) const { + return _save_bmp(file,0); + } + + const CImg& _save_bmp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_bmp(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_bmp(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_bmp(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(54,1,1,1,0); + unsigned char align_buf[4] = { 0 }; + const unsigned int + align = (4 - (3*_width)%4)%4, + buf_size = (3*_width + align)*height(), + file_size = 54 + buf_size; + header[0] = 'B'; header[1] = 'M'; + header[0x02] = file_size&0xFF; + header[0x03] = (file_size>>8)&0xFF; + header[0x04] = (file_size>>16)&0xFF; + header[0x05] = (file_size>>24)&0xFF; + header[0x0A] = 0x36; + header[0x0E] = 0x28; + header[0x12] = _width&0xFF; + header[0x13] = (_width>>8)&0xFF; + header[0x14] = (_width>>16)&0xFF; + header[0x15] = (_width>>24)&0xFF; + header[0x16] = _height&0xFF; + header[0x17] = (_height>>8)&0xFF; + header[0x18] = (_height>>16)&0xFF; + header[0x19] = (_height>>24)&0xFF; + header[0x1A] = 1; + header[0x1B] = 0; + header[0x1C] = 24; + header[0x1D] = 0; + header[0x22] = buf_size&0xFF; + header[0x23] = (buf_size>>8)&0xFF; + header[0x24] = (buf_size>>16)&0xFF; + header[0x25] = (buf_size>>24)&0xFF; + header[0x27] = 0x1; + header[0x2B] = 0x1; + cimg::fwrite(header._data,54,nfile); + + const T + *ptr_r = data(0,_height - 1,0,0), + *ptr_g = (_spectrum>=2)?data(0,_height - 1,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,_height - 1,0,2):0; + + switch (_spectrum) { + case 1 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + const unsigned char val = (unsigned char)*(ptr_r++); + std::fputc(val,nfile); std::fputc(val,nfile); std::fputc(val,nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; + } + } break; + case 2 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc(0,nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; + } + } break; + default : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc((unsigned char)(*(ptr_b++)),nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; ptr_b-=2*_width; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a JPEG file. + /** + \param filename Filename, as a C-string. + \param quality Image quality (in %) + **/ + const CImg& save_jpeg(const char *const filename, const unsigned int quality=100) const { + return _save_jpeg(0,filename,quality); + } + + //! Save image as a JPEG file \overloading. + const CImg& save_jpeg(std::FILE *const file, const unsigned int quality=100) const { + return _save_jpeg(file,0,quality); + } + + const CImg& _save_jpeg(std::FILE *const file, const char *const filename, const unsigned int quality) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_jpeg(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + +#ifndef cimg_use_jpeg + if (!file) return save_other(filename,quality); + else throw CImgIOException(_cimg_instance + "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.", + cimg_instance); +#else + unsigned int dimbuf = 0; + J_COLOR_SPACE colortype = JCS_RGB; + + switch (_spectrum) { + case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE; break; + case 2 : dimbuf = 3; colortype = JCS_RGB; break; + case 3 : dimbuf = 3; colortype = JCS_RGB; break; + default : dimbuf = 4; colortype = JCS_CMYK; break; + } + + // Call libjpeg functions + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + jpeg_stdio_dest(&cinfo,nfile); + cinfo.image_width = _width; + cinfo.image_height = _height; + cinfo.input_components = dimbuf; + cinfo.in_color_space = colortype; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE); + jpeg_start_compress(&cinfo,TRUE); + + JSAMPROW row_pointer[1]; + CImg buffer(_width*dimbuf); + + while (cinfo.next_scanline& save_magick(const char *const filename, const unsigned int bytes_per_pixel=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_magick(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_magick + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_magick(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_magick(): Instance is multispectral, only the three first channels will be " + "saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_magick(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + Magick::Image image(Magick::Geometry(_width,_height),"black"); + image.type(Magick::TrueColorType); + image.depth(bytes_per_pixel?(8*bytes_per_pixel):(stmax>=256?16:8)); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = _spectrum>1?data(0,0,0,1):0, + *ptr_b = _spectrum>2?data(0,0,0,2):0; + Magick::PixelPacket *pixels = image.getPixels(0,0,_width,_height); + switch (_spectrum) { + case 1 : // Scalar images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = pixels->green = pixels->blue = (Magick::Quantum)*(ptr_r++); + ++pixels; + } + break; + case 2 : // RG images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = 0; ++pixels; + } + break; + default : // RGB images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = (Magick::Quantum)*(ptr_b++); + ++pixels; + } + } + image.syncPixels(); + image.write(filename); + return *this; +#else + cimg::unused(bytes_per_pixel); + throw CImgIOException(_cimg_instance + "save_magick(): Unable to save file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Save image as a PNG file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving, when possible. + **/ + const CImg& save_png(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_png(0,filename,bytes_per_pixel); + } + + //! Save image as a PNG file \overloading. + const CImg& save_png(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_png(file,0,bytes_per_pixel); + } + + const CImg& _save_png(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_png(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + +#ifndef cimg_use_png + cimg::unused(bytes_per_pixel); + if (!file) return save_other(filename); + else throw CImgIOException(_cimg_instance + "save_png(): Unable to save data in '(*FILE)' unless libpng is enabled.", + cimg_instance); +#else + +#if defined __GNUC__ + const char *volatile nfilename = filename; // Use 'volatile' to avoid (wrong) g++ warning + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"wb"); + volatile double stmin, stmax = (double)max_min(stmin); +#else + const char *nfilename = filename; + std::FILE *nfile = file?file:cimg::fopen(nfilename,"wb"); + double stmin, stmax = (double)max_min(stmin); +#endif + + if (_depth>1) + cimg::warn(_cimg_instance + "save_png(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>4) + cimg::warn(_cimg_instance + "save_png(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_png(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + // Setup PNG structures for write + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,user_error_ptr, user_error_fn, + user_warning_fn); + if (!png_ptr){ + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'png_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)0); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'info_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + + const int bit_depth = bytes_per_pixel?(bytes_per_pixel*8):(stmax>=256?16:8); + + int color_type; + switch (spectrum()) { + case 1 : color_type = PNG_COLOR_TYPE_GRAY; break; + case 2 : color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; + case 3 : color_type = PNG_COLOR_TYPE_RGB; break; + default : color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + const int interlace_type = PNG_INTERLACE_NONE; + const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT; + const int filter_method = PNG_FILTER_TYPE_DEFAULT; + png_set_IHDR(png_ptr,info_ptr,_width,_height,bit_depth,color_type,interlace_type,compression_type,filter_method); + png_write_info(png_ptr,info_ptr); + const int byte_depth = bit_depth>>3; + const int numChan = spectrum()>4?4:spectrum(); + const int pixel_bit_depth_flag = numChan * (bit_depth - 1); + + // Allocate Memory for Image Save and Fill pixel data + png_bytep *const imgData = new png_byte*[_height]; + for (unsigned int row = 0; row<_height; ++row) imgData[row] = new png_byte[byte_depth*numChan*_width]; + const T *pC0 = data(0,0,0,0); + switch (pixel_bit_depth_flag) { + case 7 : { // Gray 8-bit + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) *(ptrd++) = (unsigned char)*(pC0++); + } + } break; + case 14 : { // Gray w/ Alpha 8-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + } + } + } break; + case 21 : { // RGB 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + } + } + } break; + case 28 : { // RGB x/ Alpha 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y){ + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x){ + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + *(ptrd++) = (unsigned char)*(pC3++); + } + } + } break; + case 15 : { // Gray 16-bit + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) *(ptrd++) = (unsigned short)*(pC0++); + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],_width); + } + } break; + case 30 : { // Gray w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],2*_width); + } + } break; + case 45 : { // RGB 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],3*_width); + } + } break; + case 60 : { // RGB w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + *(ptrd++) = (unsigned short)*(pC3++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],4*_width); + } + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_write_image(png_ptr,imgData); + png_write_end(png_ptr,info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + // Deallocate Image Write Memory + cimg_forY(*this,n) delete[] imgData[n]; + delete[] imgData; + + if (!file) cimg::fclose(nfile); + return *this; +#endif + } + + //! Save image as a PNM file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving. + **/ + const CImg& save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(0,filename,bytes_per_pixel); + } + + //! Save image as a PNM file \overloading. + const CImg& save_pnm(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(file,0,bytes_per_pixel); + } + + const CImg& _save_pnm(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_pnm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pnm(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_pnm(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + stmin,stmax,filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const ulongT buf_size = std::min((ulongT)(1024*1024),(ulongT)(_width*_height*(_spectrum==1?1UL:3UL))); + + std::fprintf(nfile,"P%c\n%u %u\n%u\n", + (_spectrum==1?'5':'6'),_width,_height,stmax<256?255:(stmax<4096?4095:65535)); + + switch (_spectrum) { + case 1 : { // Scalar image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PGM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr_r++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Binary PGM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned short)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + } break; + case 2 : { // RG image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = 0; + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } break; + default : { // RGB image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = (unsigned char)*(ptr_b++); + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = (unsigned short)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PNK file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pnk(const char *const filename) const { + return _save_pnk(0,filename); + } + + //! Save image as a PNK file \overloading. + const CImg& save_pnk(std::FILE *const file) const { + return _save_pnk(file,0); + } + + const CImg& _save_pnk(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnk(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + const ulongT buf_size = std::min((ulongT)1024*1024,(ulongT)_width*_height*_depth); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T *ptr = data(0,0,0,0); + + if (!cimg::type::is_float() && sizeof(T)==1 && _depth<2) // Can be saved as regular PNM file + _save_pnm(file,filename,0); + else if (!cimg::type::is_float() && sizeof(T)==1) { // Save as extended P5 file: Binary byte-valued 3D + std::fprintf(nfile,"P5\n%u %u %u\n255\n",_width,_height,_depth); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else if (!cimg::type::is_float()) { // Save as P8: Binary int32-valued 3D + if (_depth>1) std::fprintf(nfile,"P8\n%u %u %u\n%d\n",_width,_height,_depth,(int)max()); + else std::fprintf(nfile,"P8\n%u %u\n%d\n",_width,_height,(int)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + int *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (int)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Save as P9: Binary float-valued 3D + if (_depth>1) std::fprintf(nfile,"P9\n%u %u %u\n%g\n",_width,_height,_depth,(double)max()); + else std::fprintf(nfile,"P9\n%u %u\n%g\n",_width,_height,(double)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PFM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pfm(const char *const filename) const { + get_mirror('y')._save_pfm(0,filename); + return *this; + } + + //! Save image as a PFM file \overloading. + const CImg& save_pfm(std::FILE *const file) const { + get_mirror('y')._save_pfm(file,0); + return *this; + } + + const CImg& _save_pfm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pfm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pfm(): image instance is multispectral, only the three first channels will be saved " + "in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const unsigned int buf_size = std::min(1024*1024U,_width*_height*(_spectrum==1?1:3)); + + std::fprintf(nfile,"P%c\n%u %u\n1.0\n", + (_spectrum==1?'f':'F'),_width,_height); + + switch (_spectrum) { + case 1 : { // Scalar image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,(ulongT)buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } break; + case 2 : { // RG image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } break; + default : { // RGB image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = (float)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a RGB file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_rgb(const char *const filename) const { + return _save_rgb(0,filename); + } + + //! Save image as a RGB file \overloading. + const CImg& save_rgb(std::FILE *const file) const { + return _save_rgb(file,0); + } + + const CImg& _save_rgb(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgb(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=3) + cimg::warn(_cimg_instance + "save_rgb(): image instance has not exactly 3 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0; + switch (_spectrum) { + case 1 : { // Scalar image + for (ulongT k = 0; k& save_rgba(const char *const filename) const { + return _save_rgba(0,filename); + } + + //! Save image as a RGBA file \overloading. + const CImg& save_rgba(std::FILE *const file) const { + return _save_rgba(file,0); + } + + const CImg& _save_rgba(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgba(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=4) + cimg::warn(_cimg_instance + "save_rgba(): image instance has not exactly 4 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[4*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0, + *ptr4 = _spectrum>3?data(0,0,0,3):0; + switch (_spectrum) { + case 1 : { // Scalar images + for (ulongT k = 0; k{ 0=None | 1=LZW | 2=JPEG }. + \param[out] voxel_size Voxel size, to be stored in the filename. + \param[out] description Description, to be stored in the filename. + \param use_bigtiff Allow to save big tiff files (>4Gb). + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tiff is not defined at compile time the + function uses CImg&save_other(const char*). + **/ + const CImg& save_tiff(const char *const filename, const unsigned int compression_type=0, + + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_tiff(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_tiff + const bool + _use_bigtiff = use_bigtiff && sizeof(ulongT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "save_tiff(): Failed to open file '%s' for writing.", + cimg_instance, + filename); + return *this; +#else + cimg::unused(compression_type,voxel_size,description,use_bigtiff); + return save_other(filename); +#endif + } + +#ifdef cimg_use_tiff + +#define _cimg_save_tiff(types,typed,compression_type) if (!std::strcmp(types,pixel_type())) { \ + const typed foo = (typed)0; return _save_tiff(tif,directory,z,foo,compression_type,voxel_size,description); } + + // [internal] Save a plane into a tiff file + template + const CImg& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, const t& pixel_t, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + if (is_empty() || !tif || pixel_t) return *this; + const char *const filename = TIFFFileName(tif); + uint32 rowsperstrip = (uint32)-1; + uint16 spp = _spectrum, bpp = sizeof(t)*8, photometric; + if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB; + else photometric = PHOTOMETRIC_MINISBLACK; + TIFFSetDirectory(tif,directory); + TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,_width); + TIFFSetField(tif,TIFFTAG_IMAGELENGTH,_height); + if (voxel_size) { + const float vx = voxel_size[0], vy = voxel_size[1], vz = voxel_size[2]; + TIFFSetField(tif,TIFFTAG_RESOLUTIONUNIT,RESUNIT_NONE); + TIFFSetField(tif,TIFFTAG_XRESOLUTION,1.f/vx); + TIFFSetField(tif,TIFFTAG_YRESOLUTION,1.f/vy); + CImg s_description(256); + cimg_snprintf(s_description,s_description._width,"VX=%g VY=%g VZ=%g spacing=%g",vx,vy,vz,vz); + TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,s_description.data()); + } + if (description) TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,description); + TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); + TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp); + if (cimg::type::is_float()) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,3); + else if (cimg::type::min()==0) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,1); + else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2); + double valm, valM = max_min(valm); + TIFFSetField(tif,TIFFTAG_SMINSAMPLEVALUE,valm); + TIFFSetField(tif,TIFFTAG_SMAXSAMPLEVALUE,valM); + TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp); + TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); + TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric); + TIFFSetField(tif,TIFFTAG_COMPRESSION,compression_type==2?COMPRESSION_JPEG: + compression_type==1?COMPRESSION_LZW:COMPRESSION_NONE); + rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip); + TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip); + TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB); + TIFFSetField(tif,TIFFTAG_SOFTWARE,"CImg"); + + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + for (unsigned int row = 0; row<_height; row+=rowsperstrip) { + uint32 nrow = (row + rowsperstrip>_height?_height - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif,row,0); + tsize_t i = 0; + for (unsigned int rr = 0; rr& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + _cimg_save_tiff("bool",unsigned char,compression_type); + _cimg_save_tiff("unsigned char",unsigned char,compression_type); + _cimg_save_tiff("char",char,compression_type); + _cimg_save_tiff("unsigned short",unsigned short,compression_type); + _cimg_save_tiff("short",short,compression_type); + _cimg_save_tiff("unsigned int",unsigned int,compression_type); + _cimg_save_tiff("int",int,compression_type); + _cimg_save_tiff("unsigned int64",unsigned int,compression_type); + _cimg_save_tiff("int64",int,compression_type); + _cimg_save_tiff("float",float,compression_type); + _cimg_save_tiff("double",float,compression_type); + const char *const filename = TIFFFileName(tif); + throw CImgInstanceException(_cimg_instance + "save_tiff(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + return *this; + } +#endif + + //! Save image as a MINC2 file. + /** + \param filename Filename, as a C-string. + \param imitate_file If non-zero, reference filename, as a C-string, to borrow header from. + **/ + const CImg& save_minc2(const char *const filename, + const char *const imitate_file=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_minc2(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_minc2 + cimg::unused(imitate_file); + return save_other(filename); +#else + minc::minc_1_writer wtr; + if (imitate_file) + wtr.open(filename, imitate_file); + else { + minc::minc_info di; + if (width()) di.push_back(minc::dim_info(width(),width()*0.5,-1,minc::dim_info::DIM_X)); + if (height()) di.push_back(minc::dim_info(height(),height()*0.5,-1,minc::dim_info::DIM_Y)); + if (depth()) di.push_back(minc::dim_info(depth(),depth()*0.5,-1,minc::dim_info::DIM_Z)); + if (spectrum()) di.push_back(minc::dim_info(spectrum(),spectrum()*0.5,-1,minc::dim_info::DIM_TIME)); + wtr.open(filename,di,1,NC_FLOAT,0); + } + if (pixel_type()==cimg::type::string()) + wtr.setup_write_byte(); + else if (pixel_type()==cimg::type::string()) + wtr.setup_write_int(); + else if (pixel_type()==cimg::type::string()) + wtr.setup_write_double(); + else + wtr.setup_write_float(); + minc::save_standard_volume(wtr, this->_data); + return *this; +#endif + } + + //! Save image as an ANALYZE7.5 or NIFTI file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 consecutive values that tell about the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_analyze(const char *const filename, const float *const voxel_size=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_analyze(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + std::FILE *file; + CImg hname(1024), iname(1024); + const char *const ext = cimg::split_filename(filename); + short datatype = -1; + if (!*ext) { + cimg_snprintf(hname,hname._width,"%s.hdr",filename); + cimg_snprintf(iname,iname._width,"%s.img",filename); + } + if (!cimg::strncasecmp(ext,"hdr",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(iname._data + std::strlen(iname) - 3,"img"); + } + if (!cimg::strncasecmp(ext,"img",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(hname._data + std::strlen(iname) - 3,"hdr"); + } + if (!cimg::strncasecmp(ext,"nii",3)) { + std::strncpy(hname,filename,hname._width - 1); *iname = 0; + } + + CImg header(*iname?348:352,1,1,1,0); + int *const iheader = (int*)header._data; + *iheader = 348; + std::strcpy(header._data + 4,"CImg"); + std::strcpy(header._data + 14," "); + ((short*)&(header[36]))[0] = 4096; + ((char*)&(header[38]))[0] = 114; + ((short*)&(header[40]))[0] = 4; + ((short*)&(header[40]))[1] = (short)_width; + ((short*)&(header[40]))[2] = (short)_height; + ((short*)&(header[40]))[3] = (short)_depth; + ((short*)&(header[40]))[4] = (short)_spectrum; + if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"unsigned int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16; + if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64; + if (datatype<0) + throw CImgIOException(_cimg_instance + "save_analyze(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename); + + ((short*)&(header[70]))[0] = datatype; + ((short*)&(header[72]))[0] = sizeof(T); + ((float*)&(header[108]))[0] = (float)(*iname?0:header.width()); + ((float*)&(header[112]))[0] = 1; + ((float*)&(header[76]))[0] = 0; + if (voxel_size) { + ((float*)&(header[76]))[1] = voxel_size[0]; + ((float*)&(header[76]))[2] = voxel_size[1]; + ((float*)&(header[76]))[3] = voxel_size[2]; + } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1; + file = cimg::fopen(hname,"wb"); + cimg::fwrite(header._data,header.width(),file); + if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); } + cimg::fwrite(_data,size(),file); + cimg::fclose(file); + return *this; + } + + //! Save image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param is_compressed Tells if the file contains compressed image data. + **/ + const CImg& save_cimg(const char *const filename, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(filename,is_compressed); + return *this; + } + + //! Save image as a .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(file,is_compressed); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Index of the image inside the file. + \param x0 X-coordinate of the sub-image location. + \param y0 Y-coordinate of the sub-image location. + \param z0 Z-coordinate of the sub-image location. + \param c0 C-coordinate of the sub-image location. + **/ + const CImg& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(filename,n0,x0,y0,z0,c0); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(file,n0,x0,y0,z0,c0); + return *this; + } + + //! Save blank image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param dx Width of the image. + \param dy Height of the image. + \param dz Depth of the image. + \param dc Number of channels of the image. + \note + - All pixel values of the saved image are set to \c 0. + - Use this method to save large images without having to instantiate and allocate them. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(filename,1,dx,dy,dz,dc); + } + + //! Save blank image as a .cimg file \overloading. + /** + Same as save_empty_cimg(const char *,unsigned int,unsigned int,unsigned int,unsigned int) + with a file stream argument instead of a filename string. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(file,1,dx,dy,dz,dc); + } + + //! Save image as an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 values specifying the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_inr(const char *const filename, const float *const voxel_size=0) const { + return _save_inr(0,filename,voxel_size); + } + + //! Save image as an INRIMAGE-4 file \overloading. + const CImg& save_inr(std::FILE *const file, const float *const voxel_size=0) const { + return _save_inr(file,0,voxel_size); + } + + const CImg& _save_inr(std::FILE *const file, const char *const filename, const float *const voxel_size) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_inr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + int inrpixsize = -1; + const char *inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) { + inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"char")) { + inrtype = "fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) { + inrtype = "unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"short")) { + inrtype = "fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) { + inrtype = "unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"int")) { + inrtype = "fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"float")) { + inrtype = "float\nPIXSIZE=32 bits"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"double")) { + inrtype = "float\nPIXSIZE=64 bits"; inrpixsize = 8; + } + if (inrpixsize<=0) + throw CImgIOException(_cimg_instance + "save_inr(): Unsupported pixel type '%s' for file '%s'", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(257); + int err = cimg_snprintf(header,header._width,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n", + _width,_height,_depth,_spectrum); + if (voxel_size) err+=cimg_sprintf(header._data + err,"VX=%g\nVY=%g\nVZ=%g\n", + voxel_size[0],voxel_size[1],voxel_size[2]); + err+=cimg_sprintf(header._data + err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm"); + std::memset(header._data + err,'\n',252 - err); + std::memcpy(header._data + 252,"##}\n",4); + cimg::fwrite(header._data,256,nfile); + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as an OpenEXR file. + /** + \param filename Filename, as a C-string. + \note The OpenEXR file format is described here. + **/ + const CImg& save_exr(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_exr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_exr(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + +#ifndef cimg_use_openexr + return save_other(filename); +#else + Imf::Rgba *const ptrd0 = new Imf::Rgba[(size_t)_width*_height], *ptrd = ptrd0, rgba; + switch (_spectrum) { + case 1 : { // Grayscale image + for (const T *ptr_r = data(), *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_rPandore file specifications + for more information). + **/ + const CImg& save_pandore(const char *const filename, const unsigned int colorspace=0) const { + return _save_pandore(0,filename,colorspace); + } + + //! Save image as a Pandore-5 file \overloading. + /** + Same as save_pandore(const char *,unsigned int) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_pandore(std::FILE *const file, const unsigned int colorspace=0) const { + return _save_pandore(file,0,colorspace); + } + + unsigned int _save_pandore_header_length(unsigned int id, unsigned int *dims, const unsigned int colorspace) const { + unsigned int nbdims = 0; + if (id==2 || id==3 || id==4) { + dims[0] = 1; dims[1] = _width; nbdims = 2; + } + if (id==5 || id==6 || id==7) { + dims[0] = 1; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==8 || id==9 || id==10) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + if (id==16 || id==17 || id==18) { + dims[0] = 3; dims[1] = _height; dims[2] = _width; dims[3] = colorspace; nbdims = 4; + } + if (id==19 || id==20 || id==21) { + dims[0] = 3; dims[1] = _depth; dims[2] = _height; dims[3] = _width; dims[4] = colorspace; nbdims = 5; + } + if (id==22 || id==23 || id==25) { + dims[0] = _spectrum; dims[1] = _width; nbdims = 2; + } + if (id==26 || id==27 || id==29) { + dims[0] = _spectrum; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==30 || id==31 || id==33) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + return nbdims; + } + + const CImg& _save_pandore(std::FILE *const file, const char *const filename, + const unsigned int colorspace) const { + +#define __cimg_save_pandore_case(dtype) \ + dtype *buffer = new dtype[size()]; \ + const T *ptrs = _data; \ + cimg_foroff(*this,off) *(buffer++) = (dtype)(*(ptrs++)); \ + buffer-=size(); \ + cimg::fwrite(buffer,size(),nfile); \ + delete[] buffer + +#define _cimg_save_pandore_case(sy,sz,sv,stype,id) \ + if (!saved && (sy?(sy==_height):true) && (sz?(sz==_depth):true) && \ + (sv?(sv==_spectrum):true) && !std::strcmp(stype,pixel_type())) { \ + unsigned int *iheader = (unsigned int*)(header + 12); \ + nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \ + cimg::fwrite(header,36,nfile); \ + if (sizeof(unsigned long)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned long)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned int)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned int)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned short)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned short)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \ + __cimg_save_pandore_case(unsigned char); \ + } else if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \ + if (sizeof(unsigned long)==4) { __cimg_save_pandore_case(unsigned long); } \ + else if (sizeof(unsigned int)==4) { __cimg_save_pandore_case(unsigned int); } \ + else if (sizeof(unsigned short)==4) { __cimg_save_pandore_case(unsigned short); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \ + if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \ + else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pandore(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0, + 0,0,0,0,'C','I','m','g',0,0,0,0,0, + 'N','o',' ','d','a','t','e',0,0,0,0 }; + unsigned int nbdims, dims[5] = { 0 }; + bool saved = false; + _cimg_save_pandore_case(1,1,1,"unsigned char",2); + _cimg_save_pandore_case(1,1,1,"char",3); + _cimg_save_pandore_case(1,1,1,"unsigned short",3); + _cimg_save_pandore_case(1,1,1,"short",3); + _cimg_save_pandore_case(1,1,1,"unsigned int",3); + _cimg_save_pandore_case(1,1,1,"int",3); + _cimg_save_pandore_case(1,1,1,"unsigned int64",3); + _cimg_save_pandore_case(1,1,1,"int64",3); + _cimg_save_pandore_case(1,1,1,"float",4); + _cimg_save_pandore_case(1,1,1,"double",4); + + _cimg_save_pandore_case(0,1,1,"unsigned char",5); + _cimg_save_pandore_case(0,1,1,"char",6); + _cimg_save_pandore_case(0,1,1,"unsigned short",6); + _cimg_save_pandore_case(0,1,1,"short",6); + _cimg_save_pandore_case(0,1,1,"unsigned int",6); + _cimg_save_pandore_case(0,1,1,"int",6); + _cimg_save_pandore_case(0,1,1,"unsigned int64",6); + _cimg_save_pandore_case(0,1,1,"int64",6); + _cimg_save_pandore_case(0,1,1,"float",7); + _cimg_save_pandore_case(0,1,1,"double",7); + + _cimg_save_pandore_case(0,0,1,"unsigned char",8); + _cimg_save_pandore_case(0,0,1,"char",9); + _cimg_save_pandore_case(0,0,1,"unsigned short",9); + _cimg_save_pandore_case(0,0,1,"short",9); + _cimg_save_pandore_case(0,0,1,"unsigned int",9); + _cimg_save_pandore_case(0,0,1,"int",9); + _cimg_save_pandore_case(0,0,1,"unsigned int64",9); + _cimg_save_pandore_case(0,0,1,"int64",9); + _cimg_save_pandore_case(0,0,1,"float",10); + _cimg_save_pandore_case(0,0,1,"double",10); + + _cimg_save_pandore_case(0,1,3,"unsigned char",16); + _cimg_save_pandore_case(0,1,3,"char",17); + _cimg_save_pandore_case(0,1,3,"unsigned short",17); + _cimg_save_pandore_case(0,1,3,"short",17); + _cimg_save_pandore_case(0,1,3,"unsigned int",17); + _cimg_save_pandore_case(0,1,3,"int",17); + _cimg_save_pandore_case(0,1,3,"unsigned int64",17); + _cimg_save_pandore_case(0,1,3,"int64",17); + _cimg_save_pandore_case(0,1,3,"float",18); + _cimg_save_pandore_case(0,1,3,"double",18); + + _cimg_save_pandore_case(0,0,3,"unsigned char",19); + _cimg_save_pandore_case(0,0,3,"char",20); + _cimg_save_pandore_case(0,0,3,"unsigned short",20); + _cimg_save_pandore_case(0,0,3,"short",20); + _cimg_save_pandore_case(0,0,3,"unsigned int",20); + _cimg_save_pandore_case(0,0,3,"int",20); + _cimg_save_pandore_case(0,0,3,"unsigned int64",20); + _cimg_save_pandore_case(0,0,3,"int64",20); + _cimg_save_pandore_case(0,0,3,"float",21); + _cimg_save_pandore_case(0,0,3,"double",21); + + _cimg_save_pandore_case(1,1,0,"unsigned char",22); + _cimg_save_pandore_case(1,1,0,"char",23); + _cimg_save_pandore_case(1,1,0,"unsigned short",23); + _cimg_save_pandore_case(1,1,0,"short",23); + _cimg_save_pandore_case(1,1,0,"unsigned int",23); + _cimg_save_pandore_case(1,1,0,"int",23); + _cimg_save_pandore_case(1,1,0,"unsigned int64",23); + _cimg_save_pandore_case(1,1,0,"int64",23); + _cimg_save_pandore_case(1,1,0,"float",25); + _cimg_save_pandore_case(1,1,0,"double",25); + + _cimg_save_pandore_case(0,1,0,"unsigned char",26); + _cimg_save_pandore_case(0,1,0,"char",27); + _cimg_save_pandore_case(0,1,0,"unsigned short",27); + _cimg_save_pandore_case(0,1,0,"short",27); + _cimg_save_pandore_case(0,1,0,"unsigned int",27); + _cimg_save_pandore_case(0,1,0,"int",27); + _cimg_save_pandore_case(0,1,0,"unsigned int64",27); + _cimg_save_pandore_case(0,1,0,"int64",27); + _cimg_save_pandore_case(0,1,0,"float",29); + _cimg_save_pandore_case(0,1,0,"double",29); + + _cimg_save_pandore_case(0,0,0,"unsigned char",30); + _cimg_save_pandore_case(0,0,0,"char",31); + _cimg_save_pandore_case(0,0,0,"unsigned short",31); + _cimg_save_pandore_case(0,0,0,"short",31); + _cimg_save_pandore_case(0,0,0,"unsigned int",31); + _cimg_save_pandore_case(0,0,0,"int",31); + _cimg_save_pandore_case(0,0,0,"unsigned int64",31); + _cimg_save_pandore_case(0,0,0,"int64",31); + _cimg_save_pandore_case(0,0,0,"float",33); + _cimg_save_pandore_case(0,0,0,"double",33); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a raw data file. + /** + \param filename Filename, as a C-string. + \param is_multiplexed Tells if the image channels are stored in a multiplexed way (\c true) or not (\c false). + \note The .raw format does not store the image dimensions in the output file, + so you have to keep track of them somewhere to be able to read the file correctly afterwards. + **/ + const CImg& save_raw(const char *const filename, const bool is_multiplexed=false) const { + return _save_raw(0,filename,is_multiplexed); + } + + //! Save image as a raw data file \overloading. + /** + Same as save_raw(const char *,bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_raw(std::FILE *const file, const bool is_multiplexed=false) const { + return _save_raw(file,0,is_multiplexed); + } + + const CImg& _save_raw(std::FILE *const file, const char *const filename, const bool is_multiplexed) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_raw(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (pixel_type()==cimg::type::string()) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = _bool2uchar(siz,is_multiplexed); + cimg::fwrite(buf,siz,nfile); + delete[] buf; + } else { // Non boolean data + if (!is_multiplexed || _spectrum==1) cimg::fwrite(_data,size(),nfile); // Non-multiplexed + else { // Multiplexed + CImg buf(_spectrum); + cimg_forXYZ(*this,x,y,z) { + cimg_forC(*this,c) buf[c] = (*this)(x,y,z,c); + cimg::fwrite(buf._data,_spectrum,nfile); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + // Return unsigned char buffer that encodes data of a CImg instance bitwise. + // (buffer needs to be deallocated afterwards, with delete[]). + const unsigned char *_bool2uchar(ulongT &siz, const bool is_multiplexed) const { + const ulongT _siz = size(); + siz = _siz/8 + (_siz%8?1:0); + unsigned char *const buf = new unsigned char[siz], *ptrd = buf, val = 0, bit = 0; + + if (!is_multiplexed || _spectrum==1) // Non-multiplexed + cimg_for(*this,ptrs,T) { (val<<=1)|=(*ptrs?1:0); if (++bit==8) { *(ptrd++) = val; val = bit = 0; }} + else // Multiplexed + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) { + (val<<=1)|=((*this)(x,y,z,c)?1:0); if (++bit==8) { *(ptrd++) = val; val = bit = 0; } + } + if (bit) *ptrd = val; + return buf; + } + + // Fill CImg instance from bitwise data encoded in an unsigned char buffer. + void _uchar2bool(const unsigned char *buf, const ulongT siz, const bool is_multiplexed) { + const ulongT S = std::min(siz*8,size()); + const unsigned char *ptrs = buf; + unsigned char val = 0, mask = 0; + T *ptrd = _data; + if (S && (!is_multiplexed || _spectrum==1)) // Non-multiplexed + for (ulongT off = 0; off>=1)) { val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?1:0); + } + else if (S) { // Multiplexed + ulongT off = 0; + for (int z = 0; z>=1)) { val = *(ptrs++); ++off; mask = 128; } + (*this)(x,y,z,c) = (T)((val&mask)?1:0); + } + } + } + + //! Save image as a .yuv video file. + /** + \param filename Filename, as a C-string. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if pixel values of the instance image are RGB-coded (\c true) or YUV-coded (\c false). + \note Each slice of the instance image is considered to be a single frame of the output video file. + **/ + const CImg& save_yuv(const char *const filename, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + CImgList(*this,true).save_yuv(filename,chroma_subsampling,is_rgb); + return *this; + } + + //! Save image as a .yuv video file \overloading. + /** + Same as save_yuv(const char*,const unsigned int,const bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_yuv(std::FILE *const file, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + CImgList(*this,true).save_yuv(file,chroma_subsampling,is_rgb); + return *this; + } + + //! Save 3D object as an Object File Format (.off) file. + /** + \param filename Filename, as a C-string. + \param primitives List of 3D object primitives. + \param colors List of 3D object colors. + \note + - Instance image contains the vertices data of the 3D object. + - Textured, transparent or sphere-shaped primitives cannot be managed by the .off file format. + Such primitives will be lost or simplified during file saving. + - The .off file format is described here. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + const char *const filename) const { + return _save_off(primitives,colors,0,filename); + } + + //! Save 3D object as an Object File Format (.off) file \overloading. + /** + Same as save_off(const CImgList&,const CImgList&,const char*) const + with a file stream argument instead of a filename string. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file) const { + return _save_off(primitives,colors,file,0); + } + + template + const CImg& _save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_off(): Specified filename is (null).", + cimg_instance); + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "save_off(): Empty instance, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + CImgList opacities; + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgInstanceException(_cimg_instance + "save_off(): Invalid specified 3D object, for file '%s' (%s).", + cimg_instance, + filename?filename:"(FILE*)",error_message.data()); + + const CImg default_color(1,3,1,1,(tc)std::min((int)cimg::type::max(),200)); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + unsigned int supported_primitives = 0; + cimglist_for(primitives,l) if (primitives[l].size()!=5) ++supported_primitives; + std::fprintf(nfile,"OFF\n%u %u %u\n",_width,supported_primitives,3*primitives._width); + cimg_forX(*this,i) std::fprintf(nfile,"%f %f %f\n", + (float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2))); + cimglist_for(primitives,l) { + const CImg& color = l1?color[1]:r)/255.f, b = (csiz>2?color[2]:g)/255.f; + switch (psiz) { + case 1 : std::fprintf(nfile,"1 %u %f %f %f\n", + (unsigned int)primitives(l,0),r,g,b); break; + case 2 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 3 : std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),r,g,b); break; + case 4 : std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),r,g,b); break; + case 5 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 6 : { + const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 9 : { + const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 12 : { + const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save volumetric image as a video (using the OpenCV library when available). + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImg& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { + if (is_empty()) { CImgList().save_video(filename,fps,codec,keep_open); return *this; } + CImgList list; + get_split('z').move_to(list); + list.save_video(filename,fps,codec,keep_open); + return *this; + } + + //! Save volumetric image as a video, using custom external binary. + /** + \param filename Filename, as a C-string. + \param fps Video framerate. + \param codec Video codec, as a C-string. + \param bitrate Video bitrate. + \note + - Each slice of the instance image is considered to be a single frame of the output video file. + - This method uses \c custom, an external executable binary provided by + custom. + It must be installed for the method to succeed. + **/ + const CImg& save_custom_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_custom_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImgList list; + get_split('z').move_to(list); + list.save_custom_external(filename,fps,codec,bitrate); + return *this; + } + + //! Save image using gzip external binary. + /** + \param filename Filename, as a C-string. + \note This method uses \c gzip, an external executable binary provided by + gzip. + It must be installed for the method to succeed. + **/ + const CImg& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_gzip_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::gzip_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimg_instance, + filename); + + else cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using GraphicsMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c gm, an external executable binary provided by + GraphicsMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + +#ifdef cimg_use_png +#define _cimg_sge_extension1 "png" +#define _cimg_sge_extension2 "png" +#else +#define _cimg_sge_extension1 "pgm" +#define _cimg_sge_extension2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(), + _spectrum==1?_cimg_sge_extension1:_cimg_sge_extension2); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"\"%s\" convert -quality %u \"%s\" \"%s\"", + cimg::graphicsmagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::graphicsmagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_graphicsmagick_external(): Failed to save file '%s' with external command 'gm'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using ImageMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c convert, an external executable binary provided by + ImageMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_imagemagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_imagemagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick only writes the first image slice.", + cimg_instance,filename); +#ifdef cimg_use_png +#define _cimg_sie_extension1 "png" +#define _cimg_sie_extension2 "png" +#else +#define _cimg_sie_extension1 "pgm" +#define _cimg_sie_extension2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",cimg::temporary_path(), + cimg_file_separator,cimg::filenamerand(),_spectrum==1?_cimg_sie_extension1:_cimg_sie_extension2); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"\"%s\" -quality %u \"%s\" \"%s\"", + cimg::imagemagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::imagemagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_imagemagick_external(): Failed to save file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image as a Dicom file. + /** + \param filename Filename, as a C-string. + \note This method uses \c medcon, an external executable binary provided by + (X)Medcon. + It must be installed for the method to succeed. + **/ + const CImg& save_medcon_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_medcon_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save_analyze(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -w -c dicom -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::medcon_path()); + std::remove(filename_tmp); + cimg::split_filename(filename_tmp,body); + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.img",body._data); + std::remove(filename_tmp); + + file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s",filename); + file = cimg::std_fopen(command,"rb"); + if (!file) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "save_medcon_external(): Failed to save file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + std::rename(command,filename); + return *this; + } + + // Save image for non natively supported formats. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note + - The filename extension tells about the desired file format. + - This method tries to save the instance image as a file, using external tools from + ImageMagick or + GraphicsMagick. + At least one of these tool must be installed for the method to succeed. + - It is recommended to use the generic method save(const char*, int) const instead, + as it can handle some file formats natively. + **/ + const CImg& save_other(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_other(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick or GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + + const unsigned int omode = cimg::exception_mode(); + bool is_saved = true; + cimg::exception_mode(0); + try { save_magick(filename); } + catch (CImgException&) { + try { save_imagemagick_external(filename,quality); } + catch (CImgException&) { + try { save_graphicsmagick_external(filename,quality); } + catch (CImgException&) { + is_saved = false; + } + } + } + cimg::exception_mode(omode); + if (!is_saved) + throw CImgIOException(_cimg_instance + "save_other(): Failed to save file '%s'. Format is not natively supported, " + "and no external commands succeeded.", + cimg_instance, + filename); + return *this; + } + + //! Serialize a CImg instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { + return CImgList(*this,true).get_serialize(is_compressed); + } + + // [internal] Return a 40x38 color logo of a 'danger' item. + static CImg _logo40x38() { + CImg res(40,38,1,3); + const unsigned char *ptrs = cimg::logo40x38; + T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2); + for (ulongT off = 0; off<(ulongT)res._width*res._height;) { + const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++); + for (unsigned int l = 0; l structure + # + # + # + #------------------------------------------ + */ + //! Represent a list of images CImg. + template + struct CImgList { + unsigned int _width, _allocated_width; + CImg *_data; + + //! Simple iterator type, to loop through each image of a list. + /** + \note + - The \c CImgList::iterator type is defined as a CImg*. + - You may use it like this: + \code + CImgList<> list; // Assuming this image list is not empty + for (CImgList<>::iterator it = list.begin(); it* iterator; + + //! Simple const iterator type, to loop through each image of a \c const list instance. + /** + \note + - The \c CImgList::const_iterator type is defined to be a const CImg*. + - Similar to CImgList::iterator, but for constant list instances. + **/ + typedef const CImg* const_iterator; + + //! Pixel value type. + /** + Refer to the pixels value type of the images in the list. + \note + - The \c CImgList::value_type type of a \c CImgList is defined to be a \c T. + It is then similar to CImg::value_type. + - \c CImgList::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimglist_plugin +#include cimglist_plugin +#endif +#ifdef cimglist_plugin1 +#include cimglist_plugin1 +#endif +#ifdef cimglist_plugin2 +#include cimglist_plugin2 +#endif +#ifdef cimglist_plugin3 +#include cimglist_plugin3 +#endif +#ifdef cimglist_plugin4 +#include cimglist_plugin4 +#endif +#ifdef cimglist_plugin5 +#include cimglist_plugin5 +#endif +#ifdef cimglist_plugin6 +#include cimglist_plugin6 +#endif +#ifdef cimglist_plugin7 +#include cimglist_plugin7 +#endif +#ifdef cimglist_plugin8 +#include cimglist_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + Destroy current list instance. + \note + - Any allocated buffer is deallocated. + - Destroying an empty list does nothing actually. + **/ + ~CImgList() { + delete[] _data; + } + + //! Default constructor. + /** + Construct a new empty list instance. + \note + - An empty list has no pixel data and its dimension width() is set to \c 0, as well as its + image buffer pointer data(). + - An empty list may be reassigned afterwards, with the family of the assign() methods. + In all cases, the type of pixels stays \c T. + **/ + CImgList(): + _width(0),_allocated_width(0),_data(0) {} + + //! Construct list containing empty images. + /** + \param n Number of empty images. + \note Useful when you know by advance the number of images you want to manage, as + it will allocate the right amount of memory for the list, without needs for reallocation + (that may occur when starting from an empty list and inserting several images in it). + **/ + explicit CImgList(const unsigned int n):_width(n) { + if (n) _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + else { _allocated_width = 0; _data = 0; } + } + + //! Construct list containing images of specified size. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \note Pixel values are not initialized and may probably contain garbage. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + } + + //! Construct list containing images of specified size, and initialize pixel values. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val Initialization value for images pixels. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + } + + //! Construct list containing images of specified size, and initialize pixel values from a sequence of integers. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val0 First value of the initializing integers sequence. + \param val1 Second value of the initializing integers sequence. + \warning You must specify at least width*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...): + _width(0),_allocated_width(0),_data(0) { +#define _CImgList_stdarg(t) { \ + assign(n,width,height,depth,spectrum); \ + const ulongT siz = (ulongT)width*height*depth*spectrum, nsiz = siz*n; \ + T *ptrd = _data->_data; \ + va_list ap; \ + va_start(ap,val1); \ + for (ulongT l = 0, s = 0, i = 0; iwidth*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const double val0, const double val1, ...): + _width(0),_allocated_width(0),_data(0) { + _CImgList_stdarg(double); + } + + //! Construct list containing copies of an input image. + /** + \param n Number of images. + \param img Input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of \c img. + **/ + template + CImgList(const unsigned int n, const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + } + + //! Construct list from one image. + /** + \param img Input image to copy in the constructed list. + \param is_shared Tells if the element of the list is a shared or non-shared copy of \c img. + **/ + template + explicit CImgList(const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(1); + _data[0].assign(img,is_shared); + } + + //! Construct list from two images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + } + + //! Construct list from three images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + } + + //! Construct list from four images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + } + + //! Construct list from five images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + } + + //! Construct list from six images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + } + + //! Construct list from seven images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + } + + //! Construct list from eight images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param img8 Eighth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + } + + //! Construct list copy. + /** + \param list Input list to copy. + \note The shared state of each element of the constructed list is kept the same as in \c list. + **/ + template + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + } + + //! Construct list copy \specialization. + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],list[l]._is_shared); + } + + //! Construct list copy, and force the shared state of the list elements. + /** + \param list Input list to copy. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImgList& list, const bool is_shared):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],is_shared); + } + + //! Construct list by reading the content of a file. + /** + \param filename Filename, as a C-string. + **/ + explicit CImgList(const char *const filename):_width(0),_allocated_width(0),_data(0) { + assign(filename); + } + + //! Construct list from the content of a display window. + /** + \param disp Display window to get content from. + \note Constructed list contains a single image only. + **/ + explicit CImgList(const CImgDisplay& disp):_width(0),_allocated_width(0),_data(0) { + assign(disp); + } + + //! Return a list with elements being shared copies of images in the list instance. + /** + \note list2 = list1.get_shared() is equivalent to list2.assign(list1,true). + **/ + CImgList get_shared() { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Return a list with elements being shared copies of images in the list instance \const. + const CImgList get_shared() const { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Destructor \inplace. + /** + \see CImgList(). + **/ + CImgList& assign() { + delete[] _data; + _width = _allocated_width = 0; + _data = 0; + return *this; + } + + //! Destructor \inplace. + /** + Equivalent to assign(). + \note Only here for compatibility with STL naming conventions. + **/ + CImgList& clear() { + return assign(); + } + + //! Construct list containing empty images \inplace. + /** + \see CImgList(unsigned int). + **/ + CImgList& assign(const unsigned int n) { + if (!n) return assign(); + if (_allocated_width(n<<2)) { + delete[] _data; + _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + } + _width = n; + return *this; + } + + //! Construct list containing images of specified size \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + return *this; + } + + //! Construct list containing images of specified size, and initialize pixel values \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const T). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of integers \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const int, const int, ...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...) { + _CImgList_stdarg(int); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of doubles \inplace. + /** + \see CImgList(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,const double,const double,...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, + const double val0, const double val1, ...) { + _CImgList_stdarg(double); + return *this; + } + + //! Construct list containing copies of an input image \inplace. + /** + \see CImgList(unsigned int, const CImg&, bool). + **/ + template + CImgList& assign(const unsigned int n, const CImg& img, const bool is_shared=false) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + return *this; + } + + //! Construct list from one image \inplace. + /** + \see CImgList(const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img, const bool is_shared=false) { + assign(1); + _data[0].assign(img,is_shared); + return *this; + } + + //! Construct list from two images \inplace. + /** + \see CImgList(const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const bool is_shared=false) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + return *this; + } + + //! Construct list from three images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + return *this; + } + + //! Construct list from four images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + return *this; + } + + //! Construct list from five images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + return *this; + } + + //! Construct list from six images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + return *this; + } + + //! Construct list from seven images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, + const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + return *this; + } + + //! Construct list from eight images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, + const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + return *this; + } + + //! Construct list as a copy of an existing list and force the shared state of the list elements \inplace. + /** + \see CImgList(const CImgList&, bool is_shared). + **/ + template + CImgList& assign(const CImgList& list, const bool is_shared=false) { + cimg::unused(is_shared); + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + return *this; + } + + //! Construct list as a copy of an existing list and force shared state of elements \inplace \specialization. + CImgList& assign(const CImgList& list, const bool is_shared=false) { + if (this==&list) return *this; + CImgList res(list._width); + cimglist_for(res,l) res[l].assign(list[l],is_shared); + return res.move_to(*this); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& assign(const char *const filename) { + return load(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& assign(const CImgDisplay &disp) { + return assign(CImg(disp)); + } + + //! Transfer the content of the list instance to another list. + /** + \param list Destination list. + \note When returning, the current list instance is empty and the initial content of \c list is destroyed. + **/ + template + CImgList& move_to(CImgList& list) { + list.assign(_width); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[l]); + assign(); + return list; + } + + //! Transfer the content of the list instance at a specified position in another list. + /** + \param list Destination list. + \param pos Index of the insertion in the list. + \note When returning, the list instance is empty and the initial content of \c list is preserved + (only images indexes may be modified). + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos) { + if (is_empty()) return list; + const unsigned int npos = pos>list._width?list._width:pos; + list.insert(_width,npos); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[npos + l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[npos + l]); + assign(); + return list; + } + + //! Swap all fields between two list instances. + /** + \param list List to swap fields with. + \note Can be used to exchange the content of two lists in a fast way. + **/ + CImgList& swap(CImgList& list) { + cimg::swap(_width,list._width,_allocated_width,list._allocated_width); + cimg::swap(_data,list._data); + return list; + } + + //! Return a reference to an empty list. + /** + \note Can be used to define default values in a function taking a CImgList as an argument. + \code + void f(const CImgList& list=CImgList::empty()); + \endcode + **/ + static CImgList& empty() { + static CImgList _empty; + return _empty.assign(); + } + + //! Return a reference to an empty list \const. + static const CImgList& const_empty() { + static const CImgList _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Return a reference to one image element of the list. + /** + \param pos Index of the image element. + **/ + CImg& operator()(const unsigned int pos) { +#if cimg_verbosity>=3 + if (pos>=_width) { + cimg::warn(_cimglist_instance + "operator(): Invalid image request, at position [%u].", + cimglist_instance, + pos); + return *_data; + } +#endif + return _data[pos]; + } + + //! Return a reference to one image of the list. + /** + \param pos Index of the image element. + **/ + const CImg& operator()(const unsigned int pos) const { + return const_cast*>(this)->operator()(pos); + } + + //! Return a reference to one pixel value of one image of the list. + /** + \param pos Index of the image element. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list(n,x,y,z,c) is equivalent to list[n](x,y,z,c). + **/ + T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + return (*this)[pos](x,y,z,c); + } + + //! Return a reference to one pixel value of one image of the list \const. + const T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return (*this)[pos](x,y,z,c); + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + operator CImg*() { + return _data; + } + + //! Return pointer to the first image of the list \const. + operator const CImg*() const { + return _data; + } + + //! Construct list from one image \inplace. + /** + \param img Input image to copy in the constructed list. + \note list = img; is equivalent to list.assign(img);. + **/ + template + CImgList& operator=(const CImg& img) { + return assign(img); + } + + //! Construct list from another list. + /** + \param list Input list to copy. + \note list1 = list2 is equivalent to list1.assign(list2);. + **/ + template + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list from another list \specialization. + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& operator=(const char *const filename) { + return assign(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return a non-shared copy of a list. + /** + \note +list is equivalent to CImgList(list,false). + It forces the copy to have non-shared elements. + **/ + CImgList operator+() const { + return CImgList(*this,false); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end. + /** + \param img Image inserted at the end of the instance copy. + \note Define a convenient way to create temporary lists of images, as in the following code: + \code + (img1,img2,img3,img4).display("My four images"); + \endcode + **/ + template + CImgList& operator,(const CImg& img) { + return insert(img); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end \const. + template + CImgList operator,(const CImg& img) const { + return (+*this).insert(img); + } + + //! Return a copy of the list instance, where all elements of input list \c list have been inserted at the end. + /** + \param list List inserted at the end of the instance copy. + **/ + template + CImgList& operator,(const CImgList& list) { + return insert(list); + } + + //! Return a copy of the list instance, where all elements of input \c list have been inserted at the end \const. + template + CImgList& operator,(const CImgList& list) const { + return (+*this).insert(list); + } + + //! Return image corresponding to the appending of all images of the instance list along specified axis. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \note list>'x' is equivalent to list.get_append('x'). + **/ + CImg operator>(const char axis) const { + return get_append(axis,0); + } + + //! Return list corresponding to the splitting of all images of the instance list along specified axis. + /** + \param axis Axis used for image splitting. + \note list<'x' is equivalent to list.get_split('x'). + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to size() but returns result as a (signed) integer. + **/ + int width() const { + return (int)_width; + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to width() but returns result as an unsigned integer. + **/ + unsigned int size() const { + return _width; + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + CImg *data() { + return _data; + } + + //! Return pointer to the first image of the list \const. + const CImg *data() const { + return _data; + } + + //! Return pointer to the pos-th image of the list. + /** + \param pos Index of the image element to access. + \note list.data(n); is equivalent to list.data + n;. + **/ +#if cimg_verbosity>=3 + CImg *data(const unsigned int pos) { + if (pos>=size()) + cimg::warn(_cimglist_instance + "data(): Invalid pointer request, at position [%u].", + cimglist_instance, + pos); + return _data + pos; + } + + const CImg *data(const unsigned int l) const { + return const_cast*>(this)->data(l); + } +#else + CImg *data(const unsigned int l) { + return _data + l; + } + + //! Return pointer to the pos-th image of the list \const. + const CImg *data(const unsigned int l) const { + return _data + l; + } +#endif + + //! Return iterator to the first image of the list. + /** + **/ + iterator begin() { + return _data; + } + + //! Return iterator to the first image of the list \const. + const_iterator begin() const { + return _data; + } + + //! Return iterator to one position after the last image of the list. + /** + **/ + iterator end() { + return _data + _width; + } + + //! Return iterator to one position after the last image of the list \const. + const_iterator end() const { + return _data + _width; + } + + //! Return reference to the first image of the list. + /** + **/ + CImg& front() { + return *_data; + } + + //! Return reference to the first image of the list \const. + const CImg& front() const { + return *_data; + } + + //! Return a reference to the last image of the list. + /** + **/ + const CImg& back() const { + return *(_data + _width - 1); + } + + //! Return a reference to the last image of the list \const. + CImg& back() { + return *(_data + _width - 1); + } + + //! Return pos-th image of the list. + /** + \param pos Index of the image element to access. + **/ + CImg& at(const int pos) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "at(): Empty instance.", + cimglist_instance); + + return _data[cimg::cut(pos,0,width() - 1)]; + } + + //! Access to pixel value with Dirichlet boundary conditions. + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions. + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + T& _atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + T _atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + T& _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + T _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 coordinates (\c pos, \c x,\c y). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + T& _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + T _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 coordinates (\c pos,\c x). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 coordinates (\c pos,\c x) \const. + T atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x) \const. + T atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + T& _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + T _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the coordinate (\c pos). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):(*this)(pos,x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the coordinate (\c pos) \const. + T atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:(*this)(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos) \const. + T atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + T& _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + T _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Return \c true if list is empty. + /** + **/ + bool is_empty() const { + return (!_data || !_width); + } + + //! Test if number of image elements is equal to specified value. + /** + \param size_n Number of image elements to test. + **/ + bool is_sameN(const unsigned int size_n) const { + return _width==size_n; + } + + //! Test if number of image elements is equal between two images lists. + /** + \param list Input list to compare with. + **/ + template + bool is_sameN(const CImgList& list) const { + return is_sameN(list._width); + } + + // Define useful functions to check list dimensions. + // (cannot be documented because macro-generated). +#define _cimglist_def_is_same1(axis) \ + bool is_same##axis(const unsigned int val) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(val); \ + return res; \ + } \ + bool is_sameN##axis(const unsigned int n, const unsigned int val) const { \ + return is_sameN(n) && is_same##axis(val); \ + } \ + +#define _cimglist_def_is_same2(axis1,axis2) \ + bool is_same##axis1##axis2(const unsigned int val1, const unsigned int val2) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2(val1,val2); \ + return res; \ + } \ + bool is_sameN##axis1##axis2(const unsigned int n, const unsigned int val1, const unsigned int val2) const { \ + return is_sameN(n) && is_same##axis1##axis2(val1,val2); \ + } \ + +#define _cimglist_def_is_same3(axis1,axis2,axis3) \ + bool is_same##axis1##axis2##axis3(const unsigned int val1, const unsigned int val2, \ + const unsigned int val3) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2##axis3(val1,val2,val3); \ + return res; \ + } \ + bool is_sameN##axis1##axis2##axis3(const unsigned int n, const unsigned int val1, \ + const unsigned int val2, const unsigned int val3) const { \ + return is_sameN(n) && is_same##axis1##axis2##axis3(val1,val2,val3); \ + } \ + +#define _cimglist_def_is_same(axis) \ + template bool is_same##axis(const CImg& img) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(img); \ + return res; \ + } \ + template bool is_same##axis(const CImgList& list) const { \ + const unsigned int lmin = std::min(_width,list._width); \ + bool res = true; \ + for (unsigned int l = 0; l bool is_sameN##axis(const unsigned int n, const CImg& img) const { \ + return (is_sameN(n) && is_same##axis(img)); \ + } \ + template bool is_sameN##axis(const CImgList& list) const { \ + return (is_sameN(list) && is_same##axis(list)); \ + } + + _cimglist_def_is_same(XY) + _cimglist_def_is_same(XZ) + _cimglist_def_is_same(XC) + _cimglist_def_is_same(YZ) + _cimglist_def_is_same(YC) + _cimglist_def_is_same(XYZ) + _cimglist_def_is_same(XYC) + _cimglist_def_is_same(YZC) + _cimglist_def_is_same(XYZC) + _cimglist_def_is_same1(X) + _cimglist_def_is_same1(Y) + _cimglist_def_is_same1(Z) + _cimglist_def_is_same1(C) + _cimglist_def_is_same2(X,Y) + _cimglist_def_is_same2(X,Z) + _cimglist_def_is_same2(X,C) + _cimglist_def_is_same2(Y,Z) + _cimglist_def_is_same2(Y,C) + _cimglist_def_is_same2(Z,C) + _cimglist_def_is_same3(X,Y,Z) + _cimglist_def_is_same3(X,Y,C) + _cimglist_def_is_same3(X,Z,C) + _cimglist_def_is_same3(Y,Z,C) + + //! Test if dimensions of each image of the list match specified arguments. + /** + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameXYZC(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + bool res = true; + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_sameXYZC(dx,dy,dz,dc); + return res; + } + + //! Test if list dimensions match specified arguments. + /** + \param n Number of images in the list. + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameNXYZC(const unsigned int n, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + return is_sameN(n) && is_sameXYZC(dx,dy,dz,dc); + } + + //! Test if list contains one particular pixel location. + /** + \param n Index of the image whom checked pixel value belong to. + \param x X-coordinate of the checked pixel value. + \param y Y-coordinate of the checked pixel value. + \param z Z-coordinate of the checked pixel value. + \param c C-coordinate of the checked pixel value. + **/ + bool containsNXYZC(const int n, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) return false; + return n>=0 && n=0 && x<_data[n].width() && y>=0 && y<_data[n].height() && + z>=0 && z<_data[n].depth() && c>=0 && c<_data[n].spectrum(); + } + + //! Test if list contains image with specified index. + /** + \param n Index of the checked image. + **/ + bool containsN(const int n) const { + if (is_empty()) return false; + return n>=0 && n + bool contains(const T& pixel, t& n, t& x, t&y, t& z, t& c) const { + if (is_empty()) return false; + cimglist_for(*this,l) if (_data[l].contains(pixel,x,y,z,c)) { n = (t)l; return true; } + return false; + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \param[out] z Z-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y,z). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y, t& z) const { + t c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y) const { + t z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x). + **/ + template + bool contains(const T& pixel, t& n, t& x) const { + t y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \note If true, set coordinates (n). + **/ + template + bool contains(const T& pixel, t& n) const { + t x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + **/ + bool contains(const T& pixel) const { + unsigned int n, x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if the list contains the image 'img'. + /** + \param img Reference to image to test. + \param[out] n Index of image in the list, if test succeeds. + \note If true, returns the position (n) of the image in the list. + **/ + template + bool contains(const CImg& img, t& n) const { + if (is_empty()) return false; + const CImg *const ptr = &img; + cimglist_for(*this,i) if (_data + i==ptr) { n = (t)i; return true; } + return false; + } + + //! Test if the list contains the image img. + /** + \param img Reference to image to test. + **/ + bool contains(const CImg& img) const { + unsigned int n; + return contains(img,n); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + //! Return a reference to the minimum pixel value of the instance list. + /** + **/ + T& min() { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the maximum pixel value of the instance list \const. + const T& max() const { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T max_value = *ptr_max; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + T& min_max(t& max_val) { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min_max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well \const. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + const T& min_max(t& max_val) const { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min_max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the minimum value as well. + /** + \param[out] min_val Value of the minimum value found. + **/ + template + T& max_min(t& min_val) { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max_min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max_min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + if (is_shared) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified shared image " + "CImg<%s>(%u,%u,%u,%u,%p) at position %u (pixel types are different).", + cimglist_instance, + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data,npos); + + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list + _data = new_data; + *_data = img; + } else { + if (new_data) { // Insert with re-allocation + if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos); + if (npos!=_width - 1) + std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + std::memset((void*)_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else if (npos!=_width - 1) // Insert without re-allocation + std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \specialization. + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list + _data = new_data; + if (is_shared && img) { + _data->_width = img._width; + _data->_height = img._height; + _data->_depth = img._depth; + _data->_spectrum = img._spectrum; + _data->_is_shared = true; + _data->_data = img._data; + } else *_data = img; + } + else { + if (new_data) { // Insert with re-allocation + if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos); + if (npos!=_width - 1) + std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + new_data[npos]._width = img._width; + new_data[npos]._height = img._height; + new_data[npos]._depth = img._depth; + new_data[npos]._spectrum = img._spectrum; + new_data[npos]._is_shared = true; + new_data[npos]._data = img._data; + } else { + new_data[npos]._width = new_data[npos]._height = new_data[npos]._depth = new_data[npos]._spectrum = 0; + new_data[npos]._data = 0; + new_data[npos] = img; + } + std::memset((void*)_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else { // Insert without re-allocation + if (npos!=_width - 1) + std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + _data[npos]._width = img._width; + _data[npos]._height = img._height; + _data[npos]._depth = img._depth; + _data[npos]._spectrum = img._spectrum; + _data[npos]._is_shared = true; + _data[npos]._data = img._data; + } else { + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + } + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \newinstance. + template + CImgList get_insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(img,pos,is_shared); + } + + //! Insert n empty images img into the current image list, at position \p pos. + /** + \param n Number of empty images to insert. + \param pos Index of the insertion. + **/ + CImgList& insert(const unsigned int n, const unsigned int pos=~0U) { + CImg empty; + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i get_insert(const unsigned int n, const unsigned int pos=~0U) const { + return (+*this).insert(n,pos); + } + + //! Insert \c n copies of the image \c img into the current image list, at position \c pos. + /** + \param n Number of image copies to insert. + \param img Image to insert by copy. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of \c img or not. + **/ + template + CImgList& insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + insert(img,npos,is_shared); + for (unsigned int i = 1; i + CImgList get_insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,img,pos,is_shared); + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos. + /** + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if ((void*)this!=(void*)&list) cimglist_for(list,l) insert(list[l],npos + l,is_shared); + else insert(CImgList(list),npos,is_shared); + return *this; + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos \newinstance. + template + CImgList get_insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(list,pos,is_shared); + } + + //! Insert n copies of the list \c list at position \c pos of the current list. + /** + \param n Number of list copies to insert. + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i + CImgList get_insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,list,pos,is_shared); + } + + //! Remove all images between from indexes. + /** + \param pos1 Starting index of the removal. + \param pos2 Ending index of the removal. + **/ + CImgList& remove(const unsigned int pos1, const unsigned int pos2) { + const unsigned int + npos1 = pos1=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + else { + if (tpos2>=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + + for (unsigned int k = npos1; k<=npos2; ++k) _data[k].assign(); + const unsigned int nb = 1 + npos2 - npos1; + if (!(_width-=nb)) return assign(); + if (_width>(_allocated_width>>4) || _allocated_width<=16) { // Removing items without reallocation + if (npos1!=_width) + std::memmove((void*)(_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg)*(_width - npos1)); + std::memset((void*)(_data + _width),0,sizeof(CImg)*nb); + } else { // Removing items with reallocation + _allocated_width>>=4; + while (_allocated_width>16 && _width<(_allocated_width>>1)) _allocated_width>>=1; + CImg *const new_data = new CImg[_allocated_width]; + if (npos1) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos1); + if (npos1!=_width) + std::memcpy((void*)(new_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg)*(_width - npos1)); + if (_width!=_allocated_width) + std::memset((void*)(new_data + _width),0,sizeof(CImg)*(_allocated_width - _width)); + std::memset((void*)_data,0,sizeof(CImg)*(_width + nb)); + delete[] _data; + _data = new_data; + } + } + return *this; + } + + //! Remove all images between from indexes \newinstance. + CImgList get_remove(const unsigned int pos1, const unsigned int pos2) const { + return (+*this).remove(pos1,pos2); + } + + //! Remove image at index \c pos from the image list. + /** + \param pos Index of the image to remove. + **/ + CImgList& remove(const unsigned int pos) { + return remove(pos,pos); + } + + //! Remove image at index \c pos from the image list \newinstance. + CImgList get_remove(const unsigned int pos) const { + return (+*this).remove(pos); + } + + //! Remove last image. + /** + **/ + CImgList& remove() { + return remove(_width - 1); + } + + //! Remove last image \newinstance. + CImgList get_remove() const { + return (+*this).remove(); + } + + //! Reverse list order. + CImgList& reverse() { + for (unsigned int l = 0; l<_width/2; ++l) (*this)[l].swap((*this)[_width - 1 - l]); + return *this; + } + + //! Reverse list order \newinstance. + CImgList get_reverse() const { + return (+*this).reverse(); + } + + //! Return a sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList& images(const unsigned int pos0, const unsigned int pos1) { + return get_images(pos0,pos1).move_to(*this); + } + + //! Return a sublist \newinstance. + CImgList get_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l]); + return res; + } + + //! Return a shared sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a shared sublist \newinstance. + const CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a single image which is the appending of all images of the current CImgList instance. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg get_append(const char axis, const float align=0) const { + if (is_empty()) return CImg(); + if (_width==1) return +((*this)[0]); + unsigned int dx = 0, dy = 0, dz = 0, dc = 0, pos = 0; + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { // Along the X-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx+=img._width; + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._height==1 && img._depth==1 && img._spectrum==1 && + res._height==1 && res._depth==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._width); + else + res.draw_image(pos, + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._width; + } + } break; + case 'y' : { // Along the Y-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy+=img._height; + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._depth==1 && img._spectrum==1 && + res._width==1 && res._depth==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._height); + else + res.draw_image((int)(align*(dx - img._width)), + pos, + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._height; + } + } break; + case 'z' : { // Along the Z-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz+=img._depth; + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._height==1 && img._spectrum==1 && + res._width==1 && res._height==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._depth); + else + res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + pos, + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._depth; + } + } break; + default : { // Along the C-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc+=img._spectrum; + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._height==1 && img._depth==1 && + res._width==1 && res._height==1 && res._depth==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._spectrum); + else + res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + pos, + img); + } + pos+=img._spectrum; + } + } + } + return res; + } + + //! Return a list where each image has been split along the specified axis. + /** + \param axis Axis to split images along. + \param nb Number of split parts for each image. + **/ + CImgList& split(const char axis, const int nb=-1) { + return get_split(axis,nb).move_to(*this); + } + + //! Return a list where each image has been split along the specified axis \newinstance. + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + cimglist_for(*this,l) _data[l].get_split(axis,nb).move_to(res,~0U); + return res; + } + + //! Insert image at the end of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_back(const CImg& img) { + return insert(img); + } + + //! Insert image at the front of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_front(const CImg& img) { + return insert(img,0); + } + + //! Insert list at the end of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_back(const CImgList& list) { + return insert(list); + } + + //! Insert list at the front of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_front(const CImgList& list) { + return insert(list,0); + } + + //! Remove last image. + /** + **/ + CImgList& pop_back() { + return remove(_width - 1); + } + + //! Remove first image. + /** + **/ + CImgList& pop_front() { + return remove(0); + } + + //! Remove image pointed by iterator. + /** + \param iter Iterator pointing to the image to remove. + **/ + CImgList& erase(const iterator iter) { + return remove(iter - _data); + } + + //@} + //---------------------------------- + // + //! \name Data Input + //@{ + //---------------------------------- + + //! Display a simple interactive interface to select images or sublists. + /** + \param disp Window instance to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \param exit_on_anykey Exit function when any key is pressed. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(CImgDisplay &disp, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + return _select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + //! Display a simple interactive interface to select images or sublists. + /** + \param title Title of a new window used to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \param exit_on_anykey Exit function when any key is pressed. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(const char *const title, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + CImg _select(CImgDisplay &disp, const char *const title, const bool feature_type, + const char axis, const float align, const bool exit_on_anykey, + const unsigned int orig, const bool resize_disp, + const bool exit_on_rightbutton, const bool exit_on_wheel) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "select(): Empty instance.", + cimglist_instance); + + // Create image correspondence table and get list dimensions for visualization. + CImgList _indices; + unsigned int max_width = 0, max_height = 0, sum_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + if (h>max_height) max_height = h; + sum_width+=w; sum_height+=h; + if (axis=='x') CImg(w,1,1,1,(unsigned int)l).move_to(_indices); + else CImg(h,1,1,1,(unsigned int)l).move_to(_indices); + } + const CImg indices0 = _indices>'x'; + + // Create display window. + if (!disp) { + if (axis=='x') disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1); + else disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1); + if (!title) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else { + if (title) disp.set_title("%s",title); + disp.move_inside_screen(); + } + if (resize_disp) { + if (axis=='x') disp.resize(cimg_fitscreen(sum_width,max_height,1),false); + else disp.resize(cimg_fitscreen(max_width,sum_height,1),false); + } + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).show_mouse(); + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + + // Enter event loop. + CImg visu0, visu; + CImg indices; + CImg positions(_width,4,1,1,-1); + int oindex0 = -1, oindex1 = -1, index0 = -1, index1 = -1; + bool is_clicked = false, is_selected = false, text_down = false, update_display = true; + unsigned int key = 0, font_size = 32; + + while (!is_selected && !disp.is_closed() && !key) { + + // Create background image. + if (!visu0) { + visu0.assign(disp._width,disp._height,1,3,0); visu.assign(); + (indices0.get_resize(axis=='x'?visu0._width:visu0._height,1)).move_to(indices); + unsigned int _ind = 0; + const CImg onexone(1,1,1,1,(T)0); + if (axis=='x') + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4)) + cimglist_for(*this,ind) { + unsigned int x0 = 0; + while (x0 &src = _data[ind]?_data[ind]:onexone; + CImg res; + src._get_select(disp,old_normalization,src._width/2,src._height/2,src._depth/2). + move_to(res); + const unsigned int h = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,true); + res.resize(x1 - x0,std::max(32U,h*disp._height/max_height),1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)x0; + positions(ind,1) = positions(ind,3) = (int)(align*(visu0.height() - res.height())); + positions(ind,2)+=res._width; + positions(ind,3)+=res._height - 1; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4)) + cimglist_for(*this,ind) { + unsigned int y0 = 0; + while (y0 &src = _data[ind]?_data[ind]:onexone; + CImg res; + src._get_select(disp,old_normalization,(src._width - 1)/2,(src._height - 1)/2,(src._depth - 1)/2). + move_to(res); + const unsigned int w = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,false); + res.resize(std::max(32U,w*disp._width/max_width),y1 - y0,1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)(align*(visu0.width() - res.width())); + positions(ind,1) = positions(ind,3) = (int)y0; + positions(ind,2)+=res._width - 1; + positions(ind,3)+=res._height; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + if (axis=='x') --positions(_ind,2); else --positions(_ind,3); + update_display = true; + } + + if (!visu || oindex0!=index0 || oindex1!=index1) { + if (index0>=0 && index1>=0) { + visu.assign(visu0,false); + const int indm = std::min(index0,index1), indM = std::max(index0,index1); + for (int ind = indm; ind<=indM; ++ind) if (positions(ind,0)>=0) { + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + background_color,0.2f); + if ((axis=='x' && positions(ind,2) - positions(ind,0)>=8) || + (axis!='x' && positions(ind,3) - positions(ind,1)>=8)) + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + foreground_color,0.9f,0xAAAAAAAA); + } + if (is_clicked) visu.__draw_text(" Images #%u - #%u, Size = %u ",font_size,(int)text_down, + orig + indm,orig + indM,indM - indm + 1); + else visu.__draw_text(" Image #%u (%u,%u,%u,%u) ",font_size,(int)text_down, + orig + index0, + _data[index0]._width, + _data[index0]._height, + _data[index0]._depth, + _data[index0]._spectrum); + update_display = true; + } else visu.assign(); + } + if (!visu) { visu.assign(visu0,true); update_display = true; } + if (update_display) { visu.display(disp); update_display = false; } + disp.wait(); + + // Manage user events. + const int xm = disp.mouse_x(), ym = disp.mouse_y(); + int index = -1; + + if (xm>=0) { + index = (int)indices(axis=='x'?xm:ym); + if (disp.button()&1) { + if (!is_clicked) { is_clicked = true; oindex0 = index0; index0 = index; } + oindex1 = index1; index1 = index; + if (!feature_type) is_selected = true; + } else { + if (!is_clicked) { oindex0 = oindex1 = index0; index0 = index1 = index; } + else is_selected = true; + } + } else { + if (is_clicked) { + if (!(disp.button()&1)) { is_clicked = is_selected = false; index0 = index1 = -1; } + else index1 = -1; + } else index0 = index1 = -1; + } + + if (disp.button()&4) { is_clicked = is_selected = false; index0 = index1 = -1; } + if (disp.button()&2 && exit_on_rightbutton) { is_selected = true; index1 = index0 = -1; } + if (disp.wheel() && exit_on_wheel) is_selected = true; + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(axis=='x'?sum_width:max_width,axis=='x'?max_height:sum_height,1),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).__draw_text(" Saving snapshot... ",font_size,(int)text_down).display(disp); + visu0.save(filename); + (+visu0).__draw_text(" Snapshot '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + } + disp.set_key(key,false).wait(); key = 0; + } break; + case cimg::keyO : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).__draw_text(" Saving instance... ",font_size,(int)text_down).display(disp); + save(filename); + (+visu0).__draw_text(" Instance '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + disp.set_key(key,false).wait(); key = 0; + } break; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (ym>=0 && ym<13) { if (!text_down) { visu.assign(); text_down = true; }} + else if (ym>=visu.height() - 13) { if (text_down) { visu.assign(); text_down = false; }} + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + CImg res(1,2,1,1,-1); + if (is_selected) { + if (feature_type) res.fill(std::min(index0,index1),std::max(index0,index1)); + else res.fill(index0); + } + if (!(disp.button()&2)) disp.set_button(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + disp.set_key(key); + return res; + } + + //! Load a list from a file. + /** + \param filename Filename to read data from. + **/ + CImgList& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load(): Specified filename is (null).", + cimglist_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const bool is_stdin = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimglist_load_plugin + cimglist_load_plugin(filename); +#endif +#ifdef cimglist_load_plugin1 + cimglist_load_plugin1(filename); +#endif +#ifdef cimglist_load_plugin2 + cimglist_load_plugin2(filename); +#endif +#ifdef cimglist_load_plugin3 + cimglist_load_plugin3(filename); +#endif +#ifdef cimglist_load_plugin4 + cimglist_load_plugin4(filename); +#endif +#ifdef cimglist_load_plugin5 + cimglist_load_plugin5(filename); +#endif +#ifdef cimglist_load_plugin6 + cimglist_load_plugin6(filename); +#endif +#ifdef cimglist_load_plugin7 + cimglist_load_plugin7(filename); +#endif +#ifdef cimglist_load_plugin8 + cimglist_load_plugin8(filename); +#endif + if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) load_cimg(filename); + else if (!cimg::strcasecmp(ext,"rec") || + !cimg::strcasecmp(ext,"par")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded && !is_stdin) { + std::FILE *const file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to open file '%s'.", + cimglist_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + cimg::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file as a single image. + if (!is_loaded) { + assign(1); + try { + _data->load(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to recognize format of file '%s'.", + cimglist_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load a list from a file \newinstance. + static CImgList get_load(const char *const filename) { + return CImgList().load(filename); + } + + //! Load a list from a .cimg file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_cimg(const char *const filename) { + return _load_cimg(0,filename); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename) { + return CImgList().load_cimg(filename); + } + + //! Load a list from a .cimg file. + /** + \param file File to read data from. + **/ + CImgList& load_cimg(std::FILE *const file) { + return _load_cimg(file,0); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file) { + return CImgList().load_cimg(file); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename) { +#ifdef cimg_use_zlib +#define _cimgz_load_cimg_case(Tss) { \ + Bytef *const cbuf = new Bytef[csiz]; \ + cimg::fread(cbuf,(size_t)csiz,nfile); \ + if (is_bool) { \ + CImg raw(W*H*D*C/8); \ + uLongf destlen = (uLongf)raw.size(); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,(uLong)csiz); \ + img.assign(W,H,D,C); \ + img._uchar2bool(raw,raw.size(),false); \ + } else { \ + CImg raw(W,H,D,C); \ + uLongf destlen = (uLongf)(raw.size()*sizeof(Tss)); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,(uLong)csiz); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } \ + delete[] cbuf; \ +} +#else +#define _cimgz_load_cimg_case(Tss) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Unable to load compressed data from file '%s' unless zlib is enabled.", \ + cimglist_instance, \ + filename?filename:"(FILE*)"); +#endif + +#define _cimg_load_cimg_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + const bool is_bool = cimg::type::string()==cimg::type::string(); \ + for (unsigned int l = 0; l=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; csiz = 0; \ + if ((err = cimg_sscanf(tmp,"%u %u %u %u #" cimg_fuint64,&W,&H,&D,&C,&csiz))<4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'.", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:("(FILE*)")); \ + if (W*H*D*C>0) { \ + CImg &img = _data[l]; \ + if (err==5) _cimgz_load_cimg_case(Tss) \ + else { \ + img.assign(W,H,D,C); \ + T *ptrd = img._data; \ + if (is_bool) { \ + CImg raw; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + CImg(ptrd,std::min(8*raw._width,(unsigned int)(img.end() - ptrd)),1,1,1,true).\ + _uchar2bool(raw,raw._width,false); \ + to_read-=raw._width; \ + } \ + } else { \ + CImg raw; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + const Tss *ptrs = raw._data; \ + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + to_read-=raw._width; \ + } \ + } \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + + const ulongT cimg_iobuffer = (ulongT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + cimg_uint64 csiz; + int i, err; + do { + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; + } while (*tmp=='#' && i>=0); + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + assign(N); + _cimg_load_cimg_case("bool",bool); + _cimg_load_cimg_case("unsigned_char",unsigned char); + _cimg_load_cimg_case("uchar",unsigned char); + _cimg_load_cimg_case("char",char); + _cimg_load_cimg_case("unsigned_short",unsigned short); + _cimg_load_cimg_case("ushort",unsigned short); + _cimg_load_cimg_case("short",short); + _cimg_load_cimg_case("unsigned_int",unsigned int); + _cimg_load_cimg_case("uint",unsigned int); + _cimg_load_cimg_case("int",int); + _cimg_load_cimg_case("unsigned_long",ulongT); + _cimg_load_cimg_case("ulong",ulongT); + _cimg_load_cimg_case("long",longT); + _cimg_load_cimg_case("unsigned_int64",uint64T); + _cimg_load_cimg_case("uint64",uint64T); + _cimg_load_cimg_case("int64",int64T); + _cimg_load_cimg_case("float",float); + _cimg_load_cimg_case("double",double); + + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a sublist list from a (non compressed) .cimg file. + /** + \param filename Filename to read data from. + \param n0 Starting index of images to read (~0U for max). + \param n1 Ending index of images to read (~0U for max). + \param x0 Starting X-coordinates of image regions to read. + \param y0 Starting Y-coordinates of image regions to read. + \param z0 Starting Z-coordinates of image regions to read. + \param c0 Starting C-coordinates of image regions to read. + \param x1 Ending X-coordinates of image regions to read (~0U for max). + \param y1 Ending Y-coordinates of image regions to read (~0U for max). + \param z1 Ending Z-coordinates of image regions to read (~0U for max). + \param c1 Ending C-coordinates of image regions to read (~0U for max). + **/ + CImgList& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(0,filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sublist list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \overloading. + CImgList& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(file,0,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { +#define _cimg_load_cimg_case2(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l<=nn1; ++l) { \ + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; \ + if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:"(FILE*)"); \ + if (W*H*D*C>0) { \ + if (l=W || ny0>=H || nz0>=D || nc0>=C) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const unsigned int \ + _nx1 = nx1==~0U?W - 1:nx1, \ + _ny1 = ny1==~0U?H - 1:ny1, \ + _nz1 = nz1==~0U?D - 1:nz1, \ + _nc1 = nc1==~0U?C - 1:nc1; \ + if (_nx1>=W || _ny1>=H || _nz1>=D || _nc1>=C) \ + throw CImgArgumentException(_cimglist_instance \ + "load_cimg(): Invalid specified coordinates " \ + "[%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " \ + "because image [%u] in file '%s' has size (%u,%u,%u,%u).", \ + cimglist_instance, \ + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,l,filename?filename:"(FILE*)",W,H,D,C); \ + CImg raw(1 + _nx1 - nx0); \ + CImg &img = _data[l - nn0]; \ + img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \ + T *ptrd = img._data; \ + ulongT skipvb = nc0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \ + const ulongT skipzb = nz0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \ + const ulongT skipyb = ny0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \ + const ulongT skipxb = nx0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \ + const Tss *ptrs = raw._data; \ + for (unsigned int off = raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + const ulongT skipxe = (W - 1 - _nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const ulongT skipye = (H - 1 - _ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const ulongT skipze = (D - 1 - _nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const ulongT skipve = (C - 1 - _nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + unsigned int + nn0 = std::min(n0,n1), nn1 = std::max(n0,n1), + nx0 = std::min(x0,x1), nx1 = std::max(x0,x1), + ny0 = std::min(y0,y1), ny1 = std::max(y0,y1), + nz0 = std::min(z0,z1), nz1 = std::max(z0,z1), + nc0 = std::min(c0,c1), nc1 = std::max(c0,c1); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + nn1 = n1==~0U?N - 1:n1; + if (nn1>=N) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " + "because file '%s' contains only %u images.", + cimglist_instance, + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,filename?filename:"(FILE*)",N); + assign(1 + nn1 - n0); + _cimg_load_cimg_case2("bool",bool); + _cimg_load_cimg_case2("unsigned_char",unsigned char); + _cimg_load_cimg_case2("uchar",unsigned char); + _cimg_load_cimg_case2("char",char); + _cimg_load_cimg_case2("unsigned_short",unsigned short); + _cimg_load_cimg_case2("ushort",unsigned short); + _cimg_load_cimg_case2("short",short); + _cimg_load_cimg_case2("unsigned_int",unsigned int); + _cimg_load_cimg_case2("uint",unsigned int); + _cimg_load_cimg_case2("int",int); + _cimg_load_cimg_case2("unsigned_long",ulongT); + _cimg_load_cimg_case2("ulong",ulongT); + _cimg_load_cimg_case2("long",longT); + _cimg_load_cimg_case2("unsigned_int64",uint64T); + _cimg_load_cimg_case2("uint64",uint64T); + _cimg_load_cimg_case2("int64",int64T); + _cimg_load_cimg_case2("float",float); + _cimg_load_cimg_case2("double",double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_parrec(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_parrec(): Specified filename is (null).", + cimglist_instance); + + CImg body(1024), filenamepar(1024), filenamerec(1024); + *body = *filenamepar = *filenamerec = 0; + const char *const ext = cimg::split_filename(filename,body); + if (!std::strcmp(ext,"par")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.rec",body._data); + } + if (!std::strcmp(ext,"PAR")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.REC",body._data); + } + if (!std::strcmp(ext,"rec")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.par",body._data); + } + if (!std::strcmp(ext,"REC")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.PAR",body._data); + } + std::FILE *file = cimg::fopen(filenamepar,"r"); + + // Parse header file + CImgList st_slices; + CImgList st_global; + CImg line(256); *line = 0; + int err; + do { err = std::fscanf(file,"%255[^\n]%*c",line._data); } while (err!=EOF && (*line=='#' || *line=='.')); + do { + unsigned int sn,size_x,size_y,pixsize; + float rs,ri,ss; + err = std::fscanf(file,"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&size_x,&size_y,&ri,&rs,&ss); + if (err==7) { + CImg::vector((float)sn,(float)pixsize,(float)size_x,(float)size_y,ri,rs,ss,0).move_to(st_slices); + unsigned int i; for (i = 0; i::vector(size_x,size_y,sn).move_to(st_global); + else { + CImg &vec = st_global[i]; + if (size_x>vec[0]) vec[0] = size_x; + if (size_y>vec[1]) vec[1] = size_y; + vec[2] = sn; + } + st_slices[st_slices._width - 1][7] = (float)i; + } + } while (err==7); + + // Read data + std::FILE *file2 = cimg::fopen(filenamerec,"rb"); + cimglist_for(st_global,l) { + const CImg& vec = st_global[l]; + CImg(vec[0],vec[1],vec[2]).move_to(*this); + } + + cimglist_for(st_slices,l) { + const CImg& vec = st_slices[l]; + const unsigned int + sn = (unsigned int)vec[0] - 1, + pixsize = (unsigned int)vec[1], + size_x = (unsigned int)vec[2], + size_y = (unsigned int)vec[3], + imn = (unsigned int)vec[7]; + const float ri = vec[4], rs = vec[5], ss = vec[6]; + switch (pixsize) { + case 8 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 16 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 32 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + default : + cimg::fclose(file); + cimg::fclose(file2); + throw CImgIOException(_cimglist_instance + "load_parrec(): Unsupported %d-bits pixel type for file '%s'.", + cimglist_instance, + pixsize,filename); + } + } + cimg::fclose(file); + cimg::fclose(file2); + if (!_width) + throw CImgIOException(_cimglist_instance + "load_parrec(): Failed to recognize valid PAR-REC data in file '%s'.", + cimglist_instance, + filename); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file \newinstance. + static CImgList get_load_parrec(const char *const filename) { + return CImgList().load_parrec(filename); + } + + //! Load a list from a YUV image sequence file. + /** + \param filename Filename to read data from. + \param size_x Width of the images. + \param size_y Height of the images. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param yuv2rgb Apply YUV to RGB transformation during reading. + **/ + CImgList& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(0,filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from a YUV image sequence file \newinstance. + static CImgList get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \overloading. + CImgList& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(file,0,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \newinstance. + static CImgList get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + CImgList& _load_yuv(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling, + const unsigned int first_frame, const unsigned int last_frame, + const unsigned int step_frame, const bool yuv2rgb) { + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified filename is (null).", + cimglist_instance); + if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified chroma subsampling '%u' is invalid, for file '%s'.", + cimglist_instance, + chroma_subsampling,filename?filename:"(FILE*)"); + const unsigned int + cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1, + cfy = chroma_subsampling==420?2:1, + nfirst_frame = first_frame YUV(size_x,size_y,1,3), UV(size_x/cfx,size_y/cfy,1,2); + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool stop_flag = false; + int err; + if (nfirst_frame) { + err = cimg::fseek(nfile,(uint64T)nfirst_frame*(YUV._width*YUV._height + 2*UV._width*UV._height),SEEK_CUR); + if (err) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_yuv(): File '%s' doesn't contain frame number %u.", + cimglist_instance, + filename?filename:"(FILE*)",nfirst_frame); + } + } + unsigned int frame; + for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) { + YUV.get_shared_channel(0).fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(YUV._data),1,(size_t)YUV._width*YUV._height,nfile); + if (err!=(int)(YUV._width*YUV._height)) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + UV.fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(UV._data),1,(size_t)UV.size(),nfile); + if (err!=(int)(UV.size())) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + const ucharT *ptrs1 = UV._data, *ptrs2 = UV.data(0,0,0,1); + ucharT *ptrd1 = YUV.data(0,0,0,1), *ptrd2 = YUV.data(0,0,0,2); + const unsigned int wd = YUV._width; + switch (chroma_subsampling) { + case 420 : + cimg_forY(UV,y) { + cimg_forX(UV,x) { + const ucharT U = *(ptrs1++), V = *(ptrs2++); + ptrd1[wd] = U; *(ptrd1)++ = U; + ptrd1[wd] = U; *(ptrd1)++ = U; + ptrd2[wd] = V; *(ptrd2)++ = V; + ptrd2[wd] = V; *(ptrd2)++ = V; + } + ptrd1+=wd; ptrd2+=wd; + } + break; + case 422 : + cimg_forXY(UV,x,y) { + const ucharT U = *(ptrs1++), V = *(ptrs2++); + *(ptrd1++) = U; *(ptrd1++) = U; + *(ptrd2++) = V; *(ptrd2++) = V; + } + break; + default : + YUV.draw_image(0,0,0,1,UV); + } + if (yuv2rgb) YUV.YCbCrtoRGB(); + insert(YUV); + if (nstep_frame>1) cimg::fseek(nfile,(uint64T)(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR); + } + } + } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_yuv() : Missing data in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + if (stop_flag && nlast_frame!=~0U && frame!=nlast_frame) + cimg::warn(_cimglist_instance + "load_yuv(): Frame %d not reached since only %u frames were found in file '%s'.", + cimglist_instance, + nlast_frame,frame - 1,filename?filename:"(FILE*)"); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load an image from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read (can be higher than the actual number of frames, e.g. '~0U'). + \param step_frame Step value for frame reading. + \note If step_frame==0, the current video stream is forced to be released (without any frames read). + **/ + CImgList& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { +#ifndef cimg_use_opencv + if (first_frame || last_frame!=~0U || step_frame>1) + throw CImgArgumentException(_cimglist_instance + "load_video() : File '%s', arguments 'first_frame', 'last_frame' " + "and 'step_frame' requires features from the OpenCV library " + "('-Dcimg_use_opencv' must be defined).", + cimglist_instance,filename); + return load_custom_external(filename); +#else + static cv::VideoCapture *captures[32] = { 0 }; + static CImgList filenames(32); + static CImg positions(32,1,1,1,0); + static int last_used_index = -1; + + // Detect if a video capture already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Release stream if needed. + if (!step_frame || (index>=0 && positions[index]>first_frame)) { + if (index>=0) { + cimg::mutex(9); + captures[index]->release(); + delete captures[index]; + captures[index] = 0; + positions[index] = 0; + filenames[index].assign(); + if (last_used_index==index) last_used_index = -1; + index = -1; + cimg::mutex(9,0); + } else + if (filename) + cimg::warn(_cimglist_instance + "load_video() : File '%s', no opened video stream associated with filename found.", + cimglist_instance,filename); + else + cimg::warn(_cimglist_instance + "load_video() : No opened video stream found.", + cimglist_instance,filename); + if (!step_frame) return *this; + } + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_video(): No already open video reader found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', no video reader slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + cimg::mutex(9); + captures[index] = new cv::VideoCapture(filename); + positions[index] = 0; + if (!captures[index]->isOpened()) { + delete captures[index]; + captures[index] = 0; + cimg::mutex(9,0); + cimg::fclose(cimg::fopen(filename,"rb")); // Check file availability + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to detect format of video file.", + cimglist_instance,filename); + } + CImg::string(filename).move_to(filenames[index]); + cimg::mutex(9,0); + } + + cimg::mutex(9); + const unsigned int nb_frames = (unsigned int)std::max(0.,captures[index]->get(_cimg_cap_prop_frame_count)); + cimg::mutex(9,0); + assign(); + + // Skip frames if requested. + bool go_on = true; + unsigned int &pos = positions[index]; + while (posgrab()) { cimg::mutex(9,0); go_on = false; break; } + cimg::mutex(9,0); + ++pos; + } + + // Read and convert frames. + const unsigned int _last_frame = std::min(nb_frames?nb_frames - 1:~0U,last_frame); + while (go_on && pos<=_last_frame) { + cv::Mat cvimg; + cimg::mutex(9); + if (captures[index]->read(cvimg)) { CImg::_cvmat2cimg(cvimg).move_to(*this); ++pos; } + else go_on = false; + cimg::mutex(9,0); + if (go_on) + for (unsigned int i = 1; go_on && igrab()) go_on = false; + cimg::mutex(9,0); + } + } + + if (!go_on || (nb_frames && pos>=nb_frames)) { // Close video stream when necessary + cimg::mutex(9); + captures[index]->release(); + delete captures[index]; + captures[index] = 0; + filenames[index].assign(); + positions[index] = 0; + index = -1; + cimg::mutex(9,0); + } + + cimg::mutex(9); + last_used_index = index; + cimg::mutex(9,0); + + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to locate frame %u.", + cimglist_instance,filename,first_frame); + return *this; +#endif + } + + //! Load an image from a video file, using OpenCV library \newinstance. + static CImgList get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame); + } + + //! Load an image from a video file using the external tool 'custom'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_custom_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_custom_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%%6d.ppm",filename_tmp._data); + cimg_snprintf(command,command._width,"\"%s\" -v -8 -i \"%s\" \"%s\"", + cimg::custom_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp2)._system_strescape().data()); + cimg::system(command, cimg::custom_path()); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + unsigned int i = 1; + for (bool stop_flag = false; !stop_flag; ++i) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,i); + CImg img; + try { img.load_pnm(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + cimg::exception_mode(omode); + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_custom_external(): Failed to open file '%s' with external command 'custom'.", + cimglist_instance, + filename); + return *this; + } + + //! Load an image from a video file using the external tool 'custom' \newinstance. + static CImgList get_load_custom_external(const char *const filename) { + return CImgList().load_custom_external(filename); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gif_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_gif_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + if (!_load_gif_external(filename,false)) + if (!_load_gif_external(filename,true)) + try { assign(CImg().load_other(filename)); } catch (CImgException&) { assign(); } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_gif_external(): Failed to open file '%s'.", + cimglist_instance,filename); + return *this; + } + + CImgList& _load_gif_external(const char *const filename, const bool use_graphicsmagick=false) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.0",filename_tmp._data); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-0.png",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + if (use_graphicsmagick) cimg_snprintf(command,command._width,"%s convert \"%s\" \"%s.png\"", + cimg::graphicsmagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + else cimg_snprintf(command,command._width,"\"%s\" -coalesce \"%s\" \"%s.png\"", + cimg::imagemagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::imagemagick_path()); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + + // Try to read a single frame gif. + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png",filename_tmp._data); + CImg img; + try { img.load_png(filename_tmp2); } + catch (CImgException&) { } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + else { // Try to read animated gif + unsigned int i = 0; + for (bool stop_flag = false; !stop_flag; ++i) { + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.%u",filename_tmp._data,i); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-%u.png",filename_tmp._data,i); + try { img.load_png(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools \newinstance. + static CImgList get_load_gif_external(const char *const filename) { + return CImgList().load_gif_external(filename); + } + + //! Load a gzipped list, using external tool 'gunzip'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::gunzip_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Failed to open file '%s'.", + cimglist_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load a gzipped list, using external tool 'gunzip' \newinstance. + static CImgList get_load_gzip_external(const char *const filename) { + return CImgList().load_gzip_external(filename); + } + + //! Load images from a TIFF file. + /** + \param filename Filename to read data from. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + \param[out] voxel_size Voxel size, as stored in the filename. + \param[out] description Description, as stored in the filename. + **/ + CImgList& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + const unsigned int + nfirst_frame = first_frame::get_load_tiff(filename)); +#else +#if cimg_verbosity<3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimglist_instance + "load_tiff(): Invalid specified frame range is [%u,%u] (step %u) since " + "file '%s' contains %u image(s).", + cimglist_instance, + nfirst_frame,nlast_frame,nstep_frame,filename,nb_images); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + assign(1 + (nlast_frame - nfirst_frame)/nstep_frame); + TIFFSetDirectory(tif,0); + cimglist_for(*this,l) + _data[l]._load_tiff(tif,nfirst_frame + l*nstep_frame,bits_per_value,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimglist_instance + "load_tiff(): Failed to open file '%s'.", + cimglist_instance, + filename); + return *this; +#endif + } + + //! Load a multi-page TIFF file \newinstance. + static CImgList get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + return CImgList().load_tiff(filename,first_frame,last_frame,step_frame,bits_per_value,voxel_size,description); + } + + //@} + //---------------------------------- + // + //! \name Data Output + //@{ + //---------------------------------- + + //! Print information about the list on the standard output. + /** + \param title Label set to the information displayed. + \param display_stats Tells if image statistics must be computed and displayed. + **/ + const CImgList& print(const char *const title=0, const bool display_stats=true) const { + unsigned int msiz = 0; + cimglist_for(*this,l) msiz+=_data[l].size(); + msiz*=sizeof(T); + const unsigned int mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U; + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImgList<%s>",pixel_type()); + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%s>*)%p", + cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal, + cimg::t_bold,cimg::t_normal,(void*)this, + cimg::t_bold,cimg::t_normal,_width,_allocated_width, + mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)), + mdisp==0?"b":(mdisp==1?"Kio":"Mio"), + cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin()); + if (_data) std::fprintf(cimg::output(),"..%p.\n",(void*)((char*)end() - 1)); + else std::fprintf(cimg::output(),".\n"); + + char tmp[16] = { 0 }; + cimglist_for(*this,ll) { + cimg_snprintf(tmp,sizeof(tmp),"[%d]",ll); + std::fprintf(cimg::output()," "); + _data[ll].print(tmp,display_stats); + if (ll==3 && width()>8) { ll = width() - 5; std::fprintf(cimg::output()," ...\n"); } + } + std::fflush(cimg::output()); + return *this; + } + + //! Display the current CImgList instance in an existing CImgDisplay window (by reference). + /** + \param disp Reference to an existing CImgDisplay instance, where the current image list will be displayed. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + \note This function displays the list images of the current CImgList instance into an existing + CImgDisplay window. + Images of the list are appended in a single temporary image for visualization purposes. + The function returns immediately. + **/ + const CImgList& display(CImgDisplay &disp, const char axis='x', const float align=0) const { + disp.display(*this,axis,align); + return *this; + } + + //! Display the current CImgList instance in a new display window. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param axis Alignment axis for images viewing. + \param align Appending alignment. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + \note This function opens a new window with a specific title and displays the list images of the + current CImgList instance into it. + Images of the list are appended in a single temporary image for visualization purposes. + The function returns when a key is pressed or the display window is closed by the user. + **/ + const CImgList& display(CImgDisplay &disp, const bool display_info, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + bool is_exit = false; + return _display(disp,0,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + //! Display the current CImgList instance in a new display window. + /** + \param title Title of the opening display window. + \param display_info Tells if list information must be written on standard output. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImgList& display(const char *const title=0, const bool display_info=true, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + CImgDisplay disp; + bool is_exit = false; + return _display(disp,title,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + const CImgList& _display(CImgDisplay &disp, const char *const title, const CImgList *const titles, + const bool display_info, const char axis, const float align, unsigned int *const XYZ, + const bool exit_on_anykey, const unsigned int orig, const bool is_first_call, + bool &is_exit) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "display(): Empty instance.", + cimglist_instance); + if (!disp) { + if (axis=='x') { + unsigned int sum_width = 0, max_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + sum_width+=w; + if (h>max_height) max_height = h; + } + disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:titles?titles->__display()._data:0,1); + } else { + unsigned int max_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + sum_height+=h; + } + disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:titles?titles->__display()._data:0,1); + } + if (!title && !titles) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else if (title) disp.set_title("%s",title); + else if (titles) disp.set_title("%s",titles->__display()._data); + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(disp.title()); + disp.show().flush(); + + if (_width==1) { + const unsigned int dw = disp._width, dh = disp._height; + if (!is_first_call) + disp.resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),false); + disp.set_title("%s (%ux%ux%ux%u)", + dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum); + _data[0]._display(disp,0,false,XYZ,exit_on_anykey,!is_first_call); + if (disp.key()) is_exit = true; + disp.resize(cimg_fitscreen(dw,dh,1),false).set_title("%s",dtitle.data()); + } else { + bool disp_resize = !is_first_call; + while (!disp.is_closed() && !is_exit) { + const CImg s = _select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true); + disp_resize = true; + if (s[0]<0 && !disp.wheel()) { // No selections done + if (disp.button()&2) { disp.flush(); break; } + is_exit = true; + } else if (disp.wheel()) { // Zoom in/out + const int wheel = disp.wheel(); + disp.set_wheel(); + if (!is_first_call && wheel<0) break; + if (wheel>0 && _width>=4) { + const unsigned int + delta = std::max(1U,(unsigned int)cimg::round(0.3*_width)), + ind0 = (unsigned int)std::max(0,s[0] - (int)delta), + ind1 = (unsigned int)std::min(width() - 1,s[0] + (int)delta); + if ((ind0!=0 || ind1!=_width - 1) && ind1 - ind0>=3) { + const CImgList sublist = get_shared_images(ind0,ind1); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(ind0,ind1); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + ind0,false,is_exit); + } + } + } else if (s[0]!=0 || s[1]!=width() - 1) { + const CImgList sublist = get_shared_images(s[0],s[1]); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(s[0],s[1]); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + s[0],false,is_exit); + } + disp.set_title("%s",dtitle.data()); + } + } + return *this; + } + + // [internal] Return string to describe display title. + CImg __display() const { + CImg res, str; + cimglist_for(*this,l) { + CImg::string((char*)_data[l]).move_to(str); + if (l!=width() - 1) { + str.resize(str._width + 1,1,1,1,0); + str[str._width - 2] = ','; + str[str._width - 1] = ' '; + } + res.append(str,'x'); + } + if (!res) return CImg(1,1,1,1,0).move_to(res); + cimg::strellipsize(res,128,false); + if (_width>1) { + const unsigned int l = (unsigned int)std::strlen(res); + if (res._width<=l + 16) res.resize(l + 16,1,1,1,0); + cimg_snprintf(res._data + l,16," (#%u)",_width); + } + return res; + } + + //! Save list into a file. + /** + \param filename Filename to write data to. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + **/ + const CImgList& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save(): Specified filename is (null).", + cimglist_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:number>=0?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimglist_save_plugin + cimglist_save_plugin(fn); +#endif +#ifdef cimglist_save_plugin1 + cimglist_save_plugin1(fn); +#endif +#ifdef cimglist_save_plugin2 + cimglist_save_plugin2(fn); +#endif +#ifdef cimglist_save_plugin3 + cimglist_save_plugin3(fn); +#endif +#ifdef cimglist_save_plugin4 + cimglist_save_plugin4(fn); +#endif +#ifdef cimglist_save_plugin5 + cimglist_save_plugin5(fn); +#endif +#ifdef cimglist_save_plugin6 + cimglist_save_plugin6(fn); +#endif +#ifdef cimglist_save_plugin7 + cimglist_save_plugin7(fn); +#endif +#ifdef cimglist_save_plugin8 + cimglist_save_plugin8(fn); +#endif + if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg") || !*ext) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,444,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); +#ifdef cimg_use_tiff + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); +#endif + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + else { + if (_width==1) _data[0].save(fn,-1); + else cimglist_for(*this,l) { _data[l].save(fn,is_stdout?-1:l); if (is_stdout) std::fputc(EOF,cimg::_stdout()); } + } + return *this; + } + + //! Tell if an image list can be saved as one single file. + /** + \param filename Filename, as a C-string. + \return \c true if the file format supports multiple images, \c false otherwise. + **/ + static bool is_saveable(const char *const filename) { + const char *const ext = cimg::split_filename(filename); + if (!cimg::strcasecmp(ext,"cimgz") || +#ifdef cimg_use_tiff + !cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff") || +#endif + !cimg::strcasecmp(ext,"yuv") || + !cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return true; + return false; + } + + //! Save image sequence as a GIF animated file. + /** + \param filename Filename to write data to. + \param fps Number of desired frames per second. + \param nb_loops Number of loops (\c 0 for infinite looping). + **/ + const CImgList& save_gif_external(const char *const filename, const float fps=25, + const unsigned int nb_loops=0) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + +#ifdef cimg_use_png +#define _cimg_save_gif_extension "png" +#else +#define _cimg_save_gif_extension "ppm" +#endif + + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001." _cimg_save_gif_extension,filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u." _cimg_save_gif_extension,filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save(filename_tmp2); + else _data[l].save(filename_tmp2); + } + cimg_snprintf(command,command._width,"\"%s\" -delay %u -loop %u", + cimg::imagemagick_path(),(unsigned int)std::max(0.f,cimg::round(100/fps)),nb_loops); + CImg::string(command).move_to(filenames,0); + cimg_snprintf(command,command._width,"\"%s\"", + CImg::string(filename)._system_strescape().data()); + CImg::string(command).move_to(filenames); + CImg _command = filenames>'x'; + cimg_for(_command,p,char) if (!*p) *p = ' '; + _command.back() = 0; + + cimg::system(_command, cimg::imagemagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for_in(*this,1,filenames._width - 1,l) std::remove(filenames[l]); + return *this; + } + + //! Save list as a YUV image sequence file. + /** + \param filename Filename to write data to. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(const char *const filename=0, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + return _save_yuv(0,filename,chroma_subsampling,is_rgb); + } + + //! Save image sequence into a YUV file. + /** + \param file File to write data to. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(std::FILE *const file, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + return _save_yuv(file,0,chroma_subsampling,is_rgb); + } + + const CImgList& _save_yuv(std::FILE *const file, const char *const filename, + const unsigned int chroma_subsampling, + const bool is_rgb) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified filename is (null).", + cimglist_instance); + if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified chroma subsampling %u is invalid, for file '%s'.", + cimglist_instance, + chroma_subsampling,filename?filename:"(FILE*)"); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + const unsigned int + cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1, + cfy = chroma_subsampling==420?2:1, + w0 = (*this)[0]._width, h0 = (*this)[0]._height, + width0 = w0 + (w0%cfx), height0 = h0 + (h0%cfy); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + cimglist_for(*this,l) { + const CImg &frame = (*this)[l]; + cimg_forZ(frame,z) { + CImg YUV; + if (sizeof(T)==1 && !is_rgb && + frame._width==width0 && frame._height==height0 && frame._depth==1 && frame._spectrum==3) + YUV.assign((unsigned char*)frame._data,width0,height0,1,3,true); + else { + YUV = frame.get_slice(z); + if (YUV._width!=width0 || YUV._height!=height0) YUV.resize(width0,height0,1,-100,0); + if (YUV._spectrum!=3) YUV.resize(-100,-100,1,3,YUV._spectrum==1?1:0); + if (is_rgb) YUV.RGBtoYCbCr(); + } + if (chroma_subsampling==444) + cimg::fwrite(YUV._data,(size_t)YUV._width*YUV._height*3,nfile); + else { + cimg::fwrite(YUV._data,(size_t)YUV._width*YUV._height,nfile); + CImg UV = YUV.get_channels(1,2); + UV.resize(UV._width/cfx,UV._height/cfy,1,2,2); + cimg::fwrite(UV._data,(size_t)UV._width*UV._height*2,nfile); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param filename Filename to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(const char *const filename, const bool is_compressed=false) const { + return _save_cimg(0,filename,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, const bool is_compressed) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "save_cimg(): Unable to save compressed data in file '%s' unless zlib is enabled, " + "saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); +#endif + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const bool is_bool = ptype==cimg::type::string(); + if (!is_bool && std::strstr(ptype,"unsigned")==ptype) + std::fprintf(nfile,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + std::fprintf(nfile,"%u %s %s_endian\n",_width,ptype,etype); + + cimglist_for(*this,l) { + const CImg& img = _data[l]; + std::fprintf(nfile,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + Bytef *cbuf = 0; + uLongf csiz = 0; + + if (is_bool) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = ref._bool2uchar(siz,false); + csiz = siz + siz/100 + 16; + cbuf = new Bytef[csiz]; + failed_to_compress = (bool)compress(cbuf,&csiz,(Bytef*)buf,siz); + if (!failed_to_compress) { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + } + delete[] buf; + } else { // Non-boolean data + const ulongT siz = sizeof(T)*ref.size(); + csiz = siz + siz/100 + 16; + cbuf = new Bytef[csiz]; + failed_to_compress = (bool)compress(cbuf,&csiz,(Bytef*)ref._data,siz); + if (!failed_to_compress) { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + } + } + if (failed_to_compress) + cimg::warn(_cimglist_instance + "save_cimg(): Failed to save compressed data for file '%s', saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); + delete[] cbuf; +#endif + } + if (failed_to_compress) { // Write non-compressed + std::fputc('\n',nfile); + if (is_bool) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = ref._bool2uchar(siz,false); + cimg::fwrite(buf,siz,nfile); + delete[] buf; + } else cimg::fwrite(ref._data,ref.size(),nfile); // Non-boolean data + } + } else std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param file File to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(std::FILE *file, const bool is_compressed=false) const { + return _save_cimg(file,0,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { +#define _cimg_save_cimg_case(Ts,Tss) \ + if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l0) { \ + if (l=W || y0>=H || z0>=D || c0>=D) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const CImg& img = (*this)[l - n0]; \ + const T *ptrs = img._data; \ + const unsigned int \ + x1 = x0 + img._width - 1, \ + y1 = y0 + img._height - 1, \ + z1 = z0 + img._depth - 1, \ + c1 = c0 + img._spectrum - 1, \ + nx1 = x1>=W?W - 1:x1, \ + ny1 = y1>=H?H - 1:y1, \ + nz1 = z1>=D?D - 1:z1, \ + nc1 = c1>=C?C - 1:c1; \ + CImg raw(1 + nx1 - x0); \ + const unsigned int skipvb = c0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int v = 1 + nc1 - c0; v; --v) { \ + const unsigned int skipzb = z0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + nz1 - z0; z; --z) { \ + const unsigned int skipyb = y0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + ny1 - y0; y; --y) { \ + const unsigned int skipxb = x0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + raw.assign(ptrs, raw._width); \ + ptrs+=img._width; \ + if (endian) cimg::invert_endianness(raw._data,raw._width); \ + cimg::fwrite(raw._data,raw._width,nfile); \ + const unsigned int skipxe = (W - 1 - nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const unsigned int skipye = (H - 1 - ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const unsigned int skipze = (D - 1 - nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const unsigned int skipve = (C - 1 - nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_cimg(): Empty instance, for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb+"); + bool saved = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + const unsigned int lmax = std::min(N,n0 + _width); + _cimg_save_cimg_case("bool",bool); + _cimg_save_cimg_case("unsigned_char",unsigned char); + _cimg_save_cimg_case("uchar",unsigned char); + _cimg_save_cimg_case("char",char); + _cimg_save_cimg_case("unsigned_short",unsigned short); + _cimg_save_cimg_case("ushort",unsigned short); + _cimg_save_cimg_case("short",short); + _cimg_save_cimg_case("unsigned_int",unsigned int); + _cimg_save_cimg_case("uint",unsigned int); + _cimg_save_cimg_case("int",int); + _cimg_save_cimg_case("unsigned_int64",uint64T); + _cimg_save_cimg_case("uint64",uint64T); + _cimg_save_cimg_case("int64",int64T); + _cimg_save_cimg_case("float",float); + _cimg_save_cimg_case("double",double); + if (!saved) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): Unsupported data type '%s' for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)",str_pixeltype._data); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param filename Filename to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(0,filename,n0,x0,y0,z0,c0); + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param file File to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(file,0,n0,x0,y0,z0,c0); + } + + static void _save_empty_cimg(std::FILE *const file, const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT siz = (ulongT)dx*dy*dz*dc*sizeof(T); + std::fprintf(nfile,"%u %s\n",nb,pixel_type()); + for (unsigned int i=nb; i; --i) { + std::fprintf(nfile,"%u %u %u %u\n",dx,dy,dz,dc); + for (ulongT off = siz; off; --off) std::fputc(0,nfile); + } + if (!file) cimg::fclose(nfile); + } + + //! Save empty (non-compressed) .cimg file with specified dimensions. + /** + \param filename Filename to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(0,filename,nb,dx,dy,dz,dc); + } + + //! Save empty .cimg file with specified dimensions. + /** + \param file File to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(file,0,nb,dx,dy,dz,dc); + } + + //! Save list as a TIFF file. + /** + \param filename Filename to write data to. + \param compression_type Compression mode used to write data. + \param voxel_size Voxel size, to be stored in the filename. + \param description Description, to be stored in the filename. + \param use_bigtiff Allow to save big tiff files (>4Gb). + **/ + const CImgList& save_tiff(const char *const filename, const unsigned int compression_type=0, + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_tiff(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_tiff + if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,use_bigtiff); + else cimglist_for(*this,l) { + CImg nfilename(1024); + cimg::number_filename(filename,l,6,nfilename); + _data[l].save_tiff(nfilename,compression_type,voxel_size,description,use_bigtiff); + } +#else + ulongT siz = 0; + cimglist_for(*this,l) siz+=_data[l].size(); + const bool _use_bigtiff = use_bigtiff && sizeof(siz)>=8 && siz*sizeof(T)>=1UL<<31; // No bigtiff for small images + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + for (unsigned int dir = 0, l = 0; l<_width; ++l) { + const CImg& img = (*this)[l]; + cimg_forZ(img,z) img._save_tiff(tif,dir++,z,compression_type,voxel_size,description); + } + TIFFClose(tif); + } else + throw CImgIOException(_cimglist_instance + "save_tiff(): Failed to open stream for file '%s'.", + cimglist_instance, + filename); +#endif + return *this; + } + + //! Save list as a gzipped file, using external tool 'gzip'. + /** + \param filename Filename to write data to. + **/ + const CImgList& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Specified filename is (null).", + cimglist_instance); + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + + if (is_saveable(body)) { + save(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::gzip_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimglist_instance, + filename); + else cimg::fclose(file); + std::remove(filename_tmp); + } else { + CImg nfilename(1024); + cimglist_for(*this,l) { + cimg::number_filename(body,l,6,nfilename); + if (*ext) cimg_sprintf(nfilename._data + std::strlen(nfilename),".%s",ext); + _data[l].save_gzip_external(nfilename); + } + } + return *this; + } + + //! Save image sequence (using the OpenCV library when available). + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImgList& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { +#ifndef cimg_use_opencv + cimg::unused(codec,keep_open); + return save_custom_external(filename,fps); +#else + try { + static cv::VideoWriter *writers[32] = { 0 }; + static CImgList filenames(32); + static CImg sizes(32,2,1,1,0); + static int last_used_index = -1; + + // Detect if a video writer already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_video(): No already open video writer found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', no video writer slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_video(): Instance list is empty.", + cimglist_instance); + const unsigned int W = _data?_data[0]._width:0, H = _data?_data[0]._height:0; + if (!W || !H) + throw CImgInstanceException(_cimglist_instance + "save_video(): Frame [0] is an empty image.", + cimglist_instance); + const char + *const _codec = codec && *codec?codec:"h264", + codec0 = cimg::uppercase(_codec[0]), + codec1 = _codec[0]?cimg::uppercase(_codec[1]):0, + codec2 = _codec[1]?cimg::uppercase(_codec[2]):0, + codec3 = _codec[2]?cimg::uppercase(_codec[3]):0; + cimg::mutex(9); + writers[index] = new cv::VideoWriter(filename,_cimg_fourcc(codec0,codec1,codec2,codec3),fps,cv::Size(W,H)); + if (!writers[index]->isOpened()) { + delete writers[index]; + writers[index] = 0; + cimg::mutex(9,0); + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', unable to initialize video writer with codec '%c%c%c%c'.", + cimglist_instance,filename, + codec0,codec1,codec2,codec3); + } + CImg::string(filename).move_to(filenames[index]); + sizes(index,0) = W; + sizes(index,1) = H; + cimg::mutex(9,0); + } + + if (!is_empty()) { + const unsigned int W = sizes(index,0), H = sizes(index,1); + cimg::mutex(9); + cimglist_for(*this,l) { + CImg &src = _data[l]; + if (src.is_empty()) + cimg::warn(_cimglist_instance + "save_video(): Skip empty frame %d for file '%s'.", + cimglist_instance,l,filename); + if (src._depth>1 || src._spectrum>3) + cimg::warn(_cimglist_instance + "save_video(): Frame %u has incompatible dimension (%u,%u,%u,%u). " + "Some image data may be ignored when writing frame into video file '%s'.", + cimglist_instance,l,src._width,src._height,src._depth,src._spectrum,filename); + if (src._width==W && src._height==H && src._spectrum==3) + writers[index]->write(CImg(src)._cimg2cvmat()); + else { + CImg _src(src,false); + _src.channels(0,std::min(_src._spectrum - 1,2U)).resize(W,H); + _src.resize(W,H,1,3,_src._spectrum==1); + writers[index]->write(_src._cimg2cvmat()); + } + } + cimg::mutex(9,0); + } + + cimg::mutex(9); + if (!keep_open) { + delete writers[index]; + writers[index] = 0; + filenames[index].assign(); + sizes(index,0) = sizes(index,1) = 0; + last_used_index = -1; + } else last_used_index = index; + cimg::mutex(9,0); + } catch (CImgIOException &e) { + if (!keep_open) return save_custom_external(filename,fps); + throw e; + } + return *this; +#endif + } + + //! Save image sequence, using the external tool 'custom'. + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression. + \param bitrate Output bitrate + **/ + const CImgList& save_custom_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_custom_external(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + const char + *const ext = cimg::split_filename(filename), + *const _codec = codec?codec: + !cimg::strcasecmp(ext,"flv")?"flv": + !cimg::strcasecmp(ext,"mp4")?"h264":"mpeg2video"; + + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + cimglist_for(*this,l) if (!_data[l].is_sameXYZ(_data[0])) + throw CImgInstanceException(_cimglist_instance + "save_custom_external(): Invalid instance dimensions for file '%s'.", + cimglist_instance, + filename); + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + CImg tmp = _data[l].get_shared(); + if (tmp._width%2 || tmp._height%2) // Force output to have an even number of columns and rows + tmp.assign(tmp.get_resize(tmp._width + (tmp._width%2),tmp._height + (tmp._height%2),1,-100,0),false); + if (tmp._depth>1 || tmp._spectrum!=3) // Force output to be one slice, in color + tmp.assign(tmp.get_resize(-100,-100,1,3),false); + tmp.save_pnm(filename_tmp2); + } + cimg_snprintf(command,command._width, + "\"%s\" -v -8 -y -i \"%s_%%6d.ppm\" -pix_fmt yuv420p -vcodec %s -b %uk -r %u \"%s\"", + cimg::custom_path(), + CImg::string(filename_tmp)._system_strescape().data(), + _codec,bitrate,fps, + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::custom_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_custom_external(): Failed to save file '%s' with external command 'custom'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for(*this,l) std::remove(filenames[l]); + return *this; + } + + //! Serialize a CImgList instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "get_serialize(): Unable to compress data unless zlib is enabled, " + "storing them uncompressed.", + cimglist_instance); +#endif + CImgList stream; + CImg tmpstr(128); + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + if (std::strstr(ptype,"unsigned")==ptype) + cimg_snprintf(tmpstr,tmpstr._width,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + cimg_snprintf(tmpstr,tmpstr._width,"%u %s %s_endian\n",_width,ptype,etype); + CImg::string(tmpstr,false).move_to(stream); + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_snprintf(tmpstr,tmpstr._width,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + CImg::string(tmpstr,false).move_to(stream); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + const ulongT siz = sizeof(T)*ref.size(); + uLongf csiz = (ulongT)compressBound(siz); + Bytef *const cbuf = new Bytef[csiz]; + if (compress(cbuf,&csiz,(Bytef*)ref._data,siz)) + cimg::warn(_cimglist_instance + "get_serialize(): Failed to save compressed data, saving them uncompressed.", + cimglist_instance); + else { + cimg_snprintf(tmpstr,tmpstr._width," #%lu\n",csiz); + CImg::string(tmpstr,false).move_to(stream); + CImg(cbuf,csiz).move_to(stream); + delete[] cbuf; + failed_to_compress = false; + } +#endif + } + if (failed_to_compress) { // Write in a non-compressed way + CImg::string("\n",false).move_to(stream); + stream.insert(1); + stream.back().assign((unsigned char*)ref._data,ref.size()*sizeof(T),1,1,1,true); + } + } else CImg::string("\n",false).move_to(stream); + } + cimglist_apply(stream,unroll)('y'); + return stream>'y'; + } + + //! Unserialize a CImg serialized buffer into a CImgList list. + template + static CImgList get_unserialize(const CImg& buffer) { +#ifdef cimg_use_zlib +#define _cimgz_unserialize_case(Tss) { \ + Bytef *cbuf = 0; \ + if (sizeof(t)!=1 || buffer.pixel_type()==cimg::type::string()) { \ + cbuf = new Bytef[csiz]; Bytef *_cbuf = cbuf; \ + for (ulongT k = 0; k::get_unserialize(): Unable to unserialize compressed data " \ + "unless zlib is enabled.", \ + pixel_type()); +#endif + +#define _cimg_unserialize_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l::unserialize(): Invalid specified size (%u,%u,%u,%u) for " \ + "image #%u in serialized buffer.", \ + pixel_type(),W,H,D,C,l); \ + if (W*H*D*C>0) { \ + CImg raw; \ + CImg &img = res._data[l]; \ + if (err==5) _cimgz_unserialize_case(Tss) \ + else { \ + raw.assign(W,H,D,C); \ + CImg _raw((unsigned char*)raw._data,W*sizeof(Tss),H,D,C,true); \ + if (sizeof(t)==1) { std::memcpy(_raw,stream,_raw.size()); stream+=_raw.size(); } \ + else cimg_for(_raw,p,unsigned char) *p = (unsigned char)*(stream++); \ + } \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } \ + } \ + loaded = true; \ + } + + if (buffer.is_empty()) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Specified serialized buffer is (null).", + pixel_type()); + CImgList res; + const t *stream = buffer._data, *const estream = buffer._data + buffer.size(); + bool loaded = false, endian = cimg::endianness(), is_bytef = false; + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + uint64T csiz; + int i, err; + cimg::unused(is_bytef); + do { + j = 0; while ((i=(int)*stream)!='\n' && stream::get_unserialize(): CImg header not found in serialized buffer.", + pixel_type()); + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + res.assign(N); + _cimg_unserialize_case("bool",bool); + _cimg_unserialize_case("unsigned_char",unsigned char); + _cimg_unserialize_case("uchar",unsigned char); + _cimg_unserialize_case("char",char); + _cimg_unserialize_case("unsigned_short",unsigned short); + _cimg_unserialize_case("ushort",unsigned short); + _cimg_unserialize_case("short",short); + _cimg_unserialize_case("unsigned_int",unsigned int); + _cimg_unserialize_case("uint",unsigned int); + _cimg_unserialize_case("int",int); + _cimg_unserialize_case("unsigned_int64",uint64T); + _cimg_unserialize_case("uint64",uint64T); + _cimg_unserialize_case("int64",int64T); + _cimg_unserialize_case("float",float); + _cimg_unserialize_case("double",double); + if (!loaded) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Unsupported pixel type '%s' defined " + "in serialized buffer.", + pixel_type(),str_pixeltype._data); + return res; + } + + //@} + //---------------------------------- + // + //! \name Others + //@{ + //---------------------------------- + + //! Return a CImg pre-defined font with requested height. + /** + \param font_height Height of the desired font (exact match for 13,23,53,103). + \param is_variable_width Decide if the font has a variable (\c true) or fixed (\c false) width. + **/ + static const CImgList& font(const unsigned int requested_height, const bool is_variable_width=true) { + if (!requested_height) return CImgList::const_empty(); + cimg::mutex(11); + static const unsigned char font_resizemap[] = { + 0, 4, 7, 9, 11, 13, 15, 17, 19, 21, 22, 24, 26, 27, 29, 30, + 32, 33, 35, 36, 38, 39, 41, 42, 43, 45, 46, 47, 49, 50, 51, 52, + 54, 55, 56, 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 162, 163, 164, 164, 165, + 166, 167, 168, 169, 170, 170, 171, 172, 173, 174, 175, 176, 176, 177, 178, 179, + 180, 181, 181, 182, 183, 184, 185, 186, 186, 187, 188, 189, 190, 191, 191, 192, + 193, 194, 195, 196, 196, 197, 198, 199, 200, 200, 201, 202, 203, 204, 205, 205, + 206, 207, 208, 209, 209, 210, 211, 212, 213, 213, 214, 215, 216, 216, 217, 218, + 219, 220, 220, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 231, + 231, 232, 233, 234, 234, 235, 236, 237, 238, 238, 239, 240, 241, 241, 242, 243, + 244, 244, 245, 246, 247, 247, 248, 249, 250, 250, 251, 252, 253, 253, 254, 255 }; + static const char *const *font_data[] = { + cimg::data_font_small, + cimg::data_font_normal, + cimg::data_font_large, + cimg::data_font_huge }; + static const unsigned int + font_width[] = { 10,26,52,104 }, + font_height[] = { 13,32,64,128 }, + font_M[] = { 86,91,91,47 }, + font_chunk[] = { sizeof(cimg::data_font_small)/sizeof(char*), + sizeof(cimg::data_font_normal)/sizeof(char*), + sizeof(cimg::data_font_large)/sizeof(char*), + sizeof(cimg::data_font_huge)/sizeof(char*) }; + static const unsigned char font_is_binary[] = { 1,0,0,1 }; + static CImg font_base[4]; + + unsigned int ind = + requested_height<=font_height[0]?0U: + requested_height<=font_height[1]?1U: + requested_height<=font_height[2]?2U:3U; + + // Decompress nearest base font data if needed. + CImg &basef = font_base[ind]; + if (!basef) { + basef.assign(256*font_width[ind],font_height[ind]); + + unsigned char *ptrd = basef; + const unsigned char *const ptrde = basef.end(); + + // Recompose font data from several chunks, to deal with MS compiler limit with big strings (64 Kb). + CImg dataf; + for (unsigned int k = 0; k::string(font_data[ind][k],k==font_chunk[ind] - 1,true),'x'); + + // Uncompress font data (decode RLE). + const unsigned int M = font_M[ind]; + if (font_is_binary[ind]) + for (const char *ptrs = dataf; *ptrs; ++ptrs) { + const int _n = (int)(*ptrs - M - 32), v = _n>=0?255:0, n = _n>=0?_n:-_n; + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + else + for (const char *ptrs = dataf; *ptrs; ++ptrs) { + int n = (int)*ptrs - M - 32, v = 0; + if (n>=0) { v = 85*n; n = 1; } + else { + n = -n; + v = (int)*(++ptrs) - M - 32; + if (v<0) { v = 0; --ptrs; } else v*=85; + } + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + } + + // Find optimal font cache location to return. + static CImgList fonts[16]; + static bool is_variable_widths[16] = { 0 }; + ind = ~0U; + for (int i = 0; i<16; ++i) + if (!fonts[i] || (is_variable_widths[i]==is_variable_width && requested_height==fonts[i][0]._height)) { + ind = (unsigned int)i; break; // Found empty slot or cached font + } + if (ind==~0U) { // No empty slots nor existing font in cache + fonts->assign(); + std::memmove((void*)fonts,(void*)(fonts + 1),15*sizeof(CImgList)); + std::memmove(is_variable_widths,is_variable_widths + 1,15*sizeof(bool)); + std::memset((void*)(fonts + (ind=15)),0,sizeof(CImgList)); // Free a slot in cache for new font + } + CImgList &font = fonts[ind]; + + // Render requested font. + if (!font) { + is_variable_widths[ind] = is_variable_width; + basef.get_split('x',256).move_to(font); + +// cimg::tic(); + + if (requested_height!=font[0]._height) + cimglist_for(font,l) { + font[l].resize(std::max(1U,font[l]._width*requested_height/font[l]._height),requested_height,-100,-100,5); + cimg_for(font[l],ptr,ucharT) *ptr = font_resizemap[*ptr]; + } + +// cimg::toc(); +// std::exit(0); + + if (is_variable_width) { // Crop font + cimglist_for(font,l) { + CImg& letter = font[l]; + int xmin = letter.width(), xmax = 0; + cimg_forX(letter,x) { // Find xmin + cimg_forY(letter,y) if (letter(x,y)) { xmin = x; break; } + if (xmin!=letter.width()) break; + } + cimg_rofX(letter,x) { // Find xmax + cimg_forY(letter,y) if (letter(x,y)) { xmax = x; break; } + if (xmax) break; + } + if (xmin<=xmax) letter.crop(xmin,0,xmax,letter._height - 1); + } + font[(int)' '].resize(font[(int)'f']._width,-100,-100,-100,0); + if (' ' + 256& FFT(const char axis, const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + CImg::FFT(_data[0],_data[1],axis,invert); + return *this; + } + + //! Compute a 1-D Fast Fourier Transform, along specified axis \newinstance. + CImgList get_FFT(const char axis, const bool invert=false) const { + return CImgList(*this,false).FFT(axis,invert); + } + + //! Compute n-D Fast Fourier Transform. + /** + \param invert Tells if the direct (\c false) or inverse transform (\c true) is computed. + **/ + CImgList& FFT(const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + + CImg::FFT(_data[0],_data[1],invert); + return *this; + } + + //! Compute n-D Fast Fourier Transform \newinstance. + CImgList get_FFT(const bool invert=false) const { + return CImgList(*this,false).FFT(invert); + } + + //! Reverse primitives orientations of a 3D object. + /** + **/ + CImgList& reverse_object3d() { + cimglist_for(*this,l) { + CImg& p = _data[l]; + switch (p.size()) { + case 2 : case 3: cimg::swap(p[0],p[1]); break; + case 6 : cimg::swap(p[0],p[1],p[2],p[4],p[3],p[5]); break; + case 9 : cimg::swap(p[0],p[1],p[3],p[5],p[4],p[6]); break; + case 4 : cimg::swap(p[0],p[1],p[2],p[3]); break; + case 12 : cimg::swap(p[0],p[1],p[2],p[3],p[4],p[6],p[5],p[7],p[8],p[10],p[9],p[11]); break; + } + } + return *this; + } + + //! Reverse primitives orientations of a 3D object \newinstance. + CImgList get_reverse_object3d() const { + return (+*this).reverse_object3d(); + } + + //@} + }; // struct CImgList { ... + + // Completion of previously declared functions + //-------------------------------------------- + namespace cimg { + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + // (throw a CImgIOException when macro 'cimg_use_r' is defined). + inline FILE* _stdin(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stdin; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stdin(): Reference to 'stdin' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + inline FILE* _stdout(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stdout; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stdout(): Reference to 'stdout' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + inline FILE* _stderr(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stderr; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stderr(): Reference to 'stderr' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + // Open a file (similar to std:: fopen(), but with wide character support on Windows). + inline std::FILE *std_fopen(const char *const path, const char *const mode) { + std::FILE *const res = std::fopen(path,mode); + if (res) return res; +#if cimg_OS==2 + // Try alternative method, with wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (err) { + CImg wpath((unsigned int)err); + err = MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err); + if (err) { // Convert 'mode' to a wide-character string + err = MultiByteToWideChar(CP_UTF8,0,mode,-1,0,0); + if (err) { + CImg wmode((unsigned int)err); + if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wmode,err)) + return _wfopen(wpath,wmode); + } + } + } +#endif + return 0; + } + + //! Search path of an executable (Windows only). +#if cimg_OS==2 + inline bool win_searchpath(const char *const exec_name, char *const res, const unsigned int size_res) { + char *ptr = 0; + DWORD err = SearchPathA(0,exec_name,0,size_res,res,&ptr); + return err!=0; + } +#endif + + //! Get the file or directory attributes with support for UTF-8 paths (Windows only). +#if cimg_OS==2 + inline DWORD win_getfileattributes(const char *const path) { + DWORD res = GetFileAttributesA(path); + if (res==INVALID_FILE_ATTRIBUTES) { + // Try alternative method, with wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (err) { + CImg wpath((unsigned int)err); + if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err)) res = GetFileAttributesW(wpath); + } + } + return res; + } +#endif + + //! Get/set path to the Program Files/ directory (Windows only). + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the program files. + **/ +#if cimg_OS==2 + inline const char* win_programfiles_path(const char *const user_path=0, const bool reinit_path=false) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(MAX_PATH); + *s_path = 0; + // Note: in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler). +#if !defined(__INTEL_COMPILER) + if (!SHGetSpecialFolderPathA(0,s_path,0x0026,false)) { + const char *const pfPath = std::getenv("PROGRAMFILES"); + if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH - 1); + else std::strcpy(s_path,"C:\\PROGRA~1"); + } +#else + std::strcpy(s_path,"C:\\PROGRA~1"); +#endif + } + cimg::mutex(7,0); + return s_path; + } +#endif + + //! Get/set path to the \c curl binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c curl binary. + **/ + inline const char *curl_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("curl.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\curl.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./curl"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c dcraw binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c dcraw binary. + **/ + inline const char *dcraw_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("dcraw.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\dcraw.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./dcraw"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the custom's \c custom binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c custom binary. + **/ + inline const char *custom_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("custom.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\custom.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"custom.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./custom"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"custom"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the GraphicsMagick's \c gm binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gm binary. + **/ + inline const char* graphicsmagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gm.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\gm.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gm"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gunzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gunzip binary. + **/ + inline const char *gunzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gunzip.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\gunzip.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gunzip"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gzip binary. + **/ + inline const char *gzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gzip.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\gzip.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gzip"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the ImageMagick's \c convert binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c convert binary. + **/ + inline const char* imagemagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("magick.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + for (int l = 0; l<2 && !path_found; ++l) { + const char *const s_exe = l?"convert":"magick"; + cimg_snprintf(s_path,s_path._width,".\\%s.exe",s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) cimg_snprintf(s_path,s_path._width,"%s.exe",s_exe); + } +#else + std::strcpy(s_path,"./magick"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + if (!path_found) { + std::strcpy(s_path,"./convert"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"convert"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the Medcon's \c medcon binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c medcon binary. + **/ + inline const char* medcon_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("medcon.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\medcon.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.bat",pf_path); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.exe",pf_path); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + std::strcpy(s_path,"C:\\XMedCon\\bin\\medcon.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./medcon"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to store temporary files. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path where temporary files can be saved. + **/ + inline const char* temporary_path(const char *const user_path, const bool reinit_path) { +#define _cimg_test_temporary_path(p) \ + if (!path_found) { \ + cimg_snprintf(s_path,s_path._width,"%s",p); \ + cimg_snprintf(tmp,tmp._width,"%s%c%s",s_path.data(),cimg_file_separator,filename_tmp._data); \ + if ((file=cimg::std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } \ + } + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + CImg tmp(1024), filename_tmp(256); + std::FILE *file = 0; + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.tmp",cimg::filenamerand()); + char *tmpPath = std::getenv("TMP"); + if (!tmpPath) { tmpPath = std::getenv("TEMP"); winformat_string(tmpPath); } + if (tmpPath) _cimg_test_temporary_path(tmpPath); +#if cimg_OS==2 + _cimg_test_temporary_path("C:\\WINNT\\Temp"); + _cimg_test_temporary_path("C:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("C:\\Temp"); + _cimg_test_temporary_path("C:"); + _cimg_test_temporary_path("D:\\WINNT\\Temp"); + _cimg_test_temporary_path("D:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("D:\\Temp"); + _cimg_test_temporary_path("D:"); +#else + _cimg_test_temporary_path("/tmp"); + _cimg_test_temporary_path("/var/tmp"); +#endif + if (!path_found) { + *s_path = 0; + std::strncpy(tmp,filename_tmp,tmp._width - 1); + if ((file=cimg::std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } + } + if (!path_found) { + cimg::mutex(7,0); + throw CImgIOException("cimg::temporary_path(): Failed to locate path for writing temporary files.\n"); + } + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c wget binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c wget binary. + **/ + inline const char *wget_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("wget.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\wget.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./wget"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + + // [internal] Sorting function, used by cimg::files(). + inline int _sort_files(const void* a, const void* b) { + const CImg &sa = *(CImg*)a, &sb = *(CImg*)b; + return std::strcmp(sa._data,sb._data); + } + + //! Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str) { + if (!filename) { if (str) *str = 0; return 0; } + const unsigned int siz = (unsigned int)std::strlen(filename); + CImg format(16), body(siz + 32); + const char *const ext = cimg::split_filename(filename,body); + if (*ext) cimg_snprintf(format,format._width,"%%s_%%.%ud.%%s",digits); + else cimg_snprintf(format,format._width,"%%s_%%.%ud",digits); + cimg_snprintf(str,1024,format._data,body._data,number,ext); + return str; + } + + //! Return list of files/directories in specified directory. + /** + \param path Path to the directory. Set to 0 for current directory. + \param is_pattern Tell if specified path has a matching pattern in it. + \param mode Output type, can be primary { 0=files only | 1=folders only | 2=files + folders }. + \param include_path Tell if \c path must be included in resulting filenames. + \return A list of filenames. + **/ + inline CImgList files(const char *const path, const bool is_pattern=false, + const unsigned int mode=2, const bool include_path=false) { + if (!path || !*path) return files("*",true,mode,include_path); + CImgList res; + + // If path is a valid folder name, ignore argument 'is_pattern'. + const bool _is_pattern = is_pattern && !cimg::is_directory(path); + bool is_root = false, is_current = false; + cimg::unused(is_root,is_current); + + // Clean format of input path. + CImg pattern, _path = CImg::string(path); +#if cimg_OS==2 + for (char *ps = _path; *ps; ++ps) if (*ps=='\\') *ps='/'; +#endif + char *pd = _path; + for (char *ps = pd; *ps; ++ps) { if (*ps!='/' || *ps!=*(ps+1)) *(pd++) = *ps; } + *pd = 0; + unsigned int lp = (unsigned int)std::strlen(_path); + if (!_is_pattern && lp && _path[lp - 1]=='/') { + _path[lp - 1] = 0; --lp; +#if cimg_OS!=2 + is_root = !*_path; +#endif + } + + // Separate folder path and matching pattern. + if (_is_pattern) { + const unsigned int bpos = (unsigned int)(cimg::basename(_path,'/') - _path.data()); + CImg::string(_path).move_to(pattern); + if (bpos) { + _path[bpos - 1] = 0; // End 'path' at last slash +#if cimg_OS!=2 + is_root = !*_path; +#endif + } else { // No path to folder specified, assuming current folder + is_current = true; *_path = 0; + } + lp = (unsigned int)std::strlen(_path); + } + + // Windows version. +#if cimg_OS==2 + if (!_is_pattern) { + pattern.assign(lp + 3); + std::memcpy(pattern,_path,lp); + pattern[lp] = '/'; pattern[lp + 1] = '*'; pattern[lp + 2] = 0; + } + WIN32_FIND_DATAA file_data; + const HANDLE dir = FindFirstFileA(pattern.data(),&file_data); + if (dir==INVALID_HANDLE_VALUE) return CImgList::const_empty(); + do { + const char *const filename = file_data.cFileName; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode>=2) { + if (include_path) { + CImg full_filename((lp?lp+1:0) + lf + 1); + if (lp) { std::memcpy(full_filename,_path,lp); full_filename[lp] = '/'; } + std::memcpy(full_filename._data + (lp?lp + 1:0),filename,lf + 1); + full_filename.move_to(res); + } else CImg(filename,lf + 1).move_to(res); + } + } + } while (FindNextFileA(dir,&file_data)); + FindClose(dir); + + // Unix version (posix). +#elif cimg_OS == 1 + DIR *const dir = opendir(is_root?"/":is_current?".":_path.data()); + if (!dir) return CImgList::const_empty(); + struct dirent *ent; + while ((ent=readdir(dir))!=0) { + const char *const filename = ent->d_name; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + CImg full_filename(lp + lf + 2); + + if (!is_current) { + full_filename.assign(lp + lf + 2); + if (lp) std::memcpy(full_filename,_path,lp); + full_filename[lp] = '/'; + std::memcpy(full_filename._data + lp + 1,filename,lf + 1); + } else full_filename.assign(filename,lf + 1); + + struct stat st; + if (stat(full_filename,&st)==-1) continue; + const bool is_directory = (st.st_mode & S_IFDIR)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode==2) { + if (include_path) { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + full_filename.move_to(res); + } else { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + CImg(filename,lf + 1).move_to(res); + } + } + } + } + closedir(dir); +#endif + + // Sort resulting list by lexicographic order. + if (res._width>=2) std::qsort(res._data,res._width,sizeof(CImg),_sort_files); + + return res; + } + + //! Try to guess format from an image file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + \return C-string containing the guessed file format, or \c 0 if nothing has been guessed. + **/ + inline const char *ftype(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::ftype(): Specified filename is (null)."); + static const char + *const _pnm = "pnm", + *const _pfm = "pfm", + *const _bmp = "bmp", + *const _gif = "gif", + *const _jpg = "jpg", + *const _off = "off", + *const _pan = "pan", + *const _png = "png", + *const _tif = "tif", + *const _inr = "inr", + *const _dcm = "dcm"; + const char *f_type = 0; + CImg header; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + header._load_raw(file,filename,512,1,1,1,false,false,0); + const unsigned char *const uheader = (unsigned char*)header._data; + if (!std::strncmp(header,"OFF\n",4)) f_type = _off; // OFF + else if (!std::strncmp(header,"#INRIMAGE",9)) // INRIMAGE + f_type = _inr; + else if (!std::strncmp(header,"PANDORE",7)) // PANDORE + f_type = _pan; + else if (!std::strncmp(header.data() + 128,"DICM",4)) // DICOM + f_type = _dcm; + else if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) // JPEG + f_type = _jpg; + else if (header[0]=='B' && header[1]=='M') // BMP + f_type = _bmp; + else if (header[0]=='G' && header[1]=='I' && header[2]=='F' && header[3]=='8' && header[5]=='a' && + (header[4]=='7' || header[4]=='9')) // GIF + f_type = _gif; + else if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 && + uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) // PNG + f_type = _png; + else if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) // TIFF + f_type = _tif; + else { // PNM or PFM + CImgList _header = header.get_split(CImg::vector('\n'),0,false); + cimglist_for(_header,l) { + if (_header(l,0)=='#') continue; + if (_header[l]._width==2 && _header(l,0)=='P') { + const char c = _header(l,1); + if (c=='f' || c=='F') { f_type = _pfm; break; } + if (c>='1' && c<='9') { f_type = _pnm; break; } + } + f_type = 0; break; + } + } + } catch (CImgIOException&) { } + cimg::exception_mode(omode); + return f_type; + } + + //! Load file from network as a local temporary file. + /** + \param url URL of the filename, as a C-string. + \param[out] filename_local C-string containing the path to a local copy of \c filename. + \param timeout Maximum time (in seconds) authorized for downloading the file from the URL. + \param try_fallback When using libcurl, tells using system calls as fallbacks in case of libcurl failure. + \param referer Referer used, as a C-string. + \return Value of \c filename_local. + \note Use the \c libcurl library, or the external binaries \c wget or \c curl to perform the download. + **/ + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout, const bool try_fallback, + const char *const referer) { + if (!url) + throw CImgArgumentException("cimg::load_network(): Specified URL is (null)."); + if (!filename_local) + throw CImgArgumentException("cimg::load_network(): Specified destination string is (null)."); + if (!network_mode()) + throw CImgIOException("cimg::load_network(): Loading files from network is disabled."); + + const char *const __ext = cimg::split_filename(url), *const _ext = (*__ext && __ext>url)?__ext - 1:__ext; + CImg ext = CImg::string(_ext); + std::FILE *file = 0; + *filename_local = 0; + if (ext._width>16 || !cimg::strncasecmp(ext,"cgi",3)) *ext = 0; + else cimg::strwindows_reserved(ext); + do { + cimg_snprintf(filename_local,256,"%s%c%s%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext._data); + if ((file=cimg::std_fopen(filename_local,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_curl + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + CURL *curl = 0; + CURLcode res; + curl = curl_easy_init(); + if (curl) { + file = cimg::fopen(filename_local,"wb"); + curl_easy_setopt(curl,CURLOPT_URL,url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,0); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,file); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0L); + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L); + if (timeout) curl_easy_setopt(curl,CURLOPT_TIMEOUT,(long)timeout); + if (std::strchr(url,'?')) curl_easy_setopt(curl,CURLOPT_HTTPGET,1L); + if (referer) curl_easy_setopt(curl,CURLOPT_REFERER,referer); + res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + cimg::fseek(file,0,SEEK_END); // Check if file size is 0 + const cimg_ulong siz = cimg::ftell(file); + cimg::fclose(file); + if (siz>0 && res==CURLE_OK) { + cimg::exception_mode(omode); + return filename_local; + } else std::remove(filename_local); + } + } catch (...) { } + cimg::exception_mode(omode); + if (!try_fallback) throw CImgIOException("cimg::load_network(): Failed to load file '%s' with libcurl.",url); +#endif + + CImg command((unsigned int)std::strlen(url) + 64); + cimg::unused(try_fallback); + + // Try with 'curl' first. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" -e %s -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,timeout,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),timeout,filename_local, + CImg::string(url)._system_strescape().data()); + } else { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" -e %s -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),filename_local, + CImg::string(url)._system_strescape().data()); + } + cimg::system(command, cimg::curl_path()); + + if (!(file=cimg::std_fopen(filename_local,"rb"))) { + + // Try with 'wget' otherwise. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" --referer=%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,timeout,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),timeout,filename_local, + CImg::string(url)._system_strescape().data()); + } else { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" --referer=%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),filename_local, + CImg::string(url)._system_strescape().data()); + } + cimg::system(command, cimg::wget_path()); + + if (!(file=cimg::std_fopen(filename_local,"rb"))) + throw CImgIOException("cimg::load_network(): Failed to load file '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + + // Try gunzip it. + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(filename_local,command); + cimg_snprintf(command,command._width,"\"%s\" --quiet \"%s.gz\"", + gunzip_path(),filename_local); + cimg::system(command, gunzip_path()); + file = cimg::std_fopen(filename_local,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(command,filename_local); + file = cimg::std_fopen(filename_local,"rb"); + } + } + cimg::fseek(file,0,SEEK_END); // Check if file size is 0 + if (std::ftell(file)<=0) + throw CImgIOException("cimg::load_network(): Failed to load URL '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + return filename_local; + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_uint64 tictoc(const bool is_tic) { + cimg::mutex(2); + static CImg times(64); + static unsigned int pos = 0; + const cimg_uint64 t1 = cimg::time(); + if (is_tic) { + // Tic + times[pos++] = t1; + if (pos>=times._width) + throw CImgArgumentException("cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'."); + cimg::mutex(2,0); + return t1; + } + + // Toc + if (!pos) + throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made."); + const cimg_uint64 + t0 = times[--pos], + dt = t1>=t0?(t1 - t0):cimg::type::max(); + const unsigned int + edays = (unsigned int)(dt/86400000.), + ehours = (unsigned int)((dt - edays*86400000.)/3600000.), + emin = (unsigned int)((dt - edays*86400000. - ehours*3600000.)/60000.), + esec = (unsigned int)((dt - edays*86400000. - ehours*3600000. - emin*60000.)/1000.), + ems = (unsigned int)(dt - edays*86400000. - ehours*3600000. - emin*60000. - esec*1000.); + if (!edays && !ehours && !emin && !esec) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ems,cimg::t_normal); + else { + if (!edays && !ehours && !emin) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",esec,ems,cimg::t_normal); + else { + if (!edays && !ehours) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",emin,esec,ems,cimg::t_normal); + else{ + if (!edays) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ehours,emin,esec,ems,cimg::t_normal); + else{ + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u days %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",edays,ehours,emin,esec,ems,cimg::t_normal); + } + } + } + } + cimg::mutex(2,0); + return dt; + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size) { + static CImg res(256); + cimg::mutex(5); + if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",(unsigned long)size,size>1?"s":""); + else if (size<1024*1024LU) { const float nsize = size/1024.f; cimg_snprintf(res,res._width,"%.1f Kio",nsize); } + else if (size<1024*1024*1024LU) { + const float nsize = size/(1024*1024.f); cimg_snprintf(res,res._width,"%.1f Mio",nsize); + } else { const float nsize = size/(1024*1024*1024.f); cimg_snprintf(res,res._width,"%.1f Gio",nsize); } + cimg::mutex(5,0); + return res; + } + + //! Display a simple dialog box, and wait for the user's response. + /** + \param title Title of the dialog window. + \param msg Main message displayed inside the dialog window. + \param button1_label Label of the 1st button. + \param button2_label Label of the 2nd button (\c 0 to hide button). + \param button3_label Label of the 3rd button (\c 0 to hide button). + \param button4_label Label of the 4th button (\c 0 to hide button). + \param button5_label Label of the 5th button (\c 0 to hide button). + \param button6_label Label of the 6th button (\c 0 to hide button). + \param logo Image logo displayed at the left of the main message. + \param is_centered Tells if the dialog window must be centered on the screen. + \return Index of clicked button (from \c 0 to \c 5), or \c -1 if the dialog window has been closed by the user. + \note + - Up to 6 buttons can be defined in the dialog window. + - The function returns when a user clicked one of the button or closed the dialog window. + - If a button text is set to 0, the corresponding button (and the following) will not appear in the dialog box. + At least one button must be specified. + **/ + template + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const CImg& logo, const bool is_centered=false) { +#if cimg_display==0 + cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + logo._data,is_centered); + throw CImgIOException("cimg::dialog(): No display available."); +#else + static const unsigned char + black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 }; + + // Create buttons and canvas graphics + CImgList buttons, cbuttons, sbuttons; + if (button1_label) { + CImg().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons); + if (button2_label) { + CImg().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons); + if (button3_label) { + CImg().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons); + if (button4_label) { + CImg().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons); + if (button5_label) { + CImg().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons); + if (button6_label) { + CImg().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons); + }}}}}} + if (!buttons._width) + throw CImgArgumentException("cimg::dialog(): No buttons have been defined."); + cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3); + + unsigned int bw = 0, bh = 0; + cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); } + bw+=8; bh+=8; + if (bw<64) bw = 64; + if (bw>128) bw = 128; + if (bh<24) bh = 24; + if (bh>48) bh = 48; + + CImg button(bw,bh,1,3); + button.draw_rectangle(0,0,bw - 1,bh - 1,gray); + button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white); + button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black); + button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2); + CImg sbutton(bw,bh,1,3); + sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray); + sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black); + sbutton.draw_line(bw - 1,bh - 1,0,bh - 1,black).draw_line(0,bh - 1,0,0,black); + sbutton.draw_line(1,1,bw - 2,1,white).draw_line(1,bh - 2,1,1,white); + sbutton.draw_line(bw - 2,1,bw - 2,bh - 2,black).draw_line(bw - 2,bh - 2,1,bh - 2,black); + sbutton.draw_line(2,bh - 3,bw - 3,bh - 3,gray2).draw_line(bw - 3,bh - 3,bw - 3,2,gray2); + sbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true). + draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + sbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false). + draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + CImg cbutton(bw,bh,1,3); + cbutton.draw_rectangle(0,0,bw - 1,bh - 1,black).draw_rectangle(1,1,bw - 2,bh - 2,gray2). + draw_rectangle(2,2,bw - 3,bh - 3,gray); + cbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true). + draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + cbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false). + draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + + cimglist_for(buttons,ll) { + CImg(cbutton). + draw_image(1 + (bw -buttons[ll].width())/2,1 + (bh - buttons[ll].height())/2,buttons[ll]). + move_to(cbuttons); + CImg(sbutton). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(sbuttons); + CImg(button). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(buttons[ll]); + } + + CImg canvas; + if (msg) + ((CImg().draw_text(0,0,"%s",gray,0,1,13,msg)*=-1)+=200).resize(-100,-100,1,3).move_to(canvas); + + const unsigned int + bwall = (buttons._width - 1)*(12 + bw) + bw, + w = cimg::max(196U,36 + logo._width + canvas._width,24 + bwall), + h = cimg::max(96U,36 + canvas._height + bh,36 + logo._height + bh), + lx = 12 + (canvas._data?0:((w - 24 - logo._width)/2)), + ly = (h - 12 - bh - logo._height)/2, + tx = lx + logo._width + 12, + ty = (h - 12 - bh - canvas._height)/2, + bx = (w - bwall)/2, + by = h - 12 - bh; + + if (canvas._data) + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black). + draw_image(tx,ty,canvas); + else + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black); + if (logo._data) canvas.draw_image(lx,ly,logo); + + unsigned int xbuttons[6] = { 0 }; + cimglist_for(buttons,lll) { + xbuttons[lll] = bx + (bw + 12)*lll; + canvas.draw_image(xbuttons[lll],by,buttons[lll]); + } + + // Open window and enter events loop + CImgDisplay disp(canvas,title?title:" ",0,false,is_centered?true:false); + if (is_centered) disp.move((CImgDisplay::screen_width() - disp.width())/2, + (CImgDisplay::screen_height() - disp.height())/2); + bool stop_flag = false, refresh = false; + int oselected = -1, oclicked = -1, selected = -1, clicked = -1; + while (!disp.is_closed() && !stop_flag) { + if (refresh) { + if (clicked>=0) + CImg(canvas).draw_image(xbuttons[clicked],by,cbuttons[clicked]).display(disp); + else { + if (selected>=0) + CImg(canvas).draw_image(xbuttons[selected],by,sbuttons[selected]).display(disp); + else canvas.display(disp); + } + refresh = false; + } + disp.wait(15); + if (disp.is_resized()) disp.resize(disp,false); + + if (disp.button()&1) { + oclicked = clicked; + clicked = -1; + cimglist_for(buttons,l) + if (disp.mouse_y()>=(int)by && disp.mouse_y()<(int)(by + bh) && + disp.mouse_x()>=(int)xbuttons[l] && disp.mouse_x()<(int)(xbuttons[l] + bw)) { + clicked = selected = l; + refresh = true; + } + if (clicked!=oclicked) refresh = true; + } else if (clicked>=0) stop_flag = true; + + if (disp.key()) { + oselected = selected; + switch (disp.key()) { + case cimg::keyESC : selected = -1; stop_flag = true; break; + case cimg::keyENTER : if (selected<0) selected = 0; stop_flag = true; break; + case cimg::keyTAB : + case cimg::keyARROWRIGHT : + case cimg::keyARROWDOWN : selected = (selected + 1)%buttons.width(); break; + case cimg::keyARROWLEFT : + case cimg::keyARROWUP : selected = (selected + buttons.width() - 1)%buttons.width(); break; + } + disp.set_key(); + if (selected!=oselected) refresh = true; + } + } + if (!disp) selected = -1; + return selected; +#endif + } + + //! Display a simple dialog box, and wait for the user's response \specialization. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const bool is_centered) { + return dialog(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + CImg::_logo40x38(),is_centered); + } + + //! Evaluate math expression. + /** + \param expression C-string describing the formula to evaluate. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \return Result of the formula evaluation. + \note Set \c expression to \c 0 to keep evaluating the last specified \c expression. + \par Example + \code + const double + res1 = cimg::eval("cos(x)^2 + sin(y)^2",2,2), // will return '1' + res2 = cimg::eval(0,1,1); // will return '1' too + \endcode + **/ + inline double eval(const char *const expression, const double x, const double y, const double z, const double c) { + static const CImg empty; + return empty.eval(expression,x,y,z,c); + } + + template + inline CImg::type> eval(const char *const expression, const CImg& xyzc) { + static const CImg empty; + return empty.eval(expression,xyzc); + } + + } // namespace cimg { ... +} // namespace cimg_library { ... + +//! Short alias name. +namespace cil = cimg_library_suffixed; + +#ifdef _cimg_redefine_False +#define False 0 +#endif +#ifdef _cimg_redefine_True +#define True 1 +#endif +#ifdef _cimg_redefine_Status +#define Status int +#endif +#ifdef _cimg_redefine_Success +#define Success 0 +#endif +#ifdef _cimg_redefine_min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_PI +#define PI 3.141592653589793238462643383 +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif + +// Local Variables: +// mode: c++ +// End: diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/demo.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/demo.h new file mode 100644 index 0000000..0aafc91 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/demo.h @@ -0,0 +1,136 @@ +/* + + */ + +#ifndef DEMO_H_ +#define DEMO_H_ +//ڴ˴ͷļ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" +#include "math.h" + +#include "demo_define.h" +#include "tool.h" +#include "inital_alg_params_ynr.h" +#include "inital_alg_params_gic.h" +#include "inital_alg_params_lsc.h" +#include "inital_alg_params_lsc2.h" +#include "inital_alg_params_rk_shapren_HW.h" +#include "inital_alg_params_rk_edgefilter.h" + +#include "initial_alg_params_bayernr.h" + +#include "inital_alg_params_rkuvnr.h" +#include "inital_alg_params_rk_cnr.h" + +#include "inital_alg_params_mfnr.h" +#include "rk_aiq_awb_algo_v200.h" +#define FILE_RAW_EXT ".raw" +#define FILE_YUV_EXT ".yuv" +#define FILE_DAT_EXT ".dat" + +typedef enum YUV_FILE_FMT +{ + F_YUV_420SP = 0x00, + F_YUV_420P = 0x01, + F_YUV_422I = 0x02, + F_YUV_422SP = 0x03, + F_YUV_422P = 0x04, + F_YUV_444I = 0x05, + + F_YUV_MAX = 0x10, +}YUV_FILE_FMT_t; + +typedef enum INPUT_FILE_FMT +{ + F_IN_FMT_RAW = 0x00, + F_IN_FMT_YUV, + + + F_IN_FMT_MAX = 0x10, +}INPUT_FILE_FMT_t; + + + +//˴ +typedef struct tag_config_com +{ + int exp_info_en ; + int framenum ; + int rawwid ; + int rawhgt ; + int rawbit ; + int bayerfmt ; + int yuvbit ; + int yuvfmt ; +}tag_config_com; + +typedef struct tag_config_txt +{ + tag_config_com config_com; + + int framecnt ; + int iso ; + int exptime[3] ; + int expgain[3] ; + int rgain ; + int bgain ; + int grgain ; + int gbgain ; + int dGain ; + int lux ; +}tag_config_txt; + +typedef struct tag_ST_DEMO_INPUT_PARAMS +{ + int width; //rawͼ + int height; //rawͼ + int bayerPattern; //bayer patternʽ:0--BGGR,1--GBRG,2--GRBG,3--RGGB + int yuvFmt; //yuv file ʽ: YUV_FILE_FMT_t + int bitValue; //rawλ + int hdr_framenum; + float expGain[MAX_HDR_FRM_NUM]; // + float expTime[MAX_HDR_FRM_NUM]; //عʱ + int rGain; //wb rgain + int bGain; //wb bgain + int grGain; //wb grgain + int gbGain; //wb gbgain + int dGain; //wb gbgain + int fileFmt; //input file format:INPUT_FILE_FMT_t + int width_full; //rawͼ + int height_full; //rawͼ + int crop_width; + int crop_height; + int crop_xoffset; + int crop_yoffset; + + char pathFileCfg[256];//configļ· + char pathRawData[256];//rawͼ· + char nameRawData[256];//rawͼ + char pathExpInfo[256];//exp_infoļ· + char pathReslut[256];//ļ· + char suffix[256]; // ļ׺ַ + char pathRtlin[256]; //rtl in path + int skip_num; + int frame_end; + + int hdr_proc_mode; + int out_mode; + + + char dbgFlg[1024]; // must > ISP_CAP_MAX + int config_full; + + int exp_info_en; + int file_info_en; + FILE *fp_exp_info; +}ST_DEMO_INPUT_PARAMS; + + + +//˴ + + + +#endif // DEMO_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/demo_define.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/demo_define.h new file mode 100644 index 0000000..da7d26e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/demo_define.h @@ -0,0 +1,44 @@ +/* + + */ + +#ifndef DEFINE_H_ +#define DEFINE_H_ +//ڴ˴ͷļ + + + +#define S7_EDGE 1 +#define GZ 2 +#define DVR 3 +/* +#define ISP_BAYER_NR 1 +#define ISP_DPC 2 +#define ISP_BLC 3 +#define ISP_STAT_3A 4 +#define ISP_LSC 5 +#define ISP_AWBG 6 +#define ISP_VHDM 7 +#define ISP_GAMMA 8 +#define ISP_CSM 9 +#define ISP_DRC 10 +#define ISP_RGB2YUV 11 +#define ISP_LCE 12 +#define ISP_Y_NR 13 +#define ISP_SHARPEN 14 +#define ISP_SCALING 15 +#define ISP_GIC 16 +#define ISP_UV_NR 17 +#define ISP_HDR_MERGE 18 +#define ISP_HDR_TMO 19 +#define ISP_DPN 20 +#define ISP_CTK 21 +#define ISP_WDR 22 +*/ +#define SAVE_RESULT 1 + + +//#define GET_LSC_CALIBRATION_DATA //ȡlens shadingУ궨 + + +#endif // DEFINE_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/amdgpu_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/amdgpu_drm.h new file mode 100644 index 0000000..4fe35d6 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/amdgpu_drm.h @@ -0,0 +1,1067 @@ +/* amdgpu_drm.h -- Public header for the amdgpu driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#ifndef __AMDGPU_DRM_H__ +#define __AMDGPU_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_AMDGPU_GEM_CREATE 0x00 +#define DRM_AMDGPU_GEM_MMAP 0x01 +#define DRM_AMDGPU_CTX 0x02 +#define DRM_AMDGPU_BO_LIST 0x03 +#define DRM_AMDGPU_CS 0x04 +#define DRM_AMDGPU_INFO 0x05 +#define DRM_AMDGPU_GEM_METADATA 0x06 +#define DRM_AMDGPU_GEM_WAIT_IDLE 0x07 +#define DRM_AMDGPU_GEM_VA 0x08 +#define DRM_AMDGPU_WAIT_CS 0x09 +#define DRM_AMDGPU_GEM_OP 0x10 +#define DRM_AMDGPU_GEM_USERPTR 0x11 +#define DRM_AMDGPU_WAIT_FENCES 0x12 +#define DRM_AMDGPU_VM 0x13 +#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14 +#define DRM_AMDGPU_SCHED 0x15 + +#define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) +#define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) +#define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx) +#define DRM_IOCTL_AMDGPU_BO_LIST DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_BO_LIST, union drm_amdgpu_bo_list) +#define DRM_IOCTL_AMDGPU_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CS, union drm_amdgpu_cs) +#define DRM_IOCTL_AMDGPU_INFO DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_INFO, struct drm_amdgpu_info) +#define DRM_IOCTL_AMDGPU_GEM_METADATA DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, struct drm_amdgpu_gem_metadata) +#define DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_WAIT_IDLE, union drm_amdgpu_gem_wait_idle) +#define DRM_IOCTL_AMDGPU_GEM_VA DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_VA, struct drm_amdgpu_gem_va) +#define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs) +#define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op) +#define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) +#define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences) +#define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm) +#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle) +#define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched) + +/** + * DOC: memory domains + * + * %AMDGPU_GEM_DOMAIN_CPU System memory that is not GPU accessible. + * Memory in this pool could be swapped out to disk if there is pressure. + * + * %AMDGPU_GEM_DOMAIN_GTT GPU accessible system memory, mapped into the + * GPU's virtual address space via gart. Gart memory linearizes non-contiguous + * pages of system memory, allows GPU access system memory in a linezrized + * fashion. + * + * %AMDGPU_GEM_DOMAIN_VRAM Local video memory. For APUs, it is memory + * carved out by the BIOS. + * + * %AMDGPU_GEM_DOMAIN_GDS Global on-chip data storage used to share data + * across shader threads. + * + * %AMDGPU_GEM_DOMAIN_GWS Global wave sync, used to synchronize the + * execution of all the waves on a device. + * + * %AMDGPU_GEM_DOMAIN_OA Ordered append, used by 3D or Compute engines + * for appending data. + */ +#define AMDGPU_GEM_DOMAIN_CPU 0x1 +#define AMDGPU_GEM_DOMAIN_GTT 0x2 +#define AMDGPU_GEM_DOMAIN_VRAM 0x4 +#define AMDGPU_GEM_DOMAIN_GDS 0x8 +#define AMDGPU_GEM_DOMAIN_GWS 0x10 +#define AMDGPU_GEM_DOMAIN_OA 0x20 +#define AMDGPU_GEM_DOMAIN_MASK (AMDGPU_GEM_DOMAIN_CPU | \ + AMDGPU_GEM_DOMAIN_GTT | \ + AMDGPU_GEM_DOMAIN_VRAM | \ + AMDGPU_GEM_DOMAIN_GDS | \ + AMDGPU_GEM_DOMAIN_GWS | \ + AMDGPU_GEM_DOMAIN_OA) + +/* Flag that CPU access will be required for the case of VRAM domain */ +#define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0) +/* Flag that CPU access will not work, this VRAM domain is invisible */ +#define AMDGPU_GEM_CREATE_NO_CPU_ACCESS (1 << 1) +/* Flag that USWC attributes should be used for GTT */ +#define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2) +/* Flag that the memory should be in VRAM and cleared */ +#define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3) +/* Flag that create shadow bo(GTT) while allocating vram bo */ +#define AMDGPU_GEM_CREATE_SHADOW (1 << 4) +/* Flag that allocating the BO should use linear VRAM */ +#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5) +/* Flag that BO is always valid in this VM */ +#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6) +/* Flag that BO sharing will be explicitly synchronized */ +#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7) +/* Flag that indicates allocating MQD gart on GFX9, where the mtype + * for the second page onward should be set to NC. + */ +#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8) +/* Flag that BO may contain sensitive data that must be wiped before + * releasing the memory + */ +#define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE (1 << 9) + +struct drm_amdgpu_gem_create_in { + /** the requested memory size */ + __u64 bo_size; + /** physical start_addr alignment in bytes for some HW requirements */ + __u64 alignment; + /** the requested memory domains */ + __u64 domains; + /** allocation flags */ + __u64 domain_flags; +}; + +struct drm_amdgpu_gem_create_out { + /** returned GEM object handle */ + __u32 handle; + __u32 _pad; +}; + +union drm_amdgpu_gem_create { + struct drm_amdgpu_gem_create_in in; + struct drm_amdgpu_gem_create_out out; +}; + +/** Opcode to create new residency list. */ +#define AMDGPU_BO_LIST_OP_CREATE 0 +/** Opcode to destroy previously created residency list */ +#define AMDGPU_BO_LIST_OP_DESTROY 1 +/** Opcode to update resource information in the list */ +#define AMDGPU_BO_LIST_OP_UPDATE 2 + +struct drm_amdgpu_bo_list_in { + /** Type of operation */ + __u32 operation; + /** Handle of list or 0 if we want to create one */ + __u32 list_handle; + /** Number of BOs in list */ + __u32 bo_number; + /** Size of each element describing BO */ + __u32 bo_info_size; + /** Pointer to array describing BOs */ + __u64 bo_info_ptr; +}; + +struct drm_amdgpu_bo_list_entry { + /** Handle of BO */ + __u32 bo_handle; + /** New (if specified) BO priority to be used during migration */ + __u32 bo_priority; +}; + +struct drm_amdgpu_bo_list_out { + /** Handle of resource list */ + __u32 list_handle; + __u32 _pad; +}; + +union drm_amdgpu_bo_list { + struct drm_amdgpu_bo_list_in in; + struct drm_amdgpu_bo_list_out out; +}; + +/* context related */ +#define AMDGPU_CTX_OP_ALLOC_CTX 1 +#define AMDGPU_CTX_OP_FREE_CTX 2 +#define AMDGPU_CTX_OP_QUERY_STATE 3 +#define AMDGPU_CTX_OP_QUERY_STATE2 4 + +/* GPU reset status */ +#define AMDGPU_CTX_NO_RESET 0 +/* this the context caused it */ +#define AMDGPU_CTX_GUILTY_RESET 1 +/* some other context caused it */ +#define AMDGPU_CTX_INNOCENT_RESET 2 +/* unknown cause */ +#define AMDGPU_CTX_UNKNOWN_RESET 3 + +/* indicate gpu reset occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_RESET (1<<0) +/* indicate vram lost occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1) +/* indicate some job from this context once cause gpu hang */ +#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY (1<<2) +/* indicate some errors are detected by RAS */ +#define AMDGPU_CTX_QUERY2_FLAGS_RAS_CE (1<<3) +#define AMDGPU_CTX_QUERY2_FLAGS_RAS_UE (1<<4) + +/* Context priority level */ +#define AMDGPU_CTX_PRIORITY_UNSET -2048 +#define AMDGPU_CTX_PRIORITY_VERY_LOW -1023 +#define AMDGPU_CTX_PRIORITY_LOW -512 +#define AMDGPU_CTX_PRIORITY_NORMAL 0 +/* + * When used in struct drm_amdgpu_ctx_in, a priority above NORMAL requires + * CAP_SYS_NICE or DRM_MASTER +*/ +#define AMDGPU_CTX_PRIORITY_HIGH 512 +#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023 + +struct drm_amdgpu_ctx_in { + /** AMDGPU_CTX_OP_* */ + __u32 op; + /** For future use, no flags defined so far */ + __u32 flags; + __u32 ctx_id; + /** AMDGPU_CTX_PRIORITY_* */ + __s32 priority; +}; + +union drm_amdgpu_ctx_out { + struct { + __u32 ctx_id; + __u32 _pad; + } alloc; + + struct { + /** For future use, no flags defined so far */ + __u64 flags; + /** Number of resets caused by this context so far. */ + __u32 hangs; + /** Reset status since the last call of the ioctl. */ + __u32 reset_status; + } state; +}; + +union drm_amdgpu_ctx { + struct drm_amdgpu_ctx_in in; + union drm_amdgpu_ctx_out out; +}; + +/* vm ioctl */ +#define AMDGPU_VM_OP_RESERVE_VMID 1 +#define AMDGPU_VM_OP_UNRESERVE_VMID 2 + +struct drm_amdgpu_vm_in { + /** AMDGPU_VM_OP_* */ + __u32 op; + __u32 flags; +}; + +struct drm_amdgpu_vm_out { + /** For future use, no flags defined so far */ + __u64 flags; +}; + +union drm_amdgpu_vm { + struct drm_amdgpu_vm_in in; + struct drm_amdgpu_vm_out out; +}; + +/* sched ioctl */ +#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE 1 +#define AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE 2 + +struct drm_amdgpu_sched_in { + /* AMDGPU_SCHED_OP_* */ + __u32 op; + __u32 fd; + /** AMDGPU_CTX_PRIORITY_* */ + __s32 priority; + __u32 ctx_id; +}; + +union drm_amdgpu_sched { + struct drm_amdgpu_sched_in in; +}; + +/* + * This is not a reliable API and you should expect it to fail for any + * number of reasons and have fallback path that do not use userptr to + * perform any operation. + */ +#define AMDGPU_GEM_USERPTR_READONLY (1 << 0) +#define AMDGPU_GEM_USERPTR_ANONONLY (1 << 1) +#define AMDGPU_GEM_USERPTR_VALIDATE (1 << 2) +#define AMDGPU_GEM_USERPTR_REGISTER (1 << 3) + +struct drm_amdgpu_gem_userptr { + __u64 addr; + __u64 size; + /* AMDGPU_GEM_USERPTR_* */ + __u32 flags; + /* Resulting GEM handle */ + __u32 handle; +}; + +/* SI-CI-VI: */ +/* same meaning as the GB_TILE_MODE and GL_MACRO_TILE_MODE fields */ +#define AMDGPU_TILING_ARRAY_MODE_SHIFT 0 +#define AMDGPU_TILING_ARRAY_MODE_MASK 0xf +#define AMDGPU_TILING_PIPE_CONFIG_SHIFT 4 +#define AMDGPU_TILING_PIPE_CONFIG_MASK 0x1f +#define AMDGPU_TILING_TILE_SPLIT_SHIFT 9 +#define AMDGPU_TILING_TILE_SPLIT_MASK 0x7 +#define AMDGPU_TILING_MICRO_TILE_MODE_SHIFT 12 +#define AMDGPU_TILING_MICRO_TILE_MODE_MASK 0x7 +#define AMDGPU_TILING_BANK_WIDTH_SHIFT 15 +#define AMDGPU_TILING_BANK_WIDTH_MASK 0x3 +#define AMDGPU_TILING_BANK_HEIGHT_SHIFT 17 +#define AMDGPU_TILING_BANK_HEIGHT_MASK 0x3 +#define AMDGPU_TILING_MACRO_TILE_ASPECT_SHIFT 19 +#define AMDGPU_TILING_MACRO_TILE_ASPECT_MASK 0x3 +#define AMDGPU_TILING_NUM_BANKS_SHIFT 21 +#define AMDGPU_TILING_NUM_BANKS_MASK 0x3 + +/* GFX9 and later: */ +#define AMDGPU_TILING_SWIZZLE_MODE_SHIFT 0 +#define AMDGPU_TILING_SWIZZLE_MODE_MASK 0x1f +#define AMDGPU_TILING_DCC_OFFSET_256B_SHIFT 5 +#define AMDGPU_TILING_DCC_OFFSET_256B_MASK 0xFFFFFF +#define AMDGPU_TILING_DCC_PITCH_MAX_SHIFT 29 +#define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43 +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1 + +/* Set/Get helpers for tiling flags. */ +#define AMDGPU_TILING_SET(field, value) \ + (((__u64)(value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT) +#define AMDGPU_TILING_GET(value, field) \ + (((__u64)(value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK) + +#define AMDGPU_GEM_METADATA_OP_SET_METADATA 1 +#define AMDGPU_GEM_METADATA_OP_GET_METADATA 2 + +/** The same structure is shared for input/output */ +struct drm_amdgpu_gem_metadata { + /** GEM Object handle */ + __u32 handle; + /** Do we want get or set metadata */ + __u32 op; + struct { + /** For future use, no flags defined so far */ + __u64 flags; + /** family specific tiling info */ + __u64 tiling_info; + __u32 data_size_bytes; + __u32 data[64]; + } data; +}; + +struct drm_amdgpu_gem_mmap_in { + /** the GEM object handle */ + __u32 handle; + __u32 _pad; +}; + +struct drm_amdgpu_gem_mmap_out { + /** mmap offset from the vma offset manager */ + __u64 addr_ptr; +}; + +union drm_amdgpu_gem_mmap { + struct drm_amdgpu_gem_mmap_in in; + struct drm_amdgpu_gem_mmap_out out; +}; + +struct drm_amdgpu_gem_wait_idle_in { + /** GEM object handle */ + __u32 handle; + /** For future use, no flags defined so far */ + __u32 flags; + /** Absolute timeout to wait */ + __u64 timeout; +}; + +struct drm_amdgpu_gem_wait_idle_out { + /** BO status: 0 - BO is idle, 1 - BO is busy */ + __u32 status; + /** Returned current memory domain */ + __u32 domain; +}; + +union drm_amdgpu_gem_wait_idle { + struct drm_amdgpu_gem_wait_idle_in in; + struct drm_amdgpu_gem_wait_idle_out out; +}; + +struct drm_amdgpu_wait_cs_in { + /* Command submission handle + * handle equals 0 means none to wait for + * handle equals ~0ull means wait for the latest sequence number + */ + __u64 handle; + /** Absolute timeout to wait */ + __u64 timeout; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; +}; + +struct drm_amdgpu_wait_cs_out { + /** CS status: 0 - CS completed, 1 - CS still busy */ + __u64 status; +}; + +union drm_amdgpu_wait_cs { + struct drm_amdgpu_wait_cs_in in; + struct drm_amdgpu_wait_cs_out out; +}; + +struct drm_amdgpu_fence { + __u32 ctx_id; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u64 seq_no; +}; + +struct drm_amdgpu_wait_fences_in { + /** This points to uint64_t * which points to fences */ + __u64 fences; + __u32 fence_count; + __u32 wait_all; + __u64 timeout_ns; +}; + +struct drm_amdgpu_wait_fences_out { + __u32 status; + __u32 first_signaled; +}; + +union drm_amdgpu_wait_fences { + struct drm_amdgpu_wait_fences_in in; + struct drm_amdgpu_wait_fences_out out; +}; + +#define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0 +#define AMDGPU_GEM_OP_SET_PLACEMENT 1 + +/* Sets or returns a value associated with a buffer. */ +struct drm_amdgpu_gem_op { + /** GEM object handle */ + __u32 handle; + /** AMDGPU_GEM_OP_* */ + __u32 op; + /** Input or return value */ + __u64 value; +}; + +#define AMDGPU_VA_OP_MAP 1 +#define AMDGPU_VA_OP_UNMAP 2 +#define AMDGPU_VA_OP_CLEAR 3 +#define AMDGPU_VA_OP_REPLACE 4 + +/* Delay the page table update till the next CS */ +#define AMDGPU_VM_DELAY_UPDATE (1 << 0) + +/* Mapping flags */ +/* readable mapping */ +#define AMDGPU_VM_PAGE_READABLE (1 << 1) +/* writable mapping */ +#define AMDGPU_VM_PAGE_WRITEABLE (1 << 2) +/* executable mapping, new for VI */ +#define AMDGPU_VM_PAGE_EXECUTABLE (1 << 3) +/* partially resident texture */ +#define AMDGPU_VM_PAGE_PRT (1 << 4) +/* MTYPE flags use bit 5 to 8 */ +#define AMDGPU_VM_MTYPE_MASK (0xf << 5) +/* Default MTYPE. Pre-AI must use this. Recommended for newer ASICs. */ +#define AMDGPU_VM_MTYPE_DEFAULT (0 << 5) +/* Use NC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_NC (1 << 5) +/* Use WC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_WC (2 << 5) +/* Use CC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_CC (3 << 5) +/* Use UC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_UC (4 << 5) + +struct drm_amdgpu_gem_va { + /** GEM object handle */ + __u32 handle; + __u32 _pad; + /** AMDGPU_VA_OP_* */ + __u32 operation; + /** AMDGPU_VM_PAGE_* */ + __u32 flags; + /** va address to assign . Must be correctly aligned.*/ + __u64 va_address; + /** Specify offset inside of BO to assign. Must be correctly aligned.*/ + __u64 offset_in_bo; + /** Specify mapping size. Must be correctly aligned. */ + __u64 map_size; +}; + +#define AMDGPU_HW_IP_GFX 0 +#define AMDGPU_HW_IP_COMPUTE 1 +#define AMDGPU_HW_IP_DMA 2 +#define AMDGPU_HW_IP_UVD 3 +#define AMDGPU_HW_IP_VCE 4 +#define AMDGPU_HW_IP_UVD_ENC 5 +#define AMDGPU_HW_IP_VCN_DEC 6 +#define AMDGPU_HW_IP_VCN_ENC 7 +#define AMDGPU_HW_IP_VCN_JPEG 8 +#define AMDGPU_HW_IP_NUM 9 + +#define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1 + +#define AMDGPU_CHUNK_ID_IB 0x01 +#define AMDGPU_CHUNK_ID_FENCE 0x02 +#define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03 +#define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04 +#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05 +#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06 +#define AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES 0x07 +#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT 0x08 +#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL 0x09 + +struct drm_amdgpu_cs_chunk { + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; +}; + +struct drm_amdgpu_cs_in { + /** Rendering context id */ + __u32 ctx_id; + /** Handle of resource list associated with CS */ + __u32 bo_list_handle; + __u32 num_chunks; + __u32 _pad; + /** this points to __u64 * which point to cs chunks */ + __u64 chunks; +}; + +struct drm_amdgpu_cs_out { + __u64 handle; +}; + +union drm_amdgpu_cs { + struct drm_amdgpu_cs_in in; + struct drm_amdgpu_cs_out out; +}; + +/* Specify flags to be used for IB */ + +/* This IB should be submitted to CE */ +#define AMDGPU_IB_FLAG_CE (1<<0) + +/* Preamble flag, which means the IB could be dropped if no context switch */ +#define AMDGPU_IB_FLAG_PREAMBLE (1<<1) + +/* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */ +#define AMDGPU_IB_FLAG_PREEMPT (1<<2) + +/* The IB fence should do the L2 writeback but not invalidate any shader + * caches (L2/vL1/sL1/I$). */ +#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3) + +/* Set GDS_COMPUTE_MAX_WAVE_ID = DEFAULT before PACKET3_INDIRECT_BUFFER. + * This will reset wave ID counters for the IB. + */ +#define AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID (1 << 4) + +struct drm_amdgpu_cs_chunk_ib { + __u32 _pad; + /** AMDGPU_IB_FLAG_* */ + __u32 flags; + /** Virtual address to begin IB execution */ + __u64 va_start; + /** Size of submission */ + __u32 ib_bytes; + /** HW IP to submit to */ + __u32 ip_type; + /** HW IP index of the same type to submit to */ + __u32 ip_instance; + /** Ring index to submit to */ + __u32 ring; +}; + +struct drm_amdgpu_cs_chunk_dep { + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; + __u64 handle; +}; + +struct drm_amdgpu_cs_chunk_fence { + __u32 handle; + __u32 offset; +}; + +struct drm_amdgpu_cs_chunk_sem { + __u32 handle; +}; + +struct drm_amdgpu_cs_chunk_syncobj { + __u32 handle; + __u32 flags; + __u64 point; +}; + +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2 + +union drm_amdgpu_fence_to_handle { + struct { + struct drm_amdgpu_fence fence; + __u32 what; + __u32 pad; + } in; + struct { + __u32 handle; + } out; +}; + +struct drm_amdgpu_cs_chunk_data { + union { + struct drm_amdgpu_cs_chunk_ib ib_data; + struct drm_amdgpu_cs_chunk_fence fence_data; + }; +}; + +/** + * Query h/w info: Flag that this is integrated (a.h.a. fusion) GPU + * + */ +#define AMDGPU_IDS_FLAGS_FUSION 0x1 +#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 + +/* indicate if acceleration can be working */ +#define AMDGPU_INFO_ACCEL_WORKING 0x00 +/* get the crtc_id from the mode object id? */ +#define AMDGPU_INFO_CRTC_FROM_ID 0x01 +/* query hw IP info */ +#define AMDGPU_INFO_HW_IP_INFO 0x02 +/* query hw IP instance count for the specified type */ +#define AMDGPU_INFO_HW_IP_COUNT 0x03 +/* timestamp for GL_ARB_timer_query */ +#define AMDGPU_INFO_TIMESTAMP 0x05 +/* Query the firmware version */ +#define AMDGPU_INFO_FW_VERSION 0x0e + /* Subquery id: Query VCE firmware version */ + #define AMDGPU_INFO_FW_VCE 0x1 + /* Subquery id: Query UVD firmware version */ + #define AMDGPU_INFO_FW_UVD 0x2 + /* Subquery id: Query GMC firmware version */ + #define AMDGPU_INFO_FW_GMC 0x03 + /* Subquery id: Query GFX ME firmware version */ + #define AMDGPU_INFO_FW_GFX_ME 0x04 + /* Subquery id: Query GFX PFP firmware version */ + #define AMDGPU_INFO_FW_GFX_PFP 0x05 + /* Subquery id: Query GFX CE firmware version */ + #define AMDGPU_INFO_FW_GFX_CE 0x06 + /* Subquery id: Query GFX RLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC 0x07 + /* Subquery id: Query GFX MEC firmware version */ + #define AMDGPU_INFO_FW_GFX_MEC 0x08 + /* Subquery id: Query SMC firmware version */ + #define AMDGPU_INFO_FW_SMC 0x0a + /* Subquery id: Query SDMA firmware version */ + #define AMDGPU_INFO_FW_SDMA 0x0b + /* Subquery id: Query PSP SOS firmware version */ + #define AMDGPU_INFO_FW_SOS 0x0c + /* Subquery id: Query PSP ASD firmware version */ + #define AMDGPU_INFO_FW_ASD 0x0d + /* Subquery id: Query VCN firmware version */ + #define AMDGPU_INFO_FW_VCN 0x0e + /* Subquery id: Query GFX RLC SRLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f + /* Subquery id: Query GFX RLC SRLG firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10 + /* Subquery id: Query GFX RLC SRLS firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11 + /* Subquery id: Query DMCU firmware version */ + #define AMDGPU_INFO_FW_DMCU 0x12 + #define AMDGPU_INFO_FW_TA 0x13 +/* number of bytes moved for TTM migration */ +#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f +/* the used VRAM size */ +#define AMDGPU_INFO_VRAM_USAGE 0x10 +/* the used GTT size */ +#define AMDGPU_INFO_GTT_USAGE 0x11 +/* Information about GDS, etc. resource configuration */ +#define AMDGPU_INFO_GDS_CONFIG 0x13 +/* Query information about VRAM and GTT domains */ +#define AMDGPU_INFO_VRAM_GTT 0x14 +/* Query information about register in MMR address space*/ +#define AMDGPU_INFO_READ_MMR_REG 0x15 +/* Query information about device: rev id, family, etc. */ +#define AMDGPU_INFO_DEV_INFO 0x16 +/* visible vram usage */ +#define AMDGPU_INFO_VIS_VRAM_USAGE 0x17 +/* number of TTM buffer evictions */ +#define AMDGPU_INFO_NUM_EVICTIONS 0x18 +/* Query memory about VRAM and GTT domains */ +#define AMDGPU_INFO_MEMORY 0x19 +/* Query vce clock table */ +#define AMDGPU_INFO_VCE_CLOCK_TABLE 0x1A +/* Query vbios related information */ +#define AMDGPU_INFO_VBIOS 0x1B + /* Subquery id: Query vbios size */ + #define AMDGPU_INFO_VBIOS_SIZE 0x1 + /* Subquery id: Query vbios image */ + #define AMDGPU_INFO_VBIOS_IMAGE 0x2 +/* Query UVD handles */ +#define AMDGPU_INFO_NUM_HANDLES 0x1C +/* Query sensor related information */ +#define AMDGPU_INFO_SENSOR 0x1D + /* Subquery id: Query GPU shader clock */ + #define AMDGPU_INFO_SENSOR_GFX_SCLK 0x1 + /* Subquery id: Query GPU memory clock */ + #define AMDGPU_INFO_SENSOR_GFX_MCLK 0x2 + /* Subquery id: Query GPU temperature */ + #define AMDGPU_INFO_SENSOR_GPU_TEMP 0x3 + /* Subquery id: Query GPU load */ + #define AMDGPU_INFO_SENSOR_GPU_LOAD 0x4 + /* Subquery id: Query average GPU power */ + #define AMDGPU_INFO_SENSOR_GPU_AVG_POWER 0x5 + /* Subquery id: Query northbridge voltage */ + #define AMDGPU_INFO_SENSOR_VDDNB 0x6 + /* Subquery id: Query graphics voltage */ + #define AMDGPU_INFO_SENSOR_VDDGFX 0x7 + /* Subquery id: Query GPU stable pstate shader clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK 0x8 + /* Subquery id: Query GPU stable pstate memory clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK 0x9 +/* Number of VRAM page faults on CPU access. */ +#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E +#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F +/* query ras mask of enabled features*/ +#define AMDGPU_INFO_RAS_ENABLED_FEATURES 0x20 + +/* RAS MASK: UMC (VRAM) */ +#define AMDGPU_INFO_RAS_ENABLED_UMC (1 << 0) +/* RAS MASK: SDMA */ +#define AMDGPU_INFO_RAS_ENABLED_SDMA (1 << 1) +/* RAS MASK: GFX */ +#define AMDGPU_INFO_RAS_ENABLED_GFX (1 << 2) +/* RAS MASK: MMHUB */ +#define AMDGPU_INFO_RAS_ENABLED_MMHUB (1 << 3) +/* RAS MASK: ATHUB */ +#define AMDGPU_INFO_RAS_ENABLED_ATHUB (1 << 4) +/* RAS MASK: PCIE */ +#define AMDGPU_INFO_RAS_ENABLED_PCIE (1 << 5) +/* RAS MASK: HDP */ +#define AMDGPU_INFO_RAS_ENABLED_HDP (1 << 6) +/* RAS MASK: XGMI */ +#define AMDGPU_INFO_RAS_ENABLED_XGMI (1 << 7) +/* RAS MASK: DF */ +#define AMDGPU_INFO_RAS_ENABLED_DF (1 << 8) +/* RAS MASK: SMN */ +#define AMDGPU_INFO_RAS_ENABLED_SMN (1 << 9) +/* RAS MASK: SEM */ +#define AMDGPU_INFO_RAS_ENABLED_SEM (1 << 10) +/* RAS MASK: MP0 */ +#define AMDGPU_INFO_RAS_ENABLED_MP0 (1 << 11) +/* RAS MASK: MP1 */ +#define AMDGPU_INFO_RAS_ENABLED_MP1 (1 << 12) +/* RAS MASK: FUSE */ +#define AMDGPU_INFO_RAS_ENABLED_FUSE (1 << 13) + +#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 +#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff +#define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8 +#define AMDGPU_INFO_MMR_SH_INDEX_MASK 0xff + +struct drm_amdgpu_query_fw { + /** AMDGPU_INFO_FW_* */ + __u32 fw_type; + /** + * Index of the IP if there are more IPs of + * the same type. + */ + __u32 ip_instance; + /** + * Index of the engine. Whether this is used depends + * on the firmware type. (e.g. MEC, SDMA) + */ + __u32 index; + __u32 _pad; +}; + +/* Input structure for the INFO ioctl */ +struct drm_amdgpu_info { + /* Where the return value will be stored */ + __u64 return_pointer; + /* The size of the return value. Just like "size" in "snprintf", + * it limits how many bytes the kernel can write. */ + __u32 return_size; + /* The query request id. */ + __u32 query; + + union { + struct { + __u32 id; + __u32 _pad; + } mode_crtc; + + struct { + /** AMDGPU_HW_IP_* */ + __u32 type; + /** + * Index of the IP if there are more IPs of the same + * type. Ignored by AMDGPU_INFO_HW_IP_COUNT. + */ + __u32 ip_instance; + } query_hw_ip; + + struct { + __u32 dword_offset; + /** number of registers to read */ + __u32 count; + __u32 instance; + /** For future use, no flags defined so far */ + __u32 flags; + } read_mmr_reg; + + struct drm_amdgpu_query_fw query_fw; + + struct { + __u32 type; + __u32 offset; + } vbios_info; + + struct { + __u32 type; + } sensor_info; + }; +}; + +struct drm_amdgpu_info_gds { + /** GDS GFX partition size */ + __u32 gds_gfx_partition_size; + /** GDS compute partition size */ + __u32 compute_partition_size; + /** total GDS memory size */ + __u32 gds_total_size; + /** GWS size per GFX partition */ + __u32 gws_per_gfx_partition; + /** GSW size per compute partition */ + __u32 gws_per_compute_partition; + /** OA size per GFX partition */ + __u32 oa_per_gfx_partition; + /** OA size per compute partition */ + __u32 oa_per_compute_partition; + __u32 _pad; +}; + +struct drm_amdgpu_info_vram_gtt { + __u64 vram_size; + __u64 vram_cpu_accessible_size; + __u64 gtt_size; +}; + +struct drm_amdgpu_heap_info { + /** max. physical memory */ + __u64 total_heap_size; + + /** Theoretical max. available memory in the given heap */ + __u64 usable_heap_size; + + /** + * Number of bytes allocated in the heap. This includes all processes + * and private allocations in the kernel. It changes when new buffers + * are allocated, freed, and moved. It cannot be larger than + * heap_size. + */ + __u64 heap_usage; + + /** + * Theoretical possible max. size of buffer which + * could be allocated in the given heap + */ + __u64 max_allocation; +}; + +struct drm_amdgpu_memory_info { + struct drm_amdgpu_heap_info vram; + struct drm_amdgpu_heap_info cpu_accessible_vram; + struct drm_amdgpu_heap_info gtt; +}; + +struct drm_amdgpu_info_firmware { + __u32 ver; + __u32 feature; +}; + +#define AMDGPU_VRAM_TYPE_UNKNOWN 0 +#define AMDGPU_VRAM_TYPE_GDDR1 1 +#define AMDGPU_VRAM_TYPE_DDR2 2 +#define AMDGPU_VRAM_TYPE_GDDR3 3 +#define AMDGPU_VRAM_TYPE_GDDR4 4 +#define AMDGPU_VRAM_TYPE_GDDR5 5 +#define AMDGPU_VRAM_TYPE_HBM 6 +#define AMDGPU_VRAM_TYPE_DDR3 7 +#define AMDGPU_VRAM_TYPE_DDR4 8 +#define AMDGPU_VRAM_TYPE_GDDR6 9 + +struct drm_amdgpu_info_device { + /** PCI Device ID */ + __u32 device_id; + /** Internal chip revision: A0, A1, etc.) */ + __u32 chip_rev; + __u32 external_rev; + /** Revision id in PCI Config space */ + __u32 pci_rev; + __u32 family; + __u32 num_shader_engines; + __u32 num_shader_arrays_per_engine; + /* in KHz */ + __u32 gpu_counter_freq; + __u64 max_engine_clock; + __u64 max_memory_clock; + /* cu information */ + __u32 cu_active_number; + /* NOTE: cu_ao_mask is INVALID, DON'T use it */ + __u32 cu_ao_mask; + __u32 cu_bitmap[4][4]; + /** Render backend pipe mask. One render backend is CB+DB. */ + __u32 enabled_rb_pipes_mask; + __u32 num_rb_pipes; + __u32 num_hw_gfx_contexts; + __u32 _pad; + __u64 ids_flags; + /** Starting virtual address for UMDs. */ + __u64 virtual_address_offset; + /** The maximum virtual address */ + __u64 virtual_address_max; + /** Required alignment of virtual addresses. */ + __u32 virtual_address_alignment; + /** Page table entry - fragment size */ + __u32 pte_fragment_size; + __u32 gart_page_size; + /** constant engine ram size*/ + __u32 ce_ram_size; + /** video memory type info*/ + __u32 vram_type; + /** video memory bit width*/ + __u32 vram_bit_width; + /* vce harvesting instance */ + __u32 vce_harvest_config; + /* gfx double offchip LDS buffers */ + __u32 gc_double_offchip_lds_buf; + /* NGG Primitive Buffer */ + __u64 prim_buf_gpu_addr; + /* NGG Position Buffer */ + __u64 pos_buf_gpu_addr; + /* NGG Control Sideband */ + __u64 cntl_sb_buf_gpu_addr; + /* NGG Parameter Cache */ + __u64 param_buf_gpu_addr; + __u32 prim_buf_size; + __u32 pos_buf_size; + __u32 cntl_sb_buf_size; + __u32 param_buf_size; + /* wavefront size*/ + __u32 wave_front_size; + /* shader visible vgprs*/ + __u32 num_shader_visible_vgprs; + /* CU per shader array*/ + __u32 num_cu_per_sh; + /* number of tcc blocks*/ + __u32 num_tcc_blocks; + /* gs vgt table depth*/ + __u32 gs_vgt_table_depth; + /* gs primitive buffer depth*/ + __u32 gs_prim_buffer_depth; + /* max gs wavefront per vgt*/ + __u32 max_gs_waves_per_vgt; + __u32 _pad1; + /* always on cu bitmap */ + __u32 cu_ao_bitmap[4][4]; + /** Starting high virtual address for UMDs. */ + __u64 high_va_offset; + /** The maximum high virtual address */ + __u64 high_va_max; + /* gfx10 pa_sc_tile_steering_override */ + __u32 pa_sc_tile_steering_override; + /* disabled TCCs */ + __u64 tcc_disabled_mask; +}; + +struct drm_amdgpu_info_hw_ip { + /** Version of h/w IP */ + __u32 hw_ip_version_major; + __u32 hw_ip_version_minor; + /** Capabilities */ + __u64 capabilities_flags; + /** command buffer address start alignment*/ + __u32 ib_start_alignment; + /** command buffer size alignment*/ + __u32 ib_size_alignment; + /** Bitmask of available rings. Bit 0 means ring 0, etc. */ + __u32 available_rings; + __u32 _pad; +}; + +struct drm_amdgpu_info_num_handles { + /** Max handles as supported by firmware for UVD */ + __u32 uvd_max_handles; + /** Handles currently in use for UVD */ + __u32 uvd_used_handles; +}; + +#define AMDGPU_VCE_CLOCK_TABLE_ENTRIES 6 + +struct drm_amdgpu_info_vce_clock_table_entry { + /** System clock */ + __u32 sclk; + /** Memory clock */ + __u32 mclk; + /** VCE clock */ + __u32 eclk; + __u32 pad; +}; + +struct drm_amdgpu_info_vce_clock_table { + struct drm_amdgpu_info_vce_clock_table_entry entries[AMDGPU_VCE_CLOCK_TABLE_ENTRIES]; + __u32 num_valid_entries; + __u32 pad; +}; + +/* + * Supported GPU families + */ +#define AMDGPU_FAMILY_UNKNOWN 0 +#define AMDGPU_FAMILY_SI 110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */ +#define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */ +#define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */ +#define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */ +#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */ +#define AMDGPU_FAMILY_AI 141 /* Vega10 */ +#define AMDGPU_FAMILY_RV 142 /* Raven */ +#define AMDGPU_FAMILY_NV 143 /* Navi10 */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm.h new file mode 100644 index 0000000..438abde --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm.h @@ -0,0 +1,1042 @@ +/** + * \file drm.h + * Header for the Direct Rendering Manager + * + * \author Rickard E. (Rik) Faith + * + * \par Acknowledgments: + * Dec 1999, Richard Henderson , move to generic \c cmpxchg. + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_H_ +#define _DRM_H_ + +#if defined(__linux__) + +#include +#include +typedef unsigned int drm_handle_t; + +#else /* One of the BSDs */ + +#include +#include +#include +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; +typedef size_t __kernel_size_t; +typedef unsigned long drm_handle_t; + +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ +#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ +#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ +#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ + +#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ +#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) +#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) +#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) + +typedef unsigned int drm_context_t; +typedef unsigned int drm_drawable_t; +typedef unsigned int drm_magic_t; + +/** + * Cliprect. + * + * \warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well + * + * \note KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ +struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +}; + +/** + * Drawable information. + */ +struct drm_drawable_info { + unsigned int num_rects; + struct drm_clip_rect *rects; +}; + +/** + * Texture region, + */ +struct drm_tex_region { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; + unsigned int age; +}; + +/** + * Hardware lock. + * + * The lock structure is a simple cache-line aligned integer. To avoid + * processor bus contention on a multiprocessor system, there should not be any + * other data stored in the same cache line. + */ +struct drm_hw_lock { + __volatile__ unsigned int lock; /**< lock variable */ + char padding[60]; /**< Pad to cache line */ +}; + +/** + * DRM_IOCTL_VERSION ioctl argument type. + * + * \sa drmGetVersion(). + */ +struct drm_version { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + __kernel_size_t name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + __kernel_size_t date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + __kernel_size_t desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +}; + +/** + * DRM_IOCTL_GET_UNIQUE ioctl argument type. + * + * \sa drmGetBusid() and drmSetBusId(). + */ +struct drm_unique { + __kernel_size_t unique_len; /**< Length of unique */ + char *unique; /**< Unique name for driver instantiation */ +}; + +struct drm_list { + int count; /**< Length of user-space structures */ + struct drm_version *version; +}; + +struct drm_block { + int unused; +}; + +/** + * DRM_IOCTL_CONTROL ioctl argument type. + * + * \sa drmCtlInstHandler() and drmCtlUninstHandler(). + */ +struct drm_control { + enum { + DRM_ADD_COMMAND, + DRM_RM_COMMAND, + DRM_INST_HANDLER, + DRM_UNINST_HANDLER + } func; + int irq; +}; + +/** + * Type of memory to map. + */ +enum drm_map_type { + _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ + _DRM_REGISTERS = 1, /**< no caching, no core dump */ + _DRM_SHM = 2, /**< shared, cached */ + _DRM_AGP = 3, /**< AGP/GART */ + _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ + _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ +}; + +/** + * Memory mapping flags. + */ +enum drm_map_flags { + _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ + _DRM_READ_ONLY = 0x02, + _DRM_LOCKED = 0x04, /**< shared, cached, locked */ + _DRM_KERNEL = 0x08, /**< kernel requires access */ + _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ + _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ + _DRM_REMOVABLE = 0x40, /**< Removable mapping */ + _DRM_DRIVER = 0x80 /**< Managed by driver */ +}; + +struct drm_ctx_priv_map { + unsigned int ctx_id; /**< Context requesting private mapping */ + void *handle; /**< Handle of map */ +}; + +/** + * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls + * argument type. + * + * \sa drmAddMap(). + */ +struct drm_map { + unsigned long offset; /**< Requested physical address (0 for SAREA)*/ + unsigned long size; /**< Requested physical size (bytes) */ + enum drm_map_type type; /**< Type of memory to map */ + enum drm_map_flags flags; /**< Flags */ + void *handle; /**< User-space: "Handle" to pass to mmap() */ + /**< Kernel-space: kernel-virtual address */ + int mtrr; /**< MTRR slot used */ + /* Private data */ +}; + +/** + * DRM_IOCTL_GET_CLIENT ioctl argument type. + */ +struct drm_client { + int idx; /**< Which client desired? */ + int auth; /**< Is client authenticated? */ + unsigned long pid; /**< Process ID */ + unsigned long uid; /**< User ID */ + unsigned long magic; /**< Magic */ + unsigned long iocs; /**< Ioctl count */ +}; + +enum drm_stat_type { + _DRM_STAT_LOCK, + _DRM_STAT_OPENS, + _DRM_STAT_CLOSES, + _DRM_STAT_IOCTLS, + _DRM_STAT_LOCKS, + _DRM_STAT_UNLOCKS, + _DRM_STAT_VALUE, /**< Generic value */ + _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ + _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ + + _DRM_STAT_IRQ, /**< IRQ */ + _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ + _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ + _DRM_STAT_DMA, /**< DMA */ + _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ + _DRM_STAT_MISSED /**< Missed DMA opportunity */ + /* Add to the *END* of the list */ +}; + +/** + * DRM_IOCTL_GET_STATS ioctl argument type. + */ +struct drm_stats { + unsigned long count; + struct { + unsigned long value; + enum drm_stat_type type; + } data[15]; +}; + +/** + * Hardware locking flags. + */ +enum drm_lock_flags { + _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +}; + +/** + * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. + * + * \sa drmGetLock() and drmUnlock(). + */ +struct drm_lock { + int context; + enum drm_lock_flags flags; +}; + +/** + * DMA flags + * + * \warning + * These values \e must match xf86drm.h. + * + * \sa drm_dma. + */ +enum drm_dma_flags { + /* Flags for DMA buffer dispatch */ + _DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note The buffer may not yet have + * been processed by the hardware -- + * getting a hardware lock with the + * hardware quiescent will ensure + * that the buffer has been + * processed. + */ + _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + + /* Flags for DMA buffer request */ + _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ +}; + +/** + * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. + * + * \sa drmAddBufs(). + */ +struct drm_buf_desc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ + enum { + _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ + _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ + _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ + _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ + } flags; + unsigned long agp_start; /**< + * Start address of where the AGP buffers are + * in the AGP aperture + */ +}; + +/** + * DRM_IOCTL_INFO_BUFS ioctl argument type. + */ +struct drm_buf_info { + int count; /**< Entries in list */ + struct drm_buf_desc *list; +}; + +/** + * DRM_IOCTL_FREE_BUFS ioctl argument type. + */ +struct drm_buf_free { + int count; + int *list; +}; + +/** + * Buffer information + * + * \sa drm_buf_map. + */ +struct drm_buf_pub { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + void *address; /**< Address of buffer */ +}; + +/** + * DRM_IOCTL_MAP_BUFS ioctl argument type. + */ +struct drm_buf_map { + int count; /**< Length of the buffer list */ +#ifdef __cplusplus + void *virt; +#else + void *virtual; /**< Mmap'd area in user-virtual */ +#endif + struct drm_buf_pub *list; /**< Buffer information */ +}; + +/** + * DRM_IOCTL_DMA ioctl argument type. + * + * Indices here refer to the offset into the buffer list in drm_buf_get. + * + * \sa drmDMA(). + */ +struct drm_dma { + int context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_indices; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send */ + enum drm_dma_flags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size for buffers */ + int *request_indices; /**< Buffer information */ + int *request_sizes; + int granted_count; /**< Number of buffers granted */ +}; + +enum drm_ctx_flags { + _DRM_CONTEXT_PRESERVED = 0x01, + _DRM_CONTEXT_2DONLY = 0x02 +}; + +/** + * DRM_IOCTL_ADD_CTX ioctl argument type. + * + * \sa drmCreateContext() and drmDestroyContext(). + */ +struct drm_ctx { + drm_context_t handle; + enum drm_ctx_flags flags; +}; + +/** + * DRM_IOCTL_RES_CTX ioctl argument type. + */ +struct drm_ctx_res { + int count; + struct drm_ctx *contexts; +}; + +/** + * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. + */ +struct drm_draw { + drm_drawable_t handle; +}; + +/** + * DRM_IOCTL_UPDATE_DRAW ioctl argument type. + */ +typedef enum { + DRM_DRAWABLE_CLIPRECTS +} drm_drawable_info_type_t; + +struct drm_update_draw { + drm_drawable_t handle; + unsigned int type; + unsigned int num; + unsigned long long data; +}; + +/** + * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. + */ +struct drm_auth { + drm_magic_t magic; +}; + +/** + * DRM_IOCTL_IRQ_BUSID ioctl argument type. + * + * \sa drmGetInterruptFromBusID(). + */ +struct drm_irq_busid { + int irq; /**< IRQ number */ + int busnum; /**< bus number */ + int devnum; /**< device number */ + int funcnum; /**< function number */ +}; + +enum drm_vblank_seq_type { + _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + _DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ +}; +#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) + +struct drm_wait_vblank_request { + enum drm_vblank_seq_type type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + enum drm_vblank_seq_type type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +/** + * DRM_IOCTL_WAIT_VBLANK ioctl argument type. + * + * \sa drmWaitVBlank(). + */ +union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +}; + +#define _DRM_PRE_MODESET 1 +#define _DRM_POST_MODESET 2 + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + __u32 crtc; + __u32 cmd; +}; + +/** + * DRM_IOCTL_AGP_ENABLE ioctl argument type. + * + * \sa drmAgpEnable(). + */ +struct drm_agp_mode { + unsigned long mode; /**< AGP mode */ +}; + +/** + * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. + * + * \sa drmAgpAlloc() and drmAgpFree(). + */ +struct drm_agp_buffer { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for binding / unbinding */ + unsigned long type; /**< Type of memory to allocate */ + unsigned long physical; /**< Physical used by i810 */ +}; + +/** + * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. + * + * \sa drmAgpBind() and drmAgpUnbind(). + */ +struct drm_agp_binding { + unsigned long handle; /**< From drm_agp_buffer */ + unsigned long offset; /**< In bytes -- will round to page boundary */ +}; + +/** + * DRM_IOCTL_AGP_INFO ioctl argument type. + * + * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), + * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), + * drmAgpVendorId() and drmAgpDeviceId(). + */ +struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +}; + +/** + * DRM_IOCTL_SG_ALLOC ioctl argument type. + */ +struct drm_scatter_gather { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for mapping / unmapping */ +}; + +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +}; + +/** DRM_IOCTL_GEM_CLOSE ioctl argument type */ +struct drm_gem_close { + /** Handle of the object to be closed. */ + __u32 handle; + __u32 pad; +}; + +/** DRM_IOCTL_GEM_FLINK ioctl argument type */ +struct drm_gem_flink { + /** Handle for the object being named */ + __u32 handle; + + /** Returned global name */ + __u32 name; +}; + +/** DRM_IOCTL_GEM_OPEN ioctl argument type */ +struct drm_gem_open { + /** Name of object being opened */ + __u32 name; + + /** Returned handle for the object */ + __u32 handle; + + /** Returned size of the object */ + __u64 size; +}; + +#define DRM_CAP_DUMB_BUFFER 0x1 +#define DRM_CAP_VBLANK_HIGH_CRTC 0x2 +#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 +#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 +#define DRM_CAP_PRIME 0x5 +#define DRM_PRIME_CAP_IMPORT 0x1 +#define DRM_PRIME_CAP_EXPORT 0x2 +#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 +#define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +/* + * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight + * combination for the hardware cursor. The intention is that a hardware + * agnostic userspace can query a cursor plane size to use. + * + * Note that the cross-driver contract is to merely return a valid size; + * drivers are free to attach another meaning on top, eg. i915 returns the + * maximum plane size. + */ +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#define DRM_CAP_ADDFB2_MODIFIERS 0x10 +#define DRM_CAP_PAGE_FLIP_TARGET 0x11 +#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 +#define DRM_CAP_SYNCOBJ 0x13 +#define DRM_CAP_SYNCOBJ_TIMELINE 0x14 + +/** DRM_IOCTL_GET_CAP ioctl argument type */ +struct drm_get_cap { + __u64 capability; + __u64 value; +}; + +/** + * DRM_CLIENT_CAP_STEREO_3D + * + * if set to 1, the DRM core will expose the stereo 3D capabilities of the + * monitor by advertising the supported 3D layouts in the flags of struct + * drm_mode_modeinfo. + */ +#define DRM_CLIENT_CAP_STEREO_3D 1 + +/** + * DRM_CLIENT_CAP_UNIVERSAL_PLANES + * + * If set to 1, the DRM core will expose all planes (overlay, primary, and + * cursor) to userspace. + */ +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 + +/** + * DRM_CLIENT_CAP_ATOMIC + * + * If set to 1, the DRM core will expose atomic properties to userspace + */ +#define DRM_CLIENT_CAP_ATOMIC 3 + +/** + * DRM_CLIENT_CAP_ASPECT_RATIO + * + * If set to 1, the DRM core will provide aspect ratio information in modes. + */ +#define DRM_CLIENT_CAP_ASPECT_RATIO 4 + +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 + +/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ +struct drm_set_client_cap { + __u64 capability; + __u64 value; +}; + +#define DRM_RDWR O_RDWR +#define DRM_CLOEXEC O_CLOEXEC +struct drm_prime_handle { + __u32 handle; + + /** Flags.. only applicable for handle->fd */ + __u32 flags; + + /** Returned dmabuf file descriptor */ + __s32 fd; +}; + +struct drm_syncobj_create { + __u32 handle; +#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) + __u32 flags; +}; + +struct drm_syncobj_destroy { + __u32 handle; + __u32 pad; +}; + +#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) +#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) +struct drm_syncobj_handle { + __u32 handle; + __u32 flags; + + __s32 fd; + __u32 pad; +}; + +struct drm_syncobj_transfer { + __u32 src_handle; + __u32 dst_handle; + __u64 src_point; + __u64 dst_point; + __u32 flags; + __u32 pad; +}; + +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ +struct drm_syncobj_wait { + __u64 handles; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + +struct drm_syncobj_timeline_wait { + __u64 handles; + /* wait on specific timeline point for every handles*/ + __u64 points; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + + +struct drm_syncobj_array { + __u64 handles; + __u32 count_handles; + __u32 pad; +}; + +struct drm_syncobj_timeline_array { + __u64 handles; + __u64 points; + __u32 count_handles; + __u32 pad; +}; + + +/* Query current scanout sequence number */ +struct drm_crtc_get_sequence { + __u32 crtc_id; /* requested crtc_id */ + __u32 active; /* return: crtc output is active */ + __u64 sequence; /* return: most recent vblank sequence */ + __s64 sequence_ns; /* return: most recent time of first pixel out */ +}; + +/* Queue event to be delivered at specified sequence. Time stamp marks + * when the first pixel of the refresh cycle leaves the display engine + * for the display + */ +#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ +#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ + +struct drm_crtc_queue_sequence { + __u32 crtc_id; + __u32 flags; + __u64 sequence; /* on input, target sequence. on output, actual sequence */ + __u64 user_data; /* user data passed to event */ +}; + +#if defined(__cplusplus) +} +#endif + +#include "drm_mode.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_IOCTL_BASE 'd' +#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) +#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) + +#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) +#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) +#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) +#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) +#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) +#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) +#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) +#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap) + +#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) +#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) +#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) +#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) +#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) +#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) +#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) +#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) +#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) +#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) +#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) + +#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) + +#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) +#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) + +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + +#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) +#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) +#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) +#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) +#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) +#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) +#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) +#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) +#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) +#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) +#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) +#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) +#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) + +#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) +#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) + +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) + +#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) +#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) + +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) + +#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) +#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) + +#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) + +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) +#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) +#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */ +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */ + +#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) +#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) +#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) +#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) + +#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) +#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) +#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) +#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) +#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) +#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) +#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) +#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) +#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) +#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) +#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) +#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) + +#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) +#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) +#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait) +#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array) +#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array) + +#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease) +#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees) +#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) +#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) + +#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) +#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array) +#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) +#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) + +/** + * Device specific ioctls should only be in their respective headers + * The device specific ioctl range is from 0x40 to 0x9f. + * Generic IOCTLS restart at 0xA0. + * + * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and + * drmCommandReadWrite(). + */ +#define DRM_COMMAND_BASE 0x40 +#define DRM_COMMAND_END 0xA0 + +/** + * Header for events written back to userspace on the drm fd. The + * type defines the type of event, the length specifies the total + * length of the event (including the header), and user_data is + * typically a 64 bit value passed with the ioctl that triggered the + * event. A read on the drm fd will always only return complete + * events, that is, if for example the read buffer is 100 bytes, and + * there are two 64 byte events pending, only one will be returned. + * + * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and + * up are chipset specific. + */ +struct drm_event { + __u32 type; + __u32 length; +}; + +#define DRM_EVENT_VBLANK 0x01 +#define DRM_EVENT_FLIP_COMPLETE 0x02 +#define DRM_EVENT_CRTC_SEQUENCE 0x03 + +struct drm_event_vblank { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 crtc_id; /* 0 on older kernels that do not support this */ +}; + +/* Event delivered at sequence. Time stamp marks when the first pixel + * of the refresh cycle leaves the display engine for the display + */ +struct drm_event_crtc_sequence { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; +}; + +/* typedef area */ +typedef struct drm_clip_rect drm_clip_rect_t; +typedef struct drm_drawable_info drm_drawable_info_t; +typedef struct drm_tex_region drm_tex_region_t; +typedef struct drm_hw_lock drm_hw_lock_t; +typedef struct drm_version drm_version_t; +typedef struct drm_unique drm_unique_t; +typedef struct drm_list drm_list_t; +typedef struct drm_block drm_block_t; +typedef struct drm_control drm_control_t; +typedef enum drm_map_type drm_map_type_t; +typedef enum drm_map_flags drm_map_flags_t; +typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; +typedef struct drm_map drm_map_t; +typedef struct drm_client drm_client_t; +typedef enum drm_stat_type drm_stat_type_t; +typedef struct drm_stats drm_stats_t; +typedef enum drm_lock_flags drm_lock_flags_t; +typedef struct drm_lock drm_lock_t; +typedef enum drm_dma_flags drm_dma_flags_t; +typedef struct drm_buf_desc drm_buf_desc_t; +typedef struct drm_buf_info drm_buf_info_t; +typedef struct drm_buf_free drm_buf_free_t; +typedef struct drm_buf_pub drm_buf_pub_t; +typedef struct drm_buf_map drm_buf_map_t; +typedef struct drm_dma drm_dma_t; +typedef union drm_wait_vblank drm_wait_vblank_t; +typedef struct drm_agp_mode drm_agp_mode_t; +typedef enum drm_ctx_flags drm_ctx_flags_t; +typedef struct drm_ctx drm_ctx_t; +typedef struct drm_ctx_res drm_ctx_res_t; +typedef struct drm_draw drm_draw_t; +typedef struct drm_update_draw drm_update_draw_t; +typedef struct drm_auth drm_auth_t; +typedef struct drm_irq_busid drm_irq_busid_t; +typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; + +typedef struct drm_agp_buffer drm_agp_buffer_t; +typedef struct drm_agp_binding drm_agp_binding_t; +typedef struct drm_agp_info drm_agp_info_t; +typedef struct drm_scatter_gather drm_scatter_gather_t; +typedef struct drm_set_version drm_set_version_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_fourcc.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_fourcc.h new file mode 100644 index 0000000..5c69090 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_fourcc.h @@ -0,0 +1,763 @@ +/* + * Copyright 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DRM_FOURCC_H +#define DRM_FOURCC_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * DOC: overview + * + * In the DRM subsystem, framebuffer pixel formats are described using the + * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the + * fourcc code, a Format Modifier may optionally be provided, in order to + * further describe the buffer's format - for example tiling or compression. + * + * Format Modifiers + * ---------------- + * + * Format modifiers are used in conjunction with a fourcc code, forming a + * unique fourcc:modifier pair. This format:modifier pair must fully define the + * format and data layout of the buffer, and should be the only way to describe + * that particular buffer. + * + * Having multiple fourcc:modifier pairs which describe the same layout should + * be avoided, as such aliases run the risk of different drivers exposing + * different names for the same data format, forcing userspace to understand + * that they are aliases. + * + * Format modifiers may change any property of the buffer, including the number + * of planes and/or the required allocation size. Format modifiers are + * vendor-namespaced, and as such the relationship between a fourcc code and a + * modifier is specific to the modifer being used. For example, some modifiers + * may preserve meaning - such as number of planes - from the fourcc code, + * whereas others may not. + * + * Vendors should document their modifier usage in as much detail as + * possible, to ensure maximum compatibility across devices, drivers and + * applications. + * + * The authoritative list of format modifier codes is found in + * `include/uapi/drm/drm_fourcc.h` + */ + +#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ + ((__u32)(c) << 16) | ((__u32)(d) << 24)) + +#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ + +/* Reserve 0 for the invalid format specifier */ +#define DRM_FORMAT_INVALID 0 + +/* color index */ +#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ + +/* 8 bpp Red */ +#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ + +/* 16 bpp Red */ +#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ + +/* 16 bpp RG */ +#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */ +#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ + +/* 32 bpp RG */ +#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */ +#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ + +/* 8 bpp RGB */ +#define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ +#define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ + +/* 16 bpp RGB */ +#define DRM_FORMAT_XRGB4444 fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ +#define DRM_FORMAT_XBGR4444 fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ +#define DRM_FORMAT_RGBX4444 fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ +#define DRM_FORMAT_BGRX4444 fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ + +#define DRM_FORMAT_ARGB4444 fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ +#define DRM_FORMAT_ABGR4444 fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ +#define DRM_FORMAT_RGBA4444 fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ +#define DRM_FORMAT_BGRA4444 fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ + +#define DRM_FORMAT_XRGB1555 fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ +#define DRM_FORMAT_XBGR1555 fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ +#define DRM_FORMAT_RGBX5551 fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ +#define DRM_FORMAT_BGRX5551 fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ + +#define DRM_FORMAT_ARGB1555 fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ +#define DRM_FORMAT_ABGR1555 fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ +#define DRM_FORMAT_RGBA5551 fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ +#define DRM_FORMAT_BGRA5551 fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ + +#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ +#define DRM_FORMAT_BGR565 fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ + +/* 24 bpp RGB */ +#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ +#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ + +/* 32 bpp RGB */ +#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ +#define DRM_FORMAT_RGBX8888 fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ +#define DRM_FORMAT_BGRX8888 fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ + +#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ +#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ +#define DRM_FORMAT_BGRA8888 fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ + +#define DRM_FORMAT_XRGB2101010 fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ +#define DRM_FORMAT_XBGR2101010 fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ +#define DRM_FORMAT_RGBX1010102 fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ +#define DRM_FORMAT_BGRX1010102 fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ + +#define DRM_FORMAT_ARGB2101010 fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ +#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ +#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ +#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ + +/* + * Floating point 64bpp RGB + * IEEE 754-2008 binary16 half-precision float + * [15:0] sign:exponent:mantissa 1:5:10 + */ +#define DRM_FORMAT_XRGB16161616F fourcc_code('X', 'R', '4', 'H') /* [63:0] x:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ + +#define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H') /* [63:0] A:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ + +/* packed YCbCr */ +#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ +#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ + +#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */ +#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */ + +/* + * packed Y2xx indicate for each component, xx valid data occupy msb + * 16-xx padding occupy lsb + */ +#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels */ +#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels */ +#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels */ + +/* + * packed Y4xx indicate for each component, xx valid data occupy msb + * 16-xx padding occupy lsb except Y410 + */ +#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */ +#define DRM_FORMAT_Y412 fourcc_code('Y', '4', '1', '2') /* [63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ +#define DRM_FORMAT_Y416 fourcc_code('Y', '4', '1', '6') /* [63:0] A:Cr:Y:Cb 16:16:16:16 little endian */ + +#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */ +#define DRM_FORMAT_XVYU12_16161616 fourcc_code('X', 'V', '3', '6') /* [63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ +#define DRM_FORMAT_XVYU16161616 fourcc_code('X', 'V', '4', '8') /* [63:0] X:Cr:Y:Cb 16:16:16:16 little endian */ + +/* + * packed YCbCr420 2x2 tiled formats + * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile + */ +/* [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ +#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0') +/* [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ +#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0') + +/* [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ +#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2') +/* [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ +#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2') + +/* + * 1-plane YUV 4:2:0 + * In these formats, the component ordering is specified (Y, followed by U + * then V), but the exact Linear layout is undefined. + * These formats can only be used with a non-Linear modifier. + */ +#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8') +#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0') + +/* + * 2 plane RGB + A + * index 0 = RGB plane, same format as the corresponding non _A8 format has + * index 1 = A plane, [7:0] A + */ +#define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8') +#define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8') +#define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8') +#define DRM_FORMAT_BGRX8888_A8 fourcc_code('B', 'X', 'A', '8') +#define DRM_FORMAT_RGB888_A8 fourcc_code('R', '8', 'A', '8') +#define DRM_FORMAT_BGR888_A8 fourcc_code('B', '8', 'A', '8') +#define DRM_FORMAT_RGB565_A8 fourcc_code('R', '5', 'A', '8') +#define DRM_FORMAT_BGR565_A8 fourcc_code('B', '5', 'A', '8') + +/* + * 2 plane YCbCr + * index 0 = Y plane, [7:0] Y + * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian + * or + * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian + */ +#define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + */ +#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0') /* 2x1 subsampled Cr:Cb plane, 10 bit per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + */ +#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [12:4] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian + */ +#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane 12 bits per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y little endian + * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian + */ +#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + +/* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y + * index 1: Cb plane, [7:0] Cb + * index 2: Cr plane, [7:0] Cr + * or + * index 1: Cr plane, [7:0] Cr + * index 2: Cb plane, [7:0] Cb + */ +#define DRM_FORMAT_YUV410 fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU410 fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU411 fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV420 fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU420 fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV422 fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU422 fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ + + +/* + * Format Modifiers: + * + * Format modifiers describe, typically, a re-ordering or modification + * of the data in a plane of an FB. This can be used to express tiled/ + * swizzled formats, or compression, or a combination of the two. + * + * The upper 8 bits of the format modifier are a vendor-id as assigned + * below. The lower 56 bits are assigned as vendor sees fit. + */ + +/* Vendor Ids: */ +#define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 +#define DRM_FORMAT_MOD_VENDOR_AMD 0x02 +#define DRM_FORMAT_MOD_VENDOR_NVIDIA 0x03 +#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 +#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 +#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06 +#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 +#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 +#define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 + +/* add more to the end as needed */ + +#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) + +#define fourcc_mod_code(vendor, val) \ + ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL)) + +/* + * Format Modifier tokens: + * + * When adding a new token please document the layout with a code comment, + * similar to the fourcc codes above. drm_fourcc.h is considered the + * authoritative source for all of these. + */ + +/* + * Invalid Modifier + * + * This modifier can be used as a sentinel to terminate the format modifiers + * list, or to initialize a variable with an invalid modifier. It might also be + * used to report an error back to userspace for certain APIs. + */ +#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) + +/* + * Linear Layout + * + * Just plain linear layout. Note that this is different from no specifying any + * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl), + * which tells the driver to also take driver-internal information into account + * and so might actually result in a tiled framebuffer. + */ +#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) + +/* Intel framebuffer modifiers */ + +/* + * Intel X-tiling layout + * + * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) + * in row-major layout. Within the tile bytes are laid out row-major, with + * a platform-dependent stride. On top of that the memory can apply + * platform-depending swizzling of some higher address bits into bit6. + * + * This format is highly platforms specific and not useful for cross-driver + * sharing. It exists since on a given platform it does uniquely identify the + * layout in a simple way for i915-specific userspace. + */ +#define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1) + +/* + * Intel Y-tiling layout + * + * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) + * in row-major layout. Within the tile bytes are laid out in OWORD (16 bytes) + * chunks column-major, with a platform-dependent height. On top of that the + * memory can apply platform-depending swizzling of some higher address bits + * into bit6. + * + * This format is highly platforms specific and not useful for cross-driver + * sharing. It exists since on a given platform it does uniquely identify the + * layout in a simple way for i915-specific userspace. + */ +#define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2) + +/* + * Intel Yf-tiling layout + * + * This is a tiled layout using 4Kb tiles in row-major layout. + * Within the tile pixels are laid out in 16 256 byte units / sub-tiles which + * are arranged in four groups (two wide, two high) with column-major layout. + * Each group therefore consists out of four 256 byte units, which are also laid + * out as 2x2 column-major. + * 256 byte units are made out of four 64 byte blocks of pixels, producing + * either a square block or a 2:1 unit. + * 64 byte blocks of pixels contain four pixel rows of 16 bytes, where the width + * in pixel depends on the pixel depth. + */ +#define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3) + +/* + * Intel color control surface (CCS) for render compression + * + * The framebuffer format must be one of the 8:8:8:8 RGB formats. + * The main surface will be plane index 0 and must be Y/Yf-tiled, + * the CCS will be plane index 1. + * + * Each CCS tile matches a 1024x512 pixel area of the main surface. + * To match certain aspects of the 3D hardware the CCS is + * considered to be made up of normal 128Bx32 Y tiles, Thus + * the CCS pitch must be specified in multiples of 128 bytes. + * + * In reality the CCS tile appears to be a 64Bx64 Y tile, composed + * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks. + * But that fact is not relevant unless the memory is accessed + * directly. + */ +#define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) +#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) + +/* + * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks + * + * Macroblocks are laid in a Z-shape, and each pixel data is following the + * standard NV12 style. + * As for NV12, an image is the result of two frame buffers: one for Y, + * one for the interleaved Cb/Cr components (1/2 the height of the Y buffer). + * Alignment requirements are (for each buffer): + * - multiple of 128 pixels for the width + * - multiple of 32 pixels for the height + * + * For more information: see https://linuxtv.org/downloads/v4l-dvb-apis/re32.html + */ +#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) + +/* + * Tiled, 16 (pixels) x 16 (lines) - sized macroblocks + * + * This is a simple tiled layout using tiles of 16x16 pixels in a row-major + * layout. For YCbCr formats Cb/Cr components are taken in such a way that + * they correspond to their 16x16 luma block. + */ +#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2) + +/* + * Qualcomm Compressed Format + * + * Refers to a compressed variant of the base format that is compressed. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + +/* Vivante framebuffer modifiers */ + +/* + * Vivante 4x4 tiling layout + * + * This is a simple tiled layout using tiles of 4x4 pixels in a row-major + * layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1) + +/* + * Vivante 64x64 super-tiling layout + * + * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile + * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row- + * major layout. + * + * For more information: see + * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling + */ +#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2) + +/* + * Vivante 4x4 tiling layout for dual-pipe + * + * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a + * different base address. Offsets from the base addresses are therefore halved + * compared to the non-split tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3) + +/* + * Vivante 64x64 super-tiling layout for dual-pipe + * + * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile + * starts at a different base address. Offsets from the base addresses are + * therefore halved compared to the non-split super-tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4) + +/* NVIDIA frame buffer modifiers */ + +/* + * Tegra Tiled Layout, used by Tegra 2, 3 and 4. + * + * Pixels are arranged in simple tiles of 16 x 16 bytes. + */ +#define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1) + +/* + * 16Bx2 Block Linear layout, used by desktop GPUs, and Tegra K1 and later + * + * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked + * vertically by a power of 2 (1 to 32 GOBs) to form a block. + * + * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape. + * + * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically. + * Valid values are: + * + * 0 == ONE_GOB + * 1 == TWO_GOBS + * 2 == FOUR_GOBS + * 3 == EIGHT_GOBS + * 4 == SIXTEEN_GOBS + * 5 == THIRTYTWO_GOBS + * + * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format + * in full detail. + */ +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \ + fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf)) + +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \ + fourcc_mod_code(NVIDIA, 0x10) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \ + fourcc_mod_code(NVIDIA, 0x11) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \ + fourcc_mod_code(NVIDIA, 0x12) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \ + fourcc_mod_code(NVIDIA, 0x13) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \ + fourcc_mod_code(NVIDIA, 0x14) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ + fourcc_mod_code(NVIDIA, 0x15) + +/* + * Some Broadcom modifiers take parameters, for example the number of + * vertical lines in the image. Reserve the lower 32 bits for modifier + * type, and the next 24 bits for parameters. Top 8 bits are the + * vendor code. + */ +#define __fourcc_mod_broadcom_param_shift 8 +#define __fourcc_mod_broadcom_param_bits 48 +#define fourcc_mod_broadcom_code(val, params) \ + fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val)) +#define fourcc_mod_broadcom_param(m) \ + ((int)(((m) >> __fourcc_mod_broadcom_param_shift) & \ + ((1ULL << __fourcc_mod_broadcom_param_bits) - 1))) +#define fourcc_mod_broadcom_mod(m) \ + ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << \ + __fourcc_mod_broadcom_param_shift)) + +/* + * Broadcom VC4 "T" format + * + * This is the primary layout that the V3D GPU can texture from (it + * can't do linear). The T format has: + * + * - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4 + * pixels at 32 bit depth. + * + * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually + * 16x16 pixels). + * + * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On + * even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows + * they're (TR, BR, BL, TL), where bottom left is start of memory. + * + * - an image made of 4k tiles in rows either left-to-right (even rows of 4k + * tiles) or right-to-left (odd rows of 4k tiles). + */ +#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1) + +/* + * Broadcom SAND format + * + * This is the native format that the H.264 codec block uses. For VC4 + * HVS, it is only valid for H.264 (NV12/21) and RGBA modes. + * + * The image can be considered to be split into columns, and the + * columns are placed consecutively into memory. The width of those + * columns can be either 32, 64, 128, or 256 pixels, but in practice + * only 128 pixel columns are used. + * + * The pitch between the start of each column is set to optimally + * switch between SDRAM banks. This is passed as the number of lines + * of column width in the modifier (we can't use the stride value due + * to various core checks that look at it , so you should set the + * stride to width*cpp). + * + * Note that the column height for this format modifier is the same + * for all of the planes, assuming that each column contains both Y + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. + */ + +#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(2, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(3, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(4, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(5, v) + +#define DRM_FORMAT_MOD_BROADCOM_SAND32 \ + DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND64 \ + DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND128 \ + DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND256 \ + DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) + +/* Broadcom UIF format + * + * This is the common format for the current Broadcom multimedia + * blocks, including V3D 3.x and newer, newer video codecs, and + * displays. + * + * The image consists of utiles (64b blocks), UIF blocks (2x2 utiles), + * and macroblocks (4x4 UIF blocks). Those 4x4 UIF block groups are + * stored in columns, with padding between the columns to ensure that + * moving from one column to the next doesn't hit the same SDRAM page + * bank. + * + * To calculate the padding, it is assumed that each hardware block + * and the software driving it knows the platform's SDRAM page size, + * number of banks, and XOR address, and that it's identical between + * all blocks using the format. This tiling modifier will use XOR as + * necessary to reduce the padding. If a hardware block can't do XOR, + * the assumption is that a no-XOR tiling modifier will be created. + */ +#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) + +/* + * Arm Framebuffer Compression (AFBC) modifiers + * + * AFBC is a proprietary lossless image compression protocol and format. + * It provides fine-grained random access and minimizes the amount of data + * transferred between IP blocks. + * + * AFBC has several features which may be supported and/or used, which are + * represented using bits in the modifier. Not all combinations are valid, + * and different devices or use-cases may support different combinations. + * + * Further information on the use of AFBC modifiers can be found in + * Documentation/gpu/afbc.rst + */ +#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) + +/* + * AFBC superblock size + * + * Indicates the superblock size(s) used for the AFBC buffer. The buffer + * size (in pixels) must be aligned to a multiple of the superblock size. + * Four lowest significant bits(LSBs) are reserved for block size. + * + * Where one superblock size is specified, it applies to all planes of the + * buffer (e.g. 16x16, 32x8). When multiple superblock sizes are specified, + * the first applies to the Luma plane and the second applies to the Chroma + * plane(s). e.g. (32x8_64x4 means 32x8 Luma, with 64x4 Chroma). + * Multiple superblock sizes are only valid for multi-plane YCbCr formats. + */ +#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf +#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 (3ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 (4ULL) + +/* + * AFBC lossless colorspace transform + * + * Indicates that the buffer makes use of the AFBC lossless colorspace + * transform. + */ +#define AFBC_FORMAT_MOD_YTR (1ULL << 4) + +/* + * AFBC block-split + * + * Indicates that the payload of each superblock is split. The second + * half of the payload is positioned at a predefined offset from the start + * of the superblock payload. + */ +#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5) + +/* + * AFBC sparse layout + * + * This flag indicates that the payload of each superblock must be stored at a + * predefined position relative to the other superblocks in the same AFBC + * buffer. This order is the same order used by the header buffer. In this mode + * each superblock is given the same amount of space as an uncompressed + * superblock of the particular format would require, rounding up to the next + * multiple of 128 bytes in size. + */ +#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6) + +/* + * AFBC copy-block restrict + * + * Buffers with this flag must obey the copy-block restriction. The restriction + * is such that there are no copy-blocks referring across the border of 8x8 + * blocks. For the subsampled data the 8x8 limitation is also subsampled. + */ +#define AFBC_FORMAT_MOD_CBR (1ULL << 7) + +/* + * AFBC tiled layout + * + * The tiled layout groups superblocks in 8x8 or 4x4 tiles, where all + * superblocks inside a tile are stored together in memory. 8x8 tiles are used + * for pixel formats up to and including 32 bpp while 4x4 tiles are used for + * larger bpp formats. The order between the tiles is scan line. + * When the tiled layout is used, the buffer size (in pixels) must be aligned + * to the tile size. + */ +#define AFBC_FORMAT_MOD_TILED (1ULL << 8) + +/* + * AFBC solid color blocks + * + * Indicates that the buffer makes use of solid-color blocks, whereby bandwidth + * can be reduced if a whole superblock is a single color. + */ +#define AFBC_FORMAT_MOD_SC (1ULL << 9) + +/* + * AFBC double-buffer + * + * Indicates that the buffer is allocated in a layout safe for front-buffer + * rendering. + */ +#define AFBC_FORMAT_MOD_DB (1ULL << 10) + +/* + * AFBC buffer content hints + * + * Indicates that the buffer includes per-superblock content hints. + */ +#define AFBC_FORMAT_MOD_BCH (1ULL << 11) + +/* + * Allwinner tiled modifier + * + * This tiling mode is implemented by the VPU found on all Allwinner platforms, + * codenamed sunxi. It is associated with a YUV format that uses either 2 or 3 + * planes. + * + * With this tiling, the luminance samples are disposed in tiles representing + * 32x32 pixels and the chrominance samples in tiles representing 32x64 pixels. + * The pixel order in each tile is linear and the tiles are disposed linearly, + * both in row-major order. + */ +#define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) + +#if defined(__cplusplus) +} +#endif + +#endif /* DRM_FOURCC_H */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_mode.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_mode.h new file mode 100644 index 0000000..5fe6c64 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_mode.h @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2007 Dave Airlie + * Copyright (c) 2007 Jakob Bornecrantz + * Copyright (c) 2008 Red Hat Inc. + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA + * Copyright (c) 2007-2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _DRM_MODE_H +#define _DRM_MODE_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */ +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) /* deprecated */ +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +#define DRM_MODE_TYPE_ALL (DRM_MODE_TYPE_PREFERRED | \ + DRM_MODE_TYPE_USERDEF | \ + DRM_MODE_TYPE_DRIVER) + +/* Video mode flags */ +/* bit compatible with the xrandr RR_ definitions (bits 0-13) + * + * ABI warning: Existing userspace really expects + * the mode flags to match the xrandr definitions. Any + * changes that don't match the xrandr definitions will + * likely need a new client cap or some other mechanism + * to avoid breaking existing userspace. This includes + * allocating new flags in the previously unused bits! + */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) /* deprecated */ +#define DRM_MODE_FLAG_PIXMUX (1<<11) /* deprecated */ +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) + /* + * When adding a new stereo mode don't forget to adjust DRM_MODE_FLAGS_3D_MAX + * (define not exposed to user space). + */ +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + +/* Picture aspect ratio options */ +#define DRM_MODE_PICTURE_ASPECT_NONE 0 +#define DRM_MODE_PICTURE_ASPECT_4_3 1 +#define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 + +/* Content type options */ +#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 +#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 +#define DRM_MODE_CONTENT_TYPE_PHOTO 2 +#define DRM_MODE_CONTENT_TYPE_CINEMA 3 +#define DRM_MODE_CONTENT_TYPE_GAME 4 + +/* Aspect ratio flag bitmask (4 bits 22:19) */ +#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) +#define DRM_MODE_FLAG_PIC_AR_NONE \ + (DRM_MODE_PICTURE_ASPECT_NONE<<19) +#define DRM_MODE_FLAG_PIC_AR_4_3 \ + (DRM_MODE_PICTURE_ASPECT_4_3<<19) +#define DRM_MODE_FLAG_PIC_AR_16_9 \ + (DRM_MODE_PICTURE_ASPECT_16_9<<19) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<19) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<19) + +#define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ + DRM_MODE_FLAG_NHSYNC | \ + DRM_MODE_FLAG_PVSYNC | \ + DRM_MODE_FLAG_NVSYNC | \ + DRM_MODE_FLAG_INTERLACE | \ + DRM_MODE_FLAG_DBLSCAN | \ + DRM_MODE_FLAG_CSYNC | \ + DRM_MODE_FLAG_PCSYNC | \ + DRM_MODE_FLAG_NCSYNC | \ + DRM_MODE_FLAG_HSKEW | \ + DRM_MODE_FLAG_DBLCLK | \ + DRM_MODE_FLAG_CLKDIV2 | \ + DRM_MODE_FLAG_3D_MASK) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NONE 0 /* Unmodified timing (display or + software can still scale) */ +#define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ +#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ +#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 +#define DRM_MODE_DITHERING_AUTO 2 + +/* Dirty info options */ +#define DRM_MODE_DIRTY_OFF 0 +#define DRM_MODE_DIRTY_ON 1 +#define DRM_MODE_DIRTY_ANNOTATE 2 + +/* Link Status options */ +#define DRM_MODE_LINK_STATUS_GOOD 0 +#define DRM_MODE_LINK_STATUS_BAD 1 + +/* + * DRM_MODE_ROTATE_ + * + * Signals that a drm plane is been rotated degrees in counter + * clockwise direction. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_ROTATE_0 (1<<0) +#define DRM_MODE_ROTATE_90 (1<<1) +#define DRM_MODE_ROTATE_180 (1<<2) +#define DRM_MODE_ROTATE_270 (1<<3) + +/* + * DRM_MODE_ROTATE_MASK + * + * Bitmask used to look for drm plane rotations. + */ +#define DRM_MODE_ROTATE_MASK (\ + DRM_MODE_ROTATE_0 | \ + DRM_MODE_ROTATE_90 | \ + DRM_MODE_ROTATE_180 | \ + DRM_MODE_ROTATE_270) + +/* + * DRM_MODE_REFLECT_ + * + * Signals that the contents of a drm plane is reflected along the axis, + * in the same way as mirroring. + * See kerneldoc chapter "Plane Composition Properties" for more details. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_REFLECT_X (1<<4) +#define DRM_MODE_REFLECT_Y (1<<5) + +/* + * DRM_MODE_REFLECT_MASK + * + * Bitmask used to look for drm plane reflections. + */ +#define DRM_MODE_REFLECT_MASK (\ + DRM_MODE_REFLECT_X | \ + DRM_MODE_REFLECT_Y) + +/* Content Protection Flags */ +#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED 0 +#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 +#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 + +struct drm_mode_modeinfo { + __u32 clock; + __u16 hdisplay; + __u16 hsync_start; + __u16 hsync_end; + __u16 htotal; + __u16 hskew; + __u16 vdisplay; + __u16 vsync_start; + __u16 vsync_end; + __u16 vtotal; + __u16 vscan; + + __u32 vrefresh; + + __u32 flags; + __u32 type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + __u64 fb_id_ptr; + __u64 crtc_id_ptr; + __u64 connector_id_ptr; + __u64 encoder_id_ptr; + __u32 count_fbs; + __u32 count_crtcs; + __u32 count_connectors; + __u32 count_encoders; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; +}; + +struct drm_mode_crtc { + __u64 set_connectors_ptr; + __u32 count_connectors; + + __u32 crtc_id; /**< Id */ + __u32 fb_id; /**< Id of framebuffer */ + + __u32 x; /**< x Position on the framebuffer */ + __u32 y; /**< y Position on the framebuffer */ + + __u32 gamma_size; + __u32 mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_PRESENT_TOP_FIELD (1<<0) +#define DRM_MODE_PRESENT_BOTTOM_FIELD (1<<1) + +/* Planes blend with or override other bits on the CRTC */ +struct drm_mode_set_plane { + __u32 plane_id; + __u32 crtc_id; + __u32 fb_id; /* fb object contains surface format type */ + __u32 flags; /* see above flags */ + + /* Signed dest location allows it to be partially off screen */ + __s32 crtc_x; + __s32 crtc_y; + __u32 crtc_w; + __u32 crtc_h; + + /* Source values are 16.16 fixed point */ + __u32 src_x; + __u32 src_y; + __u32 src_h; + __u32 src_w; +}; + +struct drm_mode_get_plane { + __u32 plane_id; + + __u32 crtc_id; + __u32 fb_id; + + __u32 possible_crtcs; + __u32 gamma_size; + + __u32 count_format_types; + __u64 format_type_ptr; +}; + +struct drm_mode_get_plane_res { + __u64 plane_id_ptr; + __u32 count_planes; +}; + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 + +struct drm_mode_get_encoder { + __u32 encoder_id; + __u32 encoder_type; + + __u32 crtc_id; /**< Id of crtc */ + + __u32 possible_crtcs; + __u32 possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +enum drm_mode_subconnector { + DRM_MODE_SUBCONNECTOR_Automatic = 0, + DRM_MODE_SUBCONNECTOR_Unknown = 0, + DRM_MODE_SUBCONNECTOR_DVID = 3, + DRM_MODE_SUBCONNECTOR_DVIA = 4, + DRM_MODE_SUBCONNECTOR_Composite = 5, + DRM_MODE_SUBCONNECTOR_SVIDEO = 6, + DRM_MODE_SUBCONNECTOR_Component = 8, + DRM_MODE_SUBCONNECTOR_SCART = 9, +}; + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 +#define DRM_MODE_CONNECTOR_WRITEBACK 18 + +struct drm_mode_get_connector { + + __u64 encoders_ptr; + __u64 modes_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + + __u32 count_modes; + __u32 count_props; + __u32 count_encoders; + + __u32 encoder_id; /**< Current Encoder */ + __u32 connector_id; /**< Id */ + __u32 connector_type; + __u32 connector_type_id; + + __u32 connection; + __u32 mm_width; /**< width in millimeters */ + __u32 mm_height; /**< height in millimeters */ + __u32 subpixel; + + __u32 pad; +}; + +#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) +#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ + +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, + * grab a chunk of the bits to use as integer type id. + */ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE(n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) + +/* the PROP_ATOMIC flag is used to hide properties from userspace that + * is not aware of atomic properties. This is mostly to work around + * older userspace (DDX drivers) that read/write each prop they find, + * without being aware that this could be triggering a lengthy modeset. + */ +#define DRM_MODE_PROP_ATOMIC 0x80000000 + +struct drm_mode_property_enum { + __u64 value; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + __u64 values_ptr; /* values and blob lengths */ + __u64 enum_blob_ptr; /* enum and blob id ptrs */ + + __u32 prop_id; + __u32 flags; + char name[DRM_PROP_NAME_LEN]; + + __u32 count_values; + /* This is only used to count enum values, not blobs. The _blobs is + * simply because of a historical reason, i.e. backwards compat. */ + __u32 count_enum_blobs; +}; + +struct drm_mode_connector_set_property { + __u64 value; + __u32 prop_id; + __u32 connector_id; +}; + +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee +#define DRM_MODE_OBJECT_ANY 0 + +struct drm_mode_obj_get_properties { + __u64 props_ptr; + __u64 prop_values_ptr; + __u32 count_props; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_obj_set_property { + __u64 value; + __u32 prop_id; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_get_blob { + __u32 blob_id; + __u32 length; + __u64 data; +}; + +struct drm_mode_fb_cmd { + __u32 fb_id; + __u32 width; + __u32 height; + __u32 pitch; + __u32 bpp; + __u32 depth; + /* driver specific handle */ + __u32 handle; +}; + +#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ +#define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[] */ + +struct drm_mode_fb_cmd2 { + __u32 fb_id; + __u32 width; + __u32 height; + __u32 pixel_format; /* fourcc code from drm_fourcc.h */ + __u32 flags; /* see above flags */ + + /* + * In case of planar formats, this ioctl allows up to 4 + * buffer objects with offsets and pitches per plane. + * The pitch and offset order is dictated by the fourcc, + * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: + * + * YUV 4:2:0 image with a plane of 8 bit Y samples + * followed by an interleaved U/V plane containing + * 8 bit 2x2 subsampled colour difference samples. + * + * So it would consist of Y as offsets[0] and UV as + * offsets[1]. Note that offsets[0] will generally + * be 0 (but this is not required). + * + * To accommodate tiled, compressed, etc formats, a + * modifier can be specified. The default value of zero + * indicates "native" format as specified by the fourcc. + * Vendor specific modifier token. Note that even though + * it looks like we have a modifier per-plane, we in fact + * do not. The modifier for each plane must be identical. + * Thus all combinations of different data layouts for + * multi plane formats must be enumerated as separate + * modifiers. + */ + __u32 handles[4]; + __u32 pitches[4]; /* pitch for each plane */ + __u32 offsets[4]; /* offset of each plane */ + __u64 modifier[4]; /* ie, tiling, compress */ +}; + +#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 +#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 +#define DRM_MODE_FB_DIRTY_FLAGS 0x03 + +#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256 + +/* + * Mark a region of a framebuffer as dirty. + * + * Some hardware does not automatically update display contents + * as a hardware or software draw to a framebuffer. This ioctl + * allows userspace to tell the kernel and the hardware what + * regions of the framebuffer have changed. + * + * The kernel or hardware is free to update more then just the + * region specified by the clip rects. The kernel or hardware + * may also delay and/or coalesce several calls to dirty into a + * single update. + * + * Userspace may annotate the updates, the annotates are a + * promise made by the caller that the change is either a copy + * of pixels or a fill of a single color in the region specified. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then + * the number of updated regions are half of num_clips given, + * where the clip rects are paired in src and dst. The width and + * height of each one of the pairs must match. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller + * promises that the region specified of the clip rects is filled + * completely with a single color as given in the color argument. + */ + +struct drm_mode_fb_dirty_cmd { + __u32 fb_id; + __u32 flags; + __u32 color; + __u32 num_clips; + __u64 clips_ptr; +}; + +struct drm_mode_mode_cmd { + __u32 connector_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 + +/* + * depending on the value in flags different members are used. + * + * CURSOR_BO uses + * crtc_id + * width + * height + * handle - if 0 turns the cursor off + * + * CURSOR_MOVE uses + * crtc_id + * x + * y + */ +struct drm_mode_cursor { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; +}; + +struct drm_mode_cursor2 { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; + __s32 hot_x; + __s32 hot_y; +}; + +struct drm_mode_crtc_lut { + __u32 crtc_id; + __u32 gamma_size; + + /* pointers to arrays */ + __u64 red; + __u64 green; + __u64 blue; +}; + +struct drm_color_ctm { + /* + * Conversion matrix in S31.32 sign-magnitude + * (not two's complement!) format. + */ + __u64 matrix[9]; +}; + +struct drm_color_lut { + /* + * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and + * 0xffff == 1.0. + */ + __u16 red; + __u16 green; + __u16 blue; + __u16 reserved; +}; + +#define DRM_MODE_PAGE_FLIP_EVENT 0x01 +#define DRM_MODE_PAGE_FLIP_ASYNC 0x02 +#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 +#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8 +#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \ + DRM_MODE_PAGE_FLIP_TARGET_RELATIVE) +#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \ + DRM_MODE_PAGE_FLIP_ASYNC | \ + DRM_MODE_PAGE_FLIP_TARGET) + +/* + * Request a page flip on the specified crtc. + * + * This ioctl will ask KMS to schedule a page flip for the specified + * crtc. Once any pending rendering targeting the specified fb (as of + * ioctl time) has completed, the crtc will be reprogrammed to display + * that fb after the next vertical refresh. The ioctl returns + * immediately, but subsequent rendering to the current fb will block + * in the execbuffer ioctl until the page flip happens. If a page + * flip is already pending as the ioctl is called, EBUSY will be + * returned. + * + * Flag DRM_MODE_PAGE_FLIP_EVENT requests that drm sends back a vblank + * event (see drm.h: struct drm_event_vblank) when the page flip is + * done. The user_data field passed in with this ioctl will be + * returned as the user_data field in the vblank event struct. + * + * Flag DRM_MODE_PAGE_FLIP_ASYNC requests that the flip happen + * 'as soon as possible', meaning that it not delay waiting for vblank. + * This may cause tearing on the screen. + * + * The reserved field must be zero. + */ + +struct drm_mode_crtc_page_flip { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 reserved; + __u64 user_data; +}; + +/* + * Request a page flip on the specified crtc. + * + * Same as struct drm_mode_crtc_page_flip, but supports new flags and + * re-purposes the reserved field: + * + * The sequence field must be zero unless either of the + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When + * the ABSOLUTE flag is specified, the sequence field denotes the absolute + * vblank sequence when the flip should take effect. When the RELATIVE + * flag is specified, the sequence field denotes the relative (to the + * current one when the ioctl is called) vblank sequence when the flip + * should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to + * make sure the vblank sequence before the target one has passed before + * calling this ioctl. The purpose of the + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify + * the target for when code dealing with a page flip runs during a + * vertical blank period. + */ + +struct drm_mode_crtc_page_flip_target { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 sequence; + __u64 user_data; +}; + +/* create a dumb scanout buffer */ +struct drm_mode_create_dumb { + __u32 height; + __u32 width; + __u32 bpp; + __u32 flags; + /* handle, pitch, size will be returned */ + __u32 handle; + __u32 pitch; + __u64 size; +}; + +/* set up for mmap of a dumb scanout buffer */ +struct drm_mode_map_dumb { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_mode_destroy_dumb { + __u32 handle; +}; + +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + +struct drm_format_modifier_blob { +#define FORMAT_BLOB_CURRENT 1 + /* Version of this blob format */ + __u32 version; + + /* Flags */ + __u32 flags; + + /* Number of fourcc formats supported */ + __u32 count_formats; + + /* Where in this blob the formats exist (in bytes) */ + __u32 formats_offset; + + /* Number of drm_format_modifiers */ + __u32 count_modifiers; + + /* Where in this blob the modifiers exist (in bytes) */ + __u32 modifiers_offset; + + /* __u32 formats[] */ + /* struct drm_format_modifier modifiers[] */ +}; + +struct drm_format_modifier { + /* Bitmask of formats in get_plane format list this info applies to. The + * offset allows a sliding window of which 64 formats (bits). + * + * Some examples: + * In today's world with < 65 formats, and formats 0, and 2 are + * supported + * 0x0000000000000005 + * ^-offset = 0, formats = 5 + * + * If the number formats grew to 128, and formats 98-102 are + * supported with the modifier: + * + * 0x0000007c00000000 0000000000000000 + * ^ + * |__offset = 64, formats = 0x7c00000000 + * + */ + __u64 formats; + __u32 offset; + __u32 pad; + + /* The modifier that applies to the >get_plane format list bitmask. */ + __u64 modifier; +}; + +/** + * Create a new 'blob' data property, copying length bytes from data pointer, + * and returning new blob ID. + */ +struct drm_mode_create_blob { + /** Pointer to data to copy. */ + __u64 data; + /** Length of data to copy. */ + __u32 length; + /** Return: new property ID. */ + __u32 blob_id; +}; + +/** + * Destroy a user-created blob property. + */ +struct drm_mode_destroy_blob { + __u32 blob_id; +}; + +/** + * Lease mode resources, creating another drm_master. + */ +struct drm_mode_create_lease { + /** Pointer to array of object ids (__u32) */ + __u64 object_ids; + /** Number of object ids */ + __u32 object_count; + /** flags for new FD (O_CLOEXEC, etc) */ + __u32 flags; + + /** Return: unique identifier for lessee. */ + __u32 lessee_id; + /** Return: file descriptor to new drm_master file */ + __u32 fd; +}; + +/** + * List lesses from a drm_master + */ +struct drm_mode_list_lessees { + /** Number of lessees. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_lessees; + __u32 pad; + + /** Pointer to lessees. + * pointer to __u64 array of lessee ids + */ + __u64 lessees_ptr; +}; + +/** + * Get leased objects + */ +struct drm_mode_get_lease { + /** Number of leased objects. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_objects; + __u32 pad; + + /** Pointer to objects. + * pointer to __u32 array of object ids + */ + __u64 objects_ptr; +}; + +/** + * Revoke lease + */ +struct drm_mode_revoke_lease { + /** Unique ID of lessee + */ + __u32 lessee_id; +}; + +/** + * struct drm_mode_rect - Two dimensional rectangle. + * @x1: Horizontal starting coordinate (inclusive). + * @y1: Vertical starting coordinate (inclusive). + * @x2: Horizontal ending coordinate (exclusive). + * @y2: Vertical ending coordinate (exclusive). + * + * With drm subsystem using struct drm_rect to manage rectangular area this + * export it to user-space. + * + * Currently used by drm_mode_atomic blob property FB_DAMAGE_CLIPS. + */ +struct drm_mode_rect { + __s32 x1; + __s32 y1; + __s32 x2; + __s32 y2; +}; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_sarea.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_sarea.h new file mode 100644 index 0000000..93025be --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_sarea.h @@ -0,0 +1,92 @@ +/** + * \file drm_sarea.h + * \brief SAREA definitions + * + * \author Michel Dänzer + */ + +/* + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* SAREA area needs to be at least a page */ +#if defined(__alpha__) +#define SAREA_MAX 0x2000U +#elif defined(__mips__) +#define SAREA_MAX 0x4000U +#elif defined(__ia64__) +#define SAREA_MAX 0x10000U /* 64kB */ +#else +/* Intel 830M driver needs at least 8k SAREA */ +#define SAREA_MAX 0x2000U +#endif + +/** Maximum number of drawables in the SAREA */ +#define SAREA_MAX_DRAWABLES 256 + +#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000 + +/** SAREA drawable */ +struct drm_sarea_drawable { + unsigned int stamp; + unsigned int flags; +}; + +/** SAREA frame */ +struct drm_sarea_frame { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +}; + +/** SAREA */ +struct drm_sarea { + /** first thing is always the DRM locking structure */ + struct drm_hw_lock lock; + /** \todo Use readers/writer lock for drm_sarea::drawable_lock */ + struct drm_hw_lock drawable_lock; + struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */ + struct drm_sarea_frame frame; /**< frame */ + drm_context_t dummy_context; +}; + +typedef struct drm_sarea_drawable drm_sarea_drawable_t; +typedef struct drm_sarea_frame drm_sarea_frame_t; +typedef struct drm_sarea drm_sarea_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* _DRM_SAREA_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/i915_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/i915_drm.h new file mode 100644 index 0000000..72afd94 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/i915_drm.h @@ -0,0 +1,1915 @@ +/* + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _I915_DRM_H_ +#define _I915_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +/** + * DOC: uevents generated by i915 on it's device node + * + * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch + * event from the gpu l3 cache. Additional information supplied is ROW, + * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep + * track of these events and if a specific cache-line seems to have a + * persistent error remap it with the l3 remapping tool supplied in + * intel-gpu-tools. The value supplied with the event is always 1. + * + * I915_ERROR_UEVENT - Generated upon error detection, currently only via + * hangcheck. The error detection event is a good indicator of when things + * began to go badly. The value supplied with the event is a 1 upon error + * detection, and a 0 upon reset completion, signifying no more error + * exists. NOTE: Disabling hangcheck or reset via module parameter will + * cause the related events to not be seen. + * + * I915_RESET_UEVENT - Event is generated just before an attempt to reset the + * the GPU. The value supplied with the event is always 1. NOTE: Disable + * reset via module parameter will cause this event to not be seen. + */ +#define I915_L3_PARITY_UEVENT "L3_PARITY_ERROR" +#define I915_ERROR_UEVENT "ERROR" +#define I915_RESET_UEVENT "RESET" + +/* + * i915_user_extension: Base class for defining a chain of extensions + * + * Many interfaces need to grow over time. In most cases we can simply + * extend the struct and have userspace pass in more data. Another option, + * as demonstrated by Vulkan's approach to providing extensions for forward + * and backward compatibility, is to use a list of optional structs to + * provide those extra details. + * + * The key advantage to using an extension chain is that it allows us to + * redefine the interface more easily than an ever growing struct of + * increasing complexity, and for large parts of that interface to be + * entirely optional. The downside is more pointer chasing; chasing across + * the boundary with pointers encapsulated inside u64. + */ +struct i915_user_extension { + __u64 next_extension; + __u32 name; + __u32 flags; /* All undefined bits must be zero. */ + __u32 rsvd[4]; /* Reserved for future use; must be zero. */ +}; + +/* + * MOCS indexes used for GPU surfaces, defining the cacheability of the + * surface data and the coherency for this data wrt. CPU vs. GPU accesses. + */ +enum i915_mocs_table_index { + /* + * Not cached anywhere, coherency between CPU and GPU accesses is + * guaranteed. + */ + I915_MOCS_UNCACHED, + /* + * Cacheability and coherency controlled by the kernel automatically + * based on the DRM_I915_GEM_SET_CACHING IOCTL setting and the current + * usage of the surface (used for display scanout or not). + */ + I915_MOCS_PTE, + /* + * Cached in all GPU caches available on the platform. + * Coherency between CPU and GPU accesses to the surface is not + * guaranteed without extra synchronization. + */ + I915_MOCS_CACHED, +}; + +/* + * Different engines serve different roles, and there may be more than one + * engine serving each role. enum drm_i915_gem_engine_class provides a + * classification of the role of the engine, which may be used when requesting + * operations to be performed on a certain subset of engines, or for providing + * information about that group. + */ +enum drm_i915_gem_engine_class { + I915_ENGINE_CLASS_RENDER = 0, + I915_ENGINE_CLASS_COPY = 1, + I915_ENGINE_CLASS_VIDEO = 2, + I915_ENGINE_CLASS_VIDEO_ENHANCE = 3, + + /* should be kept compact */ + + I915_ENGINE_CLASS_INVALID = -1 +}; + +/** + * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915 + * + */ + +enum drm_i915_pmu_engine_sample { + I915_SAMPLE_BUSY = 0, + I915_SAMPLE_WAIT = 1, + I915_SAMPLE_SEMA = 2 +}; + +#define I915_PMU_SAMPLE_BITS (4) +#define I915_PMU_SAMPLE_MASK (0xf) +#define I915_PMU_SAMPLE_INSTANCE_BITS (8) +#define I915_PMU_CLASS_SHIFT \ + (I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS) + +#define __I915_PMU_ENGINE(class, instance, sample) \ + ((class) << I915_PMU_CLASS_SHIFT | \ + (instance) << I915_PMU_SAMPLE_BITS | \ + (sample)) + +#define I915_PMU_ENGINE_BUSY(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY) + +#define I915_PMU_ENGINE_WAIT(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT) + +#define I915_PMU_ENGINE_SEMA(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA) + +#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x)) + +#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0) +#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1) +#define I915_PMU_INTERRUPTS __I915_PMU_OTHER(2) +#define I915_PMU_RC6_RESIDENCY __I915_PMU_OTHER(3) + +#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY + +/* Each region is a minimum of 16k, and there are at most 255 of them. + */ +#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use + * of chars for next/prev indices */ +#define I915_LOG_MIN_TEX_REGION_SIZE 14 + +typedef struct _drm_i915_init { + enum { + I915_INIT_DMA = 0x01, + I915_CLEANUP_DMA = 0x02, + I915_RESUME_DMA = 0x03 + } func; + unsigned int mmio_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; + unsigned int chipset; +} drm_i915_init_t; + +typedef struct _drm_i915_sarea { + struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; + + int pipeA_x; + int pipeA_y; + int pipeA_w; + int pipeA_h; + int pipeB_x; + int pipeB_y; + int pipeB_w; + int pipeB_h; + + /* fill out some space for old userspace triple buffer */ + drm_handle_t unused_handle; + __u32 unused1, unused2, unused3; + + /* buffer object handles for static buffers. May change + * over the lifetime of the client. + */ + __u32 front_bo_handle; + __u32 back_bo_handle; + __u32 unused_bo_handle; + __u32 depth_bo_handle; + +} drm_i915_sarea_t; + +/* due to userspace building against these headers we need some compat here */ +#define planeA_x pipeA_x +#define planeA_y pipeA_y +#define planeA_w pipeA_w +#define planeA_h pipeA_h +#define planeB_x pipeB_x +#define planeB_y pipeB_y +#define planeB_w pipeB_w +#define planeB_h pipeB_h + +/* Flags for perf_boxes + */ +#define I915_BOX_RING_EMPTY 0x1 +#define I915_BOX_FLIP 0x2 +#define I915_BOX_WAIT 0x4 +#define I915_BOX_TEXTURE_LOAD 0x8 +#define I915_BOX_LOST_CONTEXT 0x10 + +/* + * i915 specific ioctls. + * + * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie + * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset + * against DRM_COMMAND_BASE and should be between [0x0, 0x60). + */ +#define DRM_I915_INIT 0x00 +#define DRM_I915_FLUSH 0x01 +#define DRM_I915_FLIP 0x02 +#define DRM_I915_BATCHBUFFER 0x03 +#define DRM_I915_IRQ_EMIT 0x04 +#define DRM_I915_IRQ_WAIT 0x05 +#define DRM_I915_GETPARAM 0x06 +#define DRM_I915_SETPARAM 0x07 +#define DRM_I915_ALLOC 0x08 +#define DRM_I915_FREE 0x09 +#define DRM_I915_INIT_HEAP 0x0a +#define DRM_I915_CMDBUFFER 0x0b +#define DRM_I915_DESTROY_HEAP 0x0c +#define DRM_I915_SET_VBLANK_PIPE 0x0d +#define DRM_I915_GET_VBLANK_PIPE 0x0e +#define DRM_I915_VBLANK_SWAP 0x0f +#define DRM_I915_HWS_ADDR 0x11 +#define DRM_I915_GEM_INIT 0x13 +#define DRM_I915_GEM_EXECBUFFER 0x14 +#define DRM_I915_GEM_PIN 0x15 +#define DRM_I915_GEM_UNPIN 0x16 +#define DRM_I915_GEM_BUSY 0x17 +#define DRM_I915_GEM_THROTTLE 0x18 +#define DRM_I915_GEM_ENTERVT 0x19 +#define DRM_I915_GEM_LEAVEVT 0x1a +#define DRM_I915_GEM_CREATE 0x1b +#define DRM_I915_GEM_PREAD 0x1c +#define DRM_I915_GEM_PWRITE 0x1d +#define DRM_I915_GEM_MMAP 0x1e +#define DRM_I915_GEM_SET_DOMAIN 0x1f +#define DRM_I915_GEM_SW_FINISH 0x20 +#define DRM_I915_GEM_SET_TILING 0x21 +#define DRM_I915_GEM_GET_TILING 0x22 +#define DRM_I915_GEM_GET_APERTURE 0x23 +#define DRM_I915_GEM_MMAP_GTT 0x24 +#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25 +#define DRM_I915_GEM_MADVISE 0x26 +#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 +#define DRM_I915_OVERLAY_ATTRS 0x28 +#define DRM_I915_GEM_EXECBUFFER2 0x29 +#define DRM_I915_GEM_EXECBUFFER2_WR DRM_I915_GEM_EXECBUFFER2 +#define DRM_I915_GET_SPRITE_COLORKEY 0x2a +#define DRM_I915_SET_SPRITE_COLORKEY 0x2b +#define DRM_I915_GEM_WAIT 0x2c +#define DRM_I915_GEM_CONTEXT_CREATE 0x2d +#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e +#define DRM_I915_GEM_SET_CACHING 0x2f +#define DRM_I915_GEM_GET_CACHING 0x30 +#define DRM_I915_REG_READ 0x31 +#define DRM_I915_GET_RESET_STATS 0x32 +#define DRM_I915_GEM_USERPTR 0x33 +#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 +#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 +#define DRM_I915_PERF_OPEN 0x36 +#define DRM_I915_PERF_ADD_CONFIG 0x37 +#define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_QUERY 0x39 +/* Must be kept compact -- no holes */ + +#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) +#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) +#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP) +#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) +#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) +#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) +#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) +#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t) +#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t) +#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) +#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) +#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) +#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) +#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_HWS_ADDR DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) +#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2) +#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2) +#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) +#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) +#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) +#define DRM_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHING, struct drm_i915_gem_caching) +#define DRM_IOCTL_I915_GEM_GET_CACHING DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHING, struct drm_i915_gem_caching) +#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) +#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) +#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) +#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) +#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) +#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) +#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) +#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) +#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) +#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) +#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) +#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture) +#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id) +#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) +#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) +#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) +#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext) +#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) +#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read) +#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats) +#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr) +#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) +#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) +#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) + +/* Allow drivers to submit batchbuffers directly to hardware, relying + * on the security mechanisms provided by hardware. + */ +typedef struct drm_i915_batchbuffer { + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_batchbuffer_t; + +/* As above, but pass a pointer to userspace buffer which can be + * validated by the kernel prior to sending to hardware. + */ +typedef struct _drm_i915_cmdbuffer { + char *buf; /* pointer to userspace command buffer */ + int sz; /* nr bytes in buf */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_cmdbuffer_t; + +/* Userspace can request & wait on irq's: + */ +typedef struct drm_i915_irq_emit { + int *irq_seq; +} drm_i915_irq_emit_t; + +typedef struct drm_i915_irq_wait { + int irq_seq; +} drm_i915_irq_wait_t; + +/* + * Different modes of per-process Graphics Translation Table, + * see I915_PARAM_HAS_ALIASING_PPGTT + */ +#define I915_GEM_PPGTT_NONE 0 +#define I915_GEM_PPGTT_ALIASING 1 +#define I915_GEM_PPGTT_FULL 2 + +/* Ioctl to query kernel params: + */ +#define I915_PARAM_IRQ_ACTIVE 1 +#define I915_PARAM_ALLOW_BATCHBUFFER 2 +#define I915_PARAM_LAST_DISPATCH 3 +#define I915_PARAM_CHIPSET_ID 4 +#define I915_PARAM_HAS_GEM 5 +#define I915_PARAM_NUM_FENCES_AVAIL 6 +#define I915_PARAM_HAS_OVERLAY 7 +#define I915_PARAM_HAS_PAGEFLIPPING 8 +#define I915_PARAM_HAS_EXECBUF2 9 +#define I915_PARAM_HAS_BSD 10 +#define I915_PARAM_HAS_BLT 11 +#define I915_PARAM_HAS_RELAXED_FENCING 12 +#define I915_PARAM_HAS_COHERENT_RINGS 13 +#define I915_PARAM_HAS_EXEC_CONSTANTS 14 +#define I915_PARAM_HAS_RELAXED_DELTA 15 +#define I915_PARAM_HAS_GEN7_SOL_RESET 16 +#define I915_PARAM_HAS_LLC 17 +#define I915_PARAM_HAS_ALIASING_PPGTT 18 +#define I915_PARAM_HAS_WAIT_TIMEOUT 19 +#define I915_PARAM_HAS_SEMAPHORES 20 +#define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21 +#define I915_PARAM_HAS_VEBOX 22 +#define I915_PARAM_HAS_SECURE_BATCHES 23 +#define I915_PARAM_HAS_PINNED_BATCHES 24 +#define I915_PARAM_HAS_EXEC_NO_RELOC 25 +#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26 +#define I915_PARAM_HAS_WT 27 +#define I915_PARAM_CMD_PARSER_VERSION 28 +#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29 +#define I915_PARAM_MMAP_VERSION 30 +#define I915_PARAM_HAS_BSD2 31 +#define I915_PARAM_REVISION 32 +#define I915_PARAM_SUBSLICE_TOTAL 33 +#define I915_PARAM_EU_TOTAL 34 +#define I915_PARAM_HAS_GPU_RESET 35 +#define I915_PARAM_HAS_RESOURCE_STREAMER 36 +#define I915_PARAM_HAS_EXEC_SOFTPIN 37 +#define I915_PARAM_HAS_POOLED_EU 38 +#define I915_PARAM_MIN_EU_IN_POOL 39 +#define I915_PARAM_MMAP_GTT_VERSION 40 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution + * priorities and the driver will attempt to execute batches in priority order. + * The param returns a capability bitmask, nonzero implies that the scheduler + * is enabled, with different features present according to the mask. + * + * The initial priority for each batch is supplied by the context and is + * controlled via I915_CONTEXT_PARAM_PRIORITY. + */ +#define I915_PARAM_HAS_SCHEDULER 41 +#define I915_SCHEDULER_CAP_ENABLED (1ul << 0) +#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1) +#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2) +#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3) + +#define I915_PARAM_HUC_STATUS 42 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of + * synchronisation with implicit fencing on individual objects. + * See EXEC_OBJECT_ASYNC. + */ +#define I915_PARAM_HAS_EXEC_ASYNC 43 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support - + * both being able to pass in a sync_file fd to wait upon before executing, + * and being able to return a new sync_file fd that is signaled when the + * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT. + */ +#define I915_PARAM_HAS_EXEC_FENCE 44 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture + * user specified buffers for post-mortem debugging of GPU hangs. See + * EXEC_OBJECT_CAPTURE. + */ +#define I915_PARAM_HAS_EXEC_CAPTURE 45 + +#define I915_PARAM_SLICE_MASK 46 + +/* Assuming it's uniform for each slice, this queries the mask of subslices + * per-slice for this system. + */ +#define I915_PARAM_SUBSLICE_MASK 47 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer + * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST. + */ +#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of + * drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY. + */ +#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49 + +/* + * Query whether every context (both per-file default and user created) is + * isolated (insofar as HW supports). If this parameter is not true, then + * freshly created contexts may inherit values from an existing context, + * rather than default HW values. If true, it also ensures (insofar as HW + * supports) that all state set by this context will not leak to any other + * context. + * + * As not every engine across every gen support contexts, the returned + * value reports the support of context isolation for individual engines by + * returning a bitmask of each engine class set to true if that class supports + * isolation. + */ +#define I915_PARAM_HAS_CONTEXT_ISOLATION 50 + +/* Frequency of the command streamer timestamps given by the *_TIMESTAMP + * registers. This used to be fixed per platform but from CNL onwards, this + * might vary depending on the parts. + */ +#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51 + +/* + * Once upon a time we supposed that writes through the GGTT would be + * immediately in physical memory (once flushed out of the CPU path). However, + * on a few different processors and chipsets, this is not necessarily the case + * as the writes appear to be buffered internally. Thus a read of the backing + * storage (physical memory) via a different path (with different physical tags + * to the indirect write via the GGTT) will see stale values from before + * the GGTT write. Inside the kernel, we can for the most part keep track of + * the different read/write domains in use (e.g. set-domain), but the assumption + * of coherency is baked into the ABI, hence reporting its true state in this + * parameter. + * + * Reports true when writes via mmap_gtt are immediately visible following an + * lfence to flush the WCB. + * + * Reports false when writes via mmap_gtt are indeterminately delayed in an in + * internal buffer and are _not_ immediately visible to third parties accessing + * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC + * communications channel when reporting false is strongly disadvised. + */ +#define I915_PARAM_MMAP_GTT_COHERENT 52 + +/* Must be kept compact -- no holes and well documented */ + +typedef struct drm_i915_getparam { + __s32 param; + /* + * WARNING: Using pointers instead of fixed-size u64 means we need to write + * compat32 code. Don't repeat this mistake. + */ + int *value; +} drm_i915_getparam_t; + +/* Ioctl to set kernel params: + */ +#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 +#define I915_SETPARAM_ALLOW_BATCHBUFFER 3 +#define I915_SETPARAM_NUM_USED_FENCES 4 +/* Must be kept compact -- no holes */ + +typedef struct drm_i915_setparam { + int param; + int value; +} drm_i915_setparam_t; + +/* A memory manager for regions of shared memory: + */ +#define I915_MEM_REGION_AGP 1 + +typedef struct drm_i915_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drm_i915_mem_alloc_t; + +typedef struct drm_i915_mem_free { + int region; + int region_offset; +} drm_i915_mem_free_t; + +typedef struct drm_i915_mem_init_heap { + int region; + int size; + int start; +} drm_i915_mem_init_heap_t; + +/* Allow memory manager to be torn down and re-initialized (eg on + * rotate): + */ +typedef struct drm_i915_mem_destroy_heap { + int region; +} drm_i915_mem_destroy_heap_t; + +/* Allow X server to configure which pipes to monitor for vblank signals + */ +#define DRM_I915_VBLANK_PIPE_A 1 +#define DRM_I915_VBLANK_PIPE_B 2 + +typedef struct drm_i915_vblank_pipe { + int pipe; +} drm_i915_vblank_pipe_t; + +/* Schedule buffer swap at given vertical blank: + */ +typedef struct drm_i915_vblank_swap { + drm_drawable_t drawable; + enum drm_vblank_seq_type seqtype; + unsigned int sequence; +} drm_i915_vblank_swap_t; + +typedef struct drm_i915_hws_addr { + __u64 addr; +} drm_i915_hws_addr_t; + +struct drm_i915_gem_init { + /** + * Beginning offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_start; + /** + * Ending offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_end; +}; + +struct drm_i915_gem_create { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + __u64 size; + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** + * Pointer to write the data into. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** + * Pointer to read the data from. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_mmap { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** Offset in the object to map. */ + __u64 offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + __u64 size; + /** + * Returned pointer the data was mapped at. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 addr_ptr; + + /** + * Flags for extended behaviour. + * + * Added in version 2. + */ + __u64 flags; +#define I915_MMAP_WC 0x1 +}; + +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_i915_gem_set_domain { + /** Handle for the object */ + __u32 handle; + + /** New read domains */ + __u32 read_domains; + + /** New write domain */ + __u32 write_domain; +}; + +struct drm_i915_gem_sw_finish { + /** Handle for the object */ + __u32 handle; +}; + +struct drm_i915_gem_relocation_entry { + /** + * Handle of the buffer being pointed to by this relocation entry. + * + * It's appealing to make this be an index into the mm_validate_entry + * list to refer to the buffer, but this allows the driver to create + * a relocation list for state buffers and not re-write it per + * exec using the buffer. + */ + __u32 target_handle; + + /** + * Value to be added to the offset of the target buffer to make up + * the relocation entry. + */ + __u32 delta; + + /** Offset in the buffer the relocation entry will be written into */ + __u64 offset; + + /** + * Offset value of the target buffer that the relocation entry was last + * written as. + * + * If the buffer has the same offset as last time, we can skip syncing + * and writing the relocation. This value is written back out by + * the execbuffer ioctl when the relocation is written. + */ + __u64 presumed_offset; + + /** + * Target memory domains read by this operation. + */ + __u32 read_domains; + + /** + * Target memory domains written by this operation. + * + * Note that only one domain may be written by the whole + * execbuffer operation, so that where there are conflicts, + * the application will get -EINVAL back. + */ + __u32 write_domain; +}; + +/** @{ + * Intel memory domains + * + * Most of these just align with the various caches in + * the system and are used to flush and invalidate as + * objects end up cached in different domains. + */ +/** CPU cache */ +#define I915_GEM_DOMAIN_CPU 0x00000001 +/** Render cache, used by 2D and 3D drawing */ +#define I915_GEM_DOMAIN_RENDER 0x00000002 +/** Sampler cache, used by texture engine */ +#define I915_GEM_DOMAIN_SAMPLER 0x00000004 +/** Command queue, used to load batch buffers */ +#define I915_GEM_DOMAIN_COMMAND 0x00000008 +/** Instruction cache, used by shader programs */ +#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 +/** Vertex address cache */ +#define I915_GEM_DOMAIN_VERTEX 0x00000020 +/** GTT domain - aperture and scanout */ +#define I915_GEM_DOMAIN_GTT 0x00000040 +/** WC domain - uncached access */ +#define I915_GEM_DOMAIN_WC 0x00000080 +/** @} */ + +struct drm_i915_gem_exec_object { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * Returned value of the updated offset of the object, for future + * presumed_offset writes. + */ + __u64 offset; +}; + +struct drm_i915_gem_execbuffer { + /** + * List of buffers to be validated with their relocations to be + * performend on them. + * + * This is a pointer to an array of struct drm_i915_gem_validate_entry. + * + * These buffers must be listed in an order such that all relocations + * a buffer is performing refer to buffers that have already appeared + * in the validate list. + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** This is a struct drm_clip_rect *cliprects */ + __u64 cliprects_ptr; +}; + +struct drm_i915_gem_exec_object2 { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * When the EXEC_OBJECT_PINNED flag is specified this is populated by + * the user with the GTT offset at which this object will be pinned. + * When the I915_EXEC_NO_RELOC flag is specified this must contain the + * presumed_offset of the object. + * During execbuffer2 the kernel populates it with the value of the + * current GTT offset of the object, for future presumed_offset writes. + */ + __u64 offset; + +#define EXEC_OBJECT_NEEDS_FENCE (1<<0) +#define EXEC_OBJECT_NEEDS_GTT (1<<1) +#define EXEC_OBJECT_WRITE (1<<2) +#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3) +#define EXEC_OBJECT_PINNED (1<<4) +#define EXEC_OBJECT_PAD_TO_SIZE (1<<5) +/* The kernel implicitly tracks GPU activity on all GEM objects, and + * synchronises operations with outstanding rendering. This includes + * rendering on other devices if exported via dma-buf. However, sometimes + * this tracking is too coarse and the user knows better. For example, + * if the object is split into non-overlapping ranges shared between different + * clients or engines (i.e. suballocating objects), the implicit tracking + * by kernel assumes that each operation affects the whole object rather + * than an individual range, causing needless synchronisation between clients. + * The kernel will also forgo any CPU cache flushes prior to rendering from + * the object as the client is expected to be also handling such domain + * tracking. + * + * The kernel maintains the implicit tracking in order to manage resources + * used by the GPU - this flag only disables the synchronisation prior to + * rendering with this object in this execbuf. + * + * Opting out of implicit synhronisation requires the user to do its own + * explicit tracking to avoid rendering corruption. See, for example, + * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously. + */ +#define EXEC_OBJECT_ASYNC (1<<6) +/* Request that the contents of this execobject be copied into the error + * state upon a GPU hang involving this batch for post-mortem debugging. + * These buffers are recorded in no particular order as "user" in + * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see + * if the kernel supports this flag. + */ +#define EXEC_OBJECT_CAPTURE (1<<7) +/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */ +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1) + __u64 flags; + + union { + __u64 rsvd1; + __u64 pad_to_size; + }; + __u64 rsvd2; +}; + +struct drm_i915_gem_exec_fence { + /** + * User's handle for a drm_syncobj to wait on or signal. + */ + __u32 handle; + +#define I915_EXEC_FENCE_WAIT (1<<0) +#define I915_EXEC_FENCE_SIGNAL (1<<1) +#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1)) + __u32 flags; +}; + +struct drm_i915_gem_execbuffer2 { + /** + * List of gem_exec_object2 structs + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** + * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY + * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a + * struct drm_i915_gem_exec_fence *fences. + */ + __u64 cliprects_ptr; +#define I915_EXEC_RING_MASK (0x3f) +#define I915_EXEC_DEFAULT (0<<0) +#define I915_EXEC_RENDER (1<<0) +#define I915_EXEC_BSD (2<<0) +#define I915_EXEC_BLT (3<<0) +#define I915_EXEC_VEBOX (4<<0) + +/* Used for switching the constants addressing mode on gen4+ RENDER ring. + * Gen6+ only supports relative addressing to dynamic state (default) and + * absolute addressing. + * + * These flags are ignored for the BSD and BLT rings. + */ +#define I915_EXEC_CONSTANTS_MASK (3<<6) +#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */ +#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) +#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ + __u64 flags; + __u64 rsvd1; /* now used for context info */ + __u64 rsvd2; +}; + +/** Resets the SO write offset registers for transform feedback on gen7. */ +#define I915_EXEC_GEN7_SOL_RESET (1<<8) + +/** Request a privileged ("secure") batch buffer. Note only available for + * DRM_ROOT_ONLY | DRM_MASTER processes. + */ +#define I915_EXEC_SECURE (1<<9) + +/** Inform the kernel that the batch is and will always be pinned. This + * negates the requirement for a workaround to be performed to avoid + * an incoherent CS (such as can be found on 830/845). If this flag is + * not passed, the kernel will endeavour to make sure the batch is + * coherent with the CS before execution. If this flag is passed, + * userspace assumes the responsibility for ensuring the same. + */ +#define I915_EXEC_IS_PINNED (1<<10) + +/** Provide a hint to the kernel that the command stream and auxiliary + * state buffers already holds the correct presumed addresses and so the + * relocation process may be skipped if no buffers need to be moved in + * preparation for the execbuffer. + */ +#define I915_EXEC_NO_RELOC (1<<11) + +/** Use the reloc.handle as an index into the exec object array rather + * than as the per-file handle. + */ +#define I915_EXEC_HANDLE_LUT (1<<12) + +/** Used for switching BSD rings on the platforms with two BSD rings */ +#define I915_EXEC_BSD_SHIFT (13) +#define I915_EXEC_BSD_MASK (3 << I915_EXEC_BSD_SHIFT) +/* default ping-pong mode */ +#define I915_EXEC_BSD_DEFAULT (0 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING1 (1 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING2 (2 << I915_EXEC_BSD_SHIFT) + +/** Tell the kernel that the batchbuffer is processed by + * the resource streamer. + */ +#define I915_EXEC_RESOURCE_STREAMER (1<<15) + +/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent + * a sync_file fd to wait upon (in a nonblocking manner) prior to executing + * the batch. + * + * Returns -EINVAL if the sync_file fd cannot be found. + */ +#define I915_EXEC_FENCE_IN (1<<16) + +/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd + * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given + * to the caller, and it should be close() after use. (The fd is a regular + * file descriptor and will be cleaned up on process termination. It holds + * a reference to the request, but nothing else.) + * + * The sync_file fd can be combined with other sync_file and passed either + * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip + * will only occur after this request completes), or to other devices. + * + * Using I915_EXEC_FENCE_OUT requires use of + * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written + * back to userspace. Failure to do so will cause the out-fence to always + * be reported as zero, and the real fence fd to be leaked. + */ +#define I915_EXEC_FENCE_OUT (1<<17) + +/* + * Traditionally the execbuf ioctl has only considered the final element in + * the execobject[] to be the executable batch. Often though, the client + * will known the batch object prior to construction and being able to place + * it into the execobject[] array first can simplify the relocation tracking. + * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the + * execobject[] as the * batch instead (the default is to use the last + * element). + */ +#define I915_EXEC_BATCH_FIRST (1<<18) + +/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr + * define an array of i915_gem_exec_fence structures which specify a set of + * dma fences to wait upon or signal. + */ +#define I915_EXEC_FENCE_ARRAY (1<<19) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1)) + +#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) +#define i915_execbuffer2_set_context_id(eb2, context) \ + (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK +#define i915_execbuffer2_get_context_id(eb2) \ + ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) + +struct drm_i915_gem_pin { + /** Handle of the buffer to be pinned. */ + __u32 handle; + __u32 pad; + + /** alignment required within the aperture */ + __u64 alignment; + + /** Returned GTT offset of the buffer. */ + __u64 offset; +}; + +struct drm_i915_gem_unpin { + /** Handle of the buffer to be unpinned. */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_busy { + /** Handle of the buffer to check for busy */ + __u32 handle; + + /** Return busy status + * + * A return of 0 implies that the object is idle (after + * having flushed any pending activity), and a non-zero return that + * the object is still in-flight on the GPU. (The GPU has not yet + * signaled completion for all pending requests that reference the + * object.) An object is guaranteed to become idle eventually (so + * long as no new GPU commands are executed upon it). Due to the + * asynchronous nature of the hardware, an object reported + * as busy may become idle before the ioctl is completed. + * + * Furthermore, if the object is busy, which engine is busy is only + * provided as a guide and only indirectly by reporting its class + * (there may be more than one engine in each class). There are race + * conditions which prevent the report of which engines are busy from + * being always accurate. However, the converse is not true. If the + * object is idle, the result of the ioctl, that all engines are idle, + * is accurate. + * + * The returned dword is split into two fields to indicate both + * the engine classess on which the object is being read, and the + * engine class on which it is currently being written (if any). + * + * The low word (bits 0:15) indicate if the object is being written + * to by any engine (there can only be one, as the GEM implicit + * synchronisation rules force writes to be serialised). Only the + * engine class (offset by 1, I915_ENGINE_CLASS_RENDER is reported as + * 1 not 0 etc) for the last write is reported. + * + * The high word (bits 16:31) are a bitmask of which engines classes + * are currently reading from the object. Multiple engines may be + * reading from the object simultaneously. + * + * The value of each engine class is the same as specified in the + * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e. + * I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc. + * reported as active itself. Some hardware may have parallel + * execution engines, e.g. multiple media engines, which are + * mapped to the same class identifier and so are not separately + * reported for busyness. + * + * Caveat emptor: + * Only the boolean result of this query is reliable; that is whether + * the object is idle or busy. The report of which engines are busy + * should be only used as a heuristic. + */ + __u32 busy; +}; + +/** + * I915_CACHING_NONE + * + * GPU access is not coherent with cpu caches. Default for machines without an + * LLC. + */ +#define I915_CACHING_NONE 0 +/** + * I915_CACHING_CACHED + * + * GPU access is coherent with cpu caches and furthermore the data is cached in + * last-level caches shared between cpu cores and the gpu GT. Default on + * machines with HAS_LLC. + */ +#define I915_CACHING_CACHED 1 +/** + * I915_CACHING_DISPLAY + * + * Special GPU caching mode which is coherent with the scanout engines. + * Transparently falls back to I915_CACHING_NONE on platforms where no special + * cache mode (like write-through or gfdt flushing) is available. The kernel + * automatically sets this mode when using a buffer as a scanout target. + * Userspace can manually set this mode to avoid a costly stall and clflush in + * the hotpath of drawing the first frame. + */ +#define I915_CACHING_DISPLAY 2 + +struct drm_i915_gem_caching { + /** + * Handle of the buffer to set/get the caching level of. */ + __u32 handle; + + /** + * Caching level to apply or return value + * + * bits0-15 are for generic caching control (i.e. the above defined + * values). bits16-31 are reserved for platform-specific variations + * (e.g. l3$ caching on gen7). */ + __u32 caching; +}; + +#define I915_TILING_NONE 0 +#define I915_TILING_X 1 +#define I915_TILING_Y 2 +#define I915_TILING_LAST I915_TILING_Y + +#define I915_BIT_6_SWIZZLE_NONE 0 +#define I915_BIT_6_SWIZZLE_9 1 +#define I915_BIT_6_SWIZZLE_9_10 2 +#define I915_BIT_6_SWIZZLE_9_11 3 +#define I915_BIT_6_SWIZZLE_9_10_11 4 +/* Not seen by userland */ +#define I915_BIT_6_SWIZZLE_UNKNOWN 5 +/* Seen by userland. */ +#define I915_BIT_6_SWIZZLE_9_17 6 +#define I915_BIT_6_SWIZZLE_9_10_17 7 + +struct drm_i915_gem_set_tiling { + /** Handle of the buffer to have its tiling state updated */ + __u32 handle; + + /** + * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + * + * This value is to be set on request, and will be updated by the + * kernel on successful return with the actual chosen tiling layout. + * + * The tiling mode may be demoted to I915_TILING_NONE when the system + * has bit 6 swizzling that can't be managed correctly by GEM. + * + * Buffer contents become undefined when changing tiling_mode. + */ + __u32 tiling_mode; + + /** + * Stride in bytes for the object when in I915_TILING_X or + * I915_TILING_Y. + */ + __u32 stride; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; +}; + +struct drm_i915_gem_get_tiling { + /** Handle of the buffer to get tiling state for. */ + __u32 handle; + + /** + * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + */ + __u32 tiling_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping whilst bound. + */ + __u32 phys_swizzle_mode; +}; + +struct drm_i915_gem_get_aperture { + /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ + __u64 aper_size; + + /** + * Available space in the aperture used by i915_gem_execbuffer, in + * bytes + */ + __u64 aper_available_size; +}; + +struct drm_i915_get_pipe_from_crtc_id { + /** ID of CRTC being requested **/ + __u32 crtc_id; + + /** pipe of requested CRTC **/ + __u32 pipe; +}; + +#define I915_MADV_WILLNEED 0 +#define I915_MADV_DONTNEED 1 +#define __I915_MADV_PURGED 2 /* internal state */ + +struct drm_i915_gem_madvise { + /** Handle of the buffer to change the backing store advice */ + __u32 handle; + + /* Advice: either the buffer will be needed again in the near future, + * or wont be and could be discarded under memory pressure. + */ + __u32 madv; + + /** Whether the backing store still exists. */ + __u32 retained; +}; + +/* flags */ +#define I915_OVERLAY_TYPE_MASK 0xff +#define I915_OVERLAY_YUV_PLANAR 0x01 +#define I915_OVERLAY_YUV_PACKED 0x02 +#define I915_OVERLAY_RGB 0x03 + +#define I915_OVERLAY_DEPTH_MASK 0xff00 +#define I915_OVERLAY_RGB24 0x1000 +#define I915_OVERLAY_RGB16 0x2000 +#define I915_OVERLAY_RGB15 0x3000 +#define I915_OVERLAY_YUV422 0x0100 +#define I915_OVERLAY_YUV411 0x0200 +#define I915_OVERLAY_YUV420 0x0300 +#define I915_OVERLAY_YUV410 0x0400 + +#define I915_OVERLAY_SWAP_MASK 0xff0000 +#define I915_OVERLAY_NO_SWAP 0x000000 +#define I915_OVERLAY_UV_SWAP 0x010000 +#define I915_OVERLAY_Y_SWAP 0x020000 +#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000 + +#define I915_OVERLAY_FLAGS_MASK 0xff000000 +#define I915_OVERLAY_ENABLE 0x01000000 + +struct drm_intel_overlay_put_image { + /* various flags and src format description */ + __u32 flags; + /* source picture description */ + __u32 bo_handle; + /* stride values and offsets are in bytes, buffer relative */ + __u16 stride_Y; /* stride for packed formats */ + __u16 stride_UV; + __u32 offset_Y; /* offset for packet formats */ + __u32 offset_U; + __u32 offset_V; + /* in pixels */ + __u16 src_width; + __u16 src_height; + /* to compensate the scaling factors for partially covered surfaces */ + __u16 src_scan_width; + __u16 src_scan_height; + /* output crtc description */ + __u32 crtc_id; + __u16 dst_x; + __u16 dst_y; + __u16 dst_width; + __u16 dst_height; +}; + +/* flags */ +#define I915_OVERLAY_UPDATE_ATTRS (1<<0) +#define I915_OVERLAY_UPDATE_GAMMA (1<<1) +#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2) +struct drm_intel_overlay_attrs { + __u32 flags; + __u32 color_key; + __s32 brightness; + __u32 contrast; + __u32 saturation; + __u32 gamma0; + __u32 gamma1; + __u32 gamma2; + __u32 gamma3; + __u32 gamma4; + __u32 gamma5; +}; + +/* + * Intel sprite handling + * + * Color keying works with a min/mask/max tuple. Both source and destination + * color keying is allowed. + * + * Source keying: + * Sprite pixels within the min & max values, masked against the color channels + * specified in the mask field, will be transparent. All other pixels will + * be displayed on top of the primary plane. For RGB surfaces, only the min + * and mask fields will be used; ranged compares are not allowed. + * + * Destination keying: + * Primary plane pixels that match the min value, masked against the color + * channels specified in the mask field, will be replaced by corresponding + * pixels from the sprite plane. + * + * Note that source & destination keying are exclusive; only one can be + * active on a given plane. + */ + +#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set + * flags==0 to disable colorkeying. + */ +#define I915_SET_COLORKEY_DESTINATION (1<<1) +#define I915_SET_COLORKEY_SOURCE (1<<2) +struct drm_intel_sprite_colorkey { + __u32 plane_id; + __u32 min_value; + __u32 channel_mask; + __u32 max_value; + __u32 flags; +}; + +struct drm_i915_gem_wait { + /** Handle of BO we shall wait on */ + __u32 bo_handle; + __u32 flags; + /** Number of nanoseconds to wait, Returns time remaining. */ + __s64 timeout_ns; +}; + +struct drm_i915_gem_context_create { + __u32 ctx_id; /* output: id of new context*/ + __u32 pad; +}; + +struct drm_i915_gem_context_create_ext { + __u32 ctx_id; /* output: id of new context*/ + __u32 flags; +#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0) +#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \ + (-(I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS << 1)) + __u64 extensions; +}; + +struct drm_i915_gem_context_param { + __u32 ctx_id; + __u32 size; + __u64 param; +#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1 +#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2 +#define I915_CONTEXT_PARAM_GTT_SIZE 0x3 +#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4 +#define I915_CONTEXT_PARAM_BANNABLE 0x5 +#define I915_CONTEXT_PARAM_PRIORITY 0x6 +#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */ +#define I915_CONTEXT_DEFAULT_PRIORITY 0 +#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */ + /* + * When using the following param, value should be a pointer to + * drm_i915_gem_context_param_sseu. + */ +#define I915_CONTEXT_PARAM_SSEU 0x7 + +/* + * Not all clients may want to attempt automatic recover of a context after + * a hang (for example, some clients may only submit very small incremental + * batches relying on known logical state of previous batches which will never + * recover correctly and each attempt will hang), and so would prefer that + * the context is forever banned instead. + * + * If set to false (0), after a reset, subsequent (and in flight) rendering + * from this context is discarded, and the client will need to create a new + * context to use instead. + * + * If set to true (1), the kernel will automatically attempt to recover the + * context by skipping the hanging batch and executing the next batch starting + * from the default context state (discarding the incomplete logical context + * state lost due to the reset). + * + * On creation, all new contexts are marked as recoverable. + */ +#define I915_CONTEXT_PARAM_RECOVERABLE 0x8 +/* Must be kept compact -- no holes and well documented */ + + __u64 value; +}; + +/** + * Context SSEU programming + * + * It may be necessary for either functional or performance reason to configure + * a context to run with a reduced number of SSEU (where SSEU stands for Slice/ + * Sub-slice/EU). + * + * This is done by configuring SSEU configuration using the below + * @struct drm_i915_gem_context_param_sseu for every supported engine which + * userspace intends to use. + * + * Not all GPUs or engines support this functionality in which case an error + * code -ENODEV will be returned. + * + * Also, flexibility of possible SSEU configuration permutations varies between + * GPU generations and software imposed limitations. Requesting such a + * combination will return an error code of -EINVAL. + * + * NOTE: When perf/OA is active the context's SSEU configuration is ignored in + * favour of a single global setting. + */ +struct drm_i915_gem_context_param_sseu { + /* + * Engine class & instance to be configured or queried. + */ + __u16 engine_class; + __u16 engine_instance; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Mask of slices to enable for the context. Valid values are a subset + * of the bitmask value returned for I915_PARAM_SLICE_MASK. + */ + __u64 slice_mask; + + /* + * Mask of subslices to enable for the context. Valid values are a + * subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK. + */ + __u64 subslice_mask; + + /* + * Minimum/Maximum number of EUs to enable per subslice for the + * context. min_eus_per_subslice must be inferior or equal to + * max_eus_per_subslice. + */ + __u16 min_eus_per_subslice; + __u16 max_eus_per_subslice; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 rsvd; +}; + +struct drm_i915_gem_context_create_ext_setparam { +#define I915_CONTEXT_CREATE_EXT_SETPARAM 0 + struct i915_user_extension base; + struct drm_i915_gem_context_param param; +}; + +struct drm_i915_gem_context_destroy { + __u32 ctx_id; + __u32 pad; +}; + +/* + * DRM_I915_GEM_VM_CREATE - + * + * Create a new virtual memory address space (ppGTT) for use within a context + * on the same file. Extensions can be provided to configure exactly how the + * address space is setup upon creation. + * + * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is + * returned in the outparam @id. + * + * No flags are defined, with all bits reserved and must be zero. + * + * An extension chain maybe provided, starting with @extensions, and terminated + * by the @next_extension being 0. Currently, no extensions are defined. + * + * DRM_I915_GEM_VM_DESTROY - + * + * Destroys a previously created VM id, specified in @id. + * + * No extensions or flags are allowed currently, and so must be zero. + */ +struct drm_i915_gem_vm_control { + __u64 extensions; + __u32 flags; + __u32 vm_id; +}; + +struct drm_i915_reg_read { + /* + * Register offset. + * For 64bit wide registers where the upper 32bits don't immediately + * follow the lower 32bits, the offset of the lower 32bits must + * be specified + */ + __u64 offset; +#define I915_REG_READ_8B_WA (1ul << 0) + + __u64 val; /* Return value */ +}; + +/* Known registers: + * + * Render engine timestamp - 0x2358 + 64bit - gen7+ + * - Note this register returns an invalid value if using the default + * single instruction 8byte read, in order to workaround that pass + * flag I915_REG_READ_8B_WA in offset field. + * + */ + +struct drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + + /* All resets since boot/module reload, for all contexts */ + __u32 reset_count; + + /* Number of batches lost when active in GPU, for this context */ + __u32 batch_active; + + /* Number of batches lost pending for execution, for this context */ + __u32 batch_pending; + + __u32 pad; +}; + +struct drm_i915_gem_userptr { + __u64 user_ptr; + __u64 user_size; + __u32 flags; +#define I915_USERPTR_READ_ONLY 0x1 +#define I915_USERPTR_UNSYNCHRONIZED 0x80000000 + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; +}; + +enum drm_i915_oa_format { + I915_OA_FORMAT_A13 = 1, /* HSW only */ + I915_OA_FORMAT_A29, /* HSW only */ + I915_OA_FORMAT_A13_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8, /* HSW only */ + I915_OA_FORMAT_A45_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8_A16, /* HSW only */ + I915_OA_FORMAT_C4_B8, /* HSW+ */ + + /* Gen8+ */ + I915_OA_FORMAT_A12, + I915_OA_FORMAT_A12_B8_C8, + I915_OA_FORMAT_A32u40_A4u32_B8_C8, + + I915_OA_FORMAT_MAX /* non-ABI */ +}; + +enum drm_i915_perf_property_id { + /** + * Open the stream for a specific context handle (as used with + * execbuffer2). A stream opened for a specific context this way + * won't typically require root privileges. + */ + DRM_I915_PERF_PROP_CTX_HANDLE = 1, + + /** + * A value of 1 requests the inclusion of raw OA unit reports as + * part of stream samples. + */ + DRM_I915_PERF_PROP_SAMPLE_OA, + + /** + * The value specifies which set of OA unit metrics should be + * be configured, defining the contents of any OA unit reports. + */ + DRM_I915_PERF_PROP_OA_METRICS_SET, + + /** + * The value specifies the size and layout of OA unit reports. + */ + DRM_I915_PERF_PROP_OA_FORMAT, + + /** + * Specifying this property implicitly requests periodic OA unit + * sampling and (at least on Haswell) the sampling frequency is derived + * from this exponent as follows: + * + * 80ns * 2^(period_exponent + 1) + */ + DRM_I915_PERF_PROP_OA_EXPONENT, + + DRM_I915_PERF_PROP_MAX /* non-ABI */ +}; + +struct drm_i915_perf_open_param { + __u32 flags; +#define I915_PERF_FLAG_FD_CLOEXEC (1<<0) +#define I915_PERF_FLAG_FD_NONBLOCK (1<<1) +#define I915_PERF_FLAG_DISABLED (1<<2) + + /** The number of u64 (id, value) pairs */ + __u32 num_properties; + + /** + * Pointer to array of u64 (id, value) pairs configuring the stream + * to open. + */ + __u64 properties_ptr; +}; + +/** + * Enable data capture for a stream that was either opened in a disabled state + * via I915_PERF_FLAG_DISABLED or was later disabled via + * I915_PERF_IOCTL_DISABLE. + * + * It is intended to be cheaper to disable and enable a stream than it may be + * to close and re-open a stream with the same configuration. + * + * It's undefined whether any pending data for the stream will be lost. + */ +#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0) + +/** + * Disable data capture for a stream. + * + * It is an error to try and read a stream that is disabled. + */ +#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1) + +/** + * Common to all i915 perf records + */ +struct drm_i915_perf_record_header { + __u32 type; + __u16 pad; + __u16 size; +}; + +enum drm_i915_perf_record_type { + + /** + * Samples are the work horse record type whose contents are extensible + * and defined when opening an i915 perf stream based on the given + * properties. + * + * Boolean properties following the naming convention + * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in + * every sample. + * + * The order of these sample properties given by userspace has no + * affect on the ordering of data within a sample. The order is + * documented here. + * + * struct { + * struct drm_i915_perf_record_header header; + * + * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA + * }; + */ + DRM_I915_PERF_RECORD_SAMPLE = 1, + + /* + * Indicates that one or more OA reports were not written by the + * hardware. This can happen for example if an MI_REPORT_PERF_COUNT + * command collides with periodic sampling - which would be more likely + * at higher sampling frequencies. + */ + DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2, + + /** + * An error occurred that resulted in all pending OA reports being lost. + */ + DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3, + + DRM_I915_PERF_RECORD_MAX /* non-ABI */ +}; + +/** + * Structure to upload perf dynamic configuration into the kernel. + */ +struct drm_i915_perf_oa_config { + /** String formatted like "%08x-%04x-%04x-%04x-%012x" */ + char uuid[36]; + + __u32 n_mux_regs; + __u32 n_boolean_regs; + __u32 n_flex_regs; + + /* + * These fields are pointers to tuples of u32 values (register address, + * value). For example the expected length of the buffer pointed by + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). + */ + __u64 mux_regs_ptr; + __u64 boolean_regs_ptr; + __u64 flex_regs_ptr; +}; + +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_TOPOLOGY_INFO 1 +/* Must be kept compact -- no holes and well documented */ + + /* + * When set to zero by userspace, this is filled with the size of the + * data to be written at the data_ptr pointer. The kernel sets this + * value to a negative value to signal an error on a particular query + * item. + */ + __s32 length; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Data will be written at the location pointed by data_ptr when the + * value of length matches the length of the data to be written by the + * kernel. + */ + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * This points to an array of num_items drm_i915_query_item structures. + */ + __u64 items_ptr; +}; + +/* + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : + * + * data: contains the 3 pieces of information : + * + * - the slice mask with one bit per slice telling whether a slice is + * available. The availability of slice X can be queried with the following + * formula : + * + * (data[X / 8] >> (X % 8)) & 1 + * + * - the subslice mask for each slice with one bit per subslice telling + * whether a subslice is available. The availability of subslice Y in slice + * X can be queried with the following formula : + * + * (data[subslice_offset + + * X * subslice_stride + + * Y / 8] >> (Y % 8)) & 1 + * + * - the EU mask for each subslice in each slice with one bit per EU telling + * whether an EU is available. The availability of EU Z in subslice Y in + * slice X can be queried with the following formula : + * + * (data[eu_offset + + * (X * max_subslices + Y) * eu_stride + + * Z / 8] >> (Z % 8)) & 1 + */ +struct drm_i915_query_topology_info { + /* + * Unused for now. Must be cleared to zero. + */ + __u16 flags; + + __u16 max_slices; + __u16 max_subslices; + __u16 max_eus_per_subslice; + + /* + * Offset in data[] at which the subslice masks are stored. + */ + __u16 subslice_offset; + + /* + * Stride at which each of the subslice masks for each slice are + * stored. + */ + __u16 subslice_stride; + + /* + * Offset in data[] at which the EU masks are stored. + */ + __u16 eu_offset; + + /* + * Stride at which each of the EU masks for each subslice are stored. + */ + __u16 eu_stride; + + __u8 data[]; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _I915_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mach64_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mach64_drm.h new file mode 100644 index 0000000..1f5fd84 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mach64_drm.h @@ -0,0 +1,256 @@ +/* mach64_drm.h -- Public header for the mach64 driver -*- linux-c -*- + * Created: Thu Nov 30 20:04:32 2000 by gareth@valinux.com + */ +/* + * Copyright 2000 Gareth Hughes + * Copyright 2002 Frank C. Earl + * Copyright 2002-2003 Leif Delgass + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Frank C. Earl + * Leif Delgass + */ + +#ifndef __MACH64_DRM_H__ +#define __MACH64_DRM_H__ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mach64_sarea.h) + */ +#ifndef __MACH64_SAREA_DEFINES__ +#define __MACH64_SAREA_DEFINES__ + +/* What needs to be changed for the current vertex buffer? + * GH: We're going to be pedantic about this. We want the card to do as + * little as possible, so let's avoid having it fetch a whole bunch of + * register values that don't change all that often, if at all. + */ +#define MACH64_UPLOAD_DST_OFF_PITCH 0x0001 +#define MACH64_UPLOAD_Z_OFF_PITCH 0x0002 +#define MACH64_UPLOAD_Z_ALPHA_CNTL 0x0004 +#define MACH64_UPLOAD_SCALE_3D_CNTL 0x0008 +#define MACH64_UPLOAD_DP_FOG_CLR 0x0010 +#define MACH64_UPLOAD_DP_WRITE_MASK 0x0020 +#define MACH64_UPLOAD_DP_PIX_WIDTH 0x0040 +#define MACH64_UPLOAD_SETUP_CNTL 0x0080 +#define MACH64_UPLOAD_MISC 0x0100 +#define MACH64_UPLOAD_TEXTURE 0x0200 +#define MACH64_UPLOAD_TEX0IMAGE 0x0400 +#define MACH64_UPLOAD_TEX1IMAGE 0x0800 +#define MACH64_UPLOAD_CLIPRECTS 0x1000 /* handled client-side */ +#define MACH64_UPLOAD_CONTEXT 0x00ff +#define MACH64_UPLOAD_ALL 0x1fff + +/* DMA buffer size + */ +#define MACH64_BUFFER_SIZE 16384 + +/* Max number of swaps allowed on the ring + * before the client must wait + */ +#define MACH64_MAX_QUEUED_FRAMES 3U + +/* Byte offsets for host blit buffer data + */ +#define MACH64_HOSTDATA_BLIT_OFFSET 104 + +/* Keep these small for testing. + */ +#define MACH64_NR_SAREA_CLIPRECTS 8 + +#define MACH64_CARD_HEAP 0 +#define MACH64_AGP_HEAP 1 +#define MACH64_NR_TEX_HEAPS 2 +#define MACH64_NR_TEX_REGIONS 64 +#define MACH64_LOG_TEX_GRANULARITY 16 + +#define MACH64_TEX_MAXLEVELS 1 + +#define MACH64_NR_CONTEXT_REGS 15 +#define MACH64_NR_TEXTURE_REGS 4 + +#endif /* __MACH64_SAREA_DEFINES__ */ + +typedef struct { + unsigned int dst_off_pitch; + + unsigned int z_off_pitch; + unsigned int z_cntl; + unsigned int alpha_tst_cntl; + + unsigned int scale_3d_cntl; + + unsigned int sc_left_right; + unsigned int sc_top_bottom; + + unsigned int dp_fog_clr; + unsigned int dp_write_mask; + unsigned int dp_pix_width; + unsigned int dp_mix; + unsigned int dp_src; + + unsigned int clr_cmp_cntl; + unsigned int gui_traj_cntl; + + unsigned int setup_cntl; + + unsigned int tex_size_pitch; + unsigned int tex_cntl; + unsigned int secondary_tex_off; + unsigned int tex_offset; +} drm_mach64_context_regs_t; + +typedef struct drm_mach64_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + drm_mach64_context_regs_t context_state; + unsigned int dirty; + unsigned int vertsize; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[MACH64_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int frames_queued; + + /* Texture memory LRU. + */ + struct drm_tex_region tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[MACH64_NR_TEX_HEAPS]; + int ctx_owner; +} drm_mach64_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mach64_common.h) + */ + +/* Mach64 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ + +#define DRM_MACH64_INIT 0x00 +#define DRM_MACH64_IDLE 0x01 +#define DRM_MACH64_RESET 0x02 +#define DRM_MACH64_SWAP 0x03 +#define DRM_MACH64_CLEAR 0x04 +#define DRM_MACH64_VERTEX 0x05 +#define DRM_MACH64_BLIT 0x06 +#define DRM_MACH64_FLUSH 0x07 +#define DRM_MACH64_GETPARAM 0x08 + +#define DRM_IOCTL_MACH64_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_INIT, drm_mach64_init_t) +#define DRM_IOCTL_MACH64_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_IDLE ) +#define DRM_IOCTL_MACH64_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_RESET ) +#define DRM_IOCTL_MACH64_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_SWAP ) +#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_CLEAR, drm_mach64_clear_t) +#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_VERTEX, drm_mach64_vertex_t) +#define DRM_IOCTL_MACH64_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_BLIT, drm_mach64_blit_t) +#define DRM_IOCTL_MACH64_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_FLUSH ) +#define DRM_IOCTL_MACH64_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_MACH64_GETPARAM, drm_mach64_getparam_t) + +/* Buffer flags for clears + */ +#define MACH64_FRONT 0x1 +#define MACH64_BACK 0x2 +#define MACH64_DEPTH 0x4 + +/* Primitive types for vertex buffers + */ +#define MACH64_PRIM_POINTS 0x00000000 +#define MACH64_PRIM_LINES 0x00000001 +#define MACH64_PRIM_LINE_LOOP 0x00000002 +#define MACH64_PRIM_LINE_STRIP 0x00000003 +#define MACH64_PRIM_TRIANGLES 0x00000004 +#define MACH64_PRIM_TRIANGLE_STRIP 0x00000005 +#define MACH64_PRIM_TRIANGLE_FAN 0x00000006 +#define MACH64_PRIM_QUADS 0x00000007 +#define MACH64_PRIM_QUAD_STRIP 0x00000008 +#define MACH64_PRIM_POLYGON 0x00000009 + +typedef enum _drm_mach64_dma_mode_t { + MACH64_MODE_DMA_ASYNC, + MACH64_MODE_DMA_SYNC, + MACH64_MODE_MMIO +} drm_mach64_dma_mode_t; + +typedef struct drm_mach64_init { + enum { + DRM_MACH64_INIT_DMA = 0x01, + DRM_MACH64_CLEANUP_DMA = 0x02 + } func; + + unsigned long sarea_priv_offset; + int is_pci; + drm_mach64_dma_mode_t dma_mode; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drm_mach64_init_t; + +typedef struct drm_mach64_clear { + unsigned int flags; + int x, y, w, h; + unsigned int clear_color; + unsigned int clear_depth; +} drm_mach64_clear_t; + +typedef struct drm_mach64_vertex { + int prim; + void *buf; /* Address of vertex buffer */ + unsigned long used; /* Number of bytes in buffer */ + int discard; /* Client finished with buffer? */ +} drm_mach64_vertex_t; + +typedef struct drm_mach64_blit { + void *buf; + int pitch; + int offset; + int format; + unsigned short x, y; + unsigned short width, height; +} drm_mach64_blit_t; + +typedef struct drm_mach64_getparam { + enum { + MACH64_PARAM_FRAMES_QUEUED = 0x01, + MACH64_PARAM_IRQ_NR = 0x02 + } param; + void *value; +} drm_mach64_getparam_t; + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mga_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mga_drm.h new file mode 100644 index 0000000..7930011 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mga_drm.h @@ -0,0 +1,427 @@ +/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- + * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jeff Hartmann + * Keith Whitwell + * + * Rewritten by: + * Gareth Hughes + */ + +#ifndef __MGA_DRM_H__ +#define __MGA_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mga_sarea.h) + */ + +#ifndef __MGA_SAREA_DEFINES__ +#define __MGA_SAREA_DEFINES__ + +/* WARP pipe flags + */ +#define MGA_F 0x1 /* fog */ +#define MGA_A 0x2 /* alpha */ +#define MGA_S 0x4 /* specular */ +#define MGA_T2 0x8 /* multitexture */ + +#define MGA_WARP_TGZ 0 +#define MGA_WARP_TGZF (MGA_F) +#define MGA_WARP_TGZA (MGA_A) +#define MGA_WARP_TGZAF (MGA_F|MGA_A) +#define MGA_WARP_TGZS (MGA_S) +#define MGA_WARP_TGZSF (MGA_S|MGA_F) +#define MGA_WARP_TGZSA (MGA_S|MGA_A) +#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) +#define MGA_WARP_T2GZ (MGA_T2) +#define MGA_WARP_T2GZF (MGA_T2|MGA_F) +#define MGA_WARP_T2GZA (MGA_T2|MGA_A) +#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) +#define MGA_WARP_T2GZS (MGA_T2|MGA_S) +#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) +#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) +#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) + +#define MGA_MAX_G200_PIPES 8 /* no multitex */ +#define MGA_MAX_G400_PIPES 16 +#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES +#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ + +#define MGA_CARD_TYPE_G200 1 +#define MGA_CARD_TYPE_G400 2 +#define MGA_CARD_TYPE_G450 3 /* not currently used */ +#define MGA_CARD_TYPE_G550 4 + +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define MGA_UPLOAD_CONTEXT 0x1 +#define MGA_UPLOAD_TEX0 0x2 +#define MGA_UPLOAD_TEX1 0x4 +#define MGA_UPLOAD_PIPE 0x8 +#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ +#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ +#define MGA_UPLOAD_2D 0x40 +#define MGA_WAIT_AGE 0x80 /* handled client-side */ +#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +#if 0 +#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock + quiescent */ +#endif + +/* 32 buffers of 64k each, total 2 meg. + */ +#define MGA_BUFFER_SIZE (1 << 16) +#define MGA_NUM_BUFFERS 128 + +/* Keep these small for testing. + */ +#define MGA_NR_SAREA_CLIPRECTS 8 + +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define MGA_CARD_HEAP 0 +#define MGA_AGP_HEAP 1 +#define MGA_NR_TEX_HEAPS 2 +#define MGA_NR_TEX_REGIONS 16 +#define MGA_LOG_MIN_TEX_REGION_SIZE 16 + +#define DRM_MGA_IDLE_RETRY 2048 + +#endif /* __MGA_SAREA_DEFINES__ */ + +/* Setup registers for 3D context + */ +typedef struct { + unsigned int dstorg; + unsigned int maccess; + unsigned int plnwt; + unsigned int dwgctl; + unsigned int alphactrl; + unsigned int fogcolor; + unsigned int wflag; + unsigned int tdualstage0; + unsigned int tdualstage1; + unsigned int fcol; + unsigned int stencil; + unsigned int stencilctl; +} drm_mga_context_regs_t; + +/* Setup registers for 2D, X server + */ +typedef struct { + unsigned int pitch; +} drm_mga_server_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int texctl; + unsigned int texctl2; + unsigned int texfilter; + unsigned int texbordercol; + unsigned int texorg; + unsigned int texwidth; + unsigned int texheight; + unsigned int texorg1; + unsigned int texorg2; + unsigned int texorg3; + unsigned int texorg4; +} drm_mga_texture_regs_t; + +/* General aging mechanism + */ +typedef struct { + unsigned int head; /* Position of head pointer */ + unsigned int wrap; /* Primary DMA wrap count */ +} drm_mga_age_t; + +typedef struct _drm_mga_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + drm_mga_context_regs_t context_state; + drm_mga_server_regs_t server_state; + drm_mga_texture_regs_t tex_state[2]; + unsigned int warp_pipe; + unsigned int dirty; + unsigned int vertsize; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Information about the most recently used 3d drawable. The + * client fills in the req_* fields, the server fills in the + * exported_ fields and puts the cliprects into boxes, above. + * + * The client clears the exported_drawable field before + * clobbering the boxes data. + */ + unsigned int req_drawable; /* the X drawable id */ + unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ + + unsigned int exported_drawable; + unsigned int exported_index; + unsigned int exported_stamp; + unsigned int exported_buffers; + unsigned int exported_nfront; + unsigned int exported_nback; + int exported_back_x, exported_front_x, exported_w; + int exported_back_y, exported_front_y, exported_h; + struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS]; + + /* Counters for aging textures and for client-side throttling. + */ + unsigned int status[4]; + unsigned int last_wrap; + + drm_mga_age_t last_frame; + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ + + /* LRU lists for texture memory in agp space and on the card. + */ + struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; + unsigned int texAge[MGA_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_mga_sarea_t; + +/* MGA specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_MGA_INIT 0x00 +#define DRM_MGA_FLUSH 0x01 +#define DRM_MGA_RESET 0x02 +#define DRM_MGA_SWAP 0x03 +#define DRM_MGA_CLEAR 0x04 +#define DRM_MGA_VERTEX 0x05 +#define DRM_MGA_INDICES 0x06 +#define DRM_MGA_ILOAD 0x07 +#define DRM_MGA_BLIT 0x08 +#define DRM_MGA_GETPARAM 0x09 + +/* 3.2: + * ioctls for operating on fences. + */ +#define DRM_MGA_SET_FENCE 0x0a +#define DRM_MGA_WAIT_FENCE 0x0b +#define DRM_MGA_DMA_BOOTSTRAP 0x0c + +#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) +#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) +#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) +#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) +#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) +#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) +#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) + +typedef struct _drm_mga_warp_index { + int installed; + unsigned long phys_addr; + int size; +} drm_mga_warp_index_t; + +typedef struct drm_mga_init { + enum { + MGA_INIT_DMA = 0x01, + MGA_CLEANUP_DMA = 0x02 + } func; + + unsigned long sarea_priv_offset; + + int chipset; + int sgram; + + unsigned int maccess; + + unsigned int fb_cpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_cpp; + unsigned int depth_offset, depth_pitch; + + unsigned int texture_offset[MGA_NR_TEX_HEAPS]; + unsigned int texture_size[MGA_NR_TEX_HEAPS]; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long status_offset; + unsigned long warp_offset; + unsigned long primary_offset; + unsigned long buffers_offset; +} drm_mga_init_t; + +typedef struct drm_mga_dma_bootstrap { + /** + * \name AGP texture region + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will + * be filled in with the actual AGP texture settings. + * + * \warning + * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode + * is zero, it means that PCI memory (most likely through the use of + * an IOMMU) is being used for "AGP" textures. + */ + /*@{ */ + unsigned long texture_handle; /**< Handle used to map AGP textures. */ + __u32 texture_size; /**< Size of the AGP texture region. */ + /*@} */ + + /** + * Requested size of the primary DMA region. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + */ + __u32 primary_size; + + /** + * Requested number of secondary DMA buffers. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual number of secondary DMA buffers + * allocated. Particularly when PCI DMA is used, this may be + * (subtantially) less than the number requested. + */ + __u32 secondary_bin_count; + + /** + * Requested size of each secondary DMA buffer. + * + * While the kernel \b is free to reduce + * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed + * to reduce dma_mga_dma_bootstrap::secondary_bin_size. + */ + __u32 secondary_bin_size; + + /** + * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, + * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is + * zero, it means that PCI DMA should be used, even if AGP is + * possible. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + * (i.e., PCI DMA was used), this value will be zero. + */ + __u32 agp_mode; + + /** + * Desired AGP GART size, measured in megabytes. + */ + __u8 agp_size; +} drm_mga_dma_bootstrap_t; + +typedef struct drm_mga_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_mga_clear_t; + +typedef struct drm_mga_vertex { + int idx; /* buffer to queue */ + int used; /* bytes in use */ + int discard; /* client finished with buffer? */ +} drm_mga_vertex_t; + +typedef struct drm_mga_indices { + int idx; /* buffer to queue */ + unsigned int start; + unsigned int end; + int discard; /* client finished with buffer? */ +} drm_mga_indices_t; + +typedef struct drm_mga_iload { + int idx; + unsigned int dstorg; + unsigned int length; +} drm_mga_iload_t; + +typedef struct _drm_mga_blit { + unsigned int planemask; + unsigned int srcorg; + unsigned int dstorg; + int src_pitch, dst_pitch; + int delta_sx, delta_sy; + int delta_dx, delta_dy; + int height, ydir; /* flip image vertically */ + int source_pitch, dest_pitch; +} drm_mga_blit_t; + +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +/* 3.2: Query the actual card type. The DDX only distinguishes between + * G200 chips and non-G200 chips, which it calls G400. It turns out that + * there are some very sublte differences between the G4x0 chips and the G550 + * chips. Using this parameter query, a client-side driver can detect the + * difference between a G4x0 and a G550. + */ +#define MGA_PARAM_CARD_TYPE 2 + +typedef struct drm_mga_getparam { + int param; + void *value; +} drm_mga_getparam_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/nouveau_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/nouveau_drm.h new file mode 100644 index 0000000..d42105c --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/nouveau_drm.h @@ -0,0 +1,221 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NOUVEAU_DRM_H__ +#define __NOUVEAU_DRM_H__ + +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16 + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +struct drm_nouveau_channel_alloc { + uint32_t fb_ctxdma_handle; + uint32_t tt_ctxdma_handle; + + int channel; + uint32_t pushbuf_domains; + + /* Notifier memory */ + uint32_t notifier_handle; + + /* DRM-enforced subchannel assignments */ + struct { + uint32_t handle; + uint32_t grclass; + } subchan[8]; + uint32_t nr_subchan; +}; + +struct drm_nouveau_channel_free { + int channel; +}; + +struct drm_nouveau_grobj_alloc { + int channel; + uint32_t handle; + int class; +}; + +struct drm_nouveau_notifierobj_alloc { + uint32_t channel; + uint32_t handle; + uint32_t size; + uint32_t offset; +}; + +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + +/* FIXME : maybe unify {GET,SET}PARAMs */ +#define NOUVEAU_GETPARAM_PCI_VENDOR 3 +#define NOUVEAU_GETPARAM_PCI_DEVICE 4 +#define NOUVEAU_GETPARAM_BUS_TYPE 5 +#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 +#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 +#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 +#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 +#define NOUVEAU_GETPARAM_GRAPH_UNITS 13 +#define NOUVEAU_GETPARAM_PTIMER_TIME 14 +#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 +#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 +struct drm_nouveau_getparam { + uint64_t param; + uint64_t value; +}; + +struct drm_nouveau_setparam { + uint64_t param; + uint64_t value; +}; + +#define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) +#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) +#define NOUVEAU_GEM_DOMAIN_GART (1 << 2) +#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) +#define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4) + +#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ +#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 +#define NOUVEAU_GEM_TILE_16BPP 0x00000001 +#define NOUVEAU_GEM_TILE_32BPP 0x00000002 +#define NOUVEAU_GEM_TILE_ZETA 0x00000004 +#define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 + +struct drm_nouveau_gem_info { + __u32 handle; + __u32 domain; + __u64 size; + __u64 offset; + __u64 map_handle; + __u32 tile_mode; + __u32 tile_flags; +}; + +struct drm_nouveau_gem_new { + struct drm_nouveau_gem_info info; + __u32 channel_hint; + __u32 align; +}; + +#define NOUVEAU_GEM_MAX_BUFFERS 1024 +struct drm_nouveau_gem_pushbuf_bo_presumed { + __u32 valid; + __u32 domain; + __u64 offset; +}; + +struct drm_nouveau_gem_pushbuf_bo { + __u64 user_priv; + __u32 handle; + __u32 read_domains; + __u32 write_domains; + __u32 valid_domains; + struct drm_nouveau_gem_pushbuf_bo_presumed presumed; +}; + +#define NOUVEAU_GEM_RELOC_LOW (1 << 0) +#define NOUVEAU_GEM_RELOC_HIGH (1 << 1) +#define NOUVEAU_GEM_RELOC_OR (1 << 2) +#define NOUVEAU_GEM_MAX_RELOCS 1024 +struct drm_nouveau_gem_pushbuf_reloc { + __u32 reloc_bo_index; + __u32 reloc_bo_offset; + __u32 bo_index; + __u32 flags; + __u32 data; + __u32 vor; + __u32 tor; +}; + +#define NOUVEAU_GEM_MAX_PUSH 512 +struct drm_nouveau_gem_pushbuf_push { + __u32 bo_index; + __u32 pad; + __u64 offset; + __u64 length; +}; + +struct drm_nouveau_gem_pushbuf { + __u32 channel; + __u32 nr_buffers; + __u64 buffers; + __u32 nr_relocs; + __u32 nr_push; + __u64 relocs; + __u64 push; + __u32 suffix0; + __u32 suffix1; + __u64 vram_available; + __u64 gart_available; +}; + +#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 +#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 +#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 +struct drm_nouveau_gem_cpu_prep { + __u32 handle; + __u32 flags; +}; + +struct drm_nouveau_gem_cpu_fini { + __u32 handle; +}; + +enum nouveau_bus_type { + NV_AGP = 0, + NV_PCI = 1, + NV_PCIE = 2, +}; + +struct drm_nouveau_sarea { +}; + +#define DRM_NOUVEAU_GETPARAM 0x00 +#define DRM_NOUVEAU_SETPARAM 0x01 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 +#define DRM_NOUVEAU_CHANNEL_FREE 0x03 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x04 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x06 +#define DRM_NOUVEAU_NVIF 0x07 +#define DRM_NOUVEAU_GEM_NEW 0x40 +#define DRM_NOUVEAU_GEM_PUSHBUF 0x41 +#define DRM_NOUVEAU_GEM_CPU_PREP 0x42 +#define DRM_NOUVEAU_GEM_CPU_FINI 0x43 +#define DRM_NOUVEAU_GEM_INFO 0x44 + +#if defined(__cplusplus) +} +#endif + +#endif /* __NOUVEAU_DRM_H__ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/qxl_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/qxl_drm.h new file mode 100644 index 0000000..880999d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/qxl_drm.h @@ -0,0 +1,158 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef QXL_DRM_H +#define QXL_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define QXL_GEM_DOMAIN_CPU 0 +#define QXL_GEM_DOMAIN_VRAM 1 +#define QXL_GEM_DOMAIN_SURFACE 2 + +#define DRM_QXL_ALLOC 0x00 +#define DRM_QXL_MAP 0x01 +#define DRM_QXL_EXECBUFFER 0x02 +#define DRM_QXL_UPDATE_AREA 0x03 +#define DRM_QXL_GETPARAM 0x04 +#define DRM_QXL_CLIENTCAP 0x05 + +#define DRM_QXL_ALLOC_SURF 0x06 + +struct drm_qxl_alloc { + __u32 size; + __u32 handle; /* 0 is an invalid handle */ +}; + +struct drm_qxl_map { + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; +}; + +/* + * dest is the bo we are writing the relocation into + * src is bo we are relocating. + * *(dest_handle.base_addr + dest_offset) = physical_address(src_handle.addr + + * src_offset) + */ +#define QXL_RELOC_TYPE_BO 1 +#define QXL_RELOC_TYPE_SURF 2 + +struct drm_qxl_reloc { + __u64 src_offset; /* offset into src_handle or src buffer */ + __u64 dst_offset; /* offset in dest handle */ + __u32 src_handle; /* dest handle to compute address from */ + __u32 dst_handle; /* 0 if to command buffer */ + __u32 reloc_type; + __u32 pad; +}; + +struct drm_qxl_command { + __u64 command; /* void* */ + __u64 relocs; /* struct drm_qxl_reloc* */ + __u32 type; + __u32 command_size; + __u32 relocs_num; + __u32 pad; +}; + +struct drm_qxl_execbuffer { + __u32 flags; /* for future use */ + __u32 commands_num; + __u64 commands; /* struct drm_qxl_command* */ +}; + +struct drm_qxl_update_area { + __u32 handle; + __u32 top; + __u32 left; + __u32 bottom; + __u32 right; + __u32 pad; +}; + +#define QXL_PARAM_NUM_SURFACES 1 /* rom->n_surfaces */ +#define QXL_PARAM_MAX_RELOCS 2 +struct drm_qxl_getparam { + __u64 param; + __u64 value; +}; + +/* these are one bit values */ +struct drm_qxl_clientcap { + __u32 index; + __u32 pad; +}; + +struct drm_qxl_alloc_surf { + __u32 format; + __u32 width; + __u32 height; + __s32 stride; + __u32 handle; + __u32 pad; +}; + +#define DRM_IOCTL_QXL_ALLOC \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC, struct drm_qxl_alloc) + +#define DRM_IOCTL_QXL_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_MAP, struct drm_qxl_map) + +#define DRM_IOCTL_QXL_EXECBUFFER \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_EXECBUFFER,\ + struct drm_qxl_execbuffer) + +#define DRM_IOCTL_QXL_UPDATE_AREA \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_UPDATE_AREA,\ + struct drm_qxl_update_area) + +#define DRM_IOCTL_QXL_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_GETPARAM,\ + struct drm_qxl_getparam) + +#define DRM_IOCTL_QXL_CLIENTCAP \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_CLIENTCAP,\ + struct drm_qxl_clientcap) + +#define DRM_IOCTL_QXL_ALLOC_SURF \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC_SURF,\ + struct drm_qxl_alloc_surf) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/r128_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/r128_drm.h new file mode 100644 index 0000000..bf431a0 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/r128_drm.h @@ -0,0 +1,336 @@ +/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + */ +/* + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Kevin E. Martin + */ + +#ifndef __R128_DRM_H__ +#define __R128_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (r128_sarea.h) + */ +#ifndef __R128_SAREA_DEFINES__ +#define __R128_SAREA_DEFINES__ + +/* What needs to be changed for the current vertex buffer? + */ +#define R128_UPLOAD_CONTEXT 0x001 +#define R128_UPLOAD_SETUP 0x002 +#define R128_UPLOAD_TEX0 0x004 +#define R128_UPLOAD_TEX1 0x008 +#define R128_UPLOAD_TEX0IMAGES 0x010 +#define R128_UPLOAD_TEX1IMAGES 0x020 +#define R128_UPLOAD_CORE 0x040 +#define R128_UPLOAD_MASKS 0x080 +#define R128_UPLOAD_WINDOW 0x100 +#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */ +#define R128_REQUIRE_QUIESCENCE 0x400 +#define R128_UPLOAD_ALL 0x7ff + +#define R128_FRONT 0x1 +#define R128_BACK 0x2 +#define R128_DEPTH 0x4 + +/* Primitive types + */ +#define R128_POINTS 0x1 +#define R128_LINES 0x2 +#define R128_LINE_STRIP 0x3 +#define R128_TRIANGLES 0x4 +#define R128_TRIANGLE_FAN 0x5 +#define R128_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define R128_BUFFER_SIZE 16384 + +/* Byte offsets for indirect buffer data + */ +#define R128_INDEX_PRIM_OFFSET 20 +#define R128_HOSTDATA_BLIT_OFFSET 32 + +/* Keep these small for testing. + */ +#define R128_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/AGP). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +#define R128_NR_CONTEXT_REGS 12 + +#define R128_MAX_TEXTURE_LEVELS 11 +#define R128_MAX_TEXTURE_UNITS 2 + +#endif /* __R128_SAREA_DEFINES__ */ + +typedef struct { + /* Context state - can be written in one large chunk */ + unsigned int dst_pitch_offset_c; + unsigned int dp_gui_master_cntl_c; + unsigned int sc_top_left_c; + unsigned int sc_bottom_right_c; + unsigned int z_offset_c; + unsigned int z_pitch_c; + unsigned int z_sten_cntl_c; + unsigned int tex_cntl_c; + unsigned int misc_3d_state_cntl_reg; + unsigned int texture_clr_cmp_clr_c; + unsigned int texture_clr_cmp_msk_c; + unsigned int fog_color_c; + + /* Texture state */ + unsigned int tex_size_pitch_c; + unsigned int constant_color_c; + + /* Setup state */ + unsigned int pm4_vc_fpu_setup; + unsigned int setup_cntl; + + /* Mask state */ + unsigned int dp_write_mask; + unsigned int sten_ref_mask_c; + unsigned int plane_3d_mask_c; + + /* Window state */ + unsigned int window_xy_offset; + + /* Core state */ + unsigned int scale_3d_cntl; +} drm_r128_context_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int tex_cntl; + unsigned int tex_combine_cntl; + unsigned int tex_size_pitch; + unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS]; + unsigned int tex_border_color; +} drm_r128_texture_regs_t; + +typedef struct drm_r128_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex buffer. + */ + drm_r128_context_regs_t context_state; + drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + + struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1]; + unsigned int tex_age[R128_NR_TEX_HEAPS]; + int ctx_owner; + int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */ + int pfCurrentPage; /* which buffer is being displayed? */ +} drm_r128_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmR128.h) + */ + +/* Rage 128 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_R128_INIT 0x00 +#define DRM_R128_CCE_START 0x01 +#define DRM_R128_CCE_STOP 0x02 +#define DRM_R128_CCE_RESET 0x03 +#define DRM_R128_CCE_IDLE 0x04 +/* 0x05 not used */ +#define DRM_R128_RESET 0x06 +#define DRM_R128_SWAP 0x07 +#define DRM_R128_CLEAR 0x08 +#define DRM_R128_VERTEX 0x09 +#define DRM_R128_INDICES 0x0a +#define DRM_R128_BLIT 0x0b +#define DRM_R128_DEPTH 0x0c +#define DRM_R128_STIPPLE 0x0d +/* 0x0e not used */ +#define DRM_R128_INDIRECT 0x0f +#define DRM_R128_FULLSCREEN 0x10 +#define DRM_R128_CLEAR2 0x11 +#define DRM_R128_GETPARAM 0x12 +#define DRM_R128_FLIP 0x13 + +#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE) +/* 0x05 not used */ +#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET) +#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t) +/* 0x0e not used */ +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) +#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP) + +typedef struct drm_r128_init { + enum { + R128_INIT_CCE = 0x01, + R128_CLEANUP_CCE = 0x02 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_secure; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + unsigned int span_offset; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drm_r128_init_t; + +typedef struct drm_r128_cce_stop { + int flush; + int idle; +} drm_r128_cce_stop_t; + +typedef struct drm_r128_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_r128_clear_t; + +typedef struct drm_r128_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_r128_vertex_t; + +typedef struct drm_r128_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_r128_indices_t; + +typedef struct drm_r128_blit { + int idx; + int pitch; + int offset; + int format; + unsigned short x, y; + unsigned short width, height; +} drm_r128_blit_t; + +typedef struct drm_r128_depth { + enum { + R128_WRITE_SPAN = 0x01, + R128_WRITE_PIXELS = 0x02, + R128_READ_SPAN = 0x03, + R128_READ_PIXELS = 0x04 + } func; + int n; + int *x; + int *y; + unsigned int *buffer; + unsigned char *mask; +} drm_r128_depth_t; + +typedef struct drm_r128_stipple { + unsigned int *mask; +} drm_r128_stipple_t; + +typedef struct drm_r128_indirect { + int idx; + int start; + int end; + int discard; +} drm_r128_indirect_t; + +typedef struct drm_r128_fullscreen { + enum { + R128_INIT_FULLSCREEN = 0x01, + R128_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_r128_fullscreen_t; + +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + void *value; +} drm_r128_getparam_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/radeon_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/radeon_drm.h new file mode 100644 index 0000000..a1e385d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/radeon_drm.h @@ -0,0 +1,1079 @@ +/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#ifndef __RADEON_DRM_H__ +#define __RADEON_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (radeon_sarea.h) + */ +#ifndef __RADEON_SAREA_DEFINES__ +#define __RADEON_SAREA_DEFINES__ + +/* Old style state flags, required for sarea interface (1.1 and 1.2 + * clears) and 1.2 drm_vertex2 ioctl. + */ +#define RADEON_UPLOAD_CONTEXT 0x00000001 +#define RADEON_UPLOAD_VERTFMT 0x00000002 +#define RADEON_UPLOAD_LINE 0x00000004 +#define RADEON_UPLOAD_BUMPMAP 0x00000008 +#define RADEON_UPLOAD_MASKS 0x00000010 +#define RADEON_UPLOAD_VIEWPORT 0x00000020 +#define RADEON_UPLOAD_SETUP 0x00000040 +#define RADEON_UPLOAD_TCL 0x00000080 +#define RADEON_UPLOAD_MISC 0x00000100 +#define RADEON_UPLOAD_TEX0 0x00000200 +#define RADEON_UPLOAD_TEX1 0x00000400 +#define RADEON_UPLOAD_TEX2 0x00000800 +#define RADEON_UPLOAD_TEX0IMAGES 0x00001000 +#define RADEON_UPLOAD_TEX1IMAGES 0x00002000 +#define RADEON_UPLOAD_TEX2IMAGES 0x00004000 +#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */ +#define RADEON_REQUIRE_QUIESCENCE 0x00010000 +#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ +#define RADEON_UPLOAD_ALL 0x003effff +#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff + +/* New style per-packet identifiers for use in cmd_buffer ioctl with + * the RADEON_EMIT_PACKET command. Comments relate new packets to old + * state bits and the packet size: + */ +#define RADEON_EMIT_PP_MISC 0 /* context/7 */ +#define RADEON_EMIT_PP_CNTL 1 /* context/3 */ +#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ +#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ +#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ +#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ +#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ +#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ +#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ +#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ +#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ +#define RADEON_EMIT_RE_MISC 11 /* misc/1 */ +#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ +#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ +#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ +#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ +#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ +#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ +#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ +#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ +#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ +#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ +#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ +#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ +#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ +#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ +#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ +#define R200_EMIT_TFACTOR_0 30 /* tf/7 */ +#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ +#define R200_EMIT_VAP_CTL 32 /* vap/1 */ +#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ +#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ +#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ +#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ +#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ +#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ +#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ +#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ +#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ +#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ +#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ +#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ +#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ +#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ +#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ +#define R200_EMIT_VTE_CNTL 48 /* vte/1 */ +#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ +#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ +#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ +#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ +#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ +#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ +#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ +#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ +#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ +#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_EMIT_PP_TEX_SIZE_0 73 +#define RADEON_EMIT_PP_TEX_SIZE_1 74 +#define RADEON_EMIT_PP_TEX_SIZE_2 75 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77 +#define RADEON_EMIT_PP_CUBIC_FACES_0 78 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79 +#define RADEON_EMIT_PP_CUBIC_FACES_1 80 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81 +#define RADEON_EMIT_PP_CUBIC_FACES_2 82 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83 +#define R200_EMIT_PP_TRI_PERF_CNTL 84 +#define R200_EMIT_PP_AFS_0 85 +#define R200_EMIT_PP_AFS_1 86 +#define R200_EMIT_ATF_TFACTOR 87 +#define R200_EMIT_PP_TXCTLALL_0 88 +#define R200_EMIT_PP_TXCTLALL_1 89 +#define R200_EMIT_PP_TXCTLALL_2 90 +#define R200_EMIT_PP_TXCTLALL_3 91 +#define R200_EMIT_PP_TXCTLALL_4 92 +#define R200_EMIT_PP_TXCTLALL_5 93 +#define R200_EMIT_VAP_PVS_CNTL 94 +#define RADEON_MAX_STATE_PACKETS 95 + +/* Commands understood by cmd_buffer ioctl. More can be added but + * obviously these can't be removed or changed: + */ +#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ +#define RADEON_CMD_SCALARS 2 /* emit scalar data */ +#define RADEON_CMD_VECTORS 3 /* emit vector data */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ +#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ +#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: + * doesn't make the cpu wait, just + * the graphics hardware */ +#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */ + +typedef union { + int i; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, packet_id, pad0, pad1; + } packet; + struct { + unsigned char cmd_type, offset, stride, count; + } scalars; + struct { + unsigned char cmd_type, offset, stride, count; + } vectors; + struct { + unsigned char cmd_type, addr_lo, addr_hi, count; + } veclinear; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; +} drm_radeon_cmd_header_t; + +#define RADEON_WAIT_2D 0x1 +#define RADEON_WAIT_3D 0x2 + +/* Allowed parameters for R300_CMD_PACKET3 + */ +#define R300_CMD_PACKET3_CLEAR 0 +#define R300_CMD_PACKET3_RAW 1 + +/* Commands understood by cmd_buffer ioctl for R300. + * The interface has not been stabilized, so some of these may be removed + * and eventually reordered before stabilization. + */ +#define R300_CMD_PACKET0 1 +#define R300_CMD_VPU 2 /* emit vertex program upload */ +#define R300_CMD_PACKET3 3 /* emit a packet3 */ +#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */ +#define R300_CMD_CP_DELAY 5 +#define R300_CMD_DMA_DISCARD 6 +#define R300_CMD_WAIT 7 +# define R300_WAIT_2D 0x1 +# define R300_WAIT_3D 0x2 +/* these two defines are DOING IT WRONG - however + * we have userspace which relies on using these. + * The wait interface is backwards compat new + * code should use the NEW_WAIT defines below + * THESE ARE NOT BIT FIELDS + */ +# define R300_WAIT_2D_CLEAN 0x3 +# define R300_WAIT_3D_CLEAN 0x4 + +# define R300_NEW_WAIT_2D_3D 0x3 +# define R300_NEW_WAIT_2D_2D_CLEAN 0x4 +# define R300_NEW_WAIT_3D_3D_CLEAN 0x6 +# define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN 0x8 + +#define R300_CMD_SCRATCH 8 +#define R300_CMD_R500FP 9 + +typedef union { + unsigned int u; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, count, reglo, reghi; + } packet0; + struct { + unsigned char cmd_type, count, adrlo, adrhi; + } vpu; + struct { + unsigned char cmd_type, packet, pad0, pad1; + } packet3; + struct { + unsigned char cmd_type, packet; + unsigned short count; /* amount of packet2 to emit */ + } delay; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; + struct { + unsigned char cmd_type, count, adrlo, adrhi_flags; + } r500fp; +} drm_r300_cmd_header_t; + +#define RADEON_FRONT 0x1 +#define RADEON_BACK 0x2 +#define RADEON_DEPTH 0x4 +#define RADEON_STENCIL 0x8 +#define RADEON_CLEAR_FASTZ 0x80000000 +#define RADEON_USE_HIERZ 0x40000000 +#define RADEON_USE_COMP_ZBUF 0x20000000 + +#define R500FP_CONSTANT_TYPE (1 << 1) +#define R500FP_CONSTANT_CLAMP (1 << 2) + +/* Primitive types + */ +#define RADEON_POINTS 0x1 +#define RADEON_LINES 0x2 +#define RADEON_LINE_STRIP 0x3 +#define RADEON_TRIANGLES 0x4 +#define RADEON_TRIANGLE_FAN 0x5 +#define RADEON_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define RADEON_BUFFER_SIZE 65536 + +/* Byte offsets for indirect buffer data + */ +#define RADEON_INDEX_PRIM_OFFSET 20 + +#define RADEON_SCRATCH_REG_OFFSET 32 + +#define R600_SCRATCH_REG_OFFSET 256 + +#define RADEON_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/GART). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define RADEON_LOCAL_TEX_HEAP 0 +#define RADEON_GART_TEX_HEAP 1 +#define RADEON_NR_TEX_HEAPS 2 +#define RADEON_NR_TEX_REGIONS 64 +#define RADEON_LOG_TEX_GRANULARITY 16 + +#define RADEON_MAX_TEXTURE_LEVELS 12 +#define RADEON_MAX_TEXTURE_UNITS 3 + +#define RADEON_MAX_SURFACES 8 + +/* Blits have strict offset rules. All blit offset must be aligned on + * a 1K-byte boundary. + */ +#define RADEON_OFFSET_SHIFT 10 +#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT) +#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1) + +#endif /* __RADEON_SAREA_DEFINES__ */ + +typedef struct { + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int alpha; +} radeon_color_regs_t; + +typedef struct { + /* Context state */ + unsigned int pp_misc; /* 0x1c14 */ + unsigned int pp_fog_color; + unsigned int re_solid_color; + unsigned int rb3d_blendcntl; + unsigned int rb3d_depthoffset; + unsigned int rb3d_depthpitch; + unsigned int rb3d_zstencilcntl; + + unsigned int pp_cntl; /* 0x1c38 */ + unsigned int rb3d_cntl; + unsigned int rb3d_coloroffset; + unsigned int re_width_height; + unsigned int rb3d_colorpitch; + unsigned int se_cntl; + + /* Vertex format state */ + unsigned int se_coord_fmt; /* 0x1c50 */ + + /* Line state */ + unsigned int re_line_pattern; /* 0x1cd0 */ + unsigned int re_line_state; + + unsigned int se_line_width; /* 0x1db8 */ + + /* Bumpmap state */ + unsigned int pp_lum_matrix; /* 0x1d00 */ + + unsigned int pp_rot_matrix_0; /* 0x1d58 */ + unsigned int pp_rot_matrix_1; + + /* Mask state */ + unsigned int rb3d_stencilrefmask; /* 0x1d7c */ + unsigned int rb3d_ropcntl; + unsigned int rb3d_planemask; + + /* Viewport state */ + unsigned int se_vport_xscale; /* 0x1d98 */ + unsigned int se_vport_xoffset; + unsigned int se_vport_yscale; + unsigned int se_vport_yoffset; + unsigned int se_vport_zscale; + unsigned int se_vport_zoffset; + + /* Setup state */ + unsigned int se_cntl_status; /* 0x2140 */ + + /* Misc state */ + unsigned int re_top_left; /* 0x26c0 */ + unsigned int re_misc; +} drm_radeon_context_regs_t; + +typedef struct { + /* Zbias state */ + unsigned int se_zbias_factor; /* 0x1dac */ + unsigned int se_zbias_constant; +} drm_radeon_context2_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int pp_txfilter; + unsigned int pp_txformat; + unsigned int pp_txoffset; + unsigned int pp_txcblend; + unsigned int pp_txablend; + unsigned int pp_tfactor; + unsigned int pp_border_color; +} drm_radeon_texture_regs_t; + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim:8; + unsigned int stateidx:8; + unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ + unsigned int vc_format; /* vertex format */ +} drm_radeon_prim_t; + +typedef struct { + drm_radeon_context_regs_t context; + drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; + drm_radeon_context2_regs_t context2; + unsigned int dirty; +} drm_radeon_state_t; + +typedef struct { + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. + */ + drm_radeon_context_regs_t context_state; + drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + unsigned int last_clear; + + struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[RADEON_NR_TEX_HEAPS]; + int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ + int tiling_enabled; /* set by drm, read by 2d + 3d clients */ +} drm_radeon_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmRadeon.h) + * + * KW: actually it's illegal to change any of this (backwards compatibility). + */ + +/* Radeon specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_RADEON_CP_INIT 0x00 +#define DRM_RADEON_CP_START 0x01 +#define DRM_RADEON_CP_STOP 0x02 +#define DRM_RADEON_CP_RESET 0x03 +#define DRM_RADEON_CP_IDLE 0x04 +#define DRM_RADEON_RESET 0x05 +#define DRM_RADEON_FULLSCREEN 0x06 +#define DRM_RADEON_SWAP 0x07 +#define DRM_RADEON_CLEAR 0x08 +#define DRM_RADEON_VERTEX 0x09 +#define DRM_RADEON_INDICES 0x0A +#define DRM_RADEON_NOT_USED +#define DRM_RADEON_STIPPLE 0x0C +#define DRM_RADEON_INDIRECT 0x0D +#define DRM_RADEON_TEXTURE 0x0E +#define DRM_RADEON_VERTEX2 0x0F +#define DRM_RADEON_CMDBUF 0x10 +#define DRM_RADEON_GETPARAM 0x11 +#define DRM_RADEON_FLIP 0x12 +#define DRM_RADEON_ALLOC 0x13 +#define DRM_RADEON_FREE 0x14 +#define DRM_RADEON_INIT_HEAP 0x15 +#define DRM_RADEON_IRQ_EMIT 0x16 +#define DRM_RADEON_IRQ_WAIT 0x17 +#define DRM_RADEON_CP_RESUME 0x18 +#define DRM_RADEON_SETPARAM 0x19 +#define DRM_RADEON_SURF_ALLOC 0x1a +#define DRM_RADEON_SURF_FREE 0x1b +/* KMS ioctl */ +#define DRM_RADEON_GEM_INFO 0x1c +#define DRM_RADEON_GEM_CREATE 0x1d +#define DRM_RADEON_GEM_MMAP 0x1e +#define DRM_RADEON_GEM_PREAD 0x21 +#define DRM_RADEON_GEM_PWRITE 0x22 +#define DRM_RADEON_GEM_SET_DOMAIN 0x23 +#define DRM_RADEON_GEM_WAIT_IDLE 0x24 +#define DRM_RADEON_CS 0x26 +#define DRM_RADEON_INFO 0x27 +#define DRM_RADEON_GEM_SET_TILING 0x28 +#define DRM_RADEON_GEM_GET_TILING 0x29 +#define DRM_RADEON_GEM_BUSY 0x2a +#define DRM_RADEON_GEM_VA 0x2b +#define DRM_RADEON_GEM_OP 0x2c +#define DRM_RADEON_GEM_USERPTR 0x2d + +#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) +#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) +#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) +#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET) +#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE) +#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t) +#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP) +#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t) +#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t) +#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME) +#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) +#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) +#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) +/* KMS */ +#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info) +#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create) +#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap) +#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) +#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) +#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) +#define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) +#define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) +#define DRM_IOCTL_RADEON_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling) +#define DRM_IOCTL_RADEON_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling) +#define DRM_IOCTL_RADEON_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy) +#define DRM_IOCTL_RADEON_GEM_VA DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_VA, struct drm_radeon_gem_va) +#define DRM_IOCTL_RADEON_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_OP, struct drm_radeon_gem_op) +#define DRM_IOCTL_RADEON_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_USERPTR, struct drm_radeon_gem_userptr) + +typedef struct drm_radeon_init { + enum { + RADEON_INIT_CP = 0x01, + RADEON_CLEANUP_CP = 0x02, + RADEON_INIT_R200_CP = 0x03, + RADEON_INIT_R300_CP = 0x04, + RADEON_INIT_R600_CP = 0x05 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cp_mode; + int gart_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long gart_textures_offset; +} drm_radeon_init_t; + +typedef struct drm_radeon_cp_stop { + int flush; + int idle; +} drm_radeon_cp_stop_t; + +typedef struct drm_radeon_fullscreen { + enum { + RADEON_INIT_FULLSCREEN = 0x01, + RADEON_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_radeon_fullscreen_t; + +#define CLEAR_X1 0 +#define CLEAR_Y1 1 +#define CLEAR_X2 2 +#define CLEAR_Y2 3 +#define CLEAR_DEPTH 4 + +typedef union drm_radeon_clear_rect { + float f[5]; + unsigned int ui[5]; +} drm_radeon_clear_rect_t; + +typedef struct drm_radeon_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ + drm_radeon_clear_rect_t *depth_boxes; +} drm_radeon_clear_t; + +typedef struct drm_radeon_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_radeon_vertex_t; + +typedef struct drm_radeon_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_radeon_indices_t; + +/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices + * - allows multiple primitives and state changes in a single ioctl + * - supports driver change to emit native primitives + */ +typedef struct drm_radeon_vertex2 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t *state; + int nr_prims; + drm_radeon_prim_t *prim; +} drm_radeon_vertex2_t; + +/* v1.3 - obsoletes drm_radeon_vertex2 + * - allows arbitrarily large cliprect list + * - allows updating of tcl packet, vector and scalar state + * - allows memory-efficient description of state updates + * - allows state to be emitted without a primitive + * (for clears, ctx switches) + * - allows more than one dma buffer to be referenced per ioctl + * - supports tcl driver + * - may be extended in future versions with new cmd types, packets + */ +typedef struct drm_radeon_cmd_buffer { + int bufsz; + char *buf; + int nbox; + struct drm_clip_rect *boxes; +} drm_radeon_cmd_buffer_t; + +typedef struct drm_radeon_tex_image { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + const void *data; +} drm_radeon_tex_image_t; + +typedef struct drm_radeon_texture { + unsigned int offset; + int pitch; + int format; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t *image; +} drm_radeon_texture_t; + +typedef struct drm_radeon_stipple { + unsigned int *mask; +} drm_radeon_stipple_t; + +typedef struct drm_radeon_indirect { + int idx; + int start; + int end; + int discard; +} drm_radeon_indirect_t; + +/* enum for card type parameters */ +#define RADEON_CARD_PCI 0 +#define RADEON_CARD_AGP 1 +#define RADEON_CARD_PCIE 2 + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +/* Added with DRM version 1.6. */ +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ +/* Added with DRM version 1.8. */ +#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ +#define RADEON_PARAM_STATUS_HANDLE 8 +#define RADEON_PARAM_SAREA_HANDLE 9 +#define RADEON_PARAM_GART_TEX_HANDLE 10 +#define RADEON_PARAM_SCRATCH_OFFSET 11 +#define RADEON_PARAM_CARD_TYPE 12 +#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ +#define RADEON_PARAM_FB_LOCATION 14 /* FB location */ +#define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ +#define RADEON_PARAM_DEVICE_ID 16 +#define RADEON_PARAM_NUM_Z_PIPES 17 /* num Z pipes */ + +typedef struct drm_radeon_getparam { + int param; + void *value; +} drm_radeon_getparam_t; + +/* 1.6: Set up a memory manager for regions of shared memory: + */ +#define RADEON_MEM_REGION_GART 1 +#define RADEON_MEM_REGION_FB 2 + +typedef struct drm_radeon_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or GART */ +} drm_radeon_mem_alloc_t; + +typedef struct drm_radeon_mem_free { + int region; + int region_offset; +} drm_radeon_mem_free_t; + +typedef struct drm_radeon_mem_init_heap { + int region; + int size; + int start; +} drm_radeon_mem_init_heap_t; + +/* 1.6: Userspace can request & wait on irq's: + */ +typedef struct drm_radeon_irq_emit { + int *irq_seq; +} drm_radeon_irq_emit_t; + +typedef struct drm_radeon_irq_wait { + int irq_seq; +} drm_radeon_irq_wait_t; + +/* 1.10: Clients tell the DRM where they think the framebuffer is located in + * the card's address space, via a new generic ioctl to set parameters + */ + +typedef struct drm_radeon_setparam { + unsigned int param; + __s64 value; +} drm_radeon_setparam_t; + +#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ +#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ +#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ +#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ +/* 1.14: Clients can allocate/free a surface + */ +typedef struct drm_radeon_surface_alloc { + unsigned int address; + unsigned int size; + unsigned int flags; +} drm_radeon_surface_alloc_t; + +typedef struct drm_radeon_surface_free { + unsigned int address; +} drm_radeon_surface_free_t; + +#define DRM_RADEON_VBLANK_CRTC1 1 +#define DRM_RADEON_VBLANK_CRTC2 2 + +/* + * Kernel modesetting world below. + */ +#define RADEON_GEM_DOMAIN_CPU 0x1 +#define RADEON_GEM_DOMAIN_GTT 0x2 +#define RADEON_GEM_DOMAIN_VRAM 0x4 + +struct drm_radeon_gem_info { + __u64 gart_size; + __u64 vram_size; + __u64 vram_visible; +}; + +#define RADEON_GEM_NO_BACKING_STORE (1 << 0) +#define RADEON_GEM_GTT_UC (1 << 1) +#define RADEON_GEM_GTT_WC (1 << 2) +/* BO is expected to be accessed by the CPU */ +#define RADEON_GEM_CPU_ACCESS (1 << 3) +/* CPU access is not expected to work for this BO */ +#define RADEON_GEM_NO_CPU_ACCESS (1 << 4) + +struct drm_radeon_gem_create { + __u64 size; + __u64 alignment; + __u32 handle; + __u32 initial_domain; + __u32 flags; +}; + +/* + * This is not a reliable API and you should expect it to fail for any + * number of reasons and have fallback path that do not use userptr to + * perform any operation. + */ +#define RADEON_GEM_USERPTR_READONLY (1 << 0) +#define RADEON_GEM_USERPTR_ANONONLY (1 << 1) +#define RADEON_GEM_USERPTR_VALIDATE (1 << 2) +#define RADEON_GEM_USERPTR_REGISTER (1 << 3) + +struct drm_radeon_gem_userptr { + __u64 addr; + __u64 size; + __u32 flags; + __u32 handle; +}; + +#define RADEON_TILING_MACRO 0x1 +#define RADEON_TILING_MICRO 0x2 +#define RADEON_TILING_SWAP_16BIT 0x4 +#define RADEON_TILING_R600_NO_SCANOUT RADEON_TILING_SWAP_16BIT +#define RADEON_TILING_SWAP_32BIT 0x8 +/* this object requires a surface when mapped - i.e. front buffer */ +#define RADEON_TILING_SURFACE 0x10 +#define RADEON_TILING_MICRO_SQUARE 0x20 +#define RADEON_TILING_EG_BANKW_SHIFT 8 +#define RADEON_TILING_EG_BANKW_MASK 0xf +#define RADEON_TILING_EG_BANKH_SHIFT 12 +#define RADEON_TILING_EG_BANKH_MASK 0xf +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT 16 +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK 0xf +#define RADEON_TILING_EG_TILE_SPLIT_SHIFT 24 +#define RADEON_TILING_EG_TILE_SPLIT_MASK 0xf +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT 28 +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf + +struct drm_radeon_gem_set_tiling { + __u32 handle; + __u32 tiling_flags; + __u32 pitch; +}; + +struct drm_radeon_gem_get_tiling { + __u32 handle; + __u32 tiling_flags; + __u32 pitch; +}; + +struct drm_radeon_gem_mmap { + __u32 handle; + __u32 pad; + __u64 offset; + __u64 size; + __u64 addr_ptr; +}; + +struct drm_radeon_gem_set_domain { + __u32 handle; + __u32 read_domains; + __u32 write_domain; +}; + +struct drm_radeon_gem_wait_idle { + __u32 handle; + __u32 pad; +}; + +struct drm_radeon_gem_busy { + __u32 handle; + __u32 domain; +}; + +struct drm_radeon_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** Pointer to write the data into. */ + /* void *, but pointers are not 32/64 compatible */ + __u64 data_ptr; +}; + +struct drm_radeon_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** Pointer to read the data from. */ + /* void *, but pointers are not 32/64 compatible */ + __u64 data_ptr; +}; + +/* Sets or returns a value associated with a buffer. */ +struct drm_radeon_gem_op { + __u32 handle; /* buffer */ + __u32 op; /* RADEON_GEM_OP_* */ + __u64 value; /* input or return value */ +}; + +#define RADEON_GEM_OP_GET_INITIAL_DOMAIN 0 +#define RADEON_GEM_OP_SET_INITIAL_DOMAIN 1 + +#define RADEON_VA_MAP 1 +#define RADEON_VA_UNMAP 2 + +#define RADEON_VA_RESULT_OK 0 +#define RADEON_VA_RESULT_ERROR 1 +#define RADEON_VA_RESULT_VA_EXIST 2 + +#define RADEON_VM_PAGE_VALID (1 << 0) +#define RADEON_VM_PAGE_READABLE (1 << 1) +#define RADEON_VM_PAGE_WRITEABLE (1 << 2) +#define RADEON_VM_PAGE_SYSTEM (1 << 3) +#define RADEON_VM_PAGE_SNOOPED (1 << 4) + +struct drm_radeon_gem_va { + __u32 handle; + __u32 operation; + __u32 vm_id; + __u32 flags; + __u64 offset; +}; + +#define RADEON_CHUNK_ID_RELOCS 0x01 +#define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_FLAGS 0x03 +#define RADEON_CHUNK_ID_CONST_IB 0x04 + +/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ +#define RADEON_CS_KEEP_TILING_FLAGS 0x01 +#define RADEON_CS_USE_VM 0x02 +#define RADEON_CS_END_OF_FRAME 0x04 /* a hint from userspace which CS is the last one */ +/* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */ +#define RADEON_CS_RING_GFX 0 +#define RADEON_CS_RING_COMPUTE 1 +#define RADEON_CS_RING_DMA 2 +#define RADEON_CS_RING_UVD 3 +#define RADEON_CS_RING_VCE 4 +/* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ +/* 0 = normal, + = higher priority, - = lower priority */ + +struct drm_radeon_cs_chunk { + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; +}; + +/* drm_radeon_cs_reloc.flags */ +#define RADEON_RELOC_PRIO_MASK (0xf << 0) + +struct drm_radeon_cs_reloc { + __u32 handle; + __u32 read_domains; + __u32 write_domain; + __u32 flags; +}; + +struct drm_radeon_cs { + __u32 num_chunks; + __u32 cs_id; + /* this points to __u64 * which point to cs chunks */ + __u64 chunks; + /* updates to the limits after this CS ioctl */ + __u64 gart_limit; + __u64 vram_limit; +}; + +#define RADEON_INFO_DEVICE_ID 0x00 +#define RADEON_INFO_NUM_GB_PIPES 0x01 +#define RADEON_INFO_NUM_Z_PIPES 0x02 +#define RADEON_INFO_ACCEL_WORKING 0x03 +#define RADEON_INFO_CRTC_FROM_ID 0x04 +#define RADEON_INFO_ACCEL_WORKING2 0x05 +#define RADEON_INFO_TILING_CONFIG 0x06 +#define RADEON_INFO_WANT_HYPERZ 0x07 +#define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ +#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ +#define RADEON_INFO_NUM_BACKENDS 0x0a /* DB/backends for r600+ - need for OQ */ +#define RADEON_INFO_NUM_TILE_PIPES 0x0b /* tile pipes for r600+ */ +#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ +#define RADEON_INFO_BACKEND_MAP 0x0d /* pipe to backend map, needed by mesa */ +/* virtual address start, va < start are reserved by the kernel */ +#define RADEON_INFO_VA_START 0x0e +/* maximum size of ib using the virtual memory cs */ +#define RADEON_INFO_IB_VM_MAX_SIZE 0x0f +/* max pipes - needed for compute shaders */ +#define RADEON_INFO_MAX_PIPES 0x10 +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ +#define RADEON_INFO_TIMESTAMP 0x11 +/* max shader engines (SE) - needed for geometry shaders, etc. */ +#define RADEON_INFO_MAX_SE 0x12 +/* max SH per SE */ +#define RADEON_INFO_MAX_SH_PER_SE 0x13 +/* fast fb access is enabled */ +#define RADEON_INFO_FASTFB_WORKING 0x14 +/* query if a RADEON_CS_RING_* submission is supported */ +#define RADEON_INFO_RING_WORKING 0x15 +/* SI tile mode array */ +#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16 +/* query if CP DMA is supported on the compute ring */ +#define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17 +/* CIK macrotile mode array */ +#define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY 0x18 +/* query the number of render backends */ +#define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19 +/* max engine clock - needed for OpenCL */ +#define RADEON_INFO_MAX_SCLK 0x1a +/* version of VCE firmware */ +#define RADEON_INFO_VCE_FW_VERSION 0x1b +/* version of VCE feedback */ +#define RADEON_INFO_VCE_FB_VERSION 0x1c +#define RADEON_INFO_NUM_BYTES_MOVED 0x1d +#define RADEON_INFO_VRAM_USAGE 0x1e +#define RADEON_INFO_GTT_USAGE 0x1f +#define RADEON_INFO_ACTIVE_CU_COUNT 0x20 +#define RADEON_INFO_CURRENT_GPU_TEMP 0x21 +#define RADEON_INFO_CURRENT_GPU_SCLK 0x22 +#define RADEON_INFO_CURRENT_GPU_MCLK 0x23 +#define RADEON_INFO_READ_REG 0x24 +#define RADEON_INFO_VA_UNMAP_WORKING 0x25 +#define RADEON_INFO_GPU_RESET_COUNTER 0x26 + +struct drm_radeon_info { + __u32 request; + __u32 pad; + __u64 value; +}; + +/* Those correspond to the tile index to use, this is to explicitly state + * the API that is implicitly defined by the tile mode array. + */ +#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8 +#define SI_TILE_MODE_COLOR_1D 13 +#define SI_TILE_MODE_COLOR_1D_SCANOUT 9 +#define SI_TILE_MODE_COLOR_2D_8BPP 14 +#define SI_TILE_MODE_COLOR_2D_16BPP 15 +#define SI_TILE_MODE_COLOR_2D_32BPP 16 +#define SI_TILE_MODE_COLOR_2D_64BPP 17 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12 +#define SI_TILE_MODE_DEPTH_STENCIL_1D 4 +#define SI_TILE_MODE_DEPTH_STENCIL_2D 0 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2 + +#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5 + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/savage_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/savage_drm.h new file mode 100644 index 0000000..1a91234 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/savage_drm.h @@ -0,0 +1,220 @@ +/* savage_drm.h -- Public header for the savage driver + * + * Copyright 2004 Felix Kuehling + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SAVAGE_DRM_H__ +#define __SAVAGE_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef __SAVAGE_SAREA_DEFINES__ +#define __SAVAGE_SAREA_DEFINES__ + +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define SAVAGE_CARD_HEAP 0 +#define SAVAGE_AGP_HEAP 1 +#define SAVAGE_NR_TEX_HEAPS 2 +#define SAVAGE_NR_TEX_REGIONS 16 +#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16 + +#endif /* __SAVAGE_SAREA_DEFINES__ */ + +typedef struct _drm_savage_sarea { + /* LRU lists for texture memory in agp space and on the card. + */ + struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS + + 1]; + unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_savage_sarea_t, *drm_savage_sarea_ptr; + +/* Savage-specific ioctls + */ +#define DRM_SAVAGE_BCI_INIT 0x00 +#define DRM_SAVAGE_BCI_CMDBUF 0x01 +#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 +#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 + +#define DRM_IOCTL_SAVAGE_BCI_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) +#define DRM_IOCTL_SAVAGE_BCI_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) + +#define SAVAGE_DMA_PCI 1 +#define SAVAGE_DMA_AGP 3 +typedef struct drm_savage_init { + enum { + SAVAGE_INIT_BCI = 1, + SAVAGE_CLEANUP_BCI = 2 + } func; + unsigned int sarea_priv_offset; + + /* some parameters */ + unsigned int cob_size; + unsigned int bci_threshold_lo, bci_threshold_hi; + unsigned int dma_type; + + /* frame buffer layout */ + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + /* local textures */ + unsigned int texture_offset; + unsigned int texture_size; + + /* physical locations of non-permanent maps */ + unsigned long status_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; + unsigned long cmd_dma_offset; +} drm_savage_init_t; + +typedef union drm_savage_cmd_header drm_savage_cmd_header_t; +typedef struct drm_savage_cmdbuf { + /* command buffer in client's address space */ + drm_savage_cmd_header_t *cmd_addr; + unsigned int size; /* size of the command buffer in 64bit units */ + + unsigned int dma_idx; /* DMA buffer index to use */ + int discard; /* discard DMA buffer when done */ + /* vertex buffer in client's address space */ + unsigned int *vb_addr; + unsigned int vb_size; /* size of client vertex buffer in bytes */ + unsigned int vb_stride; /* stride of vertices in 32bit words */ + /* boxes in client's address space */ + struct drm_clip_rect *box_addr; + unsigned int nbox; /* number of clipping boxes */ +} drm_savage_cmdbuf_t; + +#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */ +#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */ +#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */ +typedef struct drm_savage_event { + unsigned int count; + unsigned int flags; +} drm_savage_event_emit_t, drm_savage_event_wait_t; + +/* Commands for the cmdbuf ioctl + */ +#define SAVAGE_CMD_STATE 0 /* a range of state registers */ +#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */ +#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */ +#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */ +#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */ +#define SAVAGE_CMD_CLEAR 5 /* clear buffers */ +#define SAVAGE_CMD_SWAP 6 /* swap buffers */ + +/* Primitive types +*/ +#define SAVAGE_PRIM_TRILIST 0 /* triangle list */ +#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */ +#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */ +#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat + * shading on s3d */ + +/* Skip flags (vertex format) + */ +#define SAVAGE_SKIP_Z 0x01 +#define SAVAGE_SKIP_W 0x02 +#define SAVAGE_SKIP_C0 0x04 +#define SAVAGE_SKIP_C1 0x08 +#define SAVAGE_SKIP_S0 0x10 +#define SAVAGE_SKIP_T0 0x20 +#define SAVAGE_SKIP_ST0 0x30 +#define SAVAGE_SKIP_S1 0x40 +#define SAVAGE_SKIP_T1 0x80 +#define SAVAGE_SKIP_ST1 0xc0 +#define SAVAGE_SKIP_ALL_S3D 0x3f +#define SAVAGE_SKIP_ALL_S4 0xff + +/* Buffer names for clear command + */ +#define SAVAGE_FRONT 0x1 +#define SAVAGE_BACK 0x2 +#define SAVAGE_DEPTH 0x4 + +/* 64-bit command header + */ +union drm_savage_cmd_header { + struct { + unsigned char cmd; /* command */ + unsigned char pad0; + unsigned short pad1; + unsigned short pad2; + unsigned short pad3; + } cmd; /* generic */ + struct { + unsigned char cmd; + unsigned char global; /* need idle engine? */ + unsigned short count; /* number of consecutive registers */ + unsigned short start; /* first register */ + unsigned short pad3; + } state; /* SAVAGE_CMD_STATE */ + struct { + unsigned char cmd; + unsigned char prim; /* primitive type */ + unsigned short skip; /* vertex format (skip flags) */ + unsigned short count; /* number of vertices */ + unsigned short start; /* first vertex in DMA/vertex buffer */ + } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */ + struct { + unsigned char cmd; + unsigned char prim; + unsigned short skip; + unsigned short count; /* number of indices that follow */ + unsigned short pad3; + } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */ + struct { + unsigned char cmd; + unsigned char pad0; + unsigned short pad1; + unsigned int flags; + } clear0; /* SAVAGE_CMD_CLEAR */ + struct { + unsigned int mask; + unsigned int value; + } clear1; /* SAVAGE_CMD_CLEAR data */ +}; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/sis_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/sis_drm.h new file mode 100644 index 0000000..8e51bb9 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/sis_drm.h @@ -0,0 +1,77 @@ +/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ +/* + * Copyright 2005 Eric Anholt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __SIS_DRM_H__ +#define __SIS_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* SiS specific ioctls */ +#define NOT_USED_0_3 +#define DRM_SIS_FB_ALLOC 0x04 +#define DRM_SIS_FB_FREE 0x05 +#define NOT_USED_6_12 +#define DRM_SIS_AGP_INIT 0x13 +#define DRM_SIS_AGP_ALLOC 0x14 +#define DRM_SIS_AGP_FREE 0x15 +#define DRM_SIS_FB_INIT 0x16 + +#define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t) +#define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t) +/* +#define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t) +#define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49) +#define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50) +*/ + +typedef struct { + int context; + unsigned int offset; + unsigned int size; + unsigned long free; +} drm_sis_mem_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_agp_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_fb_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* __SIS_DRM_H__ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/tegra_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/tegra_drm.h new file mode 100644 index 0000000..6c07919 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/tegra_drm.h @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) +#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) + +/** + * struct drm_tegra_gem_create - parameters for the GEM object creation IOCTL + */ +struct drm_tegra_gem_create { + /** + * @size: + * + * The size, in bytes, of the buffer object to be created. + */ + __u64 size; + + /** + * @flags: + * + * A bitmask of flags that influence the creation of GEM objects: + * + * DRM_TEGRA_GEM_CREATE_TILED + * Use the 16x16 tiling format for this buffer. + * + * DRM_TEGRA_GEM_CREATE_BOTTOM_UP + * The buffer has a bottom-up layout. + */ + __u32 flags; + + /** + * @handle: + * + * The handle of the created GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u32 handle; +}; + +/** + * struct drm_tegra_gem_mmap - parameters for the GEM mmap IOCTL + */ +struct drm_tegra_gem_mmap { + /** + * @handle: + * + * Handle of the GEM object to obtain an mmap offset for. + */ + __u32 handle; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; + + /** + * @offset: + * + * The mmap offset for the given GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u64 offset; +}; + +/** + * struct drm_tegra_syncpt_read - parameters for the read syncpoint IOCTL + */ +struct drm_tegra_syncpt_read { + /** + * @id: + * + * ID of the syncpoint to read the current value from. + */ + __u32 id; + + /** + * @value: + * + * The current syncpoint value. Set by the kernel upon successful + * completion of the IOCTL. + */ + __u32 value; +}; + +/** + * struct drm_tegra_syncpt_incr - parameters for the increment syncpoint IOCTL + */ +struct drm_tegra_syncpt_incr { + /** + * @id: + * + * ID of the syncpoint to increment. + */ + __u32 id; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_syncpt_wait - parameters for the wait syncpoint IOCTL + */ +struct drm_tegra_syncpt_wait { + /** + * @id: + * + * ID of the syncpoint to wait on. + */ + __u32 id; + + /** + * @thresh: + * + * Threshold value for which to wait. + */ + __u32 thresh; + + /** + * @timeout: + * + * Timeout, in milliseconds, to wait. + */ + __u32 timeout; + + /** + * @value: + * + * The new syncpoint value after the wait. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u32 value; +}; + +#define DRM_TEGRA_NO_TIMEOUT (0xffffffff) + +/** + * struct drm_tegra_open_channel - parameters for the open channel IOCTL + */ +struct drm_tegra_open_channel { + /** + * @client: + * + * The client ID for this channel. + */ + __u32 client; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; + + /** + * @context: + * + * The application context of this channel. Set by the kernel upon + * successful completion of the IOCTL. This context needs to be passed + * to the DRM_TEGRA_CHANNEL_CLOSE or the DRM_TEGRA_SUBMIT IOCTLs. + */ + __u64 context; +}; + +/** + * struct drm_tegra_close_channel - parameters for the close channel IOCTL + */ +struct drm_tegra_close_channel { + /** + * @context: + * + * The application context of this channel. This is obtained from the + * DRM_TEGRA_OPEN_CHANNEL IOCTL. + */ + __u64 context; +}; + +/** + * struct drm_tegra_get_syncpt - parameters for the get syncpoint IOCTL + */ +struct drm_tegra_get_syncpt { + /** + * @context: + * + * The application context identifying the channel for which to obtain + * the syncpoint ID. + */ + __u64 context; + + /** + * @index: + * + * Index of the client syncpoint for which to obtain the ID. + */ + __u32 index; + + /** + * @id: + * + * The ID of the given syncpoint. Set by the kernel upon successful + * completion of the IOCTL. + */ + __u32 id; +}; + +/** + * struct drm_tegra_get_syncpt_base - parameters for the get wait base IOCTL + */ +struct drm_tegra_get_syncpt_base { + /** + * @context: + * + * The application context identifying for which channel to obtain the + * wait base. + */ + __u64 context; + + /** + * @syncpt: + * + * ID of the syncpoint for which to obtain the wait base. + */ + __u32 syncpt; + + /** + * @id: + * + * The ID of the wait base corresponding to the client syncpoint. Set + * by the kernel upon successful completion of the IOCTL. + */ + __u32 id; +}; + +/** + * struct drm_tegra_syncpt - syncpoint increment operation + */ +struct drm_tegra_syncpt { + /** + * @id: + * + * ID of the syncpoint to operate on. + */ + __u32 id; + + /** + * @incrs: + * + * Number of increments to perform for the syncpoint. + */ + __u32 incrs; +}; + +/** + * struct drm_tegra_cmdbuf - structure describing a command buffer + */ +struct drm_tegra_cmdbuf { + /** + * @handle: + * + * Handle to a GEM object containing the command buffer. + */ + __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, into the GEM object identified by @handle at + * which the command buffer starts. + */ + __u32 offset; + + /** + * @words: + * + * Number of 32-bit words in this command buffer. + */ + __u32 words; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_reloc - GEM object relocation structure + */ +struct drm_tegra_reloc { + struct { + /** + * @cmdbuf.handle: + * + * Handle to the GEM object containing the command buffer for + * which to perform this GEM object relocation. + */ + __u32 handle; + + /** + * @cmdbuf.offset: + * + * Offset, in bytes, into the command buffer at which to + * insert the relocated address. + */ + __u32 offset; + } cmdbuf; + struct { + /** + * @target.handle: + * + * Handle to the GEM object to be relocated. + */ + __u32 handle; + + /** + * @target.offset: + * + * Offset, in bytes, into the target GEM object at which the + * relocated data starts. + */ + __u32 offset; + } target; + + /** + * @shift: + * + * The number of bits by which to shift relocated addresses. + */ + __u32 shift; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_waitchk - wait check structure + */ +struct drm_tegra_waitchk { + /** + * @handle: + * + * Handle to the GEM object containing a command stream on which to + * perform the wait check. + */ + __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, of the location in the command stream to perform + * the wait check on. + */ + __u32 offset; + + /** + * @syncpt: + * + * ID of the syncpoint to wait check. + */ + __u32 syncpt; + + /** + * @thresh: + * + * Threshold value for which to check. + */ + __u32 thresh; +}; + +/** + * struct drm_tegra_submit - job submission structure + */ +struct drm_tegra_submit { + /** + * @context: + * + * The application context identifying the channel to use for the + * execution of this job. + */ + __u64 context; + + /** + * @num_syncpts: + * + * The number of syncpoints operated on by this job. This defines the + * length of the array pointed to by @syncpts. + */ + __u32 num_syncpts; + + /** + * @num_cmdbufs: + * + * The number of command buffers to execute as part of this job. This + * defines the length of the array pointed to by @cmdbufs. + */ + __u32 num_cmdbufs; + + /** + * @num_relocs: + * + * The number of relocations to perform before executing this job. + * This defines the length of the array pointed to by @relocs. + */ + __u32 num_relocs; + + /** + * @num_waitchks: + * + * The number of wait checks to perform as part of this job. This + * defines the length of the array pointed to by @waitchks. + */ + __u32 num_waitchks; + + /** + * @waitchk_mask: + * + * Bitmask of valid wait checks. + */ + __u32 waitchk_mask; + + /** + * @timeout: + * + * Timeout, in milliseconds, before this job is cancelled. + */ + __u32 timeout; + + /** + * @syncpts: + * + * A pointer to an array of &struct drm_tegra_syncpt structures that + * specify the syncpoint operations performed as part of this job. + * The number of elements in the array must be equal to the value + * given by @num_syncpts. + */ + __u64 syncpts; + + /** + * @cmdbufs: + * + * A pointer to an array of &struct drm_tegra_cmdbuf structures that + * define the command buffers to execute as part of this job. The + * number of elements in the array must be equal to the value given + * by @num_syncpts. + */ + __u64 cmdbufs; + + /** + * @relocs: + * + * A pointer to an array of &struct drm_tegra_reloc structures that + * specify the relocations that need to be performed before executing + * this job. The number of elements in the array must be equal to the + * value given by @num_relocs. + */ + __u64 relocs; + + /** + * @waitchks: + * + * A pointer to an array of &struct drm_tegra_waitchk structures that + * specify the wait checks to be performed while executing this job. + * The number of elements in the array must be equal to the value + * given by @num_waitchks. + */ + __u64 waitchks; + + /** + * @fence: + * + * The threshold of the syncpoint associated with this job after it + * has been completed. Set by the kernel upon successful completion of + * the IOCTL. This can be used with the DRM_TEGRA_SYNCPT_WAIT IOCTL to + * wait for this job to be finished. + */ + __u32 fence; + + /** + * @reserved: + * + * This field is reserved for future use. Must be 0. + */ + __u32 reserved[5]; +}; + +#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 +#define DRM_TEGRA_GEM_TILING_MODE_TILED 1 +#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 + +/** + * struct drm_tegra_gem_set_tiling - parameters for the set tiling IOCTL + */ +struct drm_tegra_gem_set_tiling { + /** + * @handle: + * + * Handle to the GEM object for which to set the tiling parameters. + */ + __u32 handle; + + /** + * @mode: + * + * The tiling mode to set. Must be one of: + * + * DRM_TEGRA_GEM_TILING_MODE_PITCH + * pitch linear format + * + * DRM_TEGRA_GEM_TILING_MODE_TILED + * 16x16 tiling format + * + * DRM_TEGRA_GEM_TILING_MODE_BLOCK + * 16Bx2 tiling format + */ + __u32 mode; + + /** + * @value: + * + * The value to set for the tiling mode parameter. + */ + __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_gem_get_tiling - parameters for the get tiling IOCTL + */ +struct drm_tegra_gem_get_tiling { + /** + * @handle: + * + * Handle to the GEM object for which to query the tiling parameters. + */ + __u32 handle; + + /** + * @mode: + * + * The tiling mode currently associated with the GEM object. Set by + * the kernel upon successful completion of the IOCTL. + */ + __u32 mode; + + /** + * @value: + * + * The tiling mode parameter currently associated with the GEM object. + * Set by the kernel upon successful completion of the IOCTL. + */ + __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) +#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) + +/** + * struct drm_tegra_gem_set_flags - parameters for the set flags IOCTL + */ +struct drm_tegra_gem_set_flags { + /** + * @handle: + * + * Handle to the GEM object for which to set the flags. + */ + __u32 handle; + + /** + * @flags: + * + * The flags to set for the GEM object. + */ + __u32 flags; +}; + +/** + * struct drm_tegra_gem_get_flags - parameters for the get flags IOCTL + */ +struct drm_tegra_gem_get_flags { + /** + * @handle: + * + * Handle to the GEM object for which to query the flags. + */ + __u32 handle; + + /** + * @flags: + * + * The flags currently associated with the GEM object. Set by the + * kernel upon successful completion of the IOCTL. + */ + __u32 flags; +}; + +#define DRM_TEGRA_GEM_CREATE 0x00 +#define DRM_TEGRA_GEM_MMAP 0x01 +#define DRM_TEGRA_SYNCPT_READ 0x02 +#define DRM_TEGRA_SYNCPT_INCR 0x03 +#define DRM_TEGRA_SYNCPT_WAIT 0x04 +#define DRM_TEGRA_OPEN_CHANNEL 0x05 +#define DRM_TEGRA_CLOSE_CHANNEL 0x06 +#define DRM_TEGRA_GET_SYNCPT 0x07 +#define DRM_TEGRA_SUBMIT 0x08 +#define DRM_TEGRA_GET_SYNCPT_BASE 0x09 +#define DRM_TEGRA_GEM_SET_TILING 0x0a +#define DRM_TEGRA_GEM_GET_TILING 0x0b +#define DRM_TEGRA_GEM_SET_FLAGS 0x0c +#define DRM_TEGRA_GEM_GET_FLAGS 0x0d + +#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) +#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) +#define DRM_IOCTL_TEGRA_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_READ, struct drm_tegra_syncpt_read) +#define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr) +#define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait) +#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel) +#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) +#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) +#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) +#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) +#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) +#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) +#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/vc4_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/vc4_drm.h new file mode 100644 index 0000000..31f50de --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/vc4_drm.h @@ -0,0 +1,442 @@ +/* + * Copyright © 2014-2015 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _VC4_DRM_H_ +#define _VC4_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_VC4_SUBMIT_CL 0x00 +#define DRM_VC4_WAIT_SEQNO 0x01 +#define DRM_VC4_WAIT_BO 0x02 +#define DRM_VC4_CREATE_BO 0x03 +#define DRM_VC4_MMAP_BO 0x04 +#define DRM_VC4_CREATE_SHADER_BO 0x05 +#define DRM_VC4_GET_HANG_STATE 0x06 +#define DRM_VC4_GET_PARAM 0x07 +#define DRM_VC4_SET_TILING 0x08 +#define DRM_VC4_GET_TILING 0x09 +#define DRM_VC4_LABEL_BO 0x0a +#define DRM_VC4_GEM_MADVISE 0x0b +#define DRM_VC4_PERFMON_CREATE 0x0c +#define DRM_VC4_PERFMON_DESTROY 0x0d +#define DRM_VC4_PERFMON_GET_VALUES 0x0e + +#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) +#define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) +#define DRM_IOCTL_VC4_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_BO, struct drm_vc4_wait_bo) +#define DRM_IOCTL_VC4_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_BO, struct drm_vc4_create_bo) +#define DRM_IOCTL_VC4_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_MMAP_BO, struct drm_vc4_mmap_bo) +#define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo) +#define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state) +#define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param) +#define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling) +#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling) +#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo) +#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise) +#define DRM_IOCTL_VC4_PERFMON_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_CREATE, struct drm_vc4_perfmon_create) +#define DRM_IOCTL_VC4_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_DESTROY, struct drm_vc4_perfmon_destroy) +#define DRM_IOCTL_VC4_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_GET_VALUES, struct drm_vc4_perfmon_get_values) + +struct drm_vc4_submit_rcl_surface { + __u32 hindex; /* Handle index, or ~0 if not present. */ + __u32 offset; /* Offset to start of buffer. */ + /* + * Bits for either render config (color_write) or load/store packet. + * Bits should all be 0 for MSAA load/stores. + */ + __u16 bits; + +#define VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES (1 << 0) + __u16 flags; +}; + +/** + * struct drm_vc4_submit_cl - ioctl argument for submitting commands to the 3D + * engine. + * + * Drivers typically use GPU BOs to store batchbuffers / command lists and + * their associated state. However, because the VC4 lacks an MMU, we have to + * do validation of memory accesses by the GPU commands. If we were to store + * our commands in BOs, we'd need to do uncached readback from them to do the + * validation process, which is too expensive. Instead, userspace accumulates + * commands and associated state in plain memory, then the kernel copies the + * data to its own address space, and then validates and stores it in a GPU + * BO. + */ +struct drm_vc4_submit_cl { + /* Pointer to the binner command list. + * + * This is the first set of commands executed, which runs the + * coordinate shader to determine where primitives land on the screen, + * then writes out the state updates and draw calls necessary per tile + * to the tile allocation BO. + */ + __u64 bin_cl; + + /* Pointer to the shader records. + * + * Shader records are the structures read by the hardware that contain + * pointers to uniforms, shaders, and vertex attributes. The + * reference to the shader record has enough information to determine + * how many pointers are necessary (fixed number for shaders/uniforms, + * and an attribute count), so those BO indices into bo_handles are + * just stored as __u32s before each shader record passed in. + */ + __u64 shader_rec; + + /* Pointer to uniform data and texture handles for the textures + * referenced by the shader. + * + * For each shader state record, there is a set of uniform data in the + * order referenced by the record (FS, VS, then CS). Each set of + * uniform data has a __u32 index into bo_handles per texture + * sample operation, in the order the QPU_W_TMUn_S writes appear in + * the program. Following the texture BO handle indices is the actual + * uniform data. + * + * The individual uniform state blocks don't have sizes passed in, + * because the kernel has to determine the sizes anyway during shader + * code validation. + */ + __u64 uniforms; + __u64 bo_handles; + + /* Size in bytes of the binner command list. */ + __u32 bin_cl_size; + /* Size in bytes of the set of shader records. */ + __u32 shader_rec_size; + /* Number of shader records. + * + * This could just be computed from the contents of shader_records and + * the address bits of references to them from the bin CL, but it + * keeps the kernel from having to resize some allocations it makes. + */ + __u32 shader_rec_count; + /* Size in bytes of the uniform state. */ + __u32 uniforms_size; + + /* Number of BO handles passed in (size is that times 4). */ + __u32 bo_handle_count; + + /* RCL setup: */ + __u16 width; + __u16 height; + __u8 min_x_tile; + __u8 min_y_tile; + __u8 max_x_tile; + __u8 max_y_tile; + struct drm_vc4_submit_rcl_surface color_read; + struct drm_vc4_submit_rcl_surface color_write; + struct drm_vc4_submit_rcl_surface zs_read; + struct drm_vc4_submit_rcl_surface zs_write; + struct drm_vc4_submit_rcl_surface msaa_color_write; + struct drm_vc4_submit_rcl_surface msaa_zs_write; + __u32 clear_color[2]; + __u32 clear_z; + __u8 clear_s; + + __u32 pad:24; + +#define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0) +/* By default, the kernel gets to choose the order that the tiles are + * rendered in. If this is set, then the tiles will be rendered in a + * raster order, with the right-to-left vs left-to-right and + * top-to-bottom vs bottom-to-top dictated by + * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*. This allows overlapping + * blits to be implemented using the 3D engine. + */ +#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3) + __u32 flags; + + /* Returned value of the seqno of this render job (for the + * wait ioctl). + */ + __u64 seqno; + + /* ID of the perfmon to attach to this job. 0 means no perfmon. */ + __u32 perfmonid; + + /* Syncobj handle to wait on. If set, processing of this render job + * will not start until the syncobj is signaled. 0 means ignore. + */ + __u32 in_sync; + + /* Syncobj handle to export fence to. If set, the fence in the syncobj + * will be replaced with a fence that signals upon completion of this + * render job. 0 means ignore. + */ + __u32 out_sync; + + __u32 pad2; +}; + +/** + * struct drm_vc4_wait_seqno - ioctl argument for waiting for + * DRM_VC4_SUBMIT_CL completion using its returned seqno. + * + * timeout_ns is the timeout in nanoseconds, where "0" means "don't + * block, just return the status." + */ +struct drm_vc4_wait_seqno { + __u64 seqno; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_wait_bo - ioctl argument for waiting for + * completion of the last DRM_VC4_SUBMIT_CL on a BO. + * + * This is useful for cases where multiple processes might be + * rendering to a BO and you want to wait for all rendering to be + * completed. + */ +struct drm_vc4_wait_bo { + __u32 handle; + __u32 pad; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_create_bo - ioctl argument for creating VC4 BOs. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_create_bo { + __u32 size; + __u32 flags; + /** Returned GEM handle for the BO. */ + __u32 handle; + __u32 pad; +}; + +/** + * struct drm_vc4_mmap_bo - ioctl argument for mapping VC4 BOs. + * + * This doesn't actually perform an mmap. Instead, it returns the + * offset you need to use in an mmap on the DRM device node. This + * means that tools like valgrind end up knowing about the mapped + * memory. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_mmap_bo { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 flags; + /** offset into the drm node to use for subsequent mmap call. */ + __u64 offset; +}; + +/** + * struct drm_vc4_create_shader_bo - ioctl argument for creating VC4 + * shader BOs. + * + * Since allowing a shader to be overwritten while it's also being + * executed from would allow privlege escalation, shaders must be + * created using this ioctl, and they can't be mmapped later. + */ +struct drm_vc4_create_shader_bo { + /* Size of the data argument. */ + __u32 size; + /* Flags, currently must be 0. */ + __u32 flags; + + /* Pointer to the data. */ + __u64 data; + + /** Returned GEM handle for the BO. */ + __u32 handle; + /* Pad, must be 0. */ + __u32 pad; +}; + +struct drm_vc4_get_hang_state_bo { + __u32 handle; + __u32 paddr; + __u32 size; + __u32 pad; +}; + +/** + * struct drm_vc4_hang_state - ioctl argument for collecting state + * from a GPU hang for analysis. +*/ +struct drm_vc4_get_hang_state { + /** Pointer to array of struct drm_vc4_get_hang_state_bo. */ + __u64 bo; + /** + * On input, the size of the bo array. Output is the number + * of bos to be returned. + */ + __u32 bo_count; + + __u32 start_bin, start_render; + + __u32 ct0ca, ct0ea; + __u32 ct1ca, ct1ea; + __u32 ct0cs, ct1cs; + __u32 ct0ra0, ct1ra0; + + __u32 bpca, bpcs; + __u32 bpoa, bpos; + + __u32 vpmbase; + + __u32 dbge; + __u32 fdbgo; + __u32 fdbgb; + __u32 fdbgr; + __u32 fdbgs; + __u32 errstat; + + /* Pad that we may save more registers into in the future. */ + __u32 pad[16]; +}; + +#define DRM_VC4_PARAM_V3D_IDENT0 0 +#define DRM_VC4_PARAM_V3D_IDENT1 1 +#define DRM_VC4_PARAM_V3D_IDENT2 2 +#define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 +#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 +#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 +#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6 +#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7 +#define DRM_VC4_PARAM_SUPPORTS_PERFMON 8 + +struct drm_vc4_get_param { + __u32 param; + __u32 pad; + __u64 value; +}; + +struct drm_vc4_get_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +struct drm_vc4_set_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +/** + * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes. + */ +struct drm_vc4_label_bo { + __u32 handle; + __u32 len; + __u64 name; +}; + +/* + * States prefixed with '__' are internal states and cannot be passed to the + * DRM_IOCTL_VC4_GEM_MADVISE ioctl. + */ +#define VC4_MADV_WILLNEED 0 +#define VC4_MADV_DONTNEED 1 +#define __VC4_MADV_PURGED 2 +#define __VC4_MADV_NOTSUPP 3 + +struct drm_vc4_gem_madvise { + __u32 handle; + __u32 madv; + __u32 retained; + __u32 pad; +}; + +enum { + VC4_PERFCNT_FEP_VALID_PRIMS_NO_RENDER, + VC4_PERFCNT_FEP_VALID_PRIMS_RENDER, + VC4_PERFCNT_FEP_CLIPPED_QUADS, + VC4_PERFCNT_FEP_VALID_QUADS, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_STENCIL, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_NON_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_WRITTEN_TO_COLOR_BUF, + VC4_PERFCNT_PLB_PRIMS_OUTSIDE_VIEWPORT, + VC4_PERFCNT_PLB_PRIMS_NEED_CLIPPING, + VC4_PERFCNT_PSE_PRIMS_REVERSED, + VC4_PERFCNT_QPU_TOTAL_IDLE_CYCLES, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_VERTEX_COORD_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_FRAGMENT_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_EXEC_VALID_INST, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_TMUS, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_SCOREBOARD, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_VARYINGS, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_MISS, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_MISS, + VC4_PERFCNT_TMU_TOTAL_TEXT_QUADS_PROCESSED, + VC4_PERFCNT_TMU_TOTAL_TEXT_CACHE_MISS, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VDW_STALLED, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VCD_STALLED, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_HIT, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_MISS, + VC4_PERFCNT_NUM_EVENTS, +}; + +#define DRM_VC4_MAX_PERF_COUNTERS 16 + +struct drm_vc4_perfmon_create { + __u32 id; + __u32 ncounters; + __u8 events[DRM_VC4_MAX_PERF_COUNTERS]; +}; + +struct drm_vc4_perfmon_destroy { + __u32 id; +}; + +/* + * Returns the values of the performance counters tracked by this + * perfmon (as an array of ncounters u64 values). + * + * No implicit synchronization is performed, so the user has to + * guarantee that any jobs using this perfmon have already been + * completed (probably by blocking on the seqno returned by the + * last exec that used the perfmon). + */ +struct drm_vc4_perfmon_get_values { + __u32 id; + __u64 values_ptr; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _VC4_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/via_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/via_drm.h new file mode 100644 index 0000000..8b69e81 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/via_drm.h @@ -0,0 +1,283 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_DRM_H_ +#define _VIA_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_DEFINES_ +#define _VIA_DEFINES_ + +#include "via_drmclient.h" + +#define VIA_NR_SAREA_CLIPRECTS 8 +#define VIA_NR_XVMC_PORTS 10 +#define VIA_NR_XVMC_LOCKS 5 +#define VIA_MAX_CACHELINE_SIZE 64 +#define XVMCLOCKPTR(saPriv,lockNo) \ + ((__volatile__ struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ + (VIA_MAX_CACHELINE_SIZE - 1)) & \ + ~(VIA_MAX_CACHELINE_SIZE - 1)) + \ + VIA_MAX_CACHELINE_SIZE*(lockNo))) + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_NR_TEX_REGIONS 64 +#define VIA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_UPLOAD_CTX 0x4 +#define VIA_UPLOAD_BUFFERS 0x8 +#define VIA_UPLOAD_TEX0 0x10 +#define VIA_UPLOAD_TEX1 0x20 +#define VIA_UPLOAD_CLIPRECTS 0x40 +#define VIA_UPLOAD_ALL 0xff + +/* VIA specific ioctls */ +#define DRM_VIA_ALLOCMEM 0x00 +#define DRM_VIA_FREEMEM 0x01 +#define DRM_VIA_AGP_INIT 0x02 +#define DRM_VIA_FB_INIT 0x03 +#define DRM_VIA_MAP_INIT 0x04 +#define DRM_VIA_DEC_FUTEX 0x05 +#define NOT_USED +#define DRM_VIA_DMA_INIT 0x07 +#define DRM_VIA_CMDBUFFER 0x08 +#define DRM_VIA_FLUSH 0x09 +#define DRM_VIA_PCICMD 0x0a +#define DRM_VIA_CMDBUF_SIZE 0x0b +#define NOT_USED +#define DRM_VIA_WAIT_IRQ 0x0d +#define DRM_VIA_DMA_BLIT 0x0e +#define DRM_VIA_BLIT_SYNC 0x0f + +#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t) +#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t) +#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t) +#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t) +#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t) +#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t) +#define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t) +#define DRM_IOCTL_VIA_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t) +#define DRM_IOCTL_VIA_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_VIA_FLUSH) +#define DRM_IOCTL_VIA_PCICMD DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t) +#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \ + drm_via_cmdbuf_size_t) +#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t) +#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t) +#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t) + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_FRONT 0x1 +#define VIA_BACK 0x2 +#define VIA_DEPTH 0x4 +#define VIA_STENCIL 0x8 +#define VIA_MEM_VIDEO 0 /* matches drm constant */ +#define VIA_MEM_AGP 1 /* matches drm constant */ +#define VIA_MEM_SYSTEM 2 +#define VIA_MEM_MIXED 3 +#define VIA_MEM_UNKNOWN 4 + +typedef struct { + __u32 offset; + __u32 size; +} drm_via_agp_t; + +typedef struct { + __u32 offset; + __u32 size; +} drm_via_fb_t; + +typedef struct { + __u32 context; + __u32 type; + __u32 size; + unsigned long index; + unsigned long offset; +} drm_via_mem_t; + +typedef struct _drm_via_init { + enum { + VIA_INIT_MAP = 0x01, + VIA_CLEANUP_MAP = 0x02 + } func; + + unsigned long sarea_priv_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long agpAddr; +} drm_via_init_t; + +typedef struct _drm_via_futex { + enum { + VIA_FUTEX_WAIT = 0x00, + VIA_FUTEX_WAKE = 0X01 + } func; + __u32 ms; + __u32 lock; + __u32 val; +} drm_via_futex_t; + +typedef struct _drm_via_dma_init { + enum { + VIA_INIT_DMA = 0x01, + VIA_CLEANUP_DMA = 0x02, + VIA_DMA_INITIALIZED = 0x03 + } func; + + unsigned long offset; + unsigned long size; + unsigned long reg_pause_addr; +} drm_via_dma_init_t; + +typedef struct _drm_via_cmdbuffer { + char *buf; + unsigned long size; +} drm_via_cmdbuffer_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_via_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_via_tex_region_t; + +typedef struct _drm_via_sarea { + unsigned int dirty; + unsigned int nbox; + struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS]; + drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1]; + int texAge; /* last time texture was uploaded */ + int ctxOwner; /* last context to upload state */ + int vertexPrim; + + /* + * Below is for XvMC. + * We want the lock integers alone on, and aligned to, a cache line. + * Therefore this somewhat strange construct. + */ + + char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)]; + + unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS]; + unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS]; + unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ + + /* Used by the 3d driver only at this point, for pageflipping: + */ + unsigned int pfCurrentOffset; +} drm_via_sarea_t; + +typedef struct _drm_via_cmdbuf_size { + enum { + VIA_CMDBUF_SPACE = 0x01, + VIA_CMDBUF_LAG = 0x02 + } func; + int wait; + __u32 size; +} drm_via_cmdbuf_size_t; + +typedef enum { + VIA_IRQ_ABSOLUTE = 0x0, + VIA_IRQ_RELATIVE = 0x1, + VIA_IRQ_SIGNAL = 0x10000000, + VIA_IRQ_FORCE_SEQUENCE = 0x20000000 +} via_irq_seq_type_t; + +#define VIA_IRQ_FLAGS_MASK 0xF0000000 + +enum drm_via_irqs { + drm_via_irq_hqv0 = 0, + drm_via_irq_hqv1, + drm_via_irq_dma0_dd, + drm_via_irq_dma0_td, + drm_via_irq_dma1_dd, + drm_via_irq_dma1_td, + drm_via_irq_num +}; + +struct drm_via_wait_irq_request { + unsigned irq; + via_irq_seq_type_t type; + __u32 sequence; + __u32 signal; +}; + +typedef union drm_via_irqwait { + struct drm_via_wait_irq_request request; + struct drm_wait_vblank_reply reply; +} drm_via_irqwait_t; + +typedef struct drm_via_blitsync { + __u32 sync_handle; + unsigned engine; +} drm_via_blitsync_t; + +/* - * Below,"flags" is currently unused but will be used for possible future + * extensions like kernel space bounce buffers for bad alignments and + * blit engine busy-wait polling for better latency in the absence of + * interrupts. + */ + +typedef struct drm_via_dmablit { + __u32 num_lines; + __u32 line_length; + + __u32 fb_addr; + __u32 fb_stride; + + unsigned char *mem_addr; + __u32 mem_stride; + + __u32 flags; + int to_fb; + + drm_via_blitsync_t sync; +} drm_via_dmablit_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* _VIA_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/virtgpu_drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/virtgpu_drm.h new file mode 100644 index 0000000..f06a789 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/virtgpu_drm.h @@ -0,0 +1,182 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRTGPU_DRM_H +#define VIRTGPU_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define DRM_VIRTGPU_MAP 0x01 +#define DRM_VIRTGPU_EXECBUFFER 0x02 +#define DRM_VIRTGPU_GETPARAM 0x03 +#define DRM_VIRTGPU_RESOURCE_CREATE 0x04 +#define DRM_VIRTGPU_RESOURCE_INFO 0x05 +#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06 +#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07 +#define DRM_VIRTGPU_WAIT 0x08 +#define DRM_VIRTGPU_GET_CAPS 0x09 + +#define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01 +#define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02 +#define VIRTGPU_EXECBUF_FLAGS (\ + VIRTGPU_EXECBUF_FENCE_FD_IN |\ + VIRTGPU_EXECBUF_FENCE_FD_OUT |\ + 0) + +struct drm_virtgpu_map { + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; +}; + +struct drm_virtgpu_execbuffer { + __u32 flags; + __u32 size; + __u64 command; /* void* */ + __u64 bo_handles; + __u32 num_bo_handles; + __s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */ +}; + +#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ +#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */ + +struct drm_virtgpu_getparam { + __u64 param; + __u64 value; +}; + +/* NO_BO flags? NO resource flag? */ +/* resource flag for y_0_top */ +struct drm_virtgpu_resource_create { + __u32 target; + __u32 format; + __u32 bind; + __u32 width; + __u32 height; + __u32 depth; + __u32 array_size; + __u32 last_level; + __u32 nr_samples; + __u32 flags; + __u32 bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ + __u32 res_handle; /* returned by kernel */ + __u32 size; /* validate transfer in the host */ + __u32 stride; /* validate transfer in the host */ +}; + +struct drm_virtgpu_resource_info { + __u32 bo_handle; + __u32 res_handle; + __u32 size; + __u32 stride; +}; + +struct drm_virtgpu_3d_box { + __u32 x; + __u32 y; + __u32 z; + __u32 w; + __u32 h; + __u32 d; +}; + +struct drm_virtgpu_3d_transfer_to_host { + __u32 bo_handle; + struct drm_virtgpu_3d_box box; + __u32 level; + __u32 offset; +}; + +struct drm_virtgpu_3d_transfer_from_host { + __u32 bo_handle; + struct drm_virtgpu_3d_box box; + __u32 level; + __u32 offset; +}; + +#define VIRTGPU_WAIT_NOWAIT 1 /* like it */ +struct drm_virtgpu_3d_wait { + __u32 handle; /* 0 is an invalid handle */ + __u32 flags; +}; + +struct drm_virtgpu_get_caps { + __u32 cap_set_id; + __u32 cap_set_ver; + __u64 addr; + __u32 size; + __u32 pad; +}; + +#define DRM_IOCTL_VIRTGPU_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) + +#define DRM_IOCTL_VIRTGPU_EXECBUFFER \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\ + struct drm_virtgpu_execbuffer) + +#define DRM_IOCTL_VIRTGPU_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\ + struct drm_virtgpu_getparam) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, \ + struct drm_virtgpu_resource_create) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \ + struct drm_virtgpu_resource_info) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST, \ + struct drm_virtgpu_3d_transfer_from_host) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST, \ + struct drm_virtgpu_3d_transfer_to_host) + +#define DRM_IOCTL_VIRTGPU_WAIT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT, \ + struct drm_virtgpu_3d_wait) + +#define DRM_IOCTL_VIRTGPU_GET_CAPS \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ + struct drm_virtgpu_get_caps) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/tool.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/tool.h new file mode 100644 index 0000000..c7b334d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/tool.h @@ -0,0 +1,145 @@ +/* + + */ + +#ifndef TOOL_H_ +#define TOOL_H_ +//ڴ˴ͷļ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define YUV420 0 +#define YUV422 YUV420 + 1 +#define YUV444 YUV422 + 1 +/************************************************************* +Function: ReadBmpFile +Description: ȡbmpͼڴ +Input: pFilePathbmp· + pDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgrrgbֵΪ8bit + widthͼ + heightͼ +Output: +*************************************************************/ +extern void ReadBmpFile(char *pFilePath, unsigned char *pData, int & width, int & height); +/************************************************************* +Function: SaveBmpFile +Description: rgbͼݱΪbmp +Input: pFilePathbmp· + pDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgrrgbֵΪ8bit + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveBmpFile(char *pFilePath, unsigned char *pData, int width, int height); +/************************************************************* +Function: SaveRaw +Description: rawͼ +Input: pSavePathraw· + pDataraw + widthrawͼ + heightrawͼ +Output: +*************************************************************/ +extern void SaveRaw(char *pSavePath, short *pRawData, int width, int height); + +extern void SaveRaw32bit(char *pSavePath, long *pRawData, int width, int height); + +/************************************************************* +Function: SaveBmpFile2 +Description: λ8bitbmpͼ +Input: pFilePathbmp· + widthͼ + heightͼ + bitValueͼλ + pRGBDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgr +Output: +*************************************************************/ +extern void SaveBmpFile2(char *pFilePath, int width, int height, int bitValue, short *pRGBData); + +/************************************************************* +Function: SaveYUVData +Description: 8bit YUVͼ +Input: pSavePath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData(char *pSavePath, unsigned char *pData, int width, int height); + + + +/************************************************************* +Function: SaveYUVData2 +Description: λ8bitYUVͼ +Input: pSavePath· + pDatayuvݣλ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData2(char *pSavePath, short *pData, int width, int height, int bitValue); +/************************************************************* +Function: SaveYUVData1 +Description: 8bit YUV420ͼ +Input: pSavePath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData1(char *pSavePath, unsigned char *pData, int width, int height, int fmt); +/************************************************************* +Function: ReadYUVData1 +Description: ȡ8bit YUV420ͼ +Input: pReadPath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void ReadYUVData1(char *pReadPath, unsigned char *pData, int width, int height, int fmt); +/************************************************************* +Function: Yuvfmtconv +Description: yuv fmt conversion.444 420 422 to 444 420 422 +Input: pDatain 뻺 + pDataout + width + height + fmt_in ʽ + fmt_out ʽ +Output: +*************************************************************/ +extern void Yuvfmtconv(void *pDatain, void *pDataout, int width, int height, int fmt_in, int fmt_out, int size); +/************************************************************* +Function: Yuvbitstochar +Description: save yuv to 8 bitdepth +Input: pDatain 뻺 + pDataout + size yuv + height λ +Output: +*************************************************************/ +extern void Yuvbitstochar(short *pDatain, unsigned char *pDataout, int size, int bitdepth); + +/************************************************************* +Function: SaveCfaBmp +Description: rawcfaͼ +Input: pRawDatarawͼ + widthrawͼ + heightrawͼߣ + bayerPatternbayer patternʽȡֵΧ[03] + bitValuerawλ +Output: +*************************************************************/ +extern void SaveCfaBmp(char *pFilePath, short *pRawData, int width, int height, int bayerPattern, int bitValue); + +#ifdef __cplusplus +} +#endif + +#endif // TOOL_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/xf86drm.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/xf86drm.h new file mode 100644 index 0000000..d86428a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/xf86drm.h @@ -0,0 +1,930 @@ +/** + * \file xf86drm.h + * OS-independent header for DRM user-level library interface. + * + * \author Rickard E. (Rik) Faith + */ + +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _XF86DRM_H_ +#define _XF86DRM_H_ + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef DRM_MAX_MINOR +#define DRM_MAX_MINOR 16 +#endif + +#if defined(__linux__) + +#define DRM_IOCTL_NR(n) _IOC_NR(n) +#define DRM_IOC_VOID _IOC_NONE +#define DRM_IOC_READ _IOC_READ +#define DRM_IOC_WRITE _IOC_WRITE +#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) + +#else /* One of the *BSDs */ + +#include +#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define DRM_IOC_VOID IOC_VOID +#define DRM_IOC_READ IOC_OUT +#define DRM_IOC_WRITE IOC_IN +#define DRM_IOC_READWRITE IOC_INOUT +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) + +#endif + + /* Defaults, if nothing set in xf86config */ +#define DRM_DEV_UID 0 +#define DRM_DEV_GID 0 +/* Default /dev/dri directory permissions 0755 */ +#define DRM_DEV_DIRMODE \ + (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) +#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + +#ifdef __OpenBSD__ +#define DRM_DIR_NAME "/dev" +#define DRM_PRIMARY_MINOR_NAME "drm" +#define DRM_CONTROL_MINOR_NAME "drmC" +#define DRM_RENDER_MINOR_NAME "drmR" +#else +#define DRM_DIR_NAME "/dev/dri" +#define DRM_PRIMARY_MINOR_NAME "card" +#define DRM_CONTROL_MINOR_NAME "controlD" +#define DRM_RENDER_MINOR_NAME "renderD" +#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ +#endif + +#define DRM_DEV_NAME "%s/" DRM_PRIMARY_MINOR_NAME "%d" +#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d" +#define DRM_RENDER_DEV_NAME "%s/" DRM_RENDER_MINOR_NAME "%d" + +#define DRM_NODE_NAME_MAX \ + (sizeof(DRM_DIR_NAME) + 1 /* slash */ \ + + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \ + sizeof(DRM_CONTROL_MINOR_NAME), \ + sizeof(DRM_RENDER_MINOR_NAME)) \ + + sizeof("144") /* highest possible node number */ \ + + 1) /* NULL-terminator */ + +#define DRM_ERR_NO_DEVICE (-1001) +#define DRM_ERR_NO_ACCESS (-1002) +#define DRM_ERR_NOT_ROOT (-1003) +#define DRM_ERR_INVALID (-1004) +#define DRM_ERR_NO_FD (-1005) + +#define DRM_AGP_NO_HANDLE 0 + +typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ +typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ + +#if (__GNUC__ >= 3) +#define DRM_PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) +#else +#define DRM_PRINTFLIKE(f, a) +#endif + +typedef struct _drmServerInfo { + int (*debug_print)(const char *format, va_list ap) DRM_PRINTFLIKE(1,0); + int (*load_module)(const char *name); + void (*get_perms)(gid_t *, mode_t *); +} drmServerInfo, *drmServerInfoPtr; + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +extern int drmIoctl(int fd, unsigned long request, void *arg); +extern void *drmGetHashTable(void); +extern drmHashEntry *drmGetEntry(int fd); + +/** + * Driver version information. + * + * \sa drmGetVersion() and drmSetVersion(). + */ +typedef struct _drmVersion { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + int name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + int date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + int desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +} drmVersion, *drmVersionPtr; + +typedef struct _drmStats { + unsigned long count; /**< Number of data */ + struct { + unsigned long value; /**< Value from kernel */ + const char *long_format; /**< Suggested format for long_name */ + const char *long_name; /**< Long name for value */ + const char *rate_format; /**< Suggested format for rate_name */ + const char *rate_name; /**< Short name for value per second */ + int isvalue; /**< True if value (vs. counter) */ + const char *mult_names; /**< Multiplier names (e.g., "KGM") */ + int mult; /**< Multiplier value (e.g., 1024) */ + int verbose; /**< Suggest only in verbose output */ + } data[15]; +} drmStatsT; + + + /* All of these enums *MUST* match with the + kernel implementation -- so do *NOT* + change them! (The drmlib implementation + will just copy the flags instead of + translating them.) */ +typedef enum { + DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */ + DRM_REGISTERS = 1, /**< no caching, no core dump */ + DRM_SHM = 2, /**< shared, cached */ + DRM_AGP = 3, /**< AGP/GART */ + DRM_SCATTER_GATHER = 4, /**< PCI scatter/gather */ + DRM_CONSISTENT = 5 /**< PCI consistent */ +} drmMapType; + +typedef enum { + DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */ + DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */ + DRM_LOCKED = 0x0004, /**< Physical pages locked */ + DRM_KERNEL = 0x0008, /**< Kernel requires access */ + DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */ + DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */ + DRM_REMOVABLE = 0x0040 /**< Removable mapping */ +} drmMapFlags; + +/** + * \warning These values *MUST* match drm.h + */ +typedef enum { + /** \name Flags for DMA buffer dispatch */ + /*@{*/ + DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note the buffer may not yet have been + * processed by the hardware -- getting a + * hardware lock with the hardware quiescent + * will ensure that the buffer has been + * processed. + */ + DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + /*@}*/ + + /** \name Flags for DMA buffer request */ + /*@{*/ + DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ + /*@}*/ +} drmDMAFlags; + +typedef enum { + DRM_PAGE_ALIGN = 0x01, + DRM_AGP_BUFFER = 0x02, + DRM_SG_BUFFER = 0x04, + DRM_FB_BUFFER = 0x08, + DRM_PCI_BUFFER_RO = 0x10 +} drmBufDescFlags; + +typedef enum { + DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +} drmLockFlags; + +typedef enum { + DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and + never swapped. */ + DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */ +} drm_context_tFlags, *drm_context_tFlagsPtr; + +typedef struct _drmBufDesc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ +} drmBufDesc, *drmBufDescPtr; + +typedef struct _drmBufInfo { + int count; /**< Number of buffers described in list */ + drmBufDescPtr list; /**< List of buffer descriptions */ +} drmBufInfo, *drmBufInfoPtr; + +typedef struct _drmBuf { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + drmAddress address; /**< Address */ +} drmBuf, *drmBufPtr; + +/** + * Buffer mapping information. + * + * Used by drmMapBufs() and drmUnmapBufs() to store information about the + * mapped buffers. + */ +typedef struct _drmBufMap { + int count; /**< Number of buffers mapped */ + drmBufPtr list; /**< Buffers */ +} drmBufMap, *drmBufMapPtr; + +typedef struct _drmLock { + volatile unsigned int lock; + char padding[60]; + /* This is big enough for most current (and future?) architectures: + DEC Alpha: 32 bytes + Intel Merced: ? + Intel P5/PPro/PII/PIII: 32 bytes + Intel StrongARM: 32 bytes + Intel i386/i486: 16 bytes + MIPS: 32 bytes (?) + Motorola 68k: 16 bytes + Motorola PowerPC: 32 bytes + Sun SPARC: 32 bytes + */ +} drmLock, *drmLockPtr; + +/** + * Indices here refer to the offset into + * list in drmBufInfo + */ +typedef struct _drmDMAReq { + drm_context_t context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_list; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send, in bytes */ + drmDMAFlags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size of buffers requested */ + int *request_list; /**< Buffer information */ + int *request_sizes; /**< Minimum acceptable sizes */ + int granted_count; /**< Number of buffers granted at this size */ +} drmDMAReq, *drmDMAReqPtr; + +typedef struct _drmRegion { + drm_handle_t handle; + unsigned int offset; + drmSize size; + drmAddress map; +} drmRegion, *drmRegionPtr; + +typedef struct _drmTextureRegion { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; /**< Explicitly pad this out */ + unsigned int age; +} drmTextureRegion, *drmTextureRegionPtr; + + +typedef enum { + DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drmVBlankSeqType; +#define DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +typedef struct _drmVBlankReq { + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq, *drmVBlankReqPtr; + +typedef struct _drmVBlankReply { + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec; + long tval_usec; +} drmVBlankReply, *drmVBlankReplyPtr; + +typedef union _drmVBlank { + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank, *drmVBlankPtr; + +typedef struct _drmSetVersion { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drmSetVersion, *drmSetVersionPtr; + +#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) + +#define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ + +#if defined(__GNUC__) && (__GNUC__ >= 2) +# if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__) + /* Reflect changes here to drmP.h */ +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + int __dummy; /* Can't mark eax as clobbered */ \ + __asm__ __volatile__( \ + "lock ; cmpxchg %4,%1\n\t" \ + "setnz %0" \ + : "=d" (__ret), \ + "=m" (__drm_dummy_lock(lock)), \ + "=a" (__dummy) \ + : "2" (old), \ + "r" (new)); \ + } while (0) + +#elif defined(__alpha__) + +#define DRM_CAS(lock, old, new, ret) \ + do { \ + int tmp, old32; \ + __asm__ __volatile__( \ + " addl $31, %5, %3\n" \ + "1: ldl_l %0, %2\n" \ + " cmpeq %0, %3, %1\n" \ + " beq %1, 2f\n" \ + " mov %4, %0\n" \ + " stl_c %0, %2\n" \ + " beq %0, 3f\n" \ + " mb\n" \ + "2: cmpeq %1, 0, %1\n" \ + ".subsection 2\n" \ + "3: br 1b\n" \ + ".previous" \ + : "=&r"(tmp), "=&r"(ret), \ + "=m"(__drm_dummy_lock(lock)), \ + "=&r"(old32) \ + : "r"(new), "r"(old) \ + : "memory"); \ + } while (0) + +#elif defined(__sparc__) + +#define DRM_CAS(lock,old,new,__ret) \ +do { register unsigned int __old __asm("o0"); \ + register unsigned int __new __asm("o1"); \ + register volatile unsigned int *__lock __asm("o2"); \ + __old = old; \ + __new = new; \ + __lock = (volatile unsigned int *)lock; \ + __asm__ __volatile__( \ + /*"cas [%2], %3, %0"*/ \ + ".word 0xd3e29008\n\t" \ + /*"membar #StoreStore | #StoreLoad"*/ \ + ".word 0x8143e00a" \ + : "=&r" (__new) \ + : "0" (__new), \ + "r" (__lock), \ + "r" (__old) \ + : "memory"); \ + __ret = (__new != __old); \ +} while(0) + +#elif defined(__ia64__) + +#ifdef __INTEL_COMPILER +/* this currently generates bad code (missing stop bits)... */ +#include + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned long __result, __old = (old) & 0xffffffff; \ + __mf(); \ + __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\ + __ret = (__result) != (__old); \ +/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ + (old), (new)) \ + != (old)); */\ + } while (0) + +#else +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned int __result, __old = (old); \ + __asm__ __volatile__( \ + "mf\n" \ + "mov ar.ccv=%2\n" \ + ";;\n" \ + "cmpxchg4.acq %0=%1,%3,ar.ccv" \ + : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ + : "r" ((unsigned long)__old), "r" (new) \ + : "memory"); \ + __ret = (__result) != (__old); \ + } while (0) + +#endif + +#elif defined(__powerpc__) + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__( \ + "sync;" \ + "0: lwarx %0,0,%1;" \ + " xor. %0,%3,%0;" \ + " bne 1f;" \ + " stwcx. %2,0,%1;" \ + " bne- 0b;" \ + "1: " \ + "sync;" \ + : "=&r"(__ret) \ + : "r"(lock), "r"(new), "r"(old) \ + : "cr0", "memory"); \ + } while (0) + +# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \ + || defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) + #undef DRM_DEV_MODE + #define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + + #define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__ ( \ + "1: ldrex %0, [%1]\n" \ + " teq %0, %2\n" \ + " ite eq\n" \ + " strexeq %0, %3, [%1]\n" \ + " movne %0, #1\n" \ + : "=&r" (__ret) \ + : "r" (lock), "r" (old), "r" (new) \ + : "cc","memory"); \ + } while (0) + +#endif /* architecture */ +#endif /* __GNUC__ >= 2 */ + +#ifndef DRM_CAS +#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ +#endif + +#if defined(__alpha__) +#define DRM_CAS_RESULT(_result) long _result +#elif defined(__powerpc__) +#define DRM_CAS_RESULT(_result) int _result +#else +#define DRM_CAS_RESULT(_result) char _result +#endif + +#define DRM_LIGHT_LOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + } while(0) + + /* This one counts fast locks -- for + benchmarking only. */ +#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + else ++count; \ + } while(0) + +#define DRM_LOCK(fd,lock,context,flags) \ + do { \ + if (flags) drmGetLock(fd,context,flags); \ + else DRM_LIGHT_LOCK(fd,lock,context); \ + } while(0) + +#define DRM_UNLOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \ + if (__ret) drmUnlock(fd,context); \ + } while(0) + + /* Simple spin locks */ +#define DRM_SPINLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + do { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) while ((spin)->lock); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_TAKE(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + int cur; \ + do { \ + cur = (*spin).lock; \ + DRM_CAS(spin,cur,val,__ret); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ + do { \ + int __i; \ + __ret = 1; \ + for (__i = 0; __ret && __i < count; __i++) { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) for (;__i < count && (spin)->lock; __i++); \ + } \ + } while(0) + +#define DRM_SPINUNLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + if ((*spin).lock == val) { /* else server stole lock */ \ + do { \ + DRM_CAS(spin,val,0,__ret); \ + } while (__ret); \ + } \ + } while(0) + + + +/* General user-level programmer's API: unprivileged */ +extern int drmAvailable(void); +extern int drmOpen(const char *name, const char *busid); + +#define DRM_NODE_PRIMARY 0 +#define DRM_NODE_CONTROL 1 +#define DRM_NODE_RENDER 2 +#define DRM_NODE_MAX 3 + +extern int drmOpenWithType(const char *name, const char *busid, + int type); + +extern int drmOpenControl(int minor); +extern int drmOpenRender(int minor); +extern int drmClose(int fd); +extern drmVersionPtr drmGetVersion(int fd); +extern drmVersionPtr drmGetLibVersion(int fd); +extern int drmGetCap(int fd, uint64_t capability, uint64_t *value); +extern void drmFreeVersion(drmVersionPtr); +extern int drmGetMagic(int fd, drm_magic_t * magic); +extern char *drmGetBusid(int fd); +extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum, + int funcnum); +extern int drmGetMap(int fd, int idx, drm_handle_t *offset, + drmSize *size, drmMapType *type, + drmMapFlags *flags, drm_handle_t *handle, + int *mtrr); +extern int drmGetClient(int fd, int idx, int *auth, int *pid, + int *uid, unsigned long *magic, + unsigned long *iocs); +extern int drmGetStats(int fd, drmStatsT *stats); +extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); +extern int drmCommandNone(int fd, unsigned long drmCommandIndex); +extern int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); + +/* General user-level programmer's API: X server (root) only */ +extern void drmFreeBusid(const char *busid); +extern int drmSetBusid(int fd, const char *busid); +extern int drmAuthMagic(int fd, drm_magic_t magic); +extern int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle); +extern int drmRmMap(int fd, drm_handle_t handle); +extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t handle); + +extern int drmAddBufs(int fd, int count, int size, + drmBufDescFlags flags, + int agp_offset); +extern int drmMarkBufs(int fd, double low, double high); +extern int drmCreateContext(int fd, drm_context_t * handle); +extern int drmSetContextFlags(int fd, drm_context_t context, + drm_context_tFlags flags); +extern int drmGetContextFlags(int fd, drm_context_t context, + drm_context_tFlagsPtr flags); +extern int drmAddContextTag(int fd, drm_context_t context, void *tag); +extern int drmDelContextTag(int fd, drm_context_t context); +extern void *drmGetContextTag(int fd, drm_context_t context); +extern drm_context_t * drmGetReservedContextList(int fd, int *count); +extern void drmFreeReservedContextList(drm_context_t *); +extern int drmSwitchToContext(int fd, drm_context_t context); +extern int drmDestroyContext(int fd, drm_context_t handle); +extern int drmCreateDrawable(int fd, drm_drawable_t * handle); +extern int drmDestroyDrawable(int fd, drm_drawable_t handle); +extern int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, + drm_drawable_info_type_t type, + unsigned int num, void *data); +extern int drmCtlInstHandler(int fd, int irq); +extern int drmCtlUninstHandler(int fd); +extern int drmSetClientCap(int fd, uint64_t capability, + uint64_t value); + +extern int drmCrtcGetSequence(int fd, uint32_t crtcId, + uint64_t *sequence, uint64_t *ns); +extern int drmCrtcQueueSequence(int fd, uint32_t crtcId, + uint32_t flags, uint64_t sequence, + uint64_t *sequence_queued, + uint64_t user_data); +/* General user-level programmer's API: authenticated client and/or X */ +extern int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address); +extern int drmUnmap(drmAddress address, drmSize size); +extern drmBufInfoPtr drmGetBufInfo(int fd); +extern drmBufMapPtr drmMapBufs(int fd); +extern int drmUnmapBufs(drmBufMapPtr bufs); +extern int drmDMA(int fd, drmDMAReqPtr request); +extern int drmFreeBufs(int fd, int count, int *list); +extern int drmGetLock(int fd, + drm_context_t context, + drmLockFlags flags); +extern int drmUnlock(int fd, drm_context_t context); +extern int drmFinish(int fd, int context, drmLockFlags flags); +extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t * handle); + +/* AGP/GART support: X server (root) only */ +extern int drmAgpAcquire(int fd); +extern int drmAgpRelease(int fd); +extern int drmAgpEnable(int fd, unsigned long mode); +extern int drmAgpAlloc(int fd, unsigned long size, + unsigned long type, unsigned long *address, + drm_handle_t *handle); +extern int drmAgpFree(int fd, drm_handle_t handle); +extern int drmAgpBind(int fd, drm_handle_t handle, + unsigned long offset); +extern int drmAgpUnbind(int fd, drm_handle_t handle); + +/* AGP/GART info: authenticated client and/or X */ +extern int drmAgpVersionMajor(int fd); +extern int drmAgpVersionMinor(int fd); +extern unsigned long drmAgpGetMode(int fd); +extern unsigned long drmAgpBase(int fd); /* Physical location */ +extern unsigned long drmAgpSize(int fd); /* Bytes */ +extern unsigned long drmAgpMemoryUsed(int fd); +extern unsigned long drmAgpMemoryAvail(int fd); +extern unsigned int drmAgpVendorId(int fd); +extern unsigned int drmAgpDeviceId(int fd); + +/* PCI scatter/gather support: X server (root) only */ +extern int drmScatterGatherAlloc(int fd, unsigned long size, + drm_handle_t *handle); +extern int drmScatterGatherFree(int fd, drm_handle_t handle); + +extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); + +/* Support routines */ +extern void drmSetServerInfo(drmServerInfoPtr info); +extern int drmError(int err, const char *label); +extern void *drmMalloc(int size); +extern void drmFree(void *pt); + +/* Hash table routines */ +extern void *drmHashCreate(void); +extern int drmHashDestroy(void *t); +extern int drmHashLookup(void *t, unsigned long key, void **value); +extern int drmHashInsert(void *t, unsigned long key, void *value); +extern int drmHashDelete(void *t, unsigned long key); +extern int drmHashFirst(void *t, unsigned long *key, void **value); +extern int drmHashNext(void *t, unsigned long *key, void **value); + +/* PRNG routines */ +extern void *drmRandomCreate(unsigned long seed); +extern int drmRandomDestroy(void *state); +extern unsigned long drmRandom(void *state); +extern double drmRandomDouble(void *state); + +/* Skip list routines */ + +extern void *drmSLCreate(void); +extern int drmSLDestroy(void *l); +extern int drmSLLookup(void *l, unsigned long key, void **value); +extern int drmSLInsert(void *l, unsigned long key, void *value); +extern int drmSLDelete(void *l, unsigned long key); +extern int drmSLNext(void *l, unsigned long *key, void **value); +extern int drmSLFirst(void *l, unsigned long *key, void **value); +extern void drmSLDump(void *l); +extern int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); + +extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened); +extern int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type); +extern void drmCloseOnce(int fd); +extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2); + +extern int drmSetMaster(int fd); +extern int drmDropMaster(int fd); +extern int drmIsMaster(int fd); + +#define DRM_EVENT_CONTEXT_VERSION 4 + +typedef struct _drmEventContext { + + /* This struct is versioned so we can add more pointers if we + * add more events. */ + int version; + + void (*vblank_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + + void (*page_flip_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + + void (*page_flip_handler2)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + unsigned int crtc_id, + void *user_data); + + void (*sequence_handler)(int fd, + uint64_t sequence, + uint64_t ns, + uint64_t user_data); +} drmEventContext, *drmEventContextPtr; + +extern int drmHandleEvent(int fd, drmEventContextPtr evctx); + +extern char *drmGetDeviceNameFromFd(int fd); + +/* Improved version of drmGetDeviceNameFromFd which attributes for any type of + * device/node - card, control or renderD. + */ +extern char *drmGetDeviceNameFromFd2(int fd); +extern int drmGetNodeTypeFromFd(int fd); + +extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd); +extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle); + +extern char *drmGetPrimaryDeviceNameFromFd(int fd); +extern char *drmGetRenderDeviceNameFromFd(int fd); + +#define DRM_BUS_PCI 0 +#define DRM_BUS_USB 1 +#define DRM_BUS_PLATFORM 2 +#define DRM_BUS_HOST1X 3 + +typedef struct _drmPciBusInfo { + uint16_t domain; + uint8_t bus; + uint8_t dev; + uint8_t func; +} drmPciBusInfo, *drmPciBusInfoPtr; + +typedef struct _drmPciDeviceInfo { + uint16_t vendor_id; + uint16_t device_id; + uint16_t subvendor_id; + uint16_t subdevice_id; + uint8_t revision_id; +} drmPciDeviceInfo, *drmPciDeviceInfoPtr; + +typedef struct _drmUsbBusInfo { + uint8_t bus; + uint8_t dev; +} drmUsbBusInfo, *drmUsbBusInfoPtr; + +typedef struct _drmUsbDeviceInfo { + uint16_t vendor; + uint16_t product; +} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr; + +#define DRM_PLATFORM_DEVICE_NAME_LEN 512 + +typedef struct _drmPlatformBusInfo { + char fullname[DRM_PLATFORM_DEVICE_NAME_LEN]; +} drmPlatformBusInfo, *drmPlatformBusInfoPtr; + +typedef struct _drmPlatformDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr; + +#define DRM_HOST1X_DEVICE_NAME_LEN 512 + +typedef struct _drmHost1xBusInfo { + char fullname[DRM_HOST1X_DEVICE_NAME_LEN]; +} drmHost1xBusInfo, *drmHost1xBusInfoPtr; + +typedef struct _drmHost1xDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; + +typedef struct _drmDevice { + char **nodes; /* DRM_NODE_MAX sized array */ + int available_nodes; /* DRM_NODE_* bitmask */ + int bustype; + union { + drmPciBusInfoPtr pci; + drmUsbBusInfoPtr usb; + drmPlatformBusInfoPtr platform; + drmHost1xBusInfoPtr host1x; + } businfo; + union { + drmPciDeviceInfoPtr pci; + drmUsbDeviceInfoPtr usb; + drmPlatformDeviceInfoPtr platform; + drmHost1xDeviceInfoPtr host1x; + } deviceinfo; +} drmDevice, *drmDevicePtr; + +extern int drmGetDevice(int fd, drmDevicePtr *device); +extern void drmFreeDevice(drmDevicePtr *device); + +extern int drmGetDevices(drmDevicePtr devices[], int max_devices); +extern void drmFreeDevices(drmDevicePtr devices[], int count); + +#define DRM_DEVICE_GET_PCI_REVISION (1 << 0) +extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device); +extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices); + +extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); + +extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); +extern int drmSyncobjDestroy(int fd, uint32_t handle); +extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd); +extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle); + +extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd); +extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd); +extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, + uint64_t *points, uint32_t handle_count); +extern int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, + unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points, + uint32_t handle_count); +extern int drmSyncobjTransfer(int fd, + uint32_t dst_handle, uint64_t dst_point, + uint32_t src_handle, uint64_t src_point, + uint32_t flags); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/xf86drmMode.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/xf86drmMode.h new file mode 100644 index 0000000..a32902f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/drm/include/xf86drmMode.h @@ -0,0 +1,551 @@ +/* + * \file xf86drmMode.h + * Header for DRM modesetting interface. + * + * \author Jakob Bornecrantz + * + * \par Acknowledgements: + * Feb 2007, Dave Airlie + */ + +/* + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 2007-2008 Dave Airlie + * Copyright (c) 2007-2008 Jakob Bornecrantz + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _XF86DRMMODE_H_ +#define _XF86DRMMODE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include + +/* + * This is the interface for modesetting for drm. + * + * In order to use this interface you must include either or another + * header defining uint32_t, int32_t and uint16_t. + * + * It aims to provide a randr1.2 compatible interface for modesettings in the + * kernel, the interface is also meant to be used by libraries like EGL. + * + * More information can be found in randrproto.txt which can be found here: + * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git + * + * There are some major differences to be noted. Unlike the randr1.2 proto you + * need to create the memory object of the framebuffer yourself with the ttm + * buffer object interface. This object needs to be pinned. + */ + +/* + * If we pickup an old version of drm.h which doesn't include drm_mode.h + * we should redefine defines. This is so that builds doesn't breaks with + * new libdrm on old kernels. + */ +#ifndef _DRM_MODE_H + +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NON_GPU 0 +#define DRM_MODE_SCALE_FULLSCREEN 1 +#define DRM_MODE_SCALE_NO_SCALE 2 +#define DRM_MODE_SCALE_ASPECT 3 + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 + +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 +#define DRM_MODE_SUBCONNECTOR_SCART 9 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) + +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) + +#endif /* _DRM_MODE_H */ + + +/* + * Feature defines + * + * Just because these are defined doesn't mean that the kernel + * can do that feature, its just for new code vs old libdrm. + */ +#define DRM_MODE_FEATURE_KMS 1 +#define DRM_MODE_FEATURE_DIRTYFB 1 + + +typedef struct _drmModeRes { + + int count_fbs; + uint32_t *fbs; + + int count_crtcs; + uint32_t *crtcs; + + int count_connectors; + uint32_t *connectors; + + int count_encoders; + uint32_t *encoders; + + uint32_t min_width, max_width; + uint32_t min_height, max_height; +} drmModeRes, *drmModeResPtr; + +typedef struct _drmModeModeInfo { + uint32_t clock; + uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; + uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; + + uint32_t vrefresh; + + uint32_t flags; + uint32_t type; + char name[DRM_DISPLAY_MODE_LEN]; +} drmModeModeInfo, *drmModeModeInfoPtr; + +typedef struct _drmModeFB { + uint32_t fb_id; + uint32_t width, height; + uint32_t pitch; + uint32_t bpp; + uint32_t depth; + /* driver specific handle */ + uint32_t handle; +} drmModeFB, *drmModeFBPtr; + +typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr; + +typedef struct _drmModePropertyBlob { + uint32_t id; + uint32_t length; + void *data; +} drmModePropertyBlobRes, *drmModePropertyBlobPtr; + +typedef struct _drmModeProperty { + uint32_t prop_id; + uint32_t flags; + char name[DRM_PROP_NAME_LEN]; + int count_values; + uint64_t *values; /* store the blob lengths */ + int count_enums; + struct drm_mode_property_enum *enums; + int count_blobs; + uint32_t *blob_ids; /* store the blob IDs */ +} drmModePropertyRes, *drmModePropertyPtr; + +static __inline int drm_property_type_is(drmModePropertyPtr property, + uint32_t type) +{ + /* instanceof for props.. handles extended type vs original types: */ + if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) + return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type; + return property->flags & type; +} + +typedef struct _drmModeCrtc { + uint32_t crtc_id; + uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */ + + uint32_t x, y; /**< Position on the framebuffer */ + uint32_t width, height; + int mode_valid; + drmModeModeInfo mode; + + int gamma_size; /**< Number of gamma stops */ + +} drmModeCrtc, *drmModeCrtcPtr; + +typedef struct _drmModeEncoder { + uint32_t encoder_id; + uint32_t encoder_type; + uint32_t crtc_id; + uint32_t possible_crtcs; + uint32_t possible_clones; +} drmModeEncoder, *drmModeEncoderPtr; + +typedef enum { + DRM_MODE_CONNECTED = 1, + DRM_MODE_DISCONNECTED = 2, + DRM_MODE_UNKNOWNCONNECTION = 3 +} drmModeConnection; + +typedef enum { + DRM_MODE_SUBPIXEL_UNKNOWN = 1, + DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2, + DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3, + DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4, + DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5, + DRM_MODE_SUBPIXEL_NONE = 6 +} drmModeSubPixel; + +typedef struct _drmModeConnector { + uint32_t connector_id; + uint32_t encoder_id; /**< Encoder currently connected to */ + uint32_t connector_type; + uint32_t connector_type_id; + drmModeConnection connection; + uint32_t mmWidth, mmHeight; /**< HxW in millimeters */ + drmModeSubPixel subpixel; + + int count_modes; + drmModeModeInfoPtr modes; + + int count_props; + uint32_t *props; /**< List of property ids */ + uint64_t *prop_values; /**< List of property values */ + + int count_encoders; + uint32_t *encoders; /**< List of encoder ids */ +} drmModeConnector, *drmModeConnectorPtr; + +#define DRM_PLANE_TYPE_OVERLAY 0 +#define DRM_PLANE_TYPE_PRIMARY 1 +#define DRM_PLANE_TYPE_CURSOR 2 + +typedef struct _drmModeObjectProperties { + uint32_t count_props; + uint32_t *props; + uint64_t *prop_values; +} drmModeObjectProperties, *drmModeObjectPropertiesPtr; + +typedef struct _drmModePlane { + uint32_t count_formats; + uint32_t *formats; + uint32_t plane_id; + + uint32_t crtc_id; + uint32_t fb_id; + + uint32_t crtc_x, crtc_y; + uint32_t x, y; + + uint32_t possible_crtcs; + uint32_t gamma_size; +} drmModePlane, *drmModePlanePtr; + +typedef struct _drmModePlaneRes { + uint32_t count_planes; + uint32_t *planes; +} drmModePlaneRes, *drmModePlaneResPtr; + +extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr ); +extern void drmModeFreeResources( drmModeResPtr ptr ); +extern void drmModeFreeFB( drmModeFBPtr ptr ); +extern void drmModeFreeCrtc( drmModeCrtcPtr ptr ); +extern void drmModeFreeConnector( drmModeConnectorPtr ptr ); +extern void drmModeFreeEncoder( drmModeEncoderPtr ptr ); +extern void drmModeFreePlane( drmModePlanePtr ptr ); +extern void drmModeFreePlaneResources(drmModePlaneResPtr ptr); + +/** + * Retrieves all of the resources associated with a card. + */ +extern drmModeResPtr drmModeGetResources(int fd); + +/* + * FrameBuffer manipulation. + */ + +/** + * Retrieve information about framebuffer bufferId + */ +extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId); + +/** + * Creates a new framebuffer with an buffer object as its scanout buffer. + */ +extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint32_t *buf_id); +/* ...with a specific pixel format */ +extern int drmModeAddFB2(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + uint32_t *buf_id, uint32_t flags); + +/* ...with format modifiers */ +int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + const uint64_t modifier[4], uint32_t *buf_id, + uint32_t flags); + +/** + * Destroies the given framebuffer. + */ +extern int drmModeRmFB(int fd, uint32_t bufferId); + +/** + * Mark a region of a framebuffer as dirty. + */ +extern int drmModeDirtyFB(int fd, uint32_t bufferId, + drmModeClipPtr clips, uint32_t num_clips); + + +/* + * Crtc functions + */ + +/** + * Retrieve information about the ctrt crtcId + */ +extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId); + +/** + * Set the mode on a crtc crtcId with the given mode modeId. + */ +int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, + uint32_t x, uint32_t y, uint32_t *connectors, int count, + drmModeModeInfoPtr mode); + +/* + * Cursor functions + */ + +/** + * Set the cursor on crtc + */ +int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height); + +int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y); +/** + * Move the cursor on crtc + */ +int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y); + +/** + * Encoder functions + */ +drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id); + +/* + * Connector manipulation + */ + +/** + * Retrieve all information about the connector connectorId. This will do a + * forced probe on the connector to retrieve remote information such as EDIDs + * from the display device. + */ +extern drmModeConnectorPtr drmModeGetConnector(int fd, + uint32_t connectorId); + +/** + * Retrieve current information, i.e the currently active mode and encoder, + * about the connector connectorId. This will not do any probing on the + * connector or remote device, and only reports what is currently known. + * For the complete set of modes and encoders associated with the connector + * use drmModeGetConnector() which will do a probe to determine any display + * link changes first. + */ +extern drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, + uint32_t connector_id); + +/** + * Attaches the given mode to an connector. + */ +extern int drmModeAttachMode(int fd, uint32_t connectorId, drmModeModeInfoPtr mode_info); + +/** + * Detaches a mode from the connector + * must be unused, by the given mode. + */ +extern int drmModeDetachMode(int fd, uint32_t connectorId, drmModeModeInfoPtr mode_info); + +extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId); +extern void drmModeFreeProperty(drmModePropertyPtr ptr); + +extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id); +extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); +extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, + uint64_t value); +extern int drmCheckModesettingSupported(const char *busid); + +extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data); +extern int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data, + uint32_t target_vblank); + +extern drmModePlaneResPtr drmModeGetPlaneResources(int fd); +extern drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id); +extern int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, + uint32_t fb_id, uint32_t flags, + int32_t crtc_x, int32_t crtc_y, + uint32_t crtc_w, uint32_t crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); + +extern drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, + uint32_t object_id, + uint32_t object_type); +extern void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr); +extern int drmModeObjectSetProperty(int fd, uint32_t object_id, + uint32_t object_type, uint32_t property_id, + uint64_t value); + + +typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr; + +extern drmModeAtomicReqPtr drmModeAtomicAlloc(void); +extern drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr req); +extern int drmModeAtomicMerge(drmModeAtomicReqPtr base, + drmModeAtomicReqPtr augment); +extern void drmModeAtomicFree(drmModeAtomicReqPtr req); +extern int drmModeAtomicGetCursor(drmModeAtomicReqPtr req); +extern void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor); +extern int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, + uint32_t object_id, + uint32_t property_id, + uint64_t value); +extern int drmModeAtomicCommit(int fd, + drmModeAtomicReqPtr req, + uint32_t flags, + void *user_data); + +extern int drmModeCreatePropertyBlob(int fd, const void *data, size_t size, + uint32_t *id); +extern int drmModeDestroyPropertyBlob(int fd, uint32_t id); + +/* + * DRM mode lease APIs. These create and manage new drm_masters with + * access to a subset of the available DRM resources + */ + +extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id); + +typedef struct drmModeLesseeList { + uint32_t count; + uint32_t lessees[0]; +} drmModeLesseeListRes, *drmModeLesseeListPtr; + +extern drmModeLesseeListPtr drmModeListLessees(int fd); + +typedef struct drmModeObjectList { + uint32_t count; + uint32_t objects[0]; +} drmModeObjectListRes, *drmModeObjectListPtr; + +extern drmModeObjectListPtr drmModeGetLease(int fd); + +extern int drmModeRevokeLease(int fd, uint32_t lessee_id); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h new file mode 100644 index 0000000..c484f4d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "drmrga.h" + +#include "RockchipRgaMacro.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +int c_RkRgaInit(); +void c_RkRgaDeInit(); +int c_RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp); +int c_RkRgaGetMmap(bo_t *bo_info); +int c_RkRgaUnmap(bo_t *bo_info); +int c_RkRgaGetBufferFd(bo_t *bo_info, int *fd); +int c_RkRgaBlit(rga_info_t *src, rga_info_t *dst, rga_info_t *src1); +int c_RkRgaColorFill(rga_info_t *dst); +#ifdef __cplusplus +} +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipFileOps.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipFileOps.h new file mode 100644 index 0000000..6d123ec --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipFileOps.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _rk_file_ops_h_ +#define _rk_file_ops_h_ + +// ------------------------------------------------------------------------------- +int get_buf_from_file(void *buf, int f, int sw, int sh, int index); +int output_buf_data_to_file(void *buf, int f, int sw, int sh, int index); +#endif + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRga.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRga.h new file mode 100644 index 0000000..c49c467 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRga.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +//#include +#include + +////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "stdio.h" + +////////////////////////////////////////////////////////////////////////////////// + +// ------------------------------------------------------------------------------- + +class RockchipRga +{ +/************************************public**************************************/ + +public: + + RockchipRga(); + ~RockchipRga(); + + int RkRgaInit(); + void RkRgaDeInit(); + int RkRgaAllocBuffer(int drm_fd /* input */, bo_t *bo_info, + int width, int height, int bpp); + int RkRgaFreeBuffer(int drm_fd /* input */, bo_t *bo_info); + int RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp); + int RkRgaGetMmap(bo_t *bo_info); + int RkRgaUnmap(bo_t *bo_info); + int RkRgaFree(bo_t *bo_info); + int RkRgaGetBufferFd(bo_t *bo_info, int *fd); + int RkRgaBlit(rga_info *src, rga_info *dst, rga_info *src1); + int RkRgaCollorFill(rga_info *dst); + + + void RkRgaSetLogOnceFlag(int log) {mLogOnce = log;} + void RkRgaSetAlwaysLogFlag(bool log) {mLogAlways = log;} + void RkRgaLogOutRgaReq(struct rga_req rgaReg); + int RkRgaLogOutUserPara(rga_info *rgaInfo); + inline bool RkRgaIsReady() { return mSupportRga; } + +/************************************private***********************************/ +private: + bool mSupportRga; + int mLogOnce; + int mLogAlways; + void * mContext; +}; + +// --------------------------------------------------------------------------- + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h new file mode 100644 index 0000000..3c1fff0 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __ROCKCHIP_RGA_MACRO_H__ +#define __ROCKCHIP_RGA_MACRO_H__ + +/* flip source image horizontally (around the vertical axis) */ +#define HAL_TRANSFORM_FLIP_H 0x01 +/* flip source image vertically (around the horizontal axis)*/ +#define HAL_TRANSFORM_FLIP_V 0x02 +/* rotate source image 90 degrees clockwise */ +#define HAL_TRANSFORM_ROT_90 0x04 +/* rotate source image 180 degrees */ +#define HAL_TRANSFORM_ROT_180 0x03 +/* rotate source image 270 degrees clockwise */ +#define HAL_TRANSFORM_ROT_270 0x07 + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h new file mode 100644 index 0000000..abd8b97 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _rk_drm_rga_ +#define _rk_drm_rga_ + +#include +#include +#include "rga.h" +#include "RockchipRgaMacro.h" + +/*****************************************************************************/ + +/* for compatibility */ +#define DRM_RGA_MODULE_API_VERSION HWC_MODULE_API_VERSION_0_1 +#define DRM_RGA_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_1 +#define DRM_RGA_API_VERSION HWC_DEVICE_API_VERSION + +#define DRM_RGA_TRANSFORM_ROT_MASK 0x0000000F +#define DRM_RGA_TRANSFORM_ROT_0 0x00000000 +#define DRM_RGA_TRANSFORM_ROT_90 HAL_TRANSFORM_ROT_90 +#define DRM_RGA_TRANSFORM_ROT_180 HAL_TRANSFORM_ROT_180 +#define DRM_RGA_TRANSFORM_ROT_270 HAL_TRANSFORM_ROT_270 + +#define DRM_RGA_TRANSFORM_FLIP_MASK 0x00000003 +#define DRM_RGA_TRANSFORM_FLIP_H HAL_TRANSFORM_FLIP_H +#define DRM_RGA_TRANSFORM_FLIP_V HAL_TRANSFORM_FLIP_V + +enum { + AWIDTH = 0, + AHEIGHT, + ASTRIDE, + AFORMAT, + ASIZE, + ATYPE, +}; +/*****************************************************************************/ + + +typedef struct bo { + int fd; + void *ptr; + size_t size; + size_t offset; + size_t pitch; + unsigned handle; + }bo_t; + +/* + @value size: user not need care about.For avoid read/write out of memory + */ +typedef struct rga_rect { + int xoffset; + int yoffset; + int width; + int height; + int wstride; + int hstride; + int format; + int size; +} rga_rect_t; + +typedef struct rga_nn { + int nn_flag; + int scale_r; + int scale_g; + int scale_b; + int offset_r; + int offset_g; + int offset_b; +} rga_nn_t; + +typedef struct rga_dither { + int enable; + int mode; + int lut0_l; + int lut0_h; + int lut1_l; + int lut1_h; +} rga_dither_t; +/* + @value fd: use fd to share memory, it can be ion shard fd,and dma fd. + @value virAddr:userspace address + @value phyAddr:use phy address + @value hnd: use buffer_handle_t + */ +typedef struct rga_info { + int fd; + void *virAddr; + void *phyAddr; + unsigned hnd; + int format; + rga_rect_t rect; + unsigned int blend; + int bufferSize; + int rotation; + int color; + int testLog; + int mmuFlag; + int scale_mode; + rga_nn_t nn; + rga_dither_t dither; + int reserve[124]; +} rga_info_t; + + +typedef struct drm_rga { + rga_rect_t src; + rga_rect_t dst; +} drm_rga_t; + +/* + @fun rga_set_rect:For use to set the rects esayly + + @param rect:The rect user want to set,like setting the src rect: + drm_rga_t rects; + rga_set_rect(rects.src,0,0,1920,1080,1920,NV12); + mean to set the src rect to the value. + */ +static inline int rga_set_rect(rga_rect_t *rect, + int x, int y, int w, int h, int sw, int sh, int f) +{ + if (!rect) + return -EINVAL; + + rect->xoffset = x; + rect->yoffset = y; + rect->width = w; + rect->height = h; + rect->wstride = sw; + rect->hstride = sh; + rect->format = f; + + return 0; +} + +static inline void rga_set_rotation(rga_info_t *info, int angle) +{ + if (angle == 90) + info->rotation = HAL_TRANSFORM_ROT_90; + else if (angle == 180) + info->rotation = HAL_TRANSFORM_ROT_180; + else if (angle == 270) + info->rotation = HAL_TRANSFORM_ROT_270; +} +/*****************************************************************************/ + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/rga.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/rga.h new file mode 100644 index 0000000..7737e7a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/rga/include/rga.h @@ -0,0 +1,752 @@ +#ifndef _RGA_DRIVER_H_ +#define _RGA_DRIVER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +#define RGA_BLIT_SYNC 0x5017 +#define RGA_BLIT_ASYNC 0x5018 +#define RGA_FLUSH 0x5019 +#define RGA_GET_RESULT 0x501a +#define RGA_GET_VERSION 0x501b + + +#define RGA_REG_CTRL_LEN 0x8 /* 8 */ +#define RGA_REG_CMD_LEN 0x1c /* 28 */ +#define RGA_CMD_BUF_SIZE 0x700 /* 16*28*4 */ + + + +#ifndef ENABLE +#define ENABLE 1 +#endif + + +#ifndef DISABLE +#define DISABLE 0 +#endif + + + +/* RGA process mode enum */ +enum +{ + bitblt_mode = 0x0, + color_palette_mode = 0x1, + color_fill_mode = 0x2, + line_point_drawing_mode = 0x3, + blur_sharp_filter_mode = 0x4, + pre_scaling_mode = 0x5, + update_palette_table_mode = 0x6, + update_patten_buff_mode = 0x7, +}; + + +enum +{ + rop_enable_mask = 0x2, + dither_enable_mask = 0x8, + fading_enable_mask = 0x10, + PD_enbale_mask = 0x20, +}; + +enum +{ + yuv2rgb_mode0 = 0x0, /* BT.601 MPEG */ + yuv2rgb_mode1 = 0x1, /* BT.601 JPEG */ + yuv2rgb_mode2 = 0x2, /* BT.709 */ +}; + + +/* RGA rotate mode */ +enum +{ + rotate_mode0 = 0x0, /* no rotate */ + rotate_mode1 = 0x1, /* rotate */ + rotate_mode2 = 0x2, /* x_mirror */ + rotate_mode3 = 0x3, /* y_mirror */ +}; + +enum +{ + color_palette_mode0 = 0x0, /* 1K */ + color_palette_mode1 = 0x1, /* 2K */ + color_palette_mode2 = 0x2, /* 4K */ + color_palette_mode3 = 0x3, /* 8K */ +}; + +enum +{ + BB_BYPASS = 0x0, /* no rotate */ + BB_ROTATE = 0x1, /* rotate */ + BB_X_MIRROR = 0x2, /* x_mirror */ + BB_Y_MIRROR = 0x3 /* y_mirror */ +}; + +enum +{ + nearby = 0x0, /* no rotate */ + bilinear = 0x1, /* rotate */ + bicubic = 0x2, /* x_mirror */ +}; + + + + + +/* +// Alpha Red Green Blue +{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // RK_FORMAT_RGBA_8888 +{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGBX_8888 +{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGB_888 +{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_BGRA }, // RK_FORMAT_BGRA_8888 +{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // RK_FORMAT_RGB_565 +{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // RK_FORMAT_RGBA_5551 +{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // RK_FORMAT_RGBA_4444 +{ 3, 24, {{ 0, 0, 24,16, 16, 8, 8, 0 }}, GGL_BGR }, // RK_FORMAT_BGB_888 + +*/ + +typedef enum _Rga_SURF_FORMAT +{ + RK_FORMAT_RGBA_8888 = 0x0, + RK_FORMAT_RGBX_8888 = 0x1, + RK_FORMAT_RGB_888 = 0x2, + RK_FORMAT_BGRA_8888 = 0x3, + RK_FORMAT_BGRX_8888 = 0x4, + RK_FORMAT_BGR_888 = 0x5, + RK_FORMAT_RGB_565 = 0x6, + RK_FORMAT_RGBA_5551 = 0x7, + RK_FORMAT_RGBA_4444 = 0x8, + RK_FORMAT_BGR_565 = 0x9, + RK_FORMAT_BGRA_5551 = 0xa, + RK_FORMAT_BGRA_4444 = 0xb, + + RK_FORMAT_Y4 = 0xe, + RK_FORMAT_YCbCr_400 = 0xf, + RK_FORMAT_YCbCr_422_SP = 0x10, + RK_FORMAT_YCbCr_422_P = 0x11, + RK_FORMAT_YCbCr_420_SP = 0x12, + RK_FORMAT_YCbCr_420_P = 0x13, + RK_FORMAT_YCrCb_422_SP = 0x14, + RK_FORMAT_YCrCb_422_P = 0x15, + RK_FORMAT_YCrCb_420_SP = 0x16, + RK_FORMAT_YCrCb_420_P = 0x17, + + RK_FORMAT_YVYU_422 = 0x18, + RK_FORMAT_YVYU_420 = 0x19, + RK_FORMAT_VYUY_422 = 0x1a, + RK_FORMAT_VYUY_420 = 0x1b, + RK_FORMAT_YUYV_422 = 0x1c, + RK_FORMAT_YUYV_420 = 0x1d, + RK_FORMAT_UYVY_422 = 0x1e, + RK_FORMAT_UYVY_420 = 0x1f, + + RK_FORMAT_YCbCr_422_10b_SP = 0x20, + RK_FORMAT_YCbCr_420_10b_SP = 0x21, + RK_FORMAT_YCrCb_422_10b_SP = 0x22, + RK_FORMAT_YCrCb_420_10b_SP = 0x23, + + RK_FORMAT_UNKNOWN = 0x100, +} RgaSURF_FORMAT; + +typedef struct rga_img_info_t +{ +#if defined(__arm64__) || defined(__aarch64__) + unsigned long yrgb_addr; /* yrgb mem addr */ + unsigned long uv_addr; /* cb/cr mem addr */ + unsigned long v_addr; /* cr mem addr */ +#else + unsigned int yrgb_addr; /* yrgb mem addr */ + unsigned int uv_addr; /* cb/cr mem addr */ + unsigned int v_addr; /* cr mem addr */ +#endif + unsigned int format; //definition by RK_FORMAT + unsigned short act_w; + unsigned short act_h; + unsigned short x_offset; + unsigned short y_offset; + + unsigned short vir_w; + unsigned short vir_h; + + unsigned short endian_mode; //for BPP + unsigned short alpha_swap; +} +rga_img_info_t; + + +typedef struct mdp_img_act +{ + unsigned short w; // width + unsigned short h; // height + short x_off; // x offset for the vir + short y_off; // y offset for the vir +} +mdp_img_act; + + + +typedef struct RANGE +{ + unsigned short min; + unsigned short max; +} +RANGE; + +typedef struct POINT_t +{ + unsigned short x; + unsigned short y; +} +POINT_t; + +typedef struct RECT_t +{ + unsigned short xmin; + unsigned short xmax; // width - 1 + unsigned short ymin; + unsigned short ymax; // height - 1 +} RECT_t; + +typedef struct RGT_t +{ + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char res; +}RGB_t; + + +typedef struct MMU +{ + unsigned char mmu_en; +#if defined(__arm64__) || defined(__aarch64__) + unsigned long base_addr; +#else + unsigned int base_addr; +#endif + unsigned int mmu_flag; /* [0] mmu enable [1] src_flush [2] dst_flush [3] CMD_flush [4~5] page size*/ +} MMU; + + + + +typedef struct COLOR_FILL +{ + short gr_x_a; + short gr_y_a; + short gr_x_b; + short gr_y_b; + short gr_x_g; + short gr_y_g; + short gr_x_r; + short gr_y_r; + + //u8 cp_gr_saturation; +} +COLOR_FILL; + +typedef struct FADING +{ + unsigned char b; + unsigned char g; + unsigned char r; + unsigned char res; +} +FADING; + + +typedef struct line_draw_t +{ + POINT_t start_point; /* LineDraw_start_point */ + POINT_t end_point; /* LineDraw_end_point */ + unsigned int color; /* LineDraw_color */ + unsigned int flag; /* (enum) LineDrawing mode sel */ + unsigned int line_width; /* range 1~16 */ +} +line_draw_t; + + + + struct rga_req { + unsigned char render_mode; /* (enum) process mode sel */ + + rga_img_info_t src; /* src image info */ + rga_img_info_t dst; /* dst image info */ + rga_img_info_t pat; /* patten image info */ + +#if defined(__arm64__) || defined(__aarch64__) + unsigned long rop_mask_addr; /* rop4 mask addr */ + unsigned long LUT_addr; /* LUT addr */ +#else + unsigned int rop_mask_addr; /* rop4 mask addr */ + unsigned int LUT_addr; /* LUT addr */ +#endif + + RECT_t clip; /* dst clip window default value is dst_vir */ + /* value from [0, w-1] / [0, h-1]*/ + + int sina; /* dst angle default value 0 16.16 scan from table */ + int cosa; /* dst angle default value 0 16.16 scan from table */ + + unsigned short alpha_rop_flag; /* alpha rop process flag */ + /* ([0] = 1 alpha_rop_enable) */ + /* ([1] = 1 rop enable) */ + /* ([2] = 1 fading_enable) */ + /* ([3] = 1 PD_enable) */ + /* ([4] = 1 alpha cal_mode_sel) */ + /* ([5] = 1 dither_enable) */ + /* ([6] = 1 gradient fill mode sel) */ + /* ([7] = 1 AA_enable) */ + + unsigned char scale_mode; /* 0 nearst / 1 bilnear / 2 bicubic */ + + unsigned int color_key_max; /* color key max */ + unsigned int color_key_min; /* color key min */ + + unsigned int fg_color; /* foreground color */ + unsigned int bg_color; /* background color */ + + COLOR_FILL gr_color; /* color fill use gradient */ + + line_draw_t line_draw_info; + + FADING fading; + + unsigned char PD_mode; /* porter duff alpha mode sel */ + + unsigned char alpha_global_value; /* global alpha value */ + + unsigned short rop_code; /* rop2/3/4 code scan from rop code table*/ + + unsigned char bsfilter_flag; /* [2] 0 blur 1 sharp / [1:0] filter_type*/ + + unsigned char palette_mode; /* (enum) color palatte 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/ + + unsigned char yuv2rgb_mode; /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */ + + unsigned char endian_mode; /* 0/big endian 1/little endian*/ + + unsigned char rotate_mode; /* (enum) rotate mode */ + /* 0x0, no rotate */ + /* 0x1, rotate */ + /* 0x2, x_mirror */ + /* 0x3, y_mirror */ + + unsigned char color_fill_mode; /* 0 solid color / 1 patten color */ + + MMU mmu_info; /* mmu information */ + + unsigned char alpha_rop_mode; /* ([0~1] alpha mode) */ + /* ([2~3] rop mode) */ + /* ([4] zero mode en) */ + /* ([5] dst alpha mode) */ + + unsigned char src_trans_mode; + + unsigned char dither_mode; + + unsigned char CMD_fin_int_enable; + + /* completion is reported through a callback */ + void (*complete)(int retval); +}; + +#if 0 +typedef struct TILE_INFO +{ + int64_t matrix[4]; + + uint16_t tile_x_num; /* x axis tile num / tile size is 8x8 pixel */ + uint16_t tile_y_num; /* y axis tile num */ + + int16_t dst_x_tmp; /* dst pos x = (xstart - xoff) default value 0 */ + int16_t dst_y_tmp; /* dst pos y = (ystart - yoff) default value 0 */ + + uint16_t tile_w; + uint16_t tile_h; + int16_t tile_start_x_coor; + int16_t tile_start_y_coor; + int32_t tile_xoff; + int32_t tile_yoff; + + int32_t tile_temp_xstart; + int32_t tile_temp_ystart; + + /* src tile incr */ + int32_t x_dx; + int32_t x_dy; + int32_t y_dx; + int32_t y_dy; + + mdp_img_act dst_ctrl; + +} +TILE_INFO; +#endif + +#if 0 + +#define RGA_BASE 0x10114000 + +//General Registers +#define RGA_SYS_CTRL 0x000 +#define RGA_CMD_CTRL 0x004 +#define RGA_CMD_ADDR 0x008 +#define RGA_STATUS 0x00c +#define RGA_INT 0x010 +#define RGA_AXI_ID 0x014 +#define RGA_MMU_STA_CTRL 0x018 +#define RGA_MMU_STA 0x01c + +//Command code start +#define RGA_MODE_CTRL 0x100 + +//Source Image Registers +#define RGA_SRC_Y_MST 0x104 +#define RGA_SRC_CB_MST 0x108 +#define RGA_MASK_READ_MST 0x108 //repeat +#define RGA_SRC_CR_MST 0x10c +#define RGA_SRC_VIR_INFO 0x110 +#define RGA_SRC_ACT_INFO 0x114 +#define RGA_SRC_X_PARA 0x118 +#define RGA_SRC_Y_PARA 0x11c +#define RGA_SRC_TILE_XINFO 0x120 +#define RGA_SRC_TILE_YINFO 0x124 +#define RGA_SRC_TILE_H_INCR 0x128 +#define RGA_SRC_TILE_V_INCR 0x12c +#define RGA_SRC_TILE_OFFSETX 0x130 +#define RGA_SRC_TILE_OFFSETY 0x134 +#define RGA_SRC_BG_COLOR 0x138 +#define RGA_SRC_FG_COLOR 0x13c +#define RGA_LINE_DRAWING_COLOR 0x13c //repeat +#define RGA_SRC_TR_COLOR0 0x140 +#define RGA_CP_GR_A 0x140 //repeat +#define RGA_SRC_TR_COLOR1 0x144 +#define RGA_CP_GR_B 0x144 //repeat + +#define RGA_LINE_DRAW 0x148 +#define RGA_PAT_START_POINT 0x148 //repeat + +//Destination Image Registers +#define RGA_DST_MST 0x14c +#define RGA_LUT_MST 0x14c //repeat +#define RGA_PAT_MST 0x14c //repeat +#define RGA_LINE_DRAWING_MST 0x14c //repeat + +#define RGA_DST_VIR_INFO 0x150 + +#define RGA_DST_CTR_INFO 0x154 +#define RGA_LINE_DRAW_XY_INFO 0x154 //repeat + +//Alpha/ROP Registers +#define RGA_ALPHA_CON 0x158 + +#define RGA_PAT_CON 0x15c +#define RGA_DST_VIR_WIDTH_PIX 0x15c //repeat + +#define RGA_ROP_CON0 0x160 +#define RGA_CP_GR_G 0x160 //repeat +#define RGA_PRESCL_CB_MST 0x160 //repeat + +#define RGA_ROP_CON1 0x164 +#define RGA_CP_GR_R 0x164 //repeat +#define RGA_PRESCL_CR_MST 0x164 //repeat + +//MMU Register +#define RGA_FADING_CON 0x168 +#define RGA_MMU_CTRL 0x168 //repeat + +#define RGA_MMU_TBL 0x16c //repeat + + +#define RGA_BLIT_COMPLETE_EVENT 1 + +#endif + +int +RGA_set_src_act_info( + struct rga_req *req, + unsigned int width, /* act width */ + unsigned int height, /* act height */ + unsigned int x_off, /* x_off */ + unsigned int y_off /* y_off */ + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_src_vir_info( + struct rga_req *req, + unsigned long yrgb_addr, /* yrgb_addr */ + unsigned long uv_addr, /* uv_addr */ + unsigned long v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + unsigned char format, /* format */ + unsigned char a_swap_en /* only for 32bit RGB888 format */ + ); +#else +int +RGA_set_src_vir_info( + struct rga_req *req, + unsigned int yrgb_addr, /* yrgb_addr */ + unsigned int uv_addr, /* uv_addr */ + unsigned int v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + unsigned char format, /* format */ + unsigned char a_swap_en /* only for 32bit RGB888 format */ + ); +#endif + +int +RGA_set_dst_act_info( + struct rga_req *req, + unsigned int width, /* act width */ + unsigned int height, /* act height */ + unsigned int x_off, /* x_off */ + unsigned int y_off /* y_off */ + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_dst_vir_info( + struct rga_req *msg, + unsigned long yrgb_addr, /* yrgb_addr */ + unsigned long uv_addr, /* uv_addr */ + unsigned long v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + RECT_t *clip, /* clip window */ + unsigned char format, /* format */ + unsigned char a_swap_en + ); +#else +int +RGA_set_dst_vir_info( + struct rga_req *msg, + unsigned int yrgb_addr, /* yrgb_addr */ + unsigned int uv_addr, /* uv_addr */ + unsigned int v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + RECT_t *clip, /* clip window */ + unsigned char format, /* format */ + unsigned char a_swap_en + ); +#endif + +int +RGA_set_pat_info( + struct rga_req *msg, + unsigned int width, + unsigned int height, + unsigned int x_off, + unsigned int y_off, + unsigned int pat_format + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_rop_mask_info( + struct rga_req *msg, + unsigned long rop_mask_addr, + unsigned int rop_mask_endian_mode + ); +#else +int +RGA_set_rop_mask_info( + struct rga_req *msg, + unsigned int rop_mask_addr, + unsigned int rop_mask_endian_mode + ); +#endif + +int RGA_set_alpha_en_info( + struct rga_req *msg, + unsigned int alpha_cal_mode, /* 0:alpha' = alpha + (alpha>>7) | alpha' = alpha */ + unsigned int alpha_mode, /* 0 global alpha / 1 per pixel alpha / 2 mix mode */ + unsigned int global_a_value, + unsigned int PD_en, /* porter duff alpha mode en */ + unsigned int PD_mode, + unsigned int dst_alpha_en ); /* use dst alpha */ + +int +RGA_set_rop_en_info( + struct rga_req *msg, + unsigned int ROP_mode, + unsigned int ROP_code, + unsigned int color_mode, + unsigned int solid_color + ); + + +int +RGA_set_fading_en_info( + struct rga_req *msg, + unsigned char r, + unsigned char g, + unsigned char b + ); + +int +RGA_set_src_trans_mode_info( + struct rga_req *msg, + unsigned char trans_mode, + unsigned char a_en, + unsigned char b_en, + unsigned char g_en, + unsigned char r_en, + unsigned char color_key_min, + unsigned char color_key_max, + unsigned char zero_mode_en + ); + + +int +RGA_set_bitblt_mode( + struct rga_req *msg, + unsigned char scale_mode, // 0/near 1/bilnear 2/bicubic + unsigned char rotate_mode, // 0/copy 1/rotate_scale 2/x_mirror 3/y_mirror + unsigned int angle, // rotate angle + unsigned int dither_en, // dither en flag + unsigned int AA_en, // AA flag + unsigned int yuv2rgb_mode + ); + + +int +RGA_set_color_palette_mode( + struct rga_req *msg, + unsigned char palette_mode, /* 1bpp/2bpp/4bpp/8bpp */ + unsigned char endian_mode, /* src endian mode sel */ + unsigned int bpp1_0_color, /* BPP1 = 0 */ + unsigned int bpp1_1_color /* BPP1 = 1 */ + ); + + +int +RGA_set_color_fill_mode( + struct rga_req *msg, + COLOR_FILL *gr_color, /* gradient color part */ + unsigned char gr_satur_mode, /* saturation mode */ + unsigned char cf_mode, /* patten fill or solid fill */ + unsigned int color, /* solid color */ + unsigned short pat_width, /* pattern width */ + unsigned short pat_height, /* pattern height */ + unsigned char pat_x_off, /* pattern x offset */ + unsigned char pat_y_off, /* pattern y offset */ + unsigned char aa_en /* alpha en */ + ); + + +int +RGA_set_line_point_drawing_mode( + struct rga_req *msg, + POINT_t sp, /* start point */ + POINT_t ep, /* end point */ + unsigned int color, /* line point drawing color */ + unsigned int line_width, /* line width */ + unsigned char AA_en, /* AA en */ + unsigned char last_point_en /* last point en */ + ); + + +int +RGA_set_blur_sharp_filter_mode( + struct rga_req *msg, + unsigned char filter_mode, /* blur/sharpness */ + unsigned char filter_type, /* filter intensity */ + unsigned char dither_en /* dither_en flag */ + ); + +int +RGA_set_pre_scaling_mode( + struct rga_req *msg, + unsigned char dither_en + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_update_palette_table_mode( + struct rga_req *msg, + unsigned long LUT_addr, /* LUT table addr */ + unsigned int palette_mode /* 1bpp/2bpp/4bpp/8bpp */ + ); +#else +int +RGA_update_palette_table_mode( + struct rga_req *msg, + unsigned int LUT_addr, /* LUT table addr */ + unsigned int palette_mode /* 1bpp/2bpp/4bpp/8bpp */ + ); +#endif + +int +RGA_set_update_patten_buff_mode( + struct rga_req *msg, + unsigned int pat_addr, /* patten addr */ + unsigned int w, /* patten width */ + unsigned int h, /* patten height */ + unsigned int format /* patten format */ + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_mmu_info( + struct rga_req *msg, + unsigned char mmu_en, + unsigned char src_flush, + unsigned char dst_flush, + unsigned char cmd_flush, + unsigned long base_addr, + unsigned char page_size + ); +#else +int +RGA_set_mmu_info( + struct rga_req *msg, + unsigned char mmu_en, + unsigned char src_flush, + unsigned char dst_flush, + unsigned char cmd_flush, + unsigned int base_addr, + unsigned char page_size + ); +#endif + +void rga_set_fds_offsets( + struct rga_req *rga_request, + unsigned short src_fd, + unsigned short dst_fd, + unsigned int src_offset, + unsigned int dst_offset); + +int +RGA_set_src_fence_flag( + struct rga_req *msg, + int acq_fence, + int src_flag +); + + +int +RGA_set_dst_fence_flag( + struct rga_req *msg, + int dst_flag +); + +int +RGA_get_dst_fence( + struct rga_req *msg +); +#ifdef __cplusplus +} +#endif + +#endif /*_RK29_IPP_DRIVER_H_*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image.h new file mode 100644 index 0000000..196dfd5 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image.h @@ -0,0 +1,7559 @@ +/* stb_image - v2.23 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt JR Smith github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image_resize.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image_resize.h new file mode 100644 index 0000000..4f6ad35 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image_resize.h @@ -0,0 +1,2630 @@ +/* stb_image_resize - v0.96 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image_write.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image_write.h new file mode 100644 index 0000000..c117344 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/3rdparty/stb/stb_image_write.h @@ -0,0 +1,1619 @@ +/* stb_image_write - v1.13 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. + +USAGE: + + There are five functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +extern int stbi_write_tga_with_rle; +extern int stbi_write_png_compression_level; +extern int stbi_write_force_png_filter; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBI_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi__flip_vertically_on_write=0; +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi__flip_vertically_on_write=0; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a; arr[1] = b; arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +#ifdef __STDC_WANT_SECURE_LIB__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else + len = snprintf(buffer, 128, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +#endif +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + const unsigned char *imageData = (const unsigned char *)data; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + int x, y, pos; + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float YDU[64], UDU[64], VDU[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + float r, g, b; + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + + r = imageData[p+0]; + g = imageData[p+ofsG]; + b = imageData[p+ofsB]; + YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; + UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; + VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/CMakeLists.txt new file mode 100644 index 0000000..b3b9339 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_batch_inference_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +# utils +include_directories(${CMAKE_SOURCE_DIR}/src/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_batch_inference_demo + src/main.cc +) + +target_link_libraries(rknn_batch_inference_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_batch_inference_demo) +install(TARGETS rknn_batch_inference_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/README.md new file mode 100644 index 0000000..4a4f668 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_batch_inference_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_batch_inference_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_batch_inference_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/build.sh new file mode 100644 index 0000000..70781f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_batch_inference_demo/ +cp run_rv1109_rv1126.sh install/rknn_batch_inference_demo/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rk180x/mobilenet_v1_rk1808_batch_4.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rk180x/mobilenet_v1_rk1808_batch_4.rknn new file mode 100644 index 0000000..a0f9b4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rk180x/mobilenet_v1_rk1808_batch_4.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rv1109_rv1126/mobilenet_v1_rv1109_rv1126_batch_4.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rv1109_rv1126/mobilenet_v1_rv1109_rv1126_batch_4.rknn new file mode 100644 index 0000000..8103d58 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rv1109_rv1126/mobilenet_v1_rv1109_rv1126_batch_4.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rk180x.sh new file mode 100644 index 0000000..2ff2d2a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rk180x.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rk180x" +./rknn_batch_inference_demo model/${chip_dir}/mobilenet_v1_rk1808_batch_4.rknn model/dog_224x224.jpg \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..efac954 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rv1109_rv1126.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +./rknn_batch_inference_demo model/${chip_dir}/mobilenet_v1_rv1109_rv1126_batch_4.rknn model/dog_224x224.jpg \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/src/main.cc new file mode 100644 index 0000000..6cd5a6b --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_batch_inference_demo/src/main.cc @@ -0,0 +1,330 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "rknn_api.h" + +using namespace std; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static int rknn_GetTop( + float *pfProb, + float *pfMaxProb, + uint32_t *pMaxClass, + uint32_t outputCount, + uint32_t topNum) +{ + uint32_t i, j; + +#define MAX_TOP_NUM 20 + if (topNum > MAX_TOP_NUM) + return 0; + + memset(pfMaxProb, 0, sizeof(float) * topNum); + memset(pMaxClass, 0xff, sizeof(float) * topNum); + + for (j = 0; j < topNum; j++) + { + for (i = 0; i < outputCount; i++) + { + if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || + (i == *(pMaxClass + 3)) || (i == *(pMaxClass + 4))) + { + continue; + } + + if (pfProb[i] > *(pfMaxProb + j)) + { + *(pfMaxProb + j) = pfProb[i]; + *(pMaxClass + j) = i; + } + } + } + + return 1; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + const int MODEL_IN_WIDTH = 224; + const int MODEL_IN_HEIGHT = 224; + const int MODEL_IN_CHANNELS = 3; + const int MODEL_IN_BATCHSIZE = 4; + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + + // Load RKNN Model + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image + unsigned char *input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) + { + return -1; + } + + //concat img to batch + int img_size = input_attrs[0].dims[0] * input_attrs[0].dims[1] * input_attrs[0].dims[2] * sizeof(uint8_t); + unsigned char *in_data_batch = NULL; + in_data_batch = (unsigned char *)malloc(MODEL_IN_BATCHSIZE * img_size); + if (!in_data_batch) + { + return -1; + } + for (int i = 0; i < MODEL_IN_BATCHSIZE; ++i) + { + unsigned char *in_data_ptr = in_data_batch + img_size * i; + memcpy(in_data_ptr, input_data, img_size); + } + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = in_data_batch; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + for (int n = 0; n < MODEL_IN_BATCHSIZE; ++n) + { + for (int i = 0; i < io_num.n_output; i++) + { + uint32_t MaxClass[5]; + float fMaxProb[5]; + float *buffer_f32 = (float *)outputs[i].buf; + float *cur_batch_buf = buffer_f32 + 1001 * n; + uint32_t cur_batch_sz = outputs[i].size / (4 * MODEL_IN_BATCHSIZE); + rknn_GetTop(cur_batch_buf, fMaxProb, MaxClass, cur_batch_sz, 5); + + printf(" --- Top5 ---\n"); + for (int i = 0; i < 5; i++) + { + printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); + } + } + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + if (input_data) + { + free(input_data); + } + if (in_data_batch) + { + stbi_image_free(in_data_batch); + } + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/CMakeLists.txt new file mode 100644 index 0000000..c2d48ec --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_mobilenet_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_mobilenet_demo + src/main.cc +) + +target_link_libraries(rknn_mobilenet_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_mobilenet_demo) +install(TARGETS rknn_mobilenet_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/README.md new file mode 100644 index 0000000..7a302a2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_mobilenet_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_mobilenet_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_mobilenet_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/build.sh new file mode 100644 index 0000000..c869f2a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/build.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +# GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/cat_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/cat_224x224.jpg new file mode 100644 index 0000000..11c5ba4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/cat_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rk180x.rknn new file mode 100644 index 0000000..b02f728 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rv1109_rv1126.rknn new file mode 100644 index 0000000..b0f6735 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/src/main.cc new file mode 100644 index 0000000..b0f7de2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_mobilenet_demo/src/main.cc @@ -0,0 +1,327 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "rknn_api.h" + +using namespace std; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static inline int64_t getCurrentTimeUs() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static int rknn_GetTop( + float *pfProb, + float *pfMaxProb, + uint32_t *pMaxClass, + uint32_t outputCount, + uint32_t topNum) +{ + uint32_t i, j; + +#define MAX_TOP_NUM 20 + if (topNum > MAX_TOP_NUM) + return 0; + + memset(pfMaxProb, 0, sizeof(float) * topNum); + memset(pMaxClass, 0xff, sizeof(float) * topNum); + + for (j = 0; j < topNum; j++) + { + for (i = 0; i < outputCount; i++) + { + if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || + (i == *(pMaxClass + 3)) || (i == *(pMaxClass + 4))) + { + continue; + } + + if (pfProb[i] > *(pfMaxProb + j)) + { + *(pfMaxProb + j) = pfProb[i]; + *(pMaxClass + j) = i; + } + } + } + + return 1; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + int loop_count = 1; + if (argc > 3) + { + loop_count = atoi(argv[3]); + } + + // Load RKNN Model + model = load_model(model_path, &model_len); + + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image + unsigned char *input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) + { + return -1; + } + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = input_data; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + for (int n = 0; n < loop_count; ++n) + { + int64_t start_us = getCurrentTimeUs(); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + int64_t elapse_us = getCurrentTimeUs() - start_us; + printf("%4d: Elapse Time = %.2fms, FPS = %.2f\n", n, elapse_us / 1000.f, 1000.f * 1000.f / elapse_us); + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + for (int i = 0; i < io_num.n_output; i++) + { + uint32_t MaxClass[5]; + float fMaxProb[5]; + float *buffer = (float *)outputs[i].buf; + uint32_t sz = outputs[i].size / 4; + + rknn_GetTop(buffer, fMaxProb, MaxClass, sz, 5); + + printf(" --- Top5 ---\n"); + for (int i = 0; i < 5; i++) + { + printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); + } + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + + if (input_data) + { + stbi_image_free(input_data); + } + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/CMakeLists.txt new file mode 100644 index 0000000..3326955 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_multi_input_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +# utils +include_directories(${CMAKE_SOURCE_DIR}/src/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_multi_input_demo + src/main.cc +) + +target_link_libraries(rknn_multi_input_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_multi_input_demo) +install(TARGETS rknn_multi_input_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/README.md new file mode 100644 index 0000000..6782968 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_multi_input_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_multi_input_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_multi_input_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/build.sh new file mode 100644 index 0000000..cbcd900 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_multi_input_demo/ +cp run_rv1109_rv1126.sh install/rknn_multi_input_demo/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/dog_128x128_gray.png b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/dog_128x128_gray.png new file mode 100644 index 0000000..3b3c325 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/dog_128x128_gray.png differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/rk180x/multi_input_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/rk180x/multi_input_rk180x.rknn new file mode 100644 index 0000000..c3c5921 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/rk180x/multi_input_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/rv1109_rv1126/multi_input_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/rv1109_rv1126/multi_input_rv1109_rv1126.rknn new file mode 100644 index 0000000..4232100 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/model/rv1109_rv1126/multi_input_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/run_rk180x.sh new file mode 100644 index 0000000..1f61582 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/run_rk180x.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rk180x" +./rknn_multi_input_demo model/${chip_dir}/multi_input_rk180x.rknn model/dog_128x128_gray.png \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..4b364fd --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/run_rv1109_rv1126.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +./rknn_multi_input_demo model/${chip_dir}/multi_input_rv1109_rv1126.rknn model/dog_128x128_gray.png \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/src/main.cc new file mode 100644 index 0000000..1c26d20 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_multi_input_demo/src/main.cc @@ -0,0 +1,284 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "rknn_api.h" + +using namespace std; + +#define DEMO_INPUT_NUM 4 + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + const int MODEL_IN_WIDTH = 128; + const int MODEL_IN_HEIGHT = 128; + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + + // Load RKNN Model + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + assert(DEMO_INPUT_NUM == io_num.n_input); + // Set Input struct + rknn_input inputs[DEMO_INPUT_NUM]; + memset(inputs, 0, DEMO_INPUT_NUM * sizeof(rknn_input)); + std::vector imgs; + for (int i = 0; i < io_num.n_input; ++i) + { + int channel = 0; + if (input_attrs[i].fmt == RKNN_TENSOR_NCHW) + { + channel = input_attrs[i].dims[2]; + } + else + { + channel = input_attrs[i].dims[0]; + } + //convert single channel to multi channels + // Load image + unsigned char *input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) + { + return -1; + } + imgs.push_back(input_data); + int img_size = input_attrs[0].size; + inputs[i].index = i; + inputs[i].type = RKNN_TENSOR_UINT8; + inputs[i].size = img_size; + inputs[i].fmt = RKNN_TENSOR_NHWC; + } + for (int i = 0; i < io_num.n_input; ++i) + { + inputs[i].buf = imgs[i]; + } + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + float ref_data[5] = {24.482, 20.453, 20.453, 20.453, 20.453}; + float *buffer = (float *)outputs[0].buf; + printf("first 5 result:\n"); + for (int i = 0; i < 5; ++i) + { + printf("[%d]:%.3f vs %.3f\n", i, buffer[i], ref_data[i]); + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + for (auto d : imgs) + { + stbi_image_free(d); + } + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/CMakeLists.txt new file mode 100644 index 0000000..1cf20d4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_pass_through_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +# utils +include_directories(${CMAKE_SOURCE_DIR}/src/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_pass_through_demo + src/main.cc + src/quant_utils.cc +) + +target_link_libraries(rknn_pass_through_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_pass_through_demo) +install(TARGETS rknn_pass_through_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/README.md new file mode 100644 index 0000000..80d9556 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_pass_through_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_pass_through_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_pass_through_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh int8 +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh int8 +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/build.sh new file mode 100644 index 0000000..b39e372 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_pass_through_demo/ +cp run_rv1109_rv1126.sh install/rknn_pass_through_demo/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/cat_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/cat_224x224.jpg new file mode 100644 index 0000000..11c5ba4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/cat_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_FP_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_FP_rk180x.rknn new file mode 100644 index 0000000..a6c328a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_FP_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT16_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT16_rk180x.rknn new file mode 100644 index 0000000..61dc82d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT16_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT8_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT8_rk180x.rknn new file mode 100644 index 0000000..b622a8e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT8_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_UINT8_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_UINT8_rk180x.rknn new file mode 100644 index 0000000..c86d218 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_UINT8_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_FP_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_FP_rv1109_rv1126.rknn new file mode 100644 index 0000000..651fcac Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_FP_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT16_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT16_rv1109_rv1126.rknn new file mode 100644 index 0000000..46b5aaf Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT16_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT8_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT8_rv1109_rv1126.rknn new file mode 100644 index 0000000..eed99da Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT8_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_UINT8_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_UINT8_rv1109_rv1126.rknn new file mode 100644 index 0000000..3308572 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_UINT8_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/run_rk180x.sh new file mode 100644 index 0000000..ffb9880 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/run_rk180x.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +chip_dir="rk180x" +case $1 in + uint8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_UINT8_rk180x.rknn model/dog_224x224.jpg + ;; + int8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT8_rk180x.rknn model/dog_224x224.jpg + ;; + int16) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT16_rk180x.rknn model/dog_224x224.jpg + ;; + fp) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_FP_rk180x.rknn model/dog_224x224.jpg + ;; + *) + echo './run.sh uint8 int8 int16 fp' + ;; +esac + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..4f7166e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/run_rv1109_rv1126.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +case $1 in + uint8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_UINT8_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + int8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT8_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + int16) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT16_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + fp) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_FP_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + *) + echo './run.sh uint8 int8 int16 fp' + ;; +esac + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/main.cc new file mode 100644 index 0000000..59108c4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/main.cc @@ -0,0 +1,484 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "quant_utils.h" +#include "rknn_api.h" + +using namespace std; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d " + "fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], + attr->dims[1], attr->dims[0], attr->n_elems, attr->size, 0, attr->type, + attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static int GetElementByte(rknn_tensor_attr *in_attr) +{ + int byte = 0; + switch (in_attr->type) + { + case RKNN_TENSOR_FLOAT32: + byte = 4; + break; + case RKNN_TENSOR_FLOAT16: + case RKNN_TENSOR_INT16: + byte = 2; + break; + case RKNN_TENSOR_INT8: + case RKNN_TENSOR_UINT8: + byte = 1; + break; + default: + break; + } + return byte; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +static int ProcessInput(unsigned char *src_buf, void **dst_buf, rknn_tensor_attr *in_attr, + std::vector mean, std::vector scale, + bool isReorder210, bool isNCHW) +{ + // check + if (3 != mean.size() || src_buf == NULL) + { + return -1; + } + int img_height, img_width, img_channels = 0; + if (isNCHW) + { + img_width = in_attr->dims[0]; + img_height = in_attr->dims[1]; + img_channels = in_attr->dims[2]; + } + else + { + img_channels = in_attr->dims[0]; + img_width = in_attr->dims[1]; + img_height = in_attr->dims[2]; + } + int HW = img_height * img_width; + int ele_count = HW * img_channels; + int ele_bytes = GetElementByte(in_attr); + printf("total element count = %d, bytes per element = %d\n", ele_count, + ele_bytes); + float *pixel_f = (float *)malloc(ele_count * sizeof(float)); + + // RGB2BGR + if (isReorder210 == true) + { + printf("perform RGB2BGR\n"); + float *f_ptr = pixel_f; + unsigned char *u_ptr = src_buf; + for (int i = 0; i < HW; ++i) + { + f_ptr[2] = u_ptr[0]; + f_ptr[1] = u_ptr[1]; + f_ptr[0] = u_ptr[2]; + u_ptr += img_channels; + f_ptr += img_channels; + } + } + else + { + float *f_ptr = pixel_f; + unsigned char *u_ptr = src_buf; + for (int i = 0; i < ele_count; ++i) + { + f_ptr[i] = u_ptr[i]; + } + } + + // normalize + printf("perform normalize\n"); + float *f_ptr = pixel_f; + for (int i = 0; i < HW; ++i) + { + for (int j = 0; j < img_channels; ++j) + { + f_ptr[j] -= mean[j]; + f_ptr[j] /= scale[j]; + } + f_ptr += img_channels; + } + + // quantize + printf("perform quantize\n"); + uint8_t *qnt_buf = (uint8_t *)malloc(ele_count * ele_bytes); + switch (in_attr->type) + { + case RKNN_TENSOR_FLOAT32: + memcpy(qnt_buf, pixel_f, ele_count * ele_bytes); + break; + case RKNN_TENSOR_FLOAT16: + f32_to_f16((uint16_t *)(qnt_buf), pixel_f, ele_count); + break; + case RKNN_TENSOR_INT16: + case RKNN_TENSOR_INT8: + case RKNN_TENSOR_UINT8: + switch (in_attr->qnt_type) + { + case RKNN_TENSOR_QNT_DFP: + qnt_f32_to_dfp(qnt_buf, in_attr->type, in_attr->fl, pixel_f, ele_count); + break; + case RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + qnt_f32_to_affine(qnt_buf, in_attr->type, in_attr->zp, in_attr->scale, pixel_f, ele_count); + break; + case RKNN_TENSOR_QNT_NONE: + qnt_f32_to_none(qnt_buf, in_attr->type, pixel_f, ele_count); + default: + break; + } + break; + default: + break; + } + + // NHWC ==> NCHW + if (isNCHW) + { + printf("perform NHWC to NCHW\n"); + uint8_t *nchw_buf = (uint8_t *)malloc(ele_count * ele_bytes); + uint8_t *dst_ptr = nchw_buf; + uint8_t *src_ptr = qnt_buf; + for (int i = 0; i < img_channels; ++i) + { + src_ptr = qnt_buf + i * ele_bytes; + dst_ptr = nchw_buf + i * HW * ele_bytes; + for (int j = 0; j < HW; ++j) + { + // dst_ptr[i*HW+j] = src_ptr[j*C+i]; + memcpy(dst_ptr, src_ptr, ele_bytes); + src_ptr += img_channels * ele_bytes; + dst_ptr += ele_bytes; + } + } + *dst_buf = nchw_buf; + free(qnt_buf); + } + else + { + *dst_buf = qnt_buf; + } + + free(pixel_f); + + return 0; +} + +static int rknn_GetTop( + float *pfProb, + float *pfMaxProb, + uint32_t *pMaxClass, + uint32_t outputCount, + uint32_t topNum) +{ + uint32_t i, j; + +#define MAX_TOP_NUM 20 + if (topNum > MAX_TOP_NUM) + return 0; + + memset(pfMaxProb, 0, sizeof(float) * topNum); + memset(pMaxClass, 0xff, sizeof(float) * topNum); + + for (j = 0; j < topNum; j++) + { + for (i = 0; i < outputCount; i++) + { + if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || + (i == *(pMaxClass + 3)) || (i == *(pMaxClass + 4))) + { + continue; + } + + if (pfProb[i] > *(pfMaxProb + j)) + { + *(pfMaxProb + j) = pfProb[i]; + *(pMaxClass + j) = i; + } + } + } + + return 1; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + const int MODEL_IN_WIDTH = 224; + const int MODEL_IN_HEIGHT = 224; + const int MODEL_IN_CHANNELS = 3; + bool isNCHW = false; + // mobilenet v2 mean/scale in rknn.config() + bool isReorder210 = true; /* reorder= '2 1 0' */ + std::vector mean({103.94, 116.78, 123.68}); + std::vector scale({58.82, 58.82, 58.82}); + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + + // Load RKNN Model + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, + io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image + unsigned char *img_data = NULL; + img_data = load_image(img_path, &input_attrs[0]); + if (!img_data) + { + return -1; + } + + // rknn model need nchw layout input + if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) + { + isNCHW = true; + } + + // process input when pass_through = 1 + void *in_data = NULL; + ProcessInput(img_data, &in_data, &(input_attrs[0]), mean, scale, isReorder210, + isNCHW); + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NCHW; + inputs[0].buf = in_data; + inputs[0].pass_through = 1; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + for (int i = 0; i < io_num.n_output; i++) + { + uint32_t MaxClass[5]; + float fMaxProb[5]; + float *buffer = (float *)outputs[i].buf; + uint32_t sz = outputs[i].size / 4; + + rknn_GetTop(buffer, fMaxProb, MaxClass, sz, 5); + + printf(" --- Top5 ---\n"); + for (int i = 0; i < 5; i++) + { + printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); + } + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + stbi_image_free(img_data); + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.cc new file mode 100644 index 0000000..d59e11c --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.cc @@ -0,0 +1,181 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "quant_utils.h" +#include "rknn_api.h" + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + // return (int32_t)((f > 0.0) ? (f + 0.5) : (f - 0.5)); //四舍五入 + return f; +} + +void f32_to_f16(uint16_t *f16, float *f32, int num) +{ + float *src = f32; + uint16_t *dst = f16; + int i = 0; + + for (; i < num; i++) + { + float in = *src; + + uint32_t fp32 = *((uint32_t *)&in); + uint32_t t1 = (fp32 & 0x80000000u) >> 16; /* sign bit. */ + uint32_t t2 = (fp32 & 0x7F800000u) >> 13; /* Exponent bits */ + uint32_t t3 = (fp32 & 0x007FE000u) >> 13; /* Mantissa bits, no rounding */ + uint32_t fp16 = 0u; + + if (t2 >= 0x023c00u) + { + fp16 = t1 | 0x7BFF; /* Don't round to infinity. */ + } + else if (t2 <= 0x01c000u) + { + fp16 = t1; + } + else + { + t2 -= 0x01c000u; + fp16 = t1 | t2 | t3; + } + + *dst = (uint16_t)fp16; + + src++; + dst++; + } +} + +void qnt_f32_to_dfp(uint8_t *qnt, uint8_t type, int8_t fl, float *f32, + int num) +{ + float *src_ptr = f32; + int i = 0; + float dst_val = 0.0; + + switch (type) + { + case RKNN_TENSOR_INT8: + for (; i < num; i++) + { + dst_val = (fl > 0) ? ((*src_ptr) * ((float)(1 << fl))) + : ((*src_ptr) / (float)(1 << -fl)); + *((int8_t *)qnt) = (int8_t)__clip(dst_val, -128, 127); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_UINT8: + for (; i < num; i++) + { + dst_val = (fl > 0) ? ((*src_ptr) * ((float)(1 << fl))) + : ((*src_ptr) / (float)(1 << -fl)); + *qnt = (uint8_t)__clip(dst_val, 0, 255); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_INT16: + for (; i < num; i++) + { + dst_val = (fl > 0) ? ((*src_ptr) * ((float)(1 << fl))) + : ((*src_ptr) / (float)(1 << -fl)); + *((int16_t *)qnt) = (int16_t)__clip(dst_val, -32768, 32767); + src_ptr++; + qnt += 2; + } + break; + default: + break; + } +} + +void qnt_f32_to_affine(uint8_t *qnt, uint8_t type, uint8_t zp, float scale, + float *f32, int num) +{ + float *src_ptr = f32; + int i = 0; + float dst_val = 0.0; + + switch (type) + { + case RKNN_TENSOR_INT8: + for (; i < num; i++) + { + dst_val = ((*src_ptr) / scale) + zp; + *((int8_t *)qnt) = (int8_t)__clip(dst_val, -128, 127); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_UINT8: + for (; i < num; i++) + { + dst_val = ((*src_ptr) / scale) + zp; + *qnt = (uint8_t)__clip(dst_val, 0, 255); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_INT16: + for (; i < num; i++) + { + dst_val = ((*src_ptr) / scale) + zp; + *((int16_t *)qnt) = (int16_t)__clip(dst_val, -32768, 32767); + src_ptr++; + qnt += 2; + } + break; + default: + break; + } +} + +void qnt_f32_to_none(uint8_t *qnt, uint8_t type, float *f32, int num) +{ + float *src_ptr = f32; + int i = 0; + + switch (type) + { + case RKNN_TENSOR_INT8: + for (; i < num; i++) + { + *((int8_t *)qnt) = (int8_t)__clip(*src_ptr, -128, 127); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_UINT8: + for (; i < num; i++) + { + *qnt = (uint8_t)__clip(*src_ptr, 0, 255); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_INT16: + for (; i < num; i++) + { + *((int16_t *)qnt) = (int16_t)__clip(*src_ptr, -32768, 32767); + src_ptr++; + qnt += 2; + } + break; + default: + break; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.h new file mode 100644 index 0000000..f6fa12e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.h @@ -0,0 +1,28 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _RKNN_DEMO_QUANT_UTILS_H_ +#define _RKNN_DEMO_QUANT_UTILS_H_ + +#include + +void f32_to_f16(uint16_t *f16, float *f32, int num); + +void qnt_f32_to_dfp(uint8_t *qnt, uint8_t type, int8_t fl, float *f32, int num); + +void qnt_f32_to_affine(uint8_t *qnt, uint8_t type, uint8_t zp, float scale, float *f32, int num); + +void qnt_f32_to_none(uint8_t *qnt, uint8_t type, float *f32, int num); + +#endif /*_RKNN_DEMO_QUANT_UTILS_H_ */ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/CMakeLists.txt new file mode 100644 index 0000000..0fb7f63 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_ssd_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_ssd_demo + src/main.cc + src/ssd.cc + ) + +target_link_libraries(rknn_ssd_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_ssd_demo) +install(TARGETS rknn_ssd_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/README.md new file mode 100644 index 0000000..bae5217 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/README.md @@ -0,0 +1,39 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_ssd_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_ssd_demo /userdata/ +``` + +- If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + + +## Run + +``` +adb shell +cd /userdata/rknn_ssd_demo/ +``` + +- RK1808/RK1806 +``` +./rknn_ssd_demo model/ssd_inception_v2_rk180x.rknn model/road.bmp +``` + +- RV1109/RV1126 +``` +./rknn_ssd_demo model/ssd_inception_v2_rv1109_rv1126.rknn model/road.bmp +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/build.sh new file mode 100644 index 0000000..6ddeae5 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/build.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=/work/projects/rv1109/git/rv1109/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=~/opts/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/box_priors.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/box_priors.txt new file mode 100644 index 0000000..efc3be4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/box_priors.txt @@ -0,0 +1,4 @@ + 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.16666667 0.16666667 0.16666666 0.16666667 0.16666669 0.16666667 0.16666667 0.16666667 0.16666666 0.16666667 0.16666669 0.16666667 0.16666667 0.16666667 0.16666666 0.16666667 0.16666669 0.16666667 0.5 0.5 0.49999997 0.5 0.5 0.5 0.5 0.5 0.49999997 0.5 0.5 0.5 0.5 0.5 0.49999997 0.5 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.25 0.25 0.25 0.24999999 0.25 0.25 0.25 0.25 0.25 0.24999999 0.25 0.25 0.75 0.75 0.75 0.75 0.74999994 0.75 0.75 0.75 0.75 0.75 0.74999994 0.75 0.5 0.5 0.5 0.5 0.5 0.5 + 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.16666667 0.16666669 0.16666667 0.16666669 0.16666667 0.16666667 0.49999997 0.5 0.5 0.50000006 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333333 0.8333334 0.8333334 0.16666667 0.16666669 0.16666667 0.16666669 0.16666667 0.16666667 0.49999997 0.5 0.5 0.50000006 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333333 0.8333334 0.8333334 0.16666667 0.16666669 0.16666667 0.16666669 0.16666667 0.16666667 0.49999997 0.5 0.5 0.50000006 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333333 0.8333334 0.8333334 0.25 0.25 0.25 0.25 0.25 0.25 0.75 0.75 0.75 0.75 0.75 0.75 0.25 0.25 0.25 0.25 0.25 0.25 0.75 0.75 0.75 0.75 0.75 0.75 0.5 0.5 0.5 0.5 0.5 0.5 + 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.65000004 0.45961943 0.91923887 0.37527767 1.1258893 0.7211102 0.65000004 0.45961943 0.91923887 0.37527767 1.1258893 0.7211102 0.65000004 0.45961943 0.91923887 0.37527767 1.1258893 0.7211102 0.6500001 0.4596194 0.9192388 0.37527764 1.1258893 0.7211102 0.6500001 0.4596194 0.9192388 0.37527764 1.1258893 0.7211102 0.6500001 0.4596194 0.9192388 0.37527764 1.1258893 0.7211102 0.6500001 0.45961946 0.9192388 0.3752777 1.1258893 0.72111017 0.6500001 0.45961946 0.9192388 0.3752777 1.1258893 0.72111017 0.6500001 0.45961946 0.9192388 0.3752777 1.1258893 0.72111017 0.8000001 0.5656855 1.131371 0.4618802 1.3857099 0.8717798 0.8000001 0.5656855 1.131371 0.4618802 1.3857099 0.8717798 0.80000013 0.5656855 1.131371 0.4618802 1.3857098 0.87177986 0.80000013 0.5656855 1.131371 0.4618802 1.3857098 0.87177986 0.95000005 0.6717515 1.343503 0.5484828 1.6455305 0.97467947 + 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.6499999 0.9192387 0.45961934 1.1258329 0.3752589 0.7211102 0.64999986 0.9192387 0.4596193 1.125833 0.37525892 0.7211102 0.64999986 0.91923875 0.45961928 1.1258328 0.37525892 0.72111017 0.6499999 0.9192387 0.45961934 1.1258329 0.3752589 0.7211102 0.64999986 0.9192387 0.4596193 1.125833 0.37525892 0.7211102 0.64999986 0.91923875 0.45961928 1.1258328 0.37525892 0.72111017 0.6499999 0.9192387 0.45961934 1.1258329 0.3752589 0.7211102 0.64999986 0.9192387 0.4596193 1.125833 0.37525892 0.7211102 0.64999986 0.91923875 0.45961928 1.1258328 0.37525892 0.72111017 0.79999995 1.1313708 0.5656854 1.3856406 0.46185714 0.8717798 0.79999995 1.1313708 0.56568533 1.3856406 0.46185708 0.87177986 0.79999995 1.1313708 0.5656854 1.3856406 0.46185714 0.8717798 0.79999995 1.1313708 0.56568533 1.3856406 0.46185708 0.87177986 0.9499999 1.3435028 0.6717514 1.6454482 0.54845536 0.97467947 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/coco_labels_list.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/coco_labels_list.txt new file mode 100644 index 0000000..c634db4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/coco_labels_list.txt @@ -0,0 +1,91 @@ +??? +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +??? +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +??? +backpack +umbrella +??? +??? +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +??? +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +??? +dining table +??? +??? +toilet +??? +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +??? +book +clock +vase +scissors +teddy bear +hair drier +toothbrush \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/road.bmp b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/road.bmp new file mode 100644 index 0000000..1254b96 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/road.bmp differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rk180x.rknn new file mode 100644 index 0000000..712b791 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rv1109_rv1126.rknn new file mode 100644 index 0000000..a65660e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/main.cc new file mode 100644 index 0000000..b4e9559 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/main.cc @@ -0,0 +1,277 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include + +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb/stb_image_write.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#undef cimg_display +#define cimg_display 0 +#include "CImg/CImg.h" +#include "rknn_api.h" +#include "ssd.h" + +using namespace std; +using namespace cimg_library; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr* attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d " + "scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char* load_model(const char* filename, int* model_size) +{ + FILE* fp = fopen(filename, "rb"); + if (fp == nullptr) { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char* model = (unsigned char*)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) { + fclose(fp); + } + return model; +} +static unsigned char* load_image(const char* image_path, rknn_tensor_attr* input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char* image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) { + unsigned char* image_resized = (unsigned char*)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char** argv) +{ + const int img_width = 300; + const int img_height = 300; + const int img_channels = 3; + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char* model; + + const char* model_path = argv[1]; + const char* img_path = argv[2]; + + if (argc != 3) { + printf("Usage:%s model image\n", argv[0]); + return -1; + } + if (strstr(img_path, ".jpg") != NULL || strstr(img_path, ".png") != NULL) { + printf("Error: read %s failed! only support .bmp format image\n", img_path); + return -1; + } + + // Load RKNN Model + printf("Loading model ...\n"); + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image, only support .bmp format + CImg img(img_path); + if (img.height() != img_height || img.width() != img_width) { + img = img.resize(img_width, img_height); + } + unsigned char* input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) { + return -1; + } + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = input_data; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[2]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + outputs[1].want_float = 1; + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + if (ret < 0) { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + detect_result_group_t detect_result_group; + postProcessSSD((float*)(outputs[0].buf), (float*)(outputs[1].buf), img_height, img_width, &detect_result_group); + // Release rknn_outputs + rknn_outputs_release(ctx, 2, outputs); + + // Draw Objects + const unsigned char blue[] = {0, 0, 255}; + for (int i = 0; i < detect_result_group.count; i++) { + detect_result_t* det_result = &(detect_result_group.results[i]); + printf("%s @ (%d %d %d %d) %f\n", det_result->name, det_result->box.left, det_result->box.top, + det_result->box.right, det_result->box.bottom, det_result->prop); + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + // draw box + img.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U); + img.draw_text(x1, y1 - 12, det_result->name, blue); + } + img.save("./out.bmp"); + + // Release + if (ctx >= 0) { + rknn_destroy(ctx); + } + if (model) { + free(model); + } + if (input_data) { + stbi_image_free(input_data); + } + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.cc new file mode 100644 index 0000000..2dccac7 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.cc @@ -0,0 +1,323 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "ssd.h" + +#define BOX_PRIORS_TXT_PATH "./model/box_priors.txt" +#define LABEL_NALE_TXT_PATH "./model/coco_labels_list.txt" + +float MIN_SCORE = 0.4f; +float NMS_THRESHOLD = 0.45f; + +static char* labels[NUM_CLASS]; +static float box_priors[4][NUM_RESULTS]; + +int64_t getCurrentTimeUs() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +char* readLine(FILE* fp, char* buffer, int* len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char*)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) { + buff_len++; + void* tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) { + free(buffer); + return NULL; // Out of memory + } + buffer = (char*)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char* fileName, char* lines[], int max_line) +{ + FILE* file = fopen(fileName, "r"); + char* s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + +int loadLabelName(const char* locationFilename, char* label[]) +{ + printf("ssd - loadLabelName %s\n", locationFilename); + readLines(locationFilename, label, NUM_CLASS); + return 0; +} + +int loadBoxPriors(const char* locationFilename, float (*boxPriors)[NUM_RESULTS]) +{ + const char* d = " "; + char* lines[4]; + int count = readLines(locationFilename, lines, 4); + // printf("line count %d\n", count); + // for (int i = 0; i < count; i++) { + // printf("%s\n", lines[i]); + // } + for (int i = 0; i < 4; i++) { + char* line_str = lines[i]; + char* p; + p = strtok(line_str, d); + int priorIndex = 0; + while (p) { + float number = (float)(atof(p)); + boxPriors[i][priorIndex++] = number; + p = strtok(NULL, d); + } + if (priorIndex != NUM_RESULTS) { + printf("error\n"); + return -1; + } + } + return 0; +} + +float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, + float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1)); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1)); + float i = w * h; + float u = (xmax0 - xmin0) * (ymax0 - ymin0) + (xmax1 - xmin1) * (ymax1 - ymin1) - i; + return u <= 0.f ? 0.f : (i / u); +} + +float unexpit(float y) { return -1.0 * logf((1.0 / y) - 1.0); } + +float expit(float x) { return (float)(1.0 / (1.0 + expf(-x))); } + +void decodeCenterSizeBoxes(float* predictions, float (*boxPriors)[NUM_RESULTS]) +{ + for (int i = 0; i < NUM_RESULTS; ++i) { + float ycenter = predictions[i * 4 + 0] / Y_SCALE * boxPriors[2][i] + boxPriors[0][i]; + float xcenter = predictions[i * 4 + 1] / X_SCALE * boxPriors[3][i] + boxPriors[1][i]; + float h = (float)expf(predictions[i * 4 + 2] / H_SCALE) * boxPriors[2][i]; + float w = (float)expf(predictions[i * 4 + 3] / W_SCALE) * boxPriors[3][i]; + + float ymin = ycenter - h / 2.0f; + float xmin = xcenter - w / 2.0f; + float ymax = ycenter + h / 2.0f; + float xmax = xcenter + w / 2.0f; + + predictions[i * 4 + 0] = ymin; + predictions[i * 4 + 1] = xmin; + predictions[i * 4 + 2] = ymax; + predictions[i * 4 + 3] = xmax; + } +} + +int filterValidResult(float* outputClasses, int (*output)[NUM_RESULTS], int numClasses, float* props) +{ + int validCount = 0; + float min_score = unexpit(MIN_SCORE); + + // Scale them back to the input size. + for (int i = 0; i < NUM_RESULTS; ++i) { + float topClassScore = (float)(-1000.0); + int topClassScoreIndex = -1; + + // Skip the first catch-all class. + for (int j = 1; j < numClasses; ++j) { + // x and expit(x) has same monotonicity + // so compare x and comare expit(x) is same + // float score = expit(outputClasses[i*numClasses+j]); + float score = outputClasses[i * numClasses + j]; + + if (score > topClassScore) { + topClassScoreIndex = j; + topClassScore = score; + } + } + + if (topClassScore >= min_score) { + output[0][validCount] = i; + output[1][validCount] = topClassScoreIndex; + props[validCount] = expit(outputClasses[i * numClasses + topClassScoreIndex]); + ++validCount; + } + } + + return validCount; +} + +int nms(int validCount, float* outputLocations, int (*output)[NUM_RESULTS]) +{ + for (int i = 0; i < validCount; ++i) { + if (output[0][i] == -1) { + continue; + } + int n = output[0][i]; + for (int j = i + 1; j < validCount; ++j) { + int m = output[0][j]; + if (m == -1) { + continue; + } + float xmin0 = outputLocations[n * 4 + 1]; + float ymin0 = outputLocations[n * 4 + 0]; + float xmax0 = outputLocations[n * 4 + 3]; + float ymax0 = outputLocations[n * 4 + 2]; + + float xmin1 = outputLocations[m * 4 + 1]; + float ymin1 = outputLocations[m * 4 + 0]; + float xmax1 = outputLocations[m * 4 + 3]; + float ymax1 = outputLocations[m * 4 + 2]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou >= NMS_THRESHOLD) { + output[0][j] = -1; + } + } + } + return 0; +} + +void sort(int output[][1917], float* props, int sz) +{ + int i = 0; + int j = 0; + + if (sz < 2) { + return; + } + + for (i = 0; i < sz - 1; i++) { + int top = i; + for (j = i + 1; j < sz; j++) { + if (props[top] < props[j]) { + top = j; + } + } + + if (i != top) { + int tmp1 = output[0][i]; + int tmp2 = output[1][i]; + float prop = props[i]; + output[0][i] = output[0][top]; + output[1][i] = output[1][top]; + props[i] = props[top]; + output[0][top] = tmp1; + output[1][top] = tmp2; + props[top] = prop; + } + } +} + +int postProcessSSD(float* predictions, float* output_classes, int width, int heigh, detect_result_group_t* group) +{ + static int init = -1; + if (init == -1) { + int ret = 0; + printf("loadLabelName\n"); + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) { + return -1; + } + + printf("loadBoxPriors\n"); + ret = loadBoxPriors(BOX_PRIORS_TXT_PATH, box_priors); + if (ret < 0) { + return -1; + } + + init = 0; + } + + int output[2][NUM_RESULTS]; + float props[NUM_RESULTS]; + memset(output, 0, 2 * NUM_RESULTS); + memset(props, 0, sizeof(float) * NUM_RESULTS); + + decodeCenterSizeBoxes(predictions, box_priors); + + int validCount = filterValidResult(output_classes, output, NUM_CLASS, props); + + if (validCount > OBJ_NUMB_MAX_SIZE) { + printf("validCount too much !!\n"); + return -1; + } + + sort(output, props, validCount); + + /* detect nest box */ + nms(validCount, predictions, output); + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) { + if (output[0][i] == -1) { + continue; + } + int n = output[0][i]; + int topClassScoreIndex = output[1][i]; + + int x1 = (int)(predictions[n * 4 + 1] * width); + int y1 = (int)(predictions[n * 4 + 0] * heigh); + int x2 = (int)(predictions[n * 4 + 3] * width); + int y2 = (int)(predictions[n * 4 + 2] * heigh); + // There are a bug show toothbrush always + if (x1 == 0 && x2 == 0 && y1 == 0 && y2 == 0) + continue; + char* label = labels[topClassScoreIndex]; + + group->results[last_count].box.left = x1; + group->results[last_count].box.top = y1; + group->results[last_count].box.right = x2; + group->results[last_count].box.bottom = y2; + group->results[last_count].prop = props[i]; + memcpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("ssd result %2d: (%4d, %4d, %4d, %4d), %4.2f, %s\n", i, x1, y1, x2, y2, props[i], label); + last_count++; + } + + group->count = last_count; + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.h new file mode 100644 index 0000000..ff910a0 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.h @@ -0,0 +1,58 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SSD_H_ +#define _SSD_H_ + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 64 + +typedef struct _BOX_RECT { + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t { + char name[OBJ_NAME_MAX_SIZE]; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t { + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + +#define IMG_CHANNEL 3 +#define MODEL_INPUT_SIZE 300 +#define NUM_RESULTS 1917 +#define NUM_CLASS 91 + +#define Y_SCALE 10.0f +#define X_SCALE 10.0f +#define H_SCALE 5.0f +#define W_SCALE 5.0f + +int loadLabelName(const char* locationFilename, char* labels[]); + +int loadBoxPriors(const char* locationFilename, float (*boxPriors)[NUM_RESULTS]); + +int postProcessSSD(float * predictions, float *output_classes, int width, int heigh, detect_result_group_t *group); + +int64_t getCurrentTimeUs(); + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/CMakeLists.txt new file mode 100644 index 0000000..d7ea9d6 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_yolov5_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s -O3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s -O3") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rga +set(RGA_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/rga) +include_directories(${RGA_DIR}/include) + +# drm +set(DRM_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/drm) +include_directories(${DRM_DIR}/include) +include_directories(${DRM_DIR}/include/libdrm) + +include_directories(${CMAKE_SOURCE_DIR}/include) + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_yolov5_demo + src/drm_func.c + src/rga_func.c + src/postprocess.cc + src/main.cc + ) + +target_link_libraries(rknn_yolov5_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_yolov5_demo) +install(TARGETS rknn_yolov5_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/README.md new file mode 100644 index 0000000..e8086cc --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/README.md @@ -0,0 +1,64 @@ +# Yolo-v5 demo + +## 导出rknn模型 + +请参考 https://github.com/airockchip/rknn_model_zoo/tree/main/models/vision/object_detection/yolov5-pytorch + + + +## 注意事项: + +1. 使用rknn-toolkit版本大于等于1.7.0。 +2. 本Demo只支持8比特非对称量化的rknn模型推理。 +3. 切换成自己训练的模型时,请注意对齐anchor等后处理参数,否则会导致后处理解析出错。 +4. 官网和rk预训练模型都是检测80类的目标,如果自己训练的模型,自行更改include/postprocess.h中的OBJ_CLASS_NUM以及NMS_THRESH,BOX_THRESH后处理参数后再编译。 +5. 由于硬件限制,该demo的模型默认把 yolov5 模型的后处理部分,移至cpu实现。本demo附带的模型均使用relu为激活函数,相比silu激活函数精度略微下降,推理速度更快。 +6. 关于加载时间:model目录下均是预编译rknn模型,加载速度比非预编译rknn模型快。convert_rknn_demo目录下的转换脚本生成非预编译rknn模型,如需重新生成预编译rknn模型,请参考rknn-toolkit的User Guide. + + +## Aarch64 Linux Demo + +### 编译 + +根据指定平台修改`build.sh`中的交叉编译器所在目录的路径`GCC_COMPILER`,例如修改成 + +```sh +GCC_COMPILER=~/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf +``` + +然后执行: + +```sh +./build.sh +``` + +### 推送执行文件到板子 + +将 install/rknn_yolov5_demo 拷贝到板子的/userdata/目录. + +- 如果使用rockchip的EVB板子,可以使用adb将文件推到板子上: + +```sh +adb push install/rknn_yolov5_demo /userdata/ +``` + +如果使用其他板子,可以使用scp等方式将install/rknn_yolov5_demo拷贝到板子的/userdata/目录 + +## 运行 + +```sh +adb shell +cd /userdata/rknn_yolov5_demo/ +``` + +- rk180x + +```sh +./run_rk180x.sh +``` + +- rv1109/rv1126 + +```sh +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/build.sh new file mode 100644 index 0000000..334bf73 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/build.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_yolov5_demo/ +cp run_rv1109_rv1126.sh install/rknn_yolov5_demo/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/bus.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/bus.jpg new file mode 100644 index 0000000..d8ef30b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/bus.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/dataset.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/dataset.txt new file mode 100644 index 0000000..a81b1f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/dataset.txt @@ -0,0 +1 @@ +bus.jpg diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py new file mode 100644 index 0000000..9f4ec6e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py @@ -0,0 +1,40 @@ +from rknn.api import RKNN + +ONNX_MODEL = './onnx_models/yolov5s_rm_transpose.onnx' +# platform="rk1808" +platform = "rv1109" +RKNN_MODEL = 'yolov5s_relu_{}_out_opt.rknn'.format(platform) + + +if __name__ == '__main__': + + add_perm = False # 如果设置成True,则将模型输入layout修改成NHWC + # Create RKNN object + rknn = RKNN(verbose=True) + + # pre-process config + print('--> config model') + rknn.config(batch_size=1, mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], reorder_channel='0 1 2', target_platform=[platform], + force_builtin_perm=add_perm, output_optimize=1) + print('done') + + # Load tensorflow model + print('--> Loading model') + ret = rknn.load_onnx(model=ONNX_MODEL) + if ret != 0: + print('Load resnet50v2 failed!') + exit(ret) + print('done') + + # Build model + print('--> Building model') + ret = rknn.build(do_quantization=True, dataset='./dataset.txt') + if ret != 0: + print('Build resnet50 failed!') + exit(ret) + print('done') + + # rknn.export_rknn_precompile_model(RKNN_MODEL) + rknn.export_rknn(RKNN_MODEL) + + rknn.release() diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/bus.jpg b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/bus.jpg new file mode 100644 index 0000000..d8ef30b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/bus.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/dataset.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/dataset.txt new file mode 100644 index 0000000..a81b1f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/dataset.txt @@ -0,0 +1 @@ +bus.jpg diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/yolov5s_rm_transpose.onnx b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/yolov5s_rm_transpose.onnx new file mode 100644 index 0000000..0a340ed Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/yolov5s_rm_transpose.onnx differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/drm_func.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/drm_func.h new file mode 100644 index 0000000..0a9e3b3 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/drm_func.h @@ -0,0 +1,53 @@ +#ifndef __DRM_FUNC_H__ +#define __DRM_FUNC_H__ +#include +#include +#include +#include +#include // open function +#include // close function +#include +#include + + +#include +#include "libdrm/drm_fourcc.h" +#include "xf86drm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (* FUNC_DRM_IOCTL)(int fd, unsigned long request, void *arg); + +typedef struct _drm_context{ + void *drm_handle; + FUNC_DRM_IOCTL io_func; +} drm_context; + +/* memory type definitions. */ +enum drm_rockchip_gem_mem_type +{ + /* Physically Continuous memory and used as default. */ + ROCKCHIP_BO_CONTIG = 1 << 0, + /* cachable mapping. */ + ROCKCHIP_BO_CACHABLE = 1 << 1, + /* write-combine mapping. */ + ROCKCHIP_BO_WC = 1 << 2, + ROCKCHIP_BO_SECURE = 1 << 3, + ROCKCHIP_BO_MASK = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_CACHABLE | + ROCKCHIP_BO_WC | ROCKCHIP_BO_SECURE +}; + +int drm_init(drm_context *drm_ctx); + +void* drm_buf_alloc(drm_context *drm_ctx,int drm_fd, int TexWidth, int TexHeight,int bpp,int *fd,unsigned int *handle,size_t *actual_size); + +int drm_buf_destroy(drm_context *drm_ctx,int drm_fd,int buf_fd, int handle,void *drm_buf,size_t size); + +void drm_deinit(drm_context *drm_ctx, int drm_fd); + +#ifdef __cplusplus +} +#endif +#endif /*__DRM_FUNC_H__*/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/postprocess.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/postprocess.h new file mode 100644 index 0000000..e474505 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/postprocess.h @@ -0,0 +1,40 @@ +#ifndef _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ +#define _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ + +#include + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 64 +#define OBJ_CLASS_NUM 80 +#define NMS_THRESH 0.6 +#define BOX_THRESH 0.5 +#define PROP_BOX_SIZE (5+OBJ_CLASS_NUM) + +typedef struct _BOX_RECT +{ + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t +{ + char name[OBJ_NAME_MAX_SIZE]; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t +{ + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + +int post_process(uint8_t *input0, uint8_t *input1, uint8_t *input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector &qnt_zps, std::vector &qnt_scales, + detect_result_group_t *group); + +#endif //_RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/rga_func.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/rga_func.h new file mode 100644 index 0000000..beeb441 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/include/rga_func.h @@ -0,0 +1,33 @@ +#ifndef __RGA_FUNC_H__ +#define __RGA_FUNC_H__ + +#include +#include "RgaApi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(* FUNC_RGA_INIT)(); +typedef void(* FUNC_RGA_DEINIT)(); +typedef int(* FUNC_RGA_BLIT)(rga_info_t *, rga_info_t *, rga_info_t *); + +typedef struct _rga_context{ + void *rga_handle; + FUNC_RGA_INIT init_func; + FUNC_RGA_DEINIT deinit_func; + FUNC_RGA_BLIT blit_func; +} rga_context; + +int RGA_init(rga_context* rga_ctx); + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h); + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h); + +int RGA_deinit(rga_context* rga_ctx); + +#ifdef __cplusplus +} +#endif +#endif/*__RGA_FUNC_H__*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/bus.bmp b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/bus.bmp new file mode 100644 index 0000000..82df079 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/bus.bmp differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt new file mode 100644 index 0000000..941cb4e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +dining table +toilet +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/rk180x/yolov5s_relu_rk180x_out_opt.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/rk180x/yolov5s_relu_rk180x_out_opt.rknn new file mode 100644 index 0000000..b240c62 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/rk180x/yolov5s_relu_rk180x_out_opt.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_out_opt.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_out_opt.rknn new file mode 100644 index 0000000..0692c1c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_out_opt.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/run_rk180x.sh new file mode 100644 index 0000000..f8492f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/run_rk180x.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +chip_dir="rk180x" +./rknn_yolov5_demo model/${chip_dir}/yolov5s_relu_rk180x_out_opt.rknn model/bus.bmp + + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..54d81fe --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/run_rv1109_rv1126.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +./rknn_yolov5_demo model/${chip_dir}/yolov5s_relu_rv1109_rv1126_out_opt.rknn model/bus.bmp + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/drm_func.c b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/drm_func.c new file mode 100644 index 0000000..2992326 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/drm_func.c @@ -0,0 +1,163 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "drm_func.h" + +#include + +int drm_init(drm_context* drm_ctx) +{ + static const char* card = "/dev/dri/card0"; + int flag = O_RDWR; + int drm_fd = -1; + + drm_fd = open(card, flag); + if (drm_fd < 0) { + printf("failed to open %s\n", card); + return -1; + } + + drm_ctx->drm_handle = dlopen("/usr/lib/libdrm.so", RTLD_LAZY); + if (!drm_ctx->drm_handle) { + printf("failed to dlopen /usr/lib/libdrm.so\n"); + drm_deinit(drm_ctx, drm_fd); + return -1; + } + + drm_ctx->io_func = (FUNC_DRM_IOCTL)dlsym(drm_ctx->drm_handle, "drmIoctl"); + if (drm_ctx->io_func == NULL) { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + drm_deinit(drm_ctx, drm_fd); + printf("failed to dlsym drmIoctl\n"); + return -1; + } + return drm_fd; +} + +void drm_deinit(drm_context* drm_ctx, int drm_fd) +{ + if (drm_ctx->drm_handle) { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + } + if (drm_fd > 0) { + close(drm_fd); + } +} + +void* drm_buf_alloc(drm_context* drm_ctx, int drm_fd, int TexWidth, int TexHeight, int bpp, int* fd, + unsigned int* handle, size_t* actual_size) +{ + int ret; + if (drm_ctx == NULL) { + printf("drm context is unvalid\n"); + return NULL; + } + char* map = NULL; + + void* vir_addr = NULL; + struct drm_prime_handle fd_args; + struct drm_mode_map_dumb mmap_arg; + struct drm_mode_destroy_dumb destory_arg; + + struct drm_mode_create_dumb alloc_arg; + + memset(&alloc_arg, 0, sizeof(alloc_arg)); + alloc_arg.bpp = bpp; + alloc_arg.width = TexWidth; + alloc_arg.height = TexHeight; + // alloc_arg.flags = ROCKCHIP_BO_CONTIG; + + //获取handle和size + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg); + if (ret) { + printf("failed to create dumb buffer: %s\n", strerror(errno)); + return NULL; + } + if (handle != NULL) { + *handle = alloc_arg.handle; + } + if (actual_size != NULL) { + *actual_size = alloc_arg.size; + } + // printf("create width=%u, height=%u, bpp=%u, size=%lu dumb + // buffer\n",alloc_arg.width,alloc_arg.height,alloc_arg.bpp,alloc_arg.size); printf("out handle= + // %d\n",alloc_arg.handle); + + //获取fd + memset(&fd_args, 0, sizeof(fd_args)); + fd_args.fd = -1; + fd_args.handle = alloc_arg.handle; + ; + fd_args.flags = 0; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args); + if (ret) { + printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle); + return NULL; + } + // printf("out fd = %d, drm fd: %d\n",fd_args.fd,drm_fd); + if (fd != NULL) { + *fd = fd_args.fd; + } + + //获取虚拟地址 + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = alloc_arg.handle; + + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg); + if (ret) { + printf("failed to create map dumb: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + vir_addr = map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset); + if (map == MAP_FAILED) { + printf("failed to mmap buffer: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + // printf("alloc map=%x \n",map); + return vir_addr; +destory_dumb: + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = alloc_arg.handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d\n", ret); + return vir_addr; +} + +int drm_buf_destroy(drm_context* drm_ctx, int drm_fd, int buf_fd, int handle, void* drm_buf, size_t size) +{ + int ret = -1; + if (drm_buf == NULL) { + printf("drm buffer is NULL\n"); + return -1; + } + + munmap(drm_buf, size); + + struct drm_mode_destroy_dumb destory_arg; + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno)); + if (buf_fd > 0) { + close(buf_fd); + } + + return ret; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/main.cc new file mode 100644 index 0000000..db229bc --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/main.cc @@ -0,0 +1,417 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include + +#include + +#define _BASETSD_H + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#undef cimg_display +#define cimg_display 0 +#include "CImg/CImg.h" +#include "drm_func.h" +#include "postprocess.h" +#include "rga_func.h" +#include "rknn_api.h" + +#define PERF_WITH_POST 1 + +using namespace cimg_library; +/*------------------------------------------- + Functions +-------------------------------------------*/ + +inline const char* get_type_string(rknn_tensor_type type) +{ + switch (type) { + case RKNN_TENSOR_FLOAT32: + return "FP32"; + case RKNN_TENSOR_FLOAT16: + return "FP16"; + case RKNN_TENSOR_INT8: + return "INT8"; + case RKNN_TENSOR_UINT8: + return "UINT8"; + case RKNN_TENSOR_INT16: + return "INT16"; + default: + return "UNKNOW"; + } +} + +inline const char* get_qnt_type_string(rknn_tensor_qnt_type type) +{ + switch (type) { + case RKNN_TENSOR_QNT_NONE: + return "NONE"; + case RKNN_TENSOR_QNT_DFP: + return "DFP"; + case RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + return "AFFINE"; + default: + return "UNKNOW"; + } +} + +inline const char* get_format_string(rknn_tensor_format fmt) +{ + switch (fmt) { + case RKNN_TENSOR_NCHW: + return "NCHW"; + case RKNN_TENSOR_NHWC: + return "NHWC"; + default: + return "UNKNOW"; + } +} + +static void dump_tensor_attr(rknn_tensor_attr* attr) +{ + printf(" index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, " + "zp=%d, scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, get_format_string(attr->fmt), get_type_string(attr->type), + get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale); +} + +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static unsigned char* load_data(FILE* fp, size_t ofst, size_t sz) +{ + unsigned char* data; + int ret; + + data = NULL; + + if (NULL == fp) { + return NULL; + } + + ret = fseek(fp, ofst, SEEK_SET); + if (ret != 0) { + printf("blob seek failure.\n"); + return NULL; + } + + data = (unsigned char*)malloc(sz); + if (data == NULL) { + printf("buffer malloc failure.\n"); + return NULL; + } + ret = fread(data, 1, sz, fp); + return data; +} + +static unsigned char* load_model(const char* filename, int* model_size) +{ + FILE* fp; + unsigned char* data; + + fp = fopen(filename, "rb"); + if (NULL == fp) { + printf("Open file %s failed.\n", filename); + return NULL; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + + data = load_data(fp, 0, size); + + fclose(fp); + + *model_size = size; + return data; +} + +static int saveFloat(const char* file_name, float* output, int element_size) +{ + FILE* fp; + fp = fopen(file_name, "w"); + for (int i = 0; i < element_size; i++) { + fprintf(fp, "%.6f\n", output[i]); + } + fclose(fp); + return 0; +} + +static unsigned char* load_image(const char* image_path, int* org_height, int* org_width, int* org_ch, + rknn_tensor_attr* input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char* image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) { + printf("load image failed!\n"); + return NULL; + } + *org_width = width; + *org_height = height; + *org_ch = channel; + + return image_data; +} + +/*------------------------------------------- + Main Functions +-------------------------------------------*/ +int main(int argc, char** argv) +{ + int status = 0; + char* model_name = NULL; + rknn_context ctx; + void* drm_buf = NULL; + int drm_fd = -1; + int buf_fd = -1; // converted from buffer handle + unsigned int handle; + size_t actual_size = 0; + int img_width = 0; + int img_height = 0; + int img_channel = 0; + rga_context rga_ctx; + drm_context drm_ctx; + const float nms_threshold = NMS_THRESH; + const float box_conf_threshold = BOX_THRESH; + struct timeval start_time, stop_time; + int ret; + memset(&rga_ctx, 0, sizeof(rga_context)); + memset(&drm_ctx, 0, sizeof(drm_context)); + + if (argc != 3) { + printf("Usage: %s \n", argv[0]); + return -1; + } + + printf("post process config: box_conf_threshold = %.2f, nms_threshold = %.2f\n", box_conf_threshold, nms_threshold); + + model_name = (char*)argv[1]; + char* image_name = argv[2]; + + if (strstr(image_name, ".jpg") != NULL || strstr(image_name, ".png") != NULL) { + printf("Error: read %s failed! only support .bmp format image\n", image_name); + return -1; + } + + /* Create the neural network */ + printf("Loading mode...\n"); + int model_data_size = 0; + unsigned char* model_data = load_model(model_name, &model_data_size); + ret = rknn_init(&ctx, model_data, model_data_size, 0); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, sizeof(rknn_sdk_version)); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("sdk version: %s driver version: %s\n", version.api_version, version.drv_version); + + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + dump_tensor_attr(&(input_attrs[i])); + } + + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + dump_tensor_attr(&(output_attrs[i])); + if (output_attrs[i].qnt_type != RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC || output_attrs[i].type != RKNN_TENSOR_UINT8) { + fprintf(stderr, + "The Demo required for a Affine asymmetric u8 quantized rknn model, but output quant type is %s, output " + "data type is %s\n", + get_qnt_type_string(output_attrs[i].qnt_type), get_type_string(output_attrs[i].type)); + return -1; + } + } + + int channel = 3; + int width = 0; + int height = 0; + if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) { + printf("model is NCHW input fmt\n"); + width = input_attrs[0].dims[0]; + height = input_attrs[0].dims[1]; + } else { + printf("model is NHWC input fmt\n"); + width = input_attrs[0].dims[1]; + height = input_attrs[0].dims[2]; + } + + printf("model input height=%d, width=%d, channel=%d\n", height, width, channel); + + // Load image + CImg img(image_name); + unsigned char* input_data = NULL; + input_data = load_image(image_name, &img_height, &img_width, &img_channel, &input_attrs[0]); + if (!input_data) { + return -1; + } + + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = width * height * channel; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].pass_through = 0; + + // DRM alloc buffer + drm_fd = drm_init(&drm_ctx); + drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, img_width, img_height, channel * 8, &buf_fd, &handle, &actual_size); + memcpy(drm_buf, input_data, img_width * img_height * channel); + void* resize_buf = malloc(height * width * channel); + + // init rga context + RGA_init(&rga_ctx); + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + inputs[0].buf = resize_buf; + gettimeofday(&start_time, NULL); + rknn_inputs_set(ctx, io_num.n_input, inputs); + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) { + outputs[i].want_float = 0; + } + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + gettimeofday(&stop_time, NULL); + printf("once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000); + + // post process + float scale_w = (float)width / img_width; + float scale_h = (float)height / img_height; + + detect_result_group_t detect_result_group; + std::vector out_scales; + std::vector out_zps; + for (int i = 0; i < io_num.n_output; ++i) { + out_scales.push_back(output_attrs[i].scale); + out_zps.push_back(output_attrs[i].zp); + } + post_process((uint8_t*)outputs[0].buf, (uint8_t*)outputs[1].buf, (uint8_t*)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); + + // Draw Objects + char text[256]; + const unsigned char blue[] = {0, 0, 255}; + const unsigned char white[] = {255, 255, 255}; + for (int i = 0; i < detect_result_group.count; i++) { + detect_result_t* det_result = &(detect_result_group.results[i]); + sprintf(text, "%s %.2f", det_result->name, det_result->prop); + printf("%s @ (%d %d %d %d) %f\n", det_result->name, det_result->box.left, det_result->box.top, + det_result->box.right, det_result->box.bottom, det_result->prop); + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + // draw box + img.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U); + img.draw_text(x1, y1 - 12, text, white); + } + img.save("./out.bmp"); + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + + // loop test + int test_count = 10; + gettimeofday(&start_time, NULL); + for (int i = 0; i < test_count; ++i) { + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + rknn_inputs_set(ctx, io_num.n_input, inputs); + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); +#if PERF_WITH_POST + post_process((uint8_t*)outputs[0].buf, (uint8_t*)outputs[1].buf, (uint8_t*)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); +#endif + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + } + gettimeofday(&stop_time, NULL); + printf("loop count = %d , average run %f ms\n", test_count, + (__get_us(stop_time) - __get_us(start_time)) / 1000.0 / test_count); + + // release + ret = rknn_destroy(ctx); + drm_buf_destroy(&drm_ctx, drm_fd, buf_fd, handle, drm_buf, actual_size); + + drm_deinit(&drm_ctx, drm_fd); + RGA_deinit(&rga_ctx); + if (model_data) { + free(model_data); + } + + if (resize_buf) { + free(resize_buf); + } + stbi_image_free(input_data); + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/postprocess.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/postprocess.cc new file mode 100644 index 0000000..793efd4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/postprocess.cc @@ -0,0 +1,328 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "postprocess.h" + + +#define LABEL_NALE_TXT_PATH "./model/coco_80_labels_list.txt" + +static char* labels[OBJ_CLASS_NUM]; + +const int anchor0[6] = {10, 13, 16, 30, 33, 23}; +const int anchor1[6] = {30, 61, 62, 45, 59, 119}; +const int anchor2[6] = {116, 90, 156, 198, 373, 326}; + +inline static int clamp(float val, int min, int max) { return val > min ? (val < max ? val : max) : min; } + +char* readLine(FILE* fp, char* buffer, int* len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char*)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) { + buff_len++; + void* tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) { + free(buffer); + return NULL; // Out of memory + } + buffer = (char*)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char* fileName, char* lines[], int max_line) +{ + FILE* file = fopen(fileName, "r"); + char* s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + +int loadLabelName(const char* locationFilename, char* label[]) +{ + printf("loadLabelName %s\n", locationFilename); + readLines(locationFilename, label, OBJ_CLASS_NUM); + return 0; +} + +static float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, + float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1) + 1.0); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1) + 1.0); + float i = w * h; + float u = (xmax0 - xmin0 + 1.0) * (ymax0 - ymin0 + 1.0) + (xmax1 - xmin1 + 1.0) * (ymax1 - ymin1 + 1.0) - i; + return u <= 0.f ? 0.f : (i / u); +} + +static int nms(int validCount, std::vector& outputLocations, std::vector classIds, std::vector& order, + int filterId, float threshold) +{ + for (int i = 0; i < validCount; ++i) { + if (order[i] == -1 || classIds[i] != filterId) { + continue; + } + int n = order[i]; + for (int j = i + 1; j < validCount; ++j) { + int m = order[j]; + if (m == -1 || classIds[i] != filterId) { + continue; + } + float xmin0 = outputLocations[n * 4 + 0]; + float ymin0 = outputLocations[n * 4 + 1]; + float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2]; + float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3]; + + float xmin1 = outputLocations[m * 4 + 0]; + float ymin1 = outputLocations[m * 4 + 1]; + float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2]; + float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou > threshold) { + order[j] = -1; + } + } + } + return 0; +} + +static int quick_sort_indice_inverse(std::vector& input, int left, int right, std::vector& indices) +{ + float key; + int key_index; + int low = left; + int high = right; + if (left < right) { + key_index = indices[left]; + key = input[left]; + while (low < high) { + while (low < high && input[high] <= key) { + high--; + } + input[low] = input[high]; + indices[low] = indices[high]; + while (low < high && input[low] >= key) { + low++; + } + input[high] = input[low]; + indices[high] = indices[low]; + } + input[low] = key; + indices[low] = key_index; + quick_sort_indice_inverse(input, left, low - 1, indices); + quick_sort_indice_inverse(input, low + 1, right, indices); + } + return low; +} + +static float sigmoid(float x) { return 1.0 / (1.0 + expf(-x)); } + +static float unsigmoid(float y) { return -1.0 * logf((1.0 / y) - 1.0); } + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + return f; +} + +static uint8_t qnt_f32_to_affine(float f32, uint32_t zp, float scale) +{ + float dst_val = (f32 / scale) + zp; + uint8_t res = (uint8_t)__clip(dst_val, 0, 255); + return res; +} + +static float deqnt_affine_to_f32(uint8_t qnt, uint32_t zp, float scale) { return ((float)qnt - (float)zp) * scale; } + +static int process(uint8_t* input, int* anchor, int grid_h, int grid_w, int height, int width, int stride, + std::vector& boxes, std::vector& objProbs, std::vector& classId, float threshold, + uint32_t zp, float scale) +{ + int validCount = 0; + int grid_len = grid_h * grid_w; + float thres = unsigmoid(threshold); + uint8_t thres_u8 = qnt_f32_to_affine(thres, zp, scale); + for (int a = 0; a < 3; a++) { + for (int i = 0; i < grid_h; i++) { + for (int j = 0; j < grid_w; j++) { + uint8_t box_confidence = input[(PROP_BOX_SIZE * a + 4) * grid_len + i * grid_w + j]; + if (box_confidence >= thres_u8) { + int offset = (PROP_BOX_SIZE * a) * grid_len + i * grid_w + j; + uint8_t* in_ptr = input + offset; + float box_x = sigmoid(deqnt_affine_to_f32(*in_ptr, zp, scale)) * 2.0 - 0.5; + float box_y = sigmoid(deqnt_affine_to_f32(in_ptr[grid_len], zp, scale)) * 2.0 - 0.5; + float box_w = sigmoid(deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale)) * 2.0; + float box_h = sigmoid(deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale)) * 2.0; + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w = box_w * box_w * (float)anchor[a * 2]; + box_h = box_h * box_h * (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + + uint8_t maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < OBJ_CLASS_NUM; ++k) { + uint8_t prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) { + maxClassId = k; + maxClassProbs = prob; + } + } + objProbs.push_back(sigmoid(deqnt_affine_to_f32(maxClassProbs, zp, scale))); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + return validCount; +} + +int post_process(uint8_t* input0, uint8_t* input1, uint8_t* input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector& qnt_zps, std::vector& qnt_scales, detect_result_group_t* group) +{ + static int init = -1; + if (init == -1) { + int ret = 0; + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) { + return -1; + } + + init = 0; + } + memset(group, 0, sizeof(detect_result_group_t)); + + std::vector filterBoxes; + std::vector objProbs; + std::vector classId; + + // stride 8 + int stride0 = 8; + int grid_h0 = model_in_h / stride0; + int grid_w0 = model_in_w / stride0; + int validCount0 = 0; + validCount0 = process(input0, (int*)anchor0, grid_h0, grid_w0, model_in_h, model_in_w, stride0, filterBoxes, objProbs, + classId, conf_threshold, qnt_zps[0], qnt_scales[0]); + + // stride 16 + int stride1 = 16; + int grid_h1 = model_in_h / stride1; + int grid_w1 = model_in_w / stride1; + int validCount1 = 0; + validCount1 = process(input1, (int*)anchor1, grid_h1, grid_w1, model_in_h, model_in_w, stride1, filterBoxes, objProbs, + classId, conf_threshold, qnt_zps[1], qnt_scales[1]); + + // stride 32 + int stride2 = 32; + int grid_h2 = model_in_h / stride2; + int grid_w2 = model_in_w / stride2; + int validCount2 = 0; + validCount2 = process(input2, (int*)anchor2, grid_h2, grid_w2, model_in_h, model_in_w, stride2, filterBoxes, objProbs, + classId, conf_threshold, qnt_zps[2], qnt_scales[2]); + + int validCount = validCount0 + validCount1 + validCount2; + // no object detect + if (validCount <= 0) { + return 0; + } + + std::vector indexArray; + for (int i = 0; i < validCount; ++i) { + indexArray.push_back(i); + } + + quick_sort_indice_inverse(objProbs, 0, validCount - 1, indexArray); + + std::set class_set(std::begin(classId), std::end(classId)); + + for (auto c : class_set) { + nms(validCount, filterBoxes, classId, indexArray, c, nms_threshold); + } + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) { + if (indexArray[i] == -1 || last_count >= OBJ_NUMB_MAX_SIZE) { + continue; + } + int n = indexArray[i]; + + float x1 = filterBoxes[n * 4 + 0]; + float y1 = filterBoxes[n * 4 + 1]; + float x2 = x1 + filterBoxes[n * 4 + 2]; + float y2 = y1 + filterBoxes[n * 4 + 3]; + int id = classId[n]; + float obj_conf = objProbs[i]; + + group->results[last_count].box.left = (int)(clamp(x1, 0, model_in_w) / scale_w); + group->results[last_count].box.top = (int)(clamp(y1, 0, model_in_h) / scale_h); + group->results[last_count].box.right = (int)(clamp(x2, 0, model_in_w) / scale_w); + group->results[last_count].box.bottom = (int)(clamp(y2, 0, model_in_h) / scale_h); + group->results[last_count].prop = obj_conf; + char* label = labels[id]; + strncpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("result %2d: (%4d, %4d, %4d, %4d), %s\n", i, group->results[last_count].box.left, + // group->results[last_count].box.top, + // group->results[last_count].box.right, group->results[last_count].box.bottom, label); + last_count++; + } + group->count = last_count; + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/rga_func.c b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/rga_func.c new file mode 100644 index 0000000..c9e8a90 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_yolov5_demo/src/rga_func.c @@ -0,0 +1,108 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rga_func.h" + +int RGA_init(rga_context* rga_ctx) +{ + rga_ctx->rga_handle = dlopen("/usr/lib/librga.so", RTLD_LAZY); + if (!rga_ctx->rga_handle) { + printf("dlopen /usr/lib/librga.so failed\n"); + return -1; + } + rga_ctx->init_func = (FUNC_RGA_INIT)dlsym(rga_ctx->rga_handle, "c_RkRgaInit"); + rga_ctx->deinit_func = (FUNC_RGA_DEINIT)dlsym(rga_ctx->rga_handle, "c_RkRgaDeInit"); + rga_ctx->blit_func = (FUNC_RGA_BLIT)dlsym(rga_ctx->rga_handle, "c_RkRgaBlit"); + rga_ctx->init_func(); + return 0; +} + +void img_resize_fast(rga_context* rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h) +{ + // printf("rga use fd, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = src_fd; + src.mmuFlag = 1; + // src.virAddr = (void *)psrc; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 0; + +#if defined(__arm__) + dst.phyAddr = (void*)((uint32_t)dst_phys); +#else + dst.phyAddr = (void*)dst_phys; +#endif + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +void img_resize_slow(rga_context* rga_ctx, void* src_virt, int src_w, int src_h, void* dst_virt, int dst_w, int dst_h) +{ + // printf("rga use virtual, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = -1; + src.mmuFlag = 1; + src.virAddr = (void*)src_virt; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 1; + dst.virAddr = dst_virt; + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +int RGA_deinit(rga_context* rga_ctx) +{ + if (rga_ctx->rga_handle) { + dlclose(rga_ctx->rga_handle); + rga_ctx->rga_handle = NULL; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/CMakeLists.txt new file mode 100644 index 0000000..cdcfc38 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_zero_copy_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s -O3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s -O3") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rga +set(RGA_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/rga) +include_directories(${RGA_DIR}/include) + +# drm +set(DRM_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/drm) +include_directories(${DRM_DIR}/include) +include_directories(${DRM_DIR}/include/libdrm) + +include_directories(${CMAKE_SOURCE_DIR}/include) + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_zero_copy_demo + src/drm_func.c + src/rga_func.c + src/postprocess.cc + src/main.cc + ) + +target_link_libraries(rknn_zero_copy_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_zero_copy_demo) +install(TARGETS rknn_zero_copy_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/README.md new file mode 100644 index 0000000..500cb9b --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/README.md @@ -0,0 +1,88 @@ +# Zero copy demo + +In specific case, the number of input data copies can be reduced to 0, that is, zero copy. For example, when the RKNN model is asymmetric quantization, the quantization data type is uint8, the mean value of the 3 channels is the same integer and the scaling factor is the same, the normalization and quantization can be omitted. + +This demo compares the performance difference between zero-copy and normal process inference. + +```txt +a. zero-copy inference uses the "rknn_inputs_map" interface + +b. normal inference uses the "rknn_inputs_set" interface. +``` + +In the "model" directory, models without NHWC suffix have input in NCHW format, and models with NHWC suffix have input in NHWC format. The model with NHWC suffix is ​​exported using rknn-toolkit by adding the following parameters + +```python +rknn.config(force_builtin_perm=True) +``` + +Note: if it shows "**get unvalid input physical address, please extend in/out memory space**", you may need to modify the size of **CMA** in the **kernel's dts**, such as: + +``` +diff --git a/arch/arm/boot/dts/rv1126.dtsi b/arch/arm/boot/dts/rv1126.dtsi +index f5f0a07..1d0487c 100644 +--- a/arch/arm/boot/dts/rv1126.dtsi ++++ b/arch/arm/boot/dts/rv1126.dtsi +@@ -362,11 +362,17 @@ + #size-cells = <1>; + ranges; + ++ nouse@0 { ++ reg = <0x00000000 0x4000>; ++ no-map; ++ }; ++ ++ + linux,cma { + compatible = "shared-dma-pool"; + inactive; + reusable; +- size = <0x800000>; ++ size = <0x8000000>; + linux,cma-default; + }; + +``` + +This patch is only for RV1109/RV1126,if you use RK1808,you need to select the appropriate dts file to modify. + +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +```sh +./build.sh +``` + +## Install + +Copy install/rknn_zero_copy_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +```sh +adb push install/rknn_zero_copy_demo /userdata/ +``` + +- If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +```sh +adb shell +cd /userdata/rknn_zero_copy_demo/ +``` + +- RK1808/RK1806 + +```sh +./run_rk180x.sh +``` + +- RV1109/RV1126 + +```sh +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/build.sh new file mode 100644 index 0000000..01da901 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/build.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_zero_copy_demo/ +cp run_rv1109_rv1126.sh install/rknn_zero_copy_demo/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/drm_func.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/drm_func.h new file mode 100644 index 0000000..0a9e3b3 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/drm_func.h @@ -0,0 +1,53 @@ +#ifndef __DRM_FUNC_H__ +#define __DRM_FUNC_H__ +#include +#include +#include +#include +#include // open function +#include // close function +#include +#include + + +#include +#include "libdrm/drm_fourcc.h" +#include "xf86drm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (* FUNC_DRM_IOCTL)(int fd, unsigned long request, void *arg); + +typedef struct _drm_context{ + void *drm_handle; + FUNC_DRM_IOCTL io_func; +} drm_context; + +/* memory type definitions. */ +enum drm_rockchip_gem_mem_type +{ + /* Physically Continuous memory and used as default. */ + ROCKCHIP_BO_CONTIG = 1 << 0, + /* cachable mapping. */ + ROCKCHIP_BO_CACHABLE = 1 << 1, + /* write-combine mapping. */ + ROCKCHIP_BO_WC = 1 << 2, + ROCKCHIP_BO_SECURE = 1 << 3, + ROCKCHIP_BO_MASK = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_CACHABLE | + ROCKCHIP_BO_WC | ROCKCHIP_BO_SECURE +}; + +int drm_init(drm_context *drm_ctx); + +void* drm_buf_alloc(drm_context *drm_ctx,int drm_fd, int TexWidth, int TexHeight,int bpp,int *fd,unsigned int *handle,size_t *actual_size); + +int drm_buf_destroy(drm_context *drm_ctx,int drm_fd,int buf_fd, int handle,void *drm_buf,size_t size); + +void drm_deinit(drm_context *drm_ctx, int drm_fd); + +#ifdef __cplusplus +} +#endif +#endif /*__DRM_FUNC_H__*/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/postprocess.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/postprocess.h new file mode 100644 index 0000000..e474505 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/postprocess.h @@ -0,0 +1,40 @@ +#ifndef _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ +#define _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ + +#include + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 64 +#define OBJ_CLASS_NUM 80 +#define NMS_THRESH 0.6 +#define BOX_THRESH 0.5 +#define PROP_BOX_SIZE (5+OBJ_CLASS_NUM) + +typedef struct _BOX_RECT +{ + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t +{ + char name[OBJ_NAME_MAX_SIZE]; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t +{ + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + +int post_process(uint8_t *input0, uint8_t *input1, uint8_t *input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector &qnt_zps, std::vector &qnt_scales, + detect_result_group_t *group); + +#endif //_RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/rga_func.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/rga_func.h new file mode 100644 index 0000000..beeb441 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/include/rga_func.h @@ -0,0 +1,33 @@ +#ifndef __RGA_FUNC_H__ +#define __RGA_FUNC_H__ + +#include +#include "RgaApi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(* FUNC_RGA_INIT)(); +typedef void(* FUNC_RGA_DEINIT)(); +typedef int(* FUNC_RGA_BLIT)(rga_info_t *, rga_info_t *, rga_info_t *); + +typedef struct _rga_context{ + void *rga_handle; + FUNC_RGA_INIT init_func; + FUNC_RGA_DEINIT deinit_func; + FUNC_RGA_BLIT blit_func; +} rga_context; + +int RGA_init(rga_context* rga_ctx); + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h); + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h); + +int RGA_deinit(rga_context* rga_ctx); + +#ifdef __cplusplus +} +#endif +#endif/*__RGA_FUNC_H__*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/bus.bmp b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/bus.bmp new file mode 100644 index 0000000..82df079 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/bus.bmp differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/coco_80_labels_list.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/coco_80_labels_list.txt new file mode 100644 index 0000000..941cb4e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/coco_80_labels_list.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +dining table +toilet +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x.rknn new file mode 100644 index 0000000..f8170d3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x_NHWC.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x_NHWC.rknn new file mode 100644 index 0000000..0b8c68c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x_NHWC.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126.rknn new file mode 100644 index 0000000..eba83c6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_NHWC.rknn b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_NHWC.rknn new file mode 100644 index 0000000..80f2a2e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_NHWC.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rk180x.sh new file mode 100644 index 0000000..d74398a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rk180x.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +chip_dir="rk180x" +echo '********************* run zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rk180x_NHWC.rknn model/bus.bmp 1 +echo '********************* run non-zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rk180x.rknn model/bus.bmp 0 + + + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..0701370 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rv1109_rv1126.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +echo '********************* run zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rv1109_rv1126_NHWC.rknn model/bus.bmp 1 + +echo '********************* run non-zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rv1109_rv1126.rknn model/bus.bmp 0 + + + diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/drm_func.c b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/drm_func.c new file mode 100644 index 0000000..5811922 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/drm_func.c @@ -0,0 +1,175 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "drm_func.h" +#include + +int drm_init(drm_context *drm_ctx) +{ + static const char *card = "/dev/dri/card0"; + int flag = O_RDWR; + int drm_fd = -1; + + drm_fd = open(card, flag); + if (drm_fd < 0) + { + printf("failed to open %s\n", card); + return -1; + } + + drm_ctx->drm_handle = dlopen("/usr/lib/libdrm.so", RTLD_LAZY); + if (!drm_ctx->drm_handle) + { + printf("failed to dlopen /usr/lib/libdrm.so\n"); + drm_deinit(drm_ctx, drm_fd); + return -1; + } + + drm_ctx->io_func = (FUNC_DRM_IOCTL)dlsym(drm_ctx->drm_handle, "drmIoctl"); + if (drm_ctx->io_func == NULL) + { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + drm_deinit(drm_ctx, drm_fd); + printf("failed to dlsym drmIoctl\n"); + return -1; + } + return drm_fd; +} + +void drm_deinit(drm_context *drm_ctx, int drm_fd) +{ + if (drm_ctx->drm_handle) + { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + } + if (drm_fd > 0) + { + close(drm_fd); + } +} + +void *drm_buf_alloc(drm_context *drm_ctx, int drm_fd, int TexWidth, int TexHeight, int bpp, int *fd, unsigned int *handle, size_t *actual_size) +{ + int ret; + if (drm_ctx == NULL) + { + printf("drm context is unvalid\n"); + return NULL; + } + char *map = NULL; + + void *vir_addr = NULL; + struct drm_prime_handle fd_args; + struct drm_mode_map_dumb mmap_arg; + struct drm_mode_destroy_dumb destory_arg; + + struct drm_mode_create_dumb alloc_arg; + + memset(&alloc_arg, 0, sizeof(alloc_arg)); + alloc_arg.bpp = bpp; + alloc_arg.width = TexWidth; + alloc_arg.height = TexHeight; + // alloc_arg.flags = ROCKCHIP_BO_CONTIG; + + //获取handle和size + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg); + if (ret) + { + printf("failed to create dumb buffer: %s\n", strerror(errno)); + return NULL; + } + if (handle != NULL) + { + *handle = alloc_arg.handle; + } + if (actual_size != NULL) + { + *actual_size = alloc_arg.size; + } + // printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n",alloc_arg.width,alloc_arg.height,alloc_arg.bpp,alloc_arg.size); + // printf("out handle= %d\n",alloc_arg.handle); + + //获取fd + memset(&fd_args, 0, sizeof(fd_args)); + fd_args.fd = -1; + fd_args.handle = alloc_arg.handle; + ; + fd_args.flags = 0; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args); + if (ret) + { + printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle); + return NULL; + } + // printf("out fd = %d, drm fd: %d\n",fd_args.fd,drm_fd); + if (fd != NULL) + { + *fd = fd_args.fd; + } + + //获取虚拟地址 + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = alloc_arg.handle; + + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg); + if (ret) + { + printf("failed to create map dumb: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + vir_addr = map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset); + if (map == MAP_FAILED) + { + printf("failed to mmap buffer: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + // printf("alloc map=%x \n",map); + return vir_addr; +destory_dumb: + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = alloc_arg.handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d\n", ret); + return vir_addr; +} + +int drm_buf_destroy(drm_context *drm_ctx, int drm_fd, int buf_fd, int handle, void *drm_buf, size_t size) +{ + int ret = -1; + if (drm_buf == NULL) + { + printf("drm buffer is NULL\n"); + return -1; + } + + munmap(drm_buf, size); + + struct drm_mode_destroy_dumb destory_arg; + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno)); + if (buf_fd > 0) + { + close(buf_fd); + } + + return ret; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/main.cc new file mode 100644 index 0000000..60ce6c8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/main.cc @@ -0,0 +1,500 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#define _BASETSD_H + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#undef cimg_display +#define cimg_display 0 +#include "CImg/CImg.h" + +#include "drm_func.h" +#include "rga_func.h" +#include "rknn_api.h" +#include "postprocess.h" + +#define PERF_WITH_POST 1 + +using namespace cimg_library; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +inline const char *get_type_string(rknn_tensor_type type) +{ + switch (type) + { + case RKNN_TENSOR_FLOAT32: + return "FP32"; + case RKNN_TENSOR_FLOAT16: + return "FP16"; + case RKNN_TENSOR_INT8: + return "INT8"; + case RKNN_TENSOR_UINT8: + return "UINT8"; + case RKNN_TENSOR_INT16: + return "INT16"; + default: + return "UNKNOW"; + } +} + +inline const char *get_qnt_type_string(rknn_tensor_qnt_type type) +{ + switch (type) + { + case RKNN_TENSOR_QNT_NONE: + return "NONE"; + case RKNN_TENSOR_QNT_DFP: + return "DFP"; + case RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + return "AFFINE"; + default: + return "UNKNOW"; + } +} + +inline const char *get_format_string(rknn_tensor_format fmt) +{ + switch (fmt) + { + case RKNN_TENSOR_NCHW: + return "NCHW"; + case RKNN_TENSOR_NHWC: + return "NHWC"; + default: + return "UNKNOW"; + } +} + +static void dump_tensor_attr(rknn_tensor_attr *attr) +{ + printf(" index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, " + "zp=%d, scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, get_format_string(attr->fmt), get_type_string(attr->type), + get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale); +} + +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static unsigned char *load_data(FILE *fp, size_t ofst, size_t sz) +{ + unsigned char *data; + int ret; + + data = NULL; + + if (NULL == fp) + { + return NULL; + } + + ret = fseek(fp, ofst, SEEK_SET); + if (ret != 0) + { + printf("blob seek failure.\n"); + return NULL; + } + + data = (unsigned char *)malloc(sz); + if (data == NULL) + { + printf("buffer malloc failure.\n"); + return NULL; + } + ret = fread(data, 1, sz, fp); + return data; +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + + FILE *fp; + unsigned char *data; + + fp = fopen(filename, "rb"); + if (NULL == fp) + { + printf("Open file %s failed.\n", filename); + return NULL; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + + data = load_data(fp, 0, size); + + fclose(fp); + + *model_size = size; + return data; +} + +static int saveFloat(const char *file_name, float *output, int element_size) +{ + FILE *fp; + fp = fopen(file_name, "w"); + for (int i = 0; i < element_size; i++) + { + fprintf(fp, "%.6f\n", output[i]); + } + fclose(fp); + return 0; +} + +static unsigned char *load_image(const char *image_path, int *org_height, int *org_width, int *org_ch, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + *org_width = width; + *org_height = height; + *org_ch = channel; + + return image_data; +} + +/*------------------------------------------- + Main Functions +-------------------------------------------*/ +int main(int argc, char **argv) +{ + int status = 0; + char *model_name = NULL; + rknn_context ctx; + int is_map = 0; + rknn_tensor_mem in_mem[1]; + void *drm_buf = NULL; + int drm_fd = -1; + int buf_fd = -1; // converted from buffer handle + unsigned int handle; + size_t actual_size = 0; + int img_width = 0; + int img_height = 0; + int img_channel = 0; + rga_context rga_ctx; + drm_context drm_ctx; + const float nms_threshold = NMS_THRESH; + const float box_conf_threshold = BOX_THRESH; + struct timeval start_time, stop_time; + int ret; + memset(&rga_ctx, 0, sizeof(rga_context)); + memset(&drm_ctx, 0, sizeof(drm_context)); + + if (argc != 4) + { + printf("Note: rknn model need meet zero-copy condition: 3-channel with same integer means and same scales\n"); + printf("Usage: %s \n", argv[0]); + printf("flag:\n"); + printf("\t 0: run builtin_permute=False rknn model, perform rknn_inputs_set\n"); + printf("\t 1: run builtin_permute=True rknn model, perform rknn_inputs_map\n"); + return -1; + } + + printf("post process config: box_conf_threshold = %.2f, nms_threshold = %.2f\n", + box_conf_threshold, nms_threshold); + model_name = (char *)argv[1]; + char *image_name = argv[2]; + is_map = atoi(argv[3]); + + if (strstr(image_name, ".jpg") != NULL || strstr(image_name, ".png") != NULL) + { + printf("Error: read %s failed! only support .bmp format image\n", image_name); + return -1; + } + + /* Create the neural network */ + printf("Loading mode...\n"); + int model_data_size = 0; + unsigned char *model_data = load_model(model_name, &model_data_size); + ret = rknn_init(&ctx, model_data, model_data_size, 0); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + sizeof(rknn_sdk_version)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("sdk version: %s driver version: %s\n", version.api_version, + version.drv_version); + + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, + io_num.n_output); + + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + sizeof(rknn_tensor_attr)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + dump_tensor_attr(&(input_attrs[i])); + } + + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + sizeof(rknn_tensor_attr)); + dump_tensor_attr(&(output_attrs[i])); + } + + int channel = 3; + int width = 0; + int height = 0; + if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) + { + printf("model is NCHW input fmt\n"); + width = input_attrs[0].dims[0]; + height = input_attrs[0].dims[1]; + } + else + { + printf("model is NHWC input fmt\n"); + width = input_attrs[0].dims[1]; + height = input_attrs[0].dims[2]; + } + + printf("model input height=%d, width=%d, channel=%d\n", height, width, + channel); + + // Load image + CImg img(image_name); + unsigned char *input_data = NULL; + input_data = load_image(image_name, &img_height, &img_width, &img_channel, &input_attrs[0]); + if (!input_data) + { + return -1; + } + + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = width * height * channel; + inputs[0].fmt = RKNN_TENSOR_NHWC; + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) + { + outputs[i].want_float = 0; + } + + // DRM alloc buffer + drm_fd = drm_init(&drm_ctx); + drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, img_width, img_height, channel * 8, + &buf_fd, &handle, &actual_size); + memcpy(drm_buf, input_data, img_width * img_height * channel); + void *resize_buf = malloc(height * width * channel); + + // init rga context + RGA_init(&rga_ctx); + if (is_map == 0) + { + inputs[0].pass_through = 0; + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + inputs[0].buf = resize_buf; + gettimeofday(&start_time, NULL); + rknn_inputs_set(ctx, io_num.n_input, inputs); + } + else + { + gettimeofday(&start_time, NULL); + ret = rknn_inputs_map(ctx, io_num.n_input, in_mem); + printf("input virt_addr = %p, phys_addr = 0x%llx, fd = %d, size = %d\n", + in_mem[0].logical_addr, in_mem[0].physical_addr, in_mem[0].fd, + in_mem[0].size); + if (in_mem[0].physical_addr == 0xffffffffffffffff) + { + printf("get unvalid input physical address, please extend in/out memory space\n"); + exit(-1); + } + else + { + // rga process by physical addr + img_resize_fast(&rga_ctx, buf_fd, img_width, img_height, in_mem[0].physical_addr, width, height); + } + rknn_inputs_sync(ctx, io_num.n_input, in_mem); + } + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + gettimeofday(&stop_time, NULL); + printf("once run use %f ms\n", + (__get_us(stop_time) - __get_us(start_time)) / 1000); + + //post process + float scale_w = (float)width / img_width; + float scale_h = (float)height / img_height; + + detect_result_group_t detect_result_group; + std::vector out_scales; + std::vector out_zps; + for (int i = 0; i < io_num.n_output; ++i) + { + out_scales.push_back(output_attrs[i].scale); + out_zps.push_back(output_attrs[i].zp); + } + post_process((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); + + // Draw Objects + char text[256]; + const unsigned char blue[] = {0, 0, 255}; + const unsigned char white[] = {255, 255, 255}; + for (int i = 0; i < detect_result_group.count; i++) + { + detect_result_t *det_result = &(detect_result_group.results[i]); + sprintf(text, "%s %.2f", det_result->name, det_result->prop); + printf("%s @ (%d %d %d %d) %f\n", + det_result->name, + det_result->box.left, det_result->box.top, det_result->box.right, det_result->box.bottom, + det_result->prop); + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + //draw box + img.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U); + img.draw_text(x1, y1 - 12, text, white); + } + img.save("./out.bmp"); + + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + + // loop test + int test_count = 10; + gettimeofday(&start_time, NULL); + if (is_map == 0) + { + for (int i = 0; i < test_count; ++i) + { + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + rknn_inputs_set(ctx, io_num.n_input, inputs); + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); +#if PERF_WITH_POST + post_process((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); +#endif + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + } + } + else + { + for (int i = 0; i < test_count; ++i) + { + img_resize_fast(&rga_ctx, buf_fd, img_width, img_height, in_mem[0].physical_addr, width, height); + rknn_inputs_sync(ctx, io_num.n_input, in_mem); + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); +#if PERF_WITH_POST + post_process((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); +#endif + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + } + } + gettimeofday(&stop_time, NULL); + printf("run loop count = %d , average time: %f ms\n", test_count, + (__get_us(stop_time) - __get_us(start_time)) / 1000.0 / test_count); + + // release + if (is_map) + { + ret = rknn_inputs_unmap(ctx, io_num.n_input, in_mem); + } + ret = rknn_destroy(ctx); + drm_buf_destroy(&drm_ctx, drm_fd, buf_fd, handle, drm_buf, actual_size); + + drm_deinit(&drm_ctx, drm_fd); + RGA_deinit(&rga_ctx); + if (model_data) + { + free(model_data); + } + + if (resize_buf) + { + free(resize_buf); + } + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/postprocess.cc b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/postprocess.cc new file mode 100644 index 0000000..adf6ea8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/postprocess.cc @@ -0,0 +1,366 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include "postprocess.h" +#include +#define LABEL_NALE_TXT_PATH "./model/coco_80_labels_list.txt" + +static char *labels[OBJ_CLASS_NUM]; + +const int anchor0[6] = {10, 13, 16, 30, 33, 23}; +const int anchor1[6] = {30, 61, 62, 45, 59, 119}; +const int anchor2[6] = {116, 90, 156, 198, 373, 326}; + +inline static int clamp(float val, int min, int max) +{ + return val > min ? (val < max ? val : max) : min; +} + +char *readLine(FILE *fp, char *buffer, int *len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char *)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) + { + buff_len++; + void *tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) + { + free(buffer); + return NULL; // Out of memory + } + buffer = (char *)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) + { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char *fileName, char *lines[], int max_line) +{ + FILE *file = fopen(fileName, "r"); + char *s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) + { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + +int loadLabelName(const char *locationFilename, char *label[]) +{ + printf("loadLabelName %s\n", locationFilename); + readLines(locationFilename, label, OBJ_CLASS_NUM); + return 0; +} + +static float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1) + 1.0); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1) + 1.0); + float i = w * h; + float u = (xmax0 - xmin0 + 1.0) * (ymax0 - ymin0 + 1.0) + (xmax1 - xmin1 + 1.0) * (ymax1 - ymin1 + 1.0) - i; + return u <= 0.f ? 0.f : (i / u); +} + +static int nms(int validCount, std::vector &outputLocations, std::vector classIds, std::vector &order, int filterId, float threshold) +{ + for (int i = 0; i < validCount; ++i) + { + if (order[i] == -1 || classIds[i] != filterId) + { + continue; + } + int n = order[i]; + for (int j = i + 1; j < validCount; ++j) + { + int m = order[j]; + if (m == -1 || classIds[i] != filterId) + { + continue; + } + float xmin0 = outputLocations[n * 4 + 0]; + float ymin0 = outputLocations[n * 4 + 1]; + float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2]; + float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3]; + + float xmin1 = outputLocations[m * 4 + 0]; + float ymin1 = outputLocations[m * 4 + 1]; + float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2]; + float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou > threshold) + { + order[j] = -1; + } + } + } + return 0; +} + +static int quick_sort_indice_inverse( + std::vector &input, + int left, + int right, + std::vector &indices) +{ + float key; + int key_index; + int low = left; + int high = right; + if (left < right) + { + key_index = indices[left]; + key = input[left]; + while (low < high) + { + while (low < high && input[high] <= key) + { + high--; + } + input[low] = input[high]; + indices[low] = indices[high]; + while (low < high && input[low] >= key) + { + low++; + } + input[high] = input[low]; + indices[high] = indices[low]; + } + input[low] = key; + indices[low] = key_index; + quick_sort_indice_inverse(input, left, low - 1, indices); + quick_sort_indice_inverse(input, low + 1, right, indices); + } + return low; +} + +static float sigmoid(float x) +{ + return 1.0 / (1.0 + expf(-x)); +} + +static float unsigmoid(float y) +{ + return -1.0 * logf((1.0 / y) - 1.0); +} + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + return f; +} + +static uint8_t qnt_f32_to_affine(float f32, uint32_t zp, float scale) +{ + float dst_val = (f32 / scale) + zp; + uint8_t res = (uint8_t)__clip(dst_val, 0, 255); + return res; +} + +static float deqnt_affine_to_f32(uint8_t qnt, uint32_t zp, float scale) +{ + return ((float)qnt - (float)zp) * scale; +} + +static int process(uint8_t *input, int *anchor, int grid_h, int grid_w, int height, int width, int stride, + std::vector &boxes, std::vector &objProbs, std::vector &classId, + float threshold, uint32_t zp, float scale) +{ + + int validCount = 0; + int grid_len = grid_h * grid_w; + float thres = unsigmoid(threshold); + uint8_t thres_u8 = qnt_f32_to_affine(thres, zp, scale); + for (int a = 0; a < 3; a++) + { + for (int i = 0; i < grid_h; i++) + { + for (int j = 0; j < grid_w; j++) + { + uint8_t box_confidence = input[(PROP_BOX_SIZE * a + 4) * grid_len + i * grid_w + j]; + if (box_confidence >= thres_u8) + { + int offset = (PROP_BOX_SIZE * a) * grid_len + i * grid_w + j; + uint8_t *in_ptr = input + offset; + float box_x = sigmoid(deqnt_affine_to_f32(*in_ptr, zp, scale)) * 2.0 - 0.5; + float box_y = sigmoid(deqnt_affine_to_f32(in_ptr[grid_len], zp, scale)) * 2.0 - 0.5; + float box_w = sigmoid(deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale)) * 2.0; + float box_h = sigmoid(deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale)) * 2.0; + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w = box_w * box_w * (float)anchor[a * 2]; + box_h = box_h * box_h * (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + + uint8_t maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < OBJ_CLASS_NUM; ++k) + { + uint8_t prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) + { + maxClassId = k; + maxClassProbs = prob; + } + } + objProbs.push_back(sigmoid(deqnt_affine_to_f32(maxClassProbs, zp, scale))); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + return validCount; +} + +int post_process(uint8_t *input0, uint8_t *input1, uint8_t *input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector &qnt_zps, std::vector &qnt_scales, + detect_result_group_t *group) +{ + static int init = -1; + if (init == -1) + { + int ret = 0; + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) + { + return -1; + } + + init = 0; + } + memset(group, 0, sizeof(detect_result_group_t)); + + std::vector filterBoxes; + std::vector objProbs; + std::vector classId; + + // stride 8 + int stride0 = 8; + int grid_h0 = model_in_h / stride0; + int grid_w0 = model_in_w / stride0; + int validCount0 = 0; + validCount0 = process(input0, (int *)anchor0, grid_h0, grid_w0, model_in_h, model_in_w, + stride0, filterBoxes, objProbs, classId, conf_threshold, qnt_zps[0], qnt_scales[0]); + + // stride 16 + int stride1 = 16; + int grid_h1 = model_in_h / stride1; + int grid_w1 = model_in_w / stride1; + int validCount1 = 0; + validCount1 = process(input1, (int *)anchor1, grid_h1, grid_w1, model_in_h, model_in_w, + stride1, filterBoxes, objProbs, classId, conf_threshold, qnt_zps[1], qnt_scales[1]); + + // stride 32 + int stride2 = 32; + int grid_h2 = model_in_h / stride2; + int grid_w2 = model_in_w / stride2; + int validCount2 = 0; + validCount2 = process(input2, (int *)anchor2, grid_h2, grid_w2, model_in_h, model_in_w, + stride2, filterBoxes, objProbs, classId, conf_threshold, qnt_zps[2], qnt_scales[2]); + + int validCount = validCount0 + validCount1 + validCount2; + // no object detect + if (validCount <= 0) + { + return 0; + } + + std::vector indexArray; + for (int i = 0; i < validCount; ++i) + { + indexArray.push_back(i); + } + + quick_sort_indice_inverse(objProbs, 0, validCount - 1, indexArray); + + std::set class_set(std::begin(classId), std::end(classId)); + + for (auto c : class_set) + { + nms(validCount, filterBoxes, classId, indexArray, c, nms_threshold); + } + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) + { + + if (indexArray[i] == -1 || last_count >= OBJ_NUMB_MAX_SIZE) + { + continue; + } + int n = indexArray[i]; + + float x1 = filterBoxes[n * 4 + 0]; + float y1 = filterBoxes[n * 4 + 1]; + float x2 = x1 + filterBoxes[n * 4 + 2]; + float y2 = y1 + filterBoxes[n * 4 + 3]; + int id = classId[n]; + float obj_conf = objProbs[i]; + + group->results[last_count].box.left = (int)(clamp(x1, 0, model_in_w) / scale_w); + group->results[last_count].box.top = (int)(clamp(y1, 0, model_in_h) / scale_h); + group->results[last_count].box.right = (int)(clamp(x2, 0, model_in_w) / scale_w); + group->results[last_count].box.bottom = (int)(clamp(y2, 0, model_in_h) / scale_h); + group->results[last_count].prop = obj_conf; + char *label = labels[id]; + strncpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("result %2d: (%4d, %4d, %4d, %4d), %s\n", i, group->results[last_count].box.left, group->results[last_count].box.top, + // group->results[last_count].box.right, group->results[last_count].box.bottom, label); + last_count++; + } + group->count = last_count; + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/rga_func.c b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/rga_func.c new file mode 100644 index 0000000..69caada --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/examples/rknn_zero_copy_demo/src/rga_func.c @@ -0,0 +1,114 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rga_func.h" + +int RGA_init(rga_context *rga_ctx) +{ + rga_ctx->rga_handle = dlopen("/usr/lib/librga.so", RTLD_LAZY); + if (!rga_ctx->rga_handle) + { + printf("dlopen /usr/lib/librga.so failed\n"); + return -1; + } + rga_ctx->init_func = (FUNC_RGA_INIT)dlsym(rga_ctx->rga_handle, "c_RkRgaInit"); + rga_ctx->deinit_func = (FUNC_RGA_DEINIT)dlsym(rga_ctx->rga_handle, "c_RkRgaDeInit"); + rga_ctx->blit_func = (FUNC_RGA_BLIT)dlsym(rga_ctx->rga_handle, "c_RkRgaBlit"); + rga_ctx->init_func(); + return 0; +} + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h) +{ + // printf("rga use fd, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) + { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = src_fd; + src.mmuFlag = 1; + // src.virAddr = (void *)psrc; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 0; + +#if defined(__arm__) + dst.phyAddr = (void *)((uint32_t)dst_phys); +#else + dst.phyAddr = (void *)dst_phys; +#endif + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) + { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h) +{ + // printf("rga use virtual, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) + { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = -1; + src.mmuFlag = 1; + src.virAddr = (void *)src_virt; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 1; + dst.virAddr = dst_virt; + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) + { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +int RGA_deinit(rga_context *rga_ctx) +{ + if(rga_ctx->rga_handle) + { + dlclose(rga_ctx->rga_handle); + rga_ctx->rga_handle = NULL; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/include/rknn_api.h b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/include/rknn_api.h new file mode 100644 index 0000000..a114c1f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/include/rknn_api.h @@ -0,0 +1,504 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + + +#ifndef _RKNN_RUNTIME_H +#define _RKNN_RUNTIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + Definition of extended flag for rknn_init. +*/ +/* set high priority context. */ +#define RKNN_FLAG_PRIOR_HIGH 0x00000000 + +/* set medium priority context */ +#define RKNN_FLAG_PRIOR_MEDIUM 0x00000001 + +/* set low priority context. */ +#define RKNN_FLAG_PRIOR_LOW 0x00000002 + +/* asynchronous mode. + when enable, rknn_outputs_get will not block for too long because it directly retrieves the result of + the previous frame which can increase the frame rate on single-threaded mode, but at the cost of + rknn_outputs_get not retrieves the result of the current frame. + in multi-threaded mode you do not need to turn this mode on. */ +#define RKNN_FLAG_ASYNC_MASK 0x00000004 + +/* collect performance mode. + when enable, you can get detailed performance reports via rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, ...), + but it will reduce the frame rate. */ +#define RKNN_FLAG_COLLECT_PERF_MASK 0x00000008 + +/* + save pre-compile model. +*/ +#define RKNN_FLAG_PRECOMPILE_MASK 0x00000020 + +/* + Error code returned by the RKNN API. +*/ +#define RKNN_SUCC 0 /* execute succeed. */ +#define RKNN_ERR_FAIL -1 /* execute failed. */ +#define RKNN_ERR_TIMEOUT -2 /* execute timeout. */ +#define RKNN_ERR_DEVICE_UNAVAILABLE -3 /* device is unavailable. */ +#define RKNN_ERR_MALLOC_FAIL -4 /* memory malloc fail. */ +#define RKNN_ERR_PARAM_INVALID -5 /* parameter is invalid. */ +#define RKNN_ERR_MODEL_INVALID -6 /* model is invalid. */ +#define RKNN_ERR_CTX_INVALID -7 /* context is invalid. */ +#define RKNN_ERR_INPUT_INVALID -8 /* input is invalid. */ +#define RKNN_ERR_OUTPUT_INVALID -9 /* output is invalid. */ +#define RKNN_ERR_DEVICE_UNMATCH -10 /* the device is unmatch, please update rknn sdk + and npu driver/firmware. */ +#define RKNN_ERR_INCOMPATILE_PRE_COMPILE_MODEL -11 /* This RKNN model use pre_compile mode, but not compatible with current driver. */ +//add by chifred: for reporting optimization version bug info +#define RKNN_ERR_INCOMPATILE_OPTIMIZATION_LEVEL_VERSION -12 /* This RKNN model set optimization level, but not compatible with current driver. */ +#define RKNN_ERR_TARGET_PLATFORM_UNMATCH -13 /* This RKNN model set target platform, but not compatible with current platform. */ +//chifred add end +#define RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER -14 /* This RKNN model is not a pre-compiled model, but the npu driver is mini driver. */ + +/* + Definition for tensor +*/ +#define RKNN_MAX_DIMS 16 /* maximum dimension of tensor. */ +#define RKNN_MAX_NAME_LEN 256 /* maximum name lenth of tensor. */ + + + +#ifdef __arm__ +typedef uint32_t rknn_context; +#else +typedef uint64_t rknn_context; +#endif + +/* + The query command for rknn_query +*/ +typedef enum _rknn_query_cmd { + RKNN_QUERY_IN_OUT_NUM = 0, /* query the number of input & output tensor. */ + RKNN_QUERY_INPUT_ATTR, /* query the attribute of input tensor. */ + RKNN_QUERY_OUTPUT_ATTR, /* query the attribute of output tensor. */ + RKNN_QUERY_PERF_DETAIL, /* query the detail performance, need set + RKNN_FLAG_COLLECT_PERF_MASK when call rknn_init. */ + RKNN_QUERY_PERF_RUN, /* query the time of run. */ + RKNN_QUERY_SDK_VERSION, /* query the sdk & driver version */ + RKNN_QUERY_PRE_COMPILE, /* query the pre compile model */ + + RKNN_QUERY_CMD_MAX +} rknn_query_cmd; + +/* + the tensor data type. +*/ +typedef enum _rknn_tensor_type { + RKNN_TENSOR_FLOAT32 = 0, /* data type is float32. */ + RKNN_TENSOR_FLOAT16, /* data type is float16. */ + RKNN_TENSOR_INT8, /* data type is int8. */ + RKNN_TENSOR_UINT8, /* data type is uint8. */ + RKNN_TENSOR_INT16, /* data type is int16. */ + + RKNN_TENSOR_TYPE_MAX +} rknn_tensor_type; + +/* + the quantitative type. +*/ +typedef enum _rknn_tensor_qnt_type { + RKNN_TENSOR_QNT_NONE = 0, /* none. */ + RKNN_TENSOR_QNT_DFP, /* dynamic fixed point. */ + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC, /* asymmetric affine. */ + + RKNN_TENSOR_QNT_MAX +} rknn_tensor_qnt_type; + +/* + the tensor data format. +*/ +typedef enum _rknn_tensor_format { + RKNN_TENSOR_NCHW = 0, /* data format is NCHW. */ + RKNN_TENSOR_NHWC, /* data format is NHWC. */ + + RKNN_TENSOR_FORMAT_MAX +} rknn_tensor_format; + +/* + the information for RKNN_QUERY_IN_OUT_NUM. +*/ +typedef struct _rknn_input_output_num { + uint32_t n_input; /* the number of input. */ + uint32_t n_output; /* the number of output. */ +} rknn_input_output_num; + +/* + the information for RKNN_QUERY_INPUT_ATTR / RKNN_QUERY_OUTPUT_ATTR. +*/ +typedef struct _rknn_tensor_attr { + uint32_t index; /* input parameter, the index of input/output tensor, + need set before call rknn_query. */ + + uint32_t n_dims; /* the number of dimensions. */ + uint32_t dims[RKNN_MAX_DIMS]; /* the dimensions array. */ + char name[RKNN_MAX_NAME_LEN]; /* the name of tensor. */ + + uint32_t n_elems; /* the number of elements. */ + uint32_t size; /* the bytes size of tensor. */ + + rknn_tensor_format fmt; /* the data format of tensor. */ + rknn_tensor_type type; /* the data type of tensor. */ + rknn_tensor_qnt_type qnt_type; /* the quantitative type of tensor. */ + int8_t fl; /* fractional length for RKNN_TENSOR_QNT_DFP. */ + uint32_t zp; /* zero point for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ + float scale; /* scale for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ +} rknn_tensor_attr; + +/* + the information for RKNN_QUERY_PERF_DETAIL. +*/ +typedef struct _rknn_perf_detail { + char* perf_data; /* the string pointer of perf detail. don't need free it by user. */ + uint64_t data_len; /* the string length. */ +} rknn_perf_detail; + +/* + the information for RKNN_QUERY_PERF_RUN. +*/ +typedef struct _rknn_perf_run { + int64_t run_duration; /* real inference time (us) */ +} rknn_perf_run; + +/* + the information for RKNN_QUERY_SDK_VERSION. +*/ +typedef struct _rknn_sdk_version { + char api_version[256]; /* the version of rknn api. */ + char drv_version[256]; /* the version of rknn driver. */ +} rknn_sdk_version; + +/* + The flags of rknn_tensor_mem. +*/ +typedef enum _rknn_tensor_mem_flags { + RKNN_TENSOR_MEMORY_FLAGS_UNKNOWN = 0, + RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE = 1, /*Used to mark in rknn_destroy_mem() whether it is necessary to release the "mem" pointer itself. + If the flag RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE is set, rknn_destroy_mem() will call free(mem).*/ + +} rknn_tensor_mem_flags; + + +/* + the memory information of tensor. +*/ +typedef struct _rknn_tensor_memory { + void* logical_addr; /* the virtual address of tensor buffer. */ + uint64_t physical_addr; /* the physical address of tensor buffer. */ + int32_t fd; /* the fd of tensor buffer. */ + uint32_t size; /* the size of tensor buffer. */ + uint32_t handle; /* the handle tensor buffer. */ + void * priv_data; /* the data which is reserved. */ + uint64_t reserved_flag; /* the flag which is reserved. */ +} rknn_tensor_mem; + +/* + the input information for rknn_input_set. +*/ +typedef struct _rknn_input { + uint32_t index; /* the input index. */ + void* buf; /* the input buf for index. */ + uint32_t size; /* the size of input buf. */ + uint8_t pass_through; /* pass through mode. + if TRUE, the buf data is passed directly to the input node of the rknn model + without any conversion. the following variables do not need to be set. + if FALSE, the buf data is converted into an input consistent with the model + according to the following type and fmt. so the following variables + need to be set.*/ + rknn_tensor_type type; /* the data type of input buf. */ + rknn_tensor_format fmt; /* the data format of input buf. + currently the internal input format of NPU is NCHW by default. + so entering NCHW data can avoid the format conversion in the driver. */ +} rknn_input; + +/* + the output information for rknn_outputs_get. +*/ +typedef struct _rknn_output { + uint8_t want_float; /* want transfer output data to float */ + uint8_t is_prealloc; /* whether buf is pre-allocated. + if true, the following variables need to be set. + if false, The following variables do not need to be set. */ + uint32_t index; /* the output index. */ + void* buf; /* the output buf for index. + when is_prealloc = FALSE and rknn_outputs_release called, + this buf pointer will be free and don't use it anymore. */ + uint32_t size; /* the size of output buf. */ +} rknn_output; + +/* + the extend information for rknn_run. +*/ +typedef struct _rknn_run_extend { + uint64_t frame_id; /* output parameter, indicate current frame id of run. */ +} rknn_run_extend; + +/* + the extend information for rknn_outputs_get. +*/ +typedef struct _rknn_output_extend { + uint64_t frame_id; /* output parameter, indicate the frame id of outputs, corresponds to + struct rknn_run_extend.frame_id.*/ +} rknn_output_extend; + +/* + the information for RKNN_QUERY_RKNN_PRECOMPILE. +*/ +typedef struct _rknn_precompile { + void* model_data; /* the pointer of precompile model. don't need free it by user. */ + uint32_t data_len; /* the model length. */ +} rknn_precompile; + + +/* rknn_init + + initial the context and load the rknn model. + + input: + rknn_context* context the pointer of context handle. + void* model pointer to the rknn model. + uint32_t size the size of rknn model. + uint32_t flag extend flag, see the define of RKNN_FLAG_XXX_XXX. + return: + int error code. +*/ +int rknn_init(rknn_context* context, void* model, uint32_t size, uint32_t flag); + + +/* rknn_destroy + + unload the rknn model and destroy the context. + + input: + rknn_context context the handle of context. + return: + int error code. +*/ +int rknn_destroy(rknn_context context); + + +/* rknn_query + + query the information about model or others. see rknn_query_cmd. + + input: + rknn_context context the handle of context. + rknn_query_cmd cmd the command of query. + void* info the buffer point of information. + uint32_t size the size of information. + return: + int error code. +*/ +int rknn_query(rknn_context context, rknn_query_cmd cmd, void* info, uint32_t size); + + +/* rknn_inputs_set + + set inputs information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_input inputs[] the arrays of inputs information, see rknn_input. + return: + int error code +*/ +int rknn_inputs_set(rknn_context context, uint32_t n_inputs, rknn_input inputs[]); + + +/* rknn_inputs_map + + map inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_map(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_sync + + synchronize inputs tensor buffer by input index of rknn model. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_sync(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_unmap + + unmap inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_unmap(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_run + + run the model to execute inference. + + input: + rknn_context context the handle of context. + rknn_run_extend* extend the extend information of run. + return: + int error code. +*/ +int rknn_run(rknn_context context, rknn_run_extend* extend); + + +/* rknn_outputs_get + + wait the inference to finish and get the outputs. + this function will block until inference finish. + the results will set to outputs[]. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_output outputs[] the arrays of output, see rknn_output. + rknn_output_extend* the extend information of output. + return: + int error code. +*/ +int rknn_outputs_get(rknn_context context, uint32_t n_outputs, rknn_output outputs[], rknn_output_extend* extend); + + +/* rknn_outputs_release + + release the outputs that get by rknn_outputs_get. + after called, the rknn_output[x].buf get from rknn_outputs_get will + also be free when rknn_output[x].is_prealloc = FALSE. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_output outputs[] the arrays of output. + return: + int error code +*/ +int rknn_outputs_release(rknn_context context, uint32_t n_ouputs, rknn_output outputs[]); + + +/* rknn_outputs_map + + map the model output tensors memory information. + The difference between this function and "rknn_outputs_get" is + that it directly maps the model output tensor memory location to the user. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_map(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_sync + + synchronize the output tensors buffer to ensure cache cohenrency, wait the inference to finish. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_sync(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_unmap + + unmap the outputs memory information that get by rknn_outputs_map. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_outputs_unmap(rknn_context context, uint32_t n_ouputs, rknn_tensor_mem mem[]); + +/* rknn_create_mem (memory allocated inside) + + Create tensor memory. This API require libdrm support! + + input: + rknn_context ctx the handle of context. + uint64_t size the size of tensor buffer. + return: + rknn_tensor_mem the pointer of tensor memory information. +*/ +rknn_tensor_mem* rknn_create_mem(rknn_context ctx, uint64_t size); + +/* rknn_destroy_mem (support allocate inside and outside) + + destroy tensor memory. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the pointer of tensor memory information. + return: + int error code +*/ +int rknn_destroy_mem(rknn_context ctx, rknn_tensor_mem *mem); + + + +/* rknn_set_io_mem + + set the input and output tensors buffer. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the array of tensor memory information. + rknn_tensor_attr *attr the attribute of input or output tensor buffer. + return: + int error code. +*/ +int rknn_set_io_mem(rknn_context ctx, rknn_tensor_mem *mem, rknn_tensor_attr *attr); + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //_RKNN_RUNTIME_H diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/lib/librknn_api.so b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/lib/librknn_api.so new file mode 100644 index 0000000..ae3b0d1 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/lib/librknn_api.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/lib64/librknn_api.so b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/lib64/librknn_api.so new file mode 100644 index 0000000..950bc6e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_api/librknn_api/lib64/librknn_api.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/CMakeLists.txt new file mode 100644 index 0000000..ab0d1f6 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_matmul_sample_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rknn_utils +include_directories(${CMAKE_SOURCE_DIR}/librknn_utils/include) +set(RKNN_UTILS_LIB ${CMAKE_CURRENT_SOURCE_DIR}/librknn_utils/${LIB_ARCH}/librknn_utils.so) + +add_executable(rknn_matmul_sample + example/matmul_sample.c +) + +target_link_libraries(rknn_matmul_sample + "-Wl,--allow-shlib-undefined" ${RKNN_UTILS_LIB} +) + +# install target +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_matmul_sample) +install(TARGETS rknn_matmul_sample DESTINATION bin) +install(PROGRAMS ${RKNN_UTILS_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/README.md b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/README.md new file mode 100644 index 0000000..bdac65e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/README.md @@ -0,0 +1,28 @@ +## build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## install + +connect device and push build output into `/userdata` + +``` +adb push install/rknn_matmul_sample/lib/librknn_utils.so /usr/lib +adb push install/rknn_matmul_sample /userdata/ +``` + +## run + +``` +adb shell +cd /userdata/rknn_matmul_sample/ +``` + +- /rk180x/rv1109/rv1126 +``` +./bin/rknn_matmul_sample 256 4096 +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/build.sh b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/build.sh new file mode 100644 index 0000000..75a9a87 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/build.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +# GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/example/matmul_sample.c b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/example/matmul_sample.c new file mode 100644 index 0000000..7fec91a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/example/matmul_sample.c @@ -0,0 +1,182 @@ +/** + * Example: Calculate (x-y)^2 using Matmul API + */ + + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#include +#include "rknn_matmul_api.h" + +/*------------------------------------------- + Macros and Variables +-------------------------------------------*/ + +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static int gen_random_data(int8_t *x,int len,int min_value,int max_value) { + srand((unsigned int)time(NULL)); + int range = max_value-min_value+1; + for (int i = 0;i \n",argv[0]); + return -1; + } + int DIM = atoi(argv[1]); + int BATCH_SIZE = atoi(argv[2]); + rknn_tensor_type dtype = RKNN_TENSOR_INT8; + int8_t *x = (int8_t *)malloc(DIM*sizeof(int8_t)); + int8_t *y = (int8_t *)malloc(DIM*BATCH_SIZE*sizeof(int8_t)); + float out_fp32_buf[BATCH_SIZE]; + float res_cpu[BATCH_SIZE]; + int x_size = DIM; + int y_size = DIM*BATCH_SIZE; + int test_count = 100; + float err; + struct timeval start_time, stop_time; + + int *square_y = (int *)malloc(BATCH_SIZE*sizeof(int)); + + //generate random test data + gen_random_data(x,x_size,-128,127); + gen_random_data(y,y_size,-128,127); + pre_process_y(y,DIM,BATCH_SIZE,square_y); + + rknn_matmul_handle_t handle= rknn_matmul_load(x,y, 1, DIM, BATCH_SIZE, dtype); + if (handle == NULL) + { + fprintf(stderr, "rknn_matmul_load failed.\n"); + return -1; + } + + //loop for matmul + gettimeofday(&start_time, NULL); + for(int i = 0;i + +/* + the tensor data type. +*/ + +typedef enum _rknn_tensor_type { + RKNN_TENSOR_FLOAT32 = 0, /* data type is float32. */ + RKNN_TENSOR_FLOAT16, /* data type is float16. */ + RKNN_TENSOR_INT8, /* data type is int8. */ + RKNN_TENSOR_UINT8, /* data type is uint8. */ + RKNN_TENSOR_INT16, /* data type is int16. */ + + RKNN_TENSOR_TYPE_MAX +} rknn_tensor_type; + +#ifdef __arm__ +typedef uint32_t rknn_context; +#else +typedef uint64_t rknn_context; +#endif + + +/* + Definition of handle for rknn_matmul_run. +*/ +typedef struct _rknn_matmul_t{ + void* A; + void* B; + int32_t M; /* the low rank dimension of A */ + int32_t K; /* the high rank dimension of A and B*/ + int32_t N; /* the low rank dimension of B */ + rknn_tensor_type in_dtype; /* the input buffer type */ + rknn_context rknn_ctx; /* rknn context handle */ +} rknn_matmul_t; + +typedef rknn_matmul_t* rknn_matmul_handle_t; + +/* rknn_matmul_load + + load input buffer and initial the context. + + [input]: + void* a the pointer of A Matrix buffer, number of element is K*M, alloced by user. + void* b the pointer to B Matrix buffer, number of element is K*N, alloced by user. + int32_t M the low rank dimension of A + int32_t K the high rank dimension of A + int32_t N the low rank dimension of B + rknn_tensor_type dtype; the input buffer type, now only support RKNN_TENSOR_UINT8 and RKNN_TENSOR_INT8. + [output]: + rknn_matmul_handle_t the handle of mamul. it will return NULL if failed. +*/ +rknn_matmul_handle_t rknn_matmul_load(void *a, void *b, int M, int K, int N, rknn_tensor_type dtype); + +/* rknn_matmul_run + + run Matmul with fixed shape. + + [input]: + rknn_matmul_handle_t matmul_handle the handle of mamul, get by rknn_matmul_load. + float *c the pointer of C Matrix buffer, number of element is 256x4096, alloced by user. + [output]: + int error code. +*/ +int rknn_matmul_run(rknn_matmul_handle_t matmul_handle, float *c); + +/* rknn_matmul_unload + + destroy the context. + + [input]: + rknn_matmul_handle_t matmul_handle the handle of mamul, get by rknn_matmul_load. + [output]: + int error code. +*/ +int rknn_matmul_unload(rknn_matmul_handle_t matmul_handle); + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //_RKNN_MATMUL_H \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/librknn_utils/lib/librknn_utils.so b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/librknn_utils/lib/librknn_utils.so new file mode 100644 index 0000000..a35f60e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/librknn_utils/lib/librknn_utils.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/librknn_utils/lib64/librknn_utils.so b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/librknn_utils/lib64/librknn_utils.so new file mode 100644 index 0000000..2ca9bf6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknn/rknn_utils/librknn_utils/lib64/librknn_utils.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/memory_profile b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/memory_profile new file mode 100644 index 0000000..c8d125b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/memory_profile differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/libann_plugin.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/libann_plugin.so new file mode 100644 index 0000000..269d25a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/libann_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/librknn_plugin.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/librknn_plugin.so new file mode 100644 index 0000000..27977c6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-aarch64/usr/lib/npu/rknn/plugins/librknn_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libGAL.so new file mode 100644 index 0000000..fe54bb2 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..d3e8586 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..ccae677 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libVSC_Lite.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libVSC_Lite.so new file mode 100644 index 0000000..041deca Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/libVSC_Lite.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..b2c409b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-mini/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libGAL.so new file mode 100644 index 0000000..669fadd Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..44c4399 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..40c62f4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libVSC_Lite.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libVSC_Lite.so new file mode 100644 index 0000000..041deca Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/libVSC_Lite.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..f2c5c5f Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma-mini/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/bin/rknn_server b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/bin/rknn_server new file mode 100644 index 0000000..1ff3313 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/bin/rknn_server differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libCLC.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libCLC.so new file mode 100644 index 0000000..642b34b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libCLC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libGAL.so new file mode 100644 index 0000000..7f5902c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNGPUBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNGPUBinary.so new file mode 100644 index 0000000..c43c374 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNGPUBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNVXCBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNVXCBinary.so new file mode 100644 index 0000000..2e20033 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libNNVXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenCL.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenCL.so.1.2 new file mode 100644 index 0000000..e6c22e1 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenCL.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..cb0ef11 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..40c62f4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOvx12VXCBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOvx12VXCBinary.so new file mode 100644 index 0000000..ffb6711 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libOvx12VXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libVSC.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libVSC.so new file mode 100644 index 0000000..639013d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libVSC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libneuralnetworks.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libneuralnetworks.so new file mode 100644 index 0000000..4afe4f3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/libneuralnetworks.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..3576099 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/memory_profile b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/memory_profile new file mode 100644 index 0000000..542fae6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/memory_profile differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/libann_plugin.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/libann_plugin.so new file mode 100644 index 0000000..da693e0 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/libann_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/librknn_plugin.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/librknn_plugin.so new file mode 100644 index 0000000..8d675de Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf-puma/usr/lib/npu/rknn/plugins/librknn_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/libVSC.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/libVSC.so new file mode 100644 index 0000000..639013d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/libVSC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..a70f988 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/memory_profile b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/memory_profile new file mode 100644 index 0000000..04dce87 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/memory_profile differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/plugins/libann_plugin.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/plugins/libann_plugin.so new file mode 100644 index 0000000..a3f8ba4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/plugins/libann_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/plugins/librknn_plugin.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/plugins/librknn_plugin.so new file mode 100644 index 0000000..b1f81ec Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/drivers/linux-armhf/usr/lib/npu/rknn/plugins/librknn_plugin.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/mobilenet_v1.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/mobilenet_v1.rknn new file mode 100644 index 0000000..1a1ff1b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/mobilenet_v1.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/test.py b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/test.py new file mode 100644 index 0000000..2484b68 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/example/mobilenet_v1/test.py @@ -0,0 +1,49 @@ +import numpy as np +import cv2 +from rknn.api import RKNN + +def show_outputs(outputs): + output = outputs[0][0] + output_sorted = sorted(output, reverse=True) + top5_str = 'mobilenet_v1\n-----TOP 5-----\n' + for i in range(5): + value = output_sorted[i] + index = np.where(output == value) + for j in range(len(index)): + if (i + j) >= 5: + break + if value > 0: + topi = '{}: {}\n'.format(index[j], value) + else: + topi = '-1: 0.0\n' + top5_str += topi + print(top5_str) + +if __name__ == '__main__': + + # Create RKNN object + rknn = RKNN() + + # Direct load rknn model + print('--> Loading RKNN model') + ret = rknn.load_rknn('./mobilenet_v1.rknn') + if ret != 0: + print('Load mobilenet_v1.rknn failed!') + exit(ret) + print('done') + + # Set inputs + img = cv2.imread('./dog_224x224.jpg') + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + + # Init Runtime + rknn.init_runtime() + + # Inference + print('--> Running model') + outputs = rknn.inference(inputs=[img]) + show_outputs(outputs) + print('done') + + rknn.release() + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/__init__.py b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/__init__.py new file mode 100644 index 0000000..5b98fb2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/__init__.py @@ -0,0 +1 @@ +from rknn.api.rknn import RKNN diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn.py b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn.py new file mode 100644 index 0000000..42b7e69 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn.py @@ -0,0 +1,130 @@ +# -*- coding:utf-8 -*- +import os +import sys +import traceback +import re + +from argparse import Namespace +from .rknn_base import RKNNBase +from .rknn_runtime import RKNNRuntime + +class RKNN: + """ + Rockchip NN SDK + """ + def __init__(self): + cur_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + self.rknn_base = RKNNBase(cur_path) + + def load_rknn(self, path): + """ + Load RKNN model + :param path: RKNN model file path + :return: success: 0, failure: -1 + """ + if not os.path.exists(path): + print('RKNN model file {} not exists!'.format(path)) + return -1 + try: + ret = self.rknn_base.import_rknn(path) + except: + print('Catch exception when loading RKNN model [{}]!'.format(path)) + RKNN._print_traceback(traceback.format_exc()) + return -1 + else: + if ret != 0: + print('Load RKNN model [{}] failed!'.format(path)) + return ret + + def init_runtime(self, perf_debug=False): + """ + Init run time environment. Needed by called before inference or eval performance. + :param perf_debug: enable dump layer performance. + :return: success: 0, failure: -1 + """ + try: + self.rknn_base.init_runtime(target=None, device_id=None, perf_debug=perf_debug) + except: + print('Catch exception when init runtime!') + RKNN._print_traceback(traceback.format_exc()) + return -1 + + return 0 + + def inference(self, inputs, data_type='uint8', data_format='nhwc', outputs=None): + """ + Run model inference + :param inputs: Input data List (ndarray list) + :param data_type: Input data type + :param data_format: Input data format + :param outputs: Output data list, for determine shape and dtype (empty ndarray) + :return: Output data (ndarray list) + """ + try: + results = self.rknn_base.inference(inputs=inputs, data_type=data_type, + data_format=data_format, outputs=outputs) + except: + print('Catch exception when inference!') + RKNN._print_traceback(traceback.format_exc()) + results = None + finally: + useless_file = os.path.join(os.getcwd(), 'viv_vir_cl_intrinsic_ImgLS.lib') + if os.path.exists(useless_file): + os.remove(useless_file) + return results + + + def eval_perf(self, inputs, data_type='uint8', data_format='nhwc', is_print=True): + """ + Evaluate model performance + :param inputs: Input data list (ndarray list) + :param data_type: Input data type + :param data_format: Input data format + :param is_print: Format print perf result + :return: Performance Result (dict) + """ + try: + perfs = self.rknn_base.eval_performance(inputs, data_type, data_format) + if perfs is None: + print('Error: Performance information is empty, some mistakes may happen.') + return perfs + if is_print: + print(self.rknn_base.format_perf_detail(detail=perfs)) + except: + print('Catch exception when evaluating model performance!') + RKNN._print_traceback(traceback.format_exc()) + return None + finally: + useless_file = os.path.join(os.getcwd(), 'viv_vir_cl_intrinsic_ImgLS.lib') + if os.path.exists(useless_file): + os.remove(useless_file) + + return perfs + + def get_sdk_version(self): + """ + Get SDK version + :return: sdk_version + """ + try: + sdk_version = self.rknn_base.get_sdk_version() + except Exception: + print('Catch exception when get sdk version') + RKNN._print_traceback(traceback.format_exc()) + return None + + return sdk_version + + def release(self): + """ + Release RKNN resource + :return: None + """ + self.rknn_base.release() + + @staticmethod + def _print_traceback(traceback_info): + reg = re.compile(re.escape(RKNNBase.redirect_src), re.IGNORECASE) + traceback_info = reg.sub(RKNNBase.redirect_dst, traceback_info) + print(traceback_info) + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_base.cpython-36m-aarch64-linux-gnu.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_base.cpython-36m-aarch64-linux-gnu.so new file mode 100644 index 0000000..f94360c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_base.cpython-36m-aarch64-linux-gnu.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_model.cpython-36m-aarch64-linux-gnu.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_model.cpython-36m-aarch64-linux-gnu.so new file mode 100644 index 0000000..533a9bb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_model.cpython-36m-aarch64-linux-gnu.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_runtime.cpython-36m-aarch64-linux-gnu.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_runtime.cpython-36m-aarch64-linux-gnu.so new file mode 100644 index 0000000..f98b431 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/python/rknn/api/rknn_runtime.cpython-36m-aarch64-linux-gnu.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/CImg/CImg.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/CImg/CImg.h new file mode 100644 index 0000000..2bfe567 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/CImg/CImg.h @@ -0,0 +1,65138 @@ +/* + # + # File : CImg.h + # ( C++ header file ) + # + # Description : C++ Template Image Processing Toolkit. + # This file is the main component of the CImg Library project. + # ( http://cimg.eu ) + # + # Project manager : David Tschumperlé + # ( http://tschumperle.users.greyc.fr/ ) + # + # A complete list of contributors is available in file 'README.txt' + # distributed within the CImg package. + # + # Licenses : This file is 'dual-licensed', you have to choose one + # of the two licenses below to apply. + # + # CeCILL-C + # The CeCILL-C license is close to the GNU LGPL. + # ( http://cecill.info/licences/Licence_CeCILL-C_V1-en.html ) + # + # or CeCILL v2.1 + # The CeCILL license is compatible with the GNU GPL. + # ( http://cecill.info/licences/Licence_CeCILL_V2.1-en.html ) + # + # This software is governed either by the CeCILL or the CeCILL-C license + # under French law and abiding by the rules of distribution of free software. + # You can use, modify and or redistribute the software under the terms of + # the CeCILL or CeCILL-C licenses as circulated by CEA, CNRS and INRIA + # at the following URL: "http://cecill.info". + # + # As a counterpart to the access to the source code and rights to copy, + # modify and redistribute granted by the license, users are provided only + # with a limited warranty and the software's author, the holder of the + # economic rights, and the successive licensors have only limited + # liability. + # + # In this respect, the user's attention is drawn to the risks associated + # with loading, using, modifying and/or developing or reproducing the + # software by the user in light of its specific status of free software, + # that may mean that it is complicated to manipulate, and that also + # therefore means that it is reserved for developers and experienced + # professionals having in-depth computer knowledge. Users are therefore + # encouraged to load and test the software's suitability as regards their + # requirements in conditions enabling the security of their systems and/or + # data to be ensured and, more generally, to use and operate it in the + # same conditions as regards security. + # + # The fact that you are presently reading this means that you have had + # knowledge of the CeCILL and CeCILL-C licenses and that you accept its terms. + # +*/ + +// Set version number of the library. +#ifndef cimg_version +#define cimg_version 298 + +/*----------------------------------------------------------- + # + # Test and possibly auto-set CImg configuration variables + # and include required headers. + # + # If you find that the default configuration variables are + # not adapted to your system, you can override their values + # before including the header file "CImg.h" + # (use the #define directive). + # + ------------------------------------------------------------*/ + +// Include standard C++ headers. +// This is the minimal set of required headers to make CImg-based codes compile. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define cimg_str(x) #x +#define cimg_str2(x) cimg_str(x) + +// Detect/configure OS variables. +// +// Define 'cimg_OS' to: '0' for an unknown OS (will try to minize library dependencies). +// '1' for a Unix-like OS (Linux, Solaris, BSD, MacOSX, Irix, ...). +// '2' for Microsoft Windows. +// (auto-detection is performed if 'cimg_OS' is not set by the user). +#ifndef cimg_OS +#if defined(unix) || defined(__unix) || defined(__unix__) \ + || defined(linux) || defined(__linux) || defined(__linux__) \ + || defined(sun) || defined(__sun) \ + || defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined (__DragonFly__) \ + || defined(sgi) || defined(__sgi) \ + || defined(__OSX__) || defined(__MACOSX__) || defined(__APPLE__) \ + || defined(__CYGWIN__) +#define cimg_OS 1 +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +#define cimg_OS 2 +#else +#define cimg_OS 0 +#endif +#elif !(cimg_OS==0 || cimg_OS==1 || cimg_OS==2) +#error CImg Library: Invalid configuration variable 'cimg_OS'. +#error (correct values are '0 = unknown OS', '1 = Unix-like OS', '2 = Microsoft Windows'). +#endif +#ifndef cimg_date +#define cimg_date __DATE__ +#endif +#ifndef cimg_time +#define cimg_time __TIME__ +#endif + +// Disable silly warnings on some Microsoft VC++ compilers. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#pragma warning(disable:4244) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#pragma warning(disable:4319) +#pragma warning(disable:4512) +#pragma warning(disable:4571) +#pragma warning(disable:4640) +#pragma warning(disable:4706) +#pragma warning(disable:4710) +#pragma warning(disable:4800) +#pragma warning(disable:4804) +#pragma warning(disable:4820) +#pragma warning(disable:4996) + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#endif + +// Define correct string functions for each compiler and OS. +#if cimg_OS==2 && defined(_MSC_VER) +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#include +#if defined(__MACOSX__) || defined(__APPLE__) +#define cimg_sscanf cimg::_sscanf +#define cimg_sprintf cimg::_sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf snprintf +#define cimg_vsnprintf vsnprintf +#endif +#endif + +// Include OS-specific headers. +#if cimg_OS==1 +#include +#include +#include +#include +#include +#include +#elif cimg_OS==2 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#ifndef _WIN32_IE +#define _WIN32_IE 0x0400 +#endif +#include +#include +#include +enum {FALSE_WIN = 0}; +#endif + +// Look for C++11 features. +#ifndef cimg_use_cpp11 +#if __cplusplus>201100 +#define cimg_use_cpp11 1 +#else +#define cimg_use_cpp11 0 +#endif +#endif +#if cimg_use_cpp11==1 +#include +#include +#endif + +// Convenient macro to define pragma +#ifdef _MSC_VER +#define cimg_pragma(x) __pragma(x) +#else +#define cimg_pragma(x) _Pragma(#x) +#endif + +// Define own types 'cimg_long/ulong' and 'cimg_int64/uint64' to ensure portability. +// ( constrained to 'sizeof(cimg_ulong/cimg_long) = sizeof(void*)' and 'sizeof(cimg_int64/cimg_uint64)=8' ). +#if cimg_OS==2 + +#define cimg_uint64 unsigned __int64 +#define cimg_int64 __int64 +#define cimg_ulong UINT_PTR +#define cimg_long INT_PTR +#ifdef _MSC_VER +#define cimg_fuint64 "%I64u" +#define cimg_fint64 "%I64d" +#else +#define cimg_fuint64 "%llu" +#define cimg_fint64 "%lld" +#endif + +#else + +#if UINTPTR_MAX==0xffffffff || defined(__arm__) || defined(_M_ARM) || ((ULONG_MAX)==(UINT_MAX)) +#define cimg_uint64 unsigned long long +#define cimg_int64 long long +#define cimg_fuint64 "%llu" +#define cimg_fint64 "%lld" +#else +#define cimg_uint64 unsigned long +#define cimg_int64 long +#define cimg_fuint64 "%lu" +#define cimg_fint64 "%ld" +#endif + +#if defined(__arm__) || defined(_M_ARM) +#define cimg_ulong unsigned long long +#define cimg_long long long +#else +#define cimg_ulong unsigned long +#define cimg_long long +#endif + +#endif + +// Configure filename separator. +// +// Filename separator is set by default to '/', except for Windows where it is '\'. +#ifndef cimg_file_separator +#if cimg_OS==2 +#define cimg_file_separator '\\' +#else +#define cimg_file_separator '/' +#endif +#endif + +// Configure verbosity of output messages. +// +// Define 'cimg_verbosity' to: '0' to hide library messages (quiet mode). +// '1' to output library messages on the console. +// '2' to output library messages on a basic dialog window (default behavior). +// '3' to do as '1' + add extra warnings (may slow down the code!). +// '4' to do as '2' + add extra warnings (may slow down the code!). +// +// Define 'cimg_strict_warnings' to replace warning messages by exception throwns. +// +// Define 'cimg_use_vt100' to allow output of color messages on VT100-compatible terminals. +#ifndef cimg_verbosity +#if cimg_OS==2 +#define cimg_verbosity 2 +#else +#define cimg_verbosity 1 +#endif +#elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4) +#error CImg Library: Configuration variable 'cimg_verbosity' is badly defined. +#error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }). +#endif + +// Configure OpenMP support. +// (http://www.openmp.org) +// +// Define 'cimg_use_openmp' to enable OpenMP support (requires OpenMP 3.0+). +// +// OpenMP directives are used in many CImg functions to get +// advantages of multi-core CPUs. +#if !defined(cimg_use_openmp) +#ifdef _OPENMP +#define cimg_use_openmp 1 +#else +#define cimg_use_openmp 0 +#endif +#endif +#if cimg_use_openmp!=0 +#include +#define cimg_pragma_openmp(p) cimg_pragma(omp p) +#else +#define cimg_pragma_openmp(p) +#endif + +// Configure the 'abort' signal handler (does nothing by default). +// A typical signal handler can be defined in your own source like this: +// #define cimg_abort_test if (is_abort) throw CImgAbortException("") +// +// where 'is_abort' is a boolean variable defined somewhere in your code and reachable in the method. +// 'cimg_abort_test2' does the same but is called more often (in inner loops). +#if defined(cimg_abort_test) && cimg_use_openmp!=0 + +// Define abort macros to be used with OpenMP. +#ifndef _cimg_abort_init_openmp +#define _cimg_abort_init_openmp bool _cimg_abort_go_openmp = true; cimg::unused(_cimg_abort_go_openmp) +#endif +#ifndef _cimg_abort_try_openmp +#define _cimg_abort_try_openmp if (_cimg_abort_go_openmp) try +#endif +#ifndef _cimg_abort_catch_openmp +#define _cimg_abort_catch_openmp catch (CImgAbortException&) { cimg_pragma(omp atomic) _cimg_abort_go_openmp&=false; } +#endif +#ifndef _cimg_abort_catch_fill_openmp +#define _cimg_abort_catch_fill_openmp \ + catch (CImgException& e) { cimg_pragma(omp critical(abort)) CImg::string(e._message).move_to(is_error); \ + cimg_pragma(omp atomic) _cimg_abort_go_openmp&=false; } +#endif +#ifdef cimg_abort_test2 +#ifndef _cimg_abort_try_openmp2 +#define _cimg_abort_try_openmp2 _cimg_abort_try_openmp +#endif +#ifndef _cimg_abort_catch_openmp2 +#define _cimg_abort_catch_openmp2 _cimg_abort_catch_openmp +#endif +#endif +#endif + +#ifndef _cimg_abort_init_openmp +#define _cimg_abort_init_openmp +#endif +#ifndef _cimg_abort_try_openmp +#define _cimg_abort_try_openmp +#endif +#ifndef _cimg_abort_catch_openmp +#define _cimg_abort_catch_openmp +#endif +#ifndef _cimg_abort_try_openmp2 +#define _cimg_abort_try_openmp2 +#endif +#ifndef _cimg_abort_catch_openmp2 +#define _cimg_abort_catch_openmp2 +#endif +#ifndef _cimg_abort_catch_fill_openmp +#define _cimg_abort_catch_fill_openmp +#endif +#ifndef cimg_abort_init +#define cimg_abort_init +#endif +#ifndef cimg_abort_test +#define cimg_abort_test +#endif +#ifndef cimg_abort_test2 +#define cimg_abort_test2 +#endif + +// Configure display framework. +// +// Define 'cimg_display' to: '0' to disable display capabilities. +// '1' to use the X-Window framework (X11). +// '2' to use the Microsoft GDI32 framework. +#ifndef cimg_display +#if cimg_OS==0 +#define cimg_display 0 +#elif cimg_OS==1 +#define cimg_display 1 +#elif cimg_OS==2 +#define cimg_display 2 +#endif +#elif !(cimg_display==0 || cimg_display==1 || cimg_display==2) +#error CImg Library: Configuration variable 'cimg_display' is badly defined. +#error (should be { 0=none | 1=X-Window (X11) | 2=Microsoft GDI32 }). +#endif + +// Include display-specific headers. +#if cimg_display==1 +#include +#include +#include +#include +#ifdef cimg_use_xshm +#include +#include +#include +#endif +#ifdef cimg_use_xrandr +#include +#endif +#endif +#ifndef cimg_appname +#define cimg_appname "CImg" +#endif + +// Configure OpenCV support. +// (http://opencv.willowgarage.com/wiki/) +// +// Define 'cimg_use_opencv' to enable OpenCV support. +// +// OpenCV library may be used to access images from cameras +// (see method 'CImg::load_camera()'). +#ifdef cimg_use_opencv +#ifdef True +#undef True +#define _cimg_redefine_True +#endif +#ifdef False +#undef False +#define _cimg_redefine_False +#endif +#ifdef Status +#undef Status +#define _cimg_redefine_Status +#endif +#include +#include +#if CV_MAJOR_VERSION>=3 +#define _cimg_fourcc cv::VideoWriter::fourcc +#define _cimg_cap_prop_frame_width cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH +#define _cimg_cap_prop_frame_height cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT +#define _cimg_cap_prop_frame_count cv::VideoCaptureProperties::CAP_PROP_FRAME_COUNT +#else +#define _cimg_fourcc CV_FOURCC +#define _cimg_cap_prop_frame_width CV_CAP_PROP_FRAME_WIDTH +#define _cimg_cap_prop_frame_height CV_CAP_PROP_FRAME_HEIGHT +#define _cimg_cap_prop_frame_count CV_CAP_PROP_FRAME_COUNT +#endif +#endif + +// Configure LibPNG support. +// (http://www.libpng.org) +// +// Define 'cimg_use_png' to enable LibPNG support. +// +// PNG library may be used to get a native support of '.png' files. +// (see methods 'CImg::{load,save}_png()'. +#ifdef cimg_use_png +extern "C" { +#include "png.h" +} +#endif + +// Configure LibJPEG support. +// (http://en.wikipedia.org/wiki/Libjpeg) +// +// Define 'cimg_use_jpeg' to enable LibJPEG support. +// +// JPEG library may be used to get a native support of '.jpg' files. +// (see methods 'CImg::{load,save}_jpeg()'). +#ifdef cimg_use_jpeg +extern "C" { +#include "jpeglib.h" +#include "setjmp.h" +} +#endif + +// Configure LibTIFF support. +// (http://www.libtiff.org) +// +// Define 'cimg_use_tiff' to enable LibTIFF support. +// +// TIFF library may be used to get a native support of '.tif' files. +// (see methods 'CImg[List]::{load,save}_tiff()'). +#ifdef cimg_use_tiff +extern "C" { +#define uint64 uint64_hack_ +#define int64 int64_hack_ +#include "tiffio.h" +#undef uint64 +#undef int64 +} +#endif + +// Configure HEIF support +// (https://github.com/strukturag/libheif) +// +// Define 'cimg_use_heif' to enable HEIF support. +// +// HEIF library may be used to get a native support of '.heic' and '.avif' files. +// (see method 'CImg::load_heif()'). +#ifdef cimg_use_heif +#include +#endif + +// Configure LibMINC2 support. +// (http://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_File_Format_Reference) +// +// Define 'cimg_use_minc2' to enable LibMINC2 support. +// +// MINC2 library may be used to get a native support of '.mnc' files. +// (see methods 'CImg::{load,save}_minc2()'). +#ifdef cimg_use_minc2 +#include "minc_io_simple_volume.h" +#include "minc_1_simple.h" +#include "minc_1_simple_rw.h" +#endif + +// Configure Zlib support. +// (http://www.zlib.net) +// +// Define 'cimg_use_zlib' to enable Zlib support. +// +// Zlib library may be used to allow compressed data in '.cimgz' files +// (see methods 'CImg[List]::{load,save}_cimg()'). +#ifdef cimg_use_zlib +extern "C" { +#include "zlib.h" +} +#endif + +// Configure libcurl support. +// (http://curl.haxx.se/libcurl/) +// +// Define 'cimg_use_curl' to enable libcurl support. +// +// Libcurl may be used to get a native support of file downloading from the network. +// (see method 'cimg::load_network()'.) +#ifdef cimg_use_curl +#include "curl/curl.h" +#endif + +// Configure Magick++ support. +// (http://www.imagemagick.org/Magick++) +// +// Define 'cimg_use_magick' to enable Magick++ support. +// +// Magick++ library may be used to get a native support of various image file formats. +// (see methods 'CImg::{load,save}()'). +#ifdef cimg_use_magick +#include "Magick++.h" +#endif + +// Configure FFTW3 support. +// (http://www.fftw.org) +// +// Define 'cimg_use_fftw3' to enable libFFTW3 support. +// +// FFTW3 library may be used to efficiently compute the Fast Fourier Transform +// of image data, without restriction on the image size. +// (see method 'CImg[List]::FFT()'). +#ifdef cimg_use_fftw3 +extern "C" { +#include "fftw3.h" +} +#endif + +// Configure LibBoard support. +// (http://libboard.sourceforge.net/) +// +// Define 'cimg_use_board' to enable Board support. +// +// Board library may be used to draw 3D objects in vector-graphics canvas +// that can be saved as '.ps' or '.svg' files afterwards. +// (see method 'CImg::draw_object3d()'). +#ifdef cimg_use_board +#include "Board.h" +#endif + +// Configure OpenEXR support. +// (http://www.openexr.com/) +// +// Define 'cimg_use_openexr' to enable OpenEXR support. +// +// OpenEXR library may be used to get a native support of '.exr' files. +// (see methods 'CImg::{load,save}_exr()'). +#ifdef cimg_use_openexr +#if __GNUC__>=5 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#pragma GCC diagnostic ignored "-Wshadow" +#endif +#include "ImfRgbaFile.h" +#include "ImfInputFile.h" +#include "ImfChannelList.h" +#include "ImfMatrixAttribute.h" +#include "ImfArray.h" +#if __GNUC__>=5 +#pragma GCC diagnostic pop +#endif +#endif + +// Configure TinyEXR support. +// (https://github.com/syoyo/tinyexr) +// +// Define 'cimg_use_tinyexr' to enable TinyEXR support. +// +// TinyEXR is a small, single header-only library to load and save OpenEXR(.exr) images. +#ifdef cimg_use_tinyexr +#ifndef TINYEXR_IMPLEMENTATION +#define TINYEXR_IMPLEMENTATION +#endif +#include "tinyexr.h" +#endif + +// Lapack configuration. +// (http://www.netlib.org/lapack) +// +// Define 'cimg_use_lapack' to enable LAPACK support. +// +// Lapack library may be used in several CImg methods to speed up +// matrix computations (eigenvalues, inverse, ...). +#ifdef cimg_use_lapack +extern "C" { + extern void sgetrf_(int*, int*, float*, int*, int*, int*); + extern void sgetri_(int*, float*, int*, int*, float*, int*, int*); + extern void sgetrs_(char*, int*, int*, float*, int*, int*, float*, int*, int*); + extern void sgesvd_(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*); + extern void ssyev_(char*, char*, int*, float*, int*, float*, float*, int*, int*); + extern void dgetrf_(int*, int*, double*, int*, int*, int*); + extern void dgetri_(int*, double*, int*, int*, double*, int*, int*); + extern void dgetrs_(char*, int*, int*, double*, int*, int*, double*, int*, int*); + extern void dgesvd_(char*, char*, int*, int*, double*, int*, double*, double*, + int*, double*, int*, double*, int*, int*); + extern void dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*); + extern void dgels_(char*, int*,int*,int*,double*,int*,double*,int*,double*,int*,int*); + extern void sgels_(char*, int*,int*,int*,float*,int*,float*,int*,float*,int*,int*); +} +#endif + +// Check if min/max/PI macros are defined. +// +// CImg does not compile if macros 'min', 'max' or 'PI' are defined, +// because it redefines functions min(), max() and const variable PI in the cimg:: namespace. +// so it '#undef' these macros if necessary, and restore them to reasonable +// values at the end of this file. +#ifdef min +#undef min +#define _cimg_redefine_min +#endif +#ifdef max +#undef max +#define _cimg_redefine_max +#endif +#ifdef PI +#undef PI +#define _cimg_redefine_PI +#endif + +// Define 'cimg_library' namespace suffix. +// +// You may want to add a suffix to the 'cimg_library' namespace, for instance if you need to work +// with several versions of the library at the same time. +#ifdef cimg_namespace_suffix +#define __cimg_library_suffixed(s) cimg_library_##s +#define _cimg_library_suffixed(s) __cimg_library_suffixed(s) +#define cimg_library_suffixed _cimg_library_suffixed(cimg_namespace_suffix) +#else +#define cimg_library_suffixed cimg_library +#endif + +/*------------------------------------------------------------------------------ + # + # Define user-friendly macros. + # + # These CImg macros are prefixed by 'cimg_' and can be used safely in your own + # code. They are useful to parse command line options, or to write image loops. + # + ------------------------------------------------------------------------------*/ + +// Macros to define program usage, and retrieve command line arguments. +#define cimg_usage(usage) cimg_library_suffixed::cimg::option((char*)0,argc,argv,(char*)0,usage,false) +#define cimg_help(str) cimg_library_suffixed::cimg::option((char*)0,argc,argv,str,(char*)0) +#define cimg_option(name,_default,usage) cimg_library_suffixed::cimg::option(name,argc,argv,_default,usage) + +// Macros to define and manipulate local neighborhoods. +#define CImg_2x2(I,T) T I[4]; \ + T& I##cc = I[0]; T& I##nc = I[1]; \ + T& I##cn = I[2]; T& I##nn = I[3]; \ + I##cc = I##nc = \ + I##cn = I##nn = 0 + +#define CImg_3x3(I,T) T I[9]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; \ + T& I##pc = I[3]; T& I##cc = I[4]; T& I##nc = I[5]; \ + T& I##pn = I[6]; T& I##cn = I[7]; T& I##nn = I[8]; \ + I##pp = I##cp = I##np = \ + I##pc = I##cc = I##nc = \ + I##pn = I##cn = I##nn = 0 + +#define CImg_4x4(I,T) T I[16]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; T& I##ap = I[3]; \ + T& I##pc = I[4]; T& I##cc = I[5]; T& I##nc = I[6]; T& I##ac = I[7]; \ + T& I##pn = I[8]; T& I##cn = I[9]; T& I##nn = I[10]; T& I##an = I[11]; \ + T& I##pa = I[12]; T& I##ca = I[13]; T& I##na = I[14]; T& I##aa = I[15]; \ + I##pp = I##cp = I##np = I##ap = \ + I##pc = I##cc = I##nc = I##ac = \ + I##pn = I##cn = I##nn = I##an = \ + I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_5x5(I,T) T I[25]; \ + T& I##bb = I[0]; T& I##pb = I[1]; T& I##cb = I[2]; T& I##nb = I[3]; T& I##ab = I[4]; \ + T& I##bp = I[5]; T& I##pp = I[6]; T& I##cp = I[7]; T& I##np = I[8]; T& I##ap = I[9]; \ + T& I##bc = I[10]; T& I##pc = I[11]; T& I##cc = I[12]; T& I##nc = I[13]; T& I##ac = I[14]; \ + T& I##bn = I[15]; T& I##pn = I[16]; T& I##cn = I[17]; T& I##nn = I[18]; T& I##an = I[19]; \ + T& I##ba = I[20]; T& I##pa = I[21]; T& I##ca = I[22]; T& I##na = I[23]; T& I##aa = I[24]; \ + I##bb = I##pb = I##cb = I##nb = I##ab = \ + I##bp = I##pp = I##cp = I##np = I##ap = \ + I##bc = I##pc = I##cc = I##nc = I##ac = \ + I##bn = I##pn = I##cn = I##nn = I##an = \ + I##ba = I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_2x2x2(I,T) T I[8]; \ + T& I##ccc = I[0]; T& I##ncc = I[1]; \ + T& I##cnc = I[2]; T& I##nnc = I[3]; \ + T& I##ccn = I[4]; T& I##ncn = I[5]; \ + T& I##cnn = I[6]; T& I##nnn = I[7]; \ + I##ccc = I##ncc = \ + I##cnc = I##nnc = \ + I##ccn = I##ncn = \ + I##cnn = I##nnn = 0 + +#define CImg_3x3x3(I,T) T I[27]; \ + T& I##ppp = I[0]; T& I##cpp = I[1]; T& I##npp = I[2]; \ + T& I##pcp = I[3]; T& I##ccp = I[4]; T& I##ncp = I[5]; \ + T& I##pnp = I[6]; T& I##cnp = I[7]; T& I##nnp = I[8]; \ + T& I##ppc = I[9]; T& I##cpc = I[10]; T& I##npc = I[11]; \ + T& I##pcc = I[12]; T& I##ccc = I[13]; T& I##ncc = I[14]; \ + T& I##pnc = I[15]; T& I##cnc = I[16]; T& I##nnc = I[17]; \ + T& I##ppn = I[18]; T& I##cpn = I[19]; T& I##npn = I[20]; \ + T& I##pcn = I[21]; T& I##ccn = I[22]; T& I##ncn = I[23]; \ + T& I##pnn = I[24]; T& I##cnn = I[25]; T& I##nnn = I[26]; \ + I##ppp = I##cpp = I##npp = \ + I##pcp = I##ccp = I##ncp = \ + I##pnp = I##cnp = I##nnp = \ + I##ppc = I##cpc = I##npc = \ + I##pcc = I##ccc = I##ncc = \ + I##pnc = I##cnc = I##nnc = \ + I##ppn = I##cpn = I##npn = \ + I##pcn = I##ccn = I##ncn = \ + I##pnn = I##cnn = I##nnn = 0 + +#define cimg_def2x2(img,x,y) \ + int _n1##x = x<(img).width() - 1?x + 1:(img).width() - 1, \ + _n1##y = y<(img).height() - 1?y + 1:(img).height() - 1 + +#define cimg_def3x3(img,x,y) \ + cimg_def2x2(img,x,y); \ + int _p1##x = x>1?x - 1:0, \ + _p1##y = y>1?y - 1:0 + +#define cimg_def4x4(img,x,y) \ + cimg_def3x3(img,x,y); \ + int _n2##x = x<(img).width() - 2?x + 2:(img).width() - 1, \ + _n2##y = y<(img).height() - 2?y + 2:(img).height() - 1 + +#define cimg_def5x5(img,x,y) \ + cimg_def4x4(img,x,y); \ + int _p2##x = x>2?x - 2:0, \ + _p2##y = y>2?y - 2:0 + +#define cimg_def6x6(img,x,y) \ + cimg_def5x5(img,x,y); \ + int _n3##x = x<(img).width() - 3?x + 3:(img).width() - 1, \ + _n3##y = y<(img).height() - 3?y + 3:(img).height() - 1 + +#define cimg_def7x7(img,x,y) \ + cimg_def6x6(img,x,y); \ + int _p3##x = x>3?x - 3:0, \ + _p3##y = y>3?y - 3:0 + +#define cimg_def8x8(img,x,y) \ + cimg_def7x7(img,x,y); \ + int _n4##x = x<(img).width() - 4?x + 4:(img).width() - 1, \ + _n4##y = y<(img).height() - 4?y + 4:(img).height() - 1 + +#define cimg_def9x9(img,x,y) \ + cimg_def8x8(img,x,y); \ + int _p4##x = x>4?x - 4:0, \ + _p4##y = y>4?y - 4:0 + +#define cimg_def2x2x2(img,x,y,z) \ + cimg_def2x2(img,x,y); \ + int _n1##z = z<(img).depth() - 1?z + 1:(img).depth() - 1 + +#define cimg_def3x3x3(img,x,y,z) \ + cimg_def2x2x2(img,x,y,z); \ + int _p1##x = x>1?x - 1:0, \ + _p1##y = y>1?y - 1:0, \ + _p1##z = z>1?z - 1:0 + +#define cimg_get2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_p1##x,y,z,c), I[4] = (T)(img)(x,y,z,c), I[5] = (T)(img)(_n1##x,y,z,c), \ + I[6] = (T)(img)(_p1##x,_n1##y,z,c), I[7] = (T)(img)(x,_n1##y,z,c), I[8] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get4x4(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_n2##x,_p1##y,z,c), I[4] = (T)(img)(_p1##x,y,z,c), I[5] = (T)(img)(x,y,z,c), \ + I[6] = (T)(img)(_n1##x,y,z,c), I[7] = (T)(img)(_n2##x,y,z,c), I[8] = (T)(img)(_p1##x,_n1##y,z,c), \ + I[9] = (T)(img)(x,_n1##y,z,c), I[10] = (T)(img)(_n1##x,_n1##y,z,c), I[11] = (T)(img)(_n2##x,_n1##y,z,c), \ + I[12] = (T)(img)(_p1##x,_n2##y,z,c), I[13] = (T)(img)(x,_n2##y,z,c), I[14] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[15] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get5x5(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[6] = (T)(img)(_p1##x,_p1##y,z,c), I[7] = (T)(img)(x,_p1##y,z,c), I[8] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[9] = (T)(img)(_n2##x,_p1##y,z,c), I[10] = (T)(img)(_p2##x,y,z,c), I[11] = (T)(img)(_p1##x,y,z,c), \ + I[12] = (T)(img)(x,y,z,c), I[13] = (T)(img)(_n1##x,y,z,c), I[14] = (T)(img)(_n2##x,y,z,c), \ + I[15] = (T)(img)(_p2##x,_n1##y,z,c), I[16] = (T)(img)(_p1##x,_n1##y,z,c), I[17] = (T)(img)(x,_n1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_n1##y,z,c), I[19] = (T)(img)(_n2##x,_n1##y,z,c), I[20] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_n2##y,z,c), I[22] = (T)(img)(x,_n2##y,z,c), I[23] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get6x6(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[6] = (T)(img)(_p2##x,_p1##y,z,c), I[7] = (T)(img)(_p1##x,_p1##y,z,c), I[8] = (T)(img)(x,_p1##y,z,c), \ + I[9] = (T)(img)(_n1##x,_p1##y,z,c), I[10] = (T)(img)(_n2##x,_p1##y,z,c), I[11] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[12] = (T)(img)(_p2##x,y,z,c), I[13] = (T)(img)(_p1##x,y,z,c), I[14] = (T)(img)(x,y,z,c), \ + I[15] = (T)(img)(_n1##x,y,z,c), I[16] = (T)(img)(_n2##x,y,z,c), I[17] = (T)(img)(_n3##x,y,z,c), \ + I[18] = (T)(img)(_p2##x,_n1##y,z,c), I[19] = (T)(img)(_p1##x,_n1##y,z,c), I[20] = (T)(img)(x,_n1##y,z,c), \ + I[21] = (T)(img)(_n1##x,_n1##y,z,c), I[22] = (T)(img)(_n2##x,_n1##y,z,c), I[23] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[24] = (T)(img)(_p2##x,_n2##y,z,c), I[25] = (T)(img)(_p1##x,_n2##y,z,c), I[26] = (T)(img)(x,_n2##y,z,c), \ + I[27] = (T)(img)(_n1##x,_n2##y,z,c), I[28] = (T)(img)(_n2##x,_n2##y,z,c), I[29] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[30] = (T)(img)(_p2##x,_n3##y,z,c), I[31] = (T)(img)(_p1##x,_n3##y,z,c), I[32] = (T)(img)(x,_n3##y,z,c), \ + I[33] = (T)(img)(_n1##x,_n3##y,z,c), I[34] = (T)(img)(_n2##x,_n3##y,z,c), I[35] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get7x7(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_p3##x,_p2##y,z,c), I[8] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p1##x,_p2##y,z,c), I[10] = (T)(img)(x,_p2##y,z,c), I[11] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[12] = (T)(img)(_n2##x,_p2##y,z,c), I[13] = (T)(img)(_n3##x,_p2##y,z,c), I[14] = (T)(img)(_p3##x,_p1##y,z,c), \ + I[15] = (T)(img)(_p2##x,_p1##y,z,c), I[16] = (T)(img)(_p1##x,_p1##y,z,c), I[17] = (T)(img)(x,_p1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_p1##y,z,c), I[19] = (T)(img)(_n2##x,_p1##y,z,c), I[20] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[21] = (T)(img)(_p3##x,y,z,c), I[22] = (T)(img)(_p2##x,y,z,c), I[23] = (T)(img)(_p1##x,y,z,c), \ + I[24] = (T)(img)(x,y,z,c), I[25] = (T)(img)(_n1##x,y,z,c), I[26] = (T)(img)(_n2##x,y,z,c), \ + I[27] = (T)(img)(_n3##x,y,z,c), I[28] = (T)(img)(_p3##x,_n1##y,z,c), I[29] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_n1##y,z,c), I[31] = (T)(img)(x,_n1##y,z,c), I[32] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_n1##y,z,c), I[34] = (T)(img)(_n3##x,_n1##y,z,c), I[35] = (T)(img)(_p3##x,_n2##y,z,c), \ + I[36] = (T)(img)(_p2##x,_n2##y,z,c), I[37] = (T)(img)(_p1##x,_n2##y,z,c), I[38] = (T)(img)(x,_n2##y,z,c), \ + I[39] = (T)(img)(_n1##x,_n2##y,z,c), I[40] = (T)(img)(_n2##x,_n2##y,z,c), I[41] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p3##x,_n3##y,z,c), I[43] = (T)(img)(_p2##x,_n3##y,z,c), I[44] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[45] = (T)(img)(x,_n3##y,z,c), I[46] = (T)(img)(_n1##x,_n3##y,z,c), I[47] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[48] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get8x8(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_n4##x,_p3##y,z,c), I[8] = (T)(img)(_p3##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p2##x,_p2##y,z,c), I[10] = (T)(img)(_p1##x,_p2##y,z,c), I[11] = (T)(img)(x,_p2##y,z,c), \ + I[12] = (T)(img)(_n1##x,_p2##y,z,c), I[13] = (T)(img)(_n2##x,_p2##y,z,c), I[14] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[15] = (T)(img)(_n4##x,_p2##y,z,c), I[16] = (T)(img)(_p3##x,_p1##y,z,c), I[17] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[18] = (T)(img)(_p1##x,_p1##y,z,c), I[19] = (T)(img)(x,_p1##y,z,c), I[20] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[21] = (T)(img)(_n2##x,_p1##y,z,c), I[22] = (T)(img)(_n3##x,_p1##y,z,c), I[23] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[24] = (T)(img)(_p3##x,y,z,c), I[25] = (T)(img)(_p2##x,y,z,c), I[26] = (T)(img)(_p1##x,y,z,c), \ + I[27] = (T)(img)(x,y,z,c), I[28] = (T)(img)(_n1##x,y,z,c), I[29] = (T)(img)(_n2##x,y,z,c), \ + I[30] = (T)(img)(_n3##x,y,z,c), I[31] = (T)(img)(_n4##x,y,z,c), I[32] = (T)(img)(_p3##x,_n1##y,z,c), \ + I[33] = (T)(img)(_p2##x,_n1##y,z,c), I[34] = (T)(img)(_p1##x,_n1##y,z,c), I[35] = (T)(img)(x,_n1##y,z,c), \ + I[36] = (T)(img)(_n1##x,_n1##y,z,c), I[37] = (T)(img)(_n2##x,_n1##y,z,c), I[38] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[39] = (T)(img)(_n4##x,_n1##y,z,c), I[40] = (T)(img)(_p3##x,_n2##y,z,c), I[41] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p1##x,_n2##y,z,c), I[43] = (T)(img)(x,_n2##y,z,c), I[44] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[45] = (T)(img)(_n2##x,_n2##y,z,c), I[46] = (T)(img)(_n3##x,_n2##y,z,c), I[47] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[48] = (T)(img)(_p3##x,_n3##y,z,c), I[49] = (T)(img)(_p2##x,_n3##y,z,c), I[50] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[51] = (T)(img)(x,_n3##y,z,c), I[52] = (T)(img)(_n1##x,_n3##y,z,c), I[53] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[54] = (T)(img)(_n3##x,_n3##y,z,c), I[55] = (T)(img)(_n4##x,_n3##y,z,c), I[56] = (T)(img)(_p3##x,_n4##y,z,c), \ + I[57] = (T)(img)(_p2##x,_n4##y,z,c), I[58] = (T)(img)(_p1##x,_n4##y,z,c), I[59] = (T)(img)(x,_n4##y,z,c), \ + I[60] = (T)(img)(_n1##x,_n4##y,z,c), I[61] = (T)(img)(_n2##x,_n4##y,z,c), I[62] = (T)(img)(_n3##x,_n4##y,z,c), \ + I[63] = (T)(img)(_n4##x,_n4##y,z,c); + +#define cimg_get9x9(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p4##x,_p4##y,z,c), I[1] = (T)(img)(_p3##x,_p4##y,z,c), I[2] = (T)(img)(_p2##x,_p4##y,z,c), \ + I[3] = (T)(img)(_p1##x,_p4##y,z,c), I[4] = (T)(img)(x,_p4##y,z,c), I[5] = (T)(img)(_n1##x,_p4##y,z,c), \ + I[6] = (T)(img)(_n2##x,_p4##y,z,c), I[7] = (T)(img)(_n3##x,_p4##y,z,c), I[8] = (T)(img)(_n4##x,_p4##y,z,c), \ + I[9] = (T)(img)(_p4##x,_p3##y,z,c), I[10] = (T)(img)(_p3##x,_p3##y,z,c), I[11] = (T)(img)(_p2##x,_p3##y,z,c), \ + I[12] = (T)(img)(_p1##x,_p3##y,z,c), I[13] = (T)(img)(x,_p3##y,z,c), I[14] = (T)(img)(_n1##x,_p3##y,z,c), \ + I[15] = (T)(img)(_n2##x,_p3##y,z,c), I[16] = (T)(img)(_n3##x,_p3##y,z,c), I[17] = (T)(img)(_n4##x,_p3##y,z,c), \ + I[18] = (T)(img)(_p4##x,_p2##y,z,c), I[19] = (T)(img)(_p3##x,_p2##y,z,c), I[20] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_p2##y,z,c), I[22] = (T)(img)(x,_p2##y,z,c), I[23] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_p2##y,z,c), I[25] = (T)(img)(_n3##x,_p2##y,z,c), I[26] = (T)(img)(_n4##x,_p2##y,z,c), \ + I[27] = (T)(img)(_p4##x,_p1##y,z,c), I[28] = (T)(img)(_p3##x,_p1##y,z,c), I[29] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_p1##y,z,c), I[31] = (T)(img)(x,_p1##y,z,c), I[32] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_p1##y,z,c), I[34] = (T)(img)(_n3##x,_p1##y,z,c), I[35] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[36] = (T)(img)(_p4##x,y,z,c), I[37] = (T)(img)(_p3##x,y,z,c), I[38] = (T)(img)(_p2##x,y,z,c), \ + I[39] = (T)(img)(_p1##x,y,z,c), I[40] = (T)(img)(x,y,z,c), I[41] = (T)(img)(_n1##x,y,z,c), \ + I[42] = (T)(img)(_n2##x,y,z,c), I[43] = (T)(img)(_n3##x,y,z,c), I[44] = (T)(img)(_n4##x,y,z,c), \ + I[45] = (T)(img)(_p4##x,_n1##y,z,c), I[46] = (T)(img)(_p3##x,_n1##y,z,c), I[47] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[48] = (T)(img)(_p1##x,_n1##y,z,c), I[49] = (T)(img)(x,_n1##y,z,c), I[50] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[51] = (T)(img)(_n2##x,_n1##y,z,c), I[52] = (T)(img)(_n3##x,_n1##y,z,c), I[53] = (T)(img)(_n4##x,_n1##y,z,c), \ + I[54] = (T)(img)(_p4##x,_n2##y,z,c), I[55] = (T)(img)(_p3##x,_n2##y,z,c), I[56] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[57] = (T)(img)(_p1##x,_n2##y,z,c), I[58] = (T)(img)(x,_n2##y,z,c), I[59] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[60] = (T)(img)(_n2##x,_n2##y,z,c), I[61] = (T)(img)(_n3##x,_n2##y,z,c), I[62] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[63] = (T)(img)(_p4##x,_n3##y,z,c), I[64] = (T)(img)(_p3##x,_n3##y,z,c), I[65] = (T)(img)(_p2##x,_n3##y,z,c), \ + I[66] = (T)(img)(_p1##x,_n3##y,z,c), I[67] = (T)(img)(x,_n3##y,z,c), I[68] = (T)(img)(_n1##x,_n3##y,z,c), \ + I[69] = (T)(img)(_n2##x,_n3##y,z,c), I[70] = (T)(img)(_n3##x,_n3##y,z,c), I[71] = (T)(img)(_n4##x,_n3##y,z,c), \ + I[72] = (T)(img)(_p4##x,_n4##y,z,c), I[73] = (T)(img)(_p3##x,_n4##y,z,c), I[74] = (T)(img)(_p2##x,_n4##y,z,c), \ + I[75] = (T)(img)(_p1##x,_n4##y,z,c), I[76] = (T)(img)(x,_n4##y,z,c), I[77] = (T)(img)(_n1##x,_n4##y,z,c), \ + I[78] = (T)(img)(_n2##x,_n4##y,z,c), I[79] = (T)(img)(_n3##x,_n4##y,z,c), I[80] = (T)(img)(_n4##x,_n4##y,z,c) + +#define cimg_get2x2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c), I[4] = (T)(img)(x,y,_n1##z,c), I[5] = (T)(img)(_n1##x,y,_n1##z,c), \ + I[6] = (T)(img)(x,_n1##y,_n1##z,c), I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +#define cimg_get3x3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c), I[1] = (T)(img)(x,_p1##y,_p1##z,c), \ + I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c), I[3] = (T)(img)(_p1##x,y,_p1##z,c), I[4] = (T)(img)(x,y,_p1##z,c), \ + I[5] = (T)(img)(_n1##x,y,_p1##z,c), I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c), I[7] = (T)(img)(x,_n1##y,_p1##z,c), \ + I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c), I[9] = (T)(img)(_p1##x,_p1##y,z,c), I[10] = (T)(img)(x,_p1##y,z,c), \ + I[11] = (T)(img)(_n1##x,_p1##y,z,c), I[12] = (T)(img)(_p1##x,y,z,c), I[13] = (T)(img)(x,y,z,c), \ + I[14] = (T)(img)(_n1##x,y,z,c), I[15] = (T)(img)(_p1##x,_n1##y,z,c), I[16] = (T)(img)(x,_n1##y,z,c), \ + I[17] = (T)(img)(_n1##x,_n1##y,z,c), I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c), I[19] = (T)(img)(x,_p1##y,_n1##z,c), \ + I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c), I[21] = (T)(img)(_p1##x,y,_n1##z,c), I[22] = (T)(img)(x,y,_n1##z,c), \ + I[23] = (T)(img)(_n1##x,y,_n1##z,c), I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c), I[25] = (T)(img)(x,_n1##y,_n1##z,c), \ + I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +// Macros to perform various image loops. +// +// These macros are simpler to use than loops with C++ iterators. +#define cimg_for(img,ptrs,T_ptrs) \ + for (T_ptrs *ptrs = (img)._data, *_max##ptrs = (img)._data + (img).size(); ptrs<_max##ptrs; ++ptrs) +#define cimg_rof(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size() - 1; ptrs>=(img)._data; --ptrs) +#define cimg_foroff(img,off) for (cimg_ulong off = 0, _max##off = (img).size(); off<_max##off; ++off) +#define cimg_rofoff(img,off) for (cimg_long off = (cimg_long)((img).size() - 1); off>=0; --off) + +#define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i) +#define cimg_forX(img,x) cimg_for1((img)._width,x) +#define cimg_forY(img,y) cimg_for1((img)._height,y) +#define cimg_forZ(img,z) cimg_for1((img)._depth,z) +#define cimg_forC(img,c) cimg_for1((img)._spectrum,c) +#define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x) +#define cimg_forXZ(img,x,z) cimg_forZ(img,z) cimg_forX(img,x) +#define cimg_forYZ(img,y,z) cimg_forZ(img,z) cimg_forY(img,y) +#define cimg_forXC(img,x,c) cimg_forC(img,c) cimg_forX(img,x) +#define cimg_forYC(img,y,c) cimg_forC(img,c) cimg_forY(img,y) +#define cimg_forZC(img,z,c) cimg_forC(img,c) cimg_forZ(img,z) +#define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y) +#define cimg_forXYC(img,x,y,c) cimg_forC(img,c) cimg_forXY(img,x,y) +#define cimg_forXZC(img,x,z,c) cimg_forC(img,c) cimg_forXZ(img,x,z) +#define cimg_forYZC(img,y,z,c) cimg_forC(img,c) cimg_forYZ(img,y,z) +#define cimg_forXYZC(img,x,y,z,c) cimg_forC(img,c) cimg_forXYZ(img,x,y,z) + +#define cimg_rof1(bound,i) for (int i = (int)(bound) - 1; i>=0; --i) +#define cimg_rofX(img,x) cimg_rof1((img)._width,x) +#define cimg_rofY(img,y) cimg_rof1((img)._height,y) +#define cimg_rofZ(img,z) cimg_rof1((img)._depth,z) +#define cimg_rofC(img,c) cimg_rof1((img)._spectrum,c) +#define cimg_rofXY(img,x,y) cimg_rofY(img,y) cimg_rofX(img,x) +#define cimg_rofXZ(img,x,z) cimg_rofZ(img,z) cimg_rofX(img,x) +#define cimg_rofYZ(img,y,z) cimg_rofZ(img,z) cimg_rofY(img,y) +#define cimg_rofXC(img,x,c) cimg_rofC(img,c) cimg_rofX(img,x) +#define cimg_rofYC(img,y,c) cimg_rofC(img,c) cimg_rofY(img,y) +#define cimg_rofZC(img,z,c) cimg_rofC(img,c) cimg_rofZ(img,z) +#define cimg_rofXYZ(img,x,y,z) cimg_rofZ(img,z) cimg_rofXY(img,x,y) +#define cimg_rofXYC(img,x,y,c) cimg_rofC(img,c) cimg_rofXY(img,x,y) +#define cimg_rofXZC(img,x,z,c) cimg_rofC(img,c) cimg_rofXZ(img,x,z) +#define cimg_rofYZC(img,y,z,c) cimg_rofC(img,c) cimg_rofYZ(img,y,z) +#define cimg_rofXYZC(img,x,y,z,c) cimg_rofC(img,c) cimg_rofXYZ(img,x,y,z) + +#define cimg_for_in1(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), _max##i = (int)(i1)<(int)(bound)?(int)(i1):(int)(bound) - 1; i<=_max##i; ++i) +#define cimg_for_inX(img,x0,x1,x) cimg_for_in1((img)._width,x0,x1,x) +#define cimg_for_inY(img,y0,y1,y) cimg_for_in1((img)._height,y0,y1,y) +#define cimg_for_inZ(img,z0,z1,z) cimg_for_in1((img)._depth,z0,z1,z) +#define cimg_for_inC(img,c0,c1,c) cimg_for_in1((img)._spectrum,c0,c1,c) +#define cimg_for_inXY(img,x0,y0,x1,y1,x,y) cimg_for_inY(img,y0,y1,y) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXZ(img,x0,z0,x1,z1,x,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXC(img,x0,c0,x1,c1,x,c) cimg_for_inC(img,c0,c1,c) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inYZ(img,y0,z0,y1,z1,y,z) cimg_for_inZ(img,x0,z1,z) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inYC(img,y0,c0,y1,c1,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inZC(img,z0,c0,z1,c1,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inZ(img,z0,z1,z) +#define cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXZ(img,x0,z0,x1,z1,x,z) +#define cimg_for_inYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inYZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_inXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_inC(img,c0,c1,c) cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_insideX(img,x,n) cimg_for_inX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_insideY(img,y,n) cimg_for_inY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_insideZ(img,z,n) cimg_for_inZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_insideC(img,c,n) cimg_for_inC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_insideXY(img,x,y,n) cimg_for_inXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_insideXYZ(img,x,y,z,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_insideXYZC(img,x,y,z,c,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) + +#define cimg_for_out1(boundi,i0,i1,i) \ + for (int i = (int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); ++i, i = i==(int)(i0)?(int)(i1) + 1:i) +#define cimg_for_out2(boundi,boundj,i0,j0,i1,j1,i,j) \ + for (int j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out3(boundi,boundj,boundk,i0,j0,k0,i1,j1,k1,i,j,k) \ + for (int k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j || _n1k?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out4(boundi,boundj,boundk,boundl,i0,j0,k0,l0,i1,j1,k1,l1,i,j,k,l) \ + for (int l = 0; l<(int)(boundl); ++l) \ + for (int _n1l = (int)(l<(int)(l0) || l>(int)(l1)), k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k || _n1l?0:(int)(i0)>0?0:(int)(i1) + 1; \ + i<(int)(boundi); ++i, i = _n1j || _n1k || _n1l?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_outX(img,x0,x1,x) cimg_for_out1((img)._width,x0,x1,x) +#define cimg_for_outY(img,y0,y1,y) cimg_for_out1((img)._height,y0,y1,y) +#define cimg_for_outZ(img,z0,z1,z) cimg_for_out1((img)._depth,z0,z1,z) +#define cimg_for_outC(img,c0,c1,c) cimg_for_out1((img)._spectrum,c0,c1,c) +#define cimg_for_outXY(img,x0,y0,x1,y1,x,y) cimg_for_out2((img)._width,(img)._height,x0,y0,x1,y1,x,y) +#define cimg_for_outXZ(img,x0,z0,x1,z1,x,z) cimg_for_out2((img)._width,(img)._depth,x0,z0,x1,z1,x,z) +#define cimg_for_outXC(img,x0,c0,x1,c1,x,c) cimg_for_out2((img)._width,(img)._spectrum,x0,c0,x1,c1,x,c) +#define cimg_for_outYZ(img,y0,z0,y1,z1,y,z) cimg_for_out2((img)._height,(img)._depth,y0,z0,y1,z1,y,z) +#define cimg_for_outYC(img,y0,c0,y1,c1,y,c) cimg_for_out2((img)._height,(img)._spectrum,y0,c0,y1,c1,y,c) +#define cimg_for_outZC(img,z0,c0,z1,c1,z,c) cimg_for_out2((img)._depth,(img)._spectrum,z0,c0,z1,c1,z,c) +#define cimg_for_outXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) \ + cimg_for_out3((img)._width,(img)._height,(img)._depth,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_outXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) \ + cimg_for_out3((img)._width,(img)._height,(img)._spectrum,x0,y0,c0,x1,y1,c1,x,y,c) +#define cimg_for_outXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) \ + cimg_for_out3((img)._width,(img)._depth,(img)._spectrum,x0,z0,c0,x1,z1,c1,x,z,c) +#define cimg_for_outYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) \ + cimg_for_out3((img)._height,(img)._depth,(img)._spectrum,y0,z0,c0,y1,z1,c1,y,z,c) +#define cimg_for_outXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_out4((img)._width,(img)._height,(img)._depth,(img)._spectrum,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) +#define cimg_for_borderX(img,x,n) cimg_for_outX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_borderY(img,y,n) cimg_for_outY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_borderZ(img,z,n) cimg_for_outZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_borderC(img,c,n) cimg_for_outC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_borderXY(img,x,y,n) cimg_for_outXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_borderXYZ(img,x,y,z,n) \ + cimg_for_outXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_borderXYZC(img,x,y,z,c,n) \ + cimg_for_outXYZC(img,n,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n), \ + (img)._depth - 1 - (n),(img)._spectrum - 1 - (n),x,y,z,c) + +#define cimg_for_spiralXY(img,x,y) \ + for (int x = 0, y = 0, _n1##x = 1, _n1##y = (img).width()*(img).height(); _n1##y; \ + --_n1##y, _n1##x+=(_n1##x>>2) - ((!(_n1##x&3)?--y:((_n1##x&3)==1?(img)._width - 1 - ++x:\ + ((_n1##x&3)==2?(img)._height - 1 - ++y:--x))))?0:1) + +#define cimg_for_lineXY(x,y,x0,y0,x1,y1) \ + for (int x = (int)(x0), y = (int)(y0), _sx = 1, _sy = 1, _steep = 0, \ + _dx=(x1)>(x0)?(int)(x1) - (int)(x0):(_sx=-1,(int)(x0) - (int)(x1)), \ + _dy=(y1)>(y0)?(int)(y1) - (int)(y0):(_sy=-1,(int)(y0) - (int)(y1)), \ + _counter = _dx, \ + _err = _dx>_dy?(_dy>>1):((_steep=1),(_counter=_dy),(_dx>>1)); \ + _counter>=0; \ + --_counter, x+=_steep? \ + (y+=_sy,(_err-=_dx)<0?_err+=_dy,_sx:0): \ + (y+=(_err-=_dy)<0?_err+=_dx,_sy:0,_sx)) + +#define cimg_for2(bound,i) \ + for (int i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + ++i, ++_n1##i) +#define cimg_for2X(img,x) cimg_for2((img)._width,x) +#define cimg_for2Y(img,y) cimg_for2((img)._height,y) +#define cimg_for2Z(img,z) cimg_for2((img)._depth,z) +#define cimg_for2C(img,c) cimg_for2((img)._spectrum,c) +#define cimg_for2XY(img,x,y) cimg_for2Y(img,y) cimg_for2X(img,x) +#define cimg_for2XZ(img,x,z) cimg_for2Z(img,z) cimg_for2X(img,x) +#define cimg_for2XC(img,x,c) cimg_for2C(img,c) cimg_for2X(img,x) +#define cimg_for2YZ(img,y,z) cimg_for2Z(img,z) cimg_for2Y(img,y) +#define cimg_for2YC(img,y,c) cimg_for2C(img,c) cimg_for2Y(img,y) +#define cimg_for2ZC(img,z,c) cimg_for2C(img,c) cimg_for2Z(img,z) +#define cimg_for2XYZ(img,x,y,z) cimg_for2Z(img,z) cimg_for2XY(img,x,y) +#define cimg_for2XZC(img,x,z,c) cimg_for2C(img,c) cimg_for2XZ(img,x,z) +#define cimg_for2YZC(img,y,z,c) cimg_for2C(img,c) cimg_for2YZ(img,y,z) +#define cimg_for2XYZC(img,x,y,z,c) cimg_for2C(img,c) cimg_for2XYZ(img,x,y,z) + +#define cimg_for_in2(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + ++i, ++_n1##i) +#define cimg_for_in2X(img,x0,x1,x) cimg_for_in2((img)._width,x0,x1,x) +#define cimg_for_in2Y(img,y0,y1,y) cimg_for_in2((img)._height,y0,y1,y) +#define cimg_for_in2Z(img,z0,z1,z) cimg_for_in2((img)._depth,z0,z1,z) +#define cimg_for_in2C(img,c0,c1,c) cimg_for_in2((img)._spectrum,c0,c1,c) +#define cimg_for_in2XY(img,x0,y0,x1,y1,x,y) cimg_for_in2Y(img,y0,y1,y) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XZ(img,x0,z0,x1,z1,x,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XC(img,x0,c0,x1,c1,x,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2YC(img,y0,c0,y1,c1,y,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2ZC(img,z0,c0,z1,c1,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Z(img,z0,z1,z) +#define cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in2XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in2YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in2XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in2C(img,c0,c1,c) cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i) +#define cimg_for3X(img,x) cimg_for3((img)._width,x) +#define cimg_for3Y(img,y) cimg_for3((img)._height,y) +#define cimg_for3Z(img,z) cimg_for3((img)._depth,z) +#define cimg_for3C(img,c) cimg_for3((img)._spectrum,c) +#define cimg_for3XY(img,x,y) cimg_for3Y(img,y) cimg_for3X(img,x) +#define cimg_for3XZ(img,x,z) cimg_for3Z(img,z) cimg_for3X(img,x) +#define cimg_for3XC(img,x,c) cimg_for3C(img,c) cimg_for3X(img,x) +#define cimg_for3YZ(img,y,z) cimg_for3Z(img,z) cimg_for3Y(img,y) +#define cimg_for3YC(img,y,c) cimg_for3C(img,c) cimg_for3Y(img,y) +#define cimg_for3ZC(img,z,c) cimg_for3C(img,c) cimg_for3Z(img,z) +#define cimg_for3XYZ(img,x,y,z) cimg_for3Z(img,z) cimg_for3XY(img,x,y) +#define cimg_for3XZC(img,x,z,c) cimg_for3C(img,c) cimg_for3XZ(img,x,z) +#define cimg_for3YZC(img,y,z,c) cimg_for3C(img,c) cimg_for3YZ(img,y,z) +#define cimg_for3XYZC(img,x,y,z,c) cimg_for3C(img,c) cimg_for3XYZ(img,x,y,z) + +#define cimg_for_in3(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + _p1##i = i++, ++_n1##i) +#define cimg_for_in3X(img,x0,x1,x) cimg_for_in3((img)._width,x0,x1,x) +#define cimg_for_in3Y(img,y0,y1,y) cimg_for_in3((img)._height,y0,y1,y) +#define cimg_for_in3Z(img,z0,z1,z) cimg_for_in3((img)._depth,z0,z1,z) +#define cimg_for_in3C(img,c0,c1,c) cimg_for_in3((img)._spectrum,c0,c1,c) +#define cimg_for_in3XY(img,x0,y0,x1,y1,x,y) cimg_for_in3Y(img,y0,y1,y) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XZ(img,x0,z0,x1,z1,x,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XC(img,x0,c0,x1,c1,x,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3YC(img,y0,c0,y1,c1,y,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3ZC(img,z0,c0,z1,c1,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Z(img,z0,z1,z) +#define cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in3XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in3YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in3XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in3C(img,c0,c1,c) cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for4(bound,i) \ + for (int i = 0, _p1##i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for4X(img,x) cimg_for4((img)._width,x) +#define cimg_for4Y(img,y) cimg_for4((img)._height,y) +#define cimg_for4Z(img,z) cimg_for4((img)._depth,z) +#define cimg_for4C(img,c) cimg_for4((img)._spectrum,c) +#define cimg_for4XY(img,x,y) cimg_for4Y(img,y) cimg_for4X(img,x) +#define cimg_for4XZ(img,x,z) cimg_for4Z(img,z) cimg_for4X(img,x) +#define cimg_for4XC(img,x,c) cimg_for4C(img,c) cimg_for4X(img,x) +#define cimg_for4YZ(img,y,z) cimg_for4Z(img,z) cimg_for4Y(img,y) +#define cimg_for4YC(img,y,c) cimg_for4C(img,c) cimg_for4Y(img,y) +#define cimg_for4ZC(img,z,c) cimg_for4C(img,c) cimg_for4Z(img,z) +#define cimg_for4XYZ(img,x,y,z) cimg_for4Z(img,z) cimg_for4XY(img,x,y) +#define cimg_for4XZC(img,x,z,c) cimg_for4C(img,c) cimg_for4XZ(img,x,z) +#define cimg_for4YZC(img,y,z,c) cimg_for4C(img,c) cimg_for4YZ(img,y,z) +#define cimg_for4XYZC(img,x,y,z,c) cimg_for4C(img,c) cimg_for4XYZ(img,x,y,z) + +#define cimg_for_in4(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in4X(img,x0,x1,x) cimg_for_in4((img)._width,x0,x1,x) +#define cimg_for_in4Y(img,y0,y1,y) cimg_for_in4((img)._height,y0,y1,y) +#define cimg_for_in4Z(img,z0,z1,z) cimg_for_in4((img)._depth,z0,z1,z) +#define cimg_for_in4C(img,c0,c1,c) cimg_for_in4((img)._spectrum,c0,c1,c) +#define cimg_for_in4XY(img,x0,y0,x1,y1,x,y) cimg_for_in4Y(img,y0,y1,y) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XZ(img,x0,z0,x1,z1,x,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XC(img,x0,c0,x1,c1,x,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4YC(img,y0,c0,y1,c1,y,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4ZC(img,z0,c0,z1,c1,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Z(img,z0,z1,z) +#define cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in4XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in4YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in4XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in4C(img,c0,c1,c) cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for5(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for5X(img,x) cimg_for5((img)._width,x) +#define cimg_for5Y(img,y) cimg_for5((img)._height,y) +#define cimg_for5Z(img,z) cimg_for5((img)._depth,z) +#define cimg_for5C(img,c) cimg_for5((img)._spectrum,c) +#define cimg_for5XY(img,x,y) cimg_for5Y(img,y) cimg_for5X(img,x) +#define cimg_for5XZ(img,x,z) cimg_for5Z(img,z) cimg_for5X(img,x) +#define cimg_for5XC(img,x,c) cimg_for5C(img,c) cimg_for5X(img,x) +#define cimg_for5YZ(img,y,z) cimg_for5Z(img,z) cimg_for5Y(img,y) +#define cimg_for5YC(img,y,c) cimg_for5C(img,c) cimg_for5Y(img,y) +#define cimg_for5ZC(img,z,c) cimg_for5C(img,c) cimg_for5Z(img,z) +#define cimg_for5XYZ(img,x,y,z) cimg_for5Z(img,z) cimg_for5XY(img,x,y) +#define cimg_for5XZC(img,x,z,c) cimg_for5C(img,c) cimg_for5XZ(img,x,z) +#define cimg_for5YZC(img,y,z,c) cimg_for5C(img,c) cimg_for5YZ(img,y,z) +#define cimg_for5XYZC(img,x,y,z,c) cimg_for5C(img,c) cimg_for5XYZ(img,x,y,z) + +#define cimg_for_in5(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in5X(img,x0,x1,x) cimg_for_in5((img)._width,x0,x1,x) +#define cimg_for_in5Y(img,y0,y1,y) cimg_for_in5((img)._height,y0,y1,y) +#define cimg_for_in5Z(img,z0,z1,z) cimg_for_in5((img)._depth,z0,z1,z) +#define cimg_for_in5C(img,c0,c1,c) cimg_for_in5((img)._spectrum,c0,c1,c) +#define cimg_for_in5XY(img,x0,y0,x1,y1,x,y) cimg_for_in5Y(img,y0,y1,y) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XZ(img,x0,z0,x1,z1,x,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XC(img,x0,c0,x1,c1,x,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5YC(img,y0,c0,y1,c1,y,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5ZC(img,z0,c0,z1,c1,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Z(img,z0,z1,z) +#define cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in5XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in5YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in5XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in5C(img,c0,c1,c) cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for6(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for6X(img,x) cimg_for6((img)._width,x) +#define cimg_for6Y(img,y) cimg_for6((img)._height,y) +#define cimg_for6Z(img,z) cimg_for6((img)._depth,z) +#define cimg_for6C(img,c) cimg_for6((img)._spectrum,c) +#define cimg_for6XY(img,x,y) cimg_for6Y(img,y) cimg_for6X(img,x) +#define cimg_for6XZ(img,x,z) cimg_for6Z(img,z) cimg_for6X(img,x) +#define cimg_for6XC(img,x,c) cimg_for6C(img,c) cimg_for6X(img,x) +#define cimg_for6YZ(img,y,z) cimg_for6Z(img,z) cimg_for6Y(img,y) +#define cimg_for6YC(img,y,c) cimg_for6C(img,c) cimg_for6Y(img,y) +#define cimg_for6ZC(img,z,c) cimg_for6C(img,c) cimg_for6Z(img,z) +#define cimg_for6XYZ(img,x,y,z) cimg_for6Z(img,z) cimg_for6XY(img,x,y) +#define cimg_for6XZC(img,x,z,c) cimg_for6C(img,c) cimg_for6XZ(img,x,z) +#define cimg_for6YZC(img,y,z,c) cimg_for6C(img,c) cimg_for6YZ(img,y,z) +#define cimg_for6XYZC(img,x,y,z,c) cimg_for6C(img,c) cimg_for6XYZ(img,x,y,z) + +#define cimg_for_in6(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in6X(img,x0,x1,x) cimg_for_in6((img)._width,x0,x1,x) +#define cimg_for_in6Y(img,y0,y1,y) cimg_for_in6((img)._height,y0,y1,y) +#define cimg_for_in6Z(img,z0,z1,z) cimg_for_in6((img)._depth,z0,z1,z) +#define cimg_for_in6C(img,c0,c1,c) cimg_for_in6((img)._spectrum,c0,c1,c) +#define cimg_for_in6XY(img,x0,y0,x1,y1,x,y) cimg_for_in6Y(img,y0,y1,y) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XZ(img,x0,z0,x1,z1,x,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XC(img,x0,c0,x1,c1,x,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6YC(img,y0,c0,y1,c1,y,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6ZC(img,z0,c0,z1,c1,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Z(img,z0,z1,z) +#define cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in6XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in6YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in6XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in6C(img,c0,c1,c) cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for7(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for7X(img,x) cimg_for7((img)._width,x) +#define cimg_for7Y(img,y) cimg_for7((img)._height,y) +#define cimg_for7Z(img,z) cimg_for7((img)._depth,z) +#define cimg_for7C(img,c) cimg_for7((img)._spectrum,c) +#define cimg_for7XY(img,x,y) cimg_for7Y(img,y) cimg_for7X(img,x) +#define cimg_for7XZ(img,x,z) cimg_for7Z(img,z) cimg_for7X(img,x) +#define cimg_for7XC(img,x,c) cimg_for7C(img,c) cimg_for7X(img,x) +#define cimg_for7YZ(img,y,z) cimg_for7Z(img,z) cimg_for7Y(img,y) +#define cimg_for7YC(img,y,c) cimg_for7C(img,c) cimg_for7Y(img,y) +#define cimg_for7ZC(img,z,c) cimg_for7C(img,c) cimg_for7Z(img,z) +#define cimg_for7XYZ(img,x,y,z) cimg_for7Z(img,z) cimg_for7XY(img,x,y) +#define cimg_for7XZC(img,x,z,c) cimg_for7C(img,c) cimg_for7XZ(img,x,z) +#define cimg_for7YZC(img,y,z,c) cimg_for7C(img,c) cimg_for7YZ(img,y,z) +#define cimg_for7XYZC(img,x,y,z,c) cimg_for7C(img,c) cimg_for7XYZ(img,x,y,z) + +#define cimg_for_in7(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in7X(img,x0,x1,x) cimg_for_in7((img)._width,x0,x1,x) +#define cimg_for_in7Y(img,y0,y1,y) cimg_for_in7((img)._height,y0,y1,y) +#define cimg_for_in7Z(img,z0,z1,z) cimg_for_in7((img)._depth,z0,z1,z) +#define cimg_for_in7C(img,c0,c1,c) cimg_for_in7((img)._spectrum,c0,c1,c) +#define cimg_for_in7XY(img,x0,y0,x1,y1,x,y) cimg_for_in7Y(img,y0,y1,y) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XZ(img,x0,z0,x1,z1,x,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XC(img,x0,c0,x1,c1,x,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7YC(img,y0,c0,y1,c1,y,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7ZC(img,z0,c0,z1,c1,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Z(img,z0,z1,z) +#define cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in7XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in7YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in7XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in7C(img,c0,c1,c) cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for8(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for8X(img,x) cimg_for8((img)._width,x) +#define cimg_for8Y(img,y) cimg_for8((img)._height,y) +#define cimg_for8Z(img,z) cimg_for8((img)._depth,z) +#define cimg_for8C(img,c) cimg_for8((img)._spectrum,c) +#define cimg_for8XY(img,x,y) cimg_for8Y(img,y) cimg_for8X(img,x) +#define cimg_for8XZ(img,x,z) cimg_for8Z(img,z) cimg_for8X(img,x) +#define cimg_for8XC(img,x,c) cimg_for8C(img,c) cimg_for8X(img,x) +#define cimg_for8YZ(img,y,z) cimg_for8Z(img,z) cimg_for8Y(img,y) +#define cimg_for8YC(img,y,c) cimg_for8C(img,c) cimg_for8Y(img,y) +#define cimg_for8ZC(img,z,c) cimg_for8C(img,c) cimg_for8Z(img,z) +#define cimg_for8XYZ(img,x,y,z) cimg_for8Z(img,z) cimg_for8XY(img,x,y) +#define cimg_for8XZC(img,x,z,c) cimg_for8C(img,c) cimg_for8XZ(img,x,z) +#define cimg_for8YZC(img,y,z,c) cimg_for8C(img,c) cimg_for8YZ(img,y,z) +#define cimg_for8XYZC(img,x,y,z,c) cimg_for8C(img,c) cimg_for8XYZ(img,x,y,z) + +#define cimg_for_in8(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in8X(img,x0,x1,x) cimg_for_in8((img)._width,x0,x1,x) +#define cimg_for_in8Y(img,y0,y1,y) cimg_for_in8((img)._height,y0,y1,y) +#define cimg_for_in8Z(img,z0,z1,z) cimg_for_in8((img)._depth,z0,z1,z) +#define cimg_for_in8C(img,c0,c1,c) cimg_for_in8((img)._spectrum,c0,c1,c) +#define cimg_for_in8XY(img,x0,y0,x1,y1,x,y) cimg_for_in8Y(img,y0,y1,y) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XZ(img,x0,z0,x1,z1,x,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XC(img,x0,c0,x1,c1,x,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8YC(img,y0,c0,y1,c1,y,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8ZC(img,z0,c0,z1,c1,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Z(img,z0,z1,z) +#define cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in8XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in8YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in8XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in8C(img,c0,c1,c) cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for9(bound,i) \ + for (int i = 0, _p4##i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(int)(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(int)(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(int)(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(int)(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for9X(img,x) cimg_for9((img)._width,x) +#define cimg_for9Y(img,y) cimg_for9((img)._height,y) +#define cimg_for9Z(img,z) cimg_for9((img)._depth,z) +#define cimg_for9C(img,c) cimg_for9((img)._spectrum,c) +#define cimg_for9XY(img,x,y) cimg_for9Y(img,y) cimg_for9X(img,x) +#define cimg_for9XZ(img,x,z) cimg_for9Z(img,z) cimg_for9X(img,x) +#define cimg_for9XC(img,x,c) cimg_for9C(img,c) cimg_for9X(img,x) +#define cimg_for9YZ(img,y,z) cimg_for9Z(img,z) cimg_for9Y(img,y) +#define cimg_for9YC(img,y,c) cimg_for9C(img,c) cimg_for9Y(img,y) +#define cimg_for9ZC(img,z,c) cimg_for9C(img,c) cimg_for9Z(img,z) +#define cimg_for9XYZ(img,x,y,z) cimg_for9Z(img,z) cimg_for9XY(img,x,y) +#define cimg_for9XZC(img,x,z,c) cimg_for9C(img,c) cimg_for9XZ(img,x,z) +#define cimg_for9YZC(img,y,z,c) cimg_for9C(img,c) cimg_for9YZ(img,y,z) +#define cimg_for9XYZC(img,x,y,z,c) cimg_for9C(img,c) cimg_for9XYZ(img,x,y,z) + +#define cimg_for_in9(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p4##i = i - 4<0?0:i - 4, \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in9X(img,x0,x1,x) cimg_for_in9((img)._width,x0,x1,x) +#define cimg_for_in9Y(img,y0,y1,y) cimg_for_in9((img)._height,y0,y1,y) +#define cimg_for_in9Z(img,z0,z1,z) cimg_for_in9((img)._depth,z0,z1,z) +#define cimg_for_in9C(img,c0,c1,c) cimg_for_in9((img)._spectrum,c0,c1,c) +#define cimg_for_in9XY(img,x0,y0,x1,y1,x,y) cimg_for_in9Y(img,y0,y1,y) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XZ(img,x0,z0,x1,z1,x,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XC(img,x0,c0,x1,c1,x,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9YC(img,y0,c0,y1,c1,y,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9ZC(img,z0,c0,z1,c1,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Z(img,z0,z1,z) +#define cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in9XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in9YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in9XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in9C(img,c0,c1,c) cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[4] = (T)(img)(x,y,z,c)), \ + (I[7] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for4x4(img,x,y,z,c,I,T) \ + cimg_for4((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = I[5] = (T)(img)(0,y,z,c)), \ + (I[8] = I[9] = (T)(img)(0,_n1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in4x4(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in4((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = (T)(img)(_p1##x,y,z,c)), \ + (I[8] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[5] = (T)(img)(x,y,z,c)), \ + (I[9] = (T)(img)(x,_n1##y,z,c)), \ + (I[13] = (T)(img)(x,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for5x5(img,x,y,z,c,I,T) \ + cimg_for5((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = I[6] = I[7] = (T)(img)(0,_p1##y,z,c)), \ + (I[10] = I[11] = I[12] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = I[17] = (T)(img)(0,_n1##y,z,c)), \ + (I[20] = I[21] = I[22] = (T)(img)(0,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in5x5(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in5((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[10] = (T)(img)(_p2##x,y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[11] = (T)(img)(_p1##x,y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[7] = (T)(img)(x,_p1##y,z,c)), \ + (I[12] = (T)(img)(x,y,z,c)), \ + (I[17] = (T)(img)(x,_n1##y,z,c)), \ + (I[22] = (T)(img)(x,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for6x6(img,x,y,z,c,I,T) \ + cimg_for6((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = I[7] = I[8] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = I[14] = (T)(img)(0,y,z,c)), \ + (I[18] = I[19] = I[20] = (T)(img)(0,_n1##y,z,c)), \ + (I[24] = I[25] = I[26] = (T)(img)(0,_n2##y,z,c)), \ + (I[30] = I[31] = I[32] = (T)(img)(0,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in6x6(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in6((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)x0, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p2##x,y,z,c)), \ + (I[18] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[30] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[7] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_p1##x,y,z,c)), \ + (I[19] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[25] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[31] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[8] = (T)(img)(x,_p1##y,z,c)), \ + (I[14] = (T)(img)(x,y,z,c)), \ + (I[20] = (T)(img)(x,_n1##y,z,c)), \ + (I[26] = (T)(img)(x,_n2##y,z,c)), \ + (I[32] = (T)(img)(x,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for7x7(img,x,y,z,c,I,T) \ + cimg_for7((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = I[8] = I[9] = I[10] = (T)(img)(0,_p2##y,z,c)), \ + (I[14] = I[15] = I[16] = I[17] = (T)(img)(0,_p1##y,z,c)), \ + (I[21] = I[22] = I[23] = I[24] = (T)(img)(0,y,z,c)), \ + (I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_n1##y,z,c)), \ + (I[35] = I[36] = I[37] = I[38] = (T)(img)(0,_n2##y,z,c)), \ + (I[42] = I[43] = I[44] = I[45] = (T)(img)(0,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in7x7(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in7((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[14] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[21] = (T)(img)(_p3##x,y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[35] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[42] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[22] = (T)(img)(_p2##x,y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[36] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[43] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[23] = (T)(img)(_p1##x,y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[37] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[44] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[10] = (T)(img)(x,_p2##y,z,c)), \ + (I[17] = (T)(img)(x,_p1##y,z,c)), \ + (I[24] = (T)(img)(x,y,z,c)), \ + (I[31] = (T)(img)(x,_n1##y,z,c)), \ + (I[38] = (T)(img)(x,_n2##y,z,c)), \ + (I[45] = (T)(img)(x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for8x8(img,x,y,z,c,I,T) \ + cimg_for8((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = I[9] = I[10] = I[11] = (T)(img)(0,_p2##y,z,c)), \ + (I[16] = I[17] = I[18] = I[19] = (T)(img)(0,_p1##y,z,c)), \ + (I[24] = I[25] = I[26] = I[27] = (T)(img)(0,y,z,c)), \ + (I[32] = I[33] = I[34] = I[35] = (T)(img)(0,_n1##y,z,c)), \ + (I[40] = I[41] = I[42] = I[43] = (T)(img)(0,_n2##y,z,c)), \ + (I[48] = I[49] = I[50] = I[51] = (T)(img)(0,_n3##y,z,c)), \ + (I[56] = I[57] = I[58] = I[59] = (T)(img)(0,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in8x8(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in8((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[24] = (T)(img)(_p3##x,y,z,c)), \ + (I[32] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[56] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[17] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_p2##x,y,z,c)), \ + (I[33] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[49] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[57] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[10] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_p1##x,y,z,c)), \ + (I[34] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[42] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[50] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[58] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[11] = (T)(img)(x,_p2##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,z,c)), \ + (I[27] = (T)(img)(x,y,z,c)), \ + (I[35] = (T)(img)(x,_n1##y,z,c)), \ + (I[43] = (T)(img)(x,_n2##y,z,c)), \ + (I[51] = (T)(img)(x,_n3##y,z,c)), \ + (I[59] = (T)(img)(x,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for9x9(img,x,y,z,c,I,T) \ + cimg_for9((img)._height,y) for (int x = 0, \ + _p4##x = 0, _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = I[4] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = I[10] = I[11] = I[12] = I[13] = (T)(img)(0,_p3##y,z,c)), \ + (I[18] = I[19] = I[20] = I[21] = I[22] = (T)(img)(0,_p2##y,z,c)), \ + (I[27] = I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_p1##y,z,c)), \ + (I[36] = I[37] = I[38] = I[39] = I[40] = (T)(img)(0,y,z,c)), \ + (I[45] = I[46] = I[47] = I[48] = I[49] = (T)(img)(0,_n1##y,z,c)), \ + (I[54] = I[55] = I[56] = I[57] = I[58] = (T)(img)(0,_n2##y,z,c)), \ + (I[63] = I[64] = I[65] = I[66] = I[67] = (T)(img)(0,_n3##y,z,c)), \ + (I[72] = I[73] = I[74] = I[75] = I[76] = (T)(img)(0,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in9x9(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in9((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p4##x = x - 4<0?0:x - 4, \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = (T)(img)(_p4##x,_p3##y,z,c)), \ + (I[18] = (T)(img)(_p4##x,_p2##y,z,c)), \ + (I[27] = (T)(img)(_p4##x,_p1##y,z,c)), \ + (I[36] = (T)(img)(_p4##x,y,z,c)), \ + (I[45] = (T)(img)(_p4##x,_n1##y,z,c)), \ + (I[54] = (T)(img)(_p4##x,_n2##y,z,c)), \ + (I[63] = (T)(img)(_p4##x,_n3##y,z,c)), \ + (I[72] = (T)(img)(_p4##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p3##x,_p4##y,z,c)), \ + (I[10] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[19] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[37] = (T)(img)(_p3##x,y,z,c)), \ + (I[46] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[55] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[64] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[73] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p2##x,_p4##y,z,c)), \ + (I[11] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[38] = (T)(img)(_p2##x,y,z,c)), \ + (I[47] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[56] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[65] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[74] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,_p4##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[39] = (T)(img)(_p1##x,y,z,c)), \ + (I[48] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[57] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[66] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[75] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[4] = (T)(img)(x,_p4##y,z,c)), \ + (I[13] = (T)(img)(x,_p3##y,z,c)), \ + (I[22] = (T)(img)(x,_p2##y,z,c)), \ + (I[31] = (T)(img)(x,_p1##y,z,c)), \ + (I[40] = (T)(img)(x,y,z,c)), \ + (I[49] = (T)(img)(x,_n1##y,z,c)), \ + (I[58] = (T)(img)(x,_n2##y,z,c)), \ + (I[67] = (T)(img)(x,_n3##y,z,c)), \ + (I[76] = (T)(img)(x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for2x2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._depth,z) cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + (I[4] = (T)(img)(0,y,_n1##z,c)), \ + (I[6] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in2((img)._depth,z0,z1,z) cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + (I[4] = (T)(img)(x,y,_n1##z,c)), \ + (I[6] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for3x3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._depth,z) cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,_p1##z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,_p1##z,c)), \ + (I[9] = I[10] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = (T)(img)(0,_n1##y,z,c)), \ + (I[18] = I[19] = (T)(img)(0,_p1##y,_n1##z,c)), \ + (I[21] = I[22] = (T)(img)(0,y,_n1##z,c)), \ + (I[24] = I[25] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in3((img)._depth,z0,z1,z) cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = (T)(img)(_p1##x,y,_p1##z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c)), \ + (I[9] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,y,z,c)), \ + (I[15] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c)), \ + (I[21] = (T)(img)(_p1##x,y,_n1##z,c)), \ + (I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c)), \ + (I[1] = (T)(img)(x,_p1##y,_p1##z,c)), \ + (I[4] = (T)(img)(x,y,_p1##z,c)), \ + (I[7] = (T)(img)(x,_n1##y,_p1##z,c)), \ + (I[10] = (T)(img)(x,_p1##y,z,c)), \ + (I[13] = (T)(img)(x,y,z,c)), \ + (I[16] = (T)(img)(x,_n1##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,_n1##z,c)), \ + (I[22] = (T)(img)(x,y,_n1##z,c)), \ + (I[25] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimglist_for(list,l) for (int l = 0; l<(int)(list)._width; ++l) +#define cimglist_rof(list,l) for (int l = (int)(list)._width - 1; l>=0; --l) +#define cimglist_for_in(list,l0,l1,l) \ + for (int l = (int)(l0)<0?0:(int)(l0), _max##l = (unsigned int)l1<(list)._width?(int)(l1):(int)(list)._width - 1; \ + l<=_max##l; ++l) + +#define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn + +// Macros used to display error messages when exceptions are thrown. +// You should not use these macros is your own code. +#define _cimgdisplay_instance "[instance(%u,%u,%u,%c%s%c)] CImgDisplay::" +#define cimgdisplay_instance _width,_height,_normalization,_title?'\"':'[',_title?_title:"untitled",_title?'\"':']' +#define _cimg_instance "[instance(%u,%u,%u,%u,%p,%sshared)] CImg<%s>::" +#define cimg_instance _width,_height,_depth,_spectrum,_data,_is_shared?"":"non-",pixel_type() +#define _cimglist_instance "[instance(%u,%u,%p)] CImgList<%s>::" +#define cimglist_instance _width,_allocated_width,_data,pixel_type() + +/*------------------------------------------------ + # + # + # Define cimg_library:: namespace + # + # + -------------------------------------------------*/ +//! Contains all classes and functions of the \CImg library. +/** + This namespace is defined to avoid functions and class names collisions + that could happen with the inclusion of other C++ header files. + Anyway, it should not happen often and you should reasonably start most of your + \CImg-based programs with + \code + #include "CImg.h" + using namespace cimg_library; + \endcode + to simplify the declaration of \CImg Library objects afterwards. +**/ +namespace cimg_library_suffixed { + + // Declare the four classes of the CImg Library. + template struct CImg; + template struct CImgList; + struct CImgDisplay; + struct CImgException; + + // Declare cimg:: namespace. + // This is an incomplete namespace definition here. It only contains some + // necessary stuff to ensure a correct declaration order of the classes and functions + // defined afterwards. + namespace cimg { + + // Define character sequences for colored terminal output. +#ifdef cimg_use_vt100 + static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 }; + static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 }; + static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 }; + static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 }; + static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 }; + static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 }; + static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 }; + static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 }; + static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 }; + static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 }; + static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 }; +#else + static const char t_normal[] = { 0 }; + static const char *const t_black = cimg::t_normal, + *const t_red = cimg::t_normal, + *const t_green = cimg::t_normal, + *const t_yellow = cimg::t_normal, + *const t_blue = cimg::t_normal, + *const t_magenta = cimg::t_normal, + *const t_cyan = cimg::t_normal, + *const t_white = cimg::t_normal, + *const t_bold = cimg::t_normal, + *const t_underscore = cimg::t_normal; +#endif + + inline std::FILE* output(std::FILE *file=0); + inline void info(); + + //! Avoid warning messages due to unused parameters. Do nothing actually. + template + inline void unused(const T&, ...) {} + + // [internal] Lock/unlock a mutex for managing concurrent threads. + // 'lock_mode' can be { 0=unlock | 1=lock | 2=trylock }. + // 'n' can be in [0,31] but mutex range [0,15] is reserved by CImg. + inline int mutex(const unsigned int n, const int lock_mode=1); + + inline unsigned int& exception_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = cimg_verbosity; + if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); } + return mode; + } + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + inline FILE* _stdin(const bool throw_exception=true); + inline FILE* _stdout(const bool throw_exception=true); + inline FILE* _stderr(const bool throw_exception=true); + + // Mandatory because Microsoft's _snprintf() and _vsnprintf() do not add the '\0' character + // at the end of the string. +#if cimg_OS==2 && defined(_MSC_VER) + inline int _snprintf(char *const s, const size_t size, const char *const format, ...) { + va_list ap; + va_start(ap,format); + const int result = _vsnprintf(s,size,format,ap); + va_end(ap); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) { + int result = -1; + cimg::mutex(6); + if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap); + if (result==-1) result = _vscprintf(format,ap); + cimg::mutex(6,0); + return result; + } + + // Mutex-protected version of sscanf, sprintf and snprintf. + // Used only MacOSX, as it seems those functions are not re-entrant on MacOSX. +#elif defined(__MACOSX__) || defined(__APPLE__) + inline int _sscanf(const char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsscanf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _sprintf(char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsprintf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _snprintf(char *const s, const size_t n, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsnprintf(s,n,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) { + cimg::mutex(6); + const int result = std::vsnprintf(s,size,format,ap); + cimg::mutex(6,0); + return result; + } +#endif + + //! Set current \CImg exception mode. + /** + The way error messages are handled by \CImg can be changed dynamically, using this function. + \param mode Desired exception mode. Possible values are: + - \c 0: Hide library messages (quiet mode). + - \c 1: Print library messages on the console. + - \c 2: Display library messages on a dialog window. + - \c 3: Do as \c 1 + add extra debug warnings (slow down the code!). + - \c 4: Do as \c 2 + add extra debug warnings (slow down the code!). + **/ + inline unsigned int& exception_mode(const unsigned int mode) { + return exception_mode(mode,true); + } + + //! Return current \CImg exception mode. + /** + \note By default, return the value of configuration macro \c cimg_verbosity + **/ + inline unsigned int& exception_mode() { + return exception_mode(0,false); + } + + inline unsigned int openmp_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = 2; + if (is_set) { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); } + return mode; + } + + //! Set current \CImg openmp mode. + /** + The way openmp-based methods are handled by \CImg can be changed dynamically, using this function. + \param mode Desired openmp mode. Possible values are: + - \c 0: Never parallelize. + - \c 1: Always parallelize. + - \c 2: Adaptive parallelization mode (default behavior). + **/ + inline unsigned int openmp_mode(const unsigned int mode) { + return openmp_mode(mode,true); + } + + //! Return current \CImg openmp mode. + inline unsigned int openmp_mode() { + return openmp_mode(0,false); + } + +#ifndef cimg_openmp_sizefactor +#define cimg_openmp_sizefactor 1 +#endif +#define cimg_openmp_if(cond) if ((cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond)))) +#define cimg_openmp_if_size(size,min_size) cimg_openmp_if((size)>=(cimg_openmp_sizefactor)*(min_size)) +#ifdef _MSC_VER +// Disable 'collapse()' directive for MSVC (supports only OpenMP 2.0). +#define cimg_openmp_collapse(k) +#else +#define cimg_openmp_collapse(k) collapse(k) +#endif + +#if cimg_OS==2 +// Disable parallelization of simple loops on Windows, due to noticed performance drop. +#define cimg_openmp_for(instance,expr,min_size) cimg_rof((instance),ptr,T) *ptr = (T)(expr); +#else +#define cimg_openmp_for(instance,expr,min_size) \ + cimg_pragma_openmp(parallel for cimg_openmp_if_size((instance).size(),min_size)) \ + cimg_rof((instance),ptr,T) *ptr = (T)(expr); +#endif + + // Display a simple dialog box, and wait for the user's response. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label="OK", const char *const button2_label=0, + const char *const button3_label=0, const char *const button4_label=0, + const char *const button5_label=0, const char *const button6_label=0, + const bool centering=false); + + // Evaluate math expression. + inline double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0); + + } // namespace cimg { ... + + /*--------------------------------------- + # + # Define the CImgException structures + # + --------------------------------------*/ + //! Instances of \c CImgException are thrown when errors are encountered in a \CImg function call. + /** + \par Overview + + CImgException is the base class of all exceptions thrown by \CImg (except \b CImgAbortException). + CImgException is never thrown itself. Derived classes that specify the type of errord are thrown instead. + These classes can be: + + - \b CImgAbortException: Thrown when a computationally-intensive function is aborted by an external signal. + This is the only \c non-derived exception class. + + - \b CImgArgumentException: Thrown when one argument of a called \CImg function is invalid. + This is probably one of the most thrown exception by \CImg. + For instance, the following example throws a \c CImgArgumentException: + \code + CImg img(100,100,1,3); // Define a 100x100 color image with float-valued pixels + img.mirror('e'); // Try to mirror image along the (non-existing) 'e'-axis + \endcode + + - \b CImgDisplayException: Thrown when something went wrong during the display of images in CImgDisplay instances. + + - \b CImgInstanceException: Thrown when an instance associated to a called \CImg method does not fit + the function requirements. For instance, the following example throws a \c CImgInstanceException: + \code + const CImg img; // Define an empty image + const float value = img.at(0); // Try to read first pixel value (does not exist) + \endcode + + - \b CImgIOException: Thrown when an error occurred when trying to load or save image files. + This happens when trying to read files that do not exist or with invalid formats. + For instance, the following example throws a \c CImgIOException: + \code + const CImg img("missing_file.jpg"); // Try to load a file that does not exist + \endcode + + - \b CImgWarningException: Thrown only if configuration macro \c cimg_strict_warnings is set, and + when a \CImg function has to display a warning message (see cimg::warn()). + + It is not recommended to throw CImgException instances by yourself, + since they are expected to be thrown only by \CImg. + When an error occurs in a library function call, \CImg may display error messages on the screen or on the + standard output, depending on the current \CImg exception mode. + The \CImg exception mode can be get and set by functions cimg::exception_mode() and + cimg::exception_mode(unsigned int). + + \par Exceptions handling + + In all cases, when an error occurs in \CImg, an instance of the corresponding exception class is thrown. + This may lead the program to break (this is the default behavior), but you can bypass this behavior by + handling the exceptions by yourself, + using a usual try { ... } catch () { ... } bloc, as in the following example: + \code + #define "CImg.h" + using namespace cimg_library; + int main() { + cimg::exception_mode(0); // Enable quiet exception mode + try { + ... // Here, do what you want to stress CImg + } catch (CImgException& e) { // You succeeded: something went wrong! + std::fprintf(stderr,"CImg Library Error: %s",e.what()); // Display your custom error message + ... // Do what you want now to save the ship! + } + } + \endcode + **/ + struct CImgException : public std::exception { +#define _cimg_exception_err(etype,disp_flag) \ + std::va_list ap, ap2; \ + va_start(ap,format); va_start(ap2,format); \ + int size = cimg_vsnprintf(0,0,format,ap2); \ + if (size++>=0) { \ + delete[] _message; \ + _message = new char[(size_t)size]; \ + cimg_vsnprintf(_message,(size_t)size,format,ap); \ + if (cimg::exception_mode()) { \ + std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \ + if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \ + catch (CImgException&) {} \ + if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \ + } \ + } \ + va_end(ap); va_end(ap2); + + char *_message; + CImgException() { _message = new char[1]; *_message = 0; } + CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); } + CImgException(const CImgException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgException() throw() { delete[] _message; } + CImgException& operator=(const CImgException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; // struct CImgException { ... + + // The CImgAbortException class is used to throw an exception when + // a computationally-intensive function has been aborted by an external signal. + struct CImgAbortException : public std::exception { + char *_message; + CImgAbortException() { _message = new char[1]; *_message = 0; } + CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); } + CImgAbortException(const CImgAbortException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgAbortException() throw() { delete[] _message; } + CImgAbortException& operator=(const CImgAbortException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; // struct CImgAbortException { ... + + // The CImgArgumentException class is used to throw an exception related + // to invalid arguments encountered in a library function call. + struct CImgArgumentException : public CImgException { + CImgArgumentException(const char *const format, ...) { _cimg_exception_err("CImgArgumentException",true); } + }; // struct CImgArgumentException { ... + + // The CImgDisplayException class is used to throw an exception related + // to display problems encountered in a library function call. + struct CImgDisplayException : public CImgException { + CImgDisplayException(const char *const format, ...) { _cimg_exception_err("CImgDisplayException",false); } + }; // struct CImgDisplayException { ... + + // The CImgInstanceException class is used to throw an exception related + // to an invalid instance encountered in a library function call. + struct CImgInstanceException : public CImgException { + CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); } + }; // struct CImgInstanceException { ... + + // The CImgIOException class is used to throw an exception related + // to input/output file problems encountered in a library function call. + struct CImgIOException : public CImgException { + CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); } + }; // struct CImgIOException { ... + + // The CImgWarningException class is used to throw an exception for warnings + // encountered in a library function call. + struct CImgWarningException : public CImgException { + CImgWarningException(const char *const format, ...) { _cimg_exception_err("CImgWarningException",false); } + }; // struct CImgWarningException { ... + + /*------------------------------------- + # + # Define cimg:: namespace + # + -----------------------------------*/ + //! Contains \a low-level functions and variables of the \CImg Library. + /** + Most of the functions and variables within this namespace are used by the \CImg library for low-level operations. + You may use them to access specific const values or environment variables internally used by \CImg. + \warning Never write using namespace cimg_library::cimg; in your source code. Lot of functions in the + cimg:: namespace have the same names as standard C functions that may be defined in the global + namespace ::. + **/ + namespace cimg { + + // Define traits that will be used to determine the best data type to work in CImg functions. + // + template struct type { + static const char* string() { + static const char* s[] = { "unknown", "unknown8", "unknown16", "unknown24", + "unknown32", "unknown40", "unknown48", "unknown56", + "unknown64", "unknown72", "unknown80", "unknown88", + "unknown96", "unknown104", "unknown112", "unknown120", + "unknown128" }; + return s[(sizeof(T)<17)?sizeof(T):0]; + } + static bool is_float() { return false; } + static bool is_inf(const T) { return false; } + static bool is_nan(const T) { return false; } + static bool is_finite(const T) { return true; } + static T min() { return ~max(); } + static T max() { return (T)1<<(8*sizeof(T) - 1); } + static T inf() { return max(); } + static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; } + static const char* format() { return "%s"; } + static const char* format_s() { return "%s"; } + static const char* format(const T& val) { static const char *const s = "unknown"; cimg::unused(val); return s; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "bool"; return s; } + static bool is_float() { return false; } + static bool is_inf(const bool) { return false; } + static bool is_nan(const bool) { return false; } + static bool is_finite(const bool) { return true; } + static bool min() { return false; } + static bool max() { return true; } + static bool inf() { return max(); } + static bool is_inf() { return false; } + static bool cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(bool)val; } + static const char* format() { return "%s"; } + static const char* format_s() { return "%s"; } + static const char* format(const bool val) { static const char* s[] = { "false", "true" }; return s[val?1:0]; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned char) { return false; } + static bool is_nan(const unsigned char) { return false; } + static bool is_finite(const unsigned char) { return true; } + static unsigned char min() { return 0; } + static unsigned char max() { return (unsigned char)-1; } + static unsigned char inf() { return max(); } + static unsigned char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned char val) { return (unsigned int)val; } + }; + +#if defined(CHAR_MAX) && CHAR_MAX==255 + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static bool is_finite(const char) { return true; } + static char min() { return 0; } + static char max() { return (char)-1; } + static char inf() { return max(); } + static char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const char val) { return (unsigned int)val; } + }; +#else + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static bool is_finite(const char) { return true; } + static char min() { return ~max(); } + static char max() { return (char)((unsigned char)-1>>1); } + static char inf() { return max(); } + static char cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(char)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const char val) { return (int)val; } + }; +#endif + + template<> struct type { + static const char* string() { static const char *const s = "signed char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const signed char) { return false; } + static bool is_nan(const signed char) { return false; } + static bool is_finite(const signed char) { return true; } + static signed char min() { return ~max(); } + static signed char max() { return (signed char)((unsigned char)-1>>1); } + static signed char inf() { return max(); } + static signed char cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(signed char)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const signed char val) { return (int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned short) { return false; } + static bool is_nan(const unsigned short) { return false; } + static bool is_finite(const unsigned short) { return true; } + static unsigned short min() { return 0; } + static unsigned short max() { return (unsigned short)-1; } + static unsigned short inf() { return max(); } + static unsigned short cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned short)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned short val) { return (unsigned int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const short) { return false; } + static bool is_nan(const short) { return false; } + static bool is_finite(const short) { return true; } + static short min() { return ~max(); } + static short max() { return (short)((unsigned short)-1>>1); } + static short inf() { return max(); } + static short cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(short)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const short val) { return (int)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned int) { return false; } + static bool is_nan(const unsigned int) { return false; } + static bool is_finite(const unsigned int) { return true; } + static unsigned int min() { return 0; } + static unsigned int max() { return (unsigned int)-1; } + static unsigned int inf() { return max(); } + static unsigned int cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(unsigned int)val; } + static const char* format() { return "%u"; } + static const char* format_s() { return "%u"; } + static unsigned int format(const unsigned int val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const int) { return false; } + static bool is_nan(const int) { return false; } + static bool is_finite(const int) { return true; } + static int min() { return ~max(); } + static int max() { return (int)((unsigned int)-1>>1); } + static int inf() { return max(); } + static int cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(int)val; } + static const char* format() { return "%d"; } + static const char* format_s() { return "%d"; } + static int format(const int val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_uint64) { return false; } + static bool is_nan(const cimg_uint64) { return false; } + static bool is_finite(const cimg_uint64) { return true; } + static cimg_uint64 min() { return 0; } + static cimg_uint64 max() { return (cimg_uint64)-1; } + static cimg_uint64 inf() { return max(); } + static cimg_uint64 cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(cimg_uint64)val; } + static const char* format() { return cimg_fuint64; } + static const char* format_s() { return cimg_fuint64; } + static cimg_uint64 format(const cimg_uint64 val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_int64) { return false; } + static bool is_nan(const cimg_int64) { return false; } + static bool is_finite(const cimg_int64) { return true; } + static cimg_int64 min() { return ~max(); } + static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); } + static cimg_int64 inf() { return max(); } + static cimg_int64 cut(const double val) { + return val<(double)min()?min():val>(double)max()?max():(cimg_int64)val; + } + static const char* format() { return cimg_fint64; } + static const char* format_s() { return cimg_fint64; } + static long format(const long val) { return (long)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const double val) { // Custom version that works with '-ffast-math' + if (sizeof(double)==8) { + cimg_uint64 u; + std::memcpy(&u,&val,sizeof(double)); + return ((unsigned int)(u>>32)&0x7fffffff) + ((unsigned int)u!=0)>0x7ff00000; + } +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const double val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static double min() { return -DBL_MAX; } + static double max() { return DBL_MAX; } + static double inf() { +#ifdef INFINITY + return (double)INFINITY; +#else + return max()*max(); +#endif + } + static double nan() { +#ifdef NAN + return (double)NAN; +#else + const double val_nan = -std::sqrt(-1.); return val_nan; +#endif + } + static double cut(const double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const double val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "float"; return s; } + static bool is_float() { return true; } + static bool is_inf(const float val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const float val) { // Custom version that works with '-ffast-math' + if (sizeof(float)==4) { + unsigned int u; + std::memcpy(&u,&val,sizeof(float)); + return (u&0x7fffffff)>0x7f800000; + } +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const float val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static float min() { return -FLT_MAX; } + static float max() { return FLT_MAX; } + static float inf() { return (float)cimg::type::inf(); } + static float nan() { return (float)cimg::type::nan(); } + static float cut(const double val) { return (float)val; } + static float cut(const float val) { return (float)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const float val) { return (double)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "long double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const long double val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static bool is_finite(const long double val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static long double min() { return -LDBL_MAX; } + static long double max() { return LDBL_MAX; } + static long double inf() { return max()*max(); } + static long double nan() { const long double val_nan = -std::sqrt(-1.L); return val_nan; } + static long double cut(const long double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const long double val) { return (double)val; } + }; + +#ifdef cimg_use_half + template<> struct type { + static const char* string() { static const char *const s = "half"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const half val) { // Custom version that works with '-ffast-math' + if (sizeof(half)==2) { + short u; + std::memcpy(&u,&val,sizeof(short)); + return (bool)((u&0x7fff)>0x7c00); + } + return cimg::type::is_nan((float)val); + } + static bool is_finite(const half val) { +#ifdef isfinite + return (bool)isfinite(val); +#else + return !is_nan(val) && !is_inf(val); +#endif + } + static half min() { return (half)-65504; } + static half max() { return (half)65504; } + static half inf() { return max()*max(); } + static half nan() { const half val_nan = (half)-std::sqrt(-1.); return val_nan; } + static half cut(const double val) { return (half)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const half val) { return (double)val; } + }; +#endif + + template struct superset { typedef T type; }; + template<> struct superset { typedef unsigned char type; }; + template<> struct superset { typedef char type; }; + template<> struct superset { typedef signed char type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + +#ifdef cimg_use_half + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; +#endif + + template struct superset2 { + typedef typename superset::type>::type type; + }; + + template struct superset3 { + typedef typename superset::type>::type type; + }; + + template struct last { typedef t2 type; }; + +#define _cimg_Tt typename cimg::superset::type +#define _cimg_Tfloat typename cimg::superset::type +#define _cimg_tfloat typename cimg::superset::type +#define _cimg_Ttfloat typename cimg::superset2::type +#define _cimg_Ttdouble typename cimg::superset2::type + + // Define variables used internally by CImg. +#if cimg_display==1 + struct X11_static { + unsigned int nb_wins; + pthread_t *events_thread; + pthread_cond_t wait_event; + pthread_mutex_t wait_event_mutex; + CImgDisplay **wins; + Display *display; + unsigned int nb_bits; + bool is_blue_first; + bool is_shm_enabled; + bool byte_order; + +#ifdef cimg_use_xrandr + XRRScreenSize *resolutions; + Rotation curr_rotation; + unsigned int curr_resolution; + unsigned int nb_resolutions; +#endif + X11_static():nb_wins(0),events_thread(0),display(0), + nb_bits(0),is_blue_first(false),is_shm_enabled(false),byte_order(false) { +#ifdef __FreeBSD__ + XInitThreads(); +#endif + wins = new CImgDisplay*[1024]; + pthread_mutex_init(&wait_event_mutex,0); + pthread_cond_init(&wait_event,0); + +#ifdef cimg_use_xrandr + resolutions = 0; + curr_rotation = 0; + curr_resolution = nb_resolutions = 0; +#endif + } + + ~X11_static() { + delete[] wins; + /* + if (events_thread) { + pthread_cancel(*events_thread); + delete events_thread; + } + if (display) { } // XCloseDisplay(display); } + pthread_cond_destroy(&wait_event); + pthread_mutex_unlock(&wait_event_mutex); + pthread_mutex_destroy(&wait_event_mutex); + */ + } + }; // struct X11_static { ... +#if defined(cimg_module) + X11_static& X11_attr(); +#elif defined(cimg_main) + X11_static& X11_attr() { static X11_static val; return val; } +#else + inline X11_static& X11_attr() { static X11_static val; return val; } +#endif + +#elif cimg_display==2 + struct Win32_static { + HANDLE wait_event; + Win32_static() { wait_event = CreateEvent(0,FALSE_WIN,FALSE_WIN,0); } + }; // struct Win32_static { ... +#if defined(cimg_module) + Win32_static& Win32_attr(); +#elif defined(cimg_main) + Win32_static& Win32_attr() { static Win32_static val; return val; } +#else + inline Win32_static& Win32_attr() { static Win32_static val; return val; } +#endif +#endif +#define cimg_lock_display() cimg::mutex(15) +#define cimg_unlock_display() cimg::mutex(15,0) + + struct Mutex_static { +#if cimg_OS==1 && (defined(cimg_use_pthread) || cimg_display==1) + pthread_mutex_t mutex[32]; + Mutex_static() { for (unsigned int i = 0; i<32; ++i) pthread_mutex_init(&mutex[i],0); } + void lock(const unsigned int n) { pthread_mutex_lock(&mutex[n]); } + void unlock(const unsigned int n) { pthread_mutex_unlock(&mutex[n]); } + int trylock(const unsigned int n) { return pthread_mutex_trylock(&mutex[n]); } +#elif cimg_OS==2 + HANDLE mutex[32]; + Mutex_static() { for (unsigned int i = 0; i<32; ++i) mutex[i] = CreateMutex(0,FALSE_WIN,0); } + void lock(const unsigned int n) { WaitForSingleObject(mutex[n],INFINITE); } + void unlock(const unsigned int n) { ReleaseMutex(mutex[n]); } + int trylock(const unsigned int) { return 0; } +#else + Mutex_static() {} + void lock(const unsigned int) {} + void unlock(const unsigned int) {} + int trylock(const unsigned int) { return 0; } +#endif + }; // struct Mutex_static { ... +#if defined(cimg_module) + Mutex_static& Mutex_attr(); +#elif defined(cimg_main) + Mutex_static& Mutex_attr() { static Mutex_static val; return val; } +#else + inline Mutex_static& Mutex_attr() { static Mutex_static val; return val; } +#endif + +#if defined(cimg_use_magick) + struct Magick_static { + Magick_static() { + Magick::InitializeMagick(""); + } + }; // struct Magick_static { ... + static Magick_static _Magick_static; +#endif + +#if defined(cimg_use_fftw3) && !defined(cimg_use_fftw3_singlethread) + struct FFTW3_static { + FFTW3_static() { + fftw_init_threads(); + } + }; // struct FFTW3_static { ... + static FFTW3_static _FFTW3_static; +#endif + +#if cimg_display==1 + // Define keycodes for X11-based graphical systems. + const unsigned int keyESC = XK_Escape; + const unsigned int keyF1 = XK_F1; + const unsigned int keyF2 = XK_F2; + const unsigned int keyF3 = XK_F3; + const unsigned int keyF4 = XK_F4; + const unsigned int keyF5 = XK_F5; + const unsigned int keyF6 = XK_F6; + const unsigned int keyF7 = XK_F7; + const unsigned int keyF8 = XK_F8; + const unsigned int keyF9 = XK_F9; + const unsigned int keyF10 = XK_F10; + const unsigned int keyF11 = XK_F11; + const unsigned int keyF12 = XK_F12; + const unsigned int keyPAUSE = XK_Pause; + const unsigned int key1 = XK_1; + const unsigned int key2 = XK_2; + const unsigned int key3 = XK_3; + const unsigned int key4 = XK_4; + const unsigned int key5 = XK_5; + const unsigned int key6 = XK_6; + const unsigned int key7 = XK_7; + const unsigned int key8 = XK_8; + const unsigned int key9 = XK_9; + const unsigned int key0 = XK_0; + const unsigned int keyBACKSPACE = XK_BackSpace; + const unsigned int keyINSERT = XK_Insert; + const unsigned int keyHOME = XK_Home; + const unsigned int keyPAGEUP = XK_Page_Up; + const unsigned int keyTAB = XK_Tab; + const unsigned int keyQ = XK_q; + const unsigned int keyW = XK_w; + const unsigned int keyE = XK_e; + const unsigned int keyR = XK_r; + const unsigned int keyT = XK_t; + const unsigned int keyY = XK_y; + const unsigned int keyU = XK_u; + const unsigned int keyI = XK_i; + const unsigned int keyO = XK_o; + const unsigned int keyP = XK_p; + const unsigned int keyDELETE = XK_Delete; + const unsigned int keyEND = XK_End; + const unsigned int keyPAGEDOWN = XK_Page_Down; + const unsigned int keyCAPSLOCK = XK_Caps_Lock; + const unsigned int keyA = XK_a; + const unsigned int keyS = XK_s; + const unsigned int keyD = XK_d; + const unsigned int keyF = XK_f; + const unsigned int keyG = XK_g; + const unsigned int keyH = XK_h; + const unsigned int keyJ = XK_j; + const unsigned int keyK = XK_k; + const unsigned int keyL = XK_l; + const unsigned int keyENTER = XK_Return; + const unsigned int keySHIFTLEFT = XK_Shift_L; + const unsigned int keyZ = XK_z; + const unsigned int keyX = XK_x; + const unsigned int keyC = XK_c; + const unsigned int keyV = XK_v; + const unsigned int keyB = XK_b; + const unsigned int keyN = XK_n; + const unsigned int keyM = XK_m; + const unsigned int keySHIFTRIGHT = XK_Shift_R; + const unsigned int keyARROWUP = XK_Up; + const unsigned int keyCTRLLEFT = XK_Control_L; + const unsigned int keyAPPLEFT = XK_Super_L; + const unsigned int keyALT = XK_Alt_L; + const unsigned int keySPACE = XK_space; + const unsigned int keyALTGR = XK_Alt_R; + const unsigned int keyAPPRIGHT = XK_Super_R; + const unsigned int keyMENU = XK_Menu; + const unsigned int keyCTRLRIGHT = XK_Control_R; + const unsigned int keyARROWLEFT = XK_Left; + const unsigned int keyARROWDOWN = XK_Down; + const unsigned int keyARROWRIGHT = XK_Right; + const unsigned int keyPAD0 = XK_KP_0; + const unsigned int keyPAD1 = XK_KP_1; + const unsigned int keyPAD2 = XK_KP_2; + const unsigned int keyPAD3 = XK_KP_3; + const unsigned int keyPAD4 = XK_KP_4; + const unsigned int keyPAD5 = XK_KP_5; + const unsigned int keyPAD6 = XK_KP_6; + const unsigned int keyPAD7 = XK_KP_7; + const unsigned int keyPAD8 = XK_KP_8; + const unsigned int keyPAD9 = XK_KP_9; + const unsigned int keyPADADD = XK_KP_Add; + const unsigned int keyPADSUB = XK_KP_Subtract; + const unsigned int keyPADMUL = XK_KP_Multiply; + const unsigned int keyPADDIV = XK_KP_Divide; + +#elif cimg_display==2 + // Define keycodes for Windows. + const unsigned int keyESC = VK_ESCAPE; + const unsigned int keyF1 = VK_F1; + const unsigned int keyF2 = VK_F2; + const unsigned int keyF3 = VK_F3; + const unsigned int keyF4 = VK_F4; + const unsigned int keyF5 = VK_F5; + const unsigned int keyF6 = VK_F6; + const unsigned int keyF7 = VK_F7; + const unsigned int keyF8 = VK_F8; + const unsigned int keyF9 = VK_F9; + const unsigned int keyF10 = VK_F10; + const unsigned int keyF11 = VK_F11; + const unsigned int keyF12 = VK_F12; + const unsigned int keyPAUSE = VK_PAUSE; + const unsigned int key1 = '1'; + const unsigned int key2 = '2'; + const unsigned int key3 = '3'; + const unsigned int key4 = '4'; + const unsigned int key5 = '5'; + const unsigned int key6 = '6'; + const unsigned int key7 = '7'; + const unsigned int key8 = '8'; + const unsigned int key9 = '9'; + const unsigned int key0 = '0'; + const unsigned int keyBACKSPACE = VK_BACK; + const unsigned int keyINSERT = VK_INSERT; + const unsigned int keyHOME = VK_HOME; + const unsigned int keyPAGEUP = VK_PRIOR; + const unsigned int keyTAB = VK_TAB; + const unsigned int keyQ = 'Q'; + const unsigned int keyW = 'W'; + const unsigned int keyE = 'E'; + const unsigned int keyR = 'R'; + const unsigned int keyT = 'T'; + const unsigned int keyY = 'Y'; + const unsigned int keyU = 'U'; + const unsigned int keyI = 'I'; + const unsigned int keyO = 'O'; + const unsigned int keyP = 'P'; + const unsigned int keyDELETE = VK_DELETE; + const unsigned int keyEND = VK_END; + const unsigned int keyPAGEDOWN = VK_NEXT; + const unsigned int keyCAPSLOCK = VK_CAPITAL; + const unsigned int keyA = 'A'; + const unsigned int keyS = 'S'; + const unsigned int keyD = 'D'; + const unsigned int keyF = 'F'; + const unsigned int keyG = 'G'; + const unsigned int keyH = 'H'; + const unsigned int keyJ = 'J'; + const unsigned int keyK = 'K'; + const unsigned int keyL = 'L'; + const unsigned int keyENTER = VK_RETURN; + const unsigned int keySHIFTLEFT = VK_SHIFT; + const unsigned int keyZ = 'Z'; + const unsigned int keyX = 'X'; + const unsigned int keyC = 'C'; + const unsigned int keyV = 'V'; + const unsigned int keyB = 'B'; + const unsigned int keyN = 'N'; + const unsigned int keyM = 'M'; + const unsigned int keySHIFTRIGHT = VK_SHIFT; + const unsigned int keyARROWUP = VK_UP; + const unsigned int keyCTRLLEFT = VK_CONTROL; + const unsigned int keyAPPLEFT = VK_LWIN; + const unsigned int keyALT = VK_LMENU; + const unsigned int keySPACE = VK_SPACE; + const unsigned int keyALTGR = VK_CONTROL; + const unsigned int keyAPPRIGHT = VK_RWIN; + const unsigned int keyMENU = VK_APPS; + const unsigned int keyCTRLRIGHT = VK_CONTROL; + const unsigned int keyARROWLEFT = VK_LEFT; + const unsigned int keyARROWDOWN = VK_DOWN; + const unsigned int keyARROWRIGHT = VK_RIGHT; + const unsigned int keyPAD0 = 0x60; + const unsigned int keyPAD1 = 0x61; + const unsigned int keyPAD2 = 0x62; + const unsigned int keyPAD3 = 0x63; + const unsigned int keyPAD4 = 0x64; + const unsigned int keyPAD5 = 0x65; + const unsigned int keyPAD6 = 0x66; + const unsigned int keyPAD7 = 0x67; + const unsigned int keyPAD8 = 0x68; + const unsigned int keyPAD9 = 0x69; + const unsigned int keyPADADD = VK_ADD; + const unsigned int keyPADSUB = VK_SUBTRACT; + const unsigned int keyPADMUL = VK_MULTIPLY; + const unsigned int keyPADDIV = VK_DIVIDE; + +#else + // Define random keycodes when no display is available. + // (should rarely be used then!). + const unsigned int keyESC = 1U; //!< Keycode for the \c ESC key (architecture-dependent) + const unsigned int keyF1 = 2U; //!< Keycode for the \c F1 key (architecture-dependent) + const unsigned int keyF2 = 3U; //!< Keycode for the \c F2 key (architecture-dependent) + const unsigned int keyF3 = 4U; //!< Keycode for the \c F3 key (architecture-dependent) + const unsigned int keyF4 = 5U; //!< Keycode for the \c F4 key (architecture-dependent) + const unsigned int keyF5 = 6U; //!< Keycode for the \c F5 key (architecture-dependent) + const unsigned int keyF6 = 7U; //!< Keycode for the \c F6 key (architecture-dependent) + const unsigned int keyF7 = 8U; //!< Keycode for the \c F7 key (architecture-dependent) + const unsigned int keyF8 = 9U; //!< Keycode for the \c F8 key (architecture-dependent) + const unsigned int keyF9 = 10U; //!< Keycode for the \c F9 key (architecture-dependent) + const unsigned int keyF10 = 11U; //!< Keycode for the \c F10 key (architecture-dependent) + const unsigned int keyF11 = 12U; //!< Keycode for the \c F11 key (architecture-dependent) + const unsigned int keyF12 = 13U; //!< Keycode for the \c F12 key (architecture-dependent) + const unsigned int keyPAUSE = 14U; //!< Keycode for the \c PAUSE key (architecture-dependent) + const unsigned int key1 = 15U; //!< Keycode for the \c 1 key (architecture-dependent) + const unsigned int key2 = 16U; //!< Keycode for the \c 2 key (architecture-dependent) + const unsigned int key3 = 17U; //!< Keycode for the \c 3 key (architecture-dependent) + const unsigned int key4 = 18U; //!< Keycode for the \c 4 key (architecture-dependent) + const unsigned int key5 = 19U; //!< Keycode for the \c 5 key (architecture-dependent) + const unsigned int key6 = 20U; //!< Keycode for the \c 6 key (architecture-dependent) + const unsigned int key7 = 21U; //!< Keycode for the \c 7 key (architecture-dependent) + const unsigned int key8 = 22U; //!< Keycode for the \c 8 key (architecture-dependent) + const unsigned int key9 = 23U; //!< Keycode for the \c 9 key (architecture-dependent) + const unsigned int key0 = 24U; //!< Keycode for the \c 0 key (architecture-dependent) + const unsigned int keyBACKSPACE = 25U; //!< Keycode for the \c BACKSPACE key (architecture-dependent) + const unsigned int keyINSERT = 26U; //!< Keycode for the \c INSERT key (architecture-dependent) + const unsigned int keyHOME = 27U; //!< Keycode for the \c HOME key (architecture-dependent) + const unsigned int keyPAGEUP = 28U; //!< Keycode for the \c PAGEUP key (architecture-dependent) + const unsigned int keyTAB = 29U; //!< Keycode for the \c TAB key (architecture-dependent) + const unsigned int keyQ = 30U; //!< Keycode for the \c Q key (architecture-dependent) + const unsigned int keyW = 31U; //!< Keycode for the \c W key (architecture-dependent) + const unsigned int keyE = 32U; //!< Keycode for the \c E key (architecture-dependent) + const unsigned int keyR = 33U; //!< Keycode for the \c R key (architecture-dependent) + const unsigned int keyT = 34U; //!< Keycode for the \c T key (architecture-dependent) + const unsigned int keyY = 35U; //!< Keycode for the \c Y key (architecture-dependent) + const unsigned int keyU = 36U; //!< Keycode for the \c U key (architecture-dependent) + const unsigned int keyI = 37U; //!< Keycode for the \c I key (architecture-dependent) + const unsigned int keyO = 38U; //!< Keycode for the \c O key (architecture-dependent) + const unsigned int keyP = 39U; //!< Keycode for the \c P key (architecture-dependent) + const unsigned int keyDELETE = 40U; //!< Keycode for the \c DELETE key (architecture-dependent) + const unsigned int keyEND = 41U; //!< Keycode for the \c END key (architecture-dependent) + const unsigned int keyPAGEDOWN = 42U; //!< Keycode for the \c PAGEDOWN key (architecture-dependent) + const unsigned int keyCAPSLOCK = 43U; //!< Keycode for the \c CAPSLOCK key (architecture-dependent) + const unsigned int keyA = 44U; //!< Keycode for the \c A key (architecture-dependent) + const unsigned int keyS = 45U; //!< Keycode for the \c S key (architecture-dependent) + const unsigned int keyD = 46U; //!< Keycode for the \c D key (architecture-dependent) + const unsigned int keyF = 47U; //!< Keycode for the \c F key (architecture-dependent) + const unsigned int keyG = 48U; //!< Keycode for the \c G key (architecture-dependent) + const unsigned int keyH = 49U; //!< Keycode for the \c H key (architecture-dependent) + const unsigned int keyJ = 50U; //!< Keycode for the \c J key (architecture-dependent) + const unsigned int keyK = 51U; //!< Keycode for the \c K key (architecture-dependent) + const unsigned int keyL = 52U; //!< Keycode for the \c L key (architecture-dependent) + const unsigned int keyENTER = 53U; //!< Keycode for the \c ENTER key (architecture-dependent) + const unsigned int keySHIFTLEFT = 54U; //!< Keycode for the \c SHIFTLEFT key (architecture-dependent) + const unsigned int keyZ = 55U; //!< Keycode for the \c Z key (architecture-dependent) + const unsigned int keyX = 56U; //!< Keycode for the \c X key (architecture-dependent) + const unsigned int keyC = 57U; //!< Keycode for the \c C key (architecture-dependent) + const unsigned int keyV = 58U; //!< Keycode for the \c V key (architecture-dependent) + const unsigned int keyB = 59U; //!< Keycode for the \c B key (architecture-dependent) + const unsigned int keyN = 60U; //!< Keycode for the \c N key (architecture-dependent) + const unsigned int keyM = 61U; //!< Keycode for the \c M key (architecture-dependent) + const unsigned int keySHIFTRIGHT = 62U; //!< Keycode for the \c SHIFTRIGHT key (architecture-dependent) + const unsigned int keyARROWUP = 63U; //!< Keycode for the \c ARROWUP key (architecture-dependent) + const unsigned int keyCTRLLEFT = 64U; //!< Keycode for the \c CTRLLEFT key (architecture-dependent) + const unsigned int keyAPPLEFT = 65U; //!< Keycode for the \c APPLEFT key (architecture-dependent) + const unsigned int keyALT = 66U; //!< Keycode for the \c ALT key (architecture-dependent) + const unsigned int keySPACE = 67U; //!< Keycode for the \c SPACE key (architecture-dependent) + const unsigned int keyALTGR = 68U; //!< Keycode for the \c ALTGR key (architecture-dependent) + const unsigned int keyAPPRIGHT = 69U; //!< Keycode for the \c APPRIGHT key (architecture-dependent) + const unsigned int keyMENU = 70U; //!< Keycode for the \c MENU key (architecture-dependent) + const unsigned int keyCTRLRIGHT = 71U; //!< Keycode for the \c CTRLRIGHT key (architecture-dependent) + const unsigned int keyARROWLEFT = 72U; //!< Keycode for the \c ARROWLEFT key (architecture-dependent) + const unsigned int keyARROWDOWN = 73U; //!< Keycode for the \c ARROWDOWN key (architecture-dependent) + const unsigned int keyARROWRIGHT = 74U; //!< Keycode for the \c ARROWRIGHT key (architecture-dependent) + const unsigned int keyPAD0 = 75U; //!< Keycode for the \c PAD0 key (architecture-dependent) + const unsigned int keyPAD1 = 76U; //!< Keycode for the \c PAD1 key (architecture-dependent) + const unsigned int keyPAD2 = 77U; //!< Keycode for the \c PAD2 key (architecture-dependent) + const unsigned int keyPAD3 = 78U; //!< Keycode for the \c PAD3 key (architecture-dependent) + const unsigned int keyPAD4 = 79U; //!< Keycode for the \c PAD4 key (architecture-dependent) + const unsigned int keyPAD5 = 80U; //!< Keycode for the \c PAD5 key (architecture-dependent) + const unsigned int keyPAD6 = 81U; //!< Keycode for the \c PAD6 key (architecture-dependent) + const unsigned int keyPAD7 = 82U; //!< Keycode for the \c PAD7 key (architecture-dependent) + const unsigned int keyPAD8 = 83U; //!< Keycode for the \c PAD8 key (architecture-dependent) + const unsigned int keyPAD9 = 84U; //!< Keycode for the \c PAD9 key (architecture-dependent) + const unsigned int keyPADADD = 85U; //!< Keycode for the \c PADADD key (architecture-dependent) + const unsigned int keyPADSUB = 86U; //!< Keycode for the \c PADSUB key (architecture-dependent) + const unsigned int keyPADMUL = 87U; //!< Keycode for the \c PADMUL key (architecture-dependent) + const unsigned int keyPADDIV = 88U; //!< Keycode for the \c PADDDIV key (architecture-dependent) +#endif + + const double PI = 3.14159265358979323846; //!< Value of the mathematical constant PI + + // Define a 10x13 binary font (small sans). + static const char *const data_font_small[] = { + " UwlwnwoyuwHwlwmwcwlwnw[xuwowlwmwoyuwRwlwnxcw Mw (wnwnwuwpwuypwuwoy" + "ZwnwmwuwowuwmwnwnwuwowuwfwuxnwnwmwuwpwuypwuwZwnwnwtwpwtwow'y Hw cwnw >{ jw %xdxZwdw_wexfwYwkw 7yowoyFx=w " + "ry qw %wuw !xnwkwnwoyuwfwuw[wkwnwcwowrwpwdwuwoxuwpwkwnwoyuwRwkwnwbwpwNyoyoyoyoy;wdwnxpxtxowG|!ydwnwuwowtwow" + "pxswqxlwnxnxmwDwoyoxnyoymwp{oyq{pyoy>ypwqwpwp{oyqzo{q{pzrwrwowlwqwswpwnwqwsxswpypzoyqzozq}swrwrwqwtwswswtxsxswq" + "ws}qwnwkwnydwew_wfwdwkwmwowkw(w0wmwmwGwtwdxQw swuwnwo{q{pynwp|rwtwtwqydwcwcwcwmwmxgwqwpwnzpwuwpzoyRzoyoyexnynwd" + "z\\xnxgxrwsxrwsyswowmwmwmwmwmwmwo}ryp{q{q{q{nwmwnwmwozqxswpyoyoyoyoyeyuwswrwrwrwrwrwrwrwrwqwrwmwtwnwmwnwuwpwuyp" + "wuwoyZwmwnwuwowuwmwqwkwuwowuwoxnwuxowmwnwuwpwuypwuwZwmwnwuwowuwnwowmwtw\\wuwuwqwswqwswqwswqwswEwqwtweypzr~qyIw " + "rwswewnwuwowuwozswtwuwqwtwmwnwlwowuwuwowOxpxuxqwuwowswqwswoxpwlwjwqwswqwswy~}P{|k~-{|w~}k{|w~}Ww~|S{|k~X{|v~vv~|Y{|}k~}|Z{|y~" + "}y|xy|}w~| s{|}k~}|Z{|l~|V{}p~}\"{|y~}|w{|}w~|V{|}|u{|v~P{}x~} {{}h~} N{|~y}y|}x~|S{|v~}|y{|}w~}2{|w~y}x~|g{}x" + "~|k{|w~y}x~|g{}x~|kx}|w{|}w~}k{}x~}%{}t~|P{}t~|P{}t~|P{}t~|P{}t~|P{}t~}W{|[~}e{}f~}b{}c~|a{}c~|a{}c~|a{}c~|X{}w" + "~}M{}w~}M{}w~}M{}w~}Z{|d~}|`{}t~}kv~b{|g~}]{|g~}]{|g~}]{|g~}]{|g~}){|g~|{|w~|h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f" + "{|v~h{}w~}f{|v~|j{|v~|b{}w~}L{|u~}|w{|}v~|W{|w~|Iw~}Qw~x{}x~|V{}y~}x{}s~|X{|v~|wv~}Vx~}v{|x~| D{}x~}I{}w~Q{}x~|" + "xw~U{}w~}w{|v~T{|w~|J{|w~Q{|x~}x{|x~|V{|v~vv~|T{}q~}|Wx~|x{}s~T{|w~I{|w~|R{|x~}x{}x~|Vx~}x{}s~|X{|v~vv~| Fw~}J{" + "|w~|R{|x~}x{|x~}Uv~|w{}w~}Q{|w~|Ww~}Hv~}w{}w~} Pw~}y{|x~}cY~ i{}y~|#{|w~}Qm~|`m~}w{|m~|\\{}v~| ;{}`~} -" + "{|r~x}t~}$v~}R{}x~}vw~}S{|w~t{|x~}U{|y~|_{|w~}w{}w~|n{}x~}_{|t~w}u~|Q{}x~}K{}w~N{}x~}Jx~ +{|w~Xs~y}s~|\\m~}X{}" + "f~\\{}g~}R{|s~}\\{|g~}Y{|i~|`{}c~|_{|s~w}s~}]{|s~x}s~ hr~}r~|[{|f~}Xs~}Y{}d~|\\{|c~}g{}b~|^{}c~|`{}e~_{|a~|g{" + "}w~}hv~|Y{}w~}M{}w~}W{}w~}n{|u~|_{}w~}V{}s~}jr~|h{}s~|lv~c{|p~}q~}^{}f~}_{|p~}q~}`{}e~[{}q~}p~dZ~g{|v~h{}w~}h{|" + "v~|f{|v~p{|v~m{|t~}m{}w~}m{|v~|m{}v~c{}v~jv~}e\\~]{|w~}Nw~}D{|w~|Sp~| ww~|!w~} `{|w~|${}w~}!w~}Cv~Lv~Tw~}Dv~ " + " Ov~ !{}w~}Mw~|N{|v~ :{}v~|s{|v~V{|t}|V{|t~s}w~| p{|v~ {{|v~|t{|v~|Vs~}W{}c~|_{}d~}c{|d~|W{|v~Y{}^~|iv~" + "}r{|v~qv~}f{|p~}q~}${}r~} v{}w~ v{}q~| ?y~}Ps~x}u~,v~k{}w~|Ww~|Su~}v|}w~X{|v~vv~|Z{}v~}y|wy|}v~}[{|}q{}x~} t{}" + "v~}y|wy|}v~}&{}w~|x{|w~}#y|r{}x~}Kw~|R{|w~ {{}p~}v|x~} H{}x~|S{}w~t{}w~|3x|x{}x~|h{|x~}j{|}|x{}x~|h{|x~}`{|w~l{" + "|w~$s~}Ps~}Ps~}Ps~}Ps~}Pr~W{}[~}g{|c~}c{}c~|a{}c~|a{}c~|a{}c~|X{}w~}M{}w~}M{}w~}M{}w~}Z{|b~}a{}s~|lv~c{|p~}q~}_" + "{|p~}q~}_{|p~}q~}_{|p~}q~}_{|p~}q~}+{|p~}q~}w~|g{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}e{}v~jv~}a{}w~}Lu~r{" + "|v~V{|w~J{}x~}Q{}x~|w{}x~Vx~|w{}u~}Vv|vv|U{}x~}x|}w~ Bw~|K{|w~|R{|x~}w{|x~}Vu|vv|S{|w~K{|w~|Qx~}v{}x~Uv|vv|T{|}" + "t~}|Tx~|w{|u~|S{}x~}Jw~}Qw~vw~Vx~|w{}u~}Vv|vv| Dw~|Kw~|Qw~v{}x~|Vv|vv|Pw~|Vw~}Hv|uv| G{|t}|P{|t}|P{|t}|P{|t}|P{" + "|t}|Lw~|xw~c{|[~} iy~}\"u~|S{|l~a{}l~|x{}l~]{}t~ ={|^~} .{|u~}|u{|}w~}$v~}R{}x~}vw~}S{}x~}t{}x~}Xy|y}y~y}x" + "|cw~}u{}w~o{|w~^u~}t{|}y~|Q{}x~}Kw~|N{|w~|T{}sx~s{} 4{}x~}Y{}v~}|v{}u~\\m~}X{}v~y}|wy|s~]{}x~}x|v{|}t~}Sr~}\\{" + "|v~k|Z{|t~}|v{|y}y~|`h|u~^t~|u{|}u~|^u~}|v{|}v~} iv~y|v{|t~]{|o~y}p~|[{|r~|Z{}w~}q|}s~]{|s~}|t{|}u~}g{}w~}r|y" + "}q~}_{}w~}h|_{}w~}j|`{|s~}|s{|}t~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}o{}u~|^{}w~}V{}r~k{|r~|h{}r~lv~d{|t~}|uy|s~_{}w~}" + "s|y}t~}a{|t~}|uy|s~a{}w~}s|y}s~]{}u~}|ty|}v~dn|}v~}n|g{|v~h{}w~}gv~}f{}w~}ov~|n{|t~}mv~|l{}v~|o{|v~|bv~}l{}v~dc" + "|u~}]{|w~}N{}w~D{|w~|T{}o~| x{|w~!w~} `{|w~|${}w~ w~} >w~}Dv~ Ov~ !{}w~|Mw~|M{}w~ :v~|q{}w~|Xp~}X{}v~|p{|" + "}| o{}w~| v~|r{|v~W{|r~|X{}v~}i|^{}w~}h|d{|s~}y|xy|}s~}[{|y}u~y}y|]{}w~}h|v~|iv~}r{|v~qv~}g{|t~}|uy|s~&{}p" + "~} w{}w~ w{}o~| @y~}Q{}v~}|u{|}y~,{|w~}m{|w~}Vw~|T{|v~|s{|}~({|w~}|o{|}w~|P{}x~| w{|w~}|o{|}w~|(x~}tw~ rw~K{}x" + "~|Rw~ {{}o~}w{|x~} H{}x~|T{|w~r{}x~}-{}x~|hw~|d{}x~|hw~|_{}x~|mw~|%{|r~|R{|r~|R{|r~|R{|r~|R{|r~|R{}r~|Y{|v~|y{|" + "v~}h|h{|s~}|t{|}u~}c{}w~}h|`{}w~}h|`{}w~}h|`{}w~}h|W{}w~}M{}w~}M{}w~}M{}w~}Z{|v~r|x}q~b{}r~lv~d{|t~}|uy|s~a{|t~" + "}|uy|s~a{|t~}|uy|s~a{|t~}|uy|s~a{|t~}|uy|s~-{|t~}|u{|}q~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}dv~}l{}v~`" + "{}w~}M{|v~p{}w~|V{}x~}L{}x~}Q{|x~|ux~}Wx~|v{|w~} {{}q~| Aw~|Lw~|Qw~u{}x~| y{|x~}Lw~|Q{}x~tx~}#{|}r~}Rx~u{|}y~}|" + "Q{}x~}L{}x~}Q{}x~|v{|x~}Wx~|v{}w~} j{|w~L{}x~}Q{}x~|u{}x~ x{}x~}Uw~} b{|}p~}|V{|}p~}|V{|}p~}|V{|}p~}|V{|}p~}|" + "P{|w~|xx|av~|fv~| j{|y~|#{}t~Sk~|c{|k~}y{|k~}_{|s~} ?{}t~}y| u{|u~|p{}y~}$v~}R{}x~}vw~}Sw~|tw~|[{|}m~}|h{" + "|w~sw~|p{}x~|_{}v~|q{|}|Q{}x~}L{}w~Lw~}U{}y~|ux~u{|y~}U{|x}| `w~|Z{|v~}s{|v~}]w~y}y|{}w~}X{}x~|p{|u~|^y}|n{|u~" + "|U{}x~y}w~}\\{|w~}K{|u~}o{}|Mv~|_{}v~}q{|u~_{}v~}r{|v~| jy~}|qu~|_{}t~}y|s{|}t~}\\{}w~}w~}Z{}w~}o{|u~}_{|t~|n" + "{|}x~}g{}w~}n{|}t~}`{}w~}L{}w~}P{|t~}m{|}w~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}p{}u~|]{}w~}V{}w~}w~|l{}r~|h{}r~|mv~e{|" + "u~}|p{|t~`{}w~}q{|}u~|c{|u~}|p{|t~b{}w~}p{}u~|_{|u~|n{|}y~W{|v~|Z{|v~h{}w~}g{|v~fv~|o{}w~}n{}x~}w~mv~|kv~}ov~}a" + "{|v~|n{|v~|M{}v~}\\{|w~}N{|w~|E{|w~|U{}v~}{|u~| x{|x~}\"w~} `{|w~|$v~ w~} >w~}Dv~ Ov~ !v~Lw~|M{}w~| <{|w~" + "}p{|w~}Xn~|Zv~ _{|v~ !{|w~}p{}w~}X{}w~}w~}W{}v~|M{}w~}R{|t~|p{|t~|_{|}l~}|`{}w~}hv~|iv~}r{|v~qv~}h{|u~}|p{|" + "t~({}n~} x{}w~ x{}m~| Ay~}R{|v~}p{}+{}w~|nv~Uw~|T{}w~| x{|w~|k{|w~|Q{|x~| x{|w~|k{|w~|*{|x~rx~|R{|w}Fw~Kw~|S{}" + "x~| {|n~}w{|x~} H{}x~|T{}x~}qw~|.{}x~|i{}x~}c{}x~|i{}x~}^{}x~|n{}x~}${}w~}w~}R{}w~}w~}R{}w~}w~}R{}w~}w~}R{}w~}w" + "~}Rv~|w~}Y{}w~}x{|v~U{|t~|n{|}x~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~n{|}s~c{}r~|mv~e{|u~}|p{|" + "t~c{|u~}|p{|t~c{|u~}|p{|t~c{|u~}|p{|t~c{|u~}|p{|t~/{|u~}|p{}t~}e{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}d{|v" + "~|n{|v~|`{}w~}M{}w~}ow~}U{}x~|N{|w~Px~}t{|x~|Xx|sy| w{}s~| @{|w~M{}x~|Q{}x~|tw~ x{}x~}N{}x~|Q{|x~|t{|x~|&{}t~}v" + "~} t{}x~|N{|x~}Q{|x~}t{}x~|Xx|sy| g{|x~}N{|x~}Q{|x~}sx~} {{|x~}Tw~} d{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|j~|R{|w~Z{}w~}" + "g{}w~} Ay|J{}y~#{|s~}Tk~}c{}j~|{}j~_q~| A{}u~} q{}v~|n{}~}$v~}R{}x~}vw~}Sw~t{|w~\\{|h~|i{}x~}s{}x~}q{|x~}^" + "v~|C{}x~}Lw~}L{}w~V{|v~|wx~w{|v~|V{}w~ a{|w~Yv~}q{|v~|^{}y|u{}w~}Xy}|m{|u~M{|v~}V{|w~|}w~}\\{|w~}Ku~|?{|v~^u~o" + "{}v~|a{|v~}p{}v~ j{~|nv~}`u~}|l{|}u~]v~{v~Z{}w~}mu~_u~}j{|y~}g{}w~}l{|}u~}a{}w~}L{}w~}Q{|u~}i{|}y~|g{}w~}hv~|" + "Y{}w~}M{}w~}W{}w~}q{}u~|\\{}w~}V{}w~|w~}lw~|v~|h{}q~mv~f{|u~}m{|u~}a{}w~}o{}v~}d{|u~}m{|u~}c{}w~}o{|u~_{}v~|j{|" + "W{|v~|Z{|v~h{}w~}fv~|h{}v~n{}w~}nw~|w~|o{|v~j{|v~}q{}v~_{}v~nv~}M{|u~[{|w~}Mw~}E{|w~|V{}v~}x{|u~| vw~} `{|w~|$" + "w~} w~} >w~}Dv~ Ov~ !v~Lw~|M{}w~| <{}w~|ow~}Xm~|[v~ ^v~| \"v~|p{|v~Xv~{v~V{}v~|N{}w~}Ru~}l{}u~|b{|g~}" + "|b{}w~}hv~|iv~}r{|v~qv~}i{|u~}m{|u~}*{}l~} y{}w~ y{}k~| By~}R{}v~ y{|w~}o{|w~}Uw~|T{}w~ x{|x~}g{}x~|R{|x~} y{|" + "x~}g{}x~|+{}y~}r{}y~}R{}w~Fx~}M{|}w~ Mm~}w{|x~} H{}x~|Tw~p{}x~|.{}x~|j{|w~b{}x~|j{|w~]w~n{|w~#v~{v~Rv~{v~Rv~{v~" + "Rv~{v~Rv~{v~S{|w~}{}w~|Zv~|x{|v~Uu~}j{|y~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~k{}t~d{}q~mv~f{|" + "u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}e{|u~}m{|u~}1{|u~}m{|u~}e{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w" + "~}c{}v~nv~}_{}w~}Mv~n{}w~Tw}N{|x}P{|x}r{|x} F{|}x~}| ={|x}|O{|x}|Px}|s{|x}| xw|Nw|Pw|rw|'{|v~}|y{|v~} tw}Nw}P{|" + "x}rx}| 6w|Nw|Ox|rw| Nw~} e{}h~}\\{}h~}\\{}h~}\\{}h~}\\{}h~}S{|w~Z{|v~gv~| Ay~}L{|y~}${|q~}V{|j~ci~}|i~|a{}p~|" + "Oy|Uw|jw|Vu|Wv|kw|b{}v~} p{|v~|l{|}$v~}R{}x~}vw~}T{|x~}t{|x~}]{|g~|i{}x~|s{|w~qw~|^v~B{}x~}M{|w~|L{|w~}V{|}" + "w~}xx~x{}w~}|U{}w~ a{}w~Z{|v~o{}w~}U{}w~}X{|j{}v~|M{}v~Vw~}{}w~}\\{|w~}L{|v~|>v~}_{|v~|nv~}a{}v~nv~| \\{}w~}" + "b{|u~|h{|}v~|`{|w~}{}w~|[{}w~}m{|v~|a{}v~}gy}g{}w~}j{}u~|b{}w~}L{}w~}Q{}v~}f{|~|g{}w~}hv~|Y{}w~}M{}w~}W{}w~}r{}" + "u~|[{}w~}V{}w~y|w~m{|w~{v~|h{}w~}v~|nv~f{}v~}ju~|b{}w~}nu~d{}v~}ju~|d{}w~}n{}v~|`v~}D{|v~|Z{|v~h{}w~}f{}w~}hv~}" + "n{|v~o{|w~{}x~}o{}w~}i{}v~|s{|v~|^v~}p{}v~M{|u~|[{|w~}M{}x~}E{|w~|W{}v~|v{|u~| ww~} `{|w~|$w~} w~} >w~}Dv~ " + "Ov~ !v~Lw~|M{|w~| <{}w~|ow~}Xy~}w|}t~[v~| _{}w~} #{|w~}n{}w~|Z{|w~}{}w~|Vu~|O{}w~}S{}v~}j{}u~c{}d~|c{}w~" + "}hv~|iv~}r{|v~qv~}i{}v~}ju~|,{}v~y}w~|v~} {{}w~ {{}v~y}w~|u~| Cy~}R{}w~}R{|ey|_{}w~|pv~Tw~|T{}w~ y{|x~}e{}x~|\\" + "{|}p~} {{|x~}e{}x~|,{}y~}r{}y~}R{}w~G{}x~|Rq~| N{|m~}w{|x~} H{}x~|U{|w~p{|x~}.{}x~|j{}x~|b{}x~|j{}x~|_{|w~|n{}" + "x~|${|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{|w~}{}w~|T{}w~|{|w~}[{|v~w{|v~V{}v~}gy}c{}w~}M{}w~}M{}w~}M{}w~" + "}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~j{|u~}e{}w~}v~|nv~f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|f{}v~}ju~|c{}d{}|d{}v~}" + "k{}u~|f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}bv~}p{}v~^{}m~y}|Yv~o{|}w~ Py~}|u{|v~} 2w~} f{" + "}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~T{|w~Yv~|i{|v~ A{}x~}M{}y~|$o~|W{|j~ch~}i~}" + "b{}n~T{|}t~y}|Zw~}kw~}X{}u~|X{}w~|m{}w~|d{|v~| ov~}j{|$v~}R{}x~}vw~}T{}x~}t{}x~}]u~}|{|y~|y{|y}x~|iw~|rw~r{" + "}x~}]v~B{}x~}Mv~Jv~T{|}w~|{x~{|w~}|S{}w~ aw~}Z{}w~}o{|v~U{}w~}Ev~}M{|v~W{}w~y{}w~}\\{|w~}Lv~}>{|v~|_{|v~m{}w~}" + "av~|n{|v~ 8{|y}6{|~|4{}v~c{|v~}d{|v~`{}w~|{|w~}[{}w~}lv~|b{|v~}e{|g{}w~}i{}u~b{}w~}L{}w~}R{|v~}dy|g{}w~}hv~|Y{}" + "w~}M{}w~}W{}w~}s{}u~Y{}w~}V{}w~|{w~|nw~}{v~|h{}w~y|v~nv~g{|v~}i{|u~b{}w~}n{|v~|f{|v~}i{|u~d{}w~}n{|v~|a{|v~C{|v" + "~|Z{|v~h{}w~}f{|v~|j{|v~|mv~|p{|w~{|x~}ov~|hv~}sv~}]{|v~|r{|v~|Mu~|Z{|w~}M{|w~E{|w~|X{}v~|t{|u~| xw~} `{|w~|$w" + "~} w~} >w~}Dv~ Ov~ !w~}Lw~|M{|w~| {|v~]{|v~m{}w~}b{|w~}l{}w~}W{|v}M{}v~D{}r~}6{|r~}|>{|v~|e{}w~|^{|w~|dv~w{|v~\\{}w~}lv~|c{}v~N{}w~}g{}v~|d{" + "}w~}L{}w~}S{}v~L{}w~}hv~|Y{}w~}M{}w~}W{}w~}vu~}V{}w~}V{}w~|yw~}pw~}yv~|h{}w~|y{}w~}pv~h{}v~e{}v~|d{}w~}mv~}g{}v" + "~e{}v~|f{}w~}mv~}a{|v~C{|v~|Z{|v~h{}w~}dv~|l{|v~k{|v~q{|w~x{}x~}q{}w~}e{}v~wv~}Y{|v~|v{|v~|N{|v~}W{|w~}L{|w~F{|" + "w~|[{}v~l{}v~ S{|}k~|Zw~}y{|o~}V{|k~|\\{|o~}y{|w~|\\{|m~}X{}k~}Y{|o~}y{|w~|`w~}y{|o~}Sv~Lv~Tw~}o{|v~}Wv~_w~}y{|" + "o~|v{|o~|ew~}y{|o~}Y{|}n~}|[w~}y{|o~}Y{|o~}y{|w~|Zw~}y{|r~|[{}j~[{}i~]{|w~|m{}w~|b{}w~|k{|w~}i{|w~}q{|u~|q{|w~|" + "h{|v~|o{|v~}b{}w~|k{|w~}`d~Uw~}Lw~|M{|w~| n{|o~}vw~|av~o{}w~|M{|v~[{|o~}|U{}k~}]w~}y{|o~}_u~|k{|w~}Wu~X{|w~|m{" + "}w~|dv~|h{|v~_{}x~}x{}s~}__~|dv~t{}w~t{|w~}\\{}n~}Y{|}e~}f{|`~b{|w~}l{}w~|\\v~w{|v~T{|u~R{}w~}U{}v~dv~}i{}u~u{|" + "v~u{|u~|g{}w~}hv~|iv~}r{|v~qv~|k{}v~e{}v~|c{~}I{|y~}w{}w~w{|y~}I{}~|U{}w~T{}~|k{}~|\\y~}w{}w~w{|y~| v~}P{}k~Z{|" + "v~S{|v~}x{|}v~}|y{|v~}^{|w~}u{|w~}Rw~|S{|u~}${}y~|v{}v~}|wy|}y~u{|y~}c{|x~}r{|x~}Q{|q{| W{}y~|uw~vy|v~u{|y~}-w~" + "|v{|w~Q{}w~K{|w~|I{|w~'{|w~|m{}w~|a{}m~}w{|x~} H{}x~|U{|x~}p{|x~}]{|q{|X{}x~|m{|w~_{}x~|m{|w~]{|}w~}q{|w~Pv~|Sv" + "~w{|v~Vv~w{|v~Vv~w{|v~Vv~w{|v~Vv~w{|v~W{|v~vv~^{|v~|v{|v~X{}v~J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z" + "{|v~g{|v~}g{}w~|y{}w~}pv~h{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|j{}v~e{}v~|g{|u~l{}v~}g{}v~kw~}{}v~g{|v~h{" + "}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}`{|v~|v{|v~|\\{}w~}s|y}t~}_w~}u{|v~|Y{|}k~|Z{|}k~|Z{|}k~|Z{|}k~|Z{|}k~|Z{|" + "}k~|d{|}k~|v{|m~}_{|k~|[{|m~}W{|m~}W{|m~}W{|m~}Rv~Lv~Lv~Lv~Q{|}l~\\w~}y{|o~}Y{|}n~}|X{|}n~}|X{|}n~}|X{|}n~}|X{|" + "}n~}|S{}u~S{|}n~}{|x~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|b{}w~|k{|w~}aw~}y{|o~}^{}w~|k{|w~} X{|w~}" + "t{}w~t{|w~}f{|w~}h{|w~}f{|w~}yy|p{|}y{|w~}f{|w~}ly|y{|w~}f{|w~}h{|w~}X{}x~}X{|v~kv~| Cv~|Lx~&{|i~|Y{|m~}bU~|e{}" + "h~\\{|u~}|xy|}u~^w~}kw~}Yr~}X{}w~}ov~d{}w~ lv~| lv~}R{}x~}vw~}^{}Z~f{|w~|v{|y~|`w~|s{|w~tw~|[{|v~|D{}x~}Nw~" + "}H{}w~|Q{|t~|N{}w~ c{|w~|Zv~|lv~|W{}w~}E{}w~}M{}w~}Z{|w~|w{}w~}\\{|w~}N{|v~={}w~}\\v~|nv~|b{}w~}l{}v~W{}v~M{}v" + "~G{|}p~|6{|o~}@u~e{|w~|\\{}w~e{|w~}v{}w~|]{}w~}m{|v~|cv~}N{}w~}g{|v~}d{}w~}L{}w~}Sv~}L{}w~}hv~|Y{}w~}M{}w~}W{}w" + "~}x{|u~}U{}w~}V{}w~|y{}w~q{|w~|yv~|h{}w~|y{|v~pv~hv~}e{|v~}d{}w~}mv~}gv~}e{|v~}f{}w~}mv~}a{|v~|D{|v~|Z{|v~h{}w~" + "}d{}w~}l{}w~}jv~|r{|w~x{|x~}qv~|e{|v~}y{}v~W{}v~vv~}N{|u~V{|w~}Kw~|G{|w~|\\{}w~}j{}v~ T{}i~}[w~}{}m~}X{}j~|]{}m" + "~}{|w~|]{}j~Y{}k~}Z{}m~}{|w~|`w~}{|l~Tv~Lv~Tw~}p{}v~}Vv~_w~}{|m~|x{|m~|fw~}{|m~}[{|j~|\\w~}{}m~}[{}m~}{|w~|Zw~}" + "{|q~|\\{}i~[{}i~]{|w~|m{}w~|b{|w~}k{}w~|hw~}q{|u~}q{}w~|g{}v~ov~}a{|w~}k{}w~|`d~Uw~}Lw~|M{|w~| Gy|l{|Z{}m~}x{|w" + "~`v~p{|v~Kv~Z{|m~|X{}j~}]w~}{|l~`t~|l{}w~|X{|u~}Y{|w~|m{}w~|e{}v~f{}w~}b{|v~}y{|q~}`_~|dv~t{}w~t{|w~}^{|k~}[{|c" + "~}f{|`~b{}w~}l{}w~}]{|w~}vv~|T{|v~}S{}w~}Uv~}d{}v~j{|u~t{|v~t{|u~g{}w~}hv~|iv~}r{|v~r{|v~|kv~}e{|v~}dx~}I{|}v{}" + "w~v{|}I{}x~|V{}w~U{}x~|m{}x~|\\{|v{}w~vy| {{v~}R{|i~Z{|v~R{|v~}|q~}|v~}\\v~u{}w~Qw~|R{|t~|'{|y~}v{}w~}p{|t{}y~|" + "d{}x~|r{|x~}Ry}r{|~ X{|y~}tw~sw~|u{}y~|.{|w~}x|}w~|Q{}w~L{|w~|G{|x~}({|w~|m{}w~|a{}m~}w{|x~} H{}x~|U{|w~p{|x~}]" + "{~|r{|}Y{}x~|mw~|_{}x~|m{}x~|[{|w~|r{}x~|Pv~|T{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{|w~}v{}w~|X{}w~}" + "v{}w~}_{}w~}u{|v~Xv~}J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~fu~g{}w~|y{|v~pv~hv~}e{|v~}jv~}e{|v~}" + "jv~}e{|v~}jv~}e{|v~}jv~}e{|v~}f{|u~n{}v~}fv~}l{}x~}y{|v~|h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}_{}v~vv~}[" + "{}w~}q{|}u~|`w~}uv~W{}i~}[{}i~}[{}i~}[{}i~}[{}i~}[{}i~}e{}i~}x{}k~}a{}j~|\\{}j~Y{}j~Y{}j~Y{}j~Sv~Lv~Lv~Lv~R{}j~" + "}]w~}{|m~}[{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|j~|T{}u~T{|f~`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|b{|w~}k{}w~|a" + "w~}{}m~}_{|w~}k{}w~| Xw~}s{}w~s{}w~fw~}f{}w~fw~}y{|y~|r{|y~}y{}w~fw~}l{|y~}y{}w~fw~}f{}w~X{}x~}Wv~|m{|v~ C{}w~}" + "[{|}|o{|y~|&g~|Y{}n~|b{}V~e{|g~}]v~}r{|v~}_w~}kw~}Z{|r~}X{|v~p{|w~}dw~} pw|v~l| {{v~}R{}x~}vw~}^{}Z~f{|w~|v" + "{|y~|`{}x~}s{|x~}u{}x~}Y{}v~|E{}x~}O{|w~}H{}w~|S{|}r~}|P{}w~ c{|w~Yv~|lv~|W{}w~}Ev~|N{|v~|Zw~}v{}w~}\\{|w~}|}v" + "~y}|X{}w~}>{|v~|\\{}w~}o{|v~a{}w~}l{}v~W{}v~M{}v~J{|}p~}|2{|}p~}|D{}v~|e{}x~}p{|}w~}|vx|uw~|f{}w~|v{|w~}]{}w~}m" + "{}v~c{|v~|N{}w~}fv~}d{}w~}L{}w~}T{|v~|L{}w~}hv~|Y{}w~}M{}w~}W{}w~}y{|u~}T{}w~}V{}w~|y{|w~|r{}x~}xv~|h{}w~|x{}w~" + "}qv~i{|v~|dv~}d{}w~}mv~}h{|v~|dv~}f{}w~}n{|v~|`u~D{|v~|Z{|v~h{}w~}d{|v~m{|v~|j{}w~}r{}x~}x{|w~qv~|d{}v~y|v~|Vv~" + "}x{}v~Mu~|V{|w~}K{}x~}G{|w~|]{}w~}h{|v~ U{}u~v}s~}\\w~}|v~w}t~}Zr~v}v~|^{}t~w}v~}|w~|^{}t~v}t~Zv}v~s}[{}t~w}v~}" + "|w~|`w~}|u~x}t~}Uv~Lv~Tw~}q{}v~|Uv~_w~}|v~x}s~y{|v~x}s~fw~}|u~x}t~}]{|s~x}s~|]w~}|v~w}t~}]{|t~w}v~}|w~|Zw~}|t~}" + "x~|]{}t~u}u~[{|x}v~q}]{|w~|m{}w~|av~kv~g{}w~q{}t~qv~e{}v~q{}v~_v~|m{|v~_d~Uw~}Lw~|M{|w~| J{|}v~}r{}v~}|_{}u~w}u" + "~|y{}x~}`v~q{|v~}K{}w~|\\{}w~}p~}Z{}s~w}u~}]w~}|u~x}t~}as~m{|v~W{}t~Y{|w~|m{}w~|ev~|f{|v~c{|u~}yn~a_~|dv~t{}w~t" + "{|w~}_{|t~w}t~}]{|b~}f{|`~b{}w~|l{}w~}]{}w~|v{|w~}S{|v~}T{}w~}Uv~|d{|v~|k{}v~|t{|v~s{}v~|h{}w~}hv~|i{}w~}r{|v~r" + "{|v~|l{|v~|dv~}ev~}C{}w~C{}v~|W{}w~V{}v~n{|v~|W{}w~ sv~}S{|s~}y~x}v~Z{|v~Q{|e~}[{|w~}w{|w~}Qw~|R{}r~|){}y~|w{|w" + "~}g{|y~}dw~q{}x~}S{}~}s{}y~ X{}y~|tw~s{}x~}u{|y~}-{}p~}P{}w~M{|w~|F{|x~}({|w~|m{}w~|a{}m~}w{|x~} H{}x~|Tw~p{}x~" + "|]y~}s{|y~Z{}x~|n{|x~}^{}x~|n{|w~Y{|x~}s{|x~}Ov~|T{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}X{}w~|v{|w~}Xv" + "~u{|v~_v~|u{|v~Y{|v~|J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{}v~g{}w~|x{}w~}qv~i{|v~|dv~}k{|v~|d" + "v~}k{|v~|dv~}k{|v~|dv~}k{|v~|dv~}e{|u~p{}v~}f{|v~|m{}w~wv~}h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}^v~}x{}v" + "~Z{}w~}o{}v~}`w~}v{|w~|W{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}\\{}u~v}s~}f{}u~v}s~}{s~w}t~}cr~v}" + "v~|]{}t~v}t~[{}t~v}t~[{}t~v}t~[{}t~v}t~Tv~Lv~Lv~Lv~S{}h~|^w~}|u~x}t~}]{|s~x}s~|\\{|s~x}s~|\\{|s~x}s~|\\{|s~x}s~" + "|\\{|s~x}s~|U{}u~U{|s~x}q~|`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|av~|m{|v~`w~}|v~w}t~}_v~|m{|v~ X{|w~" + "r{}w~rw~}h{|w~dw~}h{|w~y{|w~|t{|w~}yw~}h{|w~l{|w~}yw~}h{|w~dw~}Y{}x~}W{}w~}m{}w~} Xg|}v~s|e{|}x~}o{}y~&{}f~Y{|o" + "~}a{|V~f{|e~}_{|w~}p{|v~_w~}kw~}Z{}w~}v~Wv~|q{}w~}e{|w~ pc~} {{v~}R{|x}|v{|x}|^{}Z~f{|w~|v{|y~|`{|w~s{}x~}v" + "{|w~Wu~|F{|x}|O{}w~|H{|w~}U{|}w~|x~|w~}|R{}w~ c{}x~}Yv~|lv~|W{}w~}F{|v~N{|v~}Z{}w~u{}w~}\\{|k~}Z{}w~}x{|}u~y}|" + "L{}v~Zv~|pv~}a{|v~l{}v~|X{}v~M{}v~M{|}p~}|,{|}p~}|H{}v~|e{|w~q{|q~}y{}x~|v{|x~}fv~tv~]{}w~}n{}v~|c{|v~|N{}w~}f{" + "}v~d{}w~}L{}w~}T{}v~|L{}w~}hv~|Y{}w~}M{}w~}W{}w~}{|u~}S{}w~}V{}w~|xw~}rw~|xv~|h{}w~|x{|v~|rv~i{|v~|d{}v~d{}w~}n" + "{|v~|h{|v~|d{}v~f{}w~}n{}v~|`{}v~}|F{|v~|Z{|v~h{}w~}cv~|n{}v~i{}w~}rw~|ww~|s{|v~b{}q~}U{|v~|{|v~|N{}v~|U{|w~}K{" + "|w~G{|w~|^{}w~}f{|v~ V{}y~}|r{|u~|]r~|u{|u~}\\{}u~}s{|}y~|_{|u~|u{|}s~|_{}v~}|t{}v~}Vw~}T{|u~|u{|}s~|`r~|u{|u~|" + "Vv~Lv~Tw~}ru~|Tv~_r~|v{|}v~}{w~|u{}v~}gr~|u{|u~|^u~}|v{|}u~]r~|u{|u~|_{|u~|u{|}s~|Zr~}|v{|\\v~}|r{|}y~Wv~S{|w~|" + "m{}w~|a{}w~|m{|w~}g{}w~|rs~qw~}dv~}s{|v~|_{}w~}m{}w~|Nu~Uw~}Lw~|M{|w~| K{}r~u{|r~}a{|v~}|v{}v~yw~|`v~r{|u~|K{|w" + "~|]{}w~|xy|}t~}[u~}|s{|}~}]r~|u{|u~|ay|v~|n{}w~|X{|s~|Z{|w~|m{}w~|f{|v~dv~|e{|u~}|{|v~y|}v~}bx}u~q}u~x}|dv~t{}w" + "~t{|w~}_u~|u{|u~|_{|u~}|v{|}t~v}f{|q}u~p}b{}w~|l{|v~]v~tv~R{}v~}U{}w~}V{|v~|cv~}l{|v~}s{|v~s{|v~}h{}w~}hv~|i{}v" + "~r{|v~r{|v~|l{|v~|d{}v~fu~|C{}w~C{|u~|X{}w~W{}v~}m{}v~|X{}w~ sv~}T{|u~}|yy~}x{|}y~Z{|v~P{|g~}Y{}w~|xv~Pw~|T{|v~" + "}u~}*x~v{}w~ex~dw~qw~}U{|x~}t{}x~ Xx~sw~s{}x~}tx~,{|r~|O{}w~N{|w~|Dw~({|w~|m{}w~|a{|m~}w{|x~} H{}x~|T{}x~}qw~|]" + "x~}t{|x~|\\{}x~|nw~]{}x~|nw~|Xw~sw~|Ov~|Tv~tv~Xv~tv~Xv~tv~Xv~tv~Xv~tv~Y{|w~}tv~|a{|v~t{|v~Y{|v~|J{}w~}M{}w~}M{}" + "w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|x{|v~|rv~i{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{" + "}v~d{|u~r{}v~}e{|v~|n{}w~v{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}^{|v~|{|v~|Z{}w~}nu~`w~}v{}w~V{}y~}|r" + "{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|]{}y~}|r{|u~|g{}y~}|r{|o~}|u{|}v~}e{}u~}s{|}y~|^{}v~}|" + "t{}v~}]{}v~}|t{}v~}]{}v~}|t{}v~}]{}v~}|t{}v~}Uv~Lv~Lv~Lv~T{}u~}|v{|}v~}^r~|u{|u~|^u~}|v{|}u~\\u~}|v{|}u~\\u~}|v" + "{|}u~\\u~}|v{|}u~\\u~}|v{|}u~U{}u~Uu~}|u{}u~|_{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{}w~}m{}w~|`r~|u{" + "|u~|`{}w~}m{}w~| Xw~|r{}w~r{|w~hw~|d{|w~hw~|yu~|v{|u~y{|w~hw~|m{|u~y{|w~hw~|d{|w~Y{}x~}Vv~mv~| XZ~}g{}t~oy~}'{}" + "e~}Y{}p~_W~|fc~|`v~n{}w~|`w~}kw~}Zv~|}w~|X{}w~}qv~|e{}x~} q{|c~| {{v~} y{|x~}t{}x~}]{|w~}v{|y~|_w~|u{|w~|vw" + "~|Wt~ p{}w~|H{|v~V{}w~}yx~y{}w~}S{}w~ cw~|Z{|v~k{}w~}W{}w~}Fv~}Qy|u~}Z{|w~|u{}w~}\\{|i~|\\v~|y{}p~}|Nv~}Z{|v~|" + "s{|v~}`{|v~lu~|X{}v~M{}v~P{|}p~}|b{|Z~}b{|}p~}|L{}v~}d{}x~|r{|n~{}x~|uw~|h{}w~}t{}w~|^{}w~}q{|}u~}b{}v~M{}w~}f{" + "}v~d{}w~}L{}w~}T{}v~K{}w~}hv~|Y{}w~}M{}w~}W{}w~}|u~}R{}w~}V{}w~|x{|w~s{}w~wv~|h{}w~|w{}w~}rv~i{}v~c{}v~d{}w~}n{" + "}v~|h{}v~c{}v~f{}w~}o{|u~_{|t~}|H{|v~|Z{|v~h{}w~}c{}v~nv~}i{|v~s{|w~|w{}x~}s{}w~}b{|q~S{}v~|v~}N{}v~}T{|w~}K{|w" + "~|H{|w~| s{}|m{}w~}]t~}q{}v~|^{}v~}ny|_u~q{}t~|`{|v~|q{|v~|Ww~}Tu~q{|t~|`t~}r{|v~}Vv~Lv~Tw~}t{|u~Rv~_t~}r{}v~}" + "y~}r{}v~gt~}r{|v~}_{}v~|r{|v~}^s~q{}v~_{}v~|r{}t~|Zs~T{|w~}m{|Wv~S{|w~|m{}w~|a{|w~}mv~|g{|w~}s{|s~|s{|w~|d{|v~|" + "u{|v~}]v~mv~N{}v~Tw~}Lw~|M{|w~| L{}p~w{|p~}bv~}s{}w~y|w~_v~wx|}t~}J{|w~}^{}w~r{}u~|]{|v~|Ot~}r{|v~}_{|v~nv~W{}s" + "~}Z{|w~|m{}w~|f{}w~}d{}w~}eu~}x{|w~|x{}v~|`{|w~}q{|w~}`v~t{}w~t{|w~}`{}v~q{}v~_u~}r{|v~}V{|w~}Wv~|l{|v~^{}w~}t{" + "}w~|R{}v~}V{}w~}V{|v~bv~}l{|v~|s{|v~r{}v~h{}w~}hv~|i{}v~r{|v~r{}v~k{}v~c{}v~gu~|B{}w~B{|u~|Y{}w~X{}v~}k{}v~|Y{}" + "w~ sv~}Tu~|wy~}u{|Z{|v~O{|u~}|x{|}v~}_{|p~}y{|p~}Ww~|Tw~}y{|t~|,y~}vw~|e{}y~dw~|s{}w~}V{|w~}u{}w~ Xy~}sw~s{}x~}" + "t{}y~*y}x~}|[m|}w~l|^{}w~C{|x~}({|w~|m{}w~|`m~}w{|x~} H{}x~|T{|w~|s{}x~}\\w~}u{|w~|]{}x~|o{}x~}]{}x~|o{}x~}Ww~t" + "{}x~}Nv~|U{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~}t{}w~|Z{}w~|t{|w~}av~}t{|v~Y{}v~I{}w~}M{}w~}M{}w" + "~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|w{}w~}rv~i{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~c{|" + "u~t{}v~}d{}v~n{|w~|v{|v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}]{}v~|v~}Y{}w~}n{|v~|aw~}vv~V{}|m{}w~}]{}|m" + "{}w~}]{}|m{}w~}]{}|m{}w~}]{}|m{}w~}]{}|m{}w~}g{}|m{}r~|q{|v~|g{}v~}ny|_{|v~|q{|v~|_{|v~|q{|v~|_{|v~|q{|v~|_{|v~" + "|q{|v~|Vv~Lv~Lv~Lv~U{|v~}q{|v~|_t~}r{|v~}_{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}^{}v~|r{|v~}V{}u~V{}v~" + "|r{|v~}_{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|`v~mv~_s~q{}v~_v~mv~ X{|w~q{}w~q{}x~|j{|w~b{}x~|j{|w~wu~" + "|x{|u~|x{}x~|j{|w~m{|u~|x{}x~|j{|w~b{}x~|Z{}x~}V{}w~|o{|v~ WZ~}gx~}w~|q{}y~|({|c~}_v|{}r~u|d{}X~f{}b~|b{|w~}mw~" + "}`w~}kw~}[{|v~{}w~}X{|w~}r{|v~d{}x~| q{}c~ yv~} y{}x~}t{}x~}\\v~}w{|y~|_{}w~|vw~}v{|x~}X{|r~ qv~Fv~X{}w~}|x" + "x~x{|}w~}U{}w~ d{|w~Y{|v~k{}w~}W{}w~}G{}v~|Xm~}Y{}x~}t{}w~}\\{|h~}]v~y|l~}P{|v~|Y{|u~u|}v~}_{|v~|n{|u~|X{}v~M{" + "}v~R{|o~}|`{|Z~}_{|}p~}|P{}v~}cw~r{|l~}x~|u{|x~|hv~|t{|v~^{}e~}a{}v~M{}w~}f{|v~|e{}d~|_{}g~|d{}v~K{}^~|Y{}w~}M{" + "}w~}W{}p~|Q{}w~}V{}w~|ww~|tw~}wv~|h{}w~|vv~|sv~i{}v~c{|v~|e{}w~}o{|u~g{}v~c{|v~|g{}w~}p{|u~|^{}q~y}|M{|v~|Z{|v~" + "h{}w~}c{|v~|p{|v~gv~|t{|w~v{|x~}sv~|a{|s~|Rq~}N{}v~}S{|w~}Jw~}H{|w~| bv~|^t~ov~}^v~}P{|v~|p{}u~|`v~|o{|v~Ww~}U" + "{|v~o{}u~|`u~}p{|v~Vv~Lv~Tw~}u{|v~}Qv~_u~}pt~}pv~|hu~}p{|v~`{|v~|p{|v~|_t~ov~}a{|v~|p{}u~|Zt~S{}w~Gv~S{|w~|m{}w" + "~|`v~|o{|v~ev~s{|x~y}x~}s{}w~|c{}v~uv~}\\{}w~|o{|w~}O{}v~|U{|w~}Lw~|M{|w~} M{|x~}x|}w~}xv~}x|}x~|d{}v~qw~y}x~}_" + "v~x{}q~}I{|w~}_{|w~|q{|u~]{}w~|Nu~}p{|v~^{}w~|p{|w~}X{|q~Z{|w~|m{}w~|fv~|d{|v~f{|v~}w{}w~|wu~`{|w~}q{|w~}`v~t{}" + "w~t{|w~}a{|v~ov~}a{|v~}p{}v~|W{|w~}Wv~}l|}v~^v~|t{|v~Q{}v~}W{}w~}V{|v~b{}w~}l{}v~r{|v~r{}v~|i{}w~}hv~|i{|v~|s{|" + "v~r{}v~k{}v~xi~}y{|v~|iu~|A{}w~A{|u~|Z{}w~Y{}v~}i{}v~|Z{}w~ sv}|U{}v~|vy~}S{|v~O{|w~}s{|v~_{|o~|{o~}Ww~|U{}x~}v" + "{}u~}.{|y~|w{|w~d{|y~|e{}w~t{}v~}W{|v~|v{}w~}cY|8{|y~|sw~sw~|t{|y~| `{|Z~}_{}x~}C{|w~}({|w~|m{}w~|`{|n~}w{|x~} " + "H{}x~|Sv~|u{}w~|\\{}v~v{|v~|^{}x~|p{|w~\\{}x~|p{|w~W{|x~}u{|w~Mv}|Uv~|t{|v~Zv~|t{|v~Zv~|t{|v~Zv~|t{|v~Zv~|t{|v~" + "Zv~rv~b{|v~s{|c~l{}v~I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}Z{|v~ev~}h{}w~|vv~|sv~i{}v~c{|v~|l{}v~c{|v" + "~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|c{|u~v{}v~}c{}v~o{|w~|u{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}\\q~" + "}X{}w~}mv~}aw~}vv~Ev~|Mv~|Mv~|Mv~|Mv~|Mv~|Ws~|o{}w~}gv~}Ov~|o{|v~_v~|o{|v~_v~|o{|v~_v~|o{|v~Vv~Lv~Lv~Lv~Uv~}o{}" + "w~}_u~}p{|v~`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|`{|v~|p{|v~|Wt|W{|v~|q{}u~|`{|w~|m{}w~|a{|w~|m{}w~|" + "a{|w~|m{}w~|a{|w~|m{}w~|`{}w~|o{|w~}_t~ov~}`{}w~|o{|w~} X{}x~}q{}w~q{|x~}j{}x~}b{|x~}j{}x~}vu~|yu~|w{|x~}j{}x~}" + "mu~|w{|x~}j{}x~}b{|x~}Z{}x~}V{|v~o{}w~} WZ~}g{}|yw~}qx~'a~|c{|}t~}k~}|fY~}g{}`~b{|w~|m{}w~`w~}kw~}[{|w~}{|v~Wv~" + "r{}w~}dw~| lv~| kv~| yw~|tw~|\\{}v~}|y{|y~|^v~}y|}v~uw~X{|p~ rv~Fv~Xw~|vx~v{|w~U{}w~ d{}x~}Y{|v~k{}w~}W{}w" + "~}H{|v~}Wo~}|Y{|w~|t{}w~}\\{|v~x}|x}s~}^v~|j~}Q{}w~}V{}l~}]v~}n{}u~}X{}v~M{|v}U{|}p~}|]{|Z~}\\{}o~|S{}v~}c{|x~}" + "rv~}|w{|}t~|tx~}i{|v~rv~|_{}h~}|_v~}M{}w~}f{|v~|e{}d~|_{}g~|dv~}K{}^~|Y{}w~}M{}w~}W{}q~|P{}w~}V{}w~|w{}w~u{|w~|" + "wv~|h{}w~|v{}w~}sv~iv~}c{|v~|e{}w~}p{|u~|gv~}c{|v~|g{}w~}sy|}u~}\\{}m~}|Q{|v~|Z{|v~h{}w~}bv~}p{}w~}g{}w~}t{}x~}" + "v{|w~sv~|`{}u~}Q{|r~|O{|u~R{|w~}J{}w~H{|w~| b{|w~}^u~|o{|v~_{}v~Ov~}nu~|a{}w~}m{}w~|Xw~}Uv~|nu~|`u~nv~|Wv~Lv~T" + "w~}v{}v~}Pv~_u~o{}u~|p{}w~}hu~nv~|a{}w~}n{}w~}_u~|o{|v~a{}w~}nu~|Zu~|S{}w~Gv~S{|w~|m{}w~|`{}w~}o{}w~}e{}w~s{}x~" + "}|w~sv~a{}v~w{}v~[{|w~}ov~|P{}v~|T{|w~}Lw~|M{|w~}:{|4x~|v{|w~}{}x~}u{}x~dv~}q{}s~|_v~x{}r~}S{|y}~y}|w{|w~}_w~}o" + "{|v~}^{}w~Mu~nv~|_{|w~}pv~|X{}w~}v~|[{|w~|m{}w~|g{|v~bv~|g{}v~v{}w~v{|v~|a{|w~}q{|w~}`v~t{}w~t{|w~}a{}w~|o{|v~a" + "{}v~nv~}W{|w~}W`~_{|v~rv~|Q{}v~|X{}w~}V{|v~b{}w~}lu~r{|v~r{|v~|i{}w~}hv~|hv~}s{|v~rv~}kv~}xi~}y{|v~|ju~|@{}w~@{" + "|u~|[{}w~Z{}v~}g{}v~|[{}w~ Gv~}uy~}S{|v~Ow~}q{|w~|`{|n~}o~}Ww~|Uw~|t{}u~|0{|y~|w{|x~}d{|y~|e{|v~}w|t~}X{|v~|vv~" + "}c{|Z~}8{|y~|sw~t{}w~s{|y~| `{|Z~}`{}x~}M{|~}|v{|}v~'{|w~|m{}w~|_{}o~}w{|x~}Vv}| s{}x~|S{|v~}|{y|}w~}Z{}v~|w{|v" + "~}_{}x~|pw~|o{}w~m{}x~|p{}x~|vy|}w~y}|g{|w~|u{}x~|o{}w~3{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{|v~rv~|\\{}w~}" + "r{}w~|c{}w~}s{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w~|v{}w~}sv~iv~}c{|v~|lv~}c{|" + "v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|b{|u~x{}v~}bv~}p{|w~}t{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}\\{|r~|" + "X{}w~}mv~}aw~}v{}w~}F{|w~}M{|w~}M{|w~}M{|w~}M{|w~}M{|w~}W{|u~}m{}w~h{}v~O{}w~}m{}w~|a{}w~}m{}w~|a{}w~}m{}w~|a{}" + "w~}m{}w~|Wv~Lv~Lv~Lv~V{}v~n{|v~_u~nv~|a{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~},{}w~}q{}t~}`" + "{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|`{|w~}ov~|_u~|o{|v~`{|w~}ov~| X{}x~|q{}w~q{|w~j{}x~|b{|w~j{}x~|u" + "u~|u~|v{|w~j{}x~|nu~|v{|w~j{}x~|b{|w~Zw~}Uv~|q{|v~ VZ~}c{}w~r{|y~}({}`~d{}^~|h{|Z~g{|_~}c{}w~l{|w~`w~}kw~}[{}w~" + "|yv~|X{}w~|sv~|dV~} 2v~| k{}w~| {{|w~t{|w~Zs~y}y~|^{|o~|v{}x~}rx|e{|v~y}u~n{|w~},{|v~Fv~|Y{|~}tx~t{}~|U{}w~ " + " dw~|Y{|v~k{}w~}W{}w~}Hu~Vp~}|Y{|w~}s{}w~}\\{|~}|q{}t~|`{|q~}|xy|t~|Rv~|U{|}p~|[{}v~|ot~} V{|}p~}|Z{|Z~}Z{|}p~}" + "|W{}v~|b{}x~|s{}w~|s{|u~|tw~i{}w~}r{}w~}_{}g~}|`v~}M{}w~}f{|v~|e{}d~|_{}g~|dv~}K{}^~|Y{}w~}M{}w~}W{}q~O{}w~}V{}" + "w~|w{|w~|v{}w~vv~|h{}w~|uv~|tv~iv~}c{|v~|e{}w~}sy|s~fv~}c{|v~|g{}f~}Z{}k~}S{|v~|Z{|v~h{}w~}b{|v~pv~|g{}w~}tw~|u" + "w~|u{|v~_{}u~O{}t~|O{|u~|R{|w~}J{|w~|I{|w~| aw~}^v~}m{}w~}`v~|P{|v~m{}v~|av~l{|w~}Xw~}V{|v~m{|v~|`v~}n{}w~|Wv~" + "Lv~Tw~}w{}v~}Ov~_v~}o{|v~}o{|w~}hv~}n{}w~|av~|n{|v~|`u~mv~|bv~m{}v~|Zv~}R{}w~Gv~S{|w~|m{}w~|`{|v~ov~d{}w~|tw~|{" + "w~|u{|w~}`v~}y{|v~|Z{}w~|q{|v~P{}v~|Sv~|Lw~|Lv~|W{|y}w~}|iy}5{|y~}sw~|x~}s{}y~|f{|v~|ps~^v~x{}q~}|W{|r~|y{|w~}`" + "{}w~m{}v~^{}w~Mv~}n{}w~|^{}w~q{|v~Wv~y|w~}[{|w~|m{}w~|g{}v~b{}w~}h{|v~|v{}w~u{}w~}a{|w~}q{|w~}`v~t{}w~t{|w~}av~" + "mv~|c{|v~|n{|v~W{|w~}W`~_{}w~}r{}w~}Q{|v~}X{}w~}V{|v~b{}w~}lv~}r{|v~r{|v~|i{}w~}hv~|h{}v~s{|v~s{|v~|kv~}xi~}y{|" + "v~|ku~|?{}w~?{|u~|\\{}w~[{}v~}e{}v~|\\{}w~ H{}v~ty~}S{|v~P{|w~o{}w~_s|}r~s|Vw~|V{|w~r{|u~0{|y~v{}x~}d{|y~|d{}o~" + "|x~}Y{}v~v{|v~|b{|Z~}8{|y~rw~u}v~|s{|y~| `{|Z~}a{}l~|X{|m~|'{|w~|m{}w~|^o~}w{|x~}W{|v~| xm~}W{|n~}X{|v~|vv~}e{}" + "n~}v{}x~}o{|v~m{}x~|q{|w~w{|o~|t{|~}y|w{|}v~u{|x~}o{|v~3{}w~}r{}w~}\\{}w~}r{}w~}\\{}w~}r{}w~}\\{}w~}r{}w~}\\{}w" + "~}r{}w~}\\v~|r{|w~}cv~|s{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w~|uv~|tv~iv~}c{|v" + "~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|a{|u~|}v~}av~}pw~}s{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}[" + "{}t~|W{}w~}mv~}aw~}v{}v~|Fw~}Lw~}Lw~}Lw~}Lw~}Lw~}Vu~l{|w~|iv~|Ov~l{|w~}av~l{|w~}av~l{|w~}av~l{|w~}Wv~Lv~Lv~Lv~V" + "v~|mv~|`v~}n{}w~|av~|n{|v~|av~|n{|v~|av~|n{|v~|av~|n{|v~|av~|n{|v~|-v~|r{|x~}v~`{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{" + "}w~|a{|w~|m{}w~|_{}w~|q{|v~^u~mv~|`{}w~|q{|v~ Ww~p{}w~pw~jw~yd|yw~jw~t{|p~|tw~jw~nu~|tw~jw~pv~}qw~Zw~|U{}w~}q{}" + "w~} F{}w~}W{|w~|s{}y~|){|_~}f{}\\~|h{}\\~|g{}^~c{}w~l{|w~|aw~}kw~}[v~x{}w~}X{|w~}t{|v~cV~} 2v~| k{}w~| {{|x~" + "}t{|x~}Z{|o~}y|`{|}r~|v{|w~t{}u~}|hv~}y{}u~o{|w~|,{|v~F{}w~|X{|sx~s{|T{}w~ e{|w~X{|v~k{}w~}W{}w~}Iu~|Vm~|[{}w~" + "r{}w~}L{}u~`{|r~|s{|u~S{}v~V{|}m~}|\\u~p{}t~} Y{|}p~}|VY|W{|}p~}|[{|v~|aw~rw~}q{|v~|t{}x~iv~q{|v~_{}e~}av~}M{}w" + "~}f{|v~|e{}d~|_{}g~|dv~}m{}n~|h{}^~|Y{}w~}M{}w~}W{}q~}P{}w~}V{}w~|vw~}vw~}vv~|h{}w~|u{}v~tv~iv~}bv~|e{}e~|fv~}b" + "v~|g{}g~}X{|}k~}U{|v~|Z{|v~h{}w~}av~|r{|v~f{|v~u{|w~|u{}x~}u{}w~}`{|t~|O{}v~}Nu~|Q{|w~}Iw~}I{|w~| a{}w~^v~|m{|" + "w~}a{|v~O{|w~}lv~|b{|w~}kv~Xw~}V{|w~}lv~|`v~|n{|w~}Wv~Lv~Tw~}x{}v~|Nv~_v~|nv~|nv~hv~|n{|w~}b{|v~lv~|`v~}m{|w~}c" + "{|w~}m{|v~|Zv~|R{}w~|Hv~S{|w~|m{}w~|_{}w~|q{|w~}d{|w~}u{|w~y{}x~|u{|w~|`{|v~y|v~}Y{|w~}q{}w~|Q{|v~}S{}v~Kw~|L{}" + "w~}Y{|p~}|n{|y~}5{}y~r{|t~qy~}f{}v~ot~}^v~x{}o~}Y{}p~|{|w~|`w~}lv~|_{|w~}Nv~|n{|w~}^{|w~|r{}w~|X{}w~}yv~[{|w~|m" + "{}w~|gv~}b{}v~h{|v~u{}w~u{|v~a{|w~}q{|w~}`v~t{}w~t{|w~}b{|w~}m{|w~}c{|v~lv~|X{|w~}W`~_v~|r{|v~Qu~W{}w~}V{|v~b{}" + "w~}lv~}r{|v~qv~|i{}w~}hv~|h{|v~|t{|v~s{}v~jv~}xi~}xv~|lu~[|]{}w~\\\\|u~|]{}w~\\{}v~}c|u~|]{}w~ H{}w~}ty~}X{}g~|" + "[{}x~}nw~Vs~|Nw~|V{}x~}pv~}1{}y~v{}x~}d{|y~}c{}r~}{|x~}Z{}w~}v{|v~|a{|Z~}8{}y~rn~}q{|y~} `{|Z~}a{}l~|X{|o~}|&{|" + "w~|m{}w~|]{}q~}w{|x~}W{|v~| xm~}V{|}q~|V{|v~|v{}w~}fm~}vw~o{|u~rm~}vw~|w{}n~|u{|m~|uw~|p{|u~3v~q{|v~\\v~q{|v~\\" + "v~q{|v~\\v~q{|v~\\v~q{|v~]{|v~pv~|e{}w~}r{|c~lv~}I{}d~|`{}d~|`{}d~|`{}d~|W{}w~}M{}w~}M{}w~}M{}w~}_{}i~}nv~}h{}w" + "~|u{}v~tv~iv~}bv~|lv~}bv~|lv~}bv~|lv~}bv~|lv~}bv~|`{|p~}`v~}q{}x~}qv~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}" + "w~}Z{}v~}V{}w~}mv~}aw~}uu~}G{}w~L{}w~L{}w~L{}w~L{}w~L{}w~V{}w~}kw~}j{|v~O{|w~}kv~b{|w~}kv~b{|w~}kv~b{|w~}kv~Wv~" + "Lv~Lv~Lv~W{|v~l{}w~}`v~|n{|w~}b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|.{|v~r{|w~{}w~|a{|w~|m{}w~|a{|w~|m{}" + "w~|a{|w~|m{}w~|a{|w~|m{}w~|_{|w~}q{}w~|^v~}m{|w~}`{|w~}q{}w~| Ww~yd~|{w~jw~yd~|{w~jw~s{|r~|sw~jw~ou~|sw~jw~pv~}" + "qw~Zw~|U{|v~qv~| G{}w~}Uw~}sx~({}^~g{}Z~g]~}f{|_~|cw~}l{|w~|aw~}kw~}\\{|v~x{|v~Wv~t{}w~}cV~} 2v~| k{}w~| {{}" + "x~}t{}x~}Y{|}m~}`{|}w~}|tw~|v{|q~}j{}v~w{}u~p{}w~|,{|w~}F{}w~|Ox~Z{|Z~} t{}x~}X{|v~k{}w~}W{}w~}J{}v~|Ut|}t~}]{" + "|w~|r{}w~}K{}v~|a{|s~p{|v~}Tv~}W{}i~}]{}u~|t{|}s~} Z{|q~}| e{|}q~}\\v~}`x~}s{}w~ov~|t{}x~|k{|w~}p{}w~|`{}w~}p|}" + "t~|cv~}M{}w~}f{|v~|e{}w~}i|^{}w~}l|cv~}m{}n~|h{}w~}h|v~|Y{}w~}M{}w~}W{}w~}u~}Q{}w~}V{}w~|v{}w~w{|w~uv~|h{}w~|tv" + "~|uv~iv~}c{|v~|e{}f~|ev~}c{|v~|g{}i~}S{|}m~}V{|v~|Z{|v~h{}w~}a{}w~}rv~}ev~|v{|w~t{|w~uv~|`r~O{|v~|O{}v~}P{|w~}I" + "{}w~I{|w~| a{}w~^v~|lv~a{}w~}O{}w~|lv~|b{|w~|k{}w~Xw~}V{}w~|lv~|`v~m{|w~}Wv~Lv~Tw~}yu~|Mv~_v~mv~mv~hv~m{|w~}b{" + "}w~}l{}w~}`v~|m{|v~c{}w~|lv~|Zv~Q{}v~|Iv~S{|w~|m{}w~|_{|w~}q{}w~|cv~u{}x~}y{}x~}u{}w~^{}q~}Wv~qv~Q{|v~}Uy|}v~|K" + "w~|L{|u~}|^{|k~}|s{|}x~}5y~}q{}v~|q{}y~f{}w~}o{}u~|^v~ty|}s~[{|u~y}v~y|w~|a{|w~}l{}w~}^{}w~|Ov~m{|w~}]w~}rv~Wv~" + "|y{}w~}\\{|w~|m{}w~|gv~|b{|v~h{}w~}u{}w~tv~a{|w~}q{|w~}`v~t{}w~t{|w~}b{}w~|m{|v~c{}w~}l{}w~}X{|w~}W`~`{|w~}pv~|" + "S{}v~|W{}w~}V{|v~bv~}lv~}r{|v~r{|v~|i{}w~}hv~|gu~t{|v~t{|v~}jv~}xh|y{|v~|mT~]{}w~]T~|^{}w~]{}U~|^{}w~ Hv~|ty~}X" + "{}g~|[w~|nw~|W{}u~}Mw~|V{}w~ov~1{|y~v{}x~}d{|y~|ay}x~y}ww|[{}w~}v{|v~|`{|Z~}8{|y~ro~o{|y~| Q{}w~R{}l~|V{|y}v~y}" + "|${|w~|m{}w~|\\{|}s~}w{|x~}W{|v~| xm~}T{|y}w~}|S{|v~|v{}w~}gm~}w{}x~}oy~y}x~rm~}w{}x~}v{}~}y|w{|v~u{|o~}t{}x~}o", + "t~^v|V{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{|w~}p{}w~|^{}w~}p{}w~}ev~|r{|v~h|lv~}I{}w~}i|_{}w~}i|_{}" + "w~}i|_{}w~}i|V{}w~}M{}w~}M{}w~}M{}w~}_v}u~r}nv~}h{}w~|tv~|uv~iv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|" + "_{|r~}_v~}r{}w~q{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}mv~}aw~}u{|t~|I{}w~L{}w~L{}w~L{}w~" + "L{}w~L{}w~V{}w~|kv~j{}w~}O{|w~|k{}w~b{|w~|k{}w~b{|w~|k{}w~b{|w~|k{}w~Wv~Lv~Lv~Lv~W{}w~}l{|w~}`v~m{|w~}b{}w~}l{}" + "w~}b{}w~}l{}w~}b{}w~}l{}w~}b{}w~}l{}w~}b{}w~}l{}w~}eY|f{}w~}rw~y{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|" + "m{}w~|^v~qv~]v~|m{|v~_v~qv~ Vw~yd~|{}x~|kw~yd~|{}x~|kw~r{|t~|r{}x~|kw~pu~|r{}x~|kw~pv~}q{}x~|[w~|T{}w~|s{|v~ G{" + "}v~T{}w~t{|y~}(]~|i{|Y~}h{|_~}d{|a~}bw~}kw~|aw~}kw~}\\{}w~}wv~|Xv~|u{}w~|cV~} 2v~| k{}w~| {{w~|tw~|W{|}m~}T{" + "}x~}v{|o~}l{|v~|v{}u~q{}w~+{|w~}F{}w~|Ox~Z{|Z~}+m| ww~|X{|v~k{}w~}W{}w~}K{}v~}K{|}v~}^w~}q{}w~}Ju~a{|t~|o{}v~U{" + "|v~|X{}u~}|wy|u~}]t~}y|{y|}q~} Z{|t~}| _{|}t~}\\v~`{|x~}s{}x~}o{|w~|t{}x~|kv~|p{|w~}`{}w~}n{|u~cv~}M{}w~}f{|v~|" + "e{}w~}L{}w~}Tv~}m{}n~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}|u~}R{}w~}V{}w~|v{|w~|x{}x~}uv~|h{}w~|t{|v~uv~iv~}c{|v~|e{}h~" + "}cv~}c{|v~|g{}h~}Qy|y}p~W{|v~|Z{|v~h{}w~}a{|v~s{|v~|e{}w~}v{}x~}t{|w~uv~|a{}r~}P{|v~|P{}v~}O{|w~}I{|w~|J{|w~| " + "n{|y}l~^v~kv~a{}w~|Ov~|l{}w~|b{}w~|k{}w~|Yw~}Vv~|l{}w~|`v~m{|w~}Wv~Lv~Tw~}|u~Kv~_v~mv~mv~hv~m{|w~}b{}w~|l{|v~`v" + "~kv~c{}w~|l{}w~|Zv~Pu~}|Kv~S{|w~|m{}w~|^v~qv~b{}w~u{}x~|y{|w~uv~]{}r~V{}w~|s{|w~}R{|v~}X{|q~}Jw~|K{|q~}c{}g~}w|" + "}u~}5y~}pw~}p{}y~fv~|o{}u~]v~p{|t~\\v~}w{|w~}w~|a{}w~|l{|w~}]{}w~}y|Rv~m{|w~}]{}w~s{}w~}X{}w~}x{|v~\\{|w~|m{}w~" + "|h{|v~|b{|v~|i{}w~|u{}w~tv~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~kv~c{}w~|l{|w~}X{|w~}Wv~jv~`v~|p{}w~}T{}v~|V{}w~}V{|v~" + "|cv~|lv~}r{|v~r{|v~|i{}w~}hv~|g{}v~}u{|v~tu~|jv~}c{|v~|n{|T~]{}w~]T~}^{}w~]T~}^{}w~ I{|v~sy~}X{}g~|[w~m{}x~|Vu~" + "|#{|w~|p{|w~|2{|y~|w{|x~}d{|y~|3v~}v{}v~|Aw~}8{|y~|sw~x{|w~}p{|y~| Q{}w~ p{|w~|m{}w~|Y{|}v~}w{|x~}W{|v~| jv~}" + "v{}v~|W{|w~o{}y~{}x~r{}n~}x{|w~uy|rw~|ty|t}|s{|w~o{}y~|}x~^{}w~|Wv~|p{|w~}^v~|p{|w~}^v~|p{|w~}^v~|p{|w~}^v~|p{|" + "w~}^v~|p{|v~f{|v~q{|v~Yv~}I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~ev~}h{}w~|t{|v~uv~iv~}c{|v~|lv~}" + "c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|^{|t~}^v~}s{}w~p{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w" + "~}n{|v~|aw~}t{}t~}W{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~Y{|y}l~c{|y}l~j{}w~j{}w~|O{}w~|k{}w~|c{}w~|k{}w~|c{}w~|k{}" + "w~|c{}w~|k{}w~|Xv~Lv~Lv~Lv~W{}w~|l{|v~`v~m{|w~}b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~b{}w~|l{|v~f{|Z~}f{}" + "w~|s{}x~|y{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|^{}w~|s{|w~}]v~kv~_{}w~|s{|w~} Vw~yd~|{}x~|kw~yd" + "~|{}x~|kw~qt~|r{}x~|kw~qu~|q{}x~|kw~pv~}q{}x~|[w~|T{|w~}s{}w~} H{|v~|T{|w~|u{}y~({|]~}i{}X~g{|`~b{}b~aw~}kw~}aw" + "~}kw~}\\v~|w{}w~}X{}w~}uv~bw~}Z| 5x|v~}p| v{}w~| {|w~t{|w~S{|}n~|Vw~uv~|y{|}w~}m{}w~}t{}u~rw~}+{|w~}F{}w~|Ox" + "~Z{|Z~},{|m~ x{|w~|X{|v~k{}w~}W{}w~}L{}v~}H{}v~}`{}w~p{}w~}J{}v~`t~n{|v~|V{}v~X{}v~}q{}v~}^{|j~|v~| Z{|t~| ]{|}" + "u~}]{|w~}`{|x~|sw~|o{|w~|t{}x~|l{|v~nv~`{}w~}lv~}dv~}M{}w~}f{|v~|e{}w~}L{}w~}Tv~}m{}n~|h{}w~}hv~|Y{}w~}M{}w~}W{" + "}w~}{|t~S{}w~}V{}w~|u{}x~}y{|w~|uv~|h{}w~|sv~|vv~iv~}c{|v~|e{}k~}|av~}c{|v~|g{}w~}t|y}u~}M{|}s~}X{|v~|Z{|v~h{}w" + "~}`v~}t{}v~d{}w~}vw~|sw~|w{|v~a{|v~}v~|Q{|v~|Q{|u~N{|w~}Hw~|J{|w~| p{}h~|_v~k{}w~|bv~|Ov~k{}w~|bv~j}v~|Yw~}Vv~" + "k{}w~|`w~}m{|w~}Wv~Lv~Tq~}Jv~_w~}mv~mv~hw~}m{|w~}bv~|l{|v~`v~kv~|dv~k{}w~|Zv~P{}r~}y|Pv~S{|w~|m{}w~|^{}w~|s{|w~" + "}b{|w~|vw~|xw~|w{|w~}\\s~|Uv~sv~|Ru~W{|s~}|Iw~|I{|}t~}d{|u~}w|}g~}5{|y~|p{|x~|p{}y~fv~|o{|v~}]v~n{}v~|^{}w~|ts~" + "`v~|l{|v~\\{}p~}Xw~}m{|w~}]{|w~|tv~|Xv~|wv~|]{|w~|m{}w~|h{|v~|q{}x~}q{|v~|iv~|u{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{" + "|w~}bv~kv~|dv~|l{|v~X{|w~}Wv~|l{|v~a{|v~nv~U{|v~}U{}w~}Uv~}d{|v~|l{}v~r{|v~r{|v~|i{}w~}hv~|fu~|v{|v~u{}v~}iv~}c" + "{|v~|n{|T~]{}w~]T~}^{}w~]T~}^{}w~ rw|V{|w~}sy~}X{|w}u~q}Zw~m{}x~|V{}v~\"{|v~ow~|2{|y~|w{|w~d{|y~|4{}w~}v{|v~?w~" + "}8{|y~|sw~vw~}q{|y~| Q{}w~ p{|w~|m{}w~|Ux~}w{|x~}W{|v~| i{}w~|v{|v~Ww~|p{|y~|{}x~`{}x~|j{|x~}bw~|p{|y~}{}x~^{" + "}w~|X{|v~nv~_{|v~nv~_{|v~nv~_{|v~nv~_{|v~nv~_{|w~}nv~|g{}w~}q{|v~Yv~}I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}" + "M{}w~}Z{|v~ev~}h{}w~|sv~|vv~iv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|lv~}c{|v~|]{}u~|^v~}t{|w~|p{|v~|i{|v~h{}w~}" + "f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}n{}v~|aw~}s{|s~|[{}h~|\\{}h~|\\{}h~|\\{}h~|\\{}h~|\\{}h~|f{}h~j}v~" + "jv~|Ov~j}v~|cv~j}v~|cv~j}v~|cv~j}v~|Xv~Lv~Lv~Lv~Wv~|l{|v~`w~}m{|w~}bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v" + "~f{|Z~}fv~|t{}x~|wv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|]v~sv~|]v~kv~|_v~sv~| Vw~yd~|{w~jw~yd~|{w~j" + "w~rr~|sw~jw~ru~|pw~jw~pv~}qw~Zw~|Sv~sv~ H{|v~|Rw~}uy~}({|]~}i{}X~|g{}b~|a{}d~|aw~}kw~}aw~}kw~}]{|v~v{|v~X{|v~v{" + "|w~}b{}x~} pf~ v{|w~ {{|w~t{|x~}P{|y~}r~W{}x~|v{}w~u{}w~mv~r{}u~t{|w~|+{|v~F{}w~|Ox~Z{|Z~},{|m~ x{}w~W{|v~k" + "{}w~}W{}w~}M{}v~}F{}v~a{|w~|p{}w~}Iv~|au~}mv~}Vv~|Y{|v~}o{|v~|]{}m~|{v~| Z{|r~}| c{|}r~}]{|w~}`{|x~|sw~|nw~|t{}" + "x~k{}w~}n{}w~}a{}w~}l{|v~|e{}v~M{}w~}f{}v~d{}w~}L{}w~}T{}v~mr|v~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}y{|t~T{}w~}V{}w~|u" + "{|w~y{}w~tv~|h{}w~|s{|v~vv~i{}v~c{|v~|e{}w~}r|]{}v~c{|v~|g{}w~}q{}v~}K{|t~|Y{|v~|Z{|v~h{}w~}`{}v~tv~|d{|v~w{|w~" + "|s{}x~}w{}w~}av~}{}v~Q{|v~|R{|u~M{|w~}H{}x~}J{|w~| r{|f~|_w~}k{}w~|bv~|Ov~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~" + "Lv~Tq~Iv~_w~}mv~mv~hw~}m{|w~}bv~jv~`v~k{}w~|dv~k{}w~|Zw~}O{}o~}|Sv~S{|w~|m{}w~|^{|w~}s{}w~|b{|w~}w{|w~w{}x~}w{|" + "w~|\\{|u~}T{}w~|u{|w~}Ru~V{|s~}|Iw~|J{|}s~}d{|w~|s{|}k~|3y~}p{|x~}p{}y~fv~mv~|]v~m{}v~_{|w~}rt~`v~jv~Z{}r~}Xw~}" + "m{|w~}\\w~}u{|w~}X{|w~}v{}w~}]{|w~|m{}w~|h{|v~|q{}x~}pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~k{}w~|dv~jv" + "~X{|w~}W{}w~|l{|v~a{}w~}n{}w~}W{|u~T{}w~}U{}w~}d{}v~k{}v~|s{|v~r{}v~h{}w~}hv~|f{|u~|w{|v~v{}u~h{}v~c{|v~|n{|T~]" + "{}w~]T~|^{}w~]{}U~}^{}w~ s{|w~V{|w~}sy~}S{|v~Pw~|nw~|V{|w~}!{}v~|q{}x~|1y~}vw~|e{}y~ci|]{}w~u{|w~|?w~}7y~}sw~v{" + "|w~|r{}y~ P{}w~ p{|w~|m{}w~|Ux~}w{|x~}W{|v~| Fi|U{|w~|u{}w~X{}x~}p{|y~}y{}x~a{|w~i{|x~}c{}x~}p{|y~}y{}x~^{}w~|" + "X{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~}n{}w~}`{}w~|n{}w~}h{|v~p{|v~Y{}v~I{}w~}M{}w~}M{}w~}M{}w~}" + "D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|s{|v~vv~i{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|l{}v~c{|v~|^{}s~|_" + "{}v~u{|w~|o{|v~|i{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{|v~|V{}w~}o{|u~`w~}q{}t~|^{|f~|^{|f~|^{|f~|^{|f~|" + "^{|f~|^{|f~|h{|P~jv~|O`~|c`~|c`~|c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~f{|Z~}fv~|u{}x~}" + "vv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|]{}w~|u{|w~}\\v~k{}w~|_{}w~|u{|w~} Uw~yq}w~r}yw~jw~yd|yw~jw~" + "sp~|tw~jw~su~|ow~jw~pv~}qw~Zw~|S{}w~}u{|w~} Hv~|Q{}w~|w{|y~|({|\\~iW~|f{}d~|_e~|`w~}kw~}aw~}kw~|]{}w~}uv~Wv~|w{" + "}w~|b{}x~} q{|g~| v{|w~({}Z~X{|y~|{|}u~}Y{|w~uw~|tw~}o{|w~}q{}u~u{}w~*{|v~F{}w~|*m|}w~l|,{|m~ xw~}W{|v~k{}w" + "~}W{}w~}N{}v~}Dv~|bw~}o{}w~}Iv~|au~|m{}w~}W{|v~X{}v~m{}v~\\{|p~}xv~| Y{}p~}| i{|}p~}|]{}w~}`{|x~|sw~mw~|t{}x~kv" + "~}n|}v~a{}w~}kv~}e{}v~M{}w~}f{}v~d{}w~}L{}w~}T{}v~dv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}x{|t~U{}w~}V{}w~|tw~|{w~}tv~|" + "h{}w~|rv~}wv~i{}v~c{}v~d{}w~}T{}v~c{}v~f{}w~}p{}v~|Ju~}Y{|v~|Z{|v~h{}w~}_v~|v{|v~bv~|x{|w~r{}w~wv~|b{}v~xv~}R{|" + "v~|Ru~|M{|w~}H{|w~J{|w~| s{|q~t}v~|_w~}k{}w~|bv~Nv~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tp~Jv~_w~}mv~mv~hw~}" + "m{|w~}bv~jv~`w~}k{}w~|dv~k{}w~|Zw~}N{|m~|Uv~S{|w~|m{}w~|]v~t{|v~`v~w{}x~}w{|x~}w{}w~[{|u~|T{|w~}u{}w~|S{}v~|V{|" + "x}t~}Jw~|K{|s~y}|d{|y~}n{|}p~}1y~}p{}w~p{}y~fv~mv~\\v~lv~|`{}w~|r{|v~}`v~jv~\\{|p~}Xw~}m{|w~}\\{}w~u{}w~|Xv~|v{" + "|v~]{|w~|m{}w~|h{|v~p{}w~pv~}iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bw~}k{}w~|dv~jv~X{|w~}W{}w~|l{|w~}av~|n{|v" + "~Wu~|T{}w~}U{}v~dv~}k{|v~}s{|v~s{|v~}h{}w~}hv~|e{}u~|x{|v~w{}u~|h{}v~c{}v~l{|u~}\\|]{}w~][|u~|]{}w~\\{}v~}c|u~}" + "]{}w~ s{|w~V{|w~}sy~}S{|v~P{}x~}o{|w~`{|a~}+u~|rw~|1y~}v{}w~ex~d{|j~}]{}w~}v{|v~|@w~}7y~}sw~u{}w~rx~ P{}w~ p{|" + "w~|m{}w~|Ux~}w{|x~} w{|j~}V{|v~|v{}w~}Xw~oy~}x{}x~aw~|i{|x~|cw~ox~x{}x~^{}w~|Xv~}n|}v~`v~}n|}v~`v~}n|}v~`v~}n|" + "}v~`v~}n|}v~a{|b~h{}v~p|}v~Y{}v~I{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{|v~|h{}w~|rv~}wv~i{}v~c{" + "}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~k{}v~c{}v~^{}q~|`{}v~v{|w~}n{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}Z{" + "|v~|V{}w~}p{|u~|`w~}p{|t~}`{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|_{|q~t}v~|i{|q~t}`~|kv~N`~|c`~|c`~|" + "c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~f{|Z~}fv~u{|x~}uv~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m" + "{}w~|a{|w~|m{}w~|]{|w~}u{}w~|\\w~}k{}w~|_{|w~}u{}w~| U{}x~|q{}w~q{|w~j{}x~|b{|w~j{}x~|uu~|u~|v{|w~j{}x~|uu~|o{|" + "w~j{}x~|qv}|r{|w~[{|w~|S{|v~uv~| TZ~}a{|w~}wx~'{|\\~iW~|ee~|^{|g~}_w~}kw~}aw~}kw~|]v~|u{}w~|X{}w~}wv~|b{|w~| " + " r{}g~ u{|w~({}Z~X{|y~|w{}v~|Zw~|v{|w~s{|w~o{|w~}p{}u~vw~})v~Fv~| w{}w~ x{|m~ y{|w~|Vv~|lv~|W{}w~}O{}v~}C{}w~}" + "c{|w~n|}w~}v|N{}w~}au~l{|v~Wv~}Xv~}m{|v~|[{|y}w~y}|x{|v~ V{|}p~}|XY|X{|}q~}|Z{}w~}`{|x~|sw~mw~|tw~l{|b~|b{}w~}k" + "{}v~e{|v~|N{}w~}fv~}d{}w~}L{}w~}T{|v~|ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}w{|t~V{}w~}V{}w~|t{}w~|w~|tv~|h{}w~|r{|v~" + "wv~i{|v~|d{}v~d{}w~}T{|v~|d{}v~f{}w~}o{}v~J{|u~Y{|v~|Z{|v~h{}w~}_{}w~}v{}w~}b{}w~}x{}x~}r{|w~wv~b{|v~|x{|v~|S{|" + "v~|S{}v~|L{|w~}Gw~|K{|w~| t{|u~}|q{}w~|_v~k{}w~|bv~Nv~k{}w~|b`~|Yw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tw~}|u~Kv~_w~}mv~" + "mv~hw~}m{|w~}bv~jv~`w~}k{}w~|dv~k{}w~|Zw~}L{|}o~}Vv~S{|w~|m{}w~|]{}w~}u{}w~}`{}w~|xw~|w{|w~wv~\\{|s~Sv~uv~S{}v~" + "|O{}v~}Kw~|L{|v~}|_{|~|j{|y}x~y}|/x~q{|v~}qx~fv~m{}x~}\\v~l{}w~|`v~pv~}`v~jv~]n~}Xw~}m{|w~}\\{|w~|vv~X{|v~t{}w~" + "|^{|w~|m{}w~|h{|v~p{}w~pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bw~}k{}w~|dv~jv~X{|w~}W{}w~}l{}w~}b{|v~lv~|Y" + "{}v~|S{}w~}U{|v~}f{|v~|ju~|t{|v~s{}v~|h{}w~}hv~|dt~}y{|v~y{|t~|g{|v~|d{}v~k{|u~|?{}w~>u~|b{|v{}w~[{}v~|e{}v~}\\" + "{}w~ s{|w~V{|w~}sy~}S{|v~P{|w~o{}x~}`{|a~}+{|u~}|u{|w~0{}y~v{|w~}g{|y~}d{|j~}\\{}v~|w{|v~}Aw~}7{}y~sw~tw~}t{|y~" + "} P{}w~ p{|w~|m{}w~|Ux~}w{|x~} w{|j~}W{|v~|vv~}X{}x~|p{}y~|x{}x~b{}x~}hw~c{}x~}p{}y~|x{}x~^v~X{|b~|b{|b~|b{|b" + "~|b{|b~|b{|b~|b{}b~}id~Y{|v~|J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~f{}v~g{}w~|r{|v~wv~i{|v~|d{}v" + "~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~k{|v~|d{}v~_{}v~}u~|a{|v~|ww~}m{}v~h{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w~}f{|v~h{}w" + "~}Z{|v~|V{}w~}sy|s~_w~}n{}u~|b{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|`{|u~}|q{}w~|j{|u" + "~}|q{}a~|kv~N`~|c`~|c`~|c`~|Xv~Lv~Lv~Lv~Wv~jv~`w~}m{|w~}bv~jv~bv~jv~bv~jv~bv~jv~bv~jv~.v~v{|w~tv~a{|w~|m{}w~|a{" + "|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|\\v~uv~[w~}k{}w~|^v~uv~ T{}x~}q{}w~q{|x~}j{}x~}b{|x~}j{}x~}vu~|{|u~|w{|x~}j{}" + "x~}vu~|n{|x~}j{}x~}b{|x~}[{|w~Qv~|w{|v~ SZ~}`v~x{|y~}'{|]~}iW~|e{|g~}\\{}i~}^w~}kw~}aw~}l{|w~|^{|v~t{|w~}X{|v~x" + "{|v~`w~} m{|v~ jw|({}Z~X{|y~|v{}w~}[{}x~}u{}x~}s{|w~o{}w~}o{}u~x{|w~|)v~Fv~ v{}w~ g{}w~Uv~|lv~|W{}w~}P{}v~" + "}B{|v~c{|_~|O{}w~}a{}v~l{|v~X{|v~|Y{|v~|lv~|N{|v~ S{|}p~|[{|Z~}[{|}p~}|X{}w~}`{|x~|sw~|nw~|u{|x~}l{}b~}b{}w~}k{" + "|v~e{|v~}N{}w~}g{|v~}d{}w~}L{}w~}T{|v~}ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}v{|t~W{}w~}V{}w~|t{|r~sv~|h{}w~|q{}w~}xv" + "~i{|v~}dv~}d{}w~}T{|v~}dv~}f{}w~}nv~}J{}v~Y{|v~|Z{|v~|i{}w~}_{|v~vv~|b{}w~}xw~|qw~|y{|v~bv~}v{}v~S{|v~|T{}v~}K{" + "|w~}G{}x~}K{|w~| tv~}n{}w~|_v~kv~|bv~|Ov~k{}w~|bv~Bw~}Vv~k{}w~|`w~}m{|w~}Wv~Lv~Tw~}{|u~|Mv~_w~}mv~mv~hw~}m{|w~" + "}bv~|kv~`v~k{}w~|dv~k{}w~|Zw~}Iy|}q~Wv~S{|w~|m{}w~|]{|v~uv~_{|w~|xw~uw~|y{|w~}\\r~}T{|w~|w{}w~}T{}v~|M{|v~Kw~|L" + "{}w~} O{}y~|rt~|s{|y~}fv~|nw~}\\v~l{|w~}`w~}p{}w~|`v~|kv~^u~}|Qw~}m{|w~}[w~}w{}w~}X{}w~|t{|w~}^{|w~|m{}w~|h{|v~" + "pv~pv~|iv~t{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~}bv~k{}w~|dv~|l{|v~X{|w~}W{|w~}l{}w~|b{}w~}l{}w~}Z{|v~}R{}w~}T{}v" + "~f{}v~i{|u~t{|v~t{|u~g{}w~}hv~|cr~}v~}s~}f{|v~}dv~}j{|u~|@{}w~?u~|b{}~|w{}w~vy~a{}v~|g{}v~}b{}~|w{}w~vy} {{}w~|" + "W{|w~}sy~}S{|v~Ow~}q{|w~|`{|a~}){}u~}vw~}0{|y~}v{}w~}p{|t{}y~|d{|j~}[{|v~|vv~}Bw~}7{|y~}tw~t{|w~|u{}y~| P{}w~ " + "p{|w~|m{}w~|Ux~}w{|x~} w{|j~}X{}v~v{|v~}X{|w~p{|y~|w{}x~bw~h{}x~|d{|w~p{|y~}w{}x~^v~X{}b~}b{}b~}b{}b~}b{}b~}b{" + "}b~}b`~j{}d~Y{|v~}J{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~fv~}g{}w~|q{}w~}xv~i{|v~}dv~}k{|v~}dv~}k" + "{|v~}dv~}k{|v~}dv~}k{|v~}dv~}`{}v~|{|u~|b{|v~}x{}x~}lv~}h{|v~|i{}w~}f{|v~|i{}w~}f{|v~|i{}w~}f{|v~|i{}w~}Z{|v~|V" + "{}e~|_w~}m{|u~bv~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|`v~}n{}w~|jv~}n{}w~Tv~|Ov~Lv~Lv~Lv~Av~Lv~Lv~Lv~" + "Wv~|l{|v~`w~}m{|w~}bv~|kv~bv~|kv~bv~|kv~bv~|kv~bv~|kv~.v~vw~|u{|v~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}" + "w~|\\{|w~|w{}w~}[v~k{}w~|^{|w~|w{}w~} T{|w~q{}w~q{}x~|j{|w~b{}x~|j{|w~wu~|x{|u~|x{}x~|j{|w~wu~|m{}x~|j{|w~b{}x~" + "|[{|w~Q{|w~}w{}w~} SZ~}`{}w~|y{}y~|'{|n~y}~|n~}i{}k~x}k~c{|i~}Z{}j~]w~}kw~}a{}w~l{|w~|^{}w~}sv~Wv~|y{}w~}`{}w~|" + " mv~| o{}Z~X{|y~|v{|w~}\\{|w~t{}x~|rw~|p{}w~}n{}u~yw~}(v~|Gv~ v{}w~ gw~}U{}w~}m{|v~V{}w~}Q{}v~}A{|v~c{|_~" + "|O{}w~}a{}v~l{|v~X{}v~X{|v~k{}w~}N{}w~} Q{|}p~}|^{|Z~}^{|}p~}|U{}w~}`{|x~}sw~|o{|w~|u{}x~|l`~b{}w~}k{|v~|eu~N{}" + "w~}g{}v~|d{}w~}L{}w~}Su~ev~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}u{|t~X{}w~}V{}w~|ss~}sv~|h{}w~|q{|v~|yv~hu~e{|v~|d{}w~}" + "Su~e{|v~|f{}w~}n{}v~|K{|v~|Z{|v~|Yv~|i{}w~}^v~|x{}v~a{|v~y{|w~|q{}x~}y{}w~}c{}v~tv~}T{|v~|U{|v~}J{|w~}G{|w~K{|w" + "~| u{|v~m{}w~|_v~kv~a{}w~|O{}w~|l{}w~|bv~|Cw~}V{}w~|l{}w~|`w~}m{|w~}Wv~Lv~Tw~}y{|u~|Nv~_w~}mv~mv~hw~}m{|w~}bv~" + "|l{|v~`v~kv~cv~|l{}w~|Zw~}D{|}u~}Xv~S{|w~|m{}w~|\\{}w~|w{|w~}^w~}y{|w~u{}x~}y{}w~|]{}q~|Tv~wv~|U{|v~}K{}w~|Lw~|" + "Lv~ N{|x~s{}x~{w~|tx~|fv~|o{|v~\\v~l{|w~}a{|w~|p{}w~_{}w~|l{|v~_{}v~|Ow~}m{|w~}[{}w~|xv~X{|v~rv~|_{|w~|m{}w~|h{" + "|v~|qv~pv~|iv~|u{}w~t{}w~|b{|w~}q{|w~}`v~t{}w~t{|w~|bv~kv~c{}w~|l{|v~X{|w~}Vv~l{}w~|bv~|l{|v~[{|v~}Q{}w~}T{|v~}" + "h{|v~|hu~}u{|v~u{|u~|g{}w~}hv~|b{}f~|du~e{|v~|i{|u~|A{}w~@u~|b{}x~|x{}w~ww~a{}v~|i{}v~}b{}x~|x{}w~w{}y~} {}w~|W" + "{|v~sy~}S{|v~O{|w~}s{}w~}^q|}v~q|'{}t~|{|w~}.x~u{}v~}|wy|}y~tx~/{|v~|v{}w~}Cw~}6x~tw~s{}w~ux~ O{}w~ p{|w~|m{}w" + "~|Ux~}w{|x~} B{}w~}v{|v~|Ww~|q{|y~}v{}x~c{}x~|i{}x~}cw~|q{|y~}v{}x~_{|v~X`~b`~b`~b`~b`~c{|`~|kc~Xu~J{}w~}M{}w~" + "}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~g{|v~}g{}w~|q{|v~|yv~hu~e{|v~|ju~e{|v~|ju~e{|v~|ju~e{|v~|ju~e{|v~|a{}" + "v~|x{|u~|bu~y{}w~l{|v~|gv~|i{}w~}ev~|i{}w~}ev~|i{}w~}ev~|i{}w~}Z{|v~|V{}f~|^w~}l{|v~|d{|v~m{}w~|a{|v~m{}w~|a{|v" + "~m{}w~|a{|v~m{}w~|a{|v~m{}w~|a{|v~m{}w~|k{|v~m{}w~T{}w~|Ov~|Mv~|Mv~|Mv~|Bv~Lv~Lv~Lv~W{}w~|l{|v~`w~}m{|w~}bv~|l{" + "|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~bv~|l{|v~.v~|x{}x~|t{|v~a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|a{|w~|m{}w~|[v~wv~|[v" + "~kv~\\v~wv~| Sw~|r{}w~r{|w~hw~|d{|w~hw~|yu~|v{|u~y{|w~hw~|yu~|m{|w~hw~|d{|w~Z{|w~Pv~wv~| SZ~}_w~}yx~%n~{|~{|o~|" + "i{|l~}|}|l~}b{}j~Xk~|]w~}kw~}a{}w~l{}w~]v~|s{}w~|X{}w~}yv~|_w~} mv~} g{}x~}t{}x~}O{|y~|uw~}\\{}x~|t{}x~|rw" + "~|p{|w~}m{}u~}w~|({}w~|H{|w~} v{}w~ h{|w~|U{}w~}m{|v~V{}w~}R{}v~}@{|v~c{|_~|Ov~|a{|v~l{}w~}Xv~}X{|v~k{}w~}Nv~|" + " N{|}p~}|a{|Z~}a{|}p~}|R{|w}|_x~}s{}x~}o{}w~|v{|w~l{}`~|c{}w~}k{|v~|e{}v~|O{}w~}gu~c{}w~}L{}w~}S{}v~|fv~|h{}w~}" + "hv~|Y{}w~}M{}w~}W{}w~}t{|t~Y{}w~}V{}w~|s{}t~rv~|h{}w~|p{}w~}yv~h{}v~|f{}v~c{}w~}S{}v~|f{}v~e{}w~}mv~}K{|v~|Z{|v" + "~|Yv~|iv~|^{}w~}xv~}`v~|{|w~p{}w~yv~|d{|v~|t{|v~|U{|v~|V{|u~I{|w~}Fw~|L{|w~| u{}w~|mv~|_v~|m{|v~a{}w~}O{}w~|lv" + "~|b{}w~|Cw~}V{}w~|lv~|`w~}m{|w~}Wv~Lv~Tw~}x{|u~|Ov~_w~}mv~mv~hw~}m{|w~}b{}w~|l{|w~}`v~kv~c{}w~|lv~|Zw~}B{|u~Xv~" + "S{|w~|m{}w~|\\{|w~}w{}w~|^v~y{}x~}u{|x~}y{}w~]{|v~|}v~T{}w~|y{|w~}U{|v~}J{|w~}Lw~|M{|w~} Mx~}v{|w~|{|w~|v{}x~e{" + "}w~|o{}v~\\v~l{|w~}a{|w~|pw~}_{}w~|l{|w~}_v~Mw~}m{|w~}[{|w~}y{|w~}X{}w~|r{}w~}_{|w~|m{}w~|h{|v~|qv~|r{|v~|i{}w~" + "|u{}w~tv~|b{|w~}q{|w~}`v~t{}w~t{}w~|bv~kv~c{}w~|l{|w~}X{|w~}Vv~lv~b{}v~jv~|\\u~P{}w~}S{}v~|iu~g{|t~|w{|v~v{}u~}" + "f{}w~}hv~|a{}h~|c{}v~|f{}v~g{|u~|B{}w~Au~|b{}v~|y{}w~xu~a{}v~|k{}v~}b{}v~|y{}w~x{}w~}!{}w~|Vv~sy~}S{|v~O{|u~}y|" + "{y|u~}T{|w~}Lw}|P{|}p~}-{|y~}u{}l~u{}y~|.{|v~|v{}w~}Dw~}6{|y~}uw~rw~}w{}y~| O{}w~ p{|w~|m{}w~|Ux~}w{|x~} C{}w" + "~}v{|v~|W{}x~}px~u{}x~d{|w~i{}x~}c{}x~}px~u{}x~_{}w~}Y{}`~|d{}`~|d{}`~|d{}`~|d{}`~|d{}w~}j|}w~}l{|c~X{}v~|K{}w~" + "}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~gu~|g{}w~|p{}w~}yv~h{}v~|f{}v~i{}v~|f{}v~i{}v~|f{}v~i{}v~|f{}v~" + "i{}v~|f{}v~a{}v~|v{|u~|c{}v~|}w~|l{}v~fv~|iv~|ev~|iv~|ev~|iv~|ev~|iv~|Z{|v~|V{}h~}\\w~}k{}w~|d{}w~|mv~|a{}w~|mv" + "~|a{}w~|mv~|a{}w~|mv~|a{}w~|mv~|a{}w~|mv~|k{}w~|mv~|U{}w~}O{}w~|M{}w~|M{}w~|M{}w~|Bv~Lv~Lv~Lv~W{}w~}l{}w~}`w~}m" + "{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}b{}w~|l{|w~}.{}w~|y{}x~|s{|w~}a{|w~|m{}w~|a{|w~|m{}w~|a{|w" + "~|m{}w~|a{|w~|m{}w~|[{}w~|y{|w~}Zv~kv~\\{}w~|y{|w~} R{|w~r{}w~rw~}h{|w~dw~}h{|w~y{|w~|t{|w~}yw~}h{|w~y{|w~|lw~}" + "h{|w~dw~}Z{|w~P{}w~|y{|w~} Rs}v~g}|_{}w~{|y~}%{|p~|{|~yp~}g{}m~{}~{}m~|a{}l~|X{|m~}\\w~}kw~}a{|w~|mv~]v~r{}w~}X" + "{|v~{|v~^{}w~} n{}v~ gw~|tw~|O{|y~|uw~}]{|x~}sw~|rw~|p{|v~l{}r~}'{|w~}H{|w~} v{}w~ h{|w~T{|v~m{}w~}V{}w~}" + "S{}v~}?{|v~c{|_~|Ov~|`v~|m{}w~}Y{|v~W{|v~k{}w~}O{|v~ J{|}p~}|d{|Z~}d{|}p~}|-w~s{|w~ov~|v{}x~|lv~|j{|v~c{}w~}k{}" + "v~cv~}O{}w~}h{}v~|c{}w~}L{}w~}Rv~}fv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}rt~Z{}w~}V{}w~|ru~}rv~|h{}w~|p{|v~|{v~h{|v~}g" + "{|v~}c{}w~}Rv~}g{|v~}e{}w~}m{|v~|L{|v~|Z{|v~|Y{}w~}j{|v~|^{|v~|{|v~_{}w~}{}x~}p{|w~yv~cv~}r{}v~U{|v~|W{|u~|I{|w" + "~}F{}x~}L{|w~| u{}w~|n{|v~|_v~}m{}w~}a{|w~}O{|w~}m{|v~|b{}w~}Cw~}V{|w~}m{|v~|`w~}m{|w~}Wv~Lv~Tw~}vu~|Pv~_w~}mv" + "~mv~hw~}m{|w~}b{|w~}l{}w~}`v~|m{|w~}c{|w~}lv~|Zw~}@v~|Yv~S{|w~}mv~|[v~wv~]{}w~|{w~|u{|w~yw~}]v~}y{}v~U{|w~}y{}w" + "~|V{|v~}I{|w~}Lw~|M{|w~} M{|w~x}v~}x{}v~x}w~|e{}w~}ou~|]v~l{|w~|a{|w~p{}w~|_{|w~}l{}w~}`{|w~}Mw~}m{|w~}Zv~y{}w~" + "|Y{|v~q{|v~_{|w~}m{}w~|gv~|r{|v~|r{|v~h{}w~}u{}w~tv~a{|w~}q{|w~}`v~t{}w~t{}w~|bv~|m{|w~}c{|w~}l{}w~}X{|w~}V{}w~" + "|n{|w~}bv~}j{}v~]{}v~|P{}w~}Ru~j{}v~|f{|t~}|y{|v~x{|t~}e{}w~}hv~|`{|}l~}`v~}g{|v~}f{|u~|C{}w~Bu~|`u~|{}w~yu~|`{" + "}v~|m{}v~}a{|u~|{}w~y{}v~}!{}w~|Vv~|ty~}S{|v~P{|g~}U{|w~}Lw~|N{|r~}+{}y~|u{|}o~}v{|y~}+v~}v{}v~Ew~}5{}y~|vw~r{|" + "w~|y{|y~} N{}w~ p{|w~}m{}w~|Ux~}w{|x~} Dv~}v{}v~|W{|w~p{}y~|u{}x~dw~|j{}w~c{|w~p{}y~|u{}x~`{}v~|Yv~|j{|v~dv~|" + "j{|v~dv~|j{|v~dv~|j{|v~dv~|j{|v~dv~|j{|v~l{}w~}n{|v~Wv~}K{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~h{" + "|v~}f{}w~|p{|v~|{v~h{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}i{|v~}g{|v~}b{}v~|t{|u~|cq~|l{|v~}f{}w~}j{|v" + "~|e{}w~}j{|v~|e{}w~}j{|v~|e{}w~}j{|v~|Z{|v~|V{}k~}|Zw~}k{}w~}d{}w~|n{|v~|a{}w~|n{|v~|a{}w~|n{|v~|a{}w~|n{|v~|a{" + "}w~|n{|v~|a{}w~|n{|v~|k{}w~|n{|v~}U{|w~}O{}w~}M{}w~}M{}w~}M{}w~}Bv~Lv~Lv~Lv~W{|v~lv~|`w~}m{|w~}b{|w~}l{}w~}b{|w" + "~}l{}w~}b{|w~}l{}w~}b{|w~}l{}w~}b{|w~}l{}w~}Xt|X{}w~}{}x~}r{}w~}a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|[{|w~}y" + "{}w~|Zv~|m{|w~}\\{|w~}y{}w~| Qw~}s{}w~s{}w~fw~}f{}w~fw~}y{|y~|r{|y~}y{}w~fw~}y{|y~|l{}w~fw~}f{}w~Y{|w~P{|v~y{}w" + "~| Kv~}J{|w~|}y~|${}r~}y{}~y{|q~f{|n~|{}~yn~}_m~|V{|o~}[w~}kw~}`w~}n{|w~}^{|w~}r{|v~Wv~{}w~}]v~| o{|v~| hw" + "~t{|w~N{|y~|uw~}]w~|s{}x~|rw~|ov~|l{}s~&{|w~}H{}w~| v{}w~ h{}x~}Sv~|nv~|V{}w~}T{}v~}>{}w~}Q{}w~}J{}v~_{}w~}mv~" + "}Y{}w~}Vv~|lv~|Ov~} G{|}p~}|0{|}o~}*{}x~rw~}q{}v~|w{}w~l{|v~hv~|d{}w~}ku~c{}v~}P{}w~}i{}u~b{}w~}L{}w~}R{}v~|gv~" + "|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}qt~[{}w~}V{}w~|r{}v~|rv~|h{}w~|o{}w~}{v~g{}v~|hu~|c{}w~}R{}v~|hu~|e{}w~}lv~}L{}v~Y" + "{|v~|Y{}v~j{}v~\\{}w~}{}w~}_{|v~{w~|ow~y|v~d{}v~pv~}V{|v~|Wu~|H{|w~}F{|w~L{|w~| u{}w~m{}v~|_u~mv~|a{|v~Nv~|n{}" + "v~|b{|v~Cw~}Uv~|n{}v~|`w~}m{|w~}Wv~Lv~Tw~}uu~|Qv~_w~}mv~mv~hw~}m{|w~}b{|v~lv~|`v~}m{}w~}c{|v~m{|v~|Zw~}@{}w~|Yv" + "~S{|w~}mv~|[{}w~|y{|w~}]{|w~}{w~sw~y|w~}^{}w~}wv~}U{}w~yv~Uv~}Gw~}Lw~|M{|w~| L{|q~}v{}q~|d{|w~}p{|u~|]v~l{}w~|a" + "{|w~pv~^{|v~lv~|`{|w~|Mw~}m{|w~}Z{}w~y|v~X{}w~}pv~|`{|w~}mv~|gv~}r{|v~}r{}v~h{|v~u{}w~u{|w~}a{|w~}q{|w~}`{}w~|u" + "{}w~tv~av~}m{}w~}c{|v~lv~|X{|w~}V{|w~}n{}w~|c{|v~i{|v~|_{}v~}O{}w~}R{|v~}l{}v~|d{|r~y}v~y}s~}d{}w~}hv~|]{|}s~y}" + "|^{}v~|hu~|e{|v~}C{}w~C{}v~|^u~|}w~{}v~|^{}v~n{|v~}_{|u~|}w~{}v~} {}w~|V{}w~}ty~}S{|v~Q{}e~}V{|w~}Lw~|L{|t~*{|x" + "~|t{|y}u~}|u{|x~|*{}w~|v{|v~Fw~}5{|x~|ww|qw|y{|x~| >{|w~}mv~|Ux~}w{|x~} Ev~}v{|v~U{}x~|q{|y~}t{}x~e{}x~}j{}w" + "~b{}x~|q{|y~}t{}x~a{}v~}Y{|v~hv~|f{|v~hv~|f{|v~hv~|f{|v~hv~|f{|v~hv~|f{}v~hv~|n{|v~|n{|v~W{}v~}L{}w~}M{}w~}M{}w" + "~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~i{|u~|f{}w~|o{}w~}{v~g{}v~|hu~|h{}v~|hu~|h{}v~|hu~|h{}v~|hu~|h{}v~|hu~|c{}" + "v~|r{|u~|d{}s~|ku~|f{}v~j{}v~d{}v~j{}v~d{}v~j{}v~d{}v~j{}v~Y{|v~|V{}w~}r|Vw~}k{|w~|d{}w~m{}v~|a{}w~m{}v~|a{}w~m" + "{}v~|a{}w~m{}v~|a{}w~m{}v~|a{}w~m{}v~|k{}w~m{}u~U{|v~O{|v~M{|v~M{|v~M{|v~Bv~Lv~Lv~Lv~Vv~|n{|v~_w~}m{|w~}b{|v~lv" + "~|b{|v~lv~|b{|v~lv~|b{|v~lv~|b{|v~lv~|X{}u~X{|v~|x~}qv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|a{|w~}mv~|Z{}w~yv~Yv~}m{}" + "w~}[{}w~yv~ P{|w~}t{}w~t{|w~}f{|w~}h{|w~}f{|w~}yy|p{|}y{|w~}f{|w~}yy|l{|w~}f{|w~}h{|w~}Y{|w~Ov~y|v~ K{}w~}Hw~}y" + "~}\"{}t~}x{}~x{|s~d{|p~}y{}~y{|p~}]o~|T{}p~Zw~}kw~}`{}w~|o{}w~|^{}w~|qv~|X{}w~|v~|]{|v~| o{}v~j{} {|x~}t{|" + "x~}N{|y~|v{}w~}^{}x~}r{}x~}rw~|o{}v~k{}u~|%v~Hv~ u{}w~ hw~|S{}v~o{}v~U{}w~}U{}v~}>{|v~}Q{}w~}Ju~_{|v~n{|v~|Z{|" + "v~|Vv~}m{|v~|P{}v~ C{}o~}4{|o~}|({|x~}s{}w~}s{}u~|x{}w~|l{}w~}h{}w~}d{}w~}l{|v~}bu~|g{|}g{}w~}j{}u~|b{}w~}L{}w~" + "}R{|u~|hv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}pt~\\{}w~}V{}w~|r{|v}qv~|h{}w~|nv~|v~g{|u~|j{}v~}b{}w~}R{|u~i{}v~}d{}w~}" + "l{|v~|M{}v~Y{|v~|Y{|v~|kv~}\\{|v~{v~|_{|v~|w~|o{}x~y}w~}e{|v~|p{|v~|W{|v~|X{}v~}G{|w~}F{|w~|M{|w~| u{}w~|nu~|_" + "u~}o{}v~_v~}O{}w~}o{|u~|av~}Dw~}U{}w~}o{|u~|`w~}m{|w~}Wv~Lv~Tw~}t{}v~|Rv~_w~}mv~mv~hw~}m{|w~}av~|n{|v~_u~mv~|bv" + "~|n{}v~|Zw~}@{}w~|Yv~Rv~n{}v~|[{|w~}y{}w~|\\w~}|x~}s{}x~y}w~|_{}v~v{|v~|V{|w~y}w~}Vu~Fw~}Lw~|M{|w~| K{|s~}t{}s~" + "|bv~p{}u~}]v~|mv~`{|w~q{}w~}]v~}n{}v~_{|w~|Mw~}m{|w~}Yw~y}w~|Xv~o{|w~}`{|v~n{|v~|g{}v~r{}u~rv~}gv~|v{}w~uv~|a{|" + "w~}q{|w~}`{|w~}u{}w~u{|v~au~mv~|bv~}n{}v~Vv~Uv~nv~b{}w~}hv~}`{|v~}N{}w~}Q{|v~}n{}v~}b{|c~}c{}w~}hv~|Z{|v~Z{|u~|" + "j{}v~}c{|w~B{}w~B{}x~|\\u~}w~}v~|\\{}x~|m{}x~}]{|u~}w~}v~} {{v~|V{|v~|uy~}S{|v~R{}v~y|q~}|u~W{|w~}Lw~|J{}u~*{|x" + "~|e{|x~|({}x~}u{|w~F{|x}|4{|x~|e{|x~| ={|v~n{|v~|Ux~}w{|x~} Ew~|u{|x~}U{|x~}p{}j~}iw~j{}w~b{|x~}p{}j~}f{}v~}" + "X{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}f{}w~}h{}w~}fv~}h{}w~}n{}w~}m{|v~Vu~|g{|}c{}w~}M{}w~}M{}w~}M{}w" + "~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~j{|u~}e{}w~|nv~|v~g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}g{|u~|j{}v~}c{" + "}v~|p{|u~|e{|t~}k{}v~}e{|v~|kv~}d{|v~|kv~}d{|v~|kv~}d{|v~|kv~}Y{|v~|V{}w~}Mw~}k{}w~|d{}w~|nu~|a{}w~|nu~|a{}w~|n" + "u~|a{}w~|nu~|a{}w~|nu~|a{}w~|nu~|k{}w~|nt~|Uv~}Ov~}Mv~}Mv~}Mv~}Cv~Lv~Lv~Lv~V{}v~nv~}_w~}m{|w~}av~|n{|v~`v~|n{|v" + "~`v~|n{|v~`v~|n{|v~`v~|n{|v~W{}u~Wr~q{|v~_v~n{}v~|`v~n{}v~|`v~n{}v~|`v~n{}v~|Z{|w~y}w~}Yu~mv~|[{|w~y}w~} O{}w~}" + "u{}w~u{}w~}d{}w~}j{}w~}d{}w~}j{}w~}d{}w~}j{}w~}d{}w~}j{}w~}X{}w~O{|w~y}w~} L{}w~}G{}u~|!{|}x~}|w{}~v{}w~}b{|r~|" + "x{}~w{}s~|\\{|q~}Rq~|Zw~}kw~}`{|v~p{|v~]v~p{}w~}X{|q~[{}v~} p{|v~}ly}$v}|\"{}x~}t{}x~}Yy}|s{|y~|w{|v~|_{|w~" + "q{}x~}s{|w~n{|v~}l{|u~}%{}w~|Iw~} u{}w~L{}w~} tv}|P{|w~R{|v~|pv~}U{}w~}V{}v~}={}v~|Q{}w~}K{}v~|^v~|o{}v~Y{}v~U{" + "}v~m{}v~P{|v~}U{|v}M{}w~}F{|}q~}6{|q~}|G{|w}|^w~ru~y|x{|}t~y|}v~|kv~|h{|v~d{}w~}m{|u~|b{|u~|i{|~}g{}w~}l{|}u~}a" + "{}w~}L{}w~}Q{}u~|iv~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}ot~]{}w~}V{}w~|bv~|h{}w~|n{}q~f{}u~k{}u~a{}w~}Q{}u~k{|u~c{}w~}" + "kv~}c{|}h{|v~}Y{|v~|X{}v~l{}v~|[v~}v~]v~}w~n{}r~|ev~}n{}v~W{|v~|Y{}v~}F{|w~}Ew~}M{|w~| u{}w~|o{}u~|_t~|q{|v~}_" + "{|v~|P{|v~}pt~|a{|v~|Ew~}U{|v~|pt~|`w~}m{|w~}Wv~Lv~Tw~}s{}v~|Sv~_w~}mv~mv~hw~}m{|w~}a{}v~nv~}_u~}o{}v~a{}v~o{|u" + "~|Zw~}@{}w~|Y{}w~|Sv~|p{|u~|Zv~{|v~[v~}x~}s{|r~_{|v~|u{}v~Uq~V{}v~|Fw~}Lw~|M{|w~| I{|y}~y}|r{|}x~}|`{}w~}qs~]u~" + "n{|v~`{|w~r{|v~\\{|v~nv~}_{|w~}Mw~}m{|w~}Y{}r~X{}w~}nv~`{|v~|o{}v~|g{|v~|st~|t{|v~|g{}v~v{}w~v{|v~`{|w~}q{|w~}_" + "v~|v{}w~uv~}au~}o{}v~a{|v~nv~}Vv~U{|w~}p{}w~}bv~|h{|v~`u~M{}w~}P{|u~|q{}v~}_{}g~}|b{}w~}hv~|Z{|v~Y{}u~k{}u~a{|y" + "~A{}w~A{}~|Zl~|Z{}~|k{}~}[{|l~} yv~}Uv~}uy~}S{|v~S{}v~|x{|y}x~}|wu~X{|w~}Lw~|I{|v~}*{}x~|g{|x~}&{}y~}t{|x~ T{}x" + "~|g{|x~} <{|v~|o{}v~|Ux~}w{|x~} Ex~|t{|y~}Tw~|p{}j~}j{}x~|k{}x~}aw~|p{}j~}g{}v~}Wv~|h{|v~fv~|h{|v~fv~|h{|v~f" + "v~|h{|v~fv~|h{|v~g{|v~g{|v~|ov~|m{|v~V{|u~|i{|~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~k{}t~d{}w~" + "|n{}q~f{}u~k{}u~e{}u~k{}u~e{}u~k{}u~e{}u~k{}u~e{}u~k{}u~c{}v~|n{|u~|e{}u~|l{}u~c{}v~l{}v~|c{}v~l{}v~|c{}v~l{}v~" + "|c{}v~l{}v~|Y{|v~|V{}w~}Mw~}kv~c{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|a{}w~|o{}u~|k{}w~|o{" + "}s~U{|v~|P{|v~|N{|v~|N{|v~|N{|v~|Dv~Lv~Lv~Lv~Uv~}p{}v~^w~}m{|w~}a{}v~nv~}`{}v~nv~}`{}v~nv~}`{}v~nv~}`{}v~nv~}W{" + "}u~W{}t~|qv~}_v~|p{|u~|`v~|p{|u~|`v~|p{|u~|`v~|p{|u~|Yq~Xu~}o{}v~Yq~ M{}w~}|w{}x~}v{}v~b{}w~}|m{}v~b{}w~}|m{}v~" + "b{}w~}|m{}v~b{}w~}|m{}v~W{}x~}Nq~| M{|v~F{|u~ py~|V{|}y~y}|vy~|w{|y}y~y}Y{|s~}Q{|s~|Yw~}kw~}_{}v~|s{}v~|^{|w~}p" + "{|v~X{|r~}Z{}u~} q{}v~}o{|y~}$v~}\"w~|tw~|Y{}y~}|u{|y~|x{|u~^{}x~|q{|w~s{}x~}mu~}n{|s~}&{|w~|J{|w~| u{}w~L{" + "}v~ u{|v~|P{}x~}Q{}v~|r{}v~T{}w~}W{}v~}O{}|k{}v~}P{}w~}]{}|l{}u~]{|v~|q{}v~|Yv~}U{|v~}o{}v~}Q{|v~}T{}v~M{}v~C{|" + "}t~}6{|t~}|D{}w~}^{}x~|s{|m~y}q~|k{|v~fv~|e{}w~}n{|u~}`{}u~|l{|}y~}g{}w~}n{|}t~}`{}w~}L{}w~}P{}u~}jv~|h{}w~}hv~" + "|Y{}w~}M{}w~}W{}w~}nt~^{}w~}V{}w~|bv~|h{}w~|mq~e{}u~|n{}u~|a{}w~}P{}u~|n{}u~|c{}w~}k{|v~|d{|y~}k{|u~|Y{|v~|X{|u" + "~n{|u~Z{}r~}]{}s~}n{|r~e{}v~lv~}X{|v~|Z{|u~E{|w~}E{}w~M{|w~| u{|v~p{|t~|_s~|s{|u~]u~|P{}v~}s{|s~|`u~|k{|Ww~}T{" + "}v~}s{|s~|`w~}m{|w~}Wv~Lv~Tw~}r{}v~}Tv~_w~}mv~mv~hw~}m{|w~}`v~}p{}v~|_t~|q{|v~|`v~}q{|t~|Zw~}Q{|kv~|Y{}w~}S{}v~" + "pt~|Z{}w~y}w~}[{}s~|rs~}_v~}s{}w~}V{}s~}W{}v~|Ew~}Lw~|M{|w~| r{|v~|s{}s~}^u~}ov~|_w~|s{}w~|[v~}pu~]v~|Nw~}m{|w" + "~}Y{|s~}Xv~m{}w~|a{|u~p{|u~|fv~}t{}x~}x~}t{}v~ev~}w{}w~w{|v~}`{|w~}q{|w~}_{}v~|w{}w~v{}v~`t~|q{|v~|`v~}p{}v~U{}" + "w~|Uv~|r{|v~b{|v~fv~|bu~|M{}w~}O{|u~}t{|u~}\\{|k~}|`{}w~}hv~|Z{|v~X{}u~|n{}u~|`{|@{}w~@{|Xn~|X{|i{|Y{|n~} xv~}U" + "{|v~}vy~}S{|v~T{|v~|jv~}Y{|w~}Lw~|H{|v~|*{}x~}i{}x~}${}~}s{|y~ S{}x~}i{}x~} ;{|u~p{|u~|Ux~}w{|x~} Ey~|s{|~}T" + "{}x~}o{}j~}k{|w~k{}x~}a{}x~}o{}j~}h{}v~}W{|v~fv~|h{|v~fv~|h{|v~fv~|h{|v~fv~|h{|v~fv~|h{}w~}f{}w~}p{|v~l{|v~U{}u" + "~|l{|}y~}c{}w~}M{}w~}M{}w~}M{}w~}D{}w~}M{}w~}M{}w~}M{}w~}Z{|v~n{|}s~c{}w~|mq~e{}u~|n{}u~|d{}u~|n{}u~|d{}u~|n{}u" + "~|d{}u~|n{}u~|d{}u~|n{}u~|d{}v~|l{|u~|et~|n{}u~|c{|u~n{|u~b{|u~n{|u~b{|u~n{|u~b{|u~n{|u~X{|v~|V{}w~}Mw~}x{|p{}v" + "~c{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|a{|v~p{|t~|k{|v~p{|q~j{|gu~|Pu~|k{|_u~|k{|_u~|k{|_u~|k{" + "|Vv~Lv~Lv~Lv~U{|v~}r{}v~}^w~}m{|w~}`v~}p{}v~|_v~}p{}v~|_v~}p{}v~|_v~}p{}v~|_v~}p{}v~|W{}u~Vu~|q{}v~|_{}v~pt~|`{" + "}v~pt~|`{}v~pt~|`{}v~pt~|Y{}s~}Xt~|q{|v~|Y{}s~} Lu~}p{}u~|au~}p{}u~|au~}p{}u~|au~}p{}u~|au~}p{}u~|W{}x~}N{}s~} " + "M{|v~|Ev~} py~|Jy~|M{}t~O{|u~}Xw~}kw~}_{|t~}w|}u~}]{}w~}ov~|Xr~|Y{}t~}y| tt~|r{}x~}$v~}\"w~t{|w~X{}v~}y|y{|" + "y~y|}t~|_{|x~}ow~}tw~|m{|t~|r{|}q~}&w~}J{}w~ t{}w~L{}v~ u{|v~|Pw~|Pu~|t{}v~|\\s|}w~}r|a{}v~}Nx~}|p{}t~O{}w~}]{}" + "y~}|q{}t~|\\{}v~|s{}u~Y{|v~|T{}u~|r{}u~|_{~}|r{|}u~|T{}v~M{}v~@{|}w~}6{|w~}|A{}w~}^{|w~r{|o~}{}s~}iv~}f{}w~}e{}" + "w~}q|y}s~|_{}t~|p{|}w~}g{}w~}r|y}q~}_{}w~}g|`{}w~}O{}t~}o{|}u~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}mt~_{}w~}h|i{}w~|bv~" + "|h{}w~|m{}r~dt~}|r{|t~|`{}w~}Ot~}q{|t~}b{}w~}jv~}d{|w~}|p{|}u~}X{|v~|W{}u~|q{}u~|Z{|r~|]{|s~|mr~f{|v~|l{|v~|Y{|" + "v~|[{|u~}b|^{|w~}E{|w~|N{|w~| tv~}r{}s~|_w~y}x~}|w{|}u~|]{|u~|p{|}|^t~y|x{|}w~}w~|`{|u~|n{|y~|Xw~}St~y|x{|}w~}" + "w~|`w~}m{|w~}Wv~Lv~Tw~}q{}v~}Uv~_w~}mv~mv~hw~}m{|w~}`{}v~}r{}v~}^s~}s{|v~}_{}v~}s{|s~|Zw~}Qy~}|o{}w~}X{|v~}|U{|" + "v~}s{|s~|Z{|q~Z{|s~qs~|`{}w~}qv~}Vs~|X{}v~|Dw~}Lw~|M{|w~| qu~|u{}w~|v~}_s~|s{|u~^{}w~t{}w~}Z{|v~}|t{|}v~|]{}v~" + "|ny|^w~}m{|w~}Xs~|Y{}w~}m{|w~}a{|t~|s{}t~}f{}v~}v{|w~{w~|v{}v~}e{}v~}x{}w~x{}u~_{|w~}q{|w~}^u~}|y{}w~x{}u~}`s~}" + "s{|v~}_{|v~}|t{|}v~|U{|v~}|W{|v~|t{|v~|bu~f|v~}c{}v~}h|_{}w~}Vs}t~}v{}t~s}`{|y}t~y}|]{}w~}hv~|Z{|v~Wt~}|r{|t~|#" + "{}w~ vp~| {|p~} wv~}T{}v~}wy~}v{}~Z{|v~S{}x~|hx~}X{|w~}Lw~|G{}w~}){|w~|m{|w~|\"{|}q{} R{|w~|m{|w~| XY| ${|u~}r{" + "|t~}Ux~}w{|x~} E{}qy|T{|w~c{}x~gw~|lw~}a{|w~c{}x~e{}v~}Vv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~}f{}w~}hv~|f" + "{|v~pv~}l{|v~}h|h{}t~|p{|}w~}c{}w~}g|a{}w~}g|a{}w~}g|a{}w~}g|X{}w~}M{}w~}M{}w~}M{}w~}Z{|v~r|x}q~b{}w~|m{}r~dt~}" + "|r{|t~|bt~}|r{|t~|bt~}|r{|t~|bt~}|r{|t~|bt~}|r{|t~|d{|v~|j{|v~}f{}s~}|r{|t~|a{}u~|q{}u~|a{}u~|q{}u~|a{}u~|q{}u~" + "|a{}u~|q{}u~|X{|v~|V{}w~}Mw~}xy~}y|wy|u~|bv~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|`v~}r{}s~|jv~}r{}w~}" + "|u~|o{|}y~g{|u~|p{|}|_{|u~|n{|y~|`{|u~|n{|y~|`{|u~|n{|y~|`{|u~|n{|y~|Wv~Lv~Lv~Lv~T{}u~}|x{|}u~}]w~}m{|w~}`{}v~}" + "r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}^{}v~}r{}v~}V{}u~V{|v~}r{}v~}^{|v~}s{|s~|`{|v~}s{|s~|`{|v~}s{|s~|`{|v" + "~}s{|s~|Xs~|Xs~}s{|v~}Ws~| K{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~^{}u~}x|{x|}t~U{}x~}N{|s~| M" + "{|w~|D{}w~| q{|y~}K{|y~}L{}v~|N{}v~Ww~}kw~}^{|j~}\\v~|o{}w~}X{}s~W{|^~} -s~}v|}v~}$v~}#{|w~t{|x~}X{}e~|^w~|o" + "{|w~|v{}w~k{|s~}v|}t~y}v~}'{}w~Jw~} t{}w~L{}v~ u{|v~|Q{|w~O{|u~}w|}u~}\\{|e~|ab~`u~w}|x}r~|O{}w~}]{}v~w}|x}s~}Z" + "t~}w|}t~X{}w~}S{|t~y}v|}t~}^v~y}y|y}s~|S{}v~M{}v~={|}~}6{|y~}|?{}w~}]w~}q{}r~|y{}u~}h{|v~|f{|v~e{}c~|]{}s~y}v|y" + "}t~}g{}b~|^{}c~}`{}w~}N{}r~y}v|y}r~|h{}w~}hv~|Y{}w~}M{}w~}W{}w~}lt~`{}d~}i{}w~|bv~|h{}w~|lr~cr~}v|}s~}_{}w~}Ns~" + "y}v|}s~}a{}w~}j{|v~|e{|s~}u|}r~W{|v~|Vs~}v|y}t~|Xs~}\\{|s~|m{}t~}fv~}j{}v~Y{|v~|[{}\\~}^{|w~}Dw~}N{|w~| t{}u~y" + "|x{|}w~y}w~|_w~}{k~|[{|t~}|wy|}x~|^{|k~y|w~|_{|t~}|vy|y}w~|Xw~}S{|k~y|w~|`w~}m{|w~}Wv~Lv~Tw~}p{}v~}Vv~_w~}mv~mv" + "~hw~}m{|w~}_{}u~}|x{|}u~}]w~y}w~y|yy|}u~|^{}u~}|x{|}w~}w~|Zw~}Qv~}y|v{|}u~|Wm~[{}u~}w|}v~}w~|Y{}s~}Yt~}q{}t~|a{" + "}v~p{|v~|W{}t~W{}d~Uw~}Lw~|M{|w~| q{|u~}|y{|}v~{|s~br~}y|yy|}u~|^{|w~}v{}v~X{}u~}y|{y|}u~}\\{|t~}|vy|y}y~}^w~}" + "m{|w~}X{}t~Xv~|lv~|b{|s~}v|}q~x}hu~}|{y|w~}{}w~}|{|}u~c{}u~}|}w~|}t~|_{|w~}q{|v~}_{|s~}v~}s~}_w~y}w~y|yy|}u~|^{" + "}u~}y|{y|}u~}S{}r~}Z{}v~}|x{|}v~}b{|Z~c{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~Vr~}v|}s~|\"{}w~ ur~| y{|r~} vv~" + "}St~}y|y~}{y|}x~`{}b~}a{}~|f{~}W{|w~}Lw~|G{|w~}({|v~}|s{|}v~| E{|v~}|s{|}v~| X{|Z~} ${|s~}y|{y|}q~}|}Xx~}w{|x~" + "} l{}x~|c{}x~h{}x~}m{|w~|`{}x~|c{}x~f{|v~}V{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~|f{|v~i{|v~dv~|r{|" + "v~k{|b~g{}s~y}v|y}t~}c{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|b~}a{}w~|lr~cr~}v|}s~}`r~}v|}s~}`r~}v|}" + "s~}`r~}v|}s~}`r~}v|}s~}b{|x~|h{|x~}f{}o~}v|}s~}_s~}v|y}t~|_s~}v|y}t~|_s~}v|y}t~|_s~}v|y}t~|W{|v~|V{}w~}Mw~}xk~}" + "a{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|`{}u~y|x{|}w~y}w~|j{}" + "u~y|x{|}u~y{|t~}|vy|}v~f{|t~}|wy|}x~|^{|t~}|vy|y}w~|_{|t~}|vy|y}w~|_{|t~}|vy|y}w~|_{|t~}|vy|y}w~|Wv~Lv~Lv~Lv~S{" + "}j~}\\w~}m{|w~}_{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}\\{}u~}|x{|}u~}U{}u~V{}t~}|x{|}u~}\\{" + "}u~}w|}v~}w~|_{}u~}w|}v~}w~|_{}u~}w|}v~}w~|_{}u~}w|}v~}w~|X{}t~Ww~y}w~y|yy|}u~|W{}t~ I{}h~}\\{}h~}\\{}h~}\\{}h~" + "}\\{}h~}T{}x~}Ms~ K{|y~}C{|w~ p{}x~K{}x~Kw~|L{}x~|Ww~}kw~}]{|l~}\\{|v~n{|w~}X{|s~U{}`~} -{|h~|$v~}#{}x~}t{}x" + "~}X{|}g~|^{}x~}m{}w~}y|}v~|j{|g~}y{}v~}({|w~|L{|w~| t{}w~L{}v~ u{|v~|Q{}x~}N{}k~}[{|e~|ab~`e~|N{}w~}]{}g~}Y{|i~" + "|Xv~|R{|g~}]i~|R{}v~M{}v~;y|5{|<{}w~}]{|w~|p{|v}|w{|x}|e{}v~dv~}f{}e~}|[{}d~|g{}d~}\\{}c~}`{}w~}M{}c~}|g{}w~}hv" + "~|Y{}w~}M{}w~}W{}w~}kt~a{}d~}i{}w~|bv~|h{}w~|l{|s~b{}f~|^{}w~}M{}f~|`{}w~}iv~}e{|c~V{|v~|Uf~}W{}t~|[s~l{}t~|g{}" + "v~hv~}Z{|v~|[{}\\~}^{|w~}D{}w~N{|w~| sj~{}w~|_w~}{|m~|Y{}i~|]{|m~|{|w~|^{|f~|Xw~}R{|m~|{}w~|`w~}m{|w~}Wv~Lv~Tw" + "~}o{}v~}Wv~_w~}mv~mv~hw~}m{|w~}^h~\\w~}{k~|\\k~y|w~|Zw~}Qg~}V{|n~Zk~{}w~|Y{|s~|Y{}u~}q{|t~a{|v~|o{}v~W{|u~|W{}d" + "~Uw~}Lw~|M{|w~| p{|l~|ys~be~}\\{}v~x}u~V{}j~}Z{|h~}^w~}m{|w~}X{|u~|Y{|w~}k{}w~}b{|w~}m~|s~h{|m~xm~|b{}g~|^{|w~" + "}pr~a{|f~}^w~}{k~|\\{}j~}R{|r~}Y{}l~}a{}Z~}d{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~U{}f~|!{}w~ tt~| w{|t~} uv~" + "}R{}i~`{}b~}`{|?{|w~}Lw~|Fw~}&{}t~w}t~} A{}t~w}t~} V{|Z~} ${|w~}m~|s~Xx~}w{|x~} m{|x~}b{}x~hw~lk~k{|x~}b{}x~" + "fv~}U{}v~dv~}j{}v~dv~}j{}v~dv~}j{}v~dv~}j{}v~dv~}j{}w~}d{}w~}r{}w~}k{|b~f{}d~|c{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}" + "w~}M{}w~}M{}w~}Z{|d~}|`{}w~|l{|s~b{}f~|^{}f~|^{}f~|^{}f~|^{}f~|`{|~|f{|~}f{|w~|}f~|]f~}]f~}]f~}]f~}V{|v~|V{}w~}" + "Mw~}xl~}_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|_j~{}w~|ii~w{|f~e{}i~|]{|f~|^{|f~|^{|f~|^{|f~|Wv~Lv~Lv~Lv~R{}l~" + "}[w~}m{|w~}^h~Zh~Zh~Zh~Zh~){|f~Zk~{}w~|^k~{}w~|^k~{}w~|^k~{}w~|X{|u~|Ww~}{k~|V{|u~| H{|j~|Z{|j~|Z{|j~|Z{|j~|Z{|" + "j~|S{}x~}M{}u~} I{}Ax~} pw~|Lw~|L{|y~|Jy~|Vw~}kw~}[{}o~|[{}w~}mv~Wt~}T{|}b~} +{}l~}\"v~}#w~|tw~|U{|}l~}]{|w~" + "ko~|h{|j~}|w{}u~({}w~L{}w~ s{}w~Lv~| u{|v~|Qw~}M{|m~}Z{|e~|ab~`g~}|M{}w~}]{}h~|W{|k~W{}v~P{|i~|\\k~}P{}v~Mv~| " + "i{}w~}\\{}w~Jv~}d{}v~f{}g~}|X{|}h~}e{}g~}|Z{}c~}`{}w~}L{|}g~}|e{}w~}hv~|Y{}w~}M{}w~}W{}w~}jt~b{}d~}i{}w~|bv~|h{" + "}w~|ks~a{|i~}\\{}w~}L{|i~}^{}w~}i{|v~|e{}f~}U{|v~|T{}i~|Ut~Z{}u~}l{|t~g{|v~|h{|v~|[{|v~|[{}\\~}^{|w~}D{|w~N{|w~" + "| s{|l~|{}w~|_w~}x{}q~}|W{|j~|[{}p~|y{|w~|]{|g~|Xw~}P{}q~}|y{}w~|`w~}m{|w~}Wv~Lv~Tw~}n{|v~}Xv~_w~}mv~mv~hw~}m{" + "|w~}]{}l~}[w~}{|m~|Zm~|{|w~|Zw~}Qh~|T{|o~Z{|m~|{}w~|Xs~X{}u~|pu~}av~}m{}w~}Wu~V{}d~Uw~}Lw~|M{|w~| o{|n~|w{}u~b" + "f~}Z{}p~}T{}l~}X{|i~}^w~}m{|w~}Wu~Xv~|k{|v~b{|w~y|o~|{}t~g{|o~|x{|o~}`{}i~|]{|w~}p{}s~_{}j~}|]w~}{|m~|Z{}l~}P{|" + "s~}X{}n~}`X~d{}c~}_{}w~}Vk~v{}l~|^{|v~Y{}w~}hv~|Z{|v~T{|i~} {{}w~ sv~| u{|v~} tv~}Q{}j~`{}b~}#{|w~}Lw~|G{|w~}${" + "}m~} ={}m~} T{|Z~} ${|w~y|o~|{}t~Xx~}w{|x~} mw~|b{}x~i{}x~|lk~kw~|b{}x~g{|v~Tv~}d{}v~jv~}d{}v~jv~}d{}v~jv~}d" + "{}v~jv~}d{}v~k{|v~|d{|v~rv~|k{|b~e{|}h~}a{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|g~}|]{}w~|ks~a{|i~}[" + "{|i~}[{|i~}[{|i~}[{|i~}/{|w~|y{|i~}Z{}i~|[{}i~|[{}i~|[{}i~|U{|v~|V{}w~}Mw~}xm~|^{|l~|{}w~|_{|l~|{}w~|_{|l~|{}w~" + "|_{|l~|{}w~|_{|l~|{}w~|_{|l~|{}w~|i{|l~}u{|g~d{|j~|\\{|g~|]{|g~|]{|g~|]{|g~|Wv~Lv~Lv~Lv~Q{|}p~}|Zw~}m{|w~}]{}l~" + "}X{}l~}X{}l~}X{}l~}X{}l~}){|w~}l~}Y{|m~|{}w~|^{|m~|{}w~|^{|m~|{}w~|^{|m~|{}w~|Wu~Vw~}{|m~|Tu~ E{|}p~}|V{|}p~}|V" + "{|}p~}|V{|}p~}|V{|}p~}|Qw~}Lu~| i{}y~| q{|w~}M{|w~}K{|}I{|}Uw~}kw~}Y{|y}w~y}|Yv~|m{}w~|X{}u~|Q{|}e~} *{|}p~" + "}|!v~}#w~t{|w~Py|x}y~x}y|[w~|j{}r~|e{|n~}|t{}u~){|w~|N{|w~| s{}w~Lv~ t{|v~|R{|w~|L{|}p~|Y{|e~|ab~`y|}l~}|K{}w~}" + "]{|}k~|S{}o~|Vv~}N{|m~}Z{}n~}|O{}v~Mv~ h{}w~}[v~L{|v~|d{|v~|g{}k~y}y|T{|}m~}|c{}m~x}y|W{}c~}`{}w~}J{|}k~}|c{}w" + "~}hv~|Y{}w~}M{}w~}W{}w~}it~c{}d~}i{}w~|bv~|h{}w~|k{|t~_{|m~}|[{}w~}J{|l~|]{}w~}h{}w~}c{|}k~}|T{|v~R{|}m~|S{}v~}" + "Z{|u~|kt~gv~}f{}v~[{|v~|[{}\\~}^{|w~}Cw~|O{|w~| q{}p~}x{}w~|_v}vy}w~y}|S{}m~}Xy}w~y}|w{|w}|[{|l~}|Vw~}N{|}w~y}" + "|w{}w~|`v}lw}|Wv~Lv~Tv}m{|u}Yv}_w~}mv~mv~hw~}m{|w~}\\{|n~|Zw~}x{}q~}W{}q~}|y{|w~|Zw~}Q{|}l~}P{|y}s~X{}q~}x{}w~|" + "X{}u~}X{|u~o{}v~|b{}w~}kv~}X{}w~}V{}d~Uv~Lw~|M{|w~| n{|}q~}u{|}w~bv~{}o~}|X{|r~|R{|}p~}|U{}l~}|^w~}m{|w~}W{}w~" + "}Xw}|i{|w}b{|w~|{|q~|y{|t~f{|q~|v{|q~|^{|l~}[{|w~}os~]{|}o~}|[w~}x{}q~}W{|}p~}|M{|}v~}W{|p~|`{|X~|e{}c~}_{}w~}V" + "k~v{}l~|^{|v~Y{}w~}hv~|Z{|v~R{|m~}| y{}w~ rx~| s{|x~} sv~}P{|}n~}|`{}b~}#{|w~}Lw~|Ty|pv~|\"y|}u~}y| 9y|}u~}y| " + "R{|Z~} ${|w~|{|q~|y{|t~Xx~}w{|x~} y}| q{}x~}aw}j{|w~kk~l{}x~}aw}gv~}U{|v~|d{|v~|l{|v~|d{|v~|l{|v~|d{|v~|l{|v~|" + "d{|v~|l{|v~|d{|v~|l{|v}bv}|t{}w~}j{|b~c{|}m~}|_{}c~}a{}c~}a{}c~}a{}c~}X{}w~}M{}w~}M{}w~}M{}w~}Z{|m~x}y|Z{}w~|k{" + "|t~_{|m~}|X{|m~}|X{|m~}|X{|m~}|X{|m~}|.w~}v{|}n~}|X{|}m~|X{|}m~|X{|}m~|X{|}m~|S{|v~|V{}w~}Mv|wy|}u~y}|Z{}p~}x{}" + "w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|]{}p~}x{}w~|g{}o~|r{|l~}|a{}m~}Y{|l~}|Y{|l~}|Y{|l~}|Y{|l~}|U" + "v~Lv~Lv~Lv~O{|y}v~y}|Xw~}m{|w~}\\{|n~|V{|n~|V{|n~|V{|n~|V{|n~|(w~|{|n~|V{}q~}x{}w~|\\{}q~}x{}w~|\\{}q~}x{}w~|\\" + "{}q~}x{}w~|W{}w~}Vw~}x{}q~}R{}w~} B{|t}|P{|t}|P{|t}|P{|t}|P{|t}|Nw~} 3{|~} ;f| '{|y}w~}y| 8{|y~|X{|x~}" + "h{|}w~}|ay|y}w~y}| rw~}N{}w~ ?{|w~| D{}w~I{|y}w~y}|%b|\\{|x}u~y}|!y|y}u~y}y|O{|y}w~y}| {{y|}u~y}|Vy|y}v~}y| u{|" + "w~| B{|v~| 1{|y}u~y}| o{|x}u~y}y| Fv~| 7y|y}v~y}| {{y|y}q~|#y|y}u~y}y| {{|y}v~y}y| a{|w~}C{}x~}O{|w~| oy}" + "v~}|vv|!{|}t~y}|!{|y}t~y}|Sv|Av~\"v|Lv~ Rv|mv|mv|hv|lv|Z{|y}u~}|Xw~}v{|}w~y}|T{|}w~y}|w{|w~|Zv|Ny|y}u~y}| {{|y}" + "w~}|uw|W{|u}|Wv}|o{|v}av|ju|Xv~| sv~Lw~|M{}w~| ly|}v~}|Uv~yy|}v~y}|S{|y}~y}|N{|y}v~y}|Qy|y}v~x}|[v|m{|w~}W{|w~" + "|#{|w~|x{|}w~}|v{|}y~y}c{|y}x~y}ry}x~y}|Z{|y}s~}y|G{}w~}|Zy|v~}|Ww~}v{|}w~y}|T{|y}v~y}| x{|y}w~}| Ry|y}v~y}|" + " Zy| rv~}M{|y}u~}|]`| Iw~|T{|y~}|u{|u~ 5{|w~|x{|}w~}|v{|}x~}Wx~}w{|x~} {}y~} r{|y}|Kw~|L{|y}|Hv~| E" + "{|y}u~y}| qy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|Sy|y}v~y}|+{|y~}r{|y}v~y}|R{|y}v~y}y|S{|y}v~y}y|S{|y}v~y" + "}y|S{|y}v~y}y| oy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|Zy}v~}|vv|d{|}v~y}|n{|y}u~y}y|\\{|}t~y}|U{|y}" + "t~y}|T{|y}t~y}|T{|y}t~y}|T{|y}t~y}|Rv|Lv|Lv|Lv|!v|lv|Z{|y}u~}|R{|y}u~}|R{|y}u~}|R{|y}u~}|R{|y}u~}|'{}x~|w{|y}u~" + "}|S{|y}w~}|uw|Z{|y}w~}|uw|Z{|y}w~}|uw|Z{|y}w~}|uw|Vv~|Vw~}v{|}w~y}|Qv~| Mw~| K{|y~| e{|w~Nw~" + "| ?{}w~ Cw~} .{}w~ @{|v~|d{}| Kv~| !u~| J{|w~}C{|w~O{|w~| 9w~} Iv~ bw~}9{|w~| X{|v~ rv" + "~Lw~|M{}w~| w~| D{|w~| .w~| ?{|v~}g{|x~| M{|v~ {|u~| K{|w~}Bw~|P{|w~| :{}w~} Iw~} bw~}9{" + "|w~| X{}w~| r{}w~|Mw~|Mv~ ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~|T{|l~| 4{|w~" + "|Ax~}w{|x~} {{}y~} /v~| ?x~| f{|x~ M{} %{}w~|Uw~}D{}w~| Lw~| K" + "{|y~| d{|w~Pw~| ?{|w~ C{}w~ .{|w~ ={|u~}|l{|u~| N{}v~ {{|u~| L{|q~}H{}x~}V{}q~| :v~| Iw~}" + " bw~}9{|w~| Xv~ q{}w~}Mw~|N{|v~ ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~|T{|}o~}| " + " 3{|w~|Ax~}w{|x~} {{|x~| 0v~}m{} N{|x~ e{}y~} Rv~Tw~}Dv~ S{}x~x{|w~| " + " K{|y~| c{}x~}R{}x~} >{|x~| Cw~} .{|x~| ;{}t~}|sy|}t~| N{|v~} y{|u~| M{|q~}H{|w~V" + "{}q~| ;{}v~ I{|w~} bw~}9{|w~| Y{}w~} q{|v~}|Ow~|P{|}v~} ;v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} " + " )v~}Iy~} gw~|Q{|y}v~y}| 1{|w~|Ax~}w{|x~} yx~| 0{}v~|p{|~} N{|x~| f{|x~ " + " S{}w~}Tw~}E{}w~} S{}x~|y{|w~ J{|y~| bw~|Sw~| >{}y~} K{}y~} 9{|p~x}q~}| N{|u~" + "| x{|u~ M{|q~} y{}q~| K{|}|p{|u~| I{}w~| bw~}9{|w~| Z{|v~ o{}q~}Tw~|U{|p~ :v~ S{|w~}W{|w~|#{|" + "w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~| W{|w~|Aw|vx| y{|x~} 0{|u~|s{}x~} N{|x~| " + " f{|x~| U{|v~Sw~}F{|v~ R{|x~}y{}w~ J{|y~| b{|x}|T{|x}| w{}g~}| Q" + "x|y}u~} v{|u~ N{|p} yp}| K{|x~}y|wy|}u~} J{|}v~ aw~}9{|w~| \\{|}v~} nq~}Tw~|U{|q~| :v~ S{|w~}" + "W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy~} gw~| W{|w~| :{|}w|}w~| /t~y}x|y}v~} U{|}|x{|w~| " + " f{}x~| W{|}v~}Sw~}H{|}v~} Qq~| J{|y} *{|}l~}| O{}q" + "~ tt| `{|i~} Lr~| aw~}9{|w~| `{}q~ l{}s~}Tw~|U{|s~}| 9v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~" + "} )v~}Iy~} gw~| W{|w~| :{|q~ .{|i~} U{|q~ ly}w|}w~| [{}q~Rw~}" + "L{}q~ P{}r~ M{|y}u~y}y| L{}r~| R{|j~} Ks~} `w~}9{|w~| " + " `{}r~| jy|v}|Tw~|U{|u}| 6v~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} )v~}Iy}| gw~| W{|w~| :{|r~| " + " -{|k~}| U{|r~} l{}r~} Z{}r~|Rw~}L{}r~| O{}t~ " + " k{}t~} -{|`}| `{|}m~}| Jt~} _w~}9{|w~| `{}s~| :w~| cv~ S{|w~}W{|w~|#{|w~| j{}w~ s{}" + "w~Uw~} )v~} d{|w~| 9y}w~y} ){}o~}| S{|}u~}| k{}r~ Y{}s~|Qw~" + "}L{}s~| M{}w~} j{}w~}| +{}`~} ]{|x}v~y}| Gw~y} ]w~}9{|w~" + "| `{}v~}| 8w~| cv~ S{|w~}W{|w~|#{|w~| j{}w~ s{}w~Uw~} g{|w~| 8{|}v~y}| Ly| " + " g{|y}w~}| X{}v~}|Ow~}L{}v~}| Iy| " + "l{}`~} Ww~| " + " L{}`~} Ww}| " + " r{" }; + + // Define a 104x128 binary font (huge sans). + static const char *const data_font_huge[] = { + " " + " " + " " + " " + " " + " " + " " + " " + " FY AY " + "'Z ;W @Y @Y 'Z Y @Y (Z :Y ?Y (Z 0Y ?Y (Z >X " + " " + " " + " " + " " + " )X AX '\\ )XAV 7YDY -] BY BY '[ +YEY 2X AY (\\ -YDY 'XAU 3Y AY (\\ )XAV 8YD" + "Y LY AY (\\ ,YEY #Y " + " " + " " + " " + " (X CX '^ +[CU 6ZEY .` C" + "X CY '] -ZEZ 2X CY (^ .ZEZ )[CU 2Y CY (] *[CU 7ZEZ LY CY (] -ZEZ %Y " + " " + " " + " " + " " + " 'Y EY '^ ,^FV 6ZEY /b CX DX '_ .ZEZ 2Y DX '_ /ZEZ +_FV 1X CX (_ ,^FV 7ZEZ " + " KX CX (_ .ZEZ &Y " + " " + " " + " " + " %Y GY '` .aHV 6ZEY 1e DY FX" + " 'a /ZEZ 1Y FX '` /ZEZ +aHV 0X EX '` .aHV 7ZEZ JX EX (a /ZEZ &X " + " " + " " + " " + " " + " #X GX 'XNX 0dKW 6ZEY 1f DY HX &WMX 0ZEZ 0X GX 'XMW 0ZEZ ,dLX /X GX 'WMX 0dLX 7ZEZ" + " IX GX 'WMX 0ZEZ 'X :T " + " " + " " + " " + " ;X IX 'XLX 1o 5ZEY 2ZLY " + " CX IX &WKW 0ZEZ /X HX (XLX 1ZEZ ,o .Y HX (WKX 1o 6ZEZ IY IY (WKW 0ZEZ (X X MX &WH" + "W 3VHa 4ZEY 3WDW CX LX 'WGW 2ZEZ -X LX 'WHW 2ZEZ -VHa +X KX (XHW 3VHa 5ZEZ GX KX (WGW 2ZEZ )X " + " ?b " + " " + " " + " " + " ?W MW &WFW 4VF^ 3ZEY 4WBV BW MX 'WEW 3ZEZ ,W M" + "X 'WFW 3ZEZ -VF^ )X MX 'WFW 4VF^ 4ZEZ FX MX 'WFW 3ZEZ *X ?d " + " " + " " + " " + " " + " ?W X 'WDW 5UC[ 2ZEY 4VAV AW X &WDW 4ZEZ +W NW 'WDW 4ZEZ -UC[ 'W MW 'WDW 5UC[ 3ZEZ " + "EW MW 'WDW 4ZEZ +X ?f " + " " + " " + " " + " @X \"X 'WBW 6UAW 0ZEY 4V@V B" + "X !W &WBV 4ZEZ +X !W 'WBW 5ZEZ .VAW $W W 'WBW 6UAW 1ZEZ DW W 'WBV 4ZEZ +W >f " + " " + " " + " " + " " + " ?X #W 'W@W U?V AX #W &W@V NX #W &V@W 9W \"W 'W@V .W " + "\"W 'W@V !W >XHX " + " 3Y " + " " + " " + " 6W $W &V>V U?V @W $W &W>V " + " NW $X 'V>V 8W $X (W>V /X $W 'W>V #W >XFX " + " 5Z " + " " + " ,Z " + " GZ " + " #U?V NY 7Z ,X CVCW MY " + " 7Z ,X $Z 7Z ,X >Z 6Y ,X 4Z 7Y +W 7Y @Z " + " " + " +Z " + " " + " HY \"U?V " + " MY 8Y ,Y CVBV LY 9Z ,Y #Z 9Z ,Z >Z 8Y ,Y 3Y 8Z ,Y 9Y " + " ?Z " + " *Y " + " " + " IY !U?V " + " LY :Y ,[ $R>U ,V@V MZ :Y +Z #Y 9Y +Z ?R" + ">U 8Y 9Y +Z %S?U HY :Z ,[ ;Y ?[ " + " " + " )Y " + " 8U " + " 9Y V@U JY Y @Y /X 0Y K` .X " + " ^ =ZEY @Y " + " NVAV

Y E^ /X 0_ %f 1] 'c " + " @ZEZ AY MV" + "CW X *^ +]DU 7ZEZ 5U>U JY ?Y *^ -YEZ 4Y " + " ?Y *^ .ZEZ 5[ ]DU 5Y >Y +^ ,]DU 6ZEZ Y ?Y +_ .ZEZ \"Y Z G[ G\\ @e !f JX !Y " + "LY %d :Y Y Ha /X 0b *j L] D_ " + " +g A[ LY 8Z -ZEZ \"Y 1o )V FX NZ FY " + "%Y ,X NX*Z NW 3WEW H\\ #[ !Z \"[ \"[ \"[ G[7T 8g 0Y " + "@Y +_ ,_FV 7ZEZ 5U>U IY @Y +` .YEZ 3X ?X *` /ZEZ 4[:P 8_FV 4X ?Y +` ._EU 6ZEZ NX @Y *_ .ZEZ #Y ;Y" + " FYEZ ;] GU W ,X " + " FV a \"d -g >d (d +b %b 4f Bg Ie \"e \"h " + " Ge !f IX \"Y LY &e :Y Y Jc /X 0c " + " -n $g I` .j >a ;e HU .U +b Ac 2ZEZ 'b " + " 5o -] Na (c KY .Y #_ 8Y!W'Y\"X.c$X 3XGX Mf -e +d " + ",e ,e ,e \"e=V ;k 1Y BY +XNW .aGV 7ZEZ 5V@V HX AY +XNW .YEZ 3Y AY *WNW /ZEZ 4\\>T 9`GV 3" + "X AY +XNW .`GV 6ZEZ NY AX *XNW /ZEZ $Y :Y FYEZ <_ IU (Q LZ 4Z2Z 1Q " + " &g %Z +XCX MT Y Kd /X 0e 0p " + " (m Lb 1m ,\\ 5~S E~R Ah 'Z :~]+[;Z;Z Ik LW DX DW /i ?Y(Y 4h 5ZEZ" + " ,\\ ,h 7\\ -o .` $f -h NY No %_ %c @_\"X-_\"W0h&W .\\ $\\ \"\\ #\\ #\\ )g 5~a Lm D~S I~S " + "H~R H~R 6Z !Z !Z \"Z :r 8^,Y Bk 2k 2k 2k 2k (kAX+Z(Z#Z(Z$Z(Z$Y'Y&[%[ MZ Im 1X CY *WMX /bHV 7ZEZ 5V@V G" + "X CY *WLW /YEZ 2Y CY *WLW 0ZEZ 3[AW :bHV 3Y BX *WLW 0bHV 6ZEZ MY CX *XMX 0ZEZ $X 9Y FYEZ " + " =a M~i 7U (Q N_ 9_8_ 3R )k 'Z +XCX +X@X 4T >e,X Cl &X IX *X GV " + " GX 5i 0d 2p ;u !^ ?y 2o F~S @n 4j /l N\\ 8x .r Nx 7~R E} >t KZ(Z :Z \"Z 4Z-] KZ 2_'_(^-Z" + " Ep =t 5o Au 1u N~d'Z(Z)Z MZY " + " Le /X 0e 1r +r c 3o -\\ 5~S E~R Dn *Z :~]+[;Z;Z Ko " + " Y EX EY 2m @Y)Y 6l 7ZEZ 0e 2k >e 1o 0c 'j /i X !r (b 'g Eb\"W0c#X0i(W -" + "\\ $] #\\ $] #\\ (f 6~b r F~S I~S H~R H~R 6Z !Z !Z \"Z :w =^,Y Ep 6p 7p 7o 7p ,oDY+Z(Z#Z(Z$Z(Z$Y'Y%Z%Z LZ Kp" + " 1X DX *WKW /WMYJV 6ZEZ 5V@V GY EY *WKX 0YEZ 1Y EY *XKW 1ZEZ 2[EZ :WMZKV 1Y DX *WKX 1WLYKW 6ZEZ L" + "Y EY *WKW 0ZEZ %X 8Y FYEZ >c M~h 7T (S !a Y >X 8f /X 0f 3t -s c " + " 4q /^ 6~S E~R Fr ,Z :~]+[;Z;Z Ms #[ FX F[ 4n @Y*Y 6m 7ZEZ 3k 5l Bk 4o 1f )k 0k #" + "X #u (b (i Fb#X0c#W/k+X .^ %] $^ %] $^ (d 5~b\"v H~S I~S H~R H~R 6Z !Z !Z \"Z :{ A_-Y Gt :t ;t ;s ;t " + " 0sGY*Z(Z#Z(Z$Z(Z$Y'Y$Z'[ LZ Ls 2X FX *WIW 1WJc 6ZEZ 4VBV EY FX *XJW 0YEZ 0X EX )WJW 1ZEZ 1[I^ x %_ ?y 5r F~S Ct :p" + " 6s /e *^ 9| 6z#~ =~R E} B}!Z(Z :Z \"Z 4Z/\\ HZ 2`)`(_.Z Iw @y >w Ez 9z!~d'Z(Z)[ Z;Z0]/Z4Z,Z$[(Z%~^ " + "@e 2X Gf +a MX %Y LY *i :Y Y >Y 9f /X 0g 5v " + " 0u d 6_K_ 0^ 6~S E~R Gu .Z :~]+[;Z;Z w &] GX G] 6U &o ?Y+Y 7X )n 7ZEZ " + "6p 7m Eo 6o 2h *l 1l %X #v (b )k Gb$X/c$X/l,W -^ &_ %^ &_ %^ 'b 4~b$z J~S I~S H~R H~R 6Z !Z " + "!Z \"Z :~ D_-Y Hw =v >w >w >w 4wIX)Z(Z#Z(Z$Z(Z$Y'Y$[)[ KZ Mt 1X HX )WHW 2VHb 6ZEZ 4WDW DX GX )WHW 1YE" + "Z /X GX )WHW 2ZEZ 0[M` ;VHb /X GY *WHW 3VHb 5ZEZ JX GX )WHW 2ZEZ 'Y 7Y FYEZ ?e M~f " + " 7U )U %g Bh@g :W .~T 't +Z +XCX ,X@X 3T Ak1X Er (X JX 'X IV HX 8q" + " =m 7y ?y '` ?y 6s F~S Dv Y >Y " + " :] %X &] 5]C\\ 1v Nc 7\\D\\ 1_ 6~S E~R Iy 0Z :~]+[;Z;Z!y (_ H" + "X H_ 7U 'p ?Y,Y 6X *o 7ZEZ 8t 9YH] Ht 9o 3i *XG[ 1VE[ &Y %x (b *[I[ Hb$W.c%X.VE[-X " + " ._ &_ %_ '_ %_ '` 4~c%} L~S I~S H~R H~R 6Z !Z !Z \"Z :~Q F`.Y Jz @z Az Ay Az 7zKX(Z(Z#Z(Z$Z(Z$Y'Y#[*Z JZ Na" + "J_ 2X IX )WGW 2VG` 5ZEZ 4XFX CX IX )WFW 2YEZ .X IX )WFW 3ZEZ /j 8VG` -X HX *WFW 4VG` 4ZEZ IX IX " + ")WGW 2ZEZ 'X 6Y FYEZ ?XKX M~f 7T )W 'i DiAi ;X 1~V (w -Z " + "+XCX ,X@X 3T AZI[2W Es (X KX &X IV HX 9s >m 7z @z )a ?y 7t F~R Dx >t 9v 8s 2` :~P <~Q&~S" + " A~R E} E~T$Z(Z :Z \"Z 4Z2] FZ 2a+a(`/Z K| C{ C} H| =|!~d'Z(Z(Z!Z9Z1^1Z2[0[!Z+[$~^ @X $X ;Y -e MX 'Y " + "LY +[ +Y Y >Y :[ #X #Z 6\\?[ 2v F\\ " + " 8Z@[ 2` 7~S E~R J{ 1Z :~]+[;Z;Z#} +` HX Ia 8U (q >Y-Y 6X +p 7ZEZ 9bMb ;U@Y JbMb :" + "n 3ZIZ +T@Y 2R>Y 'X %y (XLV +ZEZ IXMW%X.YMW%W-R>Y.W -` '_ &` '_ &` '` 4~c'~R N~S I~S H~R H~R 6Z !Z " + "!Z \"Z :~S Ha/Y K| B| C| D} D| 9|MX'Z(Z#Z(Z$Z(Z$Y'Y\"Z+[ JZ N]B\\ 2X JX *WEW 3UE_ 5ZEZ 3YJY AX JW )WE" + "W 2YEZ -X KX (WFW 3ZEZ .f 5UE_ ,X JX )WFW 4VF_ 4ZEZ HX KX )WEW 3ZEZ (X 5Y FYEZ @YJW M~" + "e 7U *X (j EkCk =Y 3~X )x -Z +XCX ,W?X 3T BYEY3X Ft (X KX %X JV " + " IX 9u ?m 7{ A{ *a ?y 8u F~R Ez @v :v :w 4` :~Q >~S'~U C~R E} G~V$Z(Z :Z \"Z 4Z3] EZ 2a+a(a0Z M~P D" + "| E~P I} ?}!~d'Z(Z'Z\"Z9Z1^1Z1Z0Z [,Z#~^ @X $X ;Y .g MW 'Y LY +Y )Y Y " + " >Y :Z \"X \"Z 7[=Z 3aE[ E[ 9Z>[ 3` 7~S E~R L~ 2Z :~]+[;Z;Z$" + "~P -b IX Jc 9U )r >Y.Y 5X ,]DX 7ZEZ ;\\>\\ \\ 0XDX ,R=Y MX (X %hEW (SG" + "V ,YAY JSHW%W-SGW&X GX/W ,` (a '` (a '` (a 5~d(~S N~S I~S H~R H~R 6Z !Z !Z \"Z :~T Ia/Y L~P F~P F~P F~P F~P" + " <~X&Z(Z#Z(Z$Z(Z$Y'Y\"[-[ IZ \\>Z 1X LX )VCW 4UD] 4ZEZ 2f ?X LX )WDW 3YEZ ,W KX )WDW 4ZEZ -b 2UD] *W" + " KX )WDW 5UD] 3ZEZ GW LX (VCW 4ZEZ )X 4Y FYEZ @XIX M~d 7U *Y *l GmDl ?[ " + " 6~Z *`C\\ -Z +XCX ,W?W 2T CYCY5X E]CZ (X LX $X JV IX 9]E^ @m 7aGb B^Ec ,b ?y " + "9aF[ F~R E_C_ B_E^ ;]E_ ={ 7b ;~R @cBb'~V D~R E} HeBc$Z(Z :Z \"Z 4Z4] DZ 2b-b(a0Z NbCb E} GbCb J~ Aa" + "B_!~d'Z(Z'Z#[9Z2_1Z0Z2[ N[.Z\"~^ @X $X ;Y /i MW (Y LY ,Y (Y Y >Y " + " :Y !X !Y 8[;Z 1\\ 0\\:U D[ ;ZbCh%Z(Z" + "#Z(Z$Z(Z$Y'Y![.Z HZ Z;Z 1X NX )WBV 5VBZ $e >W MX )WBW !X MX )WBW #` /UBZ (W MX )WBW 6UBZ " + " 9X MW (WCW MX 3Y GXHW M~d 8U *[ +m HnFn A] 9~\\ +^=Y" + " -Z +XCX -X@X 2U DXAX5W E\\=V (X LX #X .R@V?Q ,X :\\A\\ @m 7\\>_ CY<_ -c ?y :^=V F~Q E]>^ D]@] " + " j E~R E| Ha8^$Z(Z :Z \"Z 4Z5] CZ 2b-b(b1Z `<_ FZ@d I`=` K[@d C_:Z ~b&Z(Z'Z#Z8Z2`" + "2Z0[4[ LZ/[\"~^ @X #X Y >Y ;Z " + "!X !Y 8Z9Y 6d 4[5R CZ ;Y:Z 5b 8~R D~Q MbAb 8` =~]+[;Z;Z&`=` 1f KX Lg " + " ;U *\\=T =Y0Y 4X ,Z;R 5Z3Y &W !Y3Y 3W@W EW LX *W %jEW KV -X=X @W'X W'X EX1W ,b " + "*b (b )b )b )b 7ZH~R)a:] N~R H~R G~R H~R 6Z !Z !Z \"Z :Z>j Lb0Y N_<` J`<_ J`=` J`=` J`=` @`=e%Z(Z#Z(Z$Z(Z$Y'Y" + " Z/[ HZ !Z9Y 0W X )WAW 6VAW \"d Y >Y ;Y X !Y " + " 8Y8Y 6f 6Z2P BY j BZ(Z+[;Z;Z'_9_ 3h LX Mi <" + "U *[:R V EW KW +W %kEW KV .X;W @W'W NW(X CW2X -c *c )b " + "*c )c +c 7ZHZ 2_5[ NZ !Z Z !Z >Z !Z !Z \"Z :Z7d Mc1Y ^8_ K^8^ L_8^ L_9_ L^8_ B_9b$Z(Z#Z(Z$Z(Z$Y'Y [1[ GZ !Z" + "8Y 0W !W (V?W I` :X !W (V?W X \"X (W@W *d EX !W (W@W 0X \"X (V?W !W 1Y #d ," + "e +d +d ,e #XHW LZ#Z 7U +] -o KqHp C_ X #X " + " Y >Y ;Y X X 9Z7X 6g 7Y" + " #Z =Y8Z 7d 7[ Z )_7_ Bp EZ(Z+[;Z;Z(^5^ 5j MX Nk =U +[7P Z !Z !Z \"Z :Z3a Nc1Y!^5] L]4] N^5^ N^5^ N^5] C^5_#Z(Z#Z(Z$Z(Z$Y'Y N[2Z FZ \"Z7Y /W #W (W>V H^" + " 8X #W (W>V NW \"W (W>W .h EW \"X )W>W 0W #X (V=V \"W 0Y &j 1i 0j 1j 1i &X ` .\\5U -Z +XCX -W?W =r'X>W8X EZ ;X NY !X 1XDVDX 2X " + " &X ;[;[ BWDZ 7T2\\ \"\\ 1XMZ ?Y L\\ 2Z E[7[ G\\9[ >S5[ F`7` ?YNY Y >Y ;Y X Y :Y6Y 7i 9Y \"Y " + " >Y6Y 7YNY 6[ !Z *^3] Dt GZ(Z+[;Z;Z)]2] 6l NX m >U +Z !Y4Z 3X -Y NW(W (W " + " &X)X 8VZ !Z !Z \"Z :Z1` d2Y\"]2] N]2] ]2]!^2]!]2] E]2]\"Z(Z#Z(Z$Z(Z$Y'Y MZ3[ FZ \"Z6X .V $W 'VR4[ G^1^ AZNY Y >Y ;Y X Y :Y6Y 7j :Y \"Y " + " >Y6Z 9YMY 5[ \"Z *]1] Hy IZ(Z+[;Z;Z)\\/\\ 8n X !o ?U ,[ Y5Y 2X -Y W&W )W 'W%W 9V" + "Z " + "!Z !Z \"Z :Z/_!d2Y#]0]!]0]\"]0\\!\\/\\\"]0] F\\0]#Z(Z#Z(Z$Z(Z$Y'Y M[5[ EZ \"Y5X +P " + " %_K[ CY *r 9q 8r 9r 9q *X ;Z%Z >Q JT ,b 0q MsKs Ge " + "C^ *[0R -Z +XCX .X@X @v)X=X:W CY :X Y NX 1[HVH[ 1X 'X ;Z7Z 0Z 7P,[ ![ 3XLZ ?Y M[" + " 1Z EZ4[ I[5Z ?P1Z I^-] BYLY =Z1[ H\\(T'Z-^ JZ MZ *\\$S$Z(Z :Z \"Z 4Z:] >Z 2YMX1XMY(YNZ4Z$].\\ JZ5" + "\\!\\-\\ Z4[ GZ ;Y 9Z(Z%Z'Z4Z5XNX5Z*Z:[ F[6Z [ ;X \"X =Y 5\\C[ #Y LY -Y 'Y 8X >Y " + " >Y ;Y X Y :Y6Y 7k ;Y \"Z @Z5Y 9YLY 5[ #Z +\\.] J| KZ" + "(Z+[;Z;Z*\\-\\ :p !X \"q @U ,Z NY6Y 1X -X W#V *W (W#W :U;V +X DW LW )mEW KV" + " /X9X BW*X LW*X BW3W +YLY -YMY ,YLY -YMY ,YLY -YMZ ;ZFZ 5\\'S NZ !Z Z !Z >Z !Z !Z \"Z :Z-^\"e3Y#\\.]#].\\" + "#\\-\\#\\-\\#\\-\\ H\\.]$Z(Z#Z(Z$Z(Z$Y'Y L[6Z DZ \"Y5Y /[G[ " + " DY +u =u S LU ,c 1q MtLt Hf E] )[.Q " + " -Z +XCX .W?X Bx)X=X;X DZ :X X MY 0ZIVIZ /X 'X ;Z7[ 1Z AZ ![ 4XKZ ?Y MZ 0Z EZ3Z I[5Z " + "Z J])\\ CYLY =Z1[ I\\%R'Z+] KZ MZ +\\\"R$Z(Z :Z \"Z 4Z;] =Z 2YMX1XMY(YNZ4Z$\\,\\ KZ4[\"\\+[ Z4\\ I[ ;Y 9Z(Z$Z" + "(Z4Z5WLW5Z*[<[ DZ7[ !\\ ;X \"X =Y 6\\A[ $Y LY -Y 'Y 8X >Y >Y " + " ;Y X Y :Y6Y 7l Z !Z !Z \"Z :Z,^#YNZ3Y$\\,\\#\\,\\$\\,\\%\\+\\%\\,\\ MP" + " NP N\\-]$Z(Z#Z(Z$Z(Z$Y'Y KZ7[ Dq :Z4X /XC[ EY " + " -x @x >x ?x @x -X :Z'Z ?U MU -e 2q MtLt Ig E[ 'Z,P -Z +XCX .W?W By)" + "XZ0Z" + " J\\#Q'Z*\\ KZ MZ +[ Q$Z(Z :Z \"Z 4Z<] Y 7[>[ %Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y" + "5Y 7UH_ Z !Z !Z \"Z :Z+]#YMZ4Y%\\*\\%\\*\\&\\*[%[)[%[*\\ R!R [-_%Z(Z#Z" + "(Z$Z(Z$Y'Y K[9[ Ct =Y3X /U@[ \"Q EY .z B{ " + "B{ Az B{ /X :Z'Y >V U -g 4r NvNu Ji *\\ 5X.X 6\\ 7Z1Z M[ '[ 8Z +XCX /X@X C`MTL_)W;" + "WZ0Z " + "J[ 'Z)\\ LZ MZ ,\\ \"Z(Z :Z \"Z 4Z=] ;Z 2YLX3XLY(YMZ5Z%[([ LZ3[$\\)\\\"Z3[ IZ :Y 9Z(Z$Z)Z3Z6XLX6Z(Z>[ B[:Z !" + "\\ 9X !X >Y 8[<[ &Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y5Y " + "7RB] =\\ $Z BY2Y ;YJY 3[ &Z -[(\\!~U Z(Z+[;Z;Z,\\)\\ ?\\MXL[ $X %\\LXM\\ CU" + " ,Y *Q\"R DY9Y 0X -Y #V=_?V Cm *V LV Z !Z !Z \"Z :Z*]$YMZ4Y%[([%[(['\\)\\'\\)\\'\\)[!T#T\"\\-`&Z(Z#Z(" + "Z$Z(Z$Y'Y J[:Z Bw @Y6[ .Q<[ #S GY /`Da E`C" + "` DaD` C`Da E`C` 0X 9Y(Z ?X !U .h 4r NvNu Kk .c 9X.X 7^ 7Y1Y M[ &Z 7Z +XCX /X@X C\\" + "ITFY)W;W=X BY 9X !X KY +YNVNZ *X (X ;Z4Z 2Z @Z !Z 6YJZ ?Y Z /Z DY2Z JZ1Y ,T T MZ N[ NZ HZJ" + "Y >Z0Z K[ &Z(\\ MZ MZ ,[ !Z(Z :Z \"Z 4Z>] :Z 2YLX3XLY(YLZ6Z&['\\ MZ3[$['[\"Z2Z IZ :Y 9Z(Z#Z*Z2Z7XLX7Z'[@[ @Z;" + "[ ![ 8X !X >Y 9[:[ 'Y LY -Y 'Y 8X >Y >Y ;Y X Y ;Y" + "5Y %\\ =] %Y BY2Z =ZJY 3\\ 'Z .\\'[#cLZLb!Z(Z+[;Z;Z,['[ @\\LXK[ %X &\\KXL\\ " + " DU -Z +S$T EY:Y /X -Z %V?fBU Eo +VEg=V =VZ !Z !Z \"Z :Z)\\$YLZ5Y&\\'['['\\(['['['['['[#V%V#[-a&Z(Z#Z(Z$" + "Z(Z$Y'Y IZ;Z Ay BY9^ G[ %U HY 0]<^ G^=^ F" + "^<] E]<^ G^=^ 1X 9Z)Z @Z \"U .i 5r NvNu Lm 2h ;X.X 7^ 7Y1Y N[ &[ 7Z +XCX /W?X D[GTC" + "V)W;W=W AZ :X \"Y KY *j (X (X ZY .Y3Y 3Z '\\ MZ )Z ;Z 2^ +Y ;Y " + "X Y 6Y /Y5Y $[ =` G^ !Z IZ M\\ #Y2Z =YIZ 3\\ (Z .[%[%aIZI`\"Z(Z+[;Z;Z-[%[ B\\KXJ[" + " &X '\\JXK\\ H\\ 1Z ,U&V EY;Y /X ,Z 'V@jDV Gp +UDj?V >VZ !Z !Z \"Z :Z(\\%YLZ5Y&[&['[&[)\\&[)[%[)" + "[&[$X'X%[-b&Z(Z#Z(Z$Z(Z$Y'Y I[=[ Az CY;` 5\\ $] $\\ \"\\ #\\ $] 8\\/[ 3\\ '\\ #\\ \"[ \"[ \"[ &Z &[ ![" + " #\\ #[ ![ G[@W IYBZ J]8] I\\7\\ H]8] I]8] I\\7\\ 2X 8Y*Z @Z \"U .k 5q N~o Mm 4l =X" + ".X 7^ 7Z3Z NZ %Z 6Z +XCX /W?W D[FT@S)W;W>X AZ :X \"Y JX (f &X )X ;Z3Z 2Z @Z !Z 7" + "XHZ ?Y !Z /Z CY1Y JZ1Z 2Y Y $Z Z HY JYHY ?Z/Y L[ %Z'\\ NZ MZ -[ Z(Z :Z \"Z 4Z@\\ 7Z 2YKX5XKY(YKZ7Z'[" + "$[ NZ2Z%[%[#Z2[ JZ :Y 9Z(Z#[,Z1Z8XJW7Z%ZB[ >[>Z !\\ 7X X ?Y ;[6[ (e 7YE` (e 3aEY 8c 2r 5`DX GYEa (X NX " + "0X1Z 8Y FXD`9` YD` -c 9XD` /aEX :XD] 6g 7t BX0Y LY)Y+X6Z6X)Z/Z NX)Y I} 2Y X Y 9_>W KY5Y #[ =c h >XD` " + "AT#X 5Y 6X0X LY'Y ?RCW ?~Y!X?X?X ;d 'r!~W KZ1Y =YHY 2\\ )Z /[$[%_GZG_#Z(Z+[;Z;Z-[%[ C\\JXI[ 'X (\\IXJ\\ " + " (Y d 5Z -W(X FYV=W +X HX )^ ,Y1Y HnEW KV 0X7W BW-W HW.X M^/X )" + "Y +YHY 2YHZ 1YHY 2ZHY 1YHY 2ZHY ?ZDZ 9[ LZ !Z Z !Z >Z !Z !Z \"Z :Z'[%YKZ6Y'\\%[)[$[*[%[)[%[)[%[%Y)Z&[.d'Z(Z#" + "Z(Z$Z(Z$Y'Y H[>Z @{ DY=b ;f -f -f ,e -f -f Ae7c ;e /b )c *c *c 'Y NX NX X E[ >XD` -c )c *b *c )c '\\ &bDX L" + "X0X GX0X GX0X GX0X KY)X KYE` ?Y*Y 8[4\\ K[3[ J\\4[ I[4\\ K[3[ 3X 8Z+Z AZ !U /m 6q N~o No 6o ?X.X 8_ " + "6Y3Z Z $Z 6Z +XCX 0X@X DZET>Q)W;W>W ?Y :X \"X IY 'b $X )X ;Z2Y 2Z @Z !Z 8YHZ ?Y " + "!Z 0[ CY1Y JZ1Z 5\\ \\ 'Z!Z FY LZHZ @Z/Y L[ %Z&[ NZ MZ .[ NZ(Z :Z \"Z 4ZA\\ 6Z 2YKX6YKY(YKZ7Z'[$[ NZ" + "2Z&[#Z#Z2[ JZ :Y 9Z(Z\"Z,Z1Z8XJX8Z%[D[ ZHY 1\\ *Z /[#['^EZE^$Z(Z+[;Z;Z.[#Z C[IXH[ (X ([HXI[ (" + "Z $k 9Z .Y*Z FY=Y .X ,\\ *UAnCU J^CW -VCmAV ?W>V *X IX (a /Y1Y HnEW KV 0X7W BW.X HW.W La3X " + "(Y ,ZHY 2YGY 2ZHZ 3YGY 1YHZ 3YGY @ZCZ 9[ LZ !Z Z !Z >Z !Z !Z \"Z :Z'\\&YJY6Y'[$[)[$[*[$[+[#[+[$[&[+\\([.e'Z(" + "Z#Z(Z$Z(Z$Y'Y GZ?Z ?| EY>c >l 4l 3l 2l 3l 4l Gl=h @k 5h /h /h /h )Y Y NX Y E[ ?XFd 1g .h /h /h /h )\\ )hHX " + "LY0X HY0X GX0X GX0Y LZ+Y KYGd AY*Y 9[EXD[ M[1[ L[1[ K[1[ M[1[ 4X 8Z+Y A[ !T /n 6q N~o q 8q @X.X 8` 7" + "Y3Y Z $Z 5Z +XCX 0X@X DYDT EW;W?X ?Y :X #Y IY %^ \"X )X k 5}\"~W KY0Z ?YGZ 1[ *Z /Z\"[(]CZD^%Z(Z+[;Z;Z.[#[ CYHXGY 'X 'YGXHY 'Z &o" + " ;Z /[,[ FZ?Y -X +\\ +UBoBU LZ>W -UBnAU >W@W *X JX 'c 1Y1Y HnEW KV /W7W BW.W GW/X Lc5W 'Y ," + "YFY 4ZGY 2YFY 3YGZ 3YFY 3YGZ AZCZ 9Z KZ !Z Z !Z >Z !Z !Z \"Z :Z&[&YJZ7Y'[#[*Z\"Z+[#[+[#[+[#[&[-\\'[/YM[(Z(Z#" + "Z(Z$Z(Z$Y'Y G[A[ ?} FY?] :p 8q 8q 7q 8q 8p LqAl Do 9l 3l 3l 3l +Y Y NX Y #i @XHh 5k 2l 3l 3k 2l +\\ +lKX KY0" + "X HY0X GX0X GX0Y KY,Z KYIh CZ,Z :ZCXC[ [/[ N[.Z MZ.[ [/[ 5X 7Y,Z AZ !U /o 7p M~n s :s AX.X 8` 7Z4Y Y" + " #Z 5Z +XCX 0W?X EYCT EW;W@X >Z ;X #Y HX #Z X *X ;Z1Z 3Z @Z !Z 9XFZ ?Y \"Z /Z " + "BY2Z KZ0[ [/Z 4t =YJj 3q >kJY >o 8r ;kJY GYJk .Y NX 0X5\\ 6Y FY" + "JiBi$YJk 8o ?YJj 9kJX ;YJc Z !Z !Z \"Z :Z&[&YIZ8Y([\"[+[\"[,[\"Z+Z!Z,[\"[%[/\\" + "&Z/YL[(Z(Z#Z(Z$Z(Z$Y'Y F[BZ >Z@d GY@\\ :t ;t t TAU NX;W )P9P =UAWAYAU >XDX )X LX HY 3Y1Y HnEW KV /W7W " + "AP9P 9W0X FW0X ?Y8W &Y -YEZ 5YEY 4ZFZ 5YEY 4ZEY 5YEY BZBZ :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z%['YIZ8Y([!Z+Z![,Z![-" + "[![-[!Z$[1\\&[/XJZ(Z(Z#Z(Z$Z(Z$Y'Y EZCZ =Z;` HYA[ 8u oLX ;YLe ?u VAW?XAU ?ZHY (X MX EX 4Y1Y HnE" + "W KV /W7W AQ:Q :W0W EW1X Z !Z !Z \"Z :Z%['YHZ" + "9Y(Z Z+Z Z-[![-[![-Z [$[3\\%[0XI[)Z(Z#Z(Z$Z(Z$Y'Y E[E[ =Z9^ HYBZ 6v =v >w =w >v =v\"vIt Lt >t ;t ;t ;t /Y Y N" + "X Y *r BXKn qMY GYMp 0Y NX 0X8[ 2Y FYMoIp'YMq ?v BYMp ?qMX ;YMf ?u U@W?XAU >j (X " + " NX CX 5Y1Y HnEW KV /W7W AR;R ;W1X EW1W :XZ " + "!Z !Z \"Z :Z$Z'YHZ9Y)[ [-[ [.[ Z-Z NZ-Z [#[5\\$Z0XH[)Z(Z#Z(Z$Z(Z$Y'Y D[FZ w ?x >x ?w >w#wKv Nu ?v" + " =v =v =v 0Y Y NX Y +s BXLp >u \\ DX.X :c 7Z7Z!Y \"Z 4Z +XCX C~d&XBT DW=XB" + "X :[ >X $Y FY +f &X +X ;Z/Z 4Z AZ !Z ;YDZ ?YFP -Z?Q BZ ?Z5Z JZ/Z 5Z \"[ Gj Ii ;[\"X1Q,W\"YCZ BZ1" + "Z MZ \"Z$[!Z MZ /Z LZ(Z :Z \"Z 4ZH] 0Z 2YHX;XHY(YHZ:Z)Z N[!Z2Z([ NZ%Z2Z I[ ;Y 9Z(Z Z1Z,Z;XGW;Z N[L[ 4[H[ #\\" + " 1X MX AY BZ&Z 8^Ga AYN[H_ " + "YDY *X )b 6UDY%U V9W ,SU@W>W@T =h 'X X AW 5Y1Y HnEW KV /X9X ASZ !Z !Z \"Z :Z$Z'YGZ:Y)[ NZ-[ [.Z N[.Z NZ.[ NZ\"[7\\$[1XFZ)Z(Z#Z(" + "Z$Z(Z$Y'Y CZGZ ;Z6\\ IYCY 4^Ga ?^Ga @_Hb ?^Ga ?^Ga ?^Ga$^GaMaI`!bH\\ @aI` ?aI` ?aI` ?aI` 1Y Y NX Y ,u CXM^Nb" + " @aKa >aJa ?aJa ?aKa =`Ja 1\\ 0`Ic GY0X HY0X GX0X GX0Y IY0Z IYN[H_ FZ0Z X>Y&X#X%YJT9TIY&Y.TJY&X#X 8X 5Y0" + "Z CZ ;P4U 1w 9l J~m#z B[;[ EX.X :d 7Y7Y X )~Q #Z +XCX C~d&XBT DW=XCX 9\\ ?X $Y FY " + "-j (X +X ;Z/Z 4Z AZ \"Z :XCZ ?YM_ 5ZE^ IZ >Y6Z IZ0[ 5Z \"[ Jj Ci ?\\\"X6\\2X#YBY BZ1Z MZ \"Z$[!Z " + "MZ 0[ LZ(Z :Z \"Z 4ZI] /Z 2YHX;XHY(YGZ;Z)Z N[!Z3[([ NZ%Z2Z H[ ^ BcB] >_?W C^CYNY C]A] 4Y /]Bc GYNYD^ 2Y NX 0X;\\ 0Y FYNXC\\KYD](YNYC] A]B^ DcB] C^CYNX ;YNZDQ A\\" + ";V 5Y .Y1Y IY/Y&Y;_;Y\"Z;Z FZ0Y $[ 2Y X Y M];\\ F]E[JX IY9[ LY >ZKf =]=V CYNYC] K`2Z 5^ 9Y1Y!Z\"Z!^JZM^" + " K~Y!Y@X@Y E]C^ CaHl\"~W LY.Z BYBY .\\ 0Z 1Z M[-[>Z>[(Z(Z*Z;Z<[0[ N[$[ W@U =f &X !X @W 5Y1Y HnEW KV /X9X AT=T =W2X DW2W 8W=X $Y .YBY 8ZC" + "Z 7YBY 8ZCZ 7YBY 8ZBY FZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(YGZ:Y)[ NZ-Z MZ.Z N[/[ N[/[ NZ![9\\#[2YFZ)Z(Z#Z(Z" + "$Z(Z$Y'Y C[I[ ;Z5\\ JYCY 4X=^ @X=] @Y=] ?Y>^ @X=^ @X=^%X=l@\\\"_?W A]@\\ @]@\\ @^A\\ @^A\\ 1Y Y NX Y -w DXNY" + "C] A^C^ ?^C^ A^B] @^C^ ?^C^ 2\\ 1^C_ FY0X HY0X GX0X GX0Y IY0Y HcB] FY0Y ;X=X=Y(Y#Y'YJV;VIX&X.VJY(Y#Y 9W 4Z1" + "Z DZ =S4U 2y 9j I~l#{ BZ9Z EX.X :d 7Z8Y!Y *~R #Z +XCX C~d'YBT DX?XBW 7\\ @X $Y FY " + "/ZNVNZ *X ,X :Z/Z 4Z AZ #Z :XBZ ?o 9ZGc MZ =Z8[ HY0\\ 6Z \"[ Li >j C\\\"X8aGVBW$ZBZ CZ2Z LZ \"Z#Z!" + "Z MZ 0[ LZ(Z :Z \"Z 4ZJ] .Z 2YHXY 9Z(Z NZ2Z,Z\\ @^:T C\\?b D\\=\\ 5Y 0\\>a Ga?\\ 2Y NX 0X<\\ /Y Fa@\\MX@[(b@\\ B]?\\ Da?] D\\?a ;b 1Z6" + "S 5Y .Y1Y IZ1Z&Y;_;X![=Z DY1Y #[ 2Y X Y `>` I\\B[KX IY:\\ LY ?ZDa ?\\7R Cb?\\ F[3Y 5_ 9Y1Y\"Z Y!]IYJ] L" + "~Y!Y@X@Y F\\?\\ D^Ai\"~W LY.Z CZBZ .\\ 1Z 1Z LZ.[=Z>[(Z(Z*Z;Z<[0[ N[%\\ XAU V ?W3X CW3X 8X>W #Y /Z" + "BZ 9YAY 8ZBZ 9YAY 8ZBZ 9YAY FZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(YFZ;Y)Z MZ-Z MZ/[ MZ/[ N[/Z M[![;\\\"[3YE[*" + "Z(Z#Z(Z$Z(Z$Y'Y B[JZ :Z4[ JYCX 3U8\\ @U8\\ AV8\\ @U7\\ AU7[ @U8\\%U8h=\\$]9T B\\=\\ B\\=\\ B\\=\\ B\\<[ 2Y Y " + "NX Y .x Da?\\ C]?] A]?] B\\?] B]?] A]?] 3\\ 2]?] FY0X HY0X GX0X GX0Y IZ1Y Ha?] GY1Z ~d W5T 2{ 9i H~k$} DZ7Z FX.X :d 7Z9Z!X )~R #Z 0~d&XBT DX?XCX 6\\ " + " =Y EY 0ZMVMZ +X ,X :Z/Z 4Z B[ %\\ :XBZ ?q ;YHg Z \\ 0Z 6Y.Z CYAZ -\\ 2Z 1Z LZ.[=Z=[)Z(Z*Z;ZW>X@T ;a #X #X =W 6Y1Y GmEW KV .X;X @W@W @W3W BW4X 6W?X #Y /Y@Y :" + "ZAY 8Y@Y 9YAZ 9Y@Y 9YAZ GZ@Z ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(YFZ;Y)Z M[/[ MZ/[ MZ/Z LZ/Z M[ [=\\!Z3YD[*Z(Z#Z" + "(Z$Z(Z$Y'Y AZKZ 9Z4[ JYDY 3R3[ AR3[ BS3Z @S4[ AS4[ AR3[&R3e:[&]6R C\\:[ D\\:[ D\\:[ D\\:[ 3Y Y NX Y /_B] E_<" + "[ C[;[ B\\<\\ C\\<\\ C[;\\ C\\<\\ 3\\ 3\\<\\ FY0X HY0X GX0X GX0Y HY2Z H`<[ FY2Y ;X~d#Z6U 3} :h G~k%~P EY5Y FX.X ;ZNY 6Y9Z!X *~R \"Z 0~d&YCT CXAXBW 5] " + " >Y EY 2ZKVKZ -X ,X :Z/Z 4Z BZ &] :XAZ ?s =YJk #[ ;[=[ FZ1\\ 6Z \"[ #j L~d Ki J\\!X:hKVAW%Y@Y CZ5\\ L" + "[ \"Z#Z!Z MZ 0Z KZ(Z :Z \"Z 4ZL] ,Z 2YGX=XGY(YEZ=Z*[ M[\"Z4['Z LZ&Z4[ F` BY 9Z(Z MZ4Z*Z=XEW=Z Jd .ZLZ #\\ .X" + " LX BY JQ1[ D_:[ B\\ ([9_ F[7Z 6Y 1[:_ G^9Z 3Y NX 0X>\\ -Y F^;b;Z)_:Z D[:\\ F_:[ G[9^ ;_ /Y EY .Y1Y " + "HY2Z$Y=a=Y NZ@[ BY3Z %[ 0Y X Y \"eCd L[>YLX HY>^ IY AY=] @Z &_:Z DY4Y 5a :Y1Y\"Z Z$\\GYG\\ EY9Y IY@X@Y G" + "Z9[ G\\;[ 0Y 5Y.Z DZ@Y ,\\ 3Z 1Z LZ.ZUDX!T\"XW>X@U :] !X $X Z !Z !Z \"Z :Z#Z(YEZ~d&^7U 4~ 9f E~i%~R GY4Y FX.X ;ZNZ 7Y9Y!X )~R \"Z NW?W BYCT CYBXCX 6_ ?Y EZ 5ZI" + "VIZ /X ,X :Z.Y 4Z C[ )_ :YAZ ?t >YKn %Z 9\\A\\ EZ1\\ 6Z \"[ &j I~d Hi N\\ W:jLVAW&Z@Z DZ8^ KZ !Z#[\"Z " + " MZ 0Z KZ(Z :Z \"Z 4ZM] +Z 2YGY?XFY(YEZ=Z*Z L[\"Z4['Z LZ&Z4[ Fc EY 9Z(Z MZ5Z)Z>XDW=Z Ic .[NZ #\\ -X KX CY " + " )Z D^8[ D\\ '[8^ FZ5Z 7Y 2[8^ G]8Z 3Y NX 0X?[ +Y F]9`9Y)^9Z E[8[ F^8Z GZ8^ ;^ .Y EY .Y1Y GY3Y#Y=WNX=Y M" + "ZAZ AY3Y %[ /Y X Y #gEf N[W>W?U 7W <~d BX ;W 6Y1Y GmEW KV -X=X ?YBY BW4W AW5X 5W@W !Y 0Y?Z ;Y?Y :Z@Z ;Y?Y :Z?Y ;Y" + "?Y HZ?Z <[ IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(YEZY D~P JZ !Z#[\"~Q Dy Z K~] :Z \"Z 4ZN] *Z 2YFX?XF" + "Y(YDZ>Z*Z L[\"Z5\\([ LZ&Z5\\ Eg JY 9Z(Z MZ5Z)Z>XDX>Z Ib ,f $\\ ,X KX CY (Y D]6Z D[ '[7^ GZ4Z 7Y 2Z6] " + "G]7Z 4Y NX 0X@[ *Y F]8^8Z*]7Z FZ6[ G]6Z I[7] ;] -X DY .Y1Y GY3Y#Y=WNX=X L[CZ ?Y4Y &[ .X NX Y $iGh Z:XNX" + " GYHg HY CY8\\ CY $]7Z DY6Y 4b ;Y1Y#Z MZ&[EYE[ FY9Y IY@X@Y HZ7[ I[7[ 2Y 5~V DY>Y +\\ 5Z 2Z KZ/[W>W?U K~d CX ;X " + " 6Y1Y FlEW KV -Y?Y ?ZCZ CW5X AW5W 5XAX !Y 0Y>Y Y Y ;Y?Z JZ>~Q3[ I~Q G~Q F~Q G~Q 5Z !Z !Z " + "\"Z :Z#Z(YDZ=Y*[ LZ/Z L[0Z L[0Z LZ0[ LZ L[C\\ N[5X@Z*Z(Z#Z(Z$Z(Z$Y'Y ?e 7Z3[ KYDY @Y Y !Z Y Y Y 4_4Y)[ %Z3" + "Y GZ3Y FZ4Y FZ4Y 4Y Y NX Y 1[8Z F\\7Z F[7[ EZ6[ G[6[ G[6Z EZ6[ Y D~ IZ !Z#[\"~Q Dy![ K~] :Z \"Z 4h )Z 2YFX@YFY(YDZ>Z*Z KZ\"Z5\\([ LZ&Z6\\ Ck Y 9Z(Z LZ6Z(" + "Z?XDX?Z G` *d #[ +X KX CY 'Y E]6[ F[ &Z5] GY2Y 7Y 3Z4\\ G\\6Z 4Y NX 0XA[ )Y F\\7]6Y*\\5Y G[5Z G\\5Z I" + "Z5\\ ;] -X DY .Y1Y GZ5Z#Y>XMW>Y K[E[ ?Y5Y &[ .Y NX Y $XIZHZIY!Z:XNX GYHf GY DY6[ CY $\\5Y CX6Y 5c ;Y1Y#" + "Z MZ&[EYDZ FY9Y IY@X@Y IZ5Z IZ5Z 2Y 5~V EZ>Y *[ 5Z 2Z KZ/[Z EiKh 6X /XC^ BTDX U\"YA\\ 4ZCZ N~d &U>W?X>T K~d EY :W 5Y1Y EkEW KV ,YAY =ZCZ DW6X @W6" + "X 5W@W 'Z>Y Z =Y=Y ;Y>Z =Z>Y JZ>~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z :Z#[)YDZ=Y*[ LZ/Z KZ0Z L[1[ LZ0[ L" + "Z K[E\\ M[6Y@Z*Z(Z#Z(Z$Z(Z$Y'Y >d 7Z2Z KYDY @Y Y Y NY Y !Y 4^3Z*Z $Z3Z HZ3Z HZ3Z HZ2Y 5Y Y NX Y 2[6Z G" + "\\6Y FZ5[ G[5Z GZ5[ GZ5[ G[5Z =[:_ HY0X HY0X GX0X GX0Y GZ5Y F\\5Z GY5Z Z6Y &[ .Y NX Y %WEYJYEX#Z8a GYHe FY DX4[ DY $\\5Y CY8Z 5d Y*Z KZ/Z KZ0Z L[1[ L[1[ LZ J[G\\ L[7Y?Z*Z(Z#Z(Z$Z(Z$" + "Y'Y >c 6Z2Z KYDY ?Y X NX NY Y Y 4\\1Y+[ %Z1Y HY1Y HY1Y HY1Y 5Y Y NX Y 3[5Z G[5Z HZ3Z GZ4[ HZ4Z HZ3Z GZ" + "4[ >Z9` IY0X HY0X GX0X GX0Y FY6Z F\\4Z GY6Y ;W9X9W-X JX,WD[I\\DW,W1[DW-X JX =X 1Y6Z <~d'RKY:U 5~U J" + "~T$~g'~X KY1X GX.X Z ?y DgF` *Z 2k >Z4^ 6Z \"[ 1j >~d =i -[ LW=\\C_?W)YZ=Z =YZ=Z =YZ=Z LZ=~Q3Z H~Q G~Q F~Q G~Q" + " 5Z !Z !Z \"Z Ew5[)YCZ>Y*Z KZ/Z KZ0Z KZ1[ L[1Z KZ I[I\\ K[8Y>[+Z(Z#Z(Z$Z(Z$Y'Y =a 5Z2Z KYDY ?Y Y X MX Y Y" + " 4\\1Y+Z $Y0Y IZ1Y IZ1Y IZ0X 5Y Y NX Y 3Z3Y GZ3Y HZ3Z HZ2Z IZ2Z IZ3Z GZ3Z >Z:a IY0X HY0X GX0X GX0Y FZ7Y E[" + "3Z GY6Y ;W9X9W-W HW,WC[K\\CW,W2[CW-W HW =X 1Z7Z <~d NX:U 5~V M~X%~e&~Y LX0Y HX.X =ZJY 6Y=Z W " + " NZ 3Y X@X ?]IT ?hCW 7h2X ;Y CY 7TAVAT 1X .X 8Z.Y 4Z G\\ 6g 5X=Z ?X?a EeB^ +Z /f ;[5" + "^ 4i ;~d :i 1[ LWr *Y " + "9Z(Z KZ8Z'Z@XBX@Y D\\ &` $\\ )X JX DY &X E[2Z HZ %Z3\\ IZ/X 8Y 4Z2[ GZ3Y 4Y NX 0XE\\ &Y FZ4[5Y*[4Z IZ" + "2Z H[2Y KY2[ ;[ +X DY .Y1Y FZ7Z!Y?WLX?X H[IZ ;Y7Y '[ ,Y NX NY *Q NV@WLW?U#Z8` FYHd .^FY EX2[ DX $[3Y CX8Y" + " 5YMY [/[IuI[.\\ 4X 4\\ =X =\\$\\" + " =X MZAU -Z &X8Y G~W 6X 0W<\\ FUEX MT iNW 8[D[ K~d &T=WE\\QZZeBX] ,Z 1j <[7_ 7i 8~d 7i 5[ KW=Z=" + "\\?W*Y:Y F{ FZ !Z\"Z\"~Q Dy![1j&~] :Z \"Z 4e &Z 2YDXCXDY(YBZ@Z*Z KZ\"Z[/[IuI[/\\ 3X 3\\ >X >\\\"\\ >X MZAU -Z 'X6X 5c " + "%X 1X;\\ GUEX MT NgMW 9[D[ J~d &T=m;T K~d In 4TA[ 4Y1Y BhEW 3Z DX )i 5[D[ IX9W5Z3W8WFj?TA[BX5Z KY" + ";Z @Z;Z ?Y:Y @Z;Z ?Z;Y ?Y;Z NZ<~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)YAY?Y*Z KZ/Z KZ1[ KZ1[ L[1Z KZ G[M\\ IZ8" + "X<[+Z(Z#Z(Z$Z(Z$Y'Y <_ 4Z2Z KYD[ @X NX Y NY X NX 3Z/Y-Z $Z/Y KZ/Y KZ/Y KZ/Y 6Y Y NX Y 4Z2Z HZ3Y IZ1Z I" + "Z1Z JY1Z JZ1Z IZ1Z @Z;XNZ JY0X HY0X GX0X GX0Y EY8Y D[2Z GY8Y ;X9X8W.W HW-W@hAW-X4[@W.W:[:W =X 0Z9Z I" + "[ 7YY ~m 4Z 3Y W?X >g =cAW?]'[K\\5Y ;Y CZ %V M" + "X /X 7Y-Z 5Z H[ 4l ;XZ>Z.[IuI[0\\ 2X 2\\ ?X ?\\ \\ ?X MY@U 8y ;X6X 4a $X 1X9[ HUEX MT MeLW :[D[ I~d &T=l:T " + "K~d Io 5m 3Y1Y AgEW 3Z Nl 2g 3[D[%lDX5Z>mDXFk@mAW5[ LZ:Y @Y:Z ?Y:Y @Z:Y ?Y:Z AZ:Y NZ<~Q3Z H~Q G~Q F~Q G" + "~Q 5Z !Z !Z \"Z Ew5[)YAZ@Y*Z KZ/Z KZ1[ KZ1[ L[1Z K[ Gh HZ9X;[+Z(Z#Z(Z$Z(Z$Y'Y ;] 3Z2Z KYC[ AX NX Y NY Y X" + " 3Y.Y-Z $Y.Y KY.Y KY.Y KY.Y 6Y Y NX Y 4Z1Y HY2Y IZ1Z IY0Z KZ0Z KZ1Z IY0Z @Y;XMZ JY0X HY0X GX0X GX0Y DY9Y D" + "Z0Y GY9Z ;W8X8W.W HW-W?f?W.W4[?W.W:[:W =X 0Z9Y HZ 5X_@XAa*[I\\6Y ;Y CZ %V MX /X 7Y-Z 5Z I[ 3n >X;Z ] G`9\\ .Z 4s @[9` " + " =i /i ;Z IV=Y9Z>V+Z:Z G~P JZ !Z\"Z\"~Q Dy!Z1l'~] :Z \"Z 4g (Z 2YDYEXCY(YAZAZ*Z KZ\"}$Z K['z 5r /Y 9Z(Z JZ;Z" + "$ZAW@WAZ F_ %\\ $[ &X IX EY &Y FZ0Y IZ %Y/Z IY.Y 9Y 4Y0Z GY1Y 5Y NX 0XH[ \"Y FY3Z3Y+Z2Y JZ0Z IZ0Y MY0" + "Z ;Z *Z FY .Y1Y DY9Y MYAWJXAY F[MZ 8Z:Y )[ +Z MX N[ 7g1U U<^;U&Z6^ EYHj 9gJY FX/Y CY &Z2Y BYY1Y%Z" + " J[*ZBYBZ HY9Y IY@X@Y KY0Z MY/Y 4Y 6~W GZ:Z ,[ 6Z 2Z KZ/Z;Z;Z*Z(Z([>Z?[.ZHuI[1\\ 1X 1\\ @X @\\ M\\ @X NZ" + "@U 8y ;W4X 5` #X 1X8Z HUEX MT LbJW ;ZC[ H~d &T=j8U L~d Io 5l 2Y1Y @fEW 3Z Nl 0c 0[CZ&lDW5[>mEXE\\N^" + "AlAX6\\ LZ:Z AY9Y @Z:Z AY9Y @Z:Z AY9Z!Z;~Q3Z H~Q G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)Y@ZAY*Z KZ/Z KZ1[ KZ1[ L[1Z K" + "[ Ff GZ:X:[+Z(Z#Z(Z$Z(Z$Y'Y :\\ 3Z2Z KYC\\ BY X NX NY Y X 3Y-X-Y #Y-X KY-X KY-X KY-X 6Y Y NX Y 5Z0Y HY" + "2Y IY/Y JZ0Z KZ0Z KY/Z KZ/Y AZ;WKY JY0X HY0X GX0X GX0Y DY:Z DZ0Y FY:Y :WK~KW.WK}KW-W>d>W.W5[>W.W:[:W =X /" + "Y:Z IZ 4Y=T 6~[%~b'~_%~\\ NY/X HX.X >ZHY 6Y?Y N~m 4Z 3Y !X@X ;l @[>WBe,ZG\\7Y ;Y" + " CZ %V ;~c LX 7Y-Z 5Z J\\ 2n @Y;Z N\\ G`8\\ /Z 5u A\\V+Y8Y G~R LZ !Z\"Z\"~Q" + " Dy![2l'~] :Z \"Z 4h )Z 2YCXEXCY(Y@ZBZ*Z KZ\"|#Z K['x 0q 1Y 9Z(Z IZY1Y%Z IZ*YAYBZ HY9Y IY@X@Y KY/Y MY/Y 4Y 6~W GY9Z " + "-[ 5Z 2[ LZ/Z;Z;Z*Z(Z'[?Z?[.[IuI[2~n BX B~n AX A~m AX NZ@U 8y dEW 3Z Nl ._ ,ZCZ'lEX6\\>mEWDVCZBkAX6] LY8Y BZ9Z AY8Y BZ9Z AY8Y BZ9Z!Z;~Q3Z H~Q " + "G~Q F~Q G~Q 5Z !Z !Z \"Z Ew5[)Y@ZAY*Z KZ/Z KZ1[ KZ1[ L[1Z KZ Ee FZ;Y:[+Z(Z#Z(Z$Z(Z$Y'Y :[ 2Z2Z KYB\\ CY X NX" + " NY Y Y 4Y-Y.Y #Y-X KY-X KY-Y LY-Y 7Y Y NX Y 5Z0Z IY2Y JZ/Z KZ/Y KY/Z KY/Z KZ/Y#~d$ZX /Z;Z JZ 2X>U 6~\\'~c&~^$~Z MY/X HX.X >YGZ 7Z@Y " + "N~m 4Z 3Y !X@X :n 'WBg.ZE\\8X :Y CZ %V <~e NX 6Y-Y 4Z K\\ #a AX:Z M\\ H_6[ 0Z" + " 6aI` A]?c ?f $f ?Z IW>Y7Y>V,Z8Z HZ8` MZ !Z\"Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZN] *Z 2YCXFYCY(Y@ZBZ*Z KZ\"{\"Z " + "K['v +o 2Y 9Z(Z IZq:X !U:[9U&Y5] DY?d =jLX FY/Z C[ " + ")Y1Y AX=Z 6ZIY >Y1Y%Z IZ*YAYAY HY9Y IY@X@Y KY/Y NZ/Z 5Y 5Y-Y HZ8Y .[ 4Z 1Z LZ/Z;Z;Z*Z(Z'[?Z@[-[ L[3~o BX B~o BX" + " B~o BX NZ@U 8y mFXDS?YBi?W5] CY 4Z8Y BY7Y BZ8Z CY7Y AY8Z CZ8Y!Y:Z Z !Z !Z \"Z Ew5[)Y?ZBY*Z KZ/Z KZ1[ KZ" + "1[ L[1Z KZ Dc E[=Y9[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z2Z KYB^ &i 0i 1i /i 0i 0i Ej-Y/Z $Z-Y MZ-Y MZ-Y LY-Y 7Y Y NX Y 5Y/" + "Z IY1X JZ/Z KZ/Z LY.Y LZ/Z KZ/Z$~d$Z=WIZ KY0X HY0X GX0X GX0Y CYX .Y;Y JZ 1Y?U 6~\\(~e'~]\"~X LX.X HX.X >YFY 7ZAZ N~m 4Z 3Y !W?X 9p +XCi0ZC\\9X " + " :Y CZ %V <~e NX 6Z.Y 4Z L\\ M^ CY:Z L[ H^4Z 0Z 7^A^ C_Ce ?c Mc @Z HW>X6Y>V,Y7Z HZ5^ NZ !Z\"" + "Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZM] +Z 2YBXGXBY(Y?ZCZ*Z KZ\"z![ LZ&w 'k 3Y 9Z(Z IZ=Z\"ZCX@XCZ Gc &Z &\\ $X HX FY " + " >q FY.Y JY $Y/Z JY,X 9Y 5Y.Y GY1Y 5Y NX 0XL\\ NY FY3Z3Y+Y1Y JY.Z JY/Z NY/Y ;Y (^ KY .Y1Y CY;Y KYCXIXCY " + "Bc 4Y\\IYMX FY/Z B\\ +Y1Y AY>Y 5ZIZ ?Y1Y%Z IZ*YAYAY HY9Y IY@X@Y KY/Y NZ" + "/Z 5Y 5Y-Y HZ8Z 0\\ 4Z 1Z LZ/Z;Z;Z*Z(Z&[@Z@[-[ L[4~p BX B~o BX B~p CX NY?U 8y mFWCQ;XAe>X6UNW CY 4Y7Z DZ7Y BZ8Z CY7Z CZ7" + "Y CY7Z#Z:Z Z !Z !Z \"Z :Z#[)Y?ZBY*Z KZ/Z KZ0Z KZ1[ L[1Z KZ Ca D[>Y8[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ " + "KYA^ /q 9r 9q 7q 8q 9r Mq,Y/Z $Y,Y MY,Y MY,Y MZ-Y 7Y Y NX Y 5Y.Y IY1X JZ/Z KY.Z LY.Y LZ/Z KY.Z$~d$Y=XIZ KY0X" + " HY0X GX0X GX0Y CYX .YW-Y6Y HZ2\\ Z !Z\"Z\"Z MZ 1[2l'Z(Z :Z \"Z 4ZL] ,Z 2YBXGXBY(Y?Z" + "CZ*Z KZ\"x N[ LZ&x #f 3Y 9Z(Z HZ>Z\"ZCW>WCZ Hd &Z &[ #X HX FY At FY.Y JY $Y/Z JY,Y :Y 5Y.Y GY1Y 5Y NX" + " 0XM\\ MY FY3Y2Y+Y1Y JY.Z JY.Y Z/Y ;Y (b Y .Y1Y CY;Y KYCWHXCY Bb 3Y=Y *[ 6e JX Ke KzF^ !U9Y7T'Z4[ CY7] @[E" + "XNX GZ.Y Ai 9Y1Y AY>Y 5YHZ ?Y1Y&[ IZ+ZAYAY HY9Y IY@X@Y KY/Y NZ.Y 5Y 5Y-Y IZ6Y 0[ 3Z 1Z LZ/Z;Z;Z*Z(Z&\\AZA[,[ L[" + "4~p BX B~o BX C~q CX NY?U 8y Z !Z !Z \"Z :Z#[)Y>ZCY*Z K" + "Z/Z KZ0Z L[1[ L[1Z KZ B_ C[>X7[+Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ KY@_ 5u XHZ KY0X HY0X GX0X GX0Y BY=Y BY.Y FY=Z 9WK~KW/WJ}JW.W:\\:W.W" + "9[:W/W9[9W >X .Z=Y JZ /X@U 6~^*~g&~Y N~V KX.Y IX.X ?ZFZ 7ZBY L~l 4Z 3Y \"X@X 3n /X" + "CZIZ2Z@\\W.Z6" + "Z IZ1[ Z !Z#[\"Z MZ 1[2l'Z(Z :Z \"Z 4ZK] -Z 2YBXHYBY(Y>ZDZ*Z KZ\"v L[ LZ&z !c 4Y 9Z(Z HZ>Z\"ZDX>XDY Ge 'Z '[ " + "\"X GX GY Dw FY.Y JY %Z/Z J~W :Y 5Y.Y GY1Y 5Y NX 0XN\\ LY FY3Y2Y+Y1Y JY.Z JY.Y Z/Y ;Y 'e $Y .Y1Y CZ=Z" + " KYDXGWDY @a 3Z>Y +[ 5d IX Ic L~d !U8X7T'Z4[ CY5\\ AZCa GY-Y @h 9Y1Y @X?Z 6ZGY ?Y1Y&[9X9Z+ZAYAZ IY9Y IY@X@Y " + "KY/Z Y-Y 5Y 5Y.Z IZ6Z 2[ 2Z 1Z M[/Z;Z<[*Z(Z%[AZB\\,[ LZ3~p BX B~o BX C~q CX NY?U 8y Z !Z !Z \"Z :Z#[)Y>ZCY*Z KZ/Z KZ0Z L[1[ L[1[ LZ A] B[?X6Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z3[ KY?" + "_ 8w ?x ?w =w >w >w$~u/Y #~W M~W M~W M~W 7Y Y NX Y 6Z.Y IX0X JY-Y KY.Z MZ.Z MY-Y KY-Y$~d$Y?XFY KY0X HY0X GX0" + "X GX0Y BY>Z BY.Y EY>Y 8WK~KW/WJ}JW.W;]:W.W:[9W/W9[9W >X -Y>Z KZ .YAU 6~^*~g%~W L~T JX.Y IX.X ?YEZ 7Z" + "CZ L~k :y KY \"X@X 0m 1WCYEY3Y>\\=X 9Y BY %V <~e =l X 5Z.Y 4Z \\ E[ GY8Z JZ I]" + "2Z 2Z 8[7[ BqMZ ?^ C^ @Y GV=W4X>V-Y5Z IZ0[!Z !Z#[\"Z MZ 1[2l'Z(Z :Z \"Z 4ZJ] .Z 2YAXIXAY(Y=YDZ*Z L[\"s" + " I[ LZ&[Cc Na 5Y 9Z(Z HZ?Z YDX>XEZ Hg (Z (\\ \"X GX GY Fy FY.Y KZ %Z/Z J~W :Y 5Y.Y GY1Y 5Y NX 0e KY" + " FY3Y2Y+Y1Y KZ.Z JY.Y Y.Y ;Y &h (Y .Y1Y BY=Y IXDXGWDY ?_ 1Y?Z ,[ 4b GX Ga L~c T6V6T'Z4[ CY4\\ CZ@_ GY-Y >f " + "9Y1Y @Y@Y 5YFZ @Y1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y KX.Z Y-Y 5Y 5Y.Z IY5Z 3[ 1Z 1Z M[/[WEY9T -X EY1Y 1WEW 3Z 6ZCZ 7X7" + "UKV HW*W KX6ULW CY 5Y5Z FZ5Z EY4Y FZ5Z EZ5Y EY5Z%Z9Z Z !Z !Z \"Z :Z#Z(Y=ZDY*[ LZ/Z KZ0Z L[0Z " + "LZ0[ LZ A] B[@X5Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z4[ JY>` Y 8WK~KW/WJ}JW.W<_;W.W;[8W/W9[9W >X -Z?Z " + " LZ -YBU 5~^*~h%~U J~R IX.Y IX.X @ZDY 6YCZ LW 'y JY \"W?X ,j 3WCYCY4Y=\\>X 9Y CZ" + " %V <~e =l X 5Z.Y 4Z !\\ C[ IY7Z JZ I]2Z 3[ 9[5[ BoLZ ?a Ia @Y HW>X3W>V.Z4Y IZ/Z!Z !Z#[\"Z MZ 0" + "Z Z'Z(Z :Z \"Z 4ZI] /Z 2YAXIXAY(Y=ZEZ*Z L[\"o DZ LZ&Z<^ M_ 5Y 9Z(Z GZ@Z ZEX>XEZ I[MZ (Z )\\ !X GX GY " + "Gz FY.Y KZ %Y-Y J~W :Y 5Y.Y GY1Y 5Y NX 0c IY FY3Y2Y+Y1Y KZ.Z JY.Y Y.Y ;Y %j +Y .Y1Y BY=Y IYEXGXEY >] 0Y?Y ,[ " + "3` EX E_ L\\Cx NT6V6T'Z4Z BY2Z CY>^ GY-Y ;c 9Y1Y @YAZ 6ZEY @Y1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y KX.Z Y-Y 5Y 5Y.Z JZ" + "4Y 4\\ 1Z 1[ NZ.[" + "WDX:U -X EY1Y 1WEW 3Z 5YBY 7W6UKV IX*W KW6UKW CY 6Z4Y FZ5Z FZ4Z GZ4Y EY4Z GZ4Y%Y8Z <[ IZ !Z " + " Z !Z >Z !Z !Z \"Z :Z#Z(Y=ZDY*[ LZ/Z L[0Z L[0Z LZ0[ LZ B_ BZAY5Z*Z(Z#Z(Z$Z(Z$Y'Y 9Z 2Z5\\ JY=` ?{ B{ Bz @z B{ " + "B{'~x/Y #~W M~W M~W M~W 7Y Y NX Y 6Z.Y IX0X JY-Y LZ-Y MZ.Z MY-Y KY-Y$~d$Y@WDY KY0X HY0X GX0X GX0Y AY@Z AY.Y " + "DY@Z 8WK~KW/WJ}JW.W=aX ,Y?Y LZ +XBU 6~_+~i%~U I~P HX.Y IX.X @ZDZ 7YCY KX " + " (y JY \"W?W (h 5XCXAX5Z<\\@Y 9Y CZ $T ;~e =l X 5Z/Z 4Z \"\\ AZ IX6Z JZ I\\1[ 4Z 8Z3Z AmKZ" + " ?d d AZ HW>X3W>V.Z4Z JZ.Z\"[ \"Z#[\"Z MZ 0Z Z'Z(Z :Z \"Z 4ZH] 0Z 2YAYKX@Y(YWCX;U -X EY1Y 1WEW 3Z Is 0YAX 8W6UJV IW)W" + " LX7UJW CY 6Z4Z GY3Y FZ4Z GY3Y FZ4Z GY3Z'Z8Z <[ IZ !Z Z !Z >Z !Z !Z \"Z :Z#Z(Yc=W.W=[6W/X:[:X >X ,Y@Z M[ " + "+YCT 5~`,~i$~S H~P HX.Y IX.X @YCZ 7ZDY KX )y HX #X@X (TNc 6WCX@X5Y:\\AX 8Y CZ :~e" + " =l !X 4Z/Z 4Z #\\ @[ KY6Z IZ I[0Z 4Z 9Z2[ @jJZ ?f %g AZ HW>X3W>V.Y2Y JZ.Z\"[ \"Z#Z!Z MZ 0Z Z'Z(Z" + " :Z \"Z 4ZG] 1Z 2Y@XKX@Y(YWBXZ !Z !Z \"Z :Z#Z(YW.W>[5W.W:[:W =W +ZAY LZ *YDU 5~`,~i#~Q F} GX.Y IX.X AZBY 7ZEZ KX " + ")y HX 6~e 9TJ_ 7XCX?X6Y9\\BX 8Y CZ KX Nl !X 4Z/Z 4Z $\\ >Z LY5Z IZ I[0Z 5Z 8Z1Z >fHY =h " + " +i @Z HW>X3W?W/Z2Z KZ.[#[ \"Z#Z!Z MZ 0Z Z'Z(Z :Z \"Z 4ZF] 2Z 2Y@XLY@Y(Y;ZGZ*[ MZ!Z /Z M[&Z7[ K\\ 6Y 9Z(Z FZ" + "BZ MYFXY FY.Y KZ %Y-Y K~X :Y 5Y.Y GY1Y 5Y NX 0e KY FY3Y2Y+Y1Y KZ-Y JY.Y" + " Y-X ;Y !m 2Y .Y1Y AZAZ GYGXEXGY >] .ZBY -[ 1e JX Ke LU4k IU8Y8T'Y2X AY0Y EX:[ FY-Z Ah 9Y1Y >XCZ 6YBY AY1Y&" + "Z8X8Z,Y@YAZ IY9Y IY@X@Y LY-Y Y-Y 5Y 5Z/Y JZ2Z 8[ .Z 0[!Z,[=Z=[)Z(Z\"]FZG]'Z M[1] 1X 1\\ @X @\\ L\\ AX DX 4" + "Z?U -Z (X4X H~W ;\\;W GTDX\"U s A[D[ 6X %T>WBXZ !Z !Z \"Z :Z$[(Y;ZFY)Z M[/[ MZ/[ MZ/Z M[/Z M[ Ee EZC" + "X3[*Z(Z#Z(Z$Z(Z$Y(Z 9Z 2Z8^ IY9` Fb=Y Eb=Y Eb=X Cb>Y Eb=Y Eb=Y*b=~V/Y #~W M~W M~W M~W 7Y Y NX Y 6Y-Z JX0X JY" + "-Y LZ-Y MY-Z MY-Y LZ-Y CZCXBY KY0X HY0X GX0X GX0Y @YBZ @Y.Y CYBY 6W8X8W.W HW-W@g@X.W?[4W.W:[:W =W *YBZ " + " MZ (XDU 5~`,~i\"~ D{ FX.Y IX.X AZBZ 7YEY IX +y GX 6~e 9TG] 8WBW>X6Y8\\DY 8Y CZ " + " KX Nl !X 4Z/Z 4Z %\\ =Z LX4Z IZ I[0Z 5Z 9Z0Z X3W?W/~S KZ-Z\"Z \"Z#Z!Z MZ 0[!Z" + "'Z(Z :Z \"Z 4ZE] 3Z 2Y?XMX?Y(Y;ZGZ)Z MZ!Z /[ N[&Z6[ K\\ 7Y 9Z(Z FZCZ LZGX^ .YCZ ." + "[ )_ KX L_ ES/e FU8Z9T'Z3X AY0Y FY:[ FY-Z Cj 9Y1Y >XCY 6ZBZ BY1Y&Z8X9[,Y@YAZ IY9Y IY@X@Y LY-Y Y-Y 5Y 5Z/Y J" + "Z2Z 9\\ .Z /Z!Z,\\>Z>[(Z(Z!]GZH^'[ N[0\\ 1X 2\\ ?X ?[ M\\ @X DX 4Z?U -Z 'W4W G~W :]>X GTDY#U s @[D[ 7" + "X %U?WAX>U ,X EY1Y 1WEW \"s 3ZC[ 9X7UHV KW(W MX7UHW CY 7~S J~S H~S I~S I~S I~S)} ;Z IZ !Z Z" + " !Z >Z !Z !Z \"Z :Z$[(Y;ZFY)Z MZ-Z MZ/[ N[/[ N[/Z MZ Eg F[EX2[*Z(Z#Z(Z$Z(Z$Y(Z 9Z 2Z9^ HY7_ G]8Y F^8Y F^8X D]8" + "Y E]8Y F^8Y+^8~V/Y #~W M~W M~W M~W 7Y Y NX Y 6Y-Z JX0X JY-Y LZ-Y MY-Z MY-Y LZ-Y BYDXAY KY0X HY0X GX0X GX0Y" + " @ZCY ?Y.Y CYBY 5W9X8W.W HW-WAiAW,WA[3W.W9Y9W >X *ZCZ 6~d IYET 4~`,~i!| By EX.Y IX.X AYAZ 7ZFY IX " + " Z 3X 6~e 9TF\\ 9WBX=W7Z7\\EX 7Y CZ KX Nl \"X 3Z/Z 4Z &\\ ;Z M~Z %Z I[0Z 6[ 9Z/" + "Y 8ZCZ 8i 6~d 5i ;Z HW>X3W?W0~T KZ-Z\"Z \"Z$[!Z MZ 0[!Z'Z(Z :Z \"Z 4ZD] 4Z 2Y?XMX?Y(Y:ZHZ)Z N[!Z /[ NZ%Z6[" + " J[ 7Y 9Z(Y DZDZ LZGW:WGZ K[GZ +Z -\\ LX EX IY L\\6Y FY.Y KZ %Y-Y K~W 9Y 5Y.Y GY1Y 5Y NX 0XM\\ MY " + "FY3Y2Y+Y1Y KZ.Z JY.Y Y-X ;Y Ji 4Y .Y1Y @YAY FYGWDXGX >` /YCY .[ $\\ LX M\\ AR+` CT9[:U'Z3X AY0Y FY9Z FY-Z " + "D` .Y1Y >YEZ 6YAZ BY1Y&Z8X9[,ZAYAZ IY9Y IY@X@Y LY.Z Y-Y 5Y 5Z/Y KZ1Z 9[ -Z /Z\"[+[>Z>[(Z(Z ^IZJ_&[ NZ.\\ 2X 3" + "\\ >X >[ \\ ?X DX 4Z?U -Z 'X6X G~W 9^@X GUDY$T Ns ?[CZ 8X %U?WAY?U ,X EY1Y 1WEW \"s 4" + "ZCZ 7W7UGV LX)X MW7UGW CY 8~T J~T I~S J~T I~T K~T*~ ;Z IZ !Z Z !Z >Z !Z !Z \"Z :Z$[(Y:ZGY)[ NZ-Z N[.Z N[/[ N" + "[/[ NZ Fi G[FX1Z)Z(Z#Z(Z$Z(Z$Z)Z 9Z 2ZX )YCY 5~d IYFU 4~`,~i!{ @x EX.Y IX.X AY@Y 7ZGZ IX Z 3X 6~e 9TD[ ;XBX=X8" + "Z6\\GY 7Y CY JX Nl \"X 2Y/Z 4Z '\\ :Z M~Z %Z I[0Z 6Z 8Z/Z \"Z 5i 9~d 8i 8Z HW>X3W?W0~U LZ-Z\"[ " + "#Z$[!Z MZ /Z!Z'Z(Z :Z \"Z 4ZC] 5Z 2Y?XNY?Y(Y:ZHZ)[ [!Z .Z NZ%Z5[ K[ 7Y 9Z(Y DZDY KZHX:XHY K[EZ ,Z .\\ KX EX" + " IY LZ4Y FY.Y KZ %Z.Y KZ X DX 4Z?U -Z 'X6X G~W " + "8^BX FUDY%U Ns =ZCZ 9X $U@W@X?T +X EY1Y 1WEW \"s 5ZCZ 7W7UFV LW(W MX8UFW CY 8~U K~T J~U K~" + "T J~U K~T*~ ;[ JZ !Z Z !Z >Z !Z !Z \"Z :Z$Z'Y9YGY)[ [-[ [.Z N[.Z NZ.[ NZ G\\L[ GZGX0Z)Z(Z#Z(Z$Z(Y#Z)Z 9Z 2~ " + "GY4] J[4Y G[4Y G[4X EZ4Y FZ4Y G[4Y,[4X 1Y #Y Y Y Y 9Y Y NX Y 6Y-Z JX0X JY-Y LZ-Y MZ.Z MY-Y KY-Y BYEW?Y" + " KY0X HY0X GX0X GX0Y ?YDY >Y.Y BYDY 4W9X9W-X JX,WD\\J[CW,WC[2W-X JX >X )YDZ 5~d HXFU 4~_+~i z @w DX.Y" + " IX.X BZ@Y 6YGZ IY Y @~e 9TCZ ;WAX=X8Y4\\HX 6Y CY JX Mj !X 2Y/Y 3Z (\\ 9Z" + " M~Z %Z I[0Z 6Z 8Z/Z \"Z 2i <~d ;i 5Z HW>X3W@W/~U LZ-[#[ #Z$Z Z MZ /Z!Z'Z(Z :Z \"Z 4ZB] 6Z 2Y>a>Y(Y9ZIZ)[ " + "Z Z .Z [%Z4Z JZ 7Y 9Z)Z DZEZ JYHX:XIZ KZD[ -Z /\\ JX EX IY MZ3Y FY.Y JY %Z/Z JY Z !Z !Z \"Z :Z%['Y9ZHY(Z [-[ Z" + "-[ Z-Z [-Z [ H\\J[ HZHY1[)Z(Z#Z(Z$Z(Y#Z)Z 9Z 2} FY2\\ KZ3Y GZ3Y GY3Y FZ3Y GZ3Y GZ3Y,Z3X 1Y #Y Y Y Y 9Y Y " + "NX Y 6Y-Z JX0X JY-Y KY.Z MZ.Z MY-Y KY-Y BYFX?Y KY0X HY0X GX0X GX0Y >YEY >Y.Y BYEZ 4X:X9W,W JW+WE\\H[EX,X" + "E[1W,W JW =X )ZEY 4~d HYHU 2~^+~i Nx >u CX.Y IX.X BY?Z 7ZHY GX Z A~e 9TCZ ~d >i 2Z GV>X3W@W0~V LZ-[\"Z " + "#Z%[ Z MZ /[\"Z'Z(Z :Z \"Z 4ZA] 7Z 2Y>a>Y(Y9ZIZ(Z Z Z .[![%Z4[ KZ 7Y 9Z)Z CZFZ JZIX:XIZ L[CZ -Z /[ IX DX J" + "Y MY2Y FY.Y JY %Z/Z JY Y CY1Y&Z9Y9Z+ZAYAY HY9Y IY@X@Y LZ/Y N" + "Y-Y 5Y 4Y0Z LZ.Y =[ *Z .[%Z(]AZA]'Z(Z L~\"[![+\\ 5X 6\\ JTEXET J[&\\ KSDXES $Y 3Y?U -Z &Y:Y F~W 5_GX DU" + "CZ9QAU DZCZ ;X $VAW?YBU +X EY1Y 1WEW DZCZ 6W7UEV NX)X MX8UEW DY 8~V L~V L~W M~V K~V M~V" + ",~P :Z JZ !Z Z !Z >Z !Z !Z \"Z :Z%['Y8ZIY(Z Z+Z Z-[![-[![-[![ I\\H[ I[JY0[(Y(Z#Z(Z$Z)Z#Z)Z 9Z 2| EY1\\ LY2Y " + "HZ2Y HZ3Y FY2Y GY2Y GY2Y-Z2X 1Y #Y Y Y Y 9Y Y NX Y 6Z.Y IX0X JY-Y KY.Z MZ.Z MY-Y KY.Z BYGX?Z KY1Y HY0X" + " GX0X GX0Y >YFZ >Y.Y AYFY 2W:X:X,W JW+XG\\F[FW+XF[1X,W JW =X (YEY 4~d GXHU 2kNRMk*tNq Mv Y 7ZIZ GY !Z A~e 9TBY `=Y(Y8ZJZ([\"[ Z " + ".[!Z$Z3Z KZ 7Y 9Z)Z CZGZ IZIW8WIZ M[AZ .Z 0\\ IX DX JY MY2Y FY.Y JY $Y/Z JY YEY CYIWBXIX @f 0YGZ 0[ LZ NX NY 'U>WMW?V&Z4Y AY/Y HY8Y" + " EZ.Y FZ %Y1Y Y CY1Y&[:Z:Z+ZAYAY HY9Y IY@X@Y LZ/Y NZ.Y 5Y 4Y0Y KZ.Z ?\\ *Z -['['\\AZB]&Z(Z K|![!Z)\\ 6" + "X 7\\ JVFXFV J[(\\ KUEXFU %Y 3Y?U -Z %YXCU *X EY1Y 1WEW" + " F[CZ 6X8UDV NW)X MX8UDW DY 8~W N~W L~W M~V L~W M~W-~P :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z%['Y8ZIY([\"[+[" + "\"[,Z![-[!Z,[!Z I\\F[ J[KY/Z'Z)Z#Z)Z#Z)Z#Z)Z 9Z 2{ DY0[ MY1Y HY1Y HY2Y FY2Y HZ2Y HY1Y-Y2Y 1Z $Y Y Y Z :Y Y" + " NX Y 6Z.Y IX0X JZ.Y KY.Z MZ.Y LZ.Y KY.Z BYHX>Z KY1Y HY1Y GX0X GX0Y =YGY =Y.Y AYFY 2X;X:W+X LX*WH\\D[HX" + "*WG[0W+X LX =X (YFZ 4~d GYIU 2jLQLj*pNRNq Lt :q AX.Y IY0Y CZ>Y 6YIZ FX !Z A~e 9T" + "BZ >W?W;W8Z2\\MY 4Y DY JX 4X 1Z1Z 3Z +\\ 6Z M~Z %Z HZ0Z 8[ 7Y.Z #Z )i D~d Ci -Z GV=W4XAW/~W M" + "Z-[\"[ $Z&[ NZ MZ .Z\"Z'Z(Z :Z \"Z 4Z?] 9Z 2Y=_=Y(Y8ZJZ([\"[ Z -Z\"[$Z3[ L[ 8Y 9Z)Z BZHZ IZJX8XJY LZ@[ /Z 1\\" + " HX DX JY NY1Y FZ0Z JY $Y/Z JY YEY BXJXAWJY A[N[ 1YGY 0[ JY NX NY 'V@WLX@U$Y5[ BY/Y HX7X DZ.Y FY $Y1Y Z " + "/Z K_MZ BUC]BVBU A[D[ >X #VBW=XDU *X EY1Y 1WEW G[D[ 5W8UCV X*X LW8UCW EZ 8~W N~X M" + "~W N~X M~W N~X.~Q :[ KZ !Z Z !Z >Z !Z !Z \"Z :Z&[&Y7ZJY([\"[+[\"[,[\"Z+[#[+Z\"[ J\\D[ JZKX/['Z*[#[*Z#Z)Z#Z)Z" + " 9Z 2z CY/Z MY1Y HY2Z HY2Y GY1Y HY1Y HY1Y-Y2Z 2Z $Z !Z !Z !Z :Y Y NX Y 6Z.Y IX0X JZ/Z KY.Z LY.Y LZ/Z KY.Z " + " BYHW=Z KY1Y GX1Y GX1Y GX0Y =YHZ =Y/Z @YHY 1X;X;X*W LW)XJ\\B[IX*XI[0X*W LW Z 7ZJY EY !Z 1X@X &TAY ?X?W;W8Z1\\NX 3Y DY JX 5Y 0" + "Y1Z 3Z ,\\ 5Z M~Z %Z HZ0Z 8Z 6Y.Z #Z &i G~d Fi )X FV=X5XAW0~Y NZ-[!Z $Z&[ NZ MZ .[#Z'Z(Z :Z \"Z 4Z>] :Z 2" + "Y=_=Y(Y7ZKZ'Z#[ NZ -[#[$Z2[ M[ 8Y 9Z)Z BZHZ HYJX8XKZ M[?Z /Z 2\\ GX CX KY NY1Y FZ0Z JZ %Y/Z JZ =Y 4" + "Y0Z GY1Y 5Y NX 0XG\\ $Y FY3Y2Y+Y1Y JZ/Y IZ0Y MY/Y ;Y 8[ 8Y .Y1Y >ZGZ BYKXAXKY B[LZ 0YHY 1[ IY NX Z &VB" + "XKXBV$Y5[ BY/Y HX8Y CY/Z GY #Y1Y Z !Z !Z \"Z :Z&[&" + "Y7ZJY'[#Z)Z#[+[#[+[#[+[#[ K\\B[ K[MX.['Z*Z!Z*Z#Z)Z#Z)Z 9Z 2x AY.Z NY2Z HY2Z IY1Y GY1Y HY1Y HY2Z-X1Z 2Z $Z !Z !Z" + " !Z :Y Y NX Y 5Y/Z IX0X JZ/Z KZ/Y KY.Y LZ/Z KZ/Y AYIWW;W8Z0e 3Y EZ JX 5X /Z2Y 2Z -\\ 4Z M~Z %Z HZ0Z 8Z 6Z/Z $Z #j J~d Ii CW>X6Y" + "BX0~Y NZ-[![ %Z'\\ NZ MZ -Z#Z'Z(Z :Z \"Z 4Z=] ;Z 2Y<][ 0" + "Z 3\\ FX CX KY NY2Z FZ0Y IZ %Y/Z JZ =Y 4Y0Z GY1Y 5Y NX 0XF\\ %Y FY3Y2Y+Y1Y JZ/Y IZ0Y MY/Y ;Y 7Z 8Y" + " .Y2Z =YGY AYKW@XKY BZJZ 1YIY 1[ HY NX Y %WEYIYFW#Y5[ BY/Y HX8Y CY/Z GY #Y1Y ;XIY 6Y;Z EY1Y%Z:Z:Z*ZBYBZ " + "HY9Y IY@X@Y LZ/Y MY/Z 4Y 4Y2Y KZ,Z B[ 'Z +[+[#_FZF_$Z(Z Gt JZ$[%\\ 9X :\\ J\\IXI[ I\\/\\ K[HXI[ (Y 3Z@U -Z " + "%^F^ /Z X \"f >VBnCU >[D[ @X \"VCWZ !Z !Z \"Z :Z'[%Y6ZKY'[$[)[$[*[$[*[%[*[$[ K\\@[ Le.[&Z*Z!Z*Z\"Z*Z#Z*[ 9Z 2v " + "?Y.Z NY2Z HX1Z IY1Y GY1Y HY2Z HX1Z.Y1Z 1Y #Y Y Y Y :Y Y NX Y 5Y/Z IX0X IY/Z KZ/Y KY/Z KY/Z KZ/Y 7\\ 7ZKW" + ";Y IX1Y GX1Y GY2Y GY2Z YJX(XJY/X)X Y W;W7Y/c 2Y EY IX 5X /Z3Z 2Z .\\" + " 3Z M~Z &Z FY1Z 8[ 6Z/Z $Z i L~d Li @W>Y7YBW0Z*Y NZ-[![ %Z'[ MZ MZ -[$Z'Z(Z :Z \"Z 4Z<] Z !Z !Z \"Z :Z(\\%" + "Y6ZKY&[%[)\\&[)[%[)[%[)[%[ L\\>[ Ld.[&Z*Z!Z*Z\"Z+[\"Z+Z 8Z 2s YJY .X=X=Y(" + "X!X'YJWX.Y HY2Y CZW=X8ZC" + "W/Z*Z Z-Z N[ &Z(\\ MZ MZ -\\%Z'Z(Z :Z \"Z 4Z;] =Z 2Y<]Y 4Z2[ GY1Y 5Y NX 0XD\\ 'Y FY3Y2Y+Y1Y IY0Z IZ1Z MZ1Z ;Y 6Y" + " 8Y .Y2Z =ZIZ @XLX?WLY C[H[ 2YKZ 3[ EX NX Y $hFh\"Z7\\ BY0Y GX9Y BZ1Z FX \"Y1Y ;YKY 6Y9Y EY2Z%Z;[:Z*ZBYB" + "Y GY9Y IY@XAZ L[1Y LZ1Z 3Y 3Y3Y LZ*Z D[ &Z *[-[ aJZJa\"Z(Z Cl F\\'[\"\\ ;X <\\ F\\KXK\\ F\\3\\ H\\JXK\\ 'Y " + "2ZAU -Z 'z 1Z X Na ;V@jDV :ZCZ BX UDW;XIU 'X EY2Z 1WEW KZCZ 3X9U@V\"W*X LX9VAW H[ " + "8Z*Z\"Y)Y!Z*Z\"Z*Y!Z*Z\"Z*Z1Z3Z 8[ MZ !Z Z !Z >Z !Z !Z \"Z :Z(\\%Y5ZLY&[&['[&[([&[)\\'\\)[&[ L\\<[ Mc.[$Z,[!" + "[,[\"Z+Z!Z+Z 8Z 2n 7Y-Y NX1Z IY2[ IY2Z GY2Z HY2Z IY2[.Y2\\ 2Z $Z !Z !Z !Z ;Y Y NX Y 5Z0Y HX0X IZ1Z IY0Z KZ0" + "Y JZ1Z IZ1Z 7\\ 6YMX;Z IY3Z GY2Y GY2Y GY2Z ;YKY ;Z1Z >YJY .Y>X=X'Y#Y&XIU:UJY&YJU.X'Y#Y ;X &YJZ #Z JXLU" + " -dIQId%kKRKk El 2j >X.Y HY2Y CY;Z 7ZMZ BZ #Z 3X@X %TAX @WZ 2Y;[;Y(Y5ZMZ&\\([ LZ +['[\"Z0[ Z 7Y 8[,Z ?YKZ EYLX6XLY [:[ 2Z 5\\ DX BX LY NY3[ F[2Z HZ %Y1" + "[ IZ >Y 3Y2[ GY1Y 5Y NX 0XC\\ (Y FY3Y2Y+Y1Y IZ2Z H[2Z LY1Z ;Y 6Z 9Y .Y2Z Z !Z" + " !Z \"Z :Z)\\$Y5ZLY%[(\\'\\(['\\(['['['[(\\ M\\:[ Ma-[$Z,Z NZ,Z![,Z!Z,[ 8Z 2Z #Y-Y NX2[ IY2[ IY2Z GY3[ HX2[ IY2" + "[.Y2\\ 2Z $Z !Z !Z Y ;Y Y NX Y 5Z1Z HX0X IZ1Z IZ1Z JZ2Z JZ1Z IZ1Z 7\\ 6c:Z IY3Z GY3Z GY3Z GY3[ ;YKY ;[2Z =" + "YLY ,Y?X>Y&Y%Y%YIS8SJY$YJS.Y&Y%Y :X &ZKY #Z IYNU ,cISIb#jKRJi Cj 1i =X.Y GY4Y BY:Y 7ZMZ AZ " + " $[,P )W?X %TBY AXXMY DZDZ 2YLY 3[ DY X Y \"eCd NY8^ CY0Y GX:Y @Z2Z FX \"Y1Y :YMY 6Y7Y " + "FY2Z%[<\\a@V 7YBY CX NV LV BZ3Z 1WEW LYBY 2W8U?V#W+X KX9U" + "?W J[ 7Z(Y#Z)Z#Z(Z$Z)Z\"Y(Z$Z(Y2Z2Z 7\\\"P NZ !Z Z !Z >Z !Z !Z \"Z :Z*\\#Y4ZMY%\\)[%[)\\&[)\\'\\)\\'\\)[ M\\8" + "[ N`-[#Z,Z NZ,Z Z-[![-[ 8Z 2Z #Y-Y NX2[ IY2[ IY3[ GY3[ HY3[ HX2[.Y3^ 2Z $Z !Z !Z !Z ZMZ DZMW4WMZ![7Z 3Z 7\\ BX AX MY NY3" + "[ F\\4Z FZ &Z3\\ HZ ?Y 3Z4\\ GY1Y 5Y NX 0X@[ *Y FY3Y2Y+Y1Y HZ3Z H\\4Z KZ3[ ;Y 5Y 9Y -Y4[ ;YKY >YNX=WNY D[D[ " + "3YMY 3[ CY X Y !cAb MZ9^ CZ2Z GX:Y @Z3Z EX \"Y1Y :YMY 7Z7Y FZ4[$Z<\\Z !Z !Z \"Z :Z+]#Y4ZMY$[*\\%\\*[%\\+\\%\\+\\%\\+\\ N\\6[ N^-\\#[.[ N[.[ [.Z NZ-Z 7Z 2Z #Y-Y NY4\\ IY3" + "\\ IY3[ GY3[ HY4\\ HX3\\.Y3^ 2Z $Z !Z !Z !Z i i 2WZ4" + "Z EY #Y1Y 9XNZ 7Y6Z GZ4[$Z=]=['ZDYDZ FY9Y HZBXBZ K]5Z J[5[ 2Y 2Z7Y L[(Z H[ #Z '\\5[ F~ LZ(Z :Z :\\-\\ KW :X :" + "V >r >V/V @s #Z 2[CU -Z +[MeL[ 5Z X G\\ :W!V 3W@W 7V!W AZ4[ 1WEW LW@W 1W7s,X-" + "Y JX8t$\\ 7Z'Z%Z'Z$Z'Y%Z'Z$Z'Y%Z'Z4Z1Z 6\\&S NZ !Z Z !Z >Z !Z !Z \"Z :Z,]\"Y3ZNY$\\,\\#\\,\\$\\,\\$\\-\\$\\," + "\\ N\\4[ ]-\\![/Z LZ/[ N[/[ N[/[ 7Z 2Z #Y-Y NY4\\ HY5] IY4\\ GY4\\ HY4\\ HY4\\.Z5` 2Z $Z !Z !Z !Z =Y Y NX Y " + "3Z4Z GX0X H[5[ GZ4Z GZ4Z H[5[ GZ4[ 6\\ 5_9[ HZ5[ GZ5[ FY5[ FY5\\ :YNZ :\\4Z ;YNY )YAXAZ\"Z+Z!Z*Y Y*Z\"Z+Z 8" + "X $YMY %[ F^ '\\FSF\\ LcGRGc >f ,c :X.Y FZ7Y BY8Y 7e >[ %[1S -Y 'X@X ;Q:TCZ CX:X=X" + "5[.] /Y HY HX NZ GZ 'X +[8Z 0Z 4\\ 0[ 'Z M\\ CZ6[ 9Z 2[3[ '[ 0Y Y ?f f BX DW=\\C_J[.Z&Z\"Z0\\ " + "J\\(T'Z._ JZ MZ *])Z'Z(Z :Z \"Z 4Z6] BZ 2Y JY(Y3e#\\.\\ JZ )]/\\ NZ.[ NQ'[ 6Y 6[0[ =ZNZ CYNX4XNY!Z4[ 5Z 8[ @X" + " AX MY NY5] F]6Z DZ &Z5] G[ AY 2[8^ GY1Y 5Y NX 0X>[ ,Y FY3Y2Y+Y1Y H[6[ G]6Z IZ5\\ ;Y 6Y 8Y -Z6\\ ;Z" + "MZ =b=b EZ@Z 3d 5[ AY X Y L[:\\ IZ;` D[4Z FXZ5[ EY #Y1Y 9c 7Z5Y GZ5\\$[>^>['[EYE[ FY9Y HZBXCZ J]5Z " + "IZ5Z 1Y 1Y8Z LZ&Z J[ \"Z &\\8] E| KZ(Z :Z :]/] JU 9X 9T

q \"Z 1ZCU -Z ,[JaI[ 6Z X F\\ :W#V 1" + "V?V 7W#W @[5[ 1WEW LV?V 1X7s,W-Y JX7t%\\ 6Z&Z&Z'Z%Z&Z&Z'Z%Z&Z&Z&Y4Y0Z 5\\(T NZ !Z Z " + "!Z >Z !Z !Z \"Z :Z.^!Y3e#\\.\\!\\.\\#].\\#]/]#\\.\\ N\\2[ ]/]![0[ L[0[ M[0[ N\\1[ 6Z 2Z #Y-Y NY5] HY5] IZ6] GY" + "5] HY5] HY5]-Y5a 3[ %[ \"[ \"[ \"[ >Y Y NX Y 3Z5[ GX0X GZ5Z F[6[ G[6[ GZ5Z F[5Z 5\\ 4^9Z FY6\\ FY6\\ FY6\\ " + "FY6] 9c 9]6Z :d )[CXBZ Z-Z NZ-[ [-Z Z-Z 7X $YNZ %Z D] $VCSDW G`FSG` ;d +c :X.Y F[9Z CZ8Y 6d =\\ " + " '\\3T -Z (W?X ;Sd c @Z EW<_Ks-Z&Z\"Z1] J^,V'Z/_ IZ MZ )]*Z'Z(Z :Z \"Z 4Z5] CZ 2Y JY(Y2d#]0\\ IZ (]1] NZ-" + "Z NS*\\ 6Y 6[1[ Z 4c 5[ @Y X Y HS3V FZZ%ZEYF[ EY9Y GZCXD[ J^7Z H[7[ 1Y 1Z:Z KZ&Z K[ !Z %];] Bx IZ(Z :Z 9]1] HS 8X 8R :n :R+R U 6W%W ?[6\\ 1WEW LU>U 0W6s-X.X HW6t&\\ 5Z&Z'Z" + "%Z&Z&Z'Z%Z&Z&Z&Z&Z6Z0Z 4],V NZ !Z Z !Z >Z !Z !Z \"Z :Z0`!Y2d\"\\0]!]0\\!]0\\!]1]!]1] \\0[ ]1] N[2\\ L\\2[ L\\" + "2[ L[1[ 6Z 2Z #Y.Y MZ7^ HY6^ HY6] GZ6] HZ7^ HZ7^-Y6c 3[ %[ \"[ \"[ \"[ ?Y Y NX Y 3[7[ FX0X G[7[ E[7[ FZ7[ F" + "[7[ E[7[ 5\\ 4]9[ FZ8] FZ8] FZ8] FZ7] 9c 9]7[ 9b '[DXD[ N[/Z LZ/[ M[0[ N[/Z 6X $d %Z C\\ ?S 2\\ETD" + "\\ 9b )a 9X.Y E[<[ BY7Z 7c ;\\ '\\5U -Z (W?W :U>TE[ CX8X?X3\\3b 1Y IY GX NZ GZ (" + "X )[;[ /Z 5[ %Q-\\ &Z BQ/] AZ9\\ 9Z 0[6\\ (\\ /Z \"[ ;a ` =Z EX[ 4b 6[ ?Y X Y " + "FZ=b E]7Z EX=Z <[9\\ D[ %Y1Y 8a 6Y3Y H\\8]#[@WNW@[%[FYG\\ EY9Y G[DXD[ J_9[ G[9[ /Y 1Z;Z LZ%Z L\\ !Z $]=\\ >t GZ" + "(Z :Z 8]3] FQ 7X 7P 8l 8P)P :m Z 0[EU -Z .[?P?[ 8Z X D[ 9W(W -T\\8] 1WEW " + " LSZ !Z !Z \"Z :Z2a Y2d\"^3] N]3^ ]3" + "] N]3] N]3] \\.[!^3] M\\4\\ J\\4\\ K\\4\\ L\\4\\ 5Z 2Z #Y.Y MZ8_ HZ8_ HZ8^ FZ8^ HZ8_ HZ8_-Z8e-Q)\\ &\\-Q G\\-Q " + "G\\-Q G\\-Q 5Y Y NX Y 2[9\\ FX0X F[9[ D\\9[ E[8[ E[9[ D\\9[ 4\\ 3[9[ EZ9^ FZ9^ FZ9^ F[9^ 9b 8^9[ 8b &[2[" + " L\\3\\ K[2[ K[2[ L\\3\\ 6X #c &Z B\\ ?S /UATAT 4a '_ 8X.Y E\\>\\ BY6Y 7c :] (\\7V " + "-Z )X@X :W@TF[ BW7X?X3]6e 1X IY GX NZ GZ (X ([=[ .Z 6[ $S1^ &Z BS3^ @\\<\\ 8Z 0]9] FR6] .Z \"[ 8^ " + " ^ ;Z DW;lMc+Z$Z#Z4_ G_2Y'Z5c GZ MZ '^/\\'Z(Z :Z \"Z 4Z3] EZ 2Y JY(Y1c!^6^ HZ '^6^ LZ,Z X1] 5Y 5]6\\ :c Ab2a" + "\"Z0[ 7Z ;\\ >X @X NY MZ:` F_:[ B\\3P D[;` E\\1S 7Y 0\\>a GY1Y 5Y NX 0X;\\ 0Y FY3Y2Y+Y1Y F[:[ E_;\\ " + "F[;_ ;Y *S1Y 6Z .[;_ :e ;`;` G[<[ 5a 6[ >Y X Y F[?YNY F_:[ DX?Z :[;\\ B[ &Y1Y 8a 7Z3Y H]:^#\\BXNWA[#[" + "GYH\\ DY9Y F\\FXF\\ I`;[ F\\;\\ /Z 2[=Z KZ$Z N\\ Z #^A] :n DZ(Z :Z 7]5] +X Mj (k NZ 0\\FUBP ;Z /[,[ " + "9Z X CZ 8X+W *R;R 4X+X =]:^ 1WEW LR;R /X5s.W.X GW5t(\\ 4Z$Z(Z%Z'Z$Z(Z$Y'Z$Z(Z$Z" + "8Z/Z 3_2Y NZ !Z Z !Z >Z !Z !Z \"Z :Z5c NY1c!^6^ L^6^ M^6^ M]5] M^6^ \\,[#a7^ K\\6] I\\6\\ J]6\\ J\\6] 5Z 2Z #" + "Y/Z LZ:` H[:` H[:_ FZ:` GZ:` GZ:`-[:YN\\0S(\\4Q C\\0S F\\0S F\\0S F\\0S 5Y Y NX Y 1[:[ EX0X F\\;\\ C\\;[ C[:" + "[ D\\;\\ C\\;\\ 4\\ 3[:\\ DZ;_ EZ;_ EZ;_ EZ;` 8a 8_;\\ 7a %\\6\\ J\\5\\ I\\6\\ I\\6\\ J\\5\\ 5X #c 'Z " + "@[ @T JT _ %] 7X.Y D^D^ BZ6Y 6b 9_ *];X -Z )X@X :ZCTH] CX7YAX1^:h 2Y JY GX NZ" + " GZ (X (\\?\\ .Z 7\\ $W7_ %Z BV8` ?\\>] 9[ /];] ET9] -Z \"[ 5[ [ 8Z DX;jLb*Z$Z#Z7a E`7\\'Z9f FZ MZ &`4^" + "'Z(Z :Z \"Z 4Z2] FZ 2Y JY(Y1c _:_ GZ &_9^ KZ,[![6^ 4Y 4]9] 8b @a2a#[/Z 7Z ;[ =X @X NY M[\\ @]7R" + " D\\=a E]4U 7Y /]Bc GY1Y 5Y NX 0X:\\ 1Y FY3Y2Y+Y1Y E\\>] E`=\\ E\\=` ;Y *U5[ 6[ /\\>a 9c :_:` GZ:Z 4` 6[ >Y " + "X Y E[AYMZ G`<[ CX@Z 9\\=\\ A\\3Q EY1Y 7` 7Y2Z I^<_\"[BWMXC\\#]IYI\\ CY9Y F]GXG] Ia=\\ E\\=\\ .[ 2[?Z J" + "Z$Z N[ NZ \"^C^ 7g @Z(Z :Z 7_9_ +X Lh &i MZ /]HUDR ;Z .Y*Y 8Z X BZ 8Y/X (Q:Q 2X/Y " + " <^<` 2WEW LQ:Q .W MV(X/X GX NW\"\\ 3Z$Z)Z#Z(Z$Z)Z#Z(Z$Z)Z#Z8Z/Z 2`7\\ NZ !Z Z !Z >Z !Z !Z \"Z :" + "Z9f MY0b _:_ J_:_ K_:_ L_9_ L_9^ N[*[$c:^ J^:^ H^:^ I^:] H]9] 4Z 2Z #YIP7[ L[] C\\=\\ A\\=\\ 3\\ 2\\=\\ C[=` E[=` E[=" + "` E[=a 8a 8`=\\ 6` #]:] H]9] G]:] G]:] H]9] 4W !a 'Z ?Z ?U KT N] $] 7X.Y Cv AZ6Z 7a 7a " + " -_?Z -Z )W?X :^GTK_ CX5XAX0_>k 3Y JX FX NZ GZ )Y ']C] ?} I~S IZ=b %Z BZ>a =]B^ 8Z ._?^ DX" + "@_ ,Z \"[ 3Y X 5Z CW:gJ`)Z\"Z$~T Cb=_'~W E~S FZ %b:a'Z(Z :Z \"Z 4Z1] G~Q)Y JY(Y0b N`>` FZ %a?` JZ+Z!^_ 8b @a2a$[.[ 8Z <~` AX ?X Y L\\@c Fb@] ?^` H`>` I`>` Ja?a Ja?` LY(Y$f?` H_>_ F_>_ G_>_ H_>" + "_ 3Z 2Z #YIS;[ K\\?c G\\?c G\\?b E\\@c F\\@c G\\?c,\\?[L^9Y'^} I~S I~ $Z B| ;^F_ 7Z -aEa Dv +Z \"[ 0V U 2Z CX9dI^'Z\"Z$~S AfGd'~U C~S FZ $gGg&Z(Z :Z \"Z 4Z0] H" + "~Q)Y JY(Y0b McGd EZ $dGc IZ+[\"cEd 3Y 3cGc 7a ?`1a$Z,[ 9Z =~a AX ?X Y L^DZNY FYNZF_ =`CY B^EZNY CaB] 7" + "Y .qMY GY1Y 5Y NX 0X8\\ 3Y FY3Y2Y+Y1Y D_F_ CYNYE_ B^EZNX ;Y *]A^ 4k >^G[NY 8a 9_9^ H[8[ 5^ 6~P 2Y X Y " + " D^H[La NfH` AYD[ 6^E_ ?`?X EY1Y 7_ 7Y0Y IcFk(]HZLZI^ `Nk BY9Z E~Q GYNZE^ B_E_ ,e ;]G] J~c!~T FZ 3oDo @Z :Z(Z :" + "Z 5dGd )X Jd \"e KZ -`MUKY H~U IU&U 6Z X AY 5Z7Z LZ7Z ;~d 3cFk 8WEW " + " BW LV)X0X FW LW$\\ 2Z\"Z+[#Z)Z\"Z*Z\"Z*Z\"Z*Z\"Z:Z.~T*fGd N~T J~T I~S I~S 7Z !Z !Z \"Z :~U JY/a MdGc FcGd GcGd" + " HdGd HdGc JW&W$kGc FbFb DbFb FcFb FcGc 3Z 2Z #YIWB] I^DZNY F]D[NY F]D[NX E^DZNY F^DZNY F^E[NY+]D]J`@]&`BY AaA]" + " DaA] DaA] DaA] 5Y Y NX Y /_F_ CX0X D_E_ ?_F_ ?_F_ @_E_ ?_F_ 7aF_ @^FZMX D^FZMX D_GZMX D_G[NY 7_ 7YNYE_ 4^" + " dLd CdMd BdLd CdLd DeMd 2X !` %X =Y ?U LV MZ !Y 5X.Y As AZ4Y 6` 5~] )x -Z " + "*X@X 9} BX3YFZ-{L] 4Y LY FX NZ GZ )X $t >} I~S I} #Z B{ :v 7[ ,{ Cu *Z \"[ -S S 0Z BW8aG[%[\"Z$~R" + " ?~S'~T B~S FZ #~V%Z(Z :Z \"Z 4Z/] I~Q)Y JY(Y/a L~ DZ #~ HZ*Z\"~R 2Y 2} 5` ?`0_$[+Z 9Z =~a AX ?X Y KsN" + "Y FYNr ;u AqMY B{ 7Y -oLY GY1Y 5Y NX 0X7\\ 4Y FY3Y2Y+Y1Y Cv BYNr ArMX ;Y *y 2j >qMY 8a 8^9^ I[6Z 5^ 6~P 2Y X " + " Y CpK` N} ?YF[ 5w =x EY1Y 6] 7Z0Z J~Y(nJm M{ AY9\\ F~ FYMq @w *d ;r J~d!~T FZ 3oDo @Z :Z(Z :Z 4~ 'X " + " Ib c JZ ,u H~U HS$S 5Z X AY 4\\>\\ I]>\\ :~d 3~Y 8WEW CW KV)W0X FX LW" + "$[ 2[\"Z+Z!Z*Z\"Z+Z!Z*Z!Z,Z!Z:Z.~T)~S N~T J~T I~S I~S 7Z !Z !Z \"Z :~T IY/a L~ D~ E~ F~ E~ HU$U$~X D| B| D} D} " + "2Z 2Z #YIr HrMY FsMY FsMX DsNY ErMY FsMY+uH|%v @| C| C| C| 5Y Y NX Y .v BX0X Cw =w >v >w =w 8{ ?qMX CqMX C" + "qMX CqMY 6] 6YNr 3^ My Ay @y @z Ay 1X _ $V X !" + "Y JqMY FYMp 9t ApLY Az 7Y ,mKY GY1Y 5Y NX 0X6\\ 5Y FY3Y2Y+Y1Y Bt AYMp ?pLX ;Y *x 1j =oLY 8a 8]8^ IZ4Z 6" + "] 5~P 2Y X Y CoI_ N} ?[K] 3u ;w EY1Y 6] 7Y.Y JvM_'mJm Ly @Y9b K| EYLp ?u (c :p I~e\"~T FZ 3oDo @Z :Z(Z" + " :Z 2{ &X H` Ma IZ +t H~U GQ\"Q 4Z X AY 2aLb FaKa 8~d 3YNlN_ 8WEW " + "DX KV*W0o-W KW%[ 1Z Z,Z!Z+Z Z,Z!Z+Z Z,Z!Z;Z-~T'~P M~T J~T I~S I~S 7Z !Z !Z \"Z :~R GY.` K| B| C{ B{ B{ FS\"S$YM" + "{ Bz @z B{ B{ 1Z 2Z #YIq GqLY EqLY EqLX CqMY ErMY EqLY*sF{$u ?{ B{ B{ B{ 5Y Y NX Y -t AX0X Bu ;u pLX CpLX CpLX BoLY 6] 6YMp 1] Lv >w =v =v >w 0X _ #T ;X ?W MV LW LV 4X.Y ?n >Y3Z 7_ 1~Z " + " 't +Z *W?X 8y @X1j)vG] 5X MY EX NZ GZ *X !p <} I~S Iz Z By 6r 5Z )w As (Z \"[ " + " 5Z AX HZ Z%~ 9|$~P >~S FZ ~P\"Z(Z :Z \"Z 4Z-] K~Q)Y JY(Y.` Jy AZ x EZ)Z#~P 0Y /x 3_ =_0_%Z([ ;Z =~a AX " + ">X !Y JpLY FYLn 7s @nKY @y 7Y +kJY GY1Y 5Y NX 0X5\\ 6Y FY3Y2Y+Y1Y Ar @YLn =nKX ;Y *w /i x ?x @y 0Z 2Z #YIp EoKY DoKY DoKX BoLY DpLY DoKY)qCy#t =y @y @y @y 5Y Y NX Y ,r @X0X As 9s :r :s 9s 7z <" + "nKX BnKX BnKX BnKY 6] 6YLn 0\\ Jt ;s :t ;t ;s .X N] !R 9V >W NX LU KU 3X.Y >l =Y2Y 7_ /~X " + " %p )Z *W?W 4u @X/i(tE] 6Y NX DX NZ GZ *X m :} I~S Iy NZ Bw 2o 5Z 'u @r 'Z \"Z " + " 4Z AY J[ Z%} 6x\"} <~S FZ N| Z(Z :Z \"Z 4Z,] L~Q)Y JY(Y.` Hv @Z Mu DZ)[$~ /Y .u 0^ =^/_&['Z ;Z =~a AX >X" + " !Y InKY FYKl 5r ?lJY >w 7Y )hIY GY1Y 5Y NX 0X4\\ 7Y FY3Y2Y+Y1Y @p ?YKl ;lJX ;Y *v -h ;kJY 7_ 7]7\\ J[2" + "[ 7\\ 5~P 2Y X Y AkE] Nz :i .p 7u EY1Y 5[ 7Y,Y KYMiL_%iGj Hu >Y8a Hv BYJl :p $a 7k H~f\"~T FZ 3oDo @Z " + ":Z(Z :Z /u #X F\\ I] GZ )r H~U *Z X AY /p >o 4~d 3YMiK^ 8WEW EX " + "JV+W/o/X JW&Z 0[ Z-Z NZ-[ [.Z NZ,Z NZ.Z NZ=Z,~T$x I~T J~T I~S I~S 7Z !Z !Z \"Z :| BY-_ Hv p %Z \"Z " + " 4Z @X JZ MZ&{ 3u z 9~S FZ Lx MZ(Z :Z \"Z 4Z+] M~Q)Y JY(Y-_ Fr >Z Lr BZ(Z!y -Y -s /] <^.]&[&[ m >YJj 8iIX ;Y *u *f :iIY 7_ 6\\7" + "\\ K[0Z 6Z 4~P 2Y X Y ?hC\\ NYMm 8f +m 3s EY1Y 5[ 8Z,Y KYLgJ^$gEh Fs =Y8a Fr @YIi 7m !` 6i G~g#~T FZ 3o" + "Do @Z :Z(Z :Z .s \"X EZ G[ FZ 'p H~U *Z X AY ,k :k 2~d 3YLgJ^ 8WEW " + " EW IV,X/o/W IW&Z 0Z MZ/[ NZ-Z MZ.Z N[.Z MZ.Z MZ>Z,~T\"t G~T J~T I~S I~S 7Z !Z !Z \"Z :y ?Y-_ Fr 8r 9r :s :r " + " AXEr :r 8r :s :s -Z 2Z #YIn AkIY BkIY BkIX @jIY BkIY BkIY'l=t Mq :t ;t ;t ;t 3Y Y NX Y *m =X0X >m 3m 5n 5m" + " 3m 6XLm 7iHX @iHX @jIX @jIY 5[ 5YJj -Z El 3k 2l 3l 4l *X N\\ 5U ?Y Y KR HQ 1X.Y 9b 9Y1Z 7" + "] )~S \"j &Z +X@X -h ;X+c!l?\\ 6X Y DX Z FZ +X Kh 8} I~S Fr JZ As ,i 3[ $n ;m " + "#Z \"Y 3Z ?X KZ MZ&x -p Mu 4~S FZ Js JZ(Z :Z \"Z 4Z*] N~Q)Y JY(Y-_ Dn gB[ NYLj 5d (j 0q EY1Y 5Z 7Y+Z LYKdG]\"dBd Bo ;Y7` Dn >YHg 4i L^ 4e " + "E~g#~T FZ 3oDo @Z :Z(Z :Z ,n NX DX EY EZ %m G~U *Z X BZ )e 4e /~d 3YKeH] 8" + "WEW FW HV,W.o0X IW'Z /Z MZ/Z LZ.Z MZ/[ MZ.Z MZ/[ MZ>Y+~T p E~T J~T I~S I~S 7Z !Z !Z \"Z :u ;Y,^ Dn 4" + "n 5n 6o 6n @XBm 5n 4n 6o 6o +Z 2Z #YIl =gGY AhGY AhGX ?hHY @hHY @gGY%i:o Hm 7p 6o 6p 7p 1Y Y NX Y (i ;X0X " + "fGX >fGX >fGY 4Y 4YHf +Z Bg /g .g -g /g (X M[ 5T ?Z !Z JP 'X.Y 5" + "[ 6Y0Y 7] &~P Ne $Z +W?X '] 6W)a Mh<\\ 7Y !X CX Y EZ +X Id 6} I~S Cm HZ =l 'e " + "1Z i 6h !Z #Z 3Z ?Y M[ M['s &k Jo .~S FZ Gm GZ(Z :Z \"Z 4Z)] ~Q)Y JY(Y,^ Bi 9Z Gl AZ'Z Jm (Y (i )\\ " + ";].]'[#Z =Z =~a AX =X \"Y DdFY FYFb *h 6cFY 8j 0Y \"YAY GY1Y 5Y NX 0X1\\ :Y FY3Y2Y+Y1Y ;f :YFb 1cFX ;Y" + " $k ` 7cFY 6] 5[5Z KZ-[ 8Y 3~P 2Y X Y ;b=X NYJe 0` $e +l BY1Y 4Y 7Y*Y LYIaE[ b@a >k 9Y6_ Ah ;YFc 0e " + "FZ 2a D~i$~T FZ 3oDo @Z :Z(Z :Z )i LX CV CW DZ #h D~U *Z X -R9Z #[ *[ *~d 3" + "YIaE\\ 8WEW GX HV-W-o0W HW'Z 0Z L[0Z LZ/[ LZ0Z LZ/[ LZ0Z LZ?Z+~T Lj B~T J~T I~S I~S 7Z !Z !Z \"Z :o " + "5Y,^ Ai /h 0i 0i 0i >W?i 1j 0j 1j 1i (Z 2Z #YGh 9cEY ?dEY ?dEX =dFY >dFY >cEY#d5j Ch 1j 1j 1j 1j -Y Y NX Y" + " &e 9X0X :e ,f -f -e ,f 4XFe 0cEX a NU CZ N` 9X -T<[ " + " LYG]BX 5WEW %U HW NX MX GZ (d +b (b )b )a )b 9V;a " + ")c *c *c *c =a 4_ &^ %^ $^ &_ &_ :_/c RM] !R Z 5\\ " + " 9X ;X $Y HY NY 0Y 'X NY BY X !Y " + ":Y 8Y 4Y *Y 1Y EX 3Y CZ IU 3X -p " + " IY 8WEW #V &Z MV " + " 0U 'P ;Y 2Y >Z 8X " + " MT *X &X 9X DX " + " 5X ?\\%W ?Z 4\\ :X ;X $Y " + " IZ NY 0Y 'X NY BZ !X !Y :Y 8Y 4Y *Y 1Y EX 3Y " + " CZ IU 3X -o HY 8WEW \"V " + " 'Z LU 0V " + " CZ 2Y >Y 7X " + " MT )X 'X 9X DX 5W <\\(X ?" + "Z 3\\ ;Y e GX 2f KZ LY 0Y 'X !Y >" + "\\ %X &] 9Y 8Y 4Y *Y 1Y EX 3Y CZ IU 3" + "X $^ @Y 8WEW !V '\\:V ;V " + " 1W GZ 0Y @Z " + " FWHX LT 'X +W 7W " + " V 5b?c A[ -\\ ?e !f " + " f /X 0g 9Y 8Y 4Y *Y " + " 1Y EX 3Y CZ IU 3X 5Y " + " NV &\\=X ;V " + "1W GY /Y AZ EWHX " + " LT &W ,X 7V V 3~T " + " A] ,\\ @e !f d " + " %e -Y Nd @c " + " (m @c " + " +u $b -Y 'X 0d 2^ /X 0_ 1Y 8Y 4Y *Y " + " 1Y EX 3Y CZ IT 2X 5Y " + "-c !q Hd >c " + " $d ,Y Nd ?b " + " %g =" + "b *t #a ,Y 'X 0d " + " ,X /X 0Y +Y 8Y 4Y *Y 1Y EX 3Y CZ '" + "X 5Y -c Nm Fc " + " =c $c +Y Nc " + " >a " + " M\\ 8a \"~Y 1" + "r !` +Y 'X 0c 1X 1Y 8Y 4Y *Y 1Y EX 3Y " + " CZ &W 5Y -b Lj " + " Db std::printf(). + \note If configuration macro \c cimg_strict_warnings is set, this function throws a + \c CImgWarningException instead. + \warning As the first argument is a format string, it is highly recommended to write + \code + cimg::warn("%s",warning_message); + \endcode + instead of + \code + cimg::warn(warning_message); + \endcode + if \c warning_message can be arbitrary, to prevent nasty memory access. + **/ + inline void warn(const char *const format, ...) { + if (cimg::exception_mode()>=1) { + char *const message = new char[16384]; + std::va_list ap; + va_start(ap,format); + cimg_vsnprintf(message,16384,format,ap); + va_end(ap); +#ifdef cimg_strict_warnings + throw CImgWarningException(message); +#else + std::fprintf(cimg::output(),"\n%s[CImg] *** Warning ***%s%s\n",cimg::t_red,cimg::t_normal,message); +#endif + delete[] message; + } + } + + // Execute an external system command. + /** + \param command C-string containing the command line to execute. + \param module_name Module name. + \return Status value of the executed command, whose meaning is OS-dependent. + \note This function is similar to std::system() + but it does not open an extra console windows + on Windows-based systems. + **/ + inline int system(const char *const command, const char *const module_name=0, const bool is_verbose=false) { + cimg::unused(module_name); +#ifdef cimg_no_system_calls + return -1; +#else + if (is_verbose) return std::system(command); +#if cimg_OS==1 + const unsigned int l = (unsigned int)std::strlen(command); + if (l) { + char *const ncommand = new char[l + 24]; + std::memcpy(ncommand,command,l); + std::strcpy(ncommand + l," >/dev/null 2>&1"); // Make command silent + const int out_val = std::system(ncommand); + delete[] ncommand; + return out_val; + } else return -1; +#elif cimg_OS==2 + PROCESS_INFORMATION pi; + STARTUPINFOA si; + std::memset(&pi,0,sizeof(PROCESS_INFORMATION)); + std::memset(&si,0,sizeof(STARTUPINFO)); + GetStartupInfoA(&si); + si.cb = sizeof(si); + si.wShowWindow = SW_HIDE; + si.dwFlags |= SW_HIDE | STARTF_USESHOWWINDOW; + const BOOL res = CreateProcessA((LPCSTR)module_name,(LPSTR)command,0,0,FALSE,0,0,0,&si,&pi); + if (res) { + WaitForSingleObject(pi.hProcess,INFINITE); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return 0; + } else { + char* lpMsgBuf; + + // Get the error message. + DWORD errorCode = GetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0,errorCode,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPSTR)&lpMsgBuf,0,0); + cimg::warn("cimg::system() : Command '%s' (module name '%s) failed with error %lu: %s", + module_name==0?"(null)":module_name, + command==0?"(null)":command, + errorCode,lpMsgBuf); + return -1; + } +#else + return std::system(command); +#endif +#endif + } + + //! Return a reference to a temporary variable of type T. + template + inline T& temporary(const T&) { + static T temp; + return temp; + } + + //! Exchange values of variables \c a and \c b. + template + inline void swap(T& a, T& b) { T t = a; a = b; b = t; } + + //! Exchange values of variables (\c a1,\c a2) and (\c b1,\c b2). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) { + cimg::swap(a1,b1); cimg::swap(a2,b2); + } + + //! Exchange values of variables (\c a1,\c a2,\c a3) and (\c b1,\c b2,\c b3). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3) { + cimg::swap(a1,b1,a2,b2); cimg::swap(a3,b3); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a4) and (\c b1,\c b2,...,\c b4). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4) { + cimg::swap(a1,b1,a2,b2,a3,b3); cimg::swap(a4,b4); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a5) and (\c b1,\c b2,...,\c b5). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4); cimg::swap(a5,b5); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a6) and (\c b1,\c b2,...,\c b6). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5); cimg::swap(a6,b6); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a7) and (\c b1,\c b2,...,\c b7). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6); cimg::swap(a7,b7); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a8) and (\c b1,\c b2,...,\c b8). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7, T8& a8, T8& b8) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7); cimg::swap(a8,b8); + } + + //! Return the endianness of the current architecture. + /** + \return \c false for Little Endian or \c true for Big Endian. + **/ + inline bool endianness() { + const int x = 1; + return ((unsigned char*)&x)[0]?false:true; + } + + //! Reverse endianness of all elements in a memory buffer. + /** + \param[in,out] buffer Memory buffer whose endianness must be reversed. + \param size Number of buffer elements to reverse. + **/ + template + inline void invert_endianness(T* const buffer, const cimg_ulong size) { + if (size) switch (sizeof(T)) { + case 1 : break; + case 2 : { + for (unsigned short *ptr = (unsigned short*)buffer + size; ptr>(unsigned short*)buffer; ) { + const unsigned short val = *(--ptr); + *ptr = (unsigned short)((val>>8) | ((val<<8))); + } + } break; + case 4 : { + for (unsigned int *ptr = (unsigned int*)buffer + size; ptr>(unsigned int*)buffer; ) { + const unsigned int val = *(--ptr); + *ptr = (val>>24) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | (val<<24); + } + } break; + case 8 : { + const cimg_uint64 + m0 = (cimg_uint64)0xff, m1 = m0<<8, m2 = m0<<16, m3 = m0<<24, + m4 = m0<<32, m5 = m0<<40, m6 = m0<<48, m7 = m0<<56; + for (cimg_uint64 *ptr = (cimg_uint64*)buffer + size; ptr>(cimg_uint64*)buffer; ) { + const cimg_uint64 val = *(--ptr); + *ptr = (((val&m7)>>56) | ((val&m6)>>40) | ((val&m5)>>24) | ((val&m4)>>8) | + ((val&m3)<<8) |((val&m2)<<24) | ((val&m1)<<40) | ((val&m0)<<56)); + } + } break; + default : { + for (T* ptr = buffer + size; ptr>buffer; ) { + unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T); + for (int i = 0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe)); + } + } + } + } + inline void invert_endianness(bool* const, const cimg_ulong) {} + inline void invert_endianness(unsigned char* const, const cimg_ulong) {} + inline void invert_endianness(char* const, const cimg_ulong) {} + + //! Reverse endianness of a single variable. + /** + \param[in,out] a Variable to reverse. + \return Reference to reversed variable. + **/ + template + inline T& invert_endianness(T& a) { + invert_endianness(&a,1); + return a; + } + + // Conversion functions to get more precision when trying to store unsigned ints values as floats. + inline unsigned int float2uint(const float f) { + int tmp = 0; + std::memcpy(&tmp,&f,sizeof(float)); + if (tmp>=0) return (unsigned int)f; + unsigned int u; + // use memcpy instead of assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&u,&f,sizeof(float)); + return ((u)<<2)>>2; // set sign & exponent bit to 0 + } + + inline float uint2float(const unsigned int u) { + if (u<(1U<<19)) return (float)u; // Consider safe storage of unsigned int as floats until 19bits (i.e 524287) + float f; + const unsigned int v = u|(3U<<(8*sizeof(unsigned int)-2)); // set sign & exponent bit to 1 + // use memcpy instead of simple assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&f,&v,sizeof(float)); + return f; + } + + //! Return the value of a system timer, with a millisecond precision. + /** + \note The timer does not necessarily starts from \c 0. + **/ + inline cimg_uint64 time() { +#if cimg_OS==1 + struct timeval st_time; + gettimeofday(&st_time,0); + return (cimg_uint64)st_time.tv_sec*1000 + (cimg_uint64)st_time.tv_usec/1000; +#elif cimg_OS==2 + ULARGE_INTEGER ul; + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + ul.LowPart = ft.dwLowDateTime; + ul.HighPart = ft.dwHighDateTime; + return (cimg_uint64)ul.QuadPart/10000; +#else + return 0; +#endif + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_uint64 tictoc(const bool is_tic); + + //! Start tic/toc timer for time measurement between code instructions. + /** + \return Current value of the timer (same value as time()). + **/ + inline cimg_uint64 tic() { + return cimg::tictoc(true); + } + + //! End tic/toc timer and displays elapsed time from last call to tic(). + /** + \return Time elapsed (in ms) since last call to tic(). + **/ + inline cimg_uint64 toc() { + return cimg::tictoc(false); + } + + //! Sleep for a given numbers of milliseconds. + /** + \param milliseconds Number of milliseconds to wait for. + \note This function frees the CPU resources during the sleeping time. + It can be used to temporize your program properly, without wasting CPU time. + **/ + inline void sleep(const unsigned int milliseconds) { +#if cimg_OS==1 + struct timespec tv; + tv.tv_sec = milliseconds/1000; + tv.tv_nsec = (milliseconds%1000)*1000000; + nanosleep(&tv,0); +#elif cimg_OS==2 + Sleep(milliseconds); +#else + cimg::unused(milliseconds); +#endif + } + + inline unsigned int wait(const unsigned int milliseconds, cimg_uint64 *const p_timer) { + if (!*p_timer) *p_timer = cimg::time(); + const cimg_uint64 current_time = cimg::time(); + if (current_time<*p_timer || current_time>=*p_timer + milliseconds) { *p_timer = current_time; return 0; } + const unsigned int time_diff = (unsigned int)(*p_timer + milliseconds - current_time); + *p_timer = current_time + time_diff; + cimg::sleep(time_diff); + return time_diff; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \return Number of milliseconds elapsed since the last call to wait(). + \note Same as sleep() with a waiting time computed with regard to the last call + of wait(). It may be used to temporize your program properly, without wasting CPU time. + **/ + inline unsigned int wait(const unsigned int milliseconds) { + cimg::mutex(3); + static cimg_uint64 timer = cimg::time(); + cimg::mutex(3,0); + return cimg::wait(milliseconds,&timer); + } + + // Custom random number generator (allow re-entrance). + inline cimg_uint64& rng() { // Used as a shared global number for rng + static cimg_uint64 rng = 0xB16B00B5U; + return rng; + } + + inline unsigned int _rand(cimg_uint64 *const p_rng) { + *p_rng = *p_rng*1103515245 + 12345U; + return (unsigned int)*p_rng; + } + + inline unsigned int _rand() { + cimg::mutex(4); + const unsigned int res = cimg::_rand(&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline void srand(cimg_uint64 *const p_rng) { +#if cimg_OS==1 + *p_rng = cimg::time() + (cimg_uint64)getpid(); +#elif cimg_OS==2 + *p_rng = cimg::time() + (cimg_uint64)_getpid(); +#endif + } + + inline void srand() { + cimg::mutex(4); + cimg::srand(&cimg::rng()); + cimg::mutex(4,0); + } + + inline void srand(const cimg_uint64 seed) { + cimg::mutex(4); + cimg::rng() = seed; + cimg::mutex(4,0); + } + + inline double rand(const double val_min, const double val_max, cimg_uint64 *const p_rng) { + const double val = cimg::_rand(p_rng)/(double)~0U; + return val_min + (val_max - val_min)*val; + } + + inline double rand(const double val_min, const double val_max) { + cimg::mutex(4); + const double res = cimg::rand(val_min,val_max,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline double rand(const double val_max, cimg_uint64 *const p_rng) { + const double val = cimg::_rand(p_rng)/(double)~0U; + return val_max*val; + } + + inline double rand(const double val_max=1) { + cimg::mutex(4); + const double res = cimg::rand(val_max,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline double grand(cimg_uint64 *const p_rng) { + double x1, w; + do { + const double x2 = cimg::rand(-1,1,p_rng); + x1 = cimg::rand(-1,1,p_rng); + w = x1*x1 + x2*x2; + } while (w<=0 || w>=1.); + return x1*std::sqrt((-2*std::log(w))/w); + } + + inline double grand() { + cimg::mutex(4); + const double res = cimg::grand(&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + inline unsigned int prand(const double z, cimg_uint64 *const p_rng) { + if (z<=1.e-10) return 0; + if (z>100) return (unsigned int)((std::sqrt(z) * cimg::grand(p_rng)) + z); + unsigned int k = 0; + const double y = std::exp(-z); + for (double s = 1.; s>=y; ++k) s*=cimg::rand(1,p_rng); + return k - 1; + } + + inline unsigned int prand(const double z) { + cimg::mutex(4); + const unsigned int res = cimg::prand(z,&cimg::rng()); + cimg::mutex(4,0); + return res; + } + + //! Cut (i.e. clamp) value in specified interval. + template + inline T cut(const T& val, const t& val_min, const t& val_max) { + return val<=val_min?(T)val_min:val>=val_max?(T)val_max:val; + } + + //! Bitwise-rotate value on the left. + template + inline T rol(const T& a, const unsigned int n=1) { + return n?(T)((a<>((sizeof(T)<<3) - n))):a; + } + + inline float rol(const float a, const unsigned int n=1) { + return (float)rol((int)a,n); + } + + inline double rol(const double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + + inline double rol(const long double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half rol(const half a, const unsigned int n=1) { + return (half)rol((int)a,n); + } +#endif + + //! Bitwise-rotate value on the right. + template + inline T ror(const T& a, const unsigned int n=1) { + return n?(T)((a>>n)|(a<<((sizeof(T)<<3) - n))):a; + } + + inline float ror(const float a, const unsigned int n=1) { + return (float)ror((int)a,n); + } + + inline double ror(const double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + + inline double ror(const long double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half ror(const half a, const unsigned int n=1) { + return (half)ror((int)a,n); + } +#endif + + //! Return absolute value of a value. + template + inline T abs(const T& a) { + return a>=0?a:-a; + } + inline bool abs(const bool a) { + return a; + } + inline int abs(const unsigned char a) { + return (int)a; + } + inline int abs(const unsigned short a) { + return (int)a; + } + inline int abs(const unsigned int a) { + return (int)a; + } + inline int abs(const int a) { + return std::abs(a); + } + inline cimg_int64 abs(const cimg_uint64 a) { + return (cimg_int64)a; + } + inline double abs(const double a) { + return std::fabs(a); + } + inline float abs(const float a) { + return (float)std::fabs((double)a); + } + + //! Return hyperbolic arcosine of a value. + inline double acosh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::acosh(x); +#else + return std::log(x + std::sqrt(x*x - 1)); +#endif + } + + //! Return hyperbolic arcsine of a value. + inline double asinh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::asinh(x); +#else + return std::log(x + std::sqrt(x*x + 1)); +#endif + } + + //! Return hyperbolic arctangent of a value. + inline double atanh(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::atanh(x); +#else + return 0.5*std::log((1. + x)/(1. - x)); +#endif + } + + //! Return the sinc of a given value. + inline double sinc(const double x) { + return x?std::sin(x)/x:1; + } + + //! Return base-2 logarithm of a value. + inline double log2(const double x) { +#if cimg_use_cpp11==1 && !defined(_MSC_VER) + return std::log2(x); +#else + const double base2 = std::log(2.); + return std::log(x)/base2; +#endif + } + + //! Return square of a value. + template + inline T sqr(const T& val) { + return val*val; + } + + // Return inverse of error function. + template + inline T erfinv(const T& val) { + const T + sgn = val<0?-1:1, + x = (1 - val)*(1 + val), + lnx = std::log(x), + tt1 = (T)(2/(cimg::PI*0.147) + 0.5*lnx), + tt2 = lnx/(T)0.147; + return sgn*std::sqrt(-tt1 + std::sqrt(tt1*tt1 - tt2)); + } + + //! Return cubic root of a value. + template + inline double cbrt(const T& x) { +#if cimg_use_cpp11==1 + return std::cbrt(x); +#else + return x>=0?std::pow((double)x,1./3):-std::pow(-(double)x,1./3); +#endif + } + + template + inline T pow3(const T& val) { + return val*val*val; + } + template + inline T pow4(const T& val) { + return val*val*val*val; + } + + //! Return the minimum between three values. + template + inline t min(const t& a, const t& b, const t& c) { + return std::min(std::min(a,b),c); + } + + //! Return the minimum between four values. + template + inline t min(const t& a, const t& b, const t& c, const t& d) { + return std::min(std::min(a,b),std::min(c,d)); + } + + //! Return the minabs between two values. + template + inline t minabs(const t& a, const t& b) { + return cimg::abs(b) + inline t minabs(const t& a, const t& b, const t& abs_b) { + return abs_b + inline t max(const t& a, const t& b, const t& c) { + return std::max(std::max(a,b),c); + } + + //! Return the maximum between four values. + template + inline t max(const t& a, const t& b, const t& c, const t& d) { + return std::max(std::max(a,b),std::max(c,d)); + } + + //! Return the maxabs between two values. + template + inline t maxabs(const t& a, const t& b) { + return cimg::abs(b)>cimg::abs(a)?b:a; + } + + template + inline t maxabs(const t& a, const t& b, const t& abs_b) { + return abs_b>cimg::abs(a)?b:a; + } + + //! Return the sign of a value. + template + inline T sign(const T& x) { + return (T)(cimg::type::is_nan(x)?0:x<0?-1:x>0); + } + + //! Return the nearest power of 2 higher than given value. + template + inline cimg_uint64 nearest_pow2(const T& x) { + cimg_uint64 i = 1; + while (x>i) i<<=1; + return i; + } + + //! Return the modulo of a value. + /** + \param x Input value. + \param m Modulo value. + \note This modulo function accepts negative and floating-points modulo numbers, as well as variables of any type. + **/ + template + inline T mod(const T& x, const T& m) { + const double dx = (double)x, dm = (double)m; + if (!cimg::type::is_finite(dm)) return x; + if (cimg::type::is_finite(dx)) return (T)(dx - dm * std::floor(dx / dm)); + return (T)0; + } + inline int mod(const bool x, const bool m) { + return m?(x?1:0):0; + } + inline int mod(const unsigned char x, const unsigned char m) { + return x%m; + } + inline int mod(const char x, const char m) { +#if defined(CHAR_MAX) && CHAR_MAX==255 + return x%m; +#else + return x>=0?x%m:(x%m?m + x%m:0); +#endif + } + inline int mod(const unsigned short x, const unsigned short m) { + return (int)(x%m); + } + inline int mod(const short x, const short m) { + return (int)(x>=0?x%m:(x%m?m + x%m:0)); + } + inline int mod(const unsigned int x, const unsigned int m) { + return (int)(x%m); + } + inline int mod(const int x, const int m) { + return (int)(x>=0?x%m:(x%m?m + x%m:0)); + } + inline cimg_int64 mod(const cimg_uint64 x, const cimg_uint64 m) { + return (cimg_int64)(x%m); + } + inline cimg_int64 mod(const cimg_int64 x, const cimg_int64 m) { + return (cimg_int64)(x>=0?x%m:(x%m?m + x%m:0)); + } + + //! Return the min-mod of two values. + /** + \note minmod(\p a,\p b) is defined to be: + - minmod(\p a,\p b) = min(\p a,\p b), if \p a and \p b have the same sign. + - minmod(\p a,\p b) = 0, if \p a and \p b have different signs. + **/ + template + inline T minmod(const T& a, const T& b) { + return a*b<=0?0:(a>0?(a + inline T round(const T& x) { + return (T)std::floor((_cimg_Tfloat)x + 0.5f); + } + + template + inline int uiround(const T x) { + return cimg::type::is_float()?(int)(x + 0.5f):(int)x; + } + + //! Return rounded value. + /** + \param x Value to be rounded. + \param y Rounding precision. + \param rounding_type Type of rounding operation (\c 0 = nearest, \c -1 = backward, \c 1 = forward). + \return Rounded value, having the same type as input value \c x. + **/ + template + inline T round(const T& x, const double y, const int rounding_type=0) { + if (y<=0) return x; + if (y==1) switch (rounding_type) { + case 0 : return cimg::round(x); + case 1 : return (T)std::ceil((_cimg_Tfloat)x); + default : return (T)std::floor((_cimg_Tfloat)x); + } + const double sx = (double)x/y, floor = std::floor(sx), delta = sx - floor; + return (T)(y*(rounding_type<0?floor:rounding_type>0?std::ceil(sx):delta<0.5?floor:std::ceil(sx))); + } + + // Code to compute fast median from 2,3,5,7,9,13,25 and 49 values. + // (contribution by RawTherapee: http://rawtherapee.com/). + template + inline T median(T val0, T val1) { + return (val0 + val1)/2; + } + + template + inline T median(T val0, T val1, T val2) { + return std::max(std::min(val0,val1),std::min(val2,std::max(val0,val1))); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = std::max(val0,tmp); val1 = std::min(val1,val4); tmp = std::min(val1,val2); val2 = std::max(val1,val2); + val1 = tmp; tmp = std::min(val2,val3); + return std::max(val1,tmp); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6) { + T tmp = std::min(val0,val5); + val5 = std::max(val0,val5); val0 = tmp; tmp = std::min(val0,val3); val3 = std::max(val0,val3); val0 = tmp; + tmp = std::min(val1,val6); val6 = std::max(val1,val6); val1 = tmp; tmp = std::min(val2,val4); + val4 = std::max(val2,val4); val2 = tmp; val1 = std::max(val0,val1); tmp = std::min(val3,val5); + val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); + val3 = std::max(tmp,val3); val3 = std::min(val3,val6); tmp = std::min(val4,val5); val4 = std::max(val1,tmp); + tmp = std::min(val1,tmp); val3 = std::max(tmp,val3); + return std::min(val3,val4); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8) { + T tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val7 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); + val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val6,val7); + val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val3 = std::max(val0,val3); val5 = std::min(val5,val8); + val7 = std::max(val4,tmp); tmp = std::min(val4,tmp); val6 = std::max(val3,val6); + val4 = std::max(val1,tmp); val2 = std::min(val2,val5); val4 = std::min(val4,val7); + tmp = std::min(val4,val2); val2 = std::max(val4,val2); val4 = std::max(val6,tmp); + return std::min(val4,val2); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8, T val9, T val10, T val11, + T val12) { + T tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = tmp; tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; + tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val5,val8); + val8 = std::max(val5,val8); val5 = tmp; tmp = std::min(val0,val12); val12 = std::max(val0,val12); + val0 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val2,val3); val3 = std::max(val2,val3); val2 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val8,val11); + val11 = std::max(val8,val11); val8 = tmp; tmp = std::min(val7,val12); val12 = std::max(val7,val12); val7 = tmp; + tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val10,val11); val11 = std::max(val10,val11); val10 = tmp; tmp = std::min(val1,val4); + val4 = std::max(val1,val4); val1 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val8); val8 = std::max(val7,val8); val7 = tmp; val11 = std::min(val11,val12); + tmp = std::min(val4,val9); val9 = std::max(val4,val9); val4 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; + tmp = std::min(val5,val6); val6 = std::max(val5,val6); val5 = tmp; val8 = std::min(val8,val9); + val10 = std::min(val10,val11); tmp = std::min(val1,val7); val7 = std::max(val1,val7); val1 = tmp; + tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; val3 = std::max(val1,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; val8 = std::min(val8,val10); + val5 = std::max(val0,val5); val5 = std::max(val2,val5); tmp = std::min(val6,val8); val8 = std::max(val6,val8); + val5 = std::max(val3,val5); val7 = std::min(val7,val8); val6 = std::max(val4,tmp); tmp = std::min(val4,tmp); + val5 = std::max(tmp,val5); val6 = std::min(val6,val7); + return std::max(val5,val6); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, + T val5, T val6, T val7, T val8, T val9, + T val10, T val11, T val12, T val13, T val14, + T val15, T val16, T val17, T val18, T val19, + T val20, T val21, T val22, T val23, T val24) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); val2 = std::min(tmp,val3); + val3 = std::max(tmp,val3); tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; + tmp = std::min(val5,val7); val7 = std::max(val5,val7); val5 = std::min(tmp,val6); val6 = std::max(tmp,val6); + tmp = std::min(val9,val10); val10 = std::max(val9,val10); val9 = tmp; tmp = std::min(val8,val10); + val10 = std::max(val8,val10); val8 = std::min(tmp,val9); val9 = std::max(tmp,val9); + tmp = std::min(val12,val13); val13 = std::max(val12,val13); val12 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val15,val16); val16 = std::max(val15,val16); val15 = tmp; tmp = std::min(val14,val16); + val16 = std::max(val14,val16); val14 = std::min(tmp,val15); val15 = std::max(tmp,val15); + tmp = std::min(val18,val19); val19 = std::max(val18,val19); val18 = tmp; tmp = std::min(val17,val19); + val19 = std::max(val17,val19); val17 = std::min(tmp,val18); val18 = std::max(tmp,val18); + tmp = std::min(val21,val22); val22 = std::max(val21,val22); val21 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = std::min(tmp,val21); val21 = std::max(tmp,val21); + tmp = std::min(val23,val24); val24 = std::max(val23,val24); val23 = tmp; tmp = std::min(val2,val5); + val5 = std::max(val2,val5); val2 = tmp; tmp = std::min(val3,val6); val6 = std::max(val3,val6); val3 = tmp; + tmp = std::min(val0,val6); val6 = std::max(val0,val6); val0 = std::min(tmp,val3); val3 = std::max(tmp,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = std::min(tmp,val4); val4 = std::max(tmp,val4); tmp = std::min(val11,val14); + val14 = std::max(val11,val14); val11 = tmp; tmp = std::min(val8,val14); val14 = std::max(val8,val14); + val8 = std::min(tmp,val11); val11 = std::max(tmp,val11); tmp = std::min(val12,val15); + val15 = std::max(val12,val15); val12 = tmp; tmp = std::min(val9,val15); val15 = std::max(val9,val15); + val9 = std::min(tmp,val12); val12 = std::max(tmp,val12); tmp = std::min(val13,val16); + val16 = std::max(val13,val16); val13 = tmp; tmp = std::min(val10,val16); val16 = std::max(val10,val16); + val10 = std::min(tmp,val13); val13 = std::max(tmp,val13); tmp = std::min(val20,val23); + val23 = std::max(val20,val23); val20 = tmp; tmp = std::min(val17,val23); val23 = std::max(val17,val23); + val17 = std::min(tmp,val20); val20 = std::max(tmp,val20); tmp = std::min(val21,val24); + val24 = std::max(val21,val24); val21 = tmp; tmp = std::min(val18,val24); val24 = std::max(val18,val24); + val18 = std::min(tmp,val21); val21 = std::max(tmp,val21); tmp = std::min(val19,val22); + val22 = std::max(val19,val22); val19 = tmp; val17 = std::max(val8,val17); tmp = std::min(val9,val18); + val18 = std::max(val9,val18); val9 = tmp; tmp = std::min(val0,val18); val18 = std::max(val0,val18); + val9 = std::max(tmp,val9); tmp = std::min(val10,val19); val19 = std::max(val10,val19); val10 = tmp; + tmp = std::min(val1,val19); val19 = std::max(val1,val19); val1 = std::min(tmp,val10); + val10 = std::max(tmp,val10); tmp = std::min(val11,val20); val20 = std::max(val11,val20); val11 = tmp; + tmp = std::min(val2,val20); val20 = std::max(val2,val20); val11 = std::max(tmp,val11); + tmp = std::min(val12,val21); val21 = std::max(val12,val21); val12 = tmp; tmp = std::min(val3,val21); + val21 = std::max(val3,val21); val3 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val13,val22); val22 = std::max(val13,val22); val4 = std::min(val4,val22); + val13 = std::max(val4,tmp); tmp = std::min(val4,tmp); val4 = tmp; tmp = std::min(val14,val23); + val23 = std::max(val14,val23); val14 = tmp; tmp = std::min(val5,val23); val23 = std::max(val5,val23); + val5 = std::min(tmp,val14); val14 = std::max(tmp,val14); tmp = std::min(val15,val24); + val24 = std::max(val15,val24); val15 = tmp; val6 = std::min(val6,val24); tmp = std::min(val6,val15); + val15 = std::max(val6,val15); val6 = tmp; tmp = std::min(val7,val16); val7 = std::min(tmp,val19); + tmp = std::min(val13,val21); val15 = std::min(val15,val23); tmp = std::min(val7,tmp); + val7 = std::min(tmp,val15); val9 = std::max(val1,val9); val11 = std::max(val3,val11); + val17 = std::max(val5,val17); val17 = std::max(val11,val17); val17 = std::max(val9,val17); + tmp = std::min(val4,val10); val10 = std::max(val4,val10); val4 = tmp; tmp = std::min(val6,val12); + val12 = std::max(val6,val12); val6 = tmp; tmp = std::min(val7,val14); val14 = std::max(val7,val14); + val7 = tmp; tmp = std::min(val4,val6); val6 = std::max(val4,val6); val7 = std::max(tmp,val7); + tmp = std::min(val12,val14); val14 = std::max(val12,val14); val12 = tmp; val10 = std::min(val10,val14); + tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val10,val12); + val12 = std::max(val10,val12); val10 = std::max(val6,tmp); tmp = std::min(val6,tmp); + val17 = std::max(tmp,val17); tmp = std::min(val12,val17); val17 = std::max(val12,val17); val12 = tmp; + val7 = std::min(val7,val17); tmp = std::min(val7,val10); val10 = std::max(val7,val10); val7 = tmp; + tmp = std::min(val12,val18); val18 = std::max(val12,val18); val12 = std::max(val7,tmp); + val10 = std::min(val10,val18); tmp = std::min(val12,val20); val20 = std::max(val12,val20); val12 = tmp; + tmp = std::min(val10,val20); + return std::max(tmp,val12); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, + T val7, T val8, T val9, T val10, T val11, T val12, T val13, + T val14, T val15, T val16, T val17, T val18, T val19, T val20, + T val21, T val22, T val23, T val24, T val25, T val26, T val27, + T val28, T val29, T val30, T val31, T val32, T val33, T val34, + T val35, T val36, T val37, T val38, T val39, T val40, T val41, + T val42, T val43, T val44, T val45, T val46, T val47, T val48) { + T tmp = std::min(val0,val32); + val32 = std::max(val0,val32); val0 = tmp; tmp = std::min(val1,val33); val33 = std::max(val1,val33); val1 = tmp; + tmp = std::min(val2,val34); val34 = std::max(val2,val34); val2 = tmp; tmp = std::min(val3,val35); + val35 = std::max(val3,val35); val3 = tmp; tmp = std::min(val4,val36); val36 = std::max(val4,val36); val4 = tmp; + tmp = std::min(val5,val37); val37 = std::max(val5,val37); val5 = tmp; tmp = std::min(val6,val38); + val38 = std::max(val6,val38); val6 = tmp; tmp = std::min(val7,val39); val39 = std::max(val7,val39); val7 = tmp; + tmp = std::min(val8,val40); val40 = std::max(val8,val40); val8 = tmp; tmp = std::min(val9,val41); + val41 = std::max(val9,val41); val9 = tmp; tmp = std::min(val10,val42); val42 = std::max(val10,val42); + val10 = tmp; tmp = std::min(val11,val43); val43 = std::max(val11,val43); val11 = tmp; + tmp = std::min(val12,val44); val44 = std::max(val12,val44); val12 = tmp; tmp = std::min(val13,val45); + val45 = std::max(val13,val45); val13 = tmp; tmp = std::min(val14,val46); val46 = std::max(val14,val46); + val14 = tmp; tmp = std::min(val15,val47); val47 = std::max(val15,val47); val15 = tmp; + tmp = std::min(val16,val48); val48 = std::max(val16,val48); val16 = tmp; tmp = std::min(val0,val16); + val16 = std::max(val0,val16); val0 = tmp; tmp = std::min(val1,val17); val17 = std::max(val1,val17); + val1 = tmp; tmp = std::min(val2,val18); val18 = std::max(val2,val18); val2 = tmp; tmp = std::min(val3,val19); + val19 = std::max(val3,val19); val3 = tmp; tmp = std::min(val4,val20); val20 = std::max(val4,val20); val4 = tmp; + tmp = std::min(val5,val21); val21 = std::max(val5,val21); val5 = tmp; tmp = std::min(val6,val22); + val22 = std::max(val6,val22); val6 = tmp; tmp = std::min(val7,val23); val23 = std::max(val7,val23); val7 = tmp; + tmp = std::min(val8,val24); val24 = std::max(val8,val24); val8 = tmp; tmp = std::min(val9,val25); + val25 = std::max(val9,val25); val9 = tmp; tmp = std::min(val10,val26); val26 = std::max(val10,val26); + val10 = tmp; tmp = std::min(val11,val27); val27 = std::max(val11,val27); val11 = tmp; + tmp = std::min(val12,val28); val28 = std::max(val12,val28); val12 = tmp; tmp = std::min(val13,val29); + val29 = std::max(val13,val29); val13 = tmp; tmp = std::min(val14,val30); val30 = std::max(val14,val30); + val14 = tmp; tmp = std::min(val15,val31); val31 = std::max(val15,val31); val15 = tmp; + tmp = std::min(val32,val48); val48 = std::max(val32,val48); val32 = tmp; tmp = std::min(val16,val32); + val32 = std::max(val16,val32); val16 = tmp; tmp = std::min(val17,val33); val33 = std::max(val17,val33); + val17 = tmp; tmp = std::min(val18,val34); val34 = std::max(val18,val34); val18 = tmp; + tmp = std::min(val19,val35); val35 = std::max(val19,val35); val19 = tmp; tmp = std::min(val20,val36); + val36 = std::max(val20,val36); val20 = tmp; tmp = std::min(val21,val37); val37 = std::max(val21,val37); + val21 = tmp; tmp = std::min(val22,val38); val38 = std::max(val22,val38); val22 = tmp; + tmp = std::min(val23,val39); val39 = std::max(val23,val39); val23 = tmp; tmp = std::min(val24,val40); + val40 = std::max(val24,val40); val24 = tmp; tmp = std::min(val25,val41); val41 = std::max(val25,val41); + val25 = tmp; tmp = std::min(val26,val42); val42 = std::max(val26,val42); val26 = tmp; + tmp = std::min(val27,val43); val43 = std::max(val27,val43); val27 = tmp; tmp = std::min(val28,val44); + val44 = std::max(val28,val44); val28 = tmp; tmp = std::min(val29,val45); val45 = std::max(val29,val45); + val29 = tmp; tmp = std::min(val30,val46); val46 = std::max(val30,val46); val30 = tmp; + tmp = std::min(val31,val47); val47 = std::max(val31,val47); val31 = tmp; tmp = std::min(val0,val8); + val8 = std::max(val0,val8); val0 = tmp; tmp = std::min(val1,val9); val9 = std::max(val1,val9); val1 = tmp; + tmp = std::min(val2,val10); val10 = std::max(val2,val10); val2 = tmp; tmp = std::min(val3,val11); + val11 = std::max(val3,val11); val3 = tmp; tmp = std::min(val4,val12); val12 = std::max(val4,val12); val4 = tmp; + tmp = std::min(val5,val13); val13 = std::max(val5,val13); val5 = tmp; tmp = std::min(val6,val14); + val14 = std::max(val6,val14); val6 = tmp; tmp = std::min(val7,val15); val15 = std::max(val7,val15); val7 = tmp; + tmp = std::min(val16,val24); val24 = std::max(val16,val24); val16 = tmp; tmp = std::min(val17,val25); + val25 = std::max(val17,val25); val17 = tmp; tmp = std::min(val18,val26); val26 = std::max(val18,val26); + val18 = tmp; tmp = std::min(val19,val27); val27 = std::max(val19,val27); val19 = tmp; + tmp = std::min(val20,val28); val28 = std::max(val20,val28); val20 = tmp; tmp = std::min(val21,val29); + val29 = std::max(val21,val29); val21 = tmp; tmp = std::min(val22,val30); val30 = std::max(val22,val30); + val22 = tmp; tmp = std::min(val23,val31); val31 = std::max(val23,val31); val23 = tmp; + tmp = std::min(val32,val40); val40 = std::max(val32,val40); val32 = tmp; tmp = std::min(val33,val41); + val41 = std::max(val33,val41); val33 = tmp; tmp = std::min(val34,val42); val42 = std::max(val34,val42); + val34 = tmp; tmp = std::min(val35,val43); val43 = std::max(val35,val43); val35 = tmp; + tmp = std::min(val36,val44); val44 = std::max(val36,val44); val36 = tmp; tmp = std::min(val37,val45); + val45 = std::max(val37,val45); val37 = tmp; tmp = std::min(val38,val46); val46 = std::max(val38,val46); + val38 = tmp; tmp = std::min(val39,val47); val47 = std::max(val39,val47); val39 = tmp; + tmp = std::min(val8,val32); val32 = std::max(val8,val32); val8 = tmp; tmp = std::min(val9,val33); + val33 = std::max(val9,val33); val9 = tmp; tmp = std::min(val10,val34); val34 = std::max(val10,val34); + val10 = tmp; tmp = std::min(val11,val35); val35 = std::max(val11,val35); val11 = tmp; + tmp = std::min(val12,val36); val36 = std::max(val12,val36); val12 = tmp; tmp = std::min(val13,val37); + val37 = std::max(val13,val37); val13 = tmp; tmp = std::min(val14,val38); val38 = std::max(val14,val38); + val14 = tmp; tmp = std::min(val15,val39); val39 = std::max(val15,val39); val15 = tmp; + tmp = std::min(val24,val48); val48 = std::max(val24,val48); val24 = tmp; tmp = std::min(val8,val16); + val16 = std::max(val8,val16); val8 = tmp; tmp = std::min(val9,val17); val17 = std::max(val9,val17); + val9 = tmp; tmp = std::min(val10,val18); val18 = std::max(val10,val18); val10 = tmp; + tmp = std::min(val11,val19); val19 = std::max(val11,val19); val11 = tmp; tmp = std::min(val12,val20); + val20 = std::max(val12,val20); val12 = tmp; tmp = std::min(val13,val21); val21 = std::max(val13,val21); + val13 = tmp; tmp = std::min(val14,val22); val22 = std::max(val14,val22); val14 = tmp; + tmp = std::min(val15,val23); val23 = std::max(val15,val23); val15 = tmp; tmp = std::min(val24,val32); + val32 = std::max(val24,val32); val24 = tmp; tmp = std::min(val25,val33); val33 = std::max(val25,val33); + val25 = tmp; tmp = std::min(val26,val34); val34 = std::max(val26,val34); val26 = tmp; + tmp = std::min(val27,val35); val35 = std::max(val27,val35); val27 = tmp; tmp = std::min(val28,val36); + val36 = std::max(val28,val36); val28 = tmp; tmp = std::min(val29,val37); val37 = std::max(val29,val37); + val29 = tmp; tmp = std::min(val30,val38); val38 = std::max(val30,val38); val30 = tmp; + tmp = std::min(val31,val39); val39 = std::max(val31,val39); val31 = tmp; tmp = std::min(val40,val48); + val48 = std::max(val40,val48); val40 = tmp; tmp = std::min(val0,val4); val4 = std::max(val0,val4); + val0 = tmp; tmp = std::min(val1,val5); val5 = std::max(val1,val5); val1 = tmp; tmp = std::min(val2,val6); + val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val8,val12); val12 = std::max(val8,val12); val8 = tmp; tmp = std::min(val9,val13); + val13 = std::max(val9,val13); val9 = tmp; tmp = std::min(val10,val14); val14 = std::max(val10,val14); + val10 = tmp; tmp = std::min(val11,val15); val15 = std::max(val11,val15); val11 = tmp; + tmp = std::min(val16,val20); val20 = std::max(val16,val20); val16 = tmp; tmp = std::min(val17,val21); + val21 = std::max(val17,val21); val17 = tmp; tmp = std::min(val18,val22); val22 = std::max(val18,val22); + val18 = tmp; tmp = std::min(val19,val23); val23 = std::max(val19,val23); val19 = tmp; + tmp = std::min(val24,val28); val28 = std::max(val24,val28); val24 = tmp; tmp = std::min(val25,val29); + val29 = std::max(val25,val29); val25 = tmp; tmp = std::min(val26,val30); val30 = std::max(val26,val30); + val26 = tmp; tmp = std::min(val27,val31); val31 = std::max(val27,val31); val27 = tmp; + tmp = std::min(val32,val36); val36 = std::max(val32,val36); val32 = tmp; tmp = std::min(val33,val37); + val37 = std::max(val33,val37); val33 = tmp; tmp = std::min(val34,val38); val38 = std::max(val34,val38); + val34 = tmp; tmp = std::min(val35,val39); val39 = std::max(val35,val39); val35 = tmp; + tmp = std::min(val40,val44); val44 = std::max(val40,val44); val40 = tmp; tmp = std::min(val41,val45); + val45 = std::max(val41,val45); val41 = tmp; tmp = std::min(val42,val46); val46 = std::max(val42,val46); + val42 = tmp; tmp = std::min(val43,val47); val47 = std::max(val43,val47); val43 = tmp; + tmp = std::min(val4,val32); val32 = std::max(val4,val32); val4 = tmp; tmp = std::min(val5,val33); + val33 = std::max(val5,val33); val5 = tmp; tmp = std::min(val6,val34); val34 = std::max(val6,val34); + val6 = tmp; tmp = std::min(val7,val35); val35 = std::max(val7,val35); val7 = tmp; + tmp = std::min(val12,val40); val40 = std::max(val12,val40); val12 = tmp; tmp = std::min(val13,val41); + val41 = std::max(val13,val41); val13 = tmp; tmp = std::min(val14,val42); val42 = std::max(val14,val42); + val14 = tmp; tmp = std::min(val15,val43); val43 = std::max(val15,val43); val15 = tmp; + tmp = std::min(val20,val48); val48 = std::max(val20,val48); val20 = tmp; tmp = std::min(val4,val16); + val16 = std::max(val4,val16); val4 = tmp; tmp = std::min(val5,val17); val17 = std::max(val5,val17); + val5 = tmp; tmp = std::min(val6,val18); val18 = std::max(val6,val18); val6 = tmp; + tmp = std::min(val7,val19); val19 = std::max(val7,val19); val7 = tmp; tmp = std::min(val12,val24); + val24 = std::max(val12,val24); val12 = tmp; tmp = std::min(val13,val25); val25 = std::max(val13,val25); + val13 = tmp; tmp = std::min(val14,val26); val26 = std::max(val14,val26); val14 = tmp; + tmp = std::min(val15,val27); val27 = std::max(val15,val27); val15 = tmp; tmp = std::min(val20,val32); + val32 = std::max(val20,val32); val20 = tmp; tmp = std::min(val21,val33); val33 = std::max(val21,val33); + val21 = tmp; tmp = std::min(val22,val34); val34 = std::max(val22,val34); val22 = tmp; + tmp = std::min(val23,val35); val35 = std::max(val23,val35); val23 = tmp; tmp = std::min(val28,val40); + val40 = std::max(val28,val40); val28 = tmp; tmp = std::min(val29,val41); val41 = std::max(val29,val41); + val29 = tmp; tmp = std::min(val30,val42); val42 = std::max(val30,val42); val30 = tmp; + tmp = std::min(val31,val43); val43 = std::max(val31,val43); val31 = tmp; tmp = std::min(val36,val48); + val48 = std::max(val36,val48); val36 = tmp; tmp = std::min(val4,val8); val8 = std::max(val4,val8); + val4 = tmp; tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val7,val11); val11 = std::max(val7,val11); val7 = tmp; + tmp = std::min(val12,val16); val16 = std::max(val12,val16); val12 = tmp; tmp = std::min(val13,val17); + val17 = std::max(val13,val17); val13 = tmp; tmp = std::min(val14,val18); val18 = std::max(val14,val18); + val14 = tmp; tmp = std::min(val15,val19); val19 = std::max(val15,val19); val15 = tmp; + tmp = std::min(val20,val24); val24 = std::max(val20,val24); val20 = tmp; tmp = std::min(val21,val25); + val25 = std::max(val21,val25); val21 = tmp; tmp = std::min(val22,val26); val26 = std::max(val22,val26); + val22 = tmp; tmp = std::min(val23,val27); val27 = std::max(val23,val27); val23 = tmp; + tmp = std::min(val28,val32); val32 = std::max(val28,val32); val28 = tmp; tmp = std::min(val29,val33); + val33 = std::max(val29,val33); val29 = tmp; tmp = std::min(val30,val34); val34 = std::max(val30,val34); + val30 = tmp; tmp = std::min(val31,val35); val35 = std::max(val31,val35); val31 = tmp; + tmp = std::min(val36,val40); val40 = std::max(val36,val40); val36 = tmp; tmp = std::min(val37,val41); + val41 = std::max(val37,val41); val37 = tmp; tmp = std::min(val38,val42); val42 = std::max(val38,val42); + val38 = tmp; tmp = std::min(val39,val43); val43 = std::max(val39,val43); val39 = tmp; + tmp = std::min(val44,val48); val48 = std::max(val44,val48); val44 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val1,val3); val3 = std::max(val1,val3); val1 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val5,val7); + val7 = std::max(val5,val7); val5 = tmp; tmp = std::min(val8,val10); val10 = std::max(val8,val10); val8 = tmp; + tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; tmp = std::min(val12,val14); + val14 = std::max(val12,val14); val12 = tmp; tmp = std::min(val13,val15); val15 = std::max(val13,val15); + val13 = tmp; tmp = std::min(val16,val18); val18 = std::max(val16,val18); val16 = tmp; + tmp = std::min(val17,val19); val19 = std::max(val17,val19); val17 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = tmp; tmp = std::min(val21,val23); val23 = std::max(val21,val23); + val21 = tmp; tmp = std::min(val24,val26); val26 = std::max(val24,val26); val24 = tmp; + tmp = std::min(val25,val27); val27 = std::max(val25,val27); val25 = tmp; tmp = std::min(val28,val30); + val30 = std::max(val28,val30); val28 = tmp; tmp = std::min(val29,val31); val31 = std::max(val29,val31); + val29 = tmp; tmp = std::min(val32,val34); val34 = std::max(val32,val34); val32 = tmp; + tmp = std::min(val33,val35); val35 = std::max(val33,val35); val33 = tmp; tmp = std::min(val36,val38); + val38 = std::max(val36,val38); val36 = tmp; tmp = std::min(val37,val39); val39 = std::max(val37,val39); + val37 = tmp; tmp = std::min(val40,val42); val42 = std::max(val40,val42); val40 = tmp; + tmp = std::min(val41,val43); val43 = std::max(val41,val43); val41 = tmp; tmp = std::min(val44,val46); + val46 = std::max(val44,val46); val44 = tmp; tmp = std::min(val45,val47); val47 = std::max(val45,val47); + val45 = tmp; tmp = std::min(val2,val32); val32 = std::max(val2,val32); val2 = tmp; tmp = std::min(val3,val33); + val33 = std::max(val3,val33); val3 = tmp; tmp = std::min(val6,val36); val36 = std::max(val6,val36); val6 = tmp; + tmp = std::min(val7,val37); val37 = std::max(val7,val37); val7 = tmp; tmp = std::min(val10,val40); + val40 = std::max(val10,val40); val10 = tmp; tmp = std::min(val11,val41); val41 = std::max(val11,val41); + val11 = tmp; tmp = std::min(val14,val44); val44 = std::max(val14,val44); val14 = tmp; + tmp = std::min(val15,val45); val45 = std::max(val15,val45); val15 = tmp; tmp = std::min(val18,val48); + val48 = std::max(val18,val48); val18 = tmp; tmp = std::min(val2,val16); val16 = std::max(val2,val16); + val2 = tmp; tmp = std::min(val3,val17); val17 = std::max(val3,val17); val3 = tmp; + tmp = std::min(val6,val20); val20 = std::max(val6,val20); val6 = tmp; tmp = std::min(val7,val21); + val21 = std::max(val7,val21); val7 = tmp; tmp = std::min(val10,val24); val24 = std::max(val10,val24); + val10 = tmp; tmp = std::min(val11,val25); val25 = std::max(val11,val25); val11 = tmp; + tmp = std::min(val14,val28); val28 = std::max(val14,val28); val14 = tmp; tmp = std::min(val15,val29); + val29 = std::max(val15,val29); val15 = tmp; tmp = std::min(val18,val32); val32 = std::max(val18,val32); + val18 = tmp; tmp = std::min(val19,val33); val33 = std::max(val19,val33); val19 = tmp; + tmp = std::min(val22,val36); val36 = std::max(val22,val36); val22 = tmp; tmp = std::min(val23,val37); + val37 = std::max(val23,val37); val23 = tmp; tmp = std::min(val26,val40); val40 = std::max(val26,val40); + val26 = tmp; tmp = std::min(val27,val41); val41 = std::max(val27,val41); val27 = tmp; + tmp = std::min(val30,val44); val44 = std::max(val30,val44); val30 = tmp; tmp = std::min(val31,val45); + val45 = std::max(val31,val45); val31 = tmp; tmp = std::min(val34,val48); val48 = std::max(val34,val48); + val34 = tmp; tmp = std::min(val2,val8); val8 = std::max(val2,val8); val2 = tmp; tmp = std::min(val3,val9); + val9 = std::max(val3,val9); val3 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val13); val13 = std::max(val7,val13); val7 = tmp; tmp = std::min(val10,val16); + val16 = std::max(val10,val16); val10 = tmp; tmp = std::min(val11,val17); val17 = std::max(val11,val17); + val11 = tmp; tmp = std::min(val14,val20); val20 = std::max(val14,val20); val14 = tmp; + tmp = std::min(val15,val21); val21 = std::max(val15,val21); val15 = tmp; tmp = std::min(val18,val24); + val24 = std::max(val18,val24); val18 = tmp; tmp = std::min(val19,val25); val25 = std::max(val19,val25); + val19 = tmp; tmp = std::min(val22,val28); val28 = std::max(val22,val28); val22 = tmp; + tmp = std::min(val23,val29); val29 = std::max(val23,val29); val23 = tmp; tmp = std::min(val26,val32); + val32 = std::max(val26,val32); val26 = tmp; tmp = std::min(val27,val33); val33 = std::max(val27,val33); + val27 = tmp; tmp = std::min(val30,val36); val36 = std::max(val30,val36); val30 = tmp; + tmp = std::min(val31,val37); val37 = std::max(val31,val37); val31 = tmp; tmp = std::min(val34,val40); + val40 = std::max(val34,val40); val34 = tmp; tmp = std::min(val35,val41); val41 = std::max(val35,val41); + val35 = tmp; tmp = std::min(val38,val44); val44 = std::max(val38,val44); val38 = tmp; + tmp = std::min(val39,val45); val45 = std::max(val39,val45); val39 = tmp; tmp = std::min(val42,val48); + val48 = std::max(val42,val48); val42 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); + val2 = tmp; tmp = std::min(val3,val5); val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val6,val8); + val8 = std::max(val6,val8); val6 = tmp; tmp = std::min(val7,val9); val9 = std::max(val7,val9); val7 = tmp; + tmp = std::min(val10,val12); val12 = std::max(val10,val12); val10 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = tmp; tmp = std::min(val14,val16); val16 = std::max(val14,val16); + val14 = tmp; tmp = std::min(val15,val17); val17 = std::max(val15,val17); val15 = tmp; + tmp = std::min(val18,val20); val20 = std::max(val18,val20); val18 = tmp; tmp = std::min(val19,val21); + val21 = std::max(val19,val21); val19 = tmp; tmp = std::min(val22,val24); val24 = std::max(val22,val24); + val22 = tmp; tmp = std::min(val23,val25); val25 = std::max(val23,val25); val23 = tmp; + tmp = std::min(val26,val28); val28 = std::max(val26,val28); val26 = tmp; tmp = std::min(val27,val29); + val29 = std::max(val27,val29); val27 = tmp; tmp = std::min(val30,val32); val32 = std::max(val30,val32); + val30 = tmp; tmp = std::min(val31,val33); val33 = std::max(val31,val33); val31 = tmp; + tmp = std::min(val34,val36); val36 = std::max(val34,val36); val34 = tmp; tmp = std::min(val35,val37); + val37 = std::max(val35,val37); val35 = tmp; tmp = std::min(val38,val40); val40 = std::max(val38,val40); + val38 = tmp; tmp = std::min(val39,val41); val41 = std::max(val39,val41); val39 = tmp; + tmp = std::min(val42,val44); val44 = std::max(val42,val44); val42 = tmp; tmp = std::min(val43,val45); + val45 = std::max(val43,val45); val43 = tmp; tmp = std::min(val46,val48); val48 = std::max(val46,val48); + val46 = tmp; val1 = std::max(val0,val1); val3 = std::max(val2,val3); val5 = std::max(val4,val5); + val7 = std::max(val6,val7); val9 = std::max(val8,val9); val11 = std::max(val10,val11); + val13 = std::max(val12,val13); val15 = std::max(val14,val15); val17 = std::max(val16,val17); + val19 = std::max(val18,val19); val21 = std::max(val20,val21); val23 = std::max(val22,val23); + val24 = std::min(val24,val25); val26 = std::min(val26,val27); val28 = std::min(val28,val29); + val30 = std::min(val30,val31); val32 = std::min(val32,val33); val34 = std::min(val34,val35); + val36 = std::min(val36,val37); val38 = std::min(val38,val39); val40 = std::min(val40,val41); + val42 = std::min(val42,val43); val44 = std::min(val44,val45); val46 = std::min(val46,val47); + val32 = std::max(val1,val32); val34 = std::max(val3,val34); val36 = std::max(val5,val36); + val38 = std::max(val7,val38); val9 = std::min(val9,val40); val11 = std::min(val11,val42); + val13 = std::min(val13,val44); val15 = std::min(val15,val46); val17 = std::min(val17,val48); + val24 = std::max(val9,val24); val26 = std::max(val11,val26); val28 = std::max(val13,val28); + val30 = std::max(val15,val30); val17 = std::min(val17,val32); val19 = std::min(val19,val34); + val21 = std::min(val21,val36); val23 = std::min(val23,val38); val24 = std::max(val17,val24); + val26 = std::max(val19,val26); val21 = std::min(val21,val28); val23 = std::min(val23,val30); + val24 = std::max(val21,val24); val23 = std::min(val23,val26); + return std::max(val23,val24); + } + + //! Return sqrt(x^2 + y^2). + template + inline T hypot(const T x, const T y) { + return std::sqrt(x*x + y*y); + } + + template + inline T hypot(const T x, const T y, const T z) { + return std::sqrt(x*x + y*y + z*z); + } + + template + inline T _hypot(const T x, const T y) { // Slower but more precise version + T nx = cimg::abs(x), ny = cimg::abs(y), t; + if (nx0) { t/=nx; return nx*std::sqrt(1 + t*t); } + return 0; + } + + //! Return the factorial of n + inline double factorial(const int n) { + if (n<0) return cimg::type::nan(); + if (n<2) return 1; + double res = 2; + for (int i = 3; i<=n; ++i) res*=i; + return res; + } + + //! Return the number of permutations of k objects in a set of n objects. + inline double permutations(const int k, const int n, const bool with_order) { + if (n<0 || k<0) return cimg::type::nan(); + if (k>n) return 0; + double res = 1; + for (int i = n; i>=n - k + 1; --i) res*=i; + return with_order?res:res/cimg::factorial(k); + } + + inline double _fibonacci(int exp) { + double + base = (1 + std::sqrt(5.))/2, + result = 1/std::sqrt(5.); + while (exp) { + if (exp&1) result*=base; + exp>>=1; + base*=base; + } + return result; + } + + //! Calculate fibonacci number. + // (Precise up to n = 78, less precise for n>78). + inline double fibonacci(const int n) { + if (n<0) return cimg::type::nan(); + if (n<3) return 1; + if (n<11) { + cimg_uint64 fn1 = 1, fn2 = 1, fn = 0; + for (int i = 3; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + if (n<75) // precise up to n = 74, faster than the integer calculation above for n>10 + return (double)((cimg_uint64)(_fibonacci(n) + 0.5)); + + if (n<94) { // precise up to n = 78, less precise for n>78 up to n = 93, overflows for n>93 + cimg_uint64 + fn1 = ((cimg_uint64)303836)<<32 | 3861581201UL, // 1304969544928657ULL (avoid C++98 warning with ULL) + fn2 = ((cimg_uint64)187781)<<32 | 2279239217UL, // 806515533049393ULL + fn = 0; + for (int i = 75; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + return _fibonacci(n); // Not precise, but better than the wrong overflowing calculation + } + + //! Calculate greatest common divisor. + inline long gcd(long a, long b) { + while (a) { const long c = a; a = b%a; b = c; } + return b; + } + + //! Convert character to lower case. + inline char lowercase(const char x) { + return (char)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + inline double lowercase(const double x) { + return (double)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + + //! Convert C-string to lower case. + inline void lowercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = lowercase(*ptr); + } + + //! Convert character to upper case. + inline char uppercase(const char x) { + return (char)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + inline double uppercase(const double x) { + return (double)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + //! Convert C-string to upper case. + inline void uppercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = uppercase(*ptr); + } + + //! Return \c true if input character is blank (space, tab, or non-printable character). + inline bool is_blank(const char c) { + return c>=0 && (unsigned char)c<=' '; + } + + //! Read value in a C-string. + /** + \param str C-string containing the float value to read. + \return Read value. + \note Same as std::atof() extended to manage the retrieval of fractions from C-strings, + as in "1/2". + **/ + inline double atof(const char *const str) { + double x = 0, y = 1; + return str && cimg_sscanf(str,"%lf/%lf",&x,&y)>0?x/y:0; + } + + //! Compare the first \p l characters of two C-strings, ignoring the case. + /** + \param str1 C-string. + \param str2 C-string. + \param l Number of characters to compare. + \return \c 0 if the two strings are equal, something else otherwise. + \note This function has to be defined since it is not provided by all C++-compilers (not ANSI). + **/ + inline int strncasecmp(const char *const str1, const char *const str2, const int l) { + if (!l) return 0; + if (!str1) return str2?-1:0; + const char *nstr1 = str1, *nstr2 = str2; + int k, diff = 0; for (k = 0; kp && str[q]==delimiter; ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Remove white spaces on the start and/or end of a C-string. + inline bool strpare(char *const str, const bool is_symmetric, const bool is_iterative) { + if (!str) return false; + const int l = (int)std::strlen(str); + int p, q; + if (is_symmetric) for (p = 0, q = l - 1; pp && is_blank(str[q]); ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Replace reserved characters (for Windows filename) by another character. + /** + \param[in,out] str C-string to work with (modified at output). + \param[in] c Replacement character. + **/ + inline void strwindows_reserved(char *const str, const char c='_') { + for (char *s = str; *s; ++s) { + const char i = *s; + if (i=='<' || i=='>' || i==':' || i=='\"' || i=='/' || i=='\\' || i=='|' || i=='?' || i=='*') *s = c; + } + } + + //! Replace escape sequences in C-strings by character values. + /** + \param[in,out] str C-string to work with (modified at output). + **/ + inline void strunescape(char *const str) { +#define cimg_strunescape(ci,co) case ci : *nd = co; ++ns; break; + + unsigned char val = 0; + for (char *ns = str, *nd = str; *ns || (bool)(*nd = 0); ++nd) if (*ns=='\\') switch (*(++ns)) { + cimg_strunescape('a','\a'); + cimg_strunescape('b','\b'); + cimg_strunescape('e',0x1B); + cimg_strunescape('f','\f'); + cimg_strunescape('n','\n'); + cimg_strunescape('r','\r'); + cimg_strunescape('t','\t'); + cimg_strunescape('v','\v'); + cimg_strunescape('\\','\\'); + cimg_strunescape('\'','\''); + cimg_strunescape('\"','\"'); + cimg_strunescape('\?','\?'); + case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : + val = (unsigned char)(*(ns++) - '0'); + if (*ns>='0' && *ns<='7') (val<<=3)|=*(ns++) - '0'; + if (*ns>='0' && *ns<='7') (val<<=3)|=*(ns++) - '0'; + *nd = (char)val; + break; + case 'x' : { + char c = lowercase(*(++ns)); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + val = (unsigned char)(c<='9'?c - '0':c - 'a' + 10); + c = lowercase(*(++ns)); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + (val<<=4)|=(c<='9'?c - '0':c - 'a' + 10); + ++ns; + } + *nd = (char)val; + } else *nd = c; + } break; + case 'u' : { // UTF-8 BMP + char c1, c2, c3, c4; + if ((((c1 = lowercase(ns[1]))>='0' && c1<='9') || (c1>='a' && c1<='f')) && + (((c2 = lowercase(ns[2]))>='0' && c2<='9') || (c2>='a' && c2<='f')) && + (((c3 = lowercase(ns[3]))>='0' && c3<='9') || (c3>='a' && c3<='f')) && + (((c4 = lowercase(ns[4]))>='0' && c4<='9') || (c4>='a' && c4<='f'))) { + c1 = (c1<='9'?c1 - '0':c1 - 'a' + 10); + c2 = (c2<='9'?c2 - '0':c2 - 'a' + 10); + c3 = (c3<='9'?c3 - '0':c3 - 'a' + 10); + c4 = (c4<='9'?c4 - '0':c4 - 'a' + 10); + const unsigned int ival = + ((unsigned int)c1<<12) | ((unsigned int)c2<<8) | ((unsigned int)c3<<4) | c4; + if (ival<=0x007f) *nd = (char)ival; + else if (ival<=0x07ff) { + *(nd++) = (char)((ival>>6)|0xc0); + *nd = (char)((ival&0x3f)|0x80); + } else { + *(nd++) = (char)((ival>>12)|0xe0); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } + ns+=5; + } else *nd = *(ns++); + } break; + case 'U' : { // UTF-8 astral planes + char c1, c2, c3, c4, c5, c6, c7, c8; + if ((((c1 = lowercase(ns[1]))>='0' && c1<='9') || (c1>='a' && c1<='f')) && + (((c2 = lowercase(ns[2]))>='0' && c2<='9') || (c2>='a' && c2<='f')) && + (((c3 = lowercase(ns[3]))>='0' && c3<='9') || (c3>='a' && c3<='f')) && + (((c4 = lowercase(ns[4]))>='0' && c4<='9') || (c4>='a' && c4<='f')) && + (((c5 = lowercase(ns[5]))>='0' && c5<='9') || (c5>='a' && c5<='f')) && + (((c6 = lowercase(ns[6]))>='0' && c6<='9') || (c6>='a' && c6<='f')) && + (((c7 = lowercase(ns[7]))>='0' && c7<='9') || (c7>='a' && c7<='f')) && + (((c8 = lowercase(ns[8]))>='0' && c8<='9') || (c8>='a' && c8<='f'))) { + c1 = (c1<='9'?c1 - '0':c1 - 'a' + 10); + c2 = (c2<='9'?c2 - '0':c2 - 'a' + 10); + c3 = (c3<='9'?c3 - '0':c3 - 'a' + 10); + c4 = (c4<='9'?c4 - '0':c4 - 'a' + 10); + c5 = (c5<='9'?c5 - '0':c5 - 'a' + 10); + c6 = (c6<='9'?c6 - '0':c6 - 'a' + 10); + c7 = (c7<='9'?c7 - '0':c7 - 'a' + 10); + c8 = (c8<='9'?c8 - '0':c8 - 'a' + 10); + const unsigned int ival = + ((unsigned int)c1<<28) | ((unsigned int)c2<<24) | ((unsigned int)c3<<20) | ((unsigned int)c4<<16) | + ((unsigned int)c5<<12) | ((unsigned int)c6<<8) | ((unsigned int)c7<<4) | (unsigned int)c8; + if (ival<=0x007f) *nd = (char)ival; + else if (ival<=0x07ff) { + *(nd++) = (char)((ival>>6)|0xc0); + *nd = (char)((ival&0x3f)|0x80); + } else if (ival<=0xffff) { + *(nd++) = (char)((ival>>12)|0xe0); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } else { + *(nd++) = (char)((ival>>18)|0xf0); + *(nd++) = (char)(((ival>>12)&0x3f)|0x80); + *(nd++) = (char)(((ival>>6)&0x3f)|0x80); + *nd = (char)((ival&0x3f)|0x80); + } + ns+=9; + } else *nd = *(ns++); + } break; + default : if (*ns) *nd = *(ns++); + } + else *nd = *(ns++); + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size); + + // Return string that identifies the running OS. + inline const char *stros() { +#if defined(linux) || defined(__linux) || defined(__linux__) + static const char *const str = "Linux"; +#elif defined(sun) || defined(__sun) + static const char *const str = "Sun OS"; +#elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__) + static const char *const str = "BSD"; +#elif defined(sgi) || defined(__sgi) + static const char *const str = "Irix"; +#elif defined(__MACOSX__) || defined(__APPLE__) + static const char *const str = "Mac OS"; +#elif defined(unix) || defined(__unix) || defined(__unix__) + static const char *const str = "Generic Unix"; +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ + defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + static const char *const str = "Windows"; +#else + const char + *const _str1 = std::getenv("OSTYPE"), + *const _str2 = _str1?_str1:std::getenv("OS"), + *const str = _str2?_str2:"Unknown OS"; +#endif + return str; + } + + //! Return the basename of a filename. + inline const char* basename(const char *const s, const char separator=cimg_file_separator) { + const char *p = 0, *np = s; + while (np>=s && (p=np)) np = std::strchr(np,separator) + 1; + return p; + } + + // Return a random filename. + inline const char* filenamerand() { + cimg::mutex(6); + static char randomid[9]; + for (unsigned int k = 0; k<8; ++k) { + const int v = (int)cimg::rand(65535)%3; + randomid[k] = (char)(v==0?('0' + ((int)cimg::rand(65535)%10)): + (v==1?('a' + ((int)cimg::rand(65535)%26)): + ('A' + ((int)cimg::rand(65535)%26)))); + } + cimg::mutex(6,0); + return randomid; + } + + // Convert filename as a Windows-style filename (short path name). + inline void winformat_string(char *const str) { + if (str && *str) { +#if cimg_OS==2 + char *const nstr = new char[MAX_PATH]; + if (GetShortPathNameA(str,nstr,MAX_PATH)) std::strcpy(str,nstr); + delete[] nstr; +#endif + } + } + + // Open a file (similar to std:: fopen(), but with wide character support on Windows). + inline std::FILE *std_fopen(const char *const path, const char *const mode); + + + //! Open a file. + /** + \param path Path of the filename to open. + \param mode C-string describing the opening mode. + \return Opened file. + \note Same as std::fopen() but throw a \c CImgIOException when + the specified file cannot be opened, instead of returning \c 0. + **/ + inline std::FILE *fopen(const char *const path, const char *const mode) { + if (!path) + throw CImgArgumentException("cimg::fopen(): Specified file path is (null)."); + if (!mode) + throw CImgArgumentException("cimg::fopen(): File '%s', specified mode is (null).", + path); + std::FILE *res = 0; + if (*path=='-' && (!path[1] || path[1]=='.')) { + res = (*mode=='r')?cimg::_stdin():cimg::_stdout(); +#if cimg_OS==2 + if (*mode && mode[1]=='b') { // Force stdin/stdout to be in binary mode +#ifdef __BORLANDC__ + if (setmode(_fileno(res),0x8000)==-1) res = 0; +#else + if (_setmode(_fileno(res),0x8000)==-1) res = 0; +#endif + } +#endif + } else res = cimg::std_fopen(path,mode); + if (!res) throw CImgIOException("cimg::fopen(): Failed to open file '%s' with mode '%s'.", + path,mode); + return res; + } + + //! Close a file. + /** + \param file File to close. + \return \c 0 if file has been closed properly, something else otherwise. + \note Same as std::fclose() but display a warning message if + the file has not been closed properly. + **/ + inline int fclose(std::FILE *file) { + if (!file) { warn("cimg::fclose(): Specified file is (null)."); return 0; } + if (file==cimg::_stdin(false) || file==cimg::_stdout(false)) return 0; + const int errn = std::fclose(file); + if (errn!=0) warn("cimg::fclose(): Error code %d returned during file closing.", + errn); + return errn; + } + + //! Version of 'fseek()' that supports >=64bits offsets everywhere (for Windows). + inline int fseek(FILE *stream, cimg_long offset, int origin) { +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + return _fseeki64(stream,(__int64)offset,origin); +#else + return std::fseek(stream,offset,origin); +#endif + } + + //! Version of 'ftell()' that supports >=64bits offsets everywhere (for Windows). + inline cimg_long ftell(FILE *stream) { +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + return (cimg_long)_ftelli64(stream); +#else + return (cimg_long)std::ftell(stream); +#endif + } + + // Get the file or directory attributes with support for UTF-8 paths (Windows only). +#if cimg_OS==2 + inline DWORD win_getfileattributes(const char *const path); +#endif + + //! Check if a path is a directory. + /** + \param path Specified path to test. + **/ + inline bool is_directory(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==1 + struct stat st_buf; + return (!stat(path,&st_buf) && S_ISDIR(st_buf.st_mode)); +#elif cimg_OS==2 + const DWORD res = win_getfileattributes(path); + return res!=INVALID_FILE_ATTRIBUTES && (res&FILE_ATTRIBUTE_DIRECTORY); +#else + return false; +#endif + } + + //! Check if a path is a file. + /** + \param path Specified path to test. + **/ + inline bool is_file(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==2 + const DWORD res = cimg::win_getfileattributes(path); + return res!=INVALID_FILE_ATTRIBUTES && !(res&FILE_ATTRIBUTE_DIRECTORY); +#else + std::FILE *const file = cimg::std_fopen(path,"rb"); + if (!file) return false; + cimg::fclose(file); + return !is_directory(path); +#endif + } + + //! Get file size. + /** + \param filename Specified filename to get size from. + \return File size or '-1' if file does not exist. + **/ + inline cimg_int64 fsize(const char *const filename) { + std::FILE *const file = cimg::std_fopen(filename,"rb"); + if (!file) return (cimg_int64)-1; + std::fseek(file,0,SEEK_END); + const cimg_int64 siz = (cimg_int64)std::ftell(file); + cimg::fclose(file); + return siz; + } + + //! Get last write time of a given file or directory (multiple-attributes version). + /** + \param path Specified path to get attributes from. + \param[in,out] attr Type of requested time attributes. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second } + Replaced by read attributes after return (or -1 if an error occurred). + \param nb_attr Number of attributes to read/write. + \return Latest read attribute. + **/ + template + inline int fdate(const char *const path, T *attr, const unsigned int nb_attr) { +#define _cimg_fdate_err() for (unsigned int i = 0; i + inline int date(T *attr, const unsigned int nb_attr) { + int res = -1; + cimg::mutex(6); +#if cimg_OS==2 + SYSTEMTIME st; + GetLocalTime(&st); + for (unsigned int i = 0; itm_year + 1900: + attr[i]==1?st->tm_mon + 1: + attr[i]==2?st->tm_mday: + attr[i]==3?st->tm_wday: + attr[i]==4?st->tm_hour: + attr[i]==5?st->tm_min: + attr[i]==6?st->tm_sec: + attr[i]==7?_st.tv_usec/1000:-1); + attr[i] = (T)res; + } +#endif + cimg::mutex(6,0); + return res; + } + + //! Get current local time (single-attribute version). + /** + \param attr Type of requested time attribute. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second | + 7=millisecond } + \return Specified attribute or -1 if an error occurred. + **/ + inline int date(unsigned int attr) { + int out = (int)attr; + return date(&out,1); + } + + // Get/set path to the \c curl binary. + inline const char *curl_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c dcraw binary. + inline const char *dcraw_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the custom's \c custom binary. + inline const char *custom_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the GraphicsMagick's \c gm binary. + inline const char* graphicsmagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gunzip binary. + inline const char *gunzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gzip binary. + inline const char *gzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the ImageMagick's \c convert binary. + inline const char* imagemagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the Medcon's \c medcon binary. + inline const char* medcon_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to store temporary files. + inline const char* temporary_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c wget binary. + inline const char *wget_path(const char *const user_path=0, const bool reinit_path=false); + + //! Split filename into two C-strings \c body and \c extension. + /** + filename and body must not overlap! + **/ + inline const char *split_filename(const char *const filename, char *const body=0) { + if (!filename) { if (body) *body = 0; return ""; } + const char * p = std::strrchr(filename,'.'); + if (!p || std::strchr(p,'/') || std::strchr(p,'\\')) { // No extension. + if (body) std::strcpy(body,filename); + return filename + std::strlen(filename); + } + const unsigned int l = (unsigned int)(p - filename); + if (body) { if (l) std::memcpy(body,filename,l); body[l] = 0; } + return p + 1; + } + + // Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str); + + //! Read data from file. + /** + \param[out] ptr Pointer to memory buffer that will contain the binary data read from file. + \param nmemb Number of elements to read. + \param stream File to read data from. + \return Number of read elements. + \note Same as std::fread() but may display warning message if all elements could not be read. + **/ + template + inline size_t fread(T *const ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fread(): Invalid reading request of %u %s%s from file %p to buffer %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",stream,ptr); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0; + do { + l_to_read = (to_read*sizeof(T))0); + if (to_read>0) + warn("cimg::fread(): Only %lu/%lu elements could be read from file.", + (unsigned long)al_read,(unsigned long)nmemb); + return al_read; + } + + //! Write data to file. + /** + \param ptr Pointer to memory buffer containing the binary data to write on file. + \param nmemb Number of elements to write. + \param[out] stream File to write data on. + \return Number of written elements. + \note Similar to std::fwrite but may display warning messages if all elements could not be written. + **/ + template + inline size_t fwrite(const T *ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",ptr,stream); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0; + do { + l_to_write = (to_write*sizeof(T))0); + if (to_write>0) + warn("cimg::fwrite(): Only %lu/%lu elements could be written in file.", + (unsigned long)al_write,(unsigned long)nmemb); + return al_write; + } + + //! Create an empty file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + **/ + inline void fempty(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::fempty(): Specified filename is (null)."); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (!file) cimg::fclose(nfile); + } + + // Try to guess format from an image file. + inline const char *ftype(std::FILE *const file, const char *const filename); + + // Get or set load from network mode (can be { 0=disabled | 1=enabled }). + inline bool& network_mode(const bool value, const bool is_set) { + static bool mode = true; + if (is_set) { cimg::mutex(0); mode = value; cimg::mutex(0,0); } + return mode; + } + + inline bool& network_mode() { + return network_mode(false,false); + } + + // Load file from network as a local temporary file. + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout=0, const bool try_fallback=false, + const char *const referer=0); + + //! Return options specified on the command line. + inline const char* option(const char *const name, const int argc, const char *const *const argv, + const char *const _default, const char *const usage, const bool reset_static) { + static bool first = true, visu = false; + if (reset_static) { first = true; return 0; } + const char *res = 0; + if (first) { + first = false; + visu = cimg::option("-h",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("-help",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("--help",argc,argv,(char*)0,(char*)0,false)!=0; + } + if (!name && visu) { + if (usage) { + std::fprintf(cimg::output(),"\n %s%s%s",cimg::t_red,cimg::basename(argv[0]),cimg::t_normal); + std::fprintf(cimg::output(),": %s",usage); + std::fprintf(cimg::output()," (%s, %s)\n\n",cimg_date,cimg_time); + } + if (_default) std::fprintf(cimg::output(),"%s\n",_default); + } + if (name) { + if (argc>0) { + int k = 0; + while (k Operating System: %s%-13s%s %s('cimg_OS'=%d)%s\n", + cimg::t_bold, + cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknown"), + cimg::t_normal,cimg::t_green, + cimg_OS, + cimg::t_normal); + + std::fprintf(cimg::output()," > CPU endianness: %s%s Endian%s\n", + cimg::t_bold, + cimg::endianness()?"Big":"Little", + cimg::t_normal); + + std::fprintf(cimg::output()," > Verbosity mode: %s%-13s%s %s('cimg_verbosity'=%d)%s\n", + cimg::t_bold, + cimg_verbosity==0?"Quiet": + cimg_verbosity==1?"Console": + cimg_verbosity==2?"Dialog": + cimg_verbosity==3?"Console+Warnings":"Dialog+Warnings", + cimg::t_normal,cimg::t_green, + cimg_verbosity, + cimg::t_normal); + + std::fprintf(cimg::output()," > Stricts warnings: %s%-13s%s %s('cimg_strict_warnings' %s)%s\n", + cimg::t_bold, +#ifdef cimg_strict_warnings + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Support for C++11: %s%-13s%s %s('cimg_use_cpp11'=%d)%s\n", + cimg::t_bold, + cimg_use_cpp11?"Yes":"No", + cimg::t_normal,cimg::t_green, + (int)cimg_use_cpp11, + cimg::t_normal); + + std::fprintf(cimg::output()," > Using VT100 messages: %s%-13s%s %s('cimg_use_vt100' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_vt100 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Display type: %s%-13s%s %s('cimg_display'=%d)%s\n", + cimg::t_bold, + cimg_display==0?"No display":cimg_display==1?"X11":cimg_display==2?"Windows GDI":"Unknown", + cimg::t_normal,cimg::t_green, + (int)cimg_display, + cimg::t_normal); + +#if cimg_display==1 + std::fprintf(cimg::output()," > Using XShm for X11: %s%-13s%s %s('cimg_use_xshm' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xshm + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using XRand for X11: %s%-13s%s %s('cimg_use_xrandr' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xrandr + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); +#endif + std::fprintf(cimg::output()," > Using OpenMP: %s%-13s%s %s('cimg_use_openmp' %s)%s\n", + cimg::t_bold, +#if cimg_use_openmp!=0 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using PNG library: %s%-13s%s %s('cimg_use_png' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_png + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using JPEG library: %s%-13s%s %s('cimg_use_jpeg' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_jpeg + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using TIFF library: %s%-13s%s %s('cimg_use_tiff' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_tiff + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using Magick++ library: %s%-13s%s %s('cimg_use_magick' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_magick + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using FFTW3 library: %s%-13s%s %s('cimg_use_fftw3' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_fftw3 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using LAPACK library: %s%-13s%s %s('cimg_use_lapack' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_lapack + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + char *const tmp = new char[1024]; + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::curl_path()); + std::fprintf(cimg::output()," > Path of 'curl': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::dcraw_path()); + std::fprintf(cimg::output()," > Path of 'dcraw': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::custom_path()); + std::fprintf(cimg::output()," > Path of 'custom': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::graphicsmagick_path()); + std::fprintf(cimg::output()," > Path of 'graphicsmagick': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::gunzip_path()); + std::fprintf(cimg::output()," > Path of 'gunzip': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::gzip_path()); + std::fprintf(cimg::output()," > Path of 'gzip': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::imagemagick_path()); + std::fprintf(cimg::output()," > Path of 'imagemagick': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::medcon_path()); + std::fprintf(cimg::output()," > Path of 'medcon': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::temporary_path()); + std::fprintf(cimg::output()," > Temporary path: %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::wget_path()); + std::fprintf(cimg::output()," > Path of 'wget': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + std::fprintf(cimg::output(),"\n"); + delete[] tmp; + } + + // Declare LAPACK function signatures if LAPACK support is enabled. +#ifdef cimg_use_lapack + template + inline void getrf(int &N, T *lapA, int *IPIV, int &INFO) { + dgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + inline void getrf(int &N, float *lapA, int *IPIV, int &INFO) { + sgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + template + inline void getri(int &N, T *lapA, int *IPIV, T* WORK, int &LWORK, int &INFO) { + dgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + inline void getri(int &N, float *lapA, int *IPIV, float* WORK, int &LWORK, int &INFO) { + sgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + template + inline void gesvd(char &JOB, int &M, int &N, T *lapA, int &MN, + T *lapS, T *lapU, T *lapV, T *WORK, int &LWORK, int &INFO) { + dgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + inline void gesvd(char &JOB, int &M, int &N, float *lapA, int &MN, + float *lapS, float *lapU, float *lapV, float *WORK, int &LWORK, int &INFO) { + sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + template + inline void getrs(char &TRANS, int &N, T *lapA, int *IPIV, T *lapB, int &INFO) { + int one = 1; + dgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + inline void getrs(char &TRANS, int &N, float *lapA, int *IPIV, float *lapB, int &INFO) { + int one = 1; + sgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + template + inline void syev(char &JOB, char &UPLO, int &N, T *lapA, T *lapW, T *WORK, int &LWORK, int &INFO) { + dsyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + inline void syev(char &JOB, char &UPLO, int &N, float *lapA, float *lapW, float *WORK, int &LWORK, int &INFO) { + ssyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + template + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, T* lapA, int &LDA, + T* lapB, int &LDB, T* WORK, int &LWORK, int &INFO) { + dgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, float* lapA, int &LDA, + float* lapB, int &LDB, float* WORK, int &LWORK, int &INFO) { + sgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + +#endif + + } // namespace cimg { ... + + /*------------------------------------------------ + # + # + # Definition of mathematical operators and + # external functions. + # + # + -------------------------------------------------*/ + +#define _cimg_create_operator(typ) \ + template \ + inline CImg::type> operator+(const typ val, const CImg& img) { \ + return img + val; \ + } \ + template \ + inline CImg::type> operator-(const typ val, const CImg& img) { \ + typedef typename cimg::superset::type Tt; \ + return CImg(img._width,img._height,img._depth,img._spectrum,val)-=img; \ + } \ + template \ + inline CImg::type> operator*(const typ val, const CImg& img) { \ + return img*val; \ + } \ + template \ + inline CImg::type> operator/(const typ val, const CImg& img) { \ + return val*img.get_invert(); \ + } \ + template \ + inline CImg::type> operator&(const typ val, const CImg& img) { \ + return img & val; \ + } \ + template \ + inline CImg::type> operator|(const typ val, const CImg& img) { \ + return img | val; \ + } \ + template \ + inline CImg::type> operator^(const typ val, const CImg& img) { \ + return img ^ val; \ + } \ + template \ + inline bool operator==(const typ val, const CImg& img) { \ + return img == val; \ + } \ + template \ + inline bool operator!=(const typ val, const CImg& img) { \ + return img != val; \ + } + + _cimg_create_operator(bool) + _cimg_create_operator(unsigned char) + _cimg_create_operator(char) + _cimg_create_operator(signed char) + _cimg_create_operator(unsigned short) + _cimg_create_operator(short) + _cimg_create_operator(unsigned int) + _cimg_create_operator(int) + _cimg_create_operator(cimg_uint64) + _cimg_create_operator(cimg_int64) + _cimg_create_operator(float) + _cimg_create_operator(double) + _cimg_create_operator(long double) + + template + inline CImg<_cimg_Tfloat> operator+(const char *const expression, const CImg& img) { + return img + expression; + } + + template + inline CImg<_cimg_Tfloat> operator-(const char *const expression, const CImg& img) { + return CImg<_cimg_Tfloat>(img,false).fill(expression,true)-=img; + } + + template + inline CImg<_cimg_Tfloat> operator*(const char *const expression, const CImg& img) { + return img*expression; + } + + template + inline CImg<_cimg_Tfloat> operator/(const char *const expression, const CImg& img) { + return expression*img.get_invert(); + } + + template + inline CImg operator&(const char *const expression, const CImg& img) { + return img & expression; + } + + template + inline CImg operator|(const char *const expression, const CImg& img) { + return img | expression; + } + + template + inline CImg operator^(const char *const expression, const CImg& img) { + return img ^ expression; + } + + template + inline bool operator==(const char *const expression, const CImg& img) { + return img==expression; + } + + template + inline bool operator!=(const char *const expression, const CImg& img) { + return img!=expression; + } + + template + inline CImg transpose(const CImg& instance) { + return instance.get_transpose(); + } + + template + inline CImg<_cimg_Tfloat> invert(const CImg& instance, const bool use_LU=true) { + return instance.get_invert(use_LU); + } + + template + inline CImg<_cimg_Tfloat> pseudoinvert(const CImg& instance, const bool use_LU=false) { + return instance.get_pseudoinvert(use_LU); + } + +#define _cimg_create_pointwise_function(name) \ + template \ + inline CImg<_cimg_Tfloat> name(const CImg& instance) { \ + return instance.get_##name(); \ + } + + _cimg_create_pointwise_function(sqr) + _cimg_create_pointwise_function(sqrt) + _cimg_create_pointwise_function(exp) + _cimg_create_pointwise_function(log) + _cimg_create_pointwise_function(log2) + _cimg_create_pointwise_function(log10) + _cimg_create_pointwise_function(abs) + _cimg_create_pointwise_function(sign) + _cimg_create_pointwise_function(cos) + _cimg_create_pointwise_function(sin) + _cimg_create_pointwise_function(sinc) + _cimg_create_pointwise_function(tan) + _cimg_create_pointwise_function(acos) + _cimg_create_pointwise_function(asin) + _cimg_create_pointwise_function(atan) + _cimg_create_pointwise_function(cosh) + _cimg_create_pointwise_function(sinh) + _cimg_create_pointwise_function(tanh) + _cimg_create_pointwise_function(acosh) + _cimg_create_pointwise_function(asinh) + _cimg_create_pointwise_function(atanh) + + /*----------------------------------- + # + # Define the CImgDisplay structure + # + ----------------------------------*/ + //! Allow the creation of windows, display images on them and manage user events (keyboard, mouse and windows events). + /** + CImgDisplay methods rely on a low-level graphic library to perform: it can be either \b X-Window + (X11, for Unix-based systems) or \b GDI32 (for Windows-based systems). + If both libraries are missing, CImgDisplay will not be able to display images on screen, and will enter + a minimal mode where warning messages will be outputted each time the program is trying to call one of the + CImgDisplay method. + + The configuration variable \c cimg_display tells about the graphic library used. + It is set automatically by \CImg when one of these graphic libraries has been detected. + But, you can override its value if necessary. Valid choices are: + - 0: Disable display capabilities. + - 1: Use \b X-Window (X11) library. + - 2: Use \b GDI32 library. + + Remember to link your program against \b X11 or \b GDI32 libraries if you use CImgDisplay. + **/ + struct CImgDisplay { + cimg_uint64 _timer, _fps_frames, _fps_timer; + unsigned int _width, _height, _normalization; + float _fps_fps, _min, _max; + bool _is_fullscreen; + char *_title; + unsigned int _window_width, _window_height, _button, *_keys, *_released_keys; + int _window_x, _window_y, _mouse_x, _mouse_y, _wheel; + bool _is_closed, _is_resized, _is_moved, _is_event, + _is_keyESC, _is_keyF1, _is_keyF2, _is_keyF3, _is_keyF4, _is_keyF5, _is_keyF6, _is_keyF7, + _is_keyF8, _is_keyF9, _is_keyF10, _is_keyF11, _is_keyF12, _is_keyPAUSE, _is_key1, _is_key2, + _is_key3, _is_key4, _is_key5, _is_key6, _is_key7, _is_key8, _is_key9, _is_key0, + _is_keyBACKSPACE, _is_keyINSERT, _is_keyHOME, _is_keyPAGEUP, _is_keyTAB, _is_keyQ, _is_keyW, _is_keyE, + _is_keyR, _is_keyT, _is_keyY, _is_keyU, _is_keyI, _is_keyO, _is_keyP, _is_keyDELETE, + _is_keyEND, _is_keyPAGEDOWN, _is_keyCAPSLOCK, _is_keyA, _is_keyS, _is_keyD, _is_keyF, _is_keyG, + _is_keyH, _is_keyJ, _is_keyK, _is_keyL, _is_keyENTER, _is_keySHIFTLEFT, _is_keyZ, _is_keyX, + _is_keyC, _is_keyV, _is_keyB, _is_keyN, _is_keyM, _is_keySHIFTRIGHT, _is_keyARROWUP, _is_keyCTRLLEFT, + _is_keyAPPLEFT, _is_keyALT, _is_keySPACE, _is_keyALTGR, _is_keyAPPRIGHT, _is_keyMENU, _is_keyCTRLRIGHT, + _is_keyARROWLEFT, _is_keyARROWDOWN, _is_keyARROWRIGHT, _is_keyPAD0, _is_keyPAD1, _is_keyPAD2, _is_keyPAD3, + _is_keyPAD4, _is_keyPAD5, _is_keyPAD6, _is_keyPAD7, _is_keyPAD8, _is_keyPAD9, _is_keyPADADD, _is_keyPADSUB, + _is_keyPADMUL, _is_keyPADDIV; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- + +#ifdef cimgdisplay_plugin +#include cimgdisplay_plugin +#endif +#ifdef cimgdisplay_plugin1 +#include cimgdisplay_plugin1 +#endif +#ifdef cimgdisplay_plugin2 +#include cimgdisplay_plugin2 +#endif +#ifdef cimgdisplay_plugin3 +#include cimgdisplay_plugin3 +#endif +#ifdef cimgdisplay_plugin4 +#include cimgdisplay_plugin4 +#endif +#ifdef cimgdisplay_plugin5 +#include cimgdisplay_plugin5 +#endif +#ifdef cimgdisplay_plugin6 +#include cimgdisplay_plugin6 +#endif +#ifdef cimgdisplay_plugin7 +#include cimgdisplay_plugin7 +#endif +#ifdef cimgdisplay_plugin8 +#include cimgdisplay_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + \note If the associated window is visible on the screen, it is closed by the call to the destructor. + **/ + ~CImgDisplay() { + assign(); + delete[] _keys; + delete[] _released_keys; + } + + //! Construct an empty display. + /** + \note Constructing an empty CImgDisplay instance does not make a window appearing on the screen, until + display of valid data is performed. + \par Example + \code + CImgDisplay disp; // Does actually nothing + ... + disp.display(img); // Construct new window and display image in it + \endcode + **/ + CImgDisplay(): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(); + } + + //! Construct a display with specified dimensions. + /** \param width Window width. + \param height Window height. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note A black background is initially displayed on the associated window. + **/ + CImgDisplay(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(width,height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image. + /** \param img Image used as a model to create the window. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note The pixels of the input image are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(img,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list. + /** \param list The images list to display. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note All images of the list, appended along the X-axis, are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(list,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of an existing one. + /** + \param disp Display instance to copy. + \note The pixel buffer of the input window is initially displayed on the associated window. + **/ + CImgDisplay(const CImgDisplay& disp): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(cimg::type::min()),_window_y(cimg::type::min()), + _mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(disp); + } + + //! Take a screenshot. + /** + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(CImg& img) { + return screenshot(0,0,cimg::type::max(),cimg::type::max(),img); + } + +#if cimg_display==0 + + static void _no_display_exception() { + throw CImgDisplayException("CImgDisplay(): No display available."); + } + + //! Destructor - Empty constructor \inplace. + /** + \note Replace the current instance by an empty display. + **/ + CImgDisplay& assign() { + return flush(); + } + + //! Construct a display with specified dimensions \inplace. + /** + **/ + CImgDisplay& assign(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + cimg::unused(width,height,title,normalization,is_fullscreen,is_closed); + _no_display_exception(); + return assign(); + } + + //! Construct a display from an image \inplace. + /** + **/ + template + CImgDisplay& assign(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(img._width,img._height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list \inplace. + /** + **/ + template + CImgDisplay& assign(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(list._width,list._width,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of another one \inplace. + /** + **/ + CImgDisplay& assign(const CImgDisplay &disp) { + _no_display_exception(); + return assign(disp._width,disp._height); + } + +#endif + + //! Return a reference to an empty display. + /** + \note Can be useful for writing function prototypes where one of the argument (of type CImgDisplay&) + must have a default value. + \par Example + \code + void foo(CImgDisplay& disp=CImgDisplay::empty()); + \endcode + **/ + static CImgDisplay& empty() { + static CImgDisplay _empty; + return _empty.assign(); + } + + //! Return a reference to an empty display \const. + static const CImgDisplay& const_empty() { + static const CImgDisplay _empty; + return _empty; + } + +#define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,-25,-85,false), \ + CImgDisplay::_fitscreen(dx,dy,dz,-25,-85,true) + static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy, const unsigned int dz, + const int dmin, const int dmax, const bool return_y) { + const int + u = CImgDisplay::screen_width(), + v = CImgDisplay::screen_height(); + const float + mw = dmin<0?cimg::round(u*-dmin/100.f):(float)dmin, + mh = dmin<0?cimg::round(v*-dmin/100.f):(float)dmin, + Mw = dmax<0?cimg::round(u*-dmax/100.f):(float)dmax, + Mh = dmax<0?cimg::round(v*-dmax/100.f):(float)dmax; + float + w = (float)std::max(1U,dx), + h = (float)std::max(1U,dy); + if (dz>1) { w+=dz; h+=dz; } + if (wMw) { h = h*Mw/w; w = Mw; } + if (h>Mh) { w = w*Mh/h; h = Mh; } + if (wdisp = img is equivalent to disp.display(img). + **/ + template + CImgDisplay& operator=(const CImg& img) { + return display(img); + } + + //! Display list of images on associated window. + /** + \note disp = list is equivalent to disp.display(list). + **/ + template + CImgDisplay& operator=(const CImgList& list) { + return display(list); + } + + //! Construct a display as a copy of another one \inplace. + /** + \note Equivalent to assign(const CImgDisplay&). + **/ + CImgDisplay& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return \c false if display is empty, \c true otherwise. + /** + \note if (disp) { ... } is equivalent to if (!disp.is_empty()) { ... }. + **/ + operator bool() const { + return !is_empty(); + } + + //@} + //------------------------------------------ + // + //! \name Instance Checking + //@{ + //------------------------------------------ + + //! Return \c true if display is empty, \c false otherwise. + /** + **/ + bool is_empty() const { + return !(_width && _height); + } + + //! Return \c true if display is closed (i.e. not visible on the screen), \c false otherwise. + /** + \note + - When a user physically closes the associated window, the display is set to closed. + - A closed display is not destroyed. Its associated window can be show again on the screen using show(). + **/ + bool is_closed() const { + return _is_closed; + } + + //! Return \c true if associated window has been resized on the screen, \c false otherwise. + /** + **/ + bool is_resized() const { + return _is_resized; + } + + //! Return \c true if associated window has been moved on the screen, \c false otherwise. + /** + **/ + bool is_moved() const { + return _is_moved; + } + + //! Return \c true if any event has occurred on the associated window, \c false otherwise. + /** + **/ + bool is_event() const { + return _is_event; + } + + //! Return \c true if current display is in fullscreen mode, \c false otherwise. + /** + **/ + bool is_fullscreen() const { + return _is_fullscreen; + } + + //! Return \c true if any key is being pressed on the associated window, \c false otherwise. + /** + \note The methods below do the same only for specific keys. + **/ + bool is_key() const { + return _is_keyESC || _is_keyF1 || _is_keyF2 || _is_keyF3 || + _is_keyF4 || _is_keyF5 || _is_keyF6 || _is_keyF7 || + _is_keyF8 || _is_keyF9 || _is_keyF10 || _is_keyF11 || + _is_keyF12 || _is_keyPAUSE || _is_key1 || _is_key2 || + _is_key3 || _is_key4 || _is_key5 || _is_key6 || + _is_key7 || _is_key8 || _is_key9 || _is_key0 || + _is_keyBACKSPACE || _is_keyINSERT || _is_keyHOME || + _is_keyPAGEUP || _is_keyTAB || _is_keyQ || _is_keyW || + _is_keyE || _is_keyR || _is_keyT || _is_keyY || + _is_keyU || _is_keyI || _is_keyO || _is_keyP || + _is_keyDELETE || _is_keyEND || _is_keyPAGEDOWN || + _is_keyCAPSLOCK || _is_keyA || _is_keyS || _is_keyD || + _is_keyF || _is_keyG || _is_keyH || _is_keyJ || + _is_keyK || _is_keyL || _is_keyENTER || + _is_keySHIFTLEFT || _is_keyZ || _is_keyX || _is_keyC || + _is_keyV || _is_keyB || _is_keyN || _is_keyM || + _is_keySHIFTRIGHT || _is_keyARROWUP || _is_keyCTRLLEFT || + _is_keyAPPLEFT || _is_keyALT || _is_keySPACE || _is_keyALTGR || + _is_keyAPPRIGHT || _is_keyMENU || _is_keyCTRLRIGHT || + _is_keyARROWLEFT || _is_keyARROWDOWN || _is_keyARROWRIGHT || + _is_keyPAD0 || _is_keyPAD1 || _is_keyPAD2 || + _is_keyPAD3 || _is_keyPAD4 || _is_keyPAD5 || + _is_keyPAD6 || _is_keyPAD7 || _is_keyPAD8 || + _is_keyPAD9 || _is_keyPADADD || _is_keyPADSUB || + _is_keyPADMUL || _is_keyPADDIV; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode Keycode to test. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.key(cimg::keyTAB)) { ... } // Equivalent to 'if (disp.is_keyTAB())' + disp.wait(); + } + \endcode + **/ + bool is_key(const unsigned int keycode) const { +#define _cimg_iskey_test(k) if (keycode==cimg::key##k) return _is_key##k; + _cimg_iskey_test(ESC); _cimg_iskey_test(F1); _cimg_iskey_test(F2); _cimg_iskey_test(F3); + _cimg_iskey_test(F4); _cimg_iskey_test(F5); _cimg_iskey_test(F6); _cimg_iskey_test(F7); + _cimg_iskey_test(F8); _cimg_iskey_test(F9); _cimg_iskey_test(F10); _cimg_iskey_test(F11); + _cimg_iskey_test(F12); _cimg_iskey_test(PAUSE); _cimg_iskey_test(1); _cimg_iskey_test(2); + _cimg_iskey_test(3); _cimg_iskey_test(4); _cimg_iskey_test(5); _cimg_iskey_test(6); + _cimg_iskey_test(7); _cimg_iskey_test(8); _cimg_iskey_test(9); _cimg_iskey_test(0); + _cimg_iskey_test(BACKSPACE); _cimg_iskey_test(INSERT); _cimg_iskey_test(HOME); + _cimg_iskey_test(PAGEUP); _cimg_iskey_test(TAB); _cimg_iskey_test(Q); _cimg_iskey_test(W); + _cimg_iskey_test(E); _cimg_iskey_test(R); _cimg_iskey_test(T); _cimg_iskey_test(Y); + _cimg_iskey_test(U); _cimg_iskey_test(I); _cimg_iskey_test(O); _cimg_iskey_test(P); + _cimg_iskey_test(DELETE); _cimg_iskey_test(END); _cimg_iskey_test(PAGEDOWN); + _cimg_iskey_test(CAPSLOCK); _cimg_iskey_test(A); _cimg_iskey_test(S); _cimg_iskey_test(D); + _cimg_iskey_test(F); _cimg_iskey_test(G); _cimg_iskey_test(H); _cimg_iskey_test(J); + _cimg_iskey_test(K); _cimg_iskey_test(L); _cimg_iskey_test(ENTER); + _cimg_iskey_test(SHIFTLEFT); _cimg_iskey_test(Z); _cimg_iskey_test(X); _cimg_iskey_test(C); + _cimg_iskey_test(V); _cimg_iskey_test(B); _cimg_iskey_test(N); _cimg_iskey_test(M); + _cimg_iskey_test(SHIFTRIGHT); _cimg_iskey_test(ARROWUP); _cimg_iskey_test(CTRLLEFT); + _cimg_iskey_test(APPLEFT); _cimg_iskey_test(ALT); _cimg_iskey_test(SPACE); _cimg_iskey_test(ALTGR); + _cimg_iskey_test(APPRIGHT); _cimg_iskey_test(MENU); _cimg_iskey_test(CTRLRIGHT); + _cimg_iskey_test(ARROWLEFT); _cimg_iskey_test(ARROWDOWN); _cimg_iskey_test(ARROWRIGHT); + _cimg_iskey_test(PAD0); _cimg_iskey_test(PAD1); _cimg_iskey_test(PAD2); + _cimg_iskey_test(PAD3); _cimg_iskey_test(PAD4); _cimg_iskey_test(PAD5); + _cimg_iskey_test(PAD6); _cimg_iskey_test(PAD7); _cimg_iskey_test(PAD8); + _cimg_iskey_test(PAD9); _cimg_iskey_test(PADADD); _cimg_iskey_test(PADSUB); + _cimg_iskey_test(PADMUL); _cimg_iskey_test(PADDIV); + return false; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode C-string containing the keycode label of the key to test. + \note Use it when the key you want to test can be dynamically set by the user. + \par Example + \code + CImgDisplay disp(400,400); + const char *const keycode = "TAB"; + while (!disp.is_closed()) { + if (disp.is_key(keycode)) { ... } // Equivalent to 'if (disp.is_keyTAB())' + disp.wait(); + } + \endcode + **/ + bool& is_key(const char *const keycode) { + static bool f = false; + f = false; +#define _cimg_iskey_test2(k) if (!cimg::strcasecmp(keycode,#k)) return _is_key##k; + _cimg_iskey_test2(ESC); _cimg_iskey_test2(F1); _cimg_iskey_test2(F2); _cimg_iskey_test2(F3); + _cimg_iskey_test2(F4); _cimg_iskey_test2(F5); _cimg_iskey_test2(F6); _cimg_iskey_test2(F7); + _cimg_iskey_test2(F8); _cimg_iskey_test2(F9); _cimg_iskey_test2(F10); _cimg_iskey_test2(F11); + _cimg_iskey_test2(F12); _cimg_iskey_test2(PAUSE); _cimg_iskey_test2(1); _cimg_iskey_test2(2); + _cimg_iskey_test2(3); _cimg_iskey_test2(4); _cimg_iskey_test2(5); _cimg_iskey_test2(6); + _cimg_iskey_test2(7); _cimg_iskey_test2(8); _cimg_iskey_test2(9); _cimg_iskey_test2(0); + _cimg_iskey_test2(BACKSPACE); _cimg_iskey_test2(INSERT); _cimg_iskey_test2(HOME); + _cimg_iskey_test2(PAGEUP); _cimg_iskey_test2(TAB); _cimg_iskey_test2(Q); _cimg_iskey_test2(W); + _cimg_iskey_test2(E); _cimg_iskey_test2(R); _cimg_iskey_test2(T); _cimg_iskey_test2(Y); + _cimg_iskey_test2(U); _cimg_iskey_test2(I); _cimg_iskey_test2(O); _cimg_iskey_test2(P); + _cimg_iskey_test2(DELETE); _cimg_iskey_test2(END); _cimg_iskey_test2(PAGEDOWN); + _cimg_iskey_test2(CAPSLOCK); _cimg_iskey_test2(A); _cimg_iskey_test2(S); _cimg_iskey_test2(D); + _cimg_iskey_test2(F); _cimg_iskey_test2(G); _cimg_iskey_test2(H); _cimg_iskey_test2(J); + _cimg_iskey_test2(K); _cimg_iskey_test2(L); _cimg_iskey_test2(ENTER); + _cimg_iskey_test2(SHIFTLEFT); _cimg_iskey_test2(Z); _cimg_iskey_test2(X); _cimg_iskey_test2(C); + _cimg_iskey_test2(V); _cimg_iskey_test2(B); _cimg_iskey_test2(N); _cimg_iskey_test2(M); + _cimg_iskey_test2(SHIFTRIGHT); _cimg_iskey_test2(ARROWUP); _cimg_iskey_test2(CTRLLEFT); + _cimg_iskey_test2(APPLEFT); _cimg_iskey_test2(ALT); _cimg_iskey_test2(SPACE); _cimg_iskey_test2(ALTGR); + _cimg_iskey_test2(APPRIGHT); _cimg_iskey_test2(MENU); _cimg_iskey_test2(CTRLRIGHT); + _cimg_iskey_test2(ARROWLEFT); _cimg_iskey_test2(ARROWDOWN); _cimg_iskey_test2(ARROWRIGHT); + _cimg_iskey_test2(PAD0); _cimg_iskey_test2(PAD1); _cimg_iskey_test2(PAD2); + _cimg_iskey_test2(PAD3); _cimg_iskey_test2(PAD4); _cimg_iskey_test2(PAD5); + _cimg_iskey_test2(PAD6); _cimg_iskey_test2(PAD7); _cimg_iskey_test2(PAD8); + _cimg_iskey_test2(PAD9); _cimg_iskey_test2(PADADD); _cimg_iskey_test2(PADSUB); + _cimg_iskey_test2(PADMUL); _cimg_iskey_test2(PADDIV); + return f; + } + + //! Return \c true if specified key sequence has been typed on the associated window, \c false otherwise. + /** + \param keycodes_sequence Buffer of keycodes to test. + \param length Number of keys in the \c keycodes_sequence buffer. + \param remove_sequence Tells if the key sequence must be removed from the key history, if found. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + const unsigned int key_seq[] = { cimg::keyCTRLLEFT, cimg::keyD }; + while (!disp.is_closed()) { + if (disp.is_key_sequence(key_seq,2)) { ... } // Test for the 'CTRL+D' keyboard event + disp.wait(); + } + \endcode + **/ + bool is_key_sequence(const unsigned int *const keycodes_sequence, const unsigned int length, + const bool remove_sequence=false) { + if (keycodes_sequence && length) { + const unsigned int + *const ps_end = keycodes_sequence + length - 1, + *const pk_end = (unsigned int*)_keys + 1 + 128 - length, + k = *ps_end; + for (unsigned int *pk = (unsigned int*)_keys; pk[0,255]. + If the range of values of the data to display is different, a normalization may be required for displaying + the data in a correct way. The normalization type can be one of: + - \c 0: Value normalization is disabled. It is then assumed that all input data to be displayed by the + CImgDisplay instance have values in range [0,255]. + - \c 1: Value normalization is always performed (this is the default behavior). + Before displaying an input image, its values will be (virtually) stretched + in range [0,255], so that the contrast of the displayed pixels will be maximum. + Use this mode for images whose minimum and maximum values are not prescribed to known values + (e.g. float-valued images). + Note that when normalized versions of images are computed for display purposes, the actual values of these + images are not modified. + - \c 2: Value normalization is performed once (on the first image display), then the same normalization + coefficients are kept for next displayed frames. + - \c 3: Value normalization depends on the pixel type of the data to display. For integer pixel types, + the normalization is done regarding the minimum/maximum values of the type (no normalization occurs then + for unsigned char). + For float-valued pixel types, the normalization is done regarding the minimum/maximum value of the image + data instead. + **/ + unsigned int normalization() const { + return _normalization; + } + + //! Return title of the associated window as a C-string. + /** + \note Window title may be not visible, depending on the used window manager or if the current display is + in fullscreen mode. + **/ + const char *title() const { + return _title?_title:""; + } + + //! Return width of the associated window. + /** + \note The width of the display (i.e. the width of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual width of the associated window. + **/ + int window_width() const { + return (int)_window_width; + } + + //! Return height of the associated window. + /** + \note The height of the display (i.e. the height of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual height of the associated window. + **/ + int window_height() const { + return (int)_window_height; + } + + //! Return X-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_x() const { + return _window_x; + } + + //! Return Y-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_y() const { + return _window_y; + } + + //! Return X-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,width()-1]. + **/ + int mouse_x() const { + return _mouse_x; + } + + //! Return Y-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,height()-1]. + **/ + int mouse_y() const { + return _mouse_y; + } + + //! Return current state of the mouse buttons. + /** + \note Three mouse buttons can be managed. If one button is pressed, its corresponding bit in the returned + value is set: + - bit \c 0 (value \c 0x1): State of the left mouse button. + - bit \c 1 (value \c 0x2): State of the right mouse button. + - bit \c 2 (value \c 0x4): State of the middle mouse button. + + Several bits can be activated if more than one button are pressed at the same time. + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.button()&1) { // Left button clicked + ... + } + if (disp.button()&2) { // Right button clicked + ... + } + if (disp.button()&4) { // Middle button clicked + ... + } + disp.wait(); + } + \endcode + **/ + unsigned int button() const { + return _button; + } + + //! Return current state of the mouse wheel. + /** + \note + - The returned value can be positive or negative depending on whether the mouse wheel has been scrolled + forward or backward. + - Scrolling the wheel forward add \c 1 to the wheel value. + - Scrolling the wheel backward subtract \c 1 to the wheel value. + - The returned value cumulates the number of forward of backward scrolls since the creation of the display, + or since the last reset of the wheel value (using set_wheel()). It is strongly recommended to quickly reset + the wheel counter when an action has been performed regarding the current wheel value. + Otherwise, the returned wheel value may be for instance \c 0 despite the fact that many scrolls have been done + (as many in forward as in backward directions). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.wheel()) { + int counter = disp.wheel(); // Read the state of the mouse wheel + ... // Do what you want with 'counter' + disp.set_wheel(); // Reset the wheel value to 0 + } + disp.wait(); + } + \endcode + **/ + int wheel() const { + return _wheel; + } + + //! Return one entry from the pressed keys history. + /** + \param pos Index to read from the pressed keys history (index \c 0 corresponds to latest entry). + \return Keycode of a pressed key or \c 0 for a released key. + \note + - Each CImgDisplay stores a history of the pressed keys in a buffer of size \c 128. When a new key is pressed, + its keycode is stored in the pressed keys history. When a key is released, \c 0 is put instead. + This means that up to the 64 last pressed keys may be read from the pressed keys history. + When a new value is stored, the pressed keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int& key(const unsigned int pos=0) const { + static unsigned int key0; + return pos<128?_keys[pos]:(key0 = 0); + + } + + //! Return one entry from the released keys history. + /** + \param pos Index to read from the released keys history (index \c 0 corresponds to latest entry). + \return Keycode of a released key or \c 0 for a pressed key. + \note + - Each CImgDisplay stores a history of the released keys in a buffer of size \c 128. When a new key is released, + its keycode is stored in the pressed keys history. When a key is pressed, \c 0 is put instead. + This means that up to the 64 last released keys may be read from the released keys history. + When a new value is stored, the released keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int& released_key(const unsigned int pos=0) const { + static unsigned int key0; + return pos<128?_released_keys[pos]:(key0 = 0); + } + + //! Return keycode corresponding to the specified string. + /** + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + const unsigned int keyTAB = CImgDisplay::keycode("TAB"); // Return cimg::keyTAB + \endcode + **/ + static unsigned int keycode(const char *const keycode) { +#define _cimg_keycode(k) if (!cimg::strcasecmp(keycode,#k)) return cimg::key##k; + _cimg_keycode(ESC); _cimg_keycode(F1); _cimg_keycode(F2); _cimg_keycode(F3); + _cimg_keycode(F4); _cimg_keycode(F5); _cimg_keycode(F6); _cimg_keycode(F7); + _cimg_keycode(F8); _cimg_keycode(F9); _cimg_keycode(F10); _cimg_keycode(F11); + _cimg_keycode(F12); _cimg_keycode(PAUSE); _cimg_keycode(1); _cimg_keycode(2); + _cimg_keycode(3); _cimg_keycode(4); _cimg_keycode(5); _cimg_keycode(6); + _cimg_keycode(7); _cimg_keycode(8); _cimg_keycode(9); _cimg_keycode(0); + _cimg_keycode(BACKSPACE); _cimg_keycode(INSERT); _cimg_keycode(HOME); + _cimg_keycode(PAGEUP); _cimg_keycode(TAB); _cimg_keycode(Q); _cimg_keycode(W); + _cimg_keycode(E); _cimg_keycode(R); _cimg_keycode(T); _cimg_keycode(Y); + _cimg_keycode(U); _cimg_keycode(I); _cimg_keycode(O); _cimg_keycode(P); + _cimg_keycode(DELETE); _cimg_keycode(END); _cimg_keycode(PAGEDOWN); + _cimg_keycode(CAPSLOCK); _cimg_keycode(A); _cimg_keycode(S); _cimg_keycode(D); + _cimg_keycode(F); _cimg_keycode(G); _cimg_keycode(H); _cimg_keycode(J); + _cimg_keycode(K); _cimg_keycode(L); _cimg_keycode(ENTER); + _cimg_keycode(SHIFTLEFT); _cimg_keycode(Z); _cimg_keycode(X); _cimg_keycode(C); + _cimg_keycode(V); _cimg_keycode(B); _cimg_keycode(N); _cimg_keycode(M); + _cimg_keycode(SHIFTRIGHT); _cimg_keycode(ARROWUP); _cimg_keycode(CTRLLEFT); + _cimg_keycode(APPLEFT); _cimg_keycode(ALT); _cimg_keycode(SPACE); _cimg_keycode(ALTGR); + _cimg_keycode(APPRIGHT); _cimg_keycode(MENU); _cimg_keycode(CTRLRIGHT); + _cimg_keycode(ARROWLEFT); _cimg_keycode(ARROWDOWN); _cimg_keycode(ARROWRIGHT); + _cimg_keycode(PAD0); _cimg_keycode(PAD1); _cimg_keycode(PAD2); + _cimg_keycode(PAD3); _cimg_keycode(PAD4); _cimg_keycode(PAD5); + _cimg_keycode(PAD6); _cimg_keycode(PAD7); _cimg_keycode(PAD8); + _cimg_keycode(PAD9); _cimg_keycode(PADADD); _cimg_keycode(PADSUB); + _cimg_keycode(PADMUL); _cimg_keycode(PADDIV); + return 0; + } + + //! Return the current refresh rate, in frames per second. + /** + \note Returns a significant value when the current instance is used to display successive frames. + It measures the delay between successive calls to frames_per_second(). + **/ + float frames_per_second() { + if (!_fps_timer) _fps_timer = cimg::time(); + const float delta = (float)((cimg::time() - _fps_timer)/1000.f); + ++_fps_frames; + if (delta>=1) { + _fps_fps = _fps_frames/delta; + _fps_frames = 0; + _fps_timer = cimg::time(); + } + return _fps_fps; + } + + // Move current display window so that its content stays inside the current screen. + CImgDisplay& move_inside_screen() { + if (is_empty()) return *this; + const int + x0 = window_x(), + y0 = window_y(), + x1 = x0 + window_width() - 1, + y1 = y0 + window_height() - 1, + sw = CImgDisplay::screen_width(), + sh = CImgDisplay::screen_height(); + if (x0<0 || y0<0 || x1>=sw || y1>=sh) + move(std::max(0,std::min(x0,sw - x1 + x0)), + std::max(0,std::min(y0,sh - y1 + y0))); + return *this; + } + + //@} + //--------------------------------------- + // + //! \name Window Manipulation + //@{ + //--------------------------------------- + +#if cimg_display==0 + + //! Display image on associated window. + /** + \param img Input image to display. + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImg& img) { + return assign(img); + } + +#endif + + //! Display list of images on associated window. + /** + \param list List of images to display. + \param axis Axis used to append the images along, for the visualization (can be \c x, \c y, \c z or \c c). + \param align Relative position of aligned images when displaying lists with images of different sizes + (\c 0 for upper-left, \c 0.5 for centering and \c 1 for lower-right). + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImgList& list, const char axis='x', const float align=0) { + if (list._width==1) { + const CImg& img = list[0]; + if (img._depth==1 && (img._spectrum==1 || img._spectrum>=3) && _normalization!=1) return display(img); + } + CImgList::ucharT> visu(list._width); + unsigned int dims = 0; + cimglist_for(list,l) { + const CImg& img = list._data[l]; + img._get_select(*this,_normalization,(img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2).move_to(visu[l]); + dims = std::max(dims,visu[l]._spectrum); + } + cimglist_for(list,l) if (visu[l]._spectrumimg.width() become equal, as well as height() and + img.height(). + - The associated window is also resized to specified dimensions. + **/ + template + CImgDisplay& resize(const CImg& img, const bool force_redraw=true) { + return resize(img._width,img._height,force_redraw); + } + + //! Resize display to the size of another CImgDisplay instance. + /** + \param disp Input display to take size from. + \param force_redraw Tells if the previous window content must be resized and updated as well. + \note + - Calling this method ensures that width() and disp.width() become equal, as well as height() and + disp.height(). + - The associated window is also resized to specified dimensions. + **/ + CImgDisplay& resize(const CImgDisplay& disp, const bool force_redraw=true) { + return resize(disp.width(),disp.height(),force_redraw); + } + + // [internal] Render pixel buffer with size (wd,hd) from source buffer of size (ws,hs). + template + static void _render_resize(const T *ptrs, const unsigned int ws, const unsigned int hs, + t *ptrd, const unsigned int wd, const unsigned int hd) { + typedef typename cimg::last::type ulongT; + const ulongT one = (ulongT)1; + CImg off_x(wd), off_y(hd + 1); + if (wd==ws) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + for (unsigned int x = 0; xstd::printf(). + \warning As the first argument is a format string, it is highly recommended to write + \code + disp.set_title("%s",window_title); + \endcode + instead of + \code + disp.set_title(window_title); + \endcode + if \c window_title can be arbitrary, to prevent nasty memory access. + **/ + CImgDisplay& set_title(const char *const format, ...) { + return assign(0,0,format); + } + +#endif + + //! Enable or disable fullscreen mode. + /** + \param is_fullscreen Tells is the fullscreen mode must be activated or not. + \param force_redraw Tells if the previous window content must be displayed as well. + \note + - When the fullscreen mode is enabled, the associated window fills the entire screen but the size of the + current display is not modified. + - The screen resolution may be switched to fit the associated window size and ensure it appears the largest + as possible. + For X-Window (X11) users, the configuration flag \c cimg_use_xrandr has to be set to allow the screen + resolution change (requires the X11 extensions to be enabled). + **/ + CImgDisplay& set_fullscreen(const bool is_fullscreen, const bool force_redraw=true) { + if (is_empty() || _is_fullscreen==is_fullscreen) return *this; + return toggle_fullscreen(force_redraw); + } + +#if cimg_display==0 + + //! Toggle fullscreen mode. + /** + \param force_redraw Tells if the previous window content must be displayed as well. + \note Enable fullscreen mode if it was not enabled, and disable it otherwise. + **/ + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + return assign(_width,_height,0,3,force_redraw); + } + + //! Show mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& show_mouse() { + return assign(); + } + + //! Hide mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& hide_mouse() { + return assign(); + } + + //! Move mouse pointer to a specified location. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& set_mouse(const int pos_x, const int pos_y) { + return assign(pos_x,pos_y); + } + +#endif + + //! Simulate a mouse button release event. + /** + \note All mouse buttons are considered released at the same time. + **/ + CImgDisplay& set_button() { + _button = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a mouse button press or release event. + /** + \param button Buttons event code, where each button is associated to a single bit. + \param is_pressed Tells if the mouse button is considered as pressed or released. + **/ + CImgDisplay& set_button(const unsigned int button, const bool is_pressed=true) { + const unsigned int buttoncode = button==1U?1U:button==2U?2U:button==3U?4U:0U; + if (is_pressed) _button |= buttoncode; else _button &= ~buttoncode; + _is_event = buttoncode?true:false; + if (buttoncode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all mouse wheel events. + /** + \note Make wheel() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_wheel() { + _wheel = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a wheel event. + /** + \param amplitude Amplitude of the wheel scrolling to simulate. + \note Make wheel() to return \c amplitude, if called afterwards. + **/ + CImgDisplay& set_wheel(const int amplitude) { + _wheel+=amplitude; + _is_event = amplitude?true:false; + if (amplitude) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all key events. + /** + \note Make key() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_key() { + std::memset((void*)_keys,0,128*sizeof(unsigned int)); + std::memset((void*)_released_keys,0,128*sizeof(unsigned int)); + _is_keyESC = _is_keyF1 = _is_keyF2 = _is_keyF3 = _is_keyF4 = _is_keyF5 = _is_keyF6 = _is_keyF7 = _is_keyF8 = + _is_keyF9 = _is_keyF10 = _is_keyF11 = _is_keyF12 = _is_keyPAUSE = _is_key1 = _is_key2 = _is_key3 = _is_key4 = + _is_key5 = _is_key6 = _is_key7 = _is_key8 = _is_key9 = _is_key0 = _is_keyBACKSPACE = _is_keyINSERT = + _is_keyHOME = _is_keyPAGEUP = _is_keyTAB = _is_keyQ = _is_keyW = _is_keyE = _is_keyR = _is_keyT = _is_keyY = + _is_keyU = _is_keyI = _is_keyO = _is_keyP = _is_keyDELETE = _is_keyEND = _is_keyPAGEDOWN = _is_keyCAPSLOCK = + _is_keyA = _is_keyS = _is_keyD = _is_keyF = _is_keyG = _is_keyH = _is_keyJ = _is_keyK = _is_keyL = + _is_keyENTER = _is_keySHIFTLEFT = _is_keyZ = _is_keyX = _is_keyC = _is_keyV = _is_keyB = _is_keyN = + _is_keyM = _is_keySHIFTRIGHT = _is_keyARROWUP = _is_keyCTRLLEFT = _is_keyAPPLEFT = _is_keyALT = _is_keySPACE = + _is_keyALTGR = _is_keyAPPRIGHT = _is_keyMENU = _is_keyCTRLRIGHT = _is_keyARROWLEFT = _is_keyARROWDOWN = + _is_keyARROWRIGHT = _is_keyPAD0 = _is_keyPAD1 = _is_keyPAD2 = _is_keyPAD3 = _is_keyPAD4 = _is_keyPAD5 = + _is_keyPAD6 = _is_keyPAD7 = _is_keyPAD8 = _is_keyPAD9 = _is_keyPADADD = _is_keyPADSUB = _is_keyPADMUL = + _is_keyPADDIV = false; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a keyboard press/release event. + /** + \param keycode Keycode of the associated key. + \param is_pressed Tells if the key is considered as pressed or released. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + CImgDisplay& set_key(const unsigned int keycode, const bool is_pressed=true) { +#define _cimg_set_key(k) if (keycode==cimg::key##k) _is_key##k = is_pressed; + _cimg_set_key(ESC); _cimg_set_key(F1); _cimg_set_key(F2); _cimg_set_key(F3); + _cimg_set_key(F4); _cimg_set_key(F5); _cimg_set_key(F6); _cimg_set_key(F7); + _cimg_set_key(F8); _cimg_set_key(F9); _cimg_set_key(F10); _cimg_set_key(F11); + _cimg_set_key(F12); _cimg_set_key(PAUSE); _cimg_set_key(1); _cimg_set_key(2); + _cimg_set_key(3); _cimg_set_key(4); _cimg_set_key(5); _cimg_set_key(6); + _cimg_set_key(7); _cimg_set_key(8); _cimg_set_key(9); _cimg_set_key(0); + _cimg_set_key(BACKSPACE); _cimg_set_key(INSERT); _cimg_set_key(HOME); + _cimg_set_key(PAGEUP); _cimg_set_key(TAB); _cimg_set_key(Q); _cimg_set_key(W); + _cimg_set_key(E); _cimg_set_key(R); _cimg_set_key(T); _cimg_set_key(Y); + _cimg_set_key(U); _cimg_set_key(I); _cimg_set_key(O); _cimg_set_key(P); + _cimg_set_key(DELETE); _cimg_set_key(END); _cimg_set_key(PAGEDOWN); + _cimg_set_key(CAPSLOCK); _cimg_set_key(A); _cimg_set_key(S); _cimg_set_key(D); + _cimg_set_key(F); _cimg_set_key(G); _cimg_set_key(H); _cimg_set_key(J); + _cimg_set_key(K); _cimg_set_key(L); _cimg_set_key(ENTER); + _cimg_set_key(SHIFTLEFT); _cimg_set_key(Z); _cimg_set_key(X); _cimg_set_key(C); + _cimg_set_key(V); _cimg_set_key(B); _cimg_set_key(N); _cimg_set_key(M); + _cimg_set_key(SHIFTRIGHT); _cimg_set_key(ARROWUP); _cimg_set_key(CTRLLEFT); + _cimg_set_key(APPLEFT); _cimg_set_key(ALT); _cimg_set_key(SPACE); _cimg_set_key(ALTGR); + _cimg_set_key(APPRIGHT); _cimg_set_key(MENU); _cimg_set_key(CTRLRIGHT); + _cimg_set_key(ARROWLEFT); _cimg_set_key(ARROWDOWN); _cimg_set_key(ARROWRIGHT); + _cimg_set_key(PAD0); _cimg_set_key(PAD1); _cimg_set_key(PAD2); + _cimg_set_key(PAD3); _cimg_set_key(PAD4); _cimg_set_key(PAD5); + _cimg_set_key(PAD6); _cimg_set_key(PAD7); _cimg_set_key(PAD8); + _cimg_set_key(PAD9); _cimg_set_key(PADADD); _cimg_set_key(PADSUB); + _cimg_set_key(PADMUL); _cimg_set_key(PADDIV); + if (is_pressed) { + if (*_keys) + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = keycode; + if (*_released_keys) { + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = 0; + } + } else { + if (*_keys) { + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = 0; + } + if (*_released_keys) + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = keycode; + } + _is_event = keycode?true:false; + if (keycode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all display events. + /** + \note Remove all passed events from the current display. + **/ + CImgDisplay& flush() { + set_key().set_button().set_wheel(); + _is_resized = _is_moved = _is_event = false; + _fps_timer = _fps_frames = _timer = 0; + _fps_fps = 0; + return *this; + } + + //! Wait for any user event occurring on the current display. + CImgDisplay& wait() { + wait(*this); + return *this; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \note Similar to cimg::wait(). + **/ + CImgDisplay& wait(const unsigned int milliseconds) { + cimg::wait(milliseconds,&_timer); + return *this; + } + + //! Wait for any event occurring on the display \c disp1. + static void wait(CImgDisplay& disp1) { + disp1._is_event = false; + while (!disp1._is_closed && !disp1._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1 or \c disp2. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2) { + disp1._is_event = disp2._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed) && + !disp1._is_event && !disp2._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2 or \c disp3. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3) { + disp1._is_event = disp2._is_event = disp3._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3 or \c disp4. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4 or \c disp5. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, + CImgDisplay& disp5) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event) + wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp6. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp7. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp8. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp9. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event) wait_all(); + } + + //! Wait for any event occurring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp10. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9, + CImgDisplay& disp10) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = disp10._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed || !disp10._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event && !disp10._is_event) + wait_all(); + } + +#if cimg_display==0 + + //! Wait for any window event occurring in any opened CImgDisplay. + static void wait_all() { + return _no_display_exception(); + } + + //! Render image into internal display buffer. + /** + \param img Input image data to render. + \note + - Convert image data representation into the internal display buffer (architecture-dependent structure). + - The content of the associated window is not modified, until paint() is called. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + template + CImgDisplay& render(const CImg& img) { + return assign(img); + } + + //! Paint internal display buffer on associated window. + /** + \note + - Update the content of the associated window with the internal display buffer, e.g. after a render() call. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + CImgDisplay& paint() { + return assign(); + } + + + //! Take a snapshot of the current screen content. + /** + \param x0 X-coordinate of the upper left corner. + \param y0 Y-coordinate of the upper left corner. + \param x1 X-coordinate of the lower right corner. + \param y1 Y-coordinate of the lower right corner. + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + cimg::unused(x0,y0,x1,y1,&img); + _no_display_exception(); + } + + //! Take a snapshot of the associated window content. + /** + \param[out] img Output snapshot. Can be empty on input. + **/ + template + const CImgDisplay& snapshot(CImg& img) const { + cimg::unused(img); + _no_display_exception(); + return *this; + } +#endif + + // X11-based implementation + //-------------------------- +#if cimg_display==1 + + Atom _wm_window_atom, _wm_protocol_atom; + Window _window, _background_window; + Colormap _colormap; + XImage *_image; + void *_data; + +#ifdef cimg_use_xshm + XShmSegmentInfo *_shminfo; +#endif + + static int screen_width() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_width(): Failed to open X11 display."); + res = DisplayWidth(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width; + else res = DisplayWidth(dpy,DefaultScreen(dpy)); +#else + res = DisplayWidth(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static int screen_height() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_height(): Failed to open X11 display."); + res = DisplayHeight(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height; + else res = DisplayHeight(dpy,DefaultScreen(dpy)); +#else + res = DisplayHeight(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static void wait_all() { + if (!cimg::X11_attr().display) return; + pthread_mutex_lock(&cimg::X11_attr().wait_event_mutex); + pthread_cond_wait(&cimg::X11_attr().wait_event,&cimg::X11_attr().wait_event_mutex); + pthread_mutex_unlock(&cimg::X11_attr().wait_event_mutex); + } + + void _handle_events(const XEvent *const pevent) { + Display *const dpy = cimg::X11_attr().display; + XEvent event = *pevent; + switch (event.type) { + case ClientMessage : { + if ((int)event.xclient.message_type==(int)_wm_protocol_atom && + (int)event.xclient.data.l[0]==(int)_wm_window_atom) { + XUnmapWindow(cimg::X11_attr().display,_window); + _is_closed = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case ConfigureNotify : { + while (XCheckWindowEvent(dpy,_window,StructureNotifyMask,&event)) {} + const unsigned int nw = event.xconfigure.width, nh = event.xconfigure.height; + const int nx = event.xconfigure.x, ny = event.xconfigure.y; + if (nw && nh && (nw!=_window_width || nh!=_window_height)) { + _window_width = nw; _window_height = nh; _mouse_x = _mouse_y = -1; + XResizeWindow(dpy,_window,_window_width,_window_height); + _is_resized = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + if (nx!=_window_x || ny!=_window_y) { + _window_x = nx; + _window_y = ny; + _is_moved = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case Expose : { + while (XCheckWindowEvent(dpy,_window,ExposureMask,&event)) {} + _paint(false); + if (_is_fullscreen) { + XWindowAttributes attr; + do { + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + XSetInputFocus(dpy,_window,RevertToParent,CurrentTime); + } + } break; + case ButtonPress : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1); break; + case 3 : set_button(2); break; + case 2 : set_button(3); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonPressMask,&event)); + } break; + case ButtonRelease : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1,false); break; + case 3 : set_button(2,false); break; + case 2 : set_button(3,false); break; + case 4 : set_wheel(1); break; + case 5 : set_wheel(-1); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonReleaseMask,&event)); + } break; + case KeyPress : { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,true); + } break; + case KeyRelease : { + char keys_return[32]; // Check that the key has been physically unpressed + XQueryKeymap(dpy,keys_return); + const unsigned int kc = event.xkey.keycode, kc1 = kc/8, kc2 = kc%8; + const bool is_key_pressed = kc1>=32?false:(keys_return[kc1]>>kc2)&1; + if (!is_key_pressed) { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,false); + } + } break; + case EnterNotify: { + while (XCheckWindowEvent(dpy,_window,EnterWindowMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + } break; + case LeaveNotify : { + while (XCheckWindowEvent(dpy,_window,LeaveWindowMask,&event)) {} + _mouse_x = _mouse_y = -1; _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + case MotionNotify : { + while (XCheckWindowEvent(dpy,_window,PointerMotionMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + } + } + + static void* _events_thread(void *arg) { // Thread to manage events for all opened display windows + Display *const dpy = cimg::X11_attr().display; + XEvent event; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); + if (!arg) for ( ; ; ) { + cimg_lock_display(); + bool event_flag = XCheckTypedEvent(dpy,ClientMessage,&event); + if (!event_flag) event_flag = XCheckMaskEvent(dpy, + ExposureMask | StructureNotifyMask | ButtonPressMask | + KeyPressMask | PointerMotionMask | EnterWindowMask | + LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask,&event); + if (event_flag) + for (unsigned int i = 0; i_is_closed && event.xany.window==cimg::X11_attr().wins[i]->_window) + cimg::X11_attr().wins[i]->_handle_events(&event); + cimg_unlock_display(); + pthread_testcancel(); + cimg::sleep(8); + } + return 0; + } + + void _set_colormap(Colormap& cmap, const unsigned int dim) { + XColor *const colormap = new XColor[256]; + switch (dim) { + case 1 : { // colormap for greyscale images + for (unsigned int index = 0; index<256; ++index) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].green = colormap[index].blue = (unsigned short)(index<<8); + colormap[index].flags = DoRed | DoGreen | DoBlue; + } + } break; + case 2 : { // colormap for RG images + for (unsigned int index = 0, r = 8; r<256; r+=16) + for (unsigned int g = 8; g<256; g+=16) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].blue = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } break; + default : { // colormap for RGB images + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap[index].pixel = index; + colormap[index].red = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index].blue = (unsigned short)(b<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } + } + XStoreColors(cimg::X11_attr().display,cmap,colormap,256); + delete[] colormap; + } + + void _map_window() { + Display *const dpy = cimg::X11_attr().display; + bool is_exposed = false, is_mapped = false; + XWindowAttributes attr; + XEvent event; + XMapRaised(dpy,_window); + do { // Wait for the window to be mapped + XWindowEvent(dpy,_window,StructureNotifyMask | ExposureMask,&event); + switch (event.type) { + case MapNotify : is_mapped = true; break; + case Expose : is_exposed = true; break; + } + } while (!is_exposed || !is_mapped); + do { // Wait for the window to be visible + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + _window_x = attr.x; + _window_y = attr.y; + } + + void _paint(const bool wait_expose=true) { + if (_is_closed || !_image) return; + Display *const dpy = cimg::X11_attr().display; + if (wait_expose) { // Send an expose event sticked to display window to force repaint + XEvent event; + event.xexpose.type = Expose; + event.xexpose.serial = 0; + event.xexpose.send_event = 1; + event.xexpose.display = dpy; + event.xexpose.window = _window; + event.xexpose.x = 0; + event.xexpose.y = 0; + event.xexpose.width = width(); + event.xexpose.height = height(); + event.xexpose.count = 0; + XSendEvent(dpy,_window,0,0,&event); + } else { // Repaint directly (may be called from the expose event) + GC gc = DefaultGC(dpy,DefaultScreen(dpy)); + +#ifdef cimg_use_xshm + if (_shminfo) XShmPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height,1); + else XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#else + XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#endif + } + } + + template + void _resize(T pixel_type, const unsigned int ndimx, const unsigned int ndimy, const bool force_redraw) { + Display *const dpy = cimg::X11_attr().display; + cimg::unused(pixel_type); + +#ifdef cimg_use_xshm + if (_shminfo) { + XShmSegmentInfo *const nshminfo = new XShmSegmentInfo; + XImage *const nimage = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy); + if (!nimage) { delete nshminfo; return; } + else { + nshminfo->shmid = shmget(IPC_PRIVATE,ndimx*ndimy*sizeof(T),IPC_CREAT | 0777); + if (nshminfo->shmid==-1) { XDestroyImage(nimage); delete nshminfo; return; } + else { + nshminfo->shmaddr = nimage->data = (char*)shmat(nshminfo->shmid,0,0); + if (nshminfo->shmaddr==(char*)-1) { + shmctl(nshminfo->shmid,IPC_RMID,0); XDestroyImage(nimage); delete nshminfo; return; + } else { + nshminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,nshminfo); + XFlush(dpy); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(nshminfo->shmaddr); + shmctl(nshminfo->shmid,IPC_RMID,0); + XDestroyImage(nimage); + delete nshminfo; + return; + } else { + T *const ndata = (T*)nimage->data; + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + XShmDetach(dpy,_shminfo); + XDestroyImage(_image); + shmdt(_shminfo->shmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = nshminfo; + _image = nimage; + _data = (void*)ndata; + } + } + } + } + } else +#endif + { + T *ndata = (T*)std::malloc(ndimx*ndimy*sizeof(T)); + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + _data = (void*)ndata; + XDestroyImage(_image); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,(char*)_data,ndimx,ndimy,8,0); + } + } + + void _init_fullscreen() { + if (!_is_fullscreen || _is_closed) return; + Display *const dpy = cimg::X11_attr().display; + _background_window = 0; + +#ifdef cimg_use_xrandr + int foo; + if (XRRQueryExtension(dpy,&foo,&foo)) { + XRRRotations(dpy,DefaultScreen(dpy),&cimg::X11_attr().curr_rotation); + if (!cimg::X11_attr().resolutions) { + cimg::X11_attr().resolutions = XRRSizes(dpy,DefaultScreen(dpy),&foo); + cimg::X11_attr().nb_resolutions = (unsigned int)foo; + } + if (cimg::X11_attr().resolutions) { + cimg::X11_attr().curr_resolution = 0; + for (unsigned int i = 0; i=_width && nh>=_height && + nw<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width) && + nh<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height)) + cimg::X11_attr().curr_resolution = i; + } + if (cimg::X11_attr().curr_resolution>0) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy), + cimg::X11_attr().curr_resolution,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + } + } + } + if (!cimg::X11_attr().resolutions) + cimg::warn(_cimgdisplay_instance + "init_fullscreen(): Xrandr extension not supported by the X server.", + cimgdisplay_instance); +#endif + + const unsigned int sx = screen_width(), sy = screen_height(); + if (sx==_width && sy==_height) return; + XSetWindowAttributes attr_set; + + attr_set.background_pixel = XBlackPixel(dpy,XDefaultScreen(dpy)); + attr_set.override_redirect = 1; + _background_window = XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,sx,sy,0,0, + InputOutput,CopyFromParent,CWBackPixel | CWOverrideRedirect,&attr_set); + XEvent event; + XSelectInput(dpy,_background_window,StructureNotifyMask); + XMapRaised(dpy,_background_window); + do XWindowEvent(dpy,_background_window,StructureNotifyMask,&event); + while (event.type!=MapNotify); + + XWindowAttributes attr; + do { + XGetWindowAttributes(dpy,_background_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + Display *const dpy = cimg::X11_attr().display; + XUngrabKeyboard(dpy,CurrentTime); + +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy),0,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + cimg::X11_attr().curr_resolution = 0; + } +#endif + if (_background_window) XDestroyWindow(dpy,_background_window); + _background_window = 0; + _is_fullscreen = false; + } + + static int _assign_xshm(Display *dpy, XErrorEvent *error) { + cimg::unused(dpy,error); + cimg::X11_attr().is_shm_enabled = false; + return 0; + } + + void _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + cimg::mutex(14); + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous display window if existing + if (!is_empty()) assign(); + + // Open X11 display and retrieve graphical properties. + Display* &dpy = cimg::X11_attr().display; + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Failed to open X11 display.", + cimgdisplay_instance); + + cimg::X11_attr().nb_bits = DefaultDepth(dpy,DefaultScreen(dpy)); + if (cimg::X11_attr().nb_bits!=8 && cimg::X11_attr().nb_bits!=16 && + cimg::X11_attr().nb_bits!=24 && cimg::X11_attr().nb_bits!=32) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Invalid %u bits screen mode detected " + "(only 8, 16, 24 and 32 bits modes are managed).", + cimgdisplay_instance, + cimg::X11_attr().nb_bits); + XVisualInfo vtemplate; + vtemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy,DefaultScreen(dpy))); + int nb_visuals; + XVisualInfo *vinfo = XGetVisualInfo(dpy,VisualIDMask,&vtemplate,&nb_visuals); + if (vinfo && vinfo->red_maskblue_mask) cimg::X11_attr().is_blue_first = true; + cimg::X11_attr().byte_order = ImageByteOrder(dpy); + XFree(vinfo); + + cimg_lock_display(); + cimg::X11_attr().events_thread = new pthread_t; + pthread_create(cimg::X11_attr().events_thread,0,_events_thread,0); + } else cimg_lock_display(); + + // Set display variables. + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = cimg::type::min(); + _is_closed = closed_flag; + _title = tmp_title; + flush(); + + // Create X11 window (and LUT, if 8bits display) + if (_is_fullscreen) { + if (!_is_closed) _init_fullscreen(); + const unsigned int sx = screen_width(), sy = screen_height(); + XSetWindowAttributes attr_set; + attr_set.override_redirect = 1; + _window = XCreateWindow(dpy,DefaultRootWindow(dpy),(sx - _width)/2,(sy - _height)/2,_width,_height,0,0, + InputOutput,CopyFromParent,CWOverrideRedirect,&attr_set); + } else + _window = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,_width,_height,0,0L,0L); + + XSelectInput(dpy,_window, + ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask | + EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask); + + XStoreName(dpy,_window,_title?_title:" "); + if (cimg::X11_attr().nb_bits==8) { + _colormap = XCreateColormap(dpy,_window,DefaultVisual(dpy,DefaultScreen(dpy)),AllocAll); + _set_colormap(_colormap,3); + XSetWindowColormap(dpy,_window,_colormap); + } + + static const char *const _window_class = cimg_appname; + XClassHint *const window_class = XAllocClassHint(); + window_class->res_name = (char*)_window_class; + window_class->res_class = (char*)_window_class; + XSetClassHint(dpy,_window,window_class); + XFree(window_class); + + _window_width = _width; + _window_height = _height; + + // Create XImage +#ifdef cimg_use_xshm + _shminfo = 0; + if (XShmQueryExtension(dpy)) { + _shminfo = new XShmSegmentInfo; + _image = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,_shminfo,_width,_height); + if (!_image) { delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmid = shmget(IPC_PRIVATE,_image->bytes_per_line*_image->height,IPC_CREAT|0777); + if (_shminfo->shmid==-1) { XDestroyImage(_image); delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmaddr = _image->data = (char*)(_data = shmat(_shminfo->shmid,0,0)); + if (_shminfo->shmaddr==(char*)-1) { + shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); delete _shminfo; _shminfo = 0; + } else { + _shminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,_shminfo); + XSync(dpy,0); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(_shminfo->shmaddr); shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); + delete _shminfo; _shminfo = 0; + } + } + } + } + } + if (!_shminfo) +#endif + { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*(cimg::X11_attr().nb_bits==8?1: + (cimg::X11_attr().nb_bits==16?2:4)); + _data = std::malloc(buf_size); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,(char*)_data,_width,_height,8,0); + } + + _wm_window_atom = XInternAtom(dpy,"WM_DELETE_WINDOW",0); + _wm_protocol_atom = XInternAtom(dpy,"WM_PROTOCOLS",0); + XSetWMProtocols(dpy,_window,&_wm_window_atom,1); + + if (_is_fullscreen) XGrabKeyboard(dpy,_window,1,GrabModeAsync,GrabModeAsync,CurrentTime); + cimg::X11_attr().wins[cimg::X11_attr().nb_wins++]=this; + if (!_is_closed) _map_window(); else _window_x = _window_y = cimg::type::min(); + cimg_unlock_display(); + cimg::mutex(14,0); + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + + // Remove display window from event thread list. + unsigned int i; + for (i = 0; ishmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = 0; + } +#endif + + XDestroyImage(_image); + if (cimg::X11_attr().nb_bits==8) XFreeColormap(dpy,_colormap); + XDestroyWindow(dpy,_window); + XSync(dpy,0); + _window = 0; _colormap = 0; _data = 0; _image = 0; + + // Reset display variables. + delete[] _title; + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = cimg::type::min(); + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + + cimg_unlock_display(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + (cimg::X11_attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))* + (size_t)_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + cimg::X11_attr().nb_bits==16?sizeof(unsigned short): + sizeof(unsigned int))*(size_t)_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign(nwidth,nheight); + Display *const dpy = cimg::X11_attr().display; + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*width()/100), + tmpdimy = (nheight>0)?nheight:(-nheight*height()/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + show(); + cimg_lock_display(); + if (_window_width!=dimx || _window_height!=dimy) { + XWindowAttributes attr; + for (unsigned int i = 0; i<10; ++i) { + XResizeWindow(dpy,_window,dimx,dimy); + XGetWindowAttributes(dpy,_window,&attr); + if (attr.width==(int)dimx && attr.height==(int)dimy) break; + cimg::wait(5,&_timer); + } + } + if (_width!=dimx || _height!=dimy) switch (cimg::X11_attr().nb_bits) { + case 8 : { unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + case 16 : { unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + default : { unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } + } + _window_width = _width = dimx; _window_height = _height = dimy; + cimg_unlock_display(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - _width)/2,(screen_height() - _height)/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height* + (cimg::X11_attr().nb_bits==8?1:(cimg::X11_attr().nb_bits==16?2:4)); + void *image_data = std::malloc(buf_size); + std::memcpy(image_data,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,image_data,buf_size); + std::free(image_data); + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + cimg_lock_display(); + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + _map_window(); + cimg_unlock_display(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (_is_fullscreen) _desinit_fullscreen(); + XUnmapWindow(dpy,_window); + _window_x = _window_y = cimg::type::min(); + _is_closed = true; + cimg_unlock_display(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + show(); + if (_window_x!=posx || _window_y!=posy) { + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XMoveWindow(dpy,_window,posx,posy); + _window_x = posx; + _window_y = posy; + cimg_unlock_display(); + } + _is_moved = false; + return paint(); + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XUndefineCursor(dpy,_window); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + static const char pix_data[8] = { 0 }; + XColor col; + col.red = col.green = col.blue = 0; + Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8); + Cursor cur = XCreatePixmapCursor(dpy,pix,pix,&col,&col,0,0); + XFreePixmap(dpy,pix); + XDefineCursor(dpy,_window,cur); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XWarpPointer(dpy,0L,_window,0,0,0,0,posx,posy); + _mouse_x = posx; _mouse_y = posy; + _is_moved = false; + XSync(dpy,0); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XStoreName(dpy,_window,tmp); + cimg_unlock_display(); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(false); + } + + CImgDisplay& paint(const bool wait_expose=true) { + if (is_empty()) return *this; + cimg_lock_display(); + _paint(wait_expose); + cimg_unlock_display(); + return *this; + } + + template + CImgDisplay& render(const CImg& img, const bool flag8=false) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + if (cimg::X11_attr().nb_bits==8 && (img._width!=_width || img._height!=_height)) + return render(img.get_resize(_width,_height,1,-100,1)); + if (cimg::X11_attr().nb_bits==8 && !flag8 && img._spectrum==3) { + static const CImg::ucharT> default_colormap = CImg::ucharT>::default_LUT256(); + return render(img.get_index(default_colormap,1,false)); + } + + const T + *data1 = img._data, + *data2 = (img._spectrum>1)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>2)?img.data(0,0,0,2):data1; + + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + cimg_lock_display(); + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, no normalization + _set_colormap(_colormap,img._spectrum); + unsigned char + *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height], + *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + (*ptrd++) = (unsigned char)*(data1++); + break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, no normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (G>>1); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (G<<5) | (G>>1); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, no normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | + (unsigned char)*(data3++); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data3++)<<24) | ((unsigned char)*(data2++)<<16) | + ((unsigned char)*(data1++)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = 0; + ptrd[3] = 0; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = 0; + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = (unsigned char)*(data2++); + ptrd[3] = (unsigned char)*(data3++); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)*(data3++); + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { _min = (float)cimg::type::min(); _max = (float)cimg::type::max(); } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.f); + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, with normalization + _set_colormap(_colormap,img._spectrum); + unsigned char *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char R = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = R; + } break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, with normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (val>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (G<<5) | (val>>3); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, with normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<24) | (val<<16) | (val<<8); + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8) | + (unsigned char)((*(data3++) - _min)*mm); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data3++) - _min)*mm)<<24) | + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = 0; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = val; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = val; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[3] = (unsigned char)((*(data3++) - _min)*mm); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)((*(data3++) - _min)*mm); + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } + cimg_unlock_display(); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + img.assign(); + Display *dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException("CImgDisplay::screenshot(): Failed to open X11 display."); + } + Window root = DefaultRootWindow(dpy); + XWindowAttributes gwa; + XGetWindowAttributes(dpy,root,&gwa); + const int width = gwa.width, height = gwa.height; + int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1; + if (_x0>_x1) cimg::swap(_x0,_x1); + if (_y0>_y1) cimg::swap(_y0,_y1); + + XImage *image = 0; + if (_x1>=0 && _x0=0 && _y0red_mask, + green_mask = image->green_mask, + blue_mask = image->blue_mask; + img.assign(image->width,image->height,1,3); + T *pR = img.data(0,0,0,0), *pG = img.data(0,0,0,1), *pB = img.data(0,0,0,2); + cimg_forXY(img,x,y) { + const unsigned long pixel = XGetPixel(image,x,y); + *(pR++) = (T)((pixel & red_mask)>>16); + *(pG++) = (T)((pixel & green_mask)>>8); + *(pB++) = (T)(pixel & blue_mask); + } + XDestroyImage(image); + } + } + if (!cimg::X11_attr().display) XCloseDisplay(dpy); + cimg_unlock_display(); + if (img.is_empty()) + throw CImgDisplayException("CImgDisplay::screenshot(): Failed to take screenshot " + "with coordinates (%d,%d)-(%d,%d).", + x0,y0,x1,y1); + } + + template + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned char *ptrs = (unsigned char*)_data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + switch (cimg::X11_attr().nb_bits) { + case 8 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = *(ptrs++); + *(data1++) = (T)(val&0xe0); + *(data2++) = (T)((val&0x1c)<<3); + *(data3++) = (T)(val<<6); + } + } break; + case 16 : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val0&0xf8); + *(data2++) = (T)((val0<<5) | ((val1&0xe0)>>5)); + *(data3++) = (T)(val1<<3); + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned short + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val1&0xf8); + *(data2++) = (T)((val1<<5) | ((val0&0xe0)>>5)); + *(data3++) = (T)(val0<<3); + } + } break; + default : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ++ptrs; + *(data1++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data3++) = (T)ptrs[2]; + ptrs+=3; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + *(data3++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data1++) = (T)ptrs[2]; + ptrs+=3; + ++ptrs; + } + } + } + return *this; + } + + // Windows-based implementation. + //------------------------------- +#elif cimg_display==2 + + bool _is_mouse_tracked, _is_cursor_visible; + HANDLE _thread, _is_created, _mutex; + HWND _window, _background_window; + CLIENTCREATESTRUCT _ccs; + unsigned int *_data; + DEVMODE _curr_mode; + BITMAPINFO _bmi; + HDC _hdc; + + static int screen_width() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsWidth; + } + + static int screen_height() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsHeight; + } + + static void wait_all() { + WaitForSingleObject(cimg::Win32_attr().wait_event,INFINITE); + } + + static LRESULT APIENTRY _handle_events(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { +#ifdef _WIN64 + CImgDisplay *const disp = (CImgDisplay*)GetWindowLongPtr(window,GWLP_USERDATA); +#else + CImgDisplay *const disp = (CImgDisplay*)GetWindowLong(window,GWL_USERDATA); +#endif + MSG st_msg; + switch (msg) { + case WM_CLOSE : + disp->_mouse_x = disp->_mouse_y = -1; + disp->_window_x = disp->_window_y = cimg::type::min(); + disp->set_button().set_key(0).set_key(0,false)._is_closed = true; + ReleaseMutex(disp->_mutex); + ShowWindow(disp->_window,SW_HIDE); + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + return 0; + case WM_SIZE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam); + if (nw && nh && (nw!=disp->_width || nh!=disp->_height)) { + disp->_window_width = nw; + disp->_window_height = nh; + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_resized = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_MOVE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const int nx = (int)(short)(LOWORD(lParam)), ny = (int)(short)(HIWORD(lParam)); + if (nx!=disp->_window_x || ny!=disp->_window_y) { + disp->_window_x = nx; + disp->_window_y = ny; + disp->_is_moved = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_PAINT : + disp->paint(); + cimg_lock_display(); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE_WIN)>=0); + cimg_unlock_display(); + break; + case WM_ERASEBKGND : + // return 0; + break; + case WM_KEYDOWN : + disp->set_key((unsigned int)wParam); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_KEYUP : + disp->set_key((unsigned int)wParam,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MOUSEMOVE : { + while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE)) {} + disp->_mouse_x = LOWORD(lParam); + disp->_mouse_y = HIWORD(lParam); +#if (_WIN32_WINNT>=0x0400) && !defined(NOTRACKMOUSEEVENT) + if (!disp->_is_mouse_tracked) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = disp->_window; + if (TrackMouseEvent(&tme)) disp->_is_mouse_tracked = true; + } +#endif + if (disp->_mouse_x<0 || disp->_mouse_y<0 || disp->_mouse_x>=disp->width() || disp->_mouse_y>=disp->height()) + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + cimg_lock_display(); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE_WIN)>=0); + cimg_unlock_display(); + } break; + case WM_MOUSELEAVE : { + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_mouse_tracked = false; + cimg_lock_display(); + while (ShowCursor(TRUE)<0) {} + cimg_unlock_display(); + } break; + case WM_LBUTTONDOWN : + disp->set_button(1); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONDOWN : + disp->set_button(2); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONDOWN : + disp->set_button(3); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_LBUTTONUP : + disp->set_button(1,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONUP : + disp->set_button(2,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONUP : + disp->set_button(3,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case 0x020A : // WM_MOUSEWHEEL: + disp->set_wheel((int)((short)HIWORD(wParam))/120); + SetEvent(cimg::Win32_attr().wait_event); + } + return DefWindowProc(window,msg,wParam,lParam); + } + + static DWORD WINAPI _events_thread(void* arg) { + CImgDisplay *const disp = (CImgDisplay*)(((void**)arg)[0]); + const char *const title = (const char*)(((void**)arg)[1]); + MSG msg; + delete[] (void**)arg; + disp->_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + disp->_bmi.bmiHeader.biWidth = disp->width(); + disp->_bmi.bmiHeader.biHeight = -disp->height(); + disp->_bmi.bmiHeader.biPlanes = 1; + disp->_bmi.bmiHeader.biBitCount = 32; + disp->_bmi.bmiHeader.biCompression = BI_RGB; + disp->_bmi.bmiHeader.biSizeImage = 0; + disp->_bmi.bmiHeader.biXPelsPerMeter = 1; + disp->_bmi.bmiHeader.biYPelsPerMeter = 1; + disp->_bmi.bmiHeader.biClrUsed = 0; + disp->_bmi.bmiHeader.biClrImportant = 0; + disp->_data = new unsigned int[(size_t)disp->_width*disp->_height]; + if (!disp->_is_fullscreen) { // Normal window + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)disp->_width - 1; rect.bottom = (LONG)disp->_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int + border1 = (int)((rect.right - rect.left + 1 - disp->_width)/2), + border2 = (int)(rect.bottom - rect.top + 1 - disp->_height - border1), + ww = disp->width() + 2*border1, + wh = disp->height() + border1 + border2, + sw = CImgDisplay::screen_width(), + sh = CImgDisplay::screen_height(); + int + wx = (int)cimg::round(cimg::rand(0,sw - ww -1)), + wy = (int)cimg::round(cimg::rand(64,sh - wh - 65)); + if (wx + ww>=sw) wx = sw - ww; + if (wy + wh>=sh) wy = sh - wh; + if (wx<0) wx = 0; + if (wy<0) wy = 0; + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + (DWORD)(WS_OVERLAPPEDWINDOW | (disp->_is_closed?0:WS_VISIBLE)), + wx,wy,ww,wh,0,0,0,&(disp->_ccs)); + if (!disp->_is_closed) { + GetWindowRect(disp->_window,&rect); + disp->_window_x = rect.left; + disp->_window_y = rect.top; + } else disp->_window_x = disp->_window_y = cimg::type::min(); + } else { // Fullscreen window + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + (DWORD)(WS_POPUP | (disp->_is_closed?0:WS_VISIBLE)), + (int)(sx - disp->_width)/2, + (int)(sy - disp->_height)/2, + disp->width(),disp->height(),0,0,0,&(disp->_ccs)); + disp->_window_x = disp->_window_y = 0; + } + SetForegroundWindow(disp->_window); + disp->_hdc = GetDC(disp->_window); + disp->_window_width = disp->_width; + disp->_window_height = disp->_height; + disp->flush(); +#ifdef _WIN64 + SetWindowLongPtr(disp->_window,GWLP_USERDATA,(LONG_PTR)disp); + SetWindowLongPtr(disp->_window,GWLP_WNDPROC,(LONG_PTR)_handle_events); +#else + SetWindowLong(disp->_window,GWL_USERDATA,(LONG)disp); + SetWindowLong(disp->_window,GWL_WNDPROC,(LONG)_handle_events); +#endif + SetEvent(disp->_is_created); + while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg); + return 0; + } + + CImgDisplay& _update_window_pos() { + if (_is_closed) _window_x = _window_y = cimg::type::min(); + else { + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)_width - 1; rect.bottom = (LONG)_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + GetWindowRect(_window,&rect); + _window_x = rect.left; + _window_y = rect.top; + } + return *this; + } + + void _init_fullscreen() { + _background_window = 0; + if (!_is_fullscreen || _is_closed) _curr_mode.dmSize = 0; + else { + DEVMODE mode; + unsigned int imode = 0, ibest = 0, bestbpp = 0, bw = ~0U, bh = ~0U; + for (mode.dmSize = sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(0,imode,&mode); ++imode) { + const unsigned int nw = mode.dmPelsWidth, nh = mode.dmPelsHeight; + if (nw>=_width && nh>=_height && mode.dmBitsPerPel>=bestbpp && nw<=bw && nh<=bh) { + bestbpp = mode.dmBitsPerPel; + ibest = imode; + bw = nw; bh = nh; + } + } + if (bestbpp) { + _curr_mode.dmSize = sizeof(DEVMODE); _curr_mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&_curr_mode); + EnumDisplaySettings(0,ibest,&mode); + ChangeDisplaySettings(&mode,0); + } else _curr_mode.dmSize = 0; + + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + if (sx!=_width || sy!=_height) { + CLIENTCREATESTRUCT background_ccs = { 0,0 }; + _background_window = CreateWindowA("MDICLIENT","",WS_POPUP | WS_VISIBLE, + 0,0,(int)sx,(int)sy,0,0,0,&background_ccs); + SetForegroundWindow(_background_window); + } + } + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + if (_background_window) DestroyWindow(_background_window); + _background_window = 0; + if (_curr_mode.dmSize) ChangeDisplaySettings(&_curr_mode,0); + _is_fullscreen = false; + } + + CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous window if existing + if (!is_empty()) assign(); + + // Set display variables + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = cimg::type::min(); + _is_closed = closed_flag; + _is_cursor_visible = true; + _is_mouse_tracked = false; + _title = tmp_title; + flush(); + if (_is_fullscreen) _init_fullscreen(); + + // Create event thread + void *const arg = (void*)(new void*[2]); + ((void**)arg)[0] = (void*)this; + ((void**)arg)[1] = (void*)_title; + _mutex = CreateMutex(0,FALSE_WIN,0); + _is_created = CreateEvent(0,FALSE_WIN,FALSE_WIN,0); + _thread = CreateThread(0,0,_events_thread,arg,0,0); + WaitForSingleObject(_is_created,INFINITE); + return *this; + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + DestroyWindow(_window); + TerminateThread(_thread,0); + delete[] _data; + delete[] _title; + _data = 0; + _title = 0; + if (_is_fullscreen) _desinit_fullscreen(); + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = cimg::type::min(); + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,sizeof(unsigned int)*_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,sizeof(unsigned int)*_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign((unsigned int)nwidth,(unsigned int)nheight); + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*_width/100), + tmpdimy = (nheight>0)?nheight:(-nheight*_height/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + if (_window_width!=dimx || _window_height!=dimy) { + RECT rect; rect.left = rect.top = 0; rect.right = (LONG)dimx - 1; rect.bottom = (LONG)dimy - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1; + SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS); + } + if (_width!=dimx || _height!=dimy) { + unsigned int *const ndata = new unsigned int[dimx*dimy]; + if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy); + else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy); + delete[] _data; + _data = ndata; + _bmi.bmiHeader.biWidth = (LONG)dimx; + _bmi.bmiHeader.biHeight = -(int)dimy; + _width = dimx; + _height = dimy; + } + _window_width = dimx; _window_height = dimy; + show(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - width())/2,(screen_height() - height())/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*4; + void *odata = std::malloc(buf_size); + if (odata) { + std::memcpy(odata,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,odata,buf_size); + std::free(odata); + } + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + ShowWindow(_window,SW_SHOW); + _update_window_pos(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + _is_closed = true; + if (_is_fullscreen) _desinit_fullscreen(); + ShowWindow(_window,SW_HIDE); + _window_x = _window_y = cimg::type::min(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + if (_window_x!=posx || _window_y!=posy) { + SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER); + _window_x = posx; + _window_y = posy; + } + show(); + _is_moved = false; + return *this; + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = true; + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = false; + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed || posx<0 || posy<0) return *this; + if (!_is_closed) { + _update_window_pos(); + const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy); + if (res) { _mouse_x = posx; _mouse_y = posy; } + } + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + SetWindowTextA(_window, tmp); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(); + } + + CImgDisplay& paint() { + if (_is_closed) return *this; + WaitForSingleObject(_mutex,INFINITE); + SetDIBitsToDevice(_hdc,0,0,_width,_height,0,0,0,_height,_data,&_bmi,DIB_RGB_COLORS); + ReleaseMutex(_mutex); + return *this; + } + + template + CImgDisplay& render(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + + const T + *data1 = img._data, + *data2 = (img._spectrum>=2)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>=3)?img.data(0,0,0,2):data1; + + WaitForSingleObject(_mutex,INFINITE); + unsigned int + *const ndata = (img._width==_width && img._height==_height)?_data: + new unsigned int[(size_t)img._width*img._height], + *ptrd = ndata; + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { + _min = (float)cimg::type::min(); + _max = (float)cimg::type::max(); + } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.f); + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } + if (ndata!=_data) { _render_resize(ndata,img._width,img._height,_data,_width,_height); delete[] ndata; } + ReleaseMutex(_mutex); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& img) { + img.assign(); + HDC hScreen = GetDC(GetDesktopWindow()); + if (hScreen) { + const int + width = GetDeviceCaps(hScreen,HORZRES), + height = GetDeviceCaps(hScreen,VERTRES); + int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1; + if (_x0>_x1) cimg::swap(_x0,_x1); + if (_y0>_y1) cimg::swap(_y0,_y1); + if (_x1>=0 && _x0=0 && _y0 + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned int *ptrs = _data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned int val = *(ptrs++); + *(data1++) = (T)(unsigned char)(val>>16); + *(data2++) = (T)(unsigned char)((val>>8)&0xFF); + *(data3++) = (T)(unsigned char)(val&0xFF); + } + return *this; + } +#endif + + //@} + }; // struct CImgDisplay { ... + + /* + #-------------------------------------- + # + # + # + # Definition of the CImg structure + # + # + # + #-------------------------------------- + */ + + //! Class representing an image (up to 4 dimensions wide), each pixel being of type \c T. + /** + This is the main class of the %CImg Library. It declares and constructs + an image, allows access to its pixel values, and is able to perform various image operations. + + \par Image representation + + A %CImg image is defined as an instance of the container \c CImg, which contains a regular grid of pixels, + each pixel value being of type \c T. The image grid can have up to 4 dimensions: width, height, depth + and number of channels. + Usually, the three first dimensions are used to describe spatial coordinates (x,y,z), + while the number of channels is rather used as a vector-valued dimension + (it may describe the R,G,B color channels for instance). + If you need a fifth dimension, you can use image lists \c CImgList rather than simple images \c CImg. + + Thus, the \c CImg class is able to represent volumetric images of vector-valued pixels, + as well as images with less dimensions (1D scalar signal, 2D color images, ...). + Most member functions of the class CImg<\c T> are designed to handle this maximum case of (3+1) dimensions. + + Concerning the pixel value type \c T: + fully supported template types are the basic C++ types: unsigned char, char, short, unsigned int, int, + unsigned long, long, float, double, ... . + Typically, fast image display can be done using CImg images, + while complex image processing algorithms may be rather coded using CImg or CImg + images that have floating-point pixel values. The default value for the template T is \c float. + Using your own template types may be possible. However, you will certainly have to define the complete set + of arithmetic and logical operators for your class. + + \par Image structure + + The \c CImg structure contains \e six fields: + - \c _width defines the number of \a columns of the image (size along the X-axis). + - \c _height defines the number of \a rows of the image (size along the Y-axis). + - \c _depth defines the number of \a slices of the image (size along the Z-axis). + - \c _spectrum defines the number of \a channels of the image (size along the C-axis). + - \c _data defines a \a pointer to the \a pixel \a data (of type \c T). + - \c _is_shared is a boolean that tells if the memory buffer \c data is shared with + another image. + + You can access these fields publicly although it is recommended to use the dedicated functions + width(), height(), depth(), spectrum() and ptr() to do so. + Image dimensions are not limited to a specific range (as long as you got enough available memory). + A value of \e 1 usually means that the corresponding dimension is \a flat. + If one of the dimensions is \e 0, or if the data pointer is null, the image is considered as \e empty. + Empty images should not contain any pixel data and thus, will not be processed by CImg member functions + (a CImgInstanceException will be thrown instead). + Pixel data are stored in memory, in a non interlaced mode (See \ref cimg_storage). + + \par Image declaration and construction + + Declaring an image can be done by using one of the several available constructors. + Here is a list of the most used: + + - Construct images from arbitrary dimensions: + - CImg img; declares an empty image. + - CImg img(128,128); declares a 128x128 greyscale image with + \c unsigned \c char pixel values. + - CImg img(3,3); declares a 3x3 matrix with \c double coefficients. + - CImg img(256,256,1,3); declares a 256x256x1x3 (color) image + (colors are stored as an image with three channels). + - CImg img(128,128,128); declares a 128x128x128 volumetric and greyscale image + (with \c double pixel values). + - CImg<> img(128,128,128,3); declares a 128x128x128 volumetric color image + (with \c float pixels, which is the default value of the template parameter \c T). + - \b Note: images pixels are not automatically initialized to 0. You may use the function \c fill() to + do it, or use the specific constructor taking 5 parameters like this: + CImg<> img(128,128,128,3,0); declares a 128x128x128 volumetric color image with all pixel values to 0. + + - Construct images from filenames: + - CImg img("image.jpg"); reads a JPEG color image from the file "image.jpg". + - CImg img("analyze.hdr"); reads a volumetric image (ANALYZE7.5 format) from the + file "analyze.hdr". + - \b Note: You need to install ImageMagick + to be able to read common compressed image formats (JPG,PNG, ...) (See \ref cimg_files_io). + + - Construct images from C-style arrays: + - CImg img(data_buffer,256,256); constructs a 256x256 greyscale image from a \c int* buffer + \c data_buffer (of size 256x256=65536). + - CImg img(data_buffer,256,256,1,3); constructs a 256x256 color image + from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others). + + The complete list of constructors can be found here. + + \par Most useful functions + + The \c CImg class contains a lot of functions that operates on images. + Some of the most useful are: + + - operator()(): Read or write pixel values. + - display(): displays the image in a new window. + **/ + template + struct CImg { + + unsigned int _width, _height, _depth, _spectrum; + bool _is_shared; + T *_data; + + //! Simple iterator type, to loop through each pixel value of an image instance. + /** + \note + - The \c CImg::iterator type is defined to be a T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + CImg img("reference.jpg"); // Load image from file + // Set all pixels to '0', with a CImg iterator. + for (CImg::iterator it = img.begin(), it::const_iterator type is defined to be a \c const \c T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + const CImg img("reference.jpg"); // Load image from file + float sum = 0; + // Compute sum of all pixel values, with a CImg iterator. + for (CImg::iterator it = img.begin(), it::value_type type of a \c CImg is defined to be a \c T. + - \c CImg::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + // Return 'dx*dy*dz*dc' as a 'size_t' and check no overflow occurs. + static size_t safe_size(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + if (!(dx && dy && dz && dc)) return 0; + size_t siz = (size_t)dx, osiz = siz; + if ((dy==1 || (siz*=dy)>osiz) && + ((osiz = siz), dz==1 || (siz*=dz)>osiz) && + ((osiz = siz), dc==1 || (siz*=dc)>osiz) && + ((osiz = siz), sizeof(T)==1 || (siz*sizeof(T))>osiz)) return siz; + throw CImgArgumentException("CImg<%s>::safe_size(): Specified size (%u,%u,%u,%u) overflows 'size_t'.", + pixel_type(),dx,dy,dz,dc); + } + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimg_plugin +#include cimg_plugin +#endif +#ifdef cimg_plugin1 +#include cimg_plugin1 +#endif +#ifdef cimg_plugin2 +#include cimg_plugin2 +#endif +#ifdef cimg_plugin3 +#include cimg_plugin3 +#endif +#ifdef cimg_plugin4 +#include cimg_plugin4 +#endif +#ifdef cimg_plugin5 +#include cimg_plugin5 +#endif +#ifdef cimg_plugin6 +#include cimg_plugin6 +#endif +#ifdef cimg_plugin7 +#include cimg_plugin7 +#endif +#ifdef cimg_plugin8 +#include cimg_plugin8 +#endif + + //@} + //--------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //--------------------------------------------------------- + + //! Destroy image. + /** + \note + - The pixel buffer data() is deallocated if necessary, e.g. for non-empty and non-shared image instances. + - Destroying an empty or shared image does nothing actually. + \warning + - When destroying a non-shared image, make sure that you will \e not operate on a remaining shared image + that shares its buffer with the destroyed instance, in order to avoid further invalid memory access + (to a deallocated buffer). + **/ + ~CImg() { + if (!_is_shared) delete[] _data; + } + + //! Construct empty image. + /** + \note + - An empty image has no pixel data and all of its dimensions width(), height(), depth(), spectrum() + are set to \c 0, as well as its pixel buffer pointer data(). + - An empty image may be re-assigned afterwards, e.g. with the family of + assign(unsigned int,unsigned int,unsigned int,unsigned int) methods, + or by operator=(const CImg&). In all cases, the type of pixels stays \c T. + - An empty image is never shared. + \par Example + \code + CImg img1, img2; // Construct two empty images + img1.assign(256,256,1,3); // Re-assign 'img1' to be a 256x256x1x3 (color) image + img2 = img1.get_rand(0,255); // Re-assign 'img2' to be a random-valued version of 'img1' + img2.assign(); // Re-assign 'img2' to be an empty image again + \endcode + **/ + CImg():_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {} + + //! Construct image with specified size. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \note + - It is able to create only \e non-shared images, and allocates thus a pixel buffer data() + for each constructed image instance. + - Setting one dimension \c size_x,\c size_y,\c size_z or \c size_c to \c 0 leads to the construction of + an \e empty image. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values during construction (e.g. with \c 0), use constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) instead. + \par Example + \code + CImg img1(256,256,1,3); // Construct a 256x256x1x3 (color) image, filled with garbage values + CImg img2(256,256,1,3,0); // Construct a 256x256x1x3 (color) image, filled with value '0' + \endcode + **/ + explicit CImg(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1): + _is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value Initialization value. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), + but it also fills the pixel buffer with the specified \c value. + \warning + - It cannot be used to construct a vector-valued image and initialize it with \e vector-valued pixels + (e.g. RGB vector, for color images). + For this task, you may use fillC() after construction. + **/ + CImg(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value): + _is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(value); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified sequence of integers \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be an \e integer). + \param value1 Second value of the initialization sequence (must be an \e integer). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \warning + - You must specify \e exactly \c size_x*\c size_y*\c size_z*\c size_c integers in the initialization sequence. + Otherwise, the constructor may crash or fill your image pixels with garbage. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image + 0,255,0,255, // Set the 4 values for the red component + 0,0,255,255, // Set the 4 values for the green component + 64,64,64,64); // Set the 4 values for the blue component + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _CImg_stdarg(img,a0,a1,N,t) { \ + size_t _siz = (size_t)N; \ + if (_siz--) { \ + va_list ap; \ + va_start(ap,a1); \ + T *ptrd = (img)._data; \ + *(ptrd++) = (T)a0; \ + if (_siz--) { \ + *(ptrd++) = (T)a1; \ + for ( ; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \ + } \ + va_end(ap); \ + } \ + } + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),int); + } + +#if cimg_use_cpp11==1 + //! Construct image with specified size and initialize pixel values from an initializer list of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... } + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param { value0, value1, ... } Initialization list + \param repeat_values Tells if the value filling process is repeated over the image. + + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image + { 0,255,0,255, // Set the 4 values for the red component + 0,0,255,255, // Set the 4 values for the green component + 64,64,64,64 }); // Set the 4 values for the blue component + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _cimg_constructor_cpp11(repeat_values) \ + auto it = values.begin(); \ + size_t siz = size(); \ + if (repeat_values) for (T *ptrd = _data; siz--; ) { \ + *(ptrd++) = (T)(*(it++)); if (it==values.end()) it = values.begin(); } \ + else { siz = std::min(siz,values.size()); for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); } + assign(size_x,size_y,size_z,size_c); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, + std::initializer_list values, + const bool repeat_values=true):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x); + _cimg_constructor_cpp11(repeat_values); + } + + //! Construct single channel 1D image with pixel values and width obtained from an initializer list of integers. + /** + Construct a new image instance of size \c width x \c 1 x \c 1 x \c 1, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... }. Image width is + given by the size of the initializer list. + \param { value0, value1, ... } Initialization list + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int) with height=1, depth=1, and spectrum=1, + but it also fills the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img = {10,20,30,20,10 }; // Construct a 5x1 image with one channel, and set its pixel values + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const std::initializer_list values): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(values.size(),1,1,1); + auto it = values.begin(); + unsigned int siz = _width; + for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); + } + + template + CImg& operator=(std::initializer_list values) { + _cimg_constructor_cpp11(siz>values.size()); + return *this; + } +#endif + + //! Construct image with specified size and initialize pixel values from a sequence of doubles. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initialize pixel values from the specified sequence of doubles \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be a \e double). + \param value1 Second value of the initialization sequence (must be a \e double). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...), but + takes a sequence of double values instead of integers. + \warning + - You must specify \e exactly \c dx*\c dy*\c dz*\c dc doubles in the initialization sequence. + Otherwise, the constructor may crash or fill your image with garbage. + For instance, the code below will probably crash on most platforms: + \code + const CImg img(2,2,1,1, 0.5,0.5,255,255); // FAIL: The two last arguments are 'int', not 'double'! + \endcode + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),double); + } + + //! Construct image with specified size and initialize pixel values from a value string. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified string \c values. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param values Value string describing the way pixel values are set. + \param repeat_values Tells if the value filling process is repeated over the image. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with values described in the value string \c values. + - Value string \c values may describe two different filling processes: + - Either \c values is a sequences of values assigned to the image pixels, as in "1,2,3,7,8,2". + In this case, set \c repeat_values to \c true to periodically fill the image with the value sequence. + - Either, \c values is a formula, as in "cos(x/10)*sin(y/20)". + In this case, parameter \c repeat_values is pointless. + - For both cases, specifying \c repeat_values is mandatory. + It disambiguates the possible overloading of constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) with \c T being a const char*. + - A \c CImgArgumentException is thrown when an invalid value string \c values is specified. + \par Example + \code + const CImg img1(129,129,1,3,"0,64,128,192,255",true), // Construct image from a value sequence + img2(129,129,1,3,"if(c==0,255*abs(cos(x/10)),1.8*y)",false); // Construct image from a formula + (img1,img2).display(); + \endcode + \image html ref_constructor2.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values):_is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(values,repeat_values); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified \c t* memory buffer. + \param values Pointer to the input memory buffer. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param is_shared Tells if input memory buffer must be shared by the current instance. + \note + - If \c is_shared is \c false, the image instance allocates its own pixel buffer, + and values from the specified input buffer are copied to the instance buffer. + If buffer types \c T and \c t are different, a regular static cast is performed during buffer copy. + - Otherwise, the image instance does \e not allocate a new buffer, and uses the input memory buffer as its + own pixel buffer. This case requires that types \c T and \c t are the same. Later, destroying such a shared + image will not deallocate the pixel buffer, this task being obviously charged to the initial buffer allocator. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - You must take care when operating on a shared image, since it may have an invalid pixel buffer pointer data() + (e.g. already deallocated). + \par Example + \code + unsigned char tab[256*256] = { 0 }; + CImg img1(tab,256,256,1,1,false), // Construct new non-shared image from buffer 'tab' + img2(tab,256,256,1,1,true); // Construct new shared-image from buffer 'tab' + tab[1024] = 255; // Here, 'img2' is indirectly modified, but not 'img1' + \endcode + **/ + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a (%u,%u,%u,%u) shared instance " + "from a (%s*) buffer (pixel types are different).", + cimg_instance, + size_x,size_y,size_z,size_c,CImg::pixel_type()); + } + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + + } + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = is_shared; + if (_is_shared) _data = const_cast(values); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy(_data,values,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from memory buffer with specified size and pixel ordering scheme. + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const axes_order):_data(0),_is_shared(false) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (values && siz) { + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = c; } + } + if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { + const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + int s0 = 0, s1 = 0, s2 = 0, s3 = 0; + const char *inv_order = 0; + switch (code) { + case 0x0123 : inv_order = "xyzc"; s0 = size_x; s1 = size_y; s2 = size_z; s3 = size_c; break; // xyzc + case 0x0132 : inv_order = "xyzc"; s0 = size_x; s1 = size_y; s2 = size_c; s3 = size_z; break; // xycz + case 0x0213 : inv_order = "xzyc"; s0 = size_x; s1 = size_z; s2 = size_y; s3 = size_c; break; // xzyc + case 0x0231 : inv_order = "xcyz"; s0 = size_x; s1 = size_z; s2 = size_c; s3 = size_y; break; // xzcy + case 0x0312 : inv_order = "xzcy"; s0 = size_x; s1 = size_c; s2 = size_y; s3 = size_z; break; // xcyz + case 0x0321 : inv_order = "xczy"; s0 = size_x; s1 = size_c; s2 = size_z; s3 = size_y; break; // xczy + case 0x1023 : inv_order = "yxzc"; s0 = size_y; s1 = size_x; s2 = size_z; s3 = size_c; break; // yxzc + case 0x1032 : inv_order = "yxcz"; s0 = size_y; s1 = size_x; s2 = size_c; s3 = size_z; break; // yxcz + case 0x1203 : inv_order = "zxyc"; s0 = size_y; s1 = size_z; s2 = size_x; s3 = size_c; break; // yzxc + case 0x1230 : inv_order = "cxyz"; s0 = size_y; s1 = size_z; s2 = size_c; s3 = size_x; break; // yzcx + case 0x1302 : inv_order = "zxcy"; s0 = size_y; s1 = size_c; s2 = size_x; s3 = size_z; break; // ycxz + case 0x1320 : inv_order = "cxzy"; s0 = size_y; s1 = size_c; s2 = size_z; s3 = size_x; break; // yczx + case 0x2013 : inv_order = "yzxc"; s0 = size_z; s1 = size_x; s2 = size_y; s3 = size_c; break; // zxyc + case 0x2031 : inv_order = "ycxz"; s0 = size_z; s1 = size_x; s2 = size_c; s3 = size_y; break; // zxcy + case 0x2103 : inv_order = "zyxc"; s0 = size_z; s1 = size_y; s2 = size_x; s3 = size_c; break; // zyxc + case 0x2130 : inv_order = "cyxz"; s0 = size_z; s1 = size_y; s2 = size_c; s3 = size_x; break; // zycx + case 0x2301 : inv_order = "zcxy"; s0 = size_z; s1 = size_c; s2 = size_x; s3 = size_y; break; // zcxy + case 0x2310 : inv_order = "czxy"; s0 = size_z; s1 = size_c; s2 = size_y; s3 = size_x; break; // zcyx + case 0x3012 : inv_order = "yzcx"; s0 = size_c; s1 = size_x; s2 = size_y; s3 = size_z; break; // cxyz + case 0x3021 : inv_order = "yczx"; s0 = size_c; s1 = size_x; s2 = size_z; s3 = size_y; break; // cxzy + case 0x3102 : inv_order = "zycx"; s0 = size_c; s1 = size_y; s2 = size_x; s3 = size_z; break; // cyxz + case 0x3120 : inv_order = "cyzx"; s0 = size_c; s1 = size_y; s2 = size_z; s3 = size_x; break; // cyzx + case 0x3201 : inv_order = "zcyx"; s0 = size_c; s1 = size_z; s2 = size_x; s3 = size_y; break; // czxy + case 0x3210 : inv_order = "czyx"; s0 = size_c; s1 = size_z; s2 = size_y; s3 = size_x; break; // czyx + } + CImg(values,s0,s1,s2,s3,true).get_permute_axes(inv_order).move_to(*this); + } else { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from reading an image file. + /** + Construct a new image instance with pixels of type \c T, and initialize pixel values with the data read from + an image file. + \param filename Filename, as a C-string. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it reads the image + dimensions and pixel values from the specified image file. + - The recognition of the image file format by %CImg higlhy depends on the tools installed on your system + and on the external libraries you used to link your code against. + - Considered pixel type \c T should better fit the file format specification, or data loss may occur during + file load (e.g. constructing a \c CImg from a float-valued image file). + - A \c CImgIOException is thrown when the specified \c filename cannot be read, or if the file format is not + recognized. + \par Example + \code + const CImg img("reference.jpg"); + img.display(); + \endcode + \image html ref_image.jpg + **/ + explicit CImg(const char *const filename):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(filename); + } + + //! Construct image copy. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance. + \param img Input image to copy. + \note + - Constructed copy has the same size width() x height() x depth() x spectrum() and pixel values as the + input image \c img. + - If input image \c img is \e shared and if types \c T and \c t are the same, the constructed copy is also + \e shared, and shares its pixel buffer with \c img. + Modifying a pixel value in the constructed copy will thus also modifies it in the input image \c img. + This behavior is needful to allow functions to return shared images. + - Otherwise, the constructed copy allocates its own pixel buffer, and copies pixel values from the input + image \c img into its buffer. The copied pixel values may be eventually statically casted if types \c T and + \c t are different. + - Constructing a copy from an image \c img when types \c t and \c T are the same is significantly faster than + with different types. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. not enough available memory). + **/ + template + CImg(const CImg& img):_is_shared(false) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image copy \specialization. + CImg(const CImg& img) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = img._is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Advanced copy constructor. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance, + while forcing the shared state of the constructed copy. + \param img Input image to copy. + \param is_shared Tells about the shared state of the constructed copy. + \note + - Similar to CImg(const CImg&), except that it allows to decide the shared state of + the constructed image, which does not depend anymore on the shared state of the input image \c img: + - If \c is_shared is \c true, the constructed copy will share its pixel buffer with the input image \c img. + For that case, the pixel types \c T and \c t \e must be the same. + - If \c is_shared is \c false, the constructed copy will allocate its own pixel buffer, whether the input + image \c img is shared or not. + - A \c CImgArgumentException is thrown when a shared copy is requested with different pixel types \c T and \c t. + **/ + template + CImg(const CImg& img, const bool is_shared):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a shared instance from a " + "CImg<%s> image (%u,%u,%u,%u,%p) (pixel types are different).", + cimg_instance, + CImg::pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data); + } + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Advanced copy constructor \specialization. + CImg(const CImg& img, const bool is_shared) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image with dimensions borrowed from another image. + /** + Construct a new image instance with pixels of type \c T, and size get from some dimensions of an existing + \c CImg instance. + \param img Input image from which dimensions are borrowed. + \param dimensions C-string describing the image size along the X,Y,Z and C-dimensions. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it takes the image dimensions + (\e not its pixel values) from an existing \c CImg instance. + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values (e.g. with \c 0), use constructor CImg(const CImg&,const char*,T) + instead. + \par Example + \code + const CImg img1(256,128,1,3), // 'img1' is a 256x128x1x3 image + img2(img1,"xyzc"), // 'img2' is a 256x128x1x3 image + img3(img1,"y,x,z,c"), // 'img3' is a 128x256x1x3 image + img4(img1,"c,x,y,3",0), // 'img4' is a 3x128x256x3 image (with pixels initialized to '0') + \endcode + **/ + template + CImg(const CImg& img, const char *const dimensions): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values. + /** + Construct a new image instance with pixels of type \c T, and size get from the dimensions of an existing + \c CImg instance, and set all pixel values to specified \c value. + \param img Input image from which dimensions are borrowed. + \param dimensions String describing the image size along the X,Y,Z and V-dimensions. + \param value Value used for initialization. + \note + - Similar to CImg(const CImg&,const char*), but it also fills the pixel buffer with the specified \c value. + **/ + template + CImg(const CImg& img, const char *const dimensions, const T& value): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions).fill(value); + } + + //! Construct image from a display window. + /** + Construct a new image instance with pixels of type \c T, as a snapshot of an existing \c CImgDisplay instance. + \param disp Input display window. + \note + - The width() and height() of the constructed image instance are the same as the specified \c CImgDisplay. + - The depth() and spectrum() of the constructed image instance are respectively set to \c 1 and \c 3 + (i.e. a 2D color image). + - The image pixels are read as 8-bits RGB values. + **/ + explicit CImg(const CImgDisplay &disp):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + disp.snapshot(*this); + } + + // Constructor and assignment operator for rvalue references (c++11). + // This avoids an additional image copy for methods returning new images. Can save RAM for big images ! +#if cimg_use_cpp11==1 + CImg(CImg&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + swap(img); + } + + CImg& operator=(CImg&& img) { + if (_is_shared) return assign(img); + return img.swap(*this); + } +#endif + + //! Construct empty image \inplace. + /** + In-place version of the default constructor CImg(). It simply resets the instance to an empty image. + **/ + CImg& assign() { + if (!_is_shared) delete[] _data; + _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; + return *this; + } + + //! Construct image with specified size \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (siz!=curr_siz) { + if (_is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from specified " + "image (%u,%u,%u,%u).", + cimg_instance, + size_x,size_y,size_z,size_c); + else { + delete[] _data; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + return *this; + } + + //! Construct image with specified size and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,T). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value) { + return assign(size_x,size_y,size_z,size_c).fill(value); + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),int); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a sequence of doubles \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,double,double,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,safe_size(size_x,size_y,size_z,size_c),double); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a value string \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,const char*,bool). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values) { + return assign(size_x,size_y,size_z,size_c).fill(values,repeat_values); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \inplace. + /** + In-place version of the constructor CImg(const t*,unsigned int,unsigned int,unsigned int,unsigned int). + **/ + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + assign(size_x,size_y,size_z,size_c); + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (values==_data && siz==curr_siz) return assign(size_x,size_y,size_z,size_c); + if (_is_shared || values + siz<_data || values>=_data + size()) { + assign(size_x,size_y,size_z,size_c); + if (_is_shared) std::memmove((void*)_data,(void*)values,siz*sizeof(T)); + else std::memcpy((void*)_data,(void*)values,siz*sizeof(T)); + } else { + T *new_data = 0; + try { new_data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy((void*)new_data,(void*)values,siz*sizeof(T)); + delete[] _data; _data = new_data; _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + } + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + if (is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from (%s*) buffer" + "(pixel types are different).", + cimg_instance, + CImg::pixel_type()); + return assign(values,size_x,size_y,size_z,size_c); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + const size_t siz = safe_size(size_x,size_y,size_z,size_c); + if (!values || !siz) return assign(); + if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); } + else { + if (!_is_shared) { + if (values + siz<_data || values>=_data + size()) assign(); + else cimg::warn(_cimg_instance + "assign(): Shared image instance has overlapping memory.", + cimg_instance); + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = true; + _data = const_cast(values); + } + return *this; + } + + //! Construct image from memory buffer with specified size and pixel ordering scheme. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const axes_order) { + CImg(values,size_x,size_y,size_z,size_c,axes_order).move_to(*this); + } + + //! Construct image from reading an image file \inplace. + /** + In-place version of the constructor CImg(const char*). + **/ + CImg& assign(const char *const filename) { + return load(filename); + } + + //! Construct image copy \inplace. + /** + In-place version of the constructor CImg(const CImg&). + **/ + template + CImg& assign(const CImg& img) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum); + } + + //! In-place version of the advanced copy constructor. + /** + In-place version of the constructor CImg(const CImg&,bool). + **/ + template + CImg& assign(const CImg& img, const bool is_shared) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum,is_shared); + } + + //! Construct image with dimensions borrowed from another image \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions) { + if (!dimensions || !*dimensions) return assign(img._width,img._height,img._depth,img._spectrum); + unsigned int siz[4] = { 0,1,1,1 }, k = 0; + CImg item(256); + for (const char *s = dimensions; *s && k<4; ++k) { + if (cimg_sscanf(s,"%255[^0-9%xyzvwhdcXYZVWHDC]",item._data)>0) s+=std::strlen(item); + if (*s) { + unsigned int val = 0; char sep = 0; + if (cimg_sscanf(s,"%u%c",&val,&sep)>0) { + if (sep=='%') siz[k] = val*(k==0?_width:k==1?_height:k==2?_depth:_spectrum)/100; + else siz[k] = val; + while (*s>='0' && *s<='9') ++s; + if (sep=='%') ++s; + } else switch (cimg::lowercase(*s)) { + case 'x' : case 'w' : siz[k] = img._width; ++s; break; + case 'y' : case 'h' : siz[k] = img._height; ++s; break; + case 'z' : case 'd' : siz[k] = img._depth; ++s; break; + case 'c' : case 's' : siz[k] = img._spectrum; ++s; break; + default : + throw CImgArgumentException(_cimg_instance + "assign(): Invalid character '%c' detected in specified dimension string '%s'.", + cimg_instance, + *s,dimensions); + } + } + } + return assign(siz[0],siz[1],siz[2],siz[3]); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*,T). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions, const T& value) { + return assign(img,dimensions).fill(value); + } + + //! Construct image from a display window \inplace. + /** + In-place version of the constructor CImg(const CImgDisplay&). + **/ + CImg& assign(const CImgDisplay &disp) { + disp.snapshot(*this); + return *this; + } + + //! Construct empty image \inplace. + /** + Equivalent to assign(). + \note + - It has been defined for compatibility with STL naming conventions. + **/ + CImg& clear() { + return assign(); + } + + //! Transfer content of an image instance into another one. + /** + Transfer the dimensions and the pixel buffer content of an image instance into another one, + and replace instance by an empty image. It avoids the copy of the pixel buffer + when possible. + \param img Destination image. + \note + - Pixel types \c T and \c t of source and destination images can be different, though the process is + designed to be instantaneous when \c T and \c t are the same. + \par Example + \code + CImg src(256,256,1,3,0), // Construct a 256x256x1x3 (color) image filled with value '0' + dest(16,16); // Construct a 16x16x1x1 (scalar) image + src.move_to(dest); // Now, 'src' is empty and 'dest' is the 256x256x1x3 image + \endcode + **/ + template + CImg& move_to(CImg& img) { + img.assign(*this); + assign(); + return img; + } + + //! Transfer content of an image instance into another one \specialization. + CImg& move_to(CImg& img) { + if (_is_shared || img._is_shared) img.assign(*this); + else swap(img); + assign(); + return img; + } + + //! Transfer content of an image instance into a new image in an image list. + /** + Transfer the dimensions and the pixel buffer content of an image instance + into a newly inserted image at position \c pos in specified \c CImgList instance. + \param list Destination list. + \param pos Position of the newly inserted image in the list. + \note + - When optional parameter \c pos is omitted, the image instance is transferred as a new + image at the end of the specified \c list. + - It is convenient to sequentially insert new images into image lists, with no + additional copies of memory buffer. + \par Example + \code + CImgList list; // Construct an empty image list + CImg img("reference.jpg"); // Read image from filename + img.move_to(list); // Transfer image content as a new item in the list (no buffer copy) + \endcode + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos=~0U) { + const unsigned int npos = pos>list._width?list._width:pos; + move_to(list.insert(1,npos)[npos]); + return list; + } + + //! Swap fields of two image instances. + /** + \param img Image to swap fields with. + \note + - It can be used to interchange the content of two images in a very fast way. Can be convenient when dealing + with algorithms requiring two swapping buffers. + \par Example + \code + CImg img1("lena.jpg"), + img2("milla.jpg"); + img1.swap(img2); // Now, 'img1' is 'milla' and 'img2' is 'lena' + \endcode + **/ + CImg& swap(CImg& img) { + cimg::swap(_width,img._width,_height,img._height,_depth,img._depth,_spectrum,img._spectrum); + cimg::swap(_data,img._data); + cimg::swap(_is_shared,img._is_shared); + return img; + } + + //! Return a reference to an empty image. + /** + \note + This function is useful mainly to declare optional parameters having type \c CImg in functions prototypes, + e.g. + \code + void f(const int x=0, const int y=0, const CImg& img=CImg::empty()); + \endcode + **/ + static CImg& empty() { + static CImg _empty; + return _empty.assign(); + } + + //! Return a reference to an empty image \const. + static const CImg& const_empty() { + static const CImg _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Access to a pixel value. + /** + Return a reference to a located pixel value of the image instance, + being possibly \e const, whether the image instance is \e const or not. + This is the standard method to get/set pixel values in \c CImg images. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Range of pixel coordinates start from (0,0,0,0) to + (width() - 1,height() - 1,depth() - 1,spectrum() - 1). + - Due to the particular arrangement of the pixel buffers defined in %CImg, you can omit one coordinate if the + corresponding dimension is equal to \c 1. + For instance, pixels of a 2D image (depth() equal to \c 1) can be accessed by img(x,y,c) instead of + img(x,y,0,c). + \warning + - There is \e no boundary checking done in this operator, to make it as fast as possible. + You \e must take care of out-of-bounds access by yourself, if necessary. + For debugging purposes, you may want to define macro \c 'cimg_verbosity'>=3 to enable additional boundary + checking operations in this operator. In that case, warning messages will be printed on the error output + when accessing out-of-bounds pixels. + \par Example + \code + CImg img(100,100,1,3,0); // Construct a 100x100x1x3 (color) image with pixels set to '0' + const float + valR = img(10,10,0,0), // Read red value at coordinates (10,10) + valG = img(10,10,0,1), // Read green value at coordinates (10,10) + valB = img(10,10,2), // Read blue value at coordinates (10,10) (Z-coordinate can be omitted) + avg = (valR + valG + valB)/3; // Compute average pixel value + img(10,10,0) = img(10,10,1) = img(10,10,2) = avg; // Replace the color pixel (10,10) by the average grey value + \endcode + **/ +#if cimg_verbosity>=3 + T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (!_data || off>=size()) { + cimg::warn(_cimg_instance + "operator(): Invalid pixel request, at coordinates (%d,%d,%d,%d) [offset=%u].", + cimg_instance, + (int)x,(int)y,(int)z,(int)c,off); + return *_data; + } + else return _data[off]; + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->operator()(x,y,z,c); + } + + //! Access to a pixel value. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param wh Precomputed offset, must be equal to width()*\ref height(). + \param whd Precomputed offset, must be equal to width()*\ref height()*\ref depth(). + \note + - Similar to (but faster than) operator()(). + It uses precomputed offsets to optimize memory access. You may use it to optimize + the reading/writing of several pixel values in the same image (e.g. in a loop). + **/ + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) const { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } +#else + T& operator()(const unsigned int x) { + return _data[x]; + } + + const T& operator()(const unsigned int x) const { + return _data[x]; + } + + T& operator()(const unsigned int x, const unsigned int y) { + return _data[x + y*_width]; + } + + const T& operator()(const unsigned int x, const unsigned int y) const { + return _data[x + y*_width]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) { + return _data[x + y*_width + z*wh]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) const { + return _data[x + y*_width + z*wh]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) { + return _data[x + y*_width + z*wh + c*whd]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) const { + return _data[x + y*_width + z*wh + c*whd]; + } +#endif + + //! Implicitly cast an image into a \c T*. + /** + Implicitly cast a \c CImg instance into a \c T* or \c const \c T* pointer, whether the image instance + is \e const or not. The returned pointer points on the first value of the image pixel buffer. + \note + - It simply returns the pointer data() to the pixel buffer. + - This implicit conversion is convenient to test the empty state of images (data() being \c 0 in this case), e.g. + \code + CImg img1(100,100), img2; // 'img1' is a 100x100 image, 'img2' is an empty image + if (img1) { // Test succeeds, 'img1' is not an empty image + if (!img2) { // Test succeeds, 'img2' is an empty image + std::printf("'img1' is not empty, 'img2' is empty."); + } + } + \endcode + - It also allows to use brackets to access pixel values, without need for a \c CImg::operator[](), e.g. + \code + CImg img(100,100); + const float value = img[99]; // Access to value of the last pixel on the first row + img[510] = 255; // Set pixel value at (10,5) + \endcode + **/ + operator T*() { + return _data; + } + + //! Implicitly cast an image into a \c T* \const. + operator const T*() const { + return _data; + } + + //! Assign a value to all image pixels. + /** + Assign specified \c value to each pixel value of the image instance. + \param value Value that will be assigned to image pixels. + \note + - The image size is never modified. + - The \c value may be casted to pixel type \c T if necessary. + \par Example + \code + CImg img(100,100); // Declare image (with garbage values) + img = 0; // Set all pixel values to '0' + img = 1.2; // Set all pixel values to '1' (cast of '1.2' as a 'char') + \endcode + **/ + CImg& operator=(const T& value) { + return fill(value); + } + + //! Assign pixels values from a specified expression. + /** + Initialize all pixel values from the specified string \c expression. + \param expression Value string describing the way pixel values are set. + \note + - String parameter \c expression may describe different things: + - If \c expression is a list of values (as in \c "1,2,3,8,3,2"), or a formula (as in \c "(x*y)%255"), + the pixel values are set from specified \c expression and the image size is not modified. + - If \c expression is a filename (as in \c "reference.jpg"), the corresponding image file is loaded and + replace the image instance. The image size is modified if necessary. + \par Example + \code + CImg img1(100,100), img2(img1), img3(img1); // Declare 3 scalar images 100x100 with uninitialized values + img1 = "0,50,100,150,200,250,200,150,100,50"; // Set pixel values of 'img1' from a value sequence + img2 = "10*((x*y)%25)"; // Set pixel values of 'img2' from a formula + img3 = "reference.jpg"; // Set pixel values of 'img3' from a file (image size is modified) + (img1,img2,img3).display(); + \endcode + \image html ref_operator_eq.jpg + **/ + CImg& operator=(const char *const expression) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + _fill(expression,true,1,0,0,"operator=",0); + } catch (CImgException&) { + cimg::exception_mode(omode); + load(expression); + } + cimg::exception_mode(omode); + return *this; + } + + //! Copy an image into the current image instance. + /** + Similar to the in-place copy constructor assign(const CImg&). + **/ + template + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy an image into the current image instance \specialization. + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy the content of a display window to the current image instance. + /** + Similar to assign(const CImgDisplay&). + **/ + CImg& operator=(const CImgDisplay& disp) { + disp.snapshot(*this); + return *this; + } + + //! In-place addition operator. + /** + Add specified \c value to all pixels of an image instance. + \param value Value to add. + \note + - Resulting pixel values are casted to fit the pixel type \c T. + For instance, adding \c 0.2 to a \c CImg is possible but does nothing indeed. + - Overflow values are treated as with standard C++ numeric types. For instance, + \code + CImg img(100,100,1,1,255); // Construct a 100x100 image with pixel values '255' + img+=1; // Add '1' to each pixels -> Overflow + // here all pixels of image 'img' are equal to '0'. + \endcode + - To prevent value overflow, you may want to consider pixel type \c T as \c float or \c double, + and use cut() after addition. + \par Example + \code + CImg img1("reference.jpg"); // Load a 8-bits RGB image (values in [0,255]) + CImg img2(img1); // Construct a float-valued copy of 'img1' + img2+=100; // Add '100' to pixel values -> goes out of [0,255] but no problems with floats + img2.cut(0,255); // Cut values in [0,255] to fit the 'unsigned char' constraint + img1 = img2; // Rewrite safe result in 'unsigned char' version 'img1' + const CImg img3 = (img1 + 100).cut(0,255); // Do the same in a more simple and elegant way + (img1,img2,img3).display(); + \endcode + \image html ref_operator_plus.jpg + **/ + template + CImg& operator+=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr + value,524288); + return *this; + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the specified string \c expression. + \param expression Value string describing the way pixel values are added. + \note + - Similar to operator=(const char*), except that it adds values to the pixels of the current image instance, + instead of assigning them. + **/ + CImg& operator+=(const char *const expression) { + return *this+=(+*this)._fill(expression,true,1,0,0,"operator+=",this); + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the values of the input image \c img. + \param img Input image to add. + \note + - The size of the image instance is never modified. + - It is not mandatory that input image \c img has the same size as the image instance. + If less values are available in \c img, then the values are added periodically. For instance, adding one + WxH scalar image (spectrum() equal to \c 1) to one WxH color image (spectrum() equal to \c 3) + means each color channel will be incremented with the same values at the same locations. + \par Example + \code + CImg img1("reference.jpg"); // Load a RGB color image (img1.spectrum()==3) + // Construct a scalar shading (img2.spectrum()==1). + const CImg img2(img1.width(),img.height(),1,1,"255*(x/w)^2"); + img1+=img2; // Add shading to each channel of 'img1' + img1.cut(0,255); // Prevent [0,255] overflow + (img2,img1).display(); + \endcode + \image html ref_operator_plus1.jpg + **/ + template + CImg& operator+=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this+=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator++() { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr + 1,524288); + return *this; + } + + //! In-place increment operator (postfix). + /** + Add \c 1 to all image pixels, and return a new copy of the initial (pre-incremented) image instance. + \note + - Use the prefixed version operator++() if you don't need a copy of the initial + (pre-incremented) image instance, since a useless image copy may be expensive in terms of memory usage. + **/ + CImg operator++(int) { + const CImg copy(*this,false); + ++*this; + return copy; + } + + //! Return a non-shared copy of the image instance. + /** + \note + - Use this operator to ensure you get a non-shared copy of an image instance with same pixel type \c T. + Indeed, the usual copy constructor CImg(const CImg&) returns a shared copy of a shared input image, + and it may be not desirable to work on a regular copy (e.g. for a resize operation) if you have no + information about the shared state of the input image. + - Writing \c (+img) is equivalent to \c CImg(img,false). + **/ + CImg operator+() const { + return CImg(*this,false); + } + + //! Addition operator. + /** + Similar to operator+=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const t value) const { + return CImg<_cimg_Tt>(*this,false)+=value; + } + + //! Addition operator. + /** + Similar to operator+=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator+(const char *const expression) const { + return CImg(*this,false)+=expression; + } + + //! Addition operator. + /** + Similar to operator+=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)+=img; + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const t), except that it performs a subtraction instead of an addition. + **/ + template + CImg& operator-=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr - value,524288); + return *this; + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const char*), except that it performs a subtraction instead of an addition. + **/ + CImg& operator-=(const char *const expression) { + return *this-=(+*this)._fill(expression,true,1,0,0,"operator-=",this); + } + + //! In-place subtraction operator. + /** + Similar to operator+=(const CImg&), except that it performs a subtraction instead of an addition. + **/ + template + CImg& operator-=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this-=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator--() { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr - 1,524288); + return *this; + } + + //! In-place decrement operator (postfix). + /** + Similar to operator++(int), except that it performs a decrement instead of an increment. + **/ + CImg operator--(int) { + const CImg copy(*this,false); + --*this; + return copy; + } + + //! Replace each pixel by its opposite value. + /** + \note + - If the computed opposite values are out-of-range, they are treated as with standard C++ numeric types. + For instance, the \c unsigned \c char opposite of \c 1 is \c 255. + \par Example + \code + const CImg + img1("reference.jpg"), // Load a RGB color image + img2 = -img1; // Compute its opposite (in 'unsigned char') + (img1,img2).display(); + \endcode + \image html ref_operator_minus.jpg + **/ + CImg operator-() const { + return CImg(_width,_height,_depth,_spectrum,(T)0)-=*this; + } + + //! Subtraction operator. + /** + Similar to operator-=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const t value) const { + return CImg<_cimg_Tt>(*this,false)-=value; + } + + //! Subtraction operator. + /** + Similar to operator-=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator-(const char *const expression) const { + return CImg(*this,false)-=expression; + } + + //! Subtraction operator. + /** + Similar to operator-=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)-=img; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const t), except that it performs a multiplication instead of an addition. + **/ + template + CImg& operator*=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr * value,262144); + return *this; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const char*), except that it performs a multiplication instead of an addition. + **/ + CImg& operator*=(const char *const expression) { + return mul((+*this)._fill(expression,true,1,0,0,"operator*=",this)); + } + + //! In-place multiplication operator. + /** + Replace the image instance by the matrix multiplication between the image instance and the specified matrix + \c img. + \param img Second operand of the matrix multiplication. + \note + - It does \e not compute a pointwise multiplication between two images. For this purpose, use + mul(const CImg&) instead. + - The size of the image instance can be modified by this operator. + \par Example + \code + CImg A(2,2,1,1, 1,2,3,4); // Construct 2x2 matrix A = [1,2;3,4] + const CImg X(1,2,1,1, 1,2); // Construct 1x2 vector X = [1;2] + A*=X; // Assign matrix multiplication A*X to 'A' + // 'A' is now a 1x2 vector whose values are [5;11]. + \endcode + **/ + template + CImg& operator*=(const CImg& img) { + return ((*this)*img).move_to(*this); + } + + //! Multiplication operator. + /** + Similar to operator*=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const t value) const { + return CImg<_cimg_Tt>(*this,false)*=value; + } + + //! Multiplication operator. + /** + Similar to operator*=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator*(const char *const expression) const { + return CImg(*this,false)*=expression; + } + + //! Multiplication operator. + /** + Similar to operator*=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const CImg& img) const { + typedef _cimg_Ttdouble Ttdouble; + typedef _cimg_Tt Tt; + if (_width!=img._height || _depth!=1 || _spectrum!=1) + throw CImgArgumentException(_cimg_instance + "operator*(): Invalid multiplication of instance by specified " + "matrix (%u,%u,%u,%u,%p).", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + CImg res(img._width,_height); + + // Check for common cases to optimize. + if (img._width==1) { // Matrix * Vector + if (_height==1) switch (_width) { // Vector^T * Vector + case 1 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0]); + return res; + case 2 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1]); + return res; + case 3 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2]); + return res; + case 4 : + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2] + (Ttdouble)_data[3]*img[3]); + return res; + default : { + Ttdouble val = 0; + cimg_pragma_openmp(parallel for reduction(+:val) cimg_openmp_if_size(size(),4096)) + cimg_forX(*this,i) val+=(Ttdouble)_data[i]*img[i]; + res[0] = val; + return res; + } + } else if (_height==_width) switch (_width) { // Square_matrix * Vector + case 2 : // 2x2_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1]); + res[1] = (Tt)((Ttdouble)_data[2]*img[0] + (Ttdouble)_data[3]*img[1]); + return res; + case 3 : // 3x3_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2]); + res[1] = (Tt)((Ttdouble)_data[3]*img[0] + (Ttdouble)_data[4]*img[1] + + (Ttdouble)_data[5]*img[2]); + res[2] = (Tt)((Ttdouble)_data[6]*img[0] + (Ttdouble)_data[7]*img[1] + + (Ttdouble)_data[8]*img[2]); + return res; + case 4 : // 4x4_matrix * Vector + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[1] + + (Ttdouble)_data[2]*img[2] + (Ttdouble)_data[3]*img[3]); + res[1] = (Tt)((Ttdouble)_data[4]*img[0] + (Ttdouble)_data[5]*img[1] + + (Ttdouble)_data[6]*img[2] + (Ttdouble)_data[7]*img[3]); + res[2] = (Tt)((Ttdouble)_data[8]*img[0] + (Ttdouble)_data[9]*img[1] + + (Ttdouble)_data[10]*img[2] + (Ttdouble)_data[11]*img[3]); + res[3] = (Tt)((Ttdouble)_data[12]*img[0] + (Ttdouble)_data[13]*img[1] + + (Ttdouble)_data[14]*img[2] + (Ttdouble)_data[15]*img[3]); + return res; + } + } else if (_height==_width) { + if (img._height==img._width) switch (_width) { // Square_matrix * Square_matrix + case 2 : // 2x2_matrix * 2x2_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[2]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[3]); + res[2] = (Tt)((Ttdouble)_data[2]*img[0] + (Ttdouble)_data[3]*img[2]); + res[3] = (Tt)((Ttdouble)_data[2]*img[1] + (Ttdouble)_data[3]*img[3]); + return res; + case 3 : // 3x3_matrix * 3x3_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[3] + + (Ttdouble)_data[2]*img[6]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[4] + + (Ttdouble)_data[2]*img[7]); + res[2] = (Tt)((Ttdouble)_data[0]*img[2] + (Ttdouble)_data[1]*img[5] + + (Ttdouble)_data[2]*img[8]); + res[3] = (Tt)((Ttdouble)_data[3]*img[0] + (Ttdouble)_data[4]*img[3] + + (Ttdouble)_data[5]*img[6]); + res[4] = (Tt)((Ttdouble)_data[3]*img[1] + (Ttdouble)_data[4]*img[4] + + (Ttdouble)_data[5]*img[7]); + res[5] = (Tt)((Ttdouble)_data[3]*img[2] + (Ttdouble)_data[4]*img[5] + + (Ttdouble)_data[5]*img[8]); + res[6] = (Tt)((Ttdouble)_data[6]*img[0] + (Ttdouble)_data[7]*img[3] + + (Ttdouble)_data[8]*img[6]); + res[7] = (Tt)((Ttdouble)_data[6]*img[1] + (Ttdouble)_data[7]*img[4] + + (Ttdouble)_data[8]*img[7]); + res[8] = (Tt)((Ttdouble)_data[6]*img[2] + (Ttdouble)_data[7]*img[5] + + (Ttdouble)_data[8]*img[8]); + return res; + case 4 : // 4x4_matrix * 4x4_matrix + res[0] = (Tt)((Ttdouble)_data[0]*img[0] + (Ttdouble)_data[1]*img[4] + + (Ttdouble)_data[2]*img[8] + (Ttdouble)_data[3]*img[12]); + res[1] = (Tt)((Ttdouble)_data[0]*img[1] + (Ttdouble)_data[1]*img[5] + + (Ttdouble)_data[2]*img[9] + (Ttdouble)_data[3]*img[13]); + res[2] = (Tt)((Ttdouble)_data[0]*img[2] + (Ttdouble)_data[1]*img[6] + + (Ttdouble)_data[2]*img[10] + (Ttdouble)_data[3]*img[14]); + res[3] = (Tt)((Ttdouble)_data[0]*img[3] + (Ttdouble)_data[1]*img[7] + + (Ttdouble)_data[2]*img[11] + (Ttdouble)_data[3]*img[15]); + res[4] = (Tt)((Ttdouble)_data[4]*img[0] + (Ttdouble)_data[5]*img[4] + + (Ttdouble)_data[6]*img[8] + (Ttdouble)_data[7]*img[12]); + res[5] = (Tt)((Ttdouble)_data[4]*img[1] + (Ttdouble)_data[5]*img[5] + + (Ttdouble)_data[6]*img[9] + (Ttdouble)_data[7]*img[13]); + res[6] = (Tt)((Ttdouble)_data[4]*img[2] + (Ttdouble)_data[5]*img[6] + + (Ttdouble)_data[6]*img[10] + (Ttdouble)_data[7]*img[14]); + res[7] = (Tt)((Ttdouble)_data[4]*img[3] + (Ttdouble)_data[5]*img[7] + + (Ttdouble)_data[6]*img[11] + (Ttdouble)_data[7]*img[15]); + res[8] = (Tt)((Ttdouble)_data[8]*img[0] + (Ttdouble)_data[9]*img[4] + + (Ttdouble)_data[10]*img[8] + (Ttdouble)_data[11]*img[12]); + res[9] = (Tt)((Ttdouble)_data[8]*img[1] + (Ttdouble)_data[9]*img[5] + + (Ttdouble)_data[10]*img[9] + (Ttdouble)_data[11]*img[13]); + res[10] = (Tt)((Ttdouble)_data[8]*img[2] + (Ttdouble)_data[9]*img[6] + + (Ttdouble)_data[10]*img[10] + (Ttdouble)_data[11]*img[14]); + res[11] = (Tt)((Ttdouble)_data[8]*img[3] + (Ttdouble)_data[9]*img[7] + + (Ttdouble)_data[10]*img[11] + (Ttdouble)_data[11]*img[15]); + res[12] = (Tt)((Ttdouble)_data[12]*img[0] + (Ttdouble)_data[13]*img[4] + + (Ttdouble)_data[14]*img[8] + (Ttdouble)_data[15]*img[12]); + res[13] = (Tt)((Ttdouble)_data[12]*img[1] + (Ttdouble)_data[13]*img[5] + + (Ttdouble)_data[14]*img[9] + (Ttdouble)_data[15]*img[13]); + res[14] = (Tt)((Ttdouble)_data[12]*img[2] + (Ttdouble)_data[13]*img[6] + + (Ttdouble)_data[14]*img[10] + (Ttdouble)_data[15]*img[14]); + res[15] = (Tt)((Ttdouble)_data[12]*img[3] + (Ttdouble)_data[13]*img[7] + + (Ttdouble)_data[14]*img[11] + (Ttdouble)_data[15]*img[15]); + return res; + } else switch (_width) { // Square_matrix * Matrix + case 2 : { // 2x2_matrix * Matrix + const t *const ps0 = img.data(), *const ps1 = img.data(0,1); + Tt *const pd0 = res.data(), *const pd1 = res.data(0,1); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], + a2 = (Ttdouble)_data[2], a3 = (Ttdouble)_data[3]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),4096)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i]; + pd0[i] = (Tt)(a0*x + a1*y); + pd1[i] = (Tt)(a2*x + a3*y); + } + return res; + } + case 3 : { // 3x3_matrix * Matrix + const t *const ps0 = img.data(), *const ps1 = img.data(0,1), *const ps2 = img.data(0,2); + Tt *const pd0 = res.data(), *const pd1 = res.data(0,1), *const pd2 = res.data(0,2); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], a2 = (Ttdouble)_data[2], + a3 = (Ttdouble)_data[3], a4 = (Ttdouble)_data[4], a5 = (Ttdouble)_data[5], + a6 = (Ttdouble)_data[6], a7 = (Ttdouble)_data[7], a8 = (Ttdouble)_data[8]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),1024)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i], z = (Ttdouble)ps2[i]; + pd0[i] = (Tt)(a0*x + a1*y + a2*z); + pd1[i] = (Tt)(a3*x + a4*y + a5*z); + pd2[i] = (Tt)(a6*x + a7*y + a8*z); + } + return res; + } + case 4 : { // 4x4_matrix * Matrix + const t + *const ps0 = img.data(), *const ps1 = img.data(0,1), + *const ps2 = img.data(0,2), *const ps3 = img.data(0,3); + Tt + *const pd0 = res.data(), *const pd1 = res.data(0,1), + *const pd2 = res.data(0,2), *const pd3 = res.data(0,3); + const Ttdouble + a0 = (Ttdouble)_data[0], a1 = (Ttdouble)_data[1], a2 = (Ttdouble)_data[2], a3 = (Ttdouble)_data[3], + a4 = (Ttdouble)_data[4], a5 = (Ttdouble)_data[5], a6 = (Ttdouble)_data[6], a7 = (Ttdouble)_data[7], + a8 = (Ttdouble)_data[8], a9 = (Ttdouble)_data[9], a10 = (Ttdouble)_data[10], a11 = (Ttdouble)_data[11], + a12 = (Ttdouble)_data[12], a13 = (Ttdouble)_data[13], a14 = (Ttdouble)_data[14], + a15 = (Ttdouble)_data[15]; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(img.width(),512)) + cimg_forX(img,i) { + const Ttdouble x = (Ttdouble)ps0[i], y = (Ttdouble)ps1[i], z = (Ttdouble)ps2[i], c = (Ttdouble)ps3[i]; + pd0[i] = (Tt)(a0*x + a1*y + a2*z + a3*c); + pd1[i] = (Tt)(a4*x + a5*y + a6*z + a7*c); + pd2[i] = (Tt)(a8*x + a9*y + a10*z + a11*c); + pd3[i] = (Tt)(a12*x + a13*y + a14*z + a15*c); + } + return res; + } + } + } + + // Fallback to generic version. +#if cimg_use_openmp!=0 + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(size()>(cimg_openmp_sizefactor)*1024 && + img.size()>(cimg_openmp_sizefactor)*1024)) + cimg_forXY(res,i,j) { + Ttdouble value = 0; + cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); + res(i,j) = (Tt)value; + } +#else + Tt *ptrd = res._data; + cimg_forXY(res,i,j) { + Ttdouble value = 0; + cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); + *(ptrd++) = (Tt)value; + } +#endif + return res; + } + + //! In-place division operator. + /** + Similar to operator+=(const t), except that it performs a division instead of an addition. + **/ + template + CImg& operator/=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,*ptr / value,32768); + return *this; + } + + //! In-place division operator. + /** + Similar to operator+=(const char*), except that it performs a division instead of an addition. + **/ + CImg& operator/=(const char *const expression) { + return div((+*this)._fill(expression,true,1,0,0,"operator/=",this)); + } + + //! In-place division operator. + /** + Replace the image instance by the (right) matrix division between the image instance and the specified + matrix \c img. + \param img Second operand of the matrix division. + \note + - It does \e not compute a pointwise division between two images. For this purpose, use + div(const CImg&) instead. + - It returns the matrix operation \c A*inverse(img). + - The size of the image instance can be modified by this operator. + **/ + template + CImg& operator/=(const CImg& img) { + return (*this*img.get_invert()).move_to(*this); + } + + //! Division operator. + /** + Similar to operator/=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const t value) const { + return CImg<_cimg_Tt>(*this,false)/=value; + } + + //! Division operator. + /** + Similar to operator/=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator/(const char *const expression) const { + return CImg(*this,false)/=expression; + } + + //! Division operator. + /** + Similar to operator/=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const CImg& img) const { + return (*this)*img.get_invert(); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const t), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::mod(*ptr,(T)value),16384); + return *this; + } + + //! In-place modulo operator. + /** + Similar to operator+=(const char*), except that it performs a modulo operation instead of an addition. + **/ + CImg& operator%=(const char *const expression) { + return *this%=(+*this)._fill(expression,true,1,0,0,"operator%=",this); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const CImg&), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this%=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> operator%(const t value) const { + return CImg<_cimg_Tt>(*this,false)%=value; + } + + //! Modulo operator. + /** + Similar to operator%=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator%(const char *const expression) const { + return CImg(*this,false)%=expression; + } + + //! Modulo operator. + /** + Similar to operator%=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator%(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)%=img; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const t), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr & (ulongT)value,32768); + return *this; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise AND operation instead of an addition. + **/ + CImg& operator&=(const char *const expression) { + return *this&=(+*this)._fill(expression,true,1,0,0,"operator&=",this); + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this&=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator&(const t value) const { + return (+*this)&=value; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator&(const char *const expression) const { + return (+*this)&=expression; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator&(const CImg& img) const { + return (+*this)&=img; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr | (ulongT)value,32768); + return *this; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise OR operation instead of an addition. + **/ + CImg& operator|=(const char *const expression) { + return *this|=(+*this)._fill(expression,true,1,0,0,"operator|=",this); + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this|=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator|(const t value) const { + return (+*this)|=value; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator|(const char *const expression) const { + return (+*this)|=expression; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator|(const CImg& img) const { + return (+*this)|=img; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const t) instead. + **/ + template + CImg& operator^=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,(ulongT)*ptr ^ (ulongT)value,32768); + return *this; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const char*) instead. + **/ + CImg& operator^=(const char *const expression) { + return *this^=(+*this)._fill(expression,true,1,0,0,"operator^=",this); + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const CImg&) instead. + **/ + template + CImg& operator^=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator^(const t value) const { + return (+*this)^=value; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator^(const char *const expression) const { + return (+*this)^=expression; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator^(const CImg& img) const { + return (+*this)^=img; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,((longT)*ptr) << (int)value,65536); + return *this; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise left shift instead of an addition. + **/ + CImg& operator<<=(const char *const expression) { + return *this<<=(+*this)._fill(expression,true,1,0,0,"operator<<=",this); + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator<<(const t value) const { + return (+*this)<<=value; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator<<(const char *const expression) const { + return (+*this)<<=expression; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator<<(const CImg& img) const { + return (+*this)<<=img; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const t value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,((longT)*ptr) >> (int)value,65536); + return *this; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise right shift instead of an addition. + **/ + CImg& operator>>=(const char *const expression) { + return *this>>=(+*this)._fill(expression,true,1,0,0,"operator>>=",this); + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs> (int)*(ptrs++)); + for (const t *ptrs = img._data; ptrd> (int)*(ptrs++)); + } + return *this; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const t value) const { + return (+*this)>>=value; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator>>(const char *const expression) const { + return (+*this)>>=expression; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const CImg& img) const { + return (+*this)>>=img; + } + + //! Bitwise inversion operator. + /** + Similar to operator-(), except that it compute the bitwise inverse instead of the opposite value. + **/ + CImg operator~() const { + CImg res(_width,_height,_depth,_spectrum); + const T *ptrs = _data; + cimg_for(res,ptrd,T) { const ulongT value = (ulongT)*(ptrs++); *ptrd = (T)~value; } + return res; + } + + //! Test if all pixels of an image have the same value. + /** + Return \c true is all pixels of the image instance are equal to the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator==(const t value) const { + if (is_empty()) return false; + typedef _cimg_Tt Tt; + bool is_equal = true; + for (T *ptrd = _data + size(); is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)value)) {} + return is_equal; + } + + //! Test if all pixel values of an image follow a specified expression. + /** + Return \c true is all pixels of the image instance are equal to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator==(const char *const expression) const { + return *this==(+*this)._fill(expression,true,1,0,0,"operator==",this); + } + + //! Test if two images have the same size and values. + /** + Return \c true if the image instance and the input image \c img have the same pixel values, + even if the dimensions of the two images do not match. It returns \c false otherwise. + \param img Input image to compare with. + \note + - The pixel buffer pointers data() of the two compared images do not have to be the same for operator==() + to return \c true. + Only the dimensions and the pixel values matter. Thus, the comparison can be \c true even for different + pixel types \c T and \c t. + \par Example + \code + const CImg img1(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'float' pixel values) + const CImg img2(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'char' pixel values) + if (img1==img2) { // Test succeeds, image dimensions and values are the same + std::printf("'img1' and 'img2' have same dimensions and values."); + } + \endcode + **/ + template + bool operator==(const CImg& img) const { + typedef _cimg_Tt Tt; + const ulongT siz = size(); + bool is_equal = true; + if (siz!=img.size()) return false; + t *ptrs = img._data + siz; + for (T *ptrd = _data + siz; is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)*(--ptrs))) {} + return is_equal; + } + + //! Test if pixels of an image are all different from a value. + /** + Return \c true is all pixels of the image instance are different than the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator!=(const t value) const { + return !((*this)==value); + } + + //! Test if all pixel values of an image are different from a specified expression. + /** + Return \c true is all pixels of the image instance are different to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator!=(const char *const expression) const { + return !((*this)==expression); + } + + //! Test if two images have different sizes or values. + /** + Return \c true if the image instance and the input image \c img have different dimensions or pixel values, + and \c false otherwise. + \param img Input image to compare with. + \note + - Writing \c img1!=img2 is equivalent to \c !(img1==img2). + **/ + template + bool operator!=(const CImg& img) const { + return !((*this)==img); + } + + //! Construct an image list from two images. + /** + Return a new list of image (\c CImgList instance) containing exactly two elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image \c img, at position [\c 1]. + + \param img Input image that will be the second image of the resulting list. + \note + - The family of operator,() is convenient to easily create list of images, but it is also \e quite \e slow + in practice (see warning below). + - Constructed lists contain no shared images. If image instance or input image \c img are shared, they are + inserted as new non-shared copies in the resulting list. + - The pixel type of the returned list may be a superset of the initial pixel type \c T, if necessary. + \warning + - Pipelining operator,() \c N times will perform \c N copies of the entire content of a (growing) image list. + This may become very expensive in terms of speed and used memory. You should avoid using this technique to + build a new CImgList instance from several images, if you are seeking for performance. + Fast insertions of images in an image list are possible with + CImgList::insert(const CImg&,unsigned int,bool) or move_to(CImgList&,unsigned int). + \par Example + \code + const CImg + img1("reference.jpg"), + img2 = img1.get_mirror('x'), + img3 = img2.get_blur(5); + const CImgList list = (img1,img2); // Create list of two elements from 'img1' and 'img2' + (list,img3).display(); // Display image list containing copies of 'img1','img2' and 'img3' + \endcode + \image html ref_operator_comma.jpg + **/ + template + CImgList<_cimg_Tt> operator,(const CImg& img) const { + return CImgList<_cimg_Tt>(*this,img); + } + + //! Construct an image list from image instance and an input image list. + /** + Return a new list of images (\c CImgList instance) containing exactly \c list.size() \c + \c 1 elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image list \c list, from positions [\c 1] to [\c list.size()]. + + \param list Input image list that will be appended to the image instance. + \note + - Similar to operator,(const CImg&) const, except that it takes an image list as an argument. + **/ + template + CImgList<_cimg_Tt> operator,(const CImgList& list) const { + return CImgList<_cimg_Tt>(list,false).insert(*this,0); + } + + //! Split image along specified axis. + /** + Return a new list of images (\c CImgList instance) containing the split components + of the instance image along the specified axis. + \param axis Splitting axis (can be '\c x','\c y','\c z' or '\c c') + \note + - Similar to get_split(char,int) const, with default second argument. + \par Example + \code + const CImg img("reference.jpg"); // Load a RGB color image + const CImgList list = (img<'c'); // Get a list of its three R,G,B channels + (img,list).display(); + \endcode + \image html ref_operator_less.jpg + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the number of image columns. + /** + Return the image width, i.e. the image dimension along the X-axis. + \note + - The width() of an empty image is equal to \c 0. + - width() is typically equal to \c 1 when considering images as \e vectors for matrix calculations. + - width() returns an \c int, although the image width is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._width. + **/ + int width() const { + return (int)_width; + } + + //! Return the number of image rows. + /** + Return the image height, i.e. the image dimension along the Y-axis. + \note + - The height() of an empty image is equal to \c 0. + - height() returns an \c int, although the image height is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._height. + **/ + int height() const { + return (int)_height; + } + + //! Return the number of image slices. + /** + Return the image depth, i.e. the image dimension along the Z-axis. + \note + - The depth() of an empty image is equal to \c 0. + - depth() is typically equal to \c 1 when considering usual 2D images. When depth()\c > \c 1, the image + is said to be \e volumetric. + - depth() returns an \c int, although the image depth is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._depth. + **/ + int depth() const { + return (int)_depth; + } + + //! Return the number of image channels. + /** + Return the number of image channels, i.e. the image dimension along the C-axis. + \note + - The spectrum() of an empty image is equal to \c 0. + - spectrum() is typically equal to \c 1 when considering scalar-valued images, to \c 3 + for RGB-coded color images, and to \c 4 for RGBA-coded color images (with alpha-channel). + The number of channels of an image instance is not limited. The meaning of the pixel values is not linked + up to the number of channels (e.g. a 4-channel image may indifferently stands for a RGBA or CMYK color image). + - spectrum() returns an \c int, although the image spectrum is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._spectrum. + **/ + int spectrum() const { + return (int)_spectrum; + } + + //! Return the total number of pixel values. + /** + Return width()*\ref height()*\ref depth()*\ref spectrum(), + i.e. the total number of values of type \c T in the pixel buffer of the image instance. + \note + - The size() of an empty image is equal to \c 0. + - The allocated memory size for a pixel buffer of a non-shared \c CImg instance is equal to + size()*sizeof(T). + \par Example + \code + const CImg img(100,100,1,3); // Construct new 100x100 color image + if (img.size()==30000) // Test succeeds + std::printf("Pixel buffer uses %lu bytes", + img.size()*sizeof(float)); + \endcode + **/ + ulongT size() const { + return (ulongT)_width*_height*_depth*_spectrum; + } + + //! Return a pointer to the first pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the first value in the pixel buffer of the image instance, + whether the instance is \c const or not. + \note + - The data() of an empty image is equal to \c 0 (null pointer). + - The allocated pixel buffer for the image instance starts from \c data() + and goes to data()+\ref size() - 1 (included). + - To get the pointer to one particular location of the pixel buffer, use + data(unsigned int,unsigned int,unsigned int,unsigned int) instead. + **/ + T* data() { + return _data; + } + + //! Return a pointer to the first pixel value \const. + const T* data() const { + return _data; + } + + //! Return a pointer to a located pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the value located at (\c x,\c y,\c z,\c c) in the pixel buffer + of the image instance, + whether the instance is \c const or not. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)). Thus, this method has the same + properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + **/ +#if cimg_verbosity>=3 + T *data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (off>=size()) + cimg::warn(_cimg_instance + "data(): Invalid pointer request, at coordinates (%u,%u,%u,%u) [offset=%u].", + cimg_instance, + x,y,z,c,off); + return _data + off; + } + + //! Return a pointer to a located pixel value \const. + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->data(x,y,z,c); + } +#else + T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } + + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } +#endif + + //! Return the offset to a located pixel value, with respect to the beginning of the pixel buffer. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)) - img.data(). + Thus, this method has the same properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + \par Example + \code + const CImg img(100,100,1,3); // Define a 100x100 RGB-color image + const long off = img.offset(10,10,0,2); // Get the offset of the blue value of the pixel located at (10,10) + const float val = img[off]; // Get the blue value of this pixel + \endcode + **/ + longT offset(const int x, const int y=0, const int z=0, const int c=0) const { + return x + (longT)y*_width + (longT)z*_width*_height + (longT)c*_width*_height*_depth; + } + + //! Return a CImg::iterator pointing to the first pixel value. + /** + \note + - Equivalent to data(). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + iterator begin() { + return _data; + } + + //! Return a CImg::iterator pointing to the first value of the pixel buffer \const. + const_iterator begin() const { + return _data; + } + + //! Return a CImg::iterator pointing next to the last pixel value. + /** + \note + - Writing \c img.end() is equivalent to img.data() + img.size(). + - It has been mainly defined for compatibility with STL naming conventions. + \warning + - The returned iterator actually points to a value located \e outside the acceptable bounds of the pixel buffer. + Trying to read or write the content of the returned iterator will probably result in a crash. + Use it mainly as a strict upper bound for a CImg::iterator. + \par Example + \code + CImg img(100,100,1,3); // Define a 100x100 RGB color image + // 'img.end()' used below as an upper bound for the iterator. + for (CImg::iterator it = img.begin(); it::iterator pointing next to the last pixel value \const. + const_iterator end() const { + return _data + size(); + } + + //! Return a reference to the first pixel value. + /** + \note + - Writing \c img.front() is equivalent to img[0], or img(0,0,0,0). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& front() { + return *_data; + } + + //! Return a reference to the first pixel value \const. + const T& front() const { + return *_data; + } + + //! Return a reference to the last pixel value. + /** + \note + - Writing \c img.back() is equivalent to img[img.size() - 1], or + img(img.width() - 1,img.height() - 1,img.depth() - 1,img.spectrum() - 1). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& back() { + return *(_data + size() - 1); + } + + //! Return a reference to the last pixel value \const. + const T& back() const { + return *(_data + size() - 1); + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to a specified default value in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note + - Writing \c img.at(offset,out_value) is similar to img[offset], except that if \c offset + is outside bounds (e.g. \c offset<0 or \c offset>=img.size()), a reference to a value \c out_value + is safely returned instead. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + **/ + T& at(const int offset, const T& out_value) { + return (offset<0 || offset>=(int)size())?(cimg::temporary(out_value)=out_value):(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions \const. + T at(const int offset, const T& out_value) const { + return (offset<0 || offset>=(int)size())?out_value:(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to the nearest pixel location in the image instance in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \note + - Similar to at(int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified offset, i.e. + - If \c offset<0, then \c img[0] is returned. + - If \c offset>=img.size(), then \c img[img.size() - 1] is returned. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + - If you know your image instance is \e not empty, you may rather use the slightly faster method \c _at(int). + **/ + T& at(const int offset) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + T& _at(const int offset) { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions \const. + const T& at(const int offset) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + const T& _at(const int offset) const { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to a specified default value in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c x,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to operator()(), except that an out-of-bounds access along the X-axis returns the specified value + \c out_value. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || x>=width())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate \const. + T atX(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || x>=width())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to the nearest pixel location in the image instance in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to at(int,int,int,int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified X-coordinate. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _at(int,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + T& _atX(const int x, const int y=0, const int z=0, const int c=0) { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate \const. + const T& atX(const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + const T& _atX(const int x, const int y=0, const int z=0, const int c=0) const { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on X and Y-coordinates. + **/ + T& atXY(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || x>=width() || y>=height())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y coordinates \const. + T atXY(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || x>=width() || y>=height())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXY(int,int,int,int). + **/ + T& atXY(const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + T& _atXY(const int x, const int y, const int z=0, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates \const. + const T& atXY(const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + const T& _atXY(const int x, const int y, const int z=0, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on + X,Y and Z-coordinates. + **/ + T& atXYZ(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates \const. + T atXYZ(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZ(int,int,int,int). + **/ + T& atXYZ(const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + T& _atXYZ(const int x, const int y, const int z, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates \const. + const T& atXYZ(const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + const T& _atXYZ(const int x, const int y, const int z, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed on all + X,Y,Z and C-coordinates. + **/ + T& atXYZC(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions \const. + T atXYZC(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())?out_value: + (*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed on all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZC(int,int,int,int). + **/ + T& atXYZC(const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + T& _atXYZC(const int x, const int y, const int z, const int c) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Access to a pixel value, using Neumann boundary conditions \const. + const T& atXYZC(const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + const T& _atXYZC(const int x, const int y, const int z, const int c) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to atX(int,int,int,int,const T), except that the returned pixel value is approximated by + a linear interpolation along the X-axis, if corresponding coordinates are not integers. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + const Tfloat + Ic = (Tfloat)atX(x,y,z,c,out_value), In = (Tfloat)atXY(nx,y,z,c,out_value); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access along + the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that an out-of-bounds access returns + the value of the nearest pixel in the image instance, regarding the specified X-coordinate. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX(): Empty instance.", + cimg_instance); + + return _linear_atX(fx,y,z,c); + } + + Tfloat _linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = dx>0?x + 1:x; + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X-coordinate. + Tfloat linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX_p(): Empty instance.", + cimg_instance); + + return _linear_atX_p(fx,y,z,c); + } + + Tfloat _linear_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = cimg::mod(x + 1,_width); + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X and Y-coordinates. + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + const Tfloat + Icc = (Tfloat)atXY(x,y,z,c,out_value), Inc = (Tfloat)atXY(nx,y,z,c,out_value), + Icn = (Tfloat)atXY(x,ny,z,c,out_value), Inn = (Tfloat)atXY(nx,ny,z,c,out_value); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXY(float,float,int,int). + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY(): Empty instance.", + cimg_instance); + + return _linear_atXY(fx,fy,z,c); + } + + Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y; + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X and Y-coordinates. + Tfloat linear_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY_p(): Empty instance.", + cimg_instance); + + return _linear_atXY_p(fx,fy,z,c); + } + + Tfloat _linear_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height); + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy; + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X,Y and Z-coordinates. + **/ + Tfloat linear_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + const Tfloat + Iccc = (Tfloat)atXYZ(x,y,z,c,out_value), Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), + Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), + Iccn = (Tfloat)atXYZ(x,y,nz,c,out_value), Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), + Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZ(float,float,float,int). + **/ + Tfloat linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ(): Empty instance.", + cimg_instance); + + return _linear_atXYZ(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z; + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for the X,Y and Z-coordinates. + Tfloat linear_atXYZ_p(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ_p(): Empty instance.", + cimg_instance); + + return _linear_atXYZ_p(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ_p(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f), + nfz = cimg::mod(fz,_depth - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height), + nz = cimg::mod(z + 1,_depth); + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + (Incc - Iccc + + (Iccc + Innc - Icnc - Incc + + (Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)*dz)*dy + + (Iccc + Incn - Iccn - Incc)*dz)*dx + + (Icnc - Iccc + + (Iccc + Icnn - Iccn - Icnc)*dz)*dy + + (Iccn - Iccc)*dz; + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for all X,Y,Z,C-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved for all X,Y,Z and C-coordinates. + **/ + Tfloat linear_atXYZC(const float fx, const float fy, const float fz, const float fc, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1, + c = (int)fc - (fc>=0?0:1), nc = c + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z, + dc = fc - c; + const Tfloat + Icccc = (Tfloat)atXYZC(x,y,z,c,out_value), Inccc = (Tfloat)atXYZC(nx,y,z,c,out_value), + Icncc = (Tfloat)atXYZC(x,ny,z,c,out_value), Inncc = (Tfloat)atXYZC(nx,ny,z,c,out_value), + Iccnc = (Tfloat)atXYZC(x,y,nz,c,out_value), Incnc = (Tfloat)atXYZC(nx,y,nz,c,out_value), + Icnnc = (Tfloat)atXYZC(x,ny,nz,c,out_value), Innnc = (Tfloat)atXYZC(nx,ny,nz,c,out_value), + Icccn = (Tfloat)atXYZC(x,y,z,nc,out_value), Inccn = (Tfloat)atXYZC(nx,y,z,nc,out_value), + Icncn = (Tfloat)atXYZC(x,ny,z,nc,out_value), Inncn = (Tfloat)atXYZC(nx,ny,z,nc,out_value), + Iccnn = (Tfloat)atXYZC(x,y,nz,nc,out_value), Incnn = (Tfloat)atXYZC(nx,y,nz,nc,out_value), + Icnnn = (Tfloat)atXYZC(x,ny,nz,nc,out_value), Innnn = (Tfloat)atXYZC(nx,ny,nz,nc,out_value); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn -Icccc); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for all X,Y,Z and C-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved for all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZC(float,float,float,float). + **/ + Tfloat linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC(): Empty instance.", + cimg_instance); + + return _linear_atXYZC(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1), + nfc = cimg::cut(fc,0,spectrum() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z, + nc = dc>0?c + 1:c; + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using linear interpolation and periodic boundary conditions for all X,Y,Z and C-coordinates. + Tfloat linear_atXYZC_p(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC_p(): Empty instance.", + cimg_instance); + + return _linear_atXYZC_p(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC_p(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::mod(fx,_width - 0.5f), + nfy = cimg::mod(fy,_height - 0.5f), + nfz = cimg::mod(fz,_depth - 0.5f), + nfc = cimg::mod(fc,_spectrum - 0.5f); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = cimg::mod(x + 1,_width), + ny = cimg::mod(y + 1,_height), + nz = cimg::mod(z + 1,_depth), + nc = cimg::mod(c + 1,_spectrum); + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + The cubic interpolation uses Hermite splines. + \param fx d X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a \e cubic interpolation along the X-axis. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2; + const float + dx = fx - x; + const Tfloat + Ip = (Tfloat)atX(px,y,z,c,out_value), Ic = (Tfloat)atX(x,y,z,c,out_value), + In = (Tfloat)atX(nx,y,z,c,out_value), Ia = (Tfloat)atX(ax,y,z,c,out_value); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atX_c(const float fx, const int y, const int z, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atX(fx,y,z,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access + along the X-axis. The cubic interpolation uses Hermite splines. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to cubic_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a cubic interpolation along the X-axis. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX(): Empty instance.", + cimg_instance); + return _cubic_atX(fx,y,z,c); + } + + Tfloat _cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2; + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atX_c(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(cubic_atX(fx,y,z,c)); + } + + T _cubic_atX_c(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(_cubic_atX(fx,y,z,c)); + } + + //! Return pixel value, using cubic interpolation and periodic boundary conditions for the X-coordinate. + Tfloat cubic_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX_p(): Empty instance.", + cimg_instance); + return _cubic_atX_p(fx,y,z,c); + } + + Tfloat _cubic_atX_p(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()); + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atX_pc(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(cubic_atX_p(fx,y,z,c)); + } + + T _cubic_atX_pc(const float fx, const int y, const int z, const int c) const { + return cimg::type::cut(_cubic_atX_p(fx,y,z,c)); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X and Y-coordinates. + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2; + const float dx = fx - x, dy = fy - y; + const Tfloat + Ipp = (Tfloat)atXY(px,py,z,c,out_value), Icp = (Tfloat)atXY(x,py,z,c,out_value), + Inp = (Tfloat)atXY(nx,py,z,c,out_value), Iap = (Tfloat)atXY(ax,py,z,c,out_value), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)atXY(px,y,z,c,out_value), Icc = (Tfloat)atXY(x, y,z,c,out_value), + Inc = (Tfloat)atXY(nx,y,z,c,out_value), Iac = (Tfloat)atXY(ax,y,z,c,out_value), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)atXY(px,ny,z,c,out_value), Icn = (Tfloat)atXY(x,ny,z,c,out_value), + Inn = (Tfloat)atXY(nx,ny,z,c,out_value), Ian = (Tfloat)atXY(ax,ny,z,c,out_value), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)atXY(px,ay,z,c,out_value), Ica = (Tfloat)atXY(x,ay,z,c,out_value), + Ina = (Tfloat)atXY(nx,ay,z,c,out_value), Iaa = (Tfloat)atXY(ax,ay,z,c,out_value), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int,const T) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXY_c(const float fx, const float fy, const int z, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atXY(fx,fy,z,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved for both X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXY(float,float,int,int). + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY(): Empty instance.", + cimg_instance); + return _cubic_atXY(fx,fy,z,c); + } + + Tfloat _cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1), + nfy = cimg::type::is_nan(fy)?0:cimg::cut(fy,0,height() - 1); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = x - 1<0?0:x - 1, nx = dx<=0?x:x + 1, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy<=0?y:y + 1, ay = y + 2>=height()?height() - 1:y + 2; + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXY_c(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(cubic_atXY(fx,fy,z,c)); + } + + T _cubic_atXY_c(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(_cubic_atXY(fx,fy,z,c)); + } + + //! Return pixel value, using cubic interpolation and periodic boundary conditions for the X and Y-coordinates. + Tfloat cubic_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY_p(): Empty instance.", + cimg_instance); + return _cubic_atXY_p(fx,fy,z,c); + } + + Tfloat _cubic_atXY_p(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f), + nfy = cimg::type::is_nan(fy)?0:cimg::mod(fy,_height - 0.5f); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()), + py = cimg::mod(y - 1,height()), ny = cimg::mod(y + 1,height()), ay = cimg::mod(y + 2,height()); + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atXY_pc(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(cubic_atXY_p(fx,fy,z,c)); + } + + T _cubic_atXY_pc(const float fx, const float fy, const int z, const int c) const { + return cimg::type::cut(_cubic_atXY_p(fx,fy,z,c)); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2, + z = (int)fz - (fz>=0?0:1), pz = z - 1, nz = z + 1, az = z + 2; + const float dx = fx - x, dy = fy - y, dz = fz - z; + const Tfloat + Ippp = (Tfloat)atXYZ(px,py,pz,c,out_value), Icpp = (Tfloat)atXYZ(x,py,pz,c,out_value), + Inpp = (Tfloat)atXYZ(nx,py,pz,c,out_value), Iapp = (Tfloat)atXYZ(ax,py,pz,c,out_value), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)atXYZ(px,y,pz,c,out_value), Iccp = (Tfloat)atXYZ(x, y,pz,c,out_value), + Incp = (Tfloat)atXYZ(nx,y,pz,c,out_value), Iacp = (Tfloat)atXYZ(ax,y,pz,c,out_value), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)atXYZ(px,ny,pz,c,out_value), Icnp = (Tfloat)atXYZ(x,ny,pz,c,out_value), + Innp = (Tfloat)atXYZ(nx,ny,pz,c,out_value), Ianp = (Tfloat)atXYZ(ax,ny,pz,c,out_value), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)atXYZ(px,ay,pz,c,out_value), Icap = (Tfloat)atXYZ(x,ay,pz,c,out_value), + Inap = (Tfloat)atXYZ(nx,ay,pz,c,out_value), Iaap = (Tfloat)atXYZ(ax,ay,pz,c,out_value), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)atXYZ(px,py,z,c,out_value), Icpc = (Tfloat)atXYZ(x,py,z,c,out_value), + Inpc = (Tfloat)atXYZ(nx,py,z,c,out_value), Iapc = (Tfloat)atXYZ(ax,py,z,c,out_value), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)atXYZ(px,y,z,c,out_value), Iccc = (Tfloat)atXYZ(x, y,z,c,out_value), + Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), Iacc = (Tfloat)atXYZ(ax,y,z,c,out_value), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)atXYZ(px,ny,z,c,out_value), Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), + Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), Ianc = (Tfloat)atXYZ(ax,ny,z,c,out_value), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)atXYZ(px,ay,z,c,out_value), Icac = (Tfloat)atXYZ(x,ay,z,c,out_value), + Inac = (Tfloat)atXYZ(nx,ay,z,c,out_value), Iaac = (Tfloat)atXYZ(ax,ay,z,c,out_value), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)atXYZ(px,py,nz,c,out_value), Icpn = (Tfloat)atXYZ(x,py,nz,c,out_value), + Inpn = (Tfloat)atXYZ(nx,py,nz,c,out_value), Iapn = (Tfloat)atXYZ(ax,py,nz,c,out_value), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)atXYZ(px,y,nz,c,out_value), Iccn = (Tfloat)atXYZ(x, y,nz,c,out_value), + Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), Iacn = (Tfloat)atXYZ(ax,y,nz,c,out_value), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)atXYZ(px,ny,nz,c,out_value), Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), + Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value), Iann = (Tfloat)atXYZ(ax,ny,nz,c,out_value), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)atXYZ(px,ay,nz,c,out_value), Ican = (Tfloat)atXYZ(x,ay,nz,c,out_value), + Inan = (Tfloat)atXYZ(nx,ay,nz,c,out_value), Iaan = (Tfloat)atXYZ(ax,ay,nz,c,out_value), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)atXYZ(px,py,az,c,out_value), Icpa = (Tfloat)atXYZ(x,py,az,c,out_value), + Inpa = (Tfloat)atXYZ(nx,py,az,c,out_value), Iapa = (Tfloat)atXYZ(ax,py,az,c,out_value), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)atXYZ(px,y,az,c,out_value), Icca = (Tfloat)atXYZ(x, y,az,c,out_value), + Inca = (Tfloat)atXYZ(nx,y,az,c,out_value), Iaca = (Tfloat)atXYZ(ax,y,az,c,out_value), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)atXYZ(px,ny,az,c,out_value), Icna = (Tfloat)atXYZ(x,ny,az,c,out_value), + Inna = (Tfloat)atXYZ(nx,ny,az,c,out_value), Iana = (Tfloat)atXYZ(ax,ny,az,c,out_value), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)atXYZ(px,ay,az,c,out_value), Icaa = (Tfloat)atXYZ(x,ay,az,c,out_value), + Inaa = (Tfloat)atXYZ(nx,ay,az,c,out_value), Iaaa = (Tfloat)atXYZ(ax,ay,az,c,out_value), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Dirichlet boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int,const T) const, except that the return value is clamped to stay + in the min/max range of the datatype \c T. + **/ + T cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + return cimg::type::cut(cubic_atXYZ(fx,fy,fz,c,out_value)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ(): Empty instance.", + cimg_instance); + return _cubic_atXYZ(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::cut(fx,0,width() - 1), + nfy = cimg::type::is_nan(fy)?0:cimg::cut(fy,0,height() - 1), + nfz = cimg::type::is_nan(fz)?0:cimg::cut(fz,0,depth() - 1); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy>0?y + 1:y, ay = y + 2>=height()?height() - 1:y + 2, + pz = z - 1<0?0:z - 1, nz = dz>0?z + 1:z, az = z + 2>=depth()?depth() - 1:z + 2; + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return clamped pixel value, using cubic interpolation and Neumann boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int) const, except that the return value is clamped to stay in the + min/max range of the datatype \c T. + **/ + T cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(cubic_atXYZ(fx,fy,fz,c)); + } + + T _cubic_atXYZ_c(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(_cubic_atXYZ(fx,fy,fz,c)); + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ_p(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ_p(): Empty instance.", + cimg_instance); + return _cubic_atXYZ_p(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ_p(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::type::is_nan(fx)?0:cimg::mod(fx,_width - 0.5f), + nfy = cimg::type::is_nan(fy)?0:cimg::mod(fy,_height - 0.5f), + nfz = cimg::type::is_nan(fz)?0:cimg::mod(fz,_depth - 0.5f); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = cimg::mod(x - 1,width()), nx = cimg::mod(x + 1,width()), ax = cimg::mod(x + 2,width()), + py = cimg::mod(y - 1,height()), ny = cimg::mod(y + 1,height()), ay = cimg::mod(y + 2,height()), + pz = cimg::mod(z - 1,depth()), nz = cimg::mod(z + 1,depth()), az = cimg::mod(z + 2,depth()); + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + T cubic_atXYZ_pc(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(cubic_atXYZ_p(fx,fy,fz,c)); + } + + T _cubic_atXYZ_pc(const float fx, const float fy, const float fz, const int c) const { + return cimg::type::cut(_cubic_atXYZ_p(fx,fy,fz,c)); + } + + //! Set pixel value, using linear interpolation for the X-coordinates. + /** + Set pixel value at specified coordinates (\c fx,\c y,\c z,\c c) in the image instance, in a way that + the value is spread amongst several neighbors if the pixel coordinates are float-valued. + \param value Pixel value to set. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param is_added Tells if the pixel value is added to (\c true), or simply replace (\c false) the current image + pixel(s). + \return A reference to the current image instance. + \note + - Calling this method with out-of-bounds coordinates does nothing. + **/ + CImg& set_linear_atX(const T& value, const float fx, const int y=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + if (y>=0 && y=0 && z=0 && c=0 && x=0 && nx& set_linear_atXY(const T& value, const float fx, const float fy=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + if (z>=0 && z=0 && c=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx& set_linear_atXYZ(const T& value, const float fx, const float fy=0, const float fz=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + if (c>=0 && c=0 && z=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx=0 && nz=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx image whose buffer data() is a \c char* string describing the list of all pixel values + of the image instance (written in base 10), separated by specified \c separator character. + \param separator A \c char character which specifies the separator between values in the returned C-string. + \param max_size Maximum size of the returned image (or \c 0 if no limits are set). + \param format For float/double-values, tell the printf format used to generate the text representation + of the numbers (or \c 0 for default representation). + \note + - The returned image is never empty. + - For an empty image instance, the returned string is "". + - If \c max_size is equal to \c 0, there are no limits on the size of the returned string. + - Otherwise, if the maximum number of string characters is exceeded, the value string is cut off + and terminated by character \c '\0'. In that case, the returned image size is max_size + 1. + **/ + CImg value_string(const char separator=',', const unsigned int max_size=0, + const char *const format=0) const { + if (is_empty() || max_size==1) return CImg(1,1,1,1,0); + CImgList items; + CImg s_item(256); *s_item = 0; + const T *ptrs = _data; + unsigned int string_size = 0; + const char *const _format = format?format:cimg::type::format(); + for (ulongT off = 0, siz = size(); off::format(*(ptrs++))); + CImg item(s_item._data,printed_size); + item[printed_size - 1] = separator; + item.move_to(items); + if (max_size) string_size+=printed_size; + } + CImg res; + (items>'x').move_to(res); + if (max_size && res._width>=max_size) res.crop(0,max_size - 1); + res.back() = 0; + return res; + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Test shared state of the pixel buffer. + /** + Return \c true if image instance has a shared memory buffer, and \c false otherwise. + \note + - A shared image do not own his pixel buffer data() and will not deallocate it on destruction. + - Most of the time, a \c CImg image instance will \e not be shared. + - A shared image can only be obtained by a limited set of constructors and methods (see list below). + **/ + bool is_shared() const { + return _is_shared; + } + + //! Test if image instance is empty. + /** + Return \c true, if image instance is empty, i.e. does \e not contain any pixel values, has dimensions + \c 0 x \c 0 x \c 0 x \c 0 and a pixel buffer pointer set to \c 0 (null pointer), and \c false otherwise. + **/ + bool is_empty() const { + return !(_data && _width && _height && _depth && _spectrum); + } + + //! Test if image instance contains a 'inf' value. + /** + Return \c true, if image instance contains a 'inf' value, and \c false otherwise. + **/ + bool is_inf() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_inf((float)*p)) return true; + return false; + } + + //! Test if image instance contains a NaN value. + /** + Return \c true, if image instance contains a NaN value, and \c false otherwise. + **/ + bool is_nan() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_nan((float)*p)) return true; + return false; + } + + //! Test if image width is equal to specified value. + bool is_sameX(const unsigned int size_x) const { + return _width==size_x; + } + + //! Test if image width is equal to specified value. + template + bool is_sameX(const CImg& img) const { + return is_sameX(img._width); + } + + //! Test if image width is equal to specified value. + bool is_sameX(const CImgDisplay& disp) const { + return is_sameX(disp._width); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const unsigned int size_y) const { + return _height==size_y; + } + + //! Test if image height is equal to specified value. + template + bool is_sameY(const CImg& img) const { + return is_sameY(img._height); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const CImgDisplay& disp) const { + return is_sameY(disp._height); + } + + //! Test if image depth is equal to specified value. + bool is_sameZ(const unsigned int size_z) const { + return _depth==size_z; + } + + //! Test if image depth is equal to specified value. + template + bool is_sameZ(const CImg& img) const { + return is_sameZ(img._depth); + } + + //! Test if image spectrum is equal to specified value. + bool is_sameC(const unsigned int size_c) const { + return _spectrum==size_c; + } + + //! Test if image spectrum is equal to specified value. + template + bool is_sameC(const CImg& img) const { + return is_sameC(img._spectrum); + } + + //! Test if image width and height are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameY(unsigned int) const are both verified. + **/ + bool is_sameXY(const unsigned int size_x, const unsigned int size_y) const { + return _width==size_x && _height==size_y; + } + + //! Test if image width and height are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameY(const CImg&) const are both verified. + **/ + template + bool is_sameXY(const CImg& img) const { + return is_sameXY(img._width,img._height); + } + + //! Test if image width and height are the same as that of an existing display window. + /** + Test if is_sameX(const CImgDisplay&) const and is_sameY(const CImgDisplay&) const are both verified. + **/ + bool is_sameXY(const CImgDisplay& disp) const { + return is_sameXY(disp._width,disp._height); + } + + //! Test if image width and depth are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXZ(const unsigned int size_x, const unsigned int size_z) const { + return _width==size_x && _depth==size_z; + } + + //! Test if image width and depth are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXZ(const CImg& img) const { + return is_sameXZ(img._width,img._depth); + } + + //! Test if image width and spectrum are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXC(const unsigned int size_x, const unsigned int size_c) const { + return _width==size_x && _spectrum==size_c; + } + + //! Test if image width and spectrum are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXC(const CImg& img) const { + return is_sameXC(img._width,img._spectrum); + } + + //! Test if image height and depth are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameYZ(const unsigned int size_y, const unsigned int size_z) const { + return _height==size_y && _depth==size_z; + } + + //! Test if image height and depth are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameYZ(const CImg& img) const { + return is_sameYZ(img._height,img._depth); + } + + //! Test if image height and spectrum are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYC(const unsigned int size_y, const unsigned int size_c) const { + return _height==size_y && _spectrum==size_c; + } + + //! Test if image height and spectrum are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYC(const CImg& img) const { + return is_sameYC(img._height,img._spectrum); + } + + //! Test if image depth and spectrum are equal to specified values. + /** + Test if is_sameZ(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameZC(const unsigned int size_z, const unsigned int size_c) const { + return _depth==size_z && _spectrum==size_c; + } + + //! Test if image depth and spectrum are the same as that of another image. + /** + Test if is_sameZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameZC(const CImg& img) const { + return is_sameZC(img._depth,img._spectrum); + } + + //! Test if image width, height and depth are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXYZ(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z) const { + return is_sameXY(size_x,size_y) && _depth==size_z; + } + + //! Test if image width, height and depth are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXYZ(const CImg& img) const { + return is_sameXYZ(img._width,img._height,img._depth); + } + + //! Test if image width, height and spectrum are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXYC(const unsigned int size_x, const unsigned int size_y, const unsigned int size_c) const { + return is_sameXY(size_x,size_y) && _spectrum==size_c; + } + + //! Test if image width, height and spectrum are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYC(const CImg& img) const { + return is_sameXYC(img._width,img._height,img._spectrum); + } + + //! Test if image width, depth and spectrum are equal to specified values. + /** + Test if is_sameXZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXZC(const unsigned int size_x, const unsigned int size_z, const unsigned int size_c) const { + return is_sameXZ(size_x,size_z) && _spectrum==size_c; + } + + //! Test if image width, depth and spectrum are the same as that of another image. + /** + Test if is_sameXZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXZC(const CImg& img) const { + return is_sameXZC(img._width,img._depth,img._spectrum); + } + + //! Test if image height, depth and spectrum are equal to specified values. + /** + Test if is_sameYZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYZC(const unsigned int size_y, const unsigned int size_z, const unsigned int size_c) const { + return is_sameYZ(size_y,size_z) && _spectrum==size_c; + } + + //! Test if image height, depth and spectrum are the same as that of another image. + /** + Test if is_sameYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYZC(const CImg& img) const { + return is_sameYZC(img._height,img._depth,img._spectrum); + } + + //! Test if image width, height, depth and spectrum are equal to specified values. + /** + Test if is_sameXYZ(unsigned int,unsigned int,unsigned int) const and is_sameC(unsigned int) const are both + verified. + **/ + bool is_sameXYZC(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c) const { + return is_sameXYZ(size_x,size_y,size_z) && _spectrum==size_c; + } + + //! Test if image width, height, depth and spectrum are the same as that of another image. + /** + Test if is_sameXYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYZC(const CImg& img) const { + return is_sameXYZC(img._width,img._height,img._depth,img._spectrum); + } + + //! Test if specified coordinates are inside image bounds. + /** + Return \c true if pixel located at (\c x,\c y,\c z,\c c) is inside bounds of the image instance, + and \c false otherwise. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Return \c true only if all these conditions are verified: + - The image instance is \e not empty. + - 0<=x<=\ref width() - 1. + - 0<=y<=\ref height() - 1. + - 0<=z<=\ref depth() - 1. + - 0<=c<=\ref spectrum() - 1. + **/ + bool containsXYZC(const int x, const int y=0, const int z=0, const int c=0) const { + return !is_empty() && x>=0 && x=0 && y=0 && z=0 && c img(100,100,1,3); // Construct a 100x100 RGB color image + const unsigned long offset = 1249; // Offset to the pixel (49,12,0,0) + unsigned int x,y,z,c; + if (img.contains(img[offset],x,y,z,c)) { // Convert offset to (x,y,z,c) coordinates + std::printf("Offset %u refers to pixel located at (%u,%u,%u,%u).\n", + offset,x,y,z,c); + } + \endcode + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z, t& c) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = (ulongT)(ppixel - _data); + const ulongT nc = off/whd; + off%=whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; c = (t)nc; + return true; + } + + //! Test if pixel value is inside image bounds and get its X,Y and Z-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X,Y and Z-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((ulongT)(ppixel - _data))%whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; + return true; + } + + //! Test if pixel value is inside image bounds and get its X and Y-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X and Y-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y) const { + const ulongT wh = (ulongT)_width*_height, siz = wh*_depth*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((unsigned int)(ppixel - _data))%wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; + return true; + } + + //! Test if pixel value is inside image bounds and get its X-coordinate. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X-coordinate is set. + **/ + template + bool contains(const T& pixel, t& x) const { + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + size()) return false; + x = (t)(((ulongT)(ppixel - _data))%_width); + return true; + } + + //! Test if pixel value is inside image bounds. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that no pixel coordinates are set. + **/ + bool contains(const T& pixel) const { + const T *const ppixel = &pixel; + return !is_empty() && ppixel>=_data && ppixel<_data + size(); + } + + //! Test if pixel buffers of instance and input images overlap. + /** + Return \c true, if pixel buffers attached to image instance and input image \c img overlap, + and \c false otherwise. + \param img Input image to compare with. + \note + - Buffer overlapping may happen when manipulating \e shared images. + - If two image buffers overlap, operating on one of the image will probably modify the other one. + - Most of the time, \c CImg instances are \e non-shared and do not overlap between each others. + \par Example + \code + const CImg + img1("reference.jpg"), // Load RGB-color image + img2 = img1.get_shared_channel(1); // Get shared version of the green channel + if (img1.is_overlapped(img2)) { // Test succeeds, 'img1' and 'img2' overlaps + std::printf("Buffers overlap!\n"); + } + \endcode + **/ + template + bool is_overlapped(const CImg& img) const { + const ulongT csiz = size(), isiz = img.size(); + return !((void*)(_data + csiz)<=(void*)img._data || (void*)_data>=(void*)(img._data + isiz)); + } + + //! Test if the set {\c *this,\c primitives,\c colors,\c opacities} defines a valid 3D object. + /** + Return \c true is the 3D object represented by the set {\c *this,\c primitives,\c colors,\c opacities} defines a + valid 3D object, and \c false otherwise. The vertex coordinates are defined by the instance image. + \param primitives List of primitives of the 3D object. + \param colors List of colors of the 3D object. + \param opacities List (or image) of opacities of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_checking to \c false to speed-up the 3D object checking. In this case, only the size of + each 3D object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + template + bool is_object3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true, + char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check consistency for the particular case of an empty 3D object. + if (is_empty()) { + if (primitives || colors || opacities) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines no vertices but %u primitives, " + "%u colors and %lu opacities", + _width,primitives._width,primitives._width, + colors._width,(unsigned long)opacities.size()); + return false; + } + return true; + } + + // Check consistency of vertices. + if (_height!=3 || _depth>1 || _spectrum>1) { // Check vertices dimensions + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) has invalid vertex dimensions (%u,%u,%u,%u)", + _width,primitives._width,_width,_height,_depth,_spectrum); + return false; + } + if (colors._width>primitives._width + 1) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines %u colors", + _width,primitives._width,colors._width); + return false; + } + if (opacities.size()>primitives._width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines %lu opacities", + _width,primitives._width,(unsigned long)opacities.size()); + return false; + } + if (!full_check) return true; + + // Check consistency of primitives. + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + const unsigned int psiz = (unsigned int)primitive.size(); + switch (psiz) { + case 1 : { // Point + const unsigned int i0 = (unsigned int)primitive(0); + if (i0>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex index %u in " + "point primitive [%u]", + _width,primitives._width,i0,l); + return false; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + if (i0>=_width || i1>=_width || i2>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + _width,primitives._width,i0,i1,i2,l); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + if (i0>=_width || i1>=_width || i2>=_width || i3>=_width) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + _width,primitives._width,i0,i1,i2,i3,l); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines an invalid primitive [%u] of size %u", + _width,primitives._width,l,(unsigned int)psiz); + return false; + } + } + + // Check consistency of colors. + cimglist_for(colors,c) { + const CImg& color = colors[c]; + if (!color) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines no color for primitive [%u]", + _width,primitives._width,c); + return false; + } + } + + // Check consistency of light texture. + if (colors._width>primitives._width) { + const CImg &light = colors.back(); + if (!light || light._depth>1) { + if (error_message) cimg_sprintf(error_message, + "3D object (%u,%u) defines an invalid light texture (%u,%u,%u,%u)", + _width,primitives._width,light._width, + light._height,light._depth,light._spectrum); + return false; + } + } + + return true; + } + + //! Test if image instance represents a valid serialization of a 3D object. + /** + Return \c true if the image instance represents a valid serialization of a 3D object, and \c false otherwise. + \param full_check Tells if full checking of the instance must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_check to \c false to speed-up the 3D object checking. In this case, only the size of + each 3D object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + bool is_CImg3d(const bool full_check=true, char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check instance dimension and header. + if (_width!=1 || _height<8 || _depth!=1 || _spectrum!=1) { + if (error_message) cimg_sprintf(error_message, + "CImg3d has invalid dimensions (%u,%u,%u,%u)", + _width,_height,_depth,_spectrum); + return false; + } + const T *ptrs = _data, *const ptre = end(); + if (!_is_CImg3d(*(ptrs++),'C') || !_is_CImg3d(*(ptrs++),'I') || !_is_CImg3d(*(ptrs++),'m') || + !_is_CImg3d(*(ptrs++),'g') || !_is_CImg3d(*(ptrs++),'3') || !_is_CImg3d(*(ptrs++),'d')) { + if (error_message) cimg_sprintf(error_message, + "CImg3d header not found"); + return false; + } + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + + // Check consistency of number of vertices / primitives. + if (!full_check) { + const ulongT minimal_size = 8UL + 3*nb_points + 6*nb_primitives; + if (_data + minimal_size>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has only %lu values, while at least %lu values were expected", + nb_points,nb_primitives,(unsigned long)size(),(unsigned long)minimal_size); + return false; + } + } + + // Check consistency of vertex data. + if (!nb_points) { + if (nb_primitives) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no vertices but %u primitives", + nb_points,nb_primitives,nb_primitives); + return false; + } + if (ptrs!=ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) is an empty object but contains %u value%s " + "more than expected", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs),(ptre - ptrs)>1?"s":""); + return false; + } + return true; + } + if (ptrs + 3*nb_points>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines only %u vertices data", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs)/3); + return false; + } + ptrs+=3*nb_points; + + // Check consistency of primitive data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines %u vertices but no primitive", + nb_points,nb_primitives,nb_points); + return false; + } + + if (!full_check) return true; + + for (unsigned int p = 0; p=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex index %u in point primitive [%u]", + nb_points,nb_primitives,i0,p); + return false; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + ptrs+=3; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==6) ptrs+=4; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==9) ptrs+=6; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,p); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)), + i3 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==12) ptrs+=8; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points || i3>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,i3,p); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines an invalid primitive [%u] of size %u", + nb_points,nb_primitives,p,nb_inds); + return false; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete primitive data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,p,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of color data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no color/texture data", + nb_points,nb_primitives); + return false; + } + for (unsigned int c = 0; c=c) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared sprite/texture index %u " + "for primitive [%u]", + nb_points,nb_primitives,w,c); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete color/texture data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,c,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of opacity data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no opacity data", + nb_points,nb_primitives); + return false; + } + for (unsigned int o = 0; o=o) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared opacity index %u " + "for primitive [%u]", + nb_points,nb_primitives,w,o); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete opacity data for primitive [%u]", + nb_points,nb_primitives,o); + return false; + } + } + + // Check end of data. + if (ptrs1?"s":""); + return false; + } + return true; + } + + static bool _is_CImg3d(const T val, const char c) { + return val>=(T)c && val<(T)(c + 1); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + // Define the math formula parser/compiler and expression evaluator. + struct _cimg_math_parser { + CImg mem; + CImg memtype, memmerge; + CImgList _code, &code, code_begin, code_end, + _code_begin_t, &code_begin_t, _code_end_t, &code_end_t; + CImg opcode; + const CImg *p_code_end, *p_code; + const CImg *const p_break; + + CImg expr, pexpr; + const CImg& imgin; + const CImgList& listin; + CImg &imgout; + CImgList& listout; + + CImg _img_stats, &img_stats, constcache_vals; + CImgList _list_stats, &list_stats, _list_median, &list_median, _list_norm, &list_norm; + CImg mem_img_stats, constcache_inds; + + CImg level, variable_pos, reserved_label; + CImgList variable_def, macro_def, macro_body; + CImgList macro_body_is_string; + char *user_macro; + + unsigned int mempos, mem_img_median, mem_img_norm, mem_img_index, debug_indent, result_dim, break_type, + constcache_size; + bool is_parallelizable, is_end_code, is_fill, return_new_comp, need_input_copy; + double *result; + cimg_uint64 rng; + const char *const calling_function, *s_op, *ss_op; + typedef double (*mp_func)(_cimg_math_parser&); + +#define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant value? +#define _cimg_mp_is_scalar(arg) (memtype[arg]<2) // Is scalar value? +#define _cimg_mp_is_comp(arg) (!memtype[arg]) // Is computation value? +#define _cimg_mp_is_reserved(arg) (memtype[arg]==-1) // Is scalar and reserved (e.g. variable)? +#define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector? +#define _cimg_mp_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Size (0=scalar, N>0=vectorN) +#define _cimg_mp_calling_function s_calling_function()._data +#define _cimg_mp_op(s) s_op = s; ss_op = ss +#define _cimg_mp_check_type(arg,n_arg,mode,N) check_type(arg,n_arg,mode,N,ss,se,saved_char) +#define _cimg_mp_check_constant(arg,n_arg,mode) check_constant(arg,n_arg,mode,ss,se,saved_char) +#define _cimg_mp_check_constant_index(arg) check_constant_index(arg,ss,se,saved_char) +#define _cimg_mp_check_matrix_square(arg,n_arg) check_matrix_square(arg,n_arg,ss,se,saved_char) +#define _cimg_mp_check_list(is_out) check_list(is_out,ss,se,saved_char) +#define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp) +#define _cimg_mp_return(x) { *se = saved_char; s_op = previous_s_op; ss_op = previous_ss_op; return x; } +#define _cimg_mp_return_nan() _cimg_mp_return(_cimg_mp_slot_nan) +#define _cimg_mp_constant(val) _cimg_mp_return(constant((double)(val))) +#define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op)) +#define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1)) +#define _cimg_mp_scalar2(op,i1,i2) _cimg_mp_return(scalar2(op,i1,i2)) +#define _cimg_mp_scalar3(op,i1,i2,i3) _cimg_mp_return(scalar3(op,i1,i2,i3)) +#define _cimg_mp_scalar4(op,i1,i2,i3,i4) _cimg_mp_return(scalar4(op,i1,i2,i3,i4)) +#define _cimg_mp_scalar5(op,i1,i2,i3,i4,i5) _cimg_mp_return(scalar5(op,i1,i2,i3,i4,i5)) +#define _cimg_mp_scalar6(op,i1,i2,i3,i4,i5,i6) _cimg_mp_return(scalar6(op,i1,i2,i3,i4,i5,i6)) +#define _cimg_mp_scalar7(op,i1,i2,i3,i4,i5,i6,i7) _cimg_mp_return(scalar7(op,i1,i2,i3,i4,i5,i6,i7)) +#define _cimg_mp_vector1_v(op,i1) _cimg_mp_return(vector1_v(op,i1)) +#define _cimg_mp_vector2_sv(op,i1,i2) _cimg_mp_return(vector2_sv(op,i1,i2)) +#define _cimg_mp_vector2_vs(op,i1,i2) _cimg_mp_return(vector2_vs(op,i1,i2)) +#define _cimg_mp_vector2_vv(op,i1,i2) _cimg_mp_return(vector2_vv(op,i1,i2)) +#define _cimg_mp_vector3_vss(op,i1,i2,i3) _cimg_mp_return(vector3_vss(op,i1,i2,i3)) +#define _cimg_mp_strerr \ + *se = saved_char; \ + for (s0 = ss; s0>expr._data && *s0!=';'; --s0) {} \ + if (*s0==';') ++s0; \ + while (cimg::is_blank(*s0)) ++s0; \ + cimg::strellipsize(s0,64) + + // Constructors / Destructors. + ~_cimg_math_parser() { + cimg::srand(rng); + } + + _cimg_math_parser(const char *const expression, const char *const funcname=0, + const CImg& img_input=CImg::const_empty(), CImg *const img_output=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0, + const bool _is_fill=false): + code(_code),code_begin_t(_code_begin_t),code_end_t(_code_end_t), + p_break((CImg*)(cimg_ulong)-2), + imgin(img_input),listin(list_inputs?*list_inputs:CImgList::const_empty()), + imgout(img_output?*img_output:CImg::empty()),listout(list_outputs?*list_outputs:CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),list_norm(_list_norm),user_macro(0), + mem_img_median(~0U),mem_img_norm(~0U),mem_img_index(~0U),debug_indent(0),result_dim(0),break_type(0), + constcache_size(0),is_parallelizable(true),is_fill(_is_fill),need_input_copy(false), + rng((cimg::_rand(),cimg::rng())),calling_function(funcname?funcname:"cimg_math_parser") { + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + if (!expression || !*expression) + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Empty expression.", + pixel_type(),_cimg_mp_calling_function); + const char *_expression = expression; + while (*_expression && (cimg::is_blank(*_expression) || *_expression==';')) ++_expression; + CImg::string(_expression).move_to(expr); + char *ps = &expr.back() - 1; + while (ps>expr._data && (cimg::is_blank(*ps) || *ps==';')) --ps; + *(++ps) = 0; expr._width = (unsigned int)(ps - expr._data + 1); + + // Ease the retrieval of previous non-space characters afterwards. + pexpr.assign(expr._width); + char c, *pe = pexpr._data; + for (ps = expr._data, c = ' '; *ps; ++ps) { + if (!cimg::is_blank(*ps)) c = *ps; else *ps = ' '; + *(pe++) = c; + } + *pe = 0; + level = get_level(expr); + + // Init constant values. +#define _cimg_mp_interpolation (reserved_label[30]!=~0U?reserved_label[30]:0) +#define _cimg_mp_boundary (reserved_label[31]!=~0U?reserved_label[31]:0) +#define _cimg_mp_slot_t 17 +#define _cimg_mp_slot_nan 29 +#define _cimg_mp_slot_x 30 +#define _cimg_mp_slot_y 31 +#define _cimg_mp_slot_z 32 +#define _cimg_mp_slot_c 33 + + mem.assign(96); + for (unsigned int i = 0; i<=10; ++i) mem[i] = (double)i; // mem[0-10] = 0...10 + for (unsigned int i = 1; i<=5; ++i) mem[i + 10] = -(double)i; // mem[11-15] = -1...-5 + mem[16] = 0.5; + mem[_cimg_mp_slot_t] = 0; // thread_id + mem[18] = (double)imgin._width; // w + mem[19] = (double)imgin._height; // h + mem[20] = (double)imgin._depth; // d + mem[21] = (double)imgin._spectrum; // s + mem[22] = (double)imgin._is_shared; // r + mem[23] = (double)imgin._width*imgin._height; // wh + mem[24] = (double)imgin._width*imgin._height*imgin._depth; // whd + mem[25] = (double)imgin._width*imgin._height*imgin._depth*imgin._spectrum; // whds + mem[26] = (double)listin._width; // l + mem[27] = std::exp(1.); // e + mem[28] = cimg::PI; // pi + mem[_cimg_mp_slot_nan] = cimg::type::nan(); // nan + + // Set value property : + // { -1 = reserved (e.g. variable) | 0 = computation value | + // 1 = compile-time constant | N>1 = constant ptr to vector[N-1] }. + memtype.assign(mem._width,1,1,1,0); + for (unsigned int i = 0; i<_cimg_mp_slot_x; ++i) memtype[i] = 1; + memtype[_cimg_mp_slot_t] = memtype[_cimg_mp_slot_x] = memtype[_cimg_mp_slot_y] = + memtype[_cimg_mp_slot_z] = memtype[_cimg_mp_slot_c] = -1; + mempos = _cimg_mp_slot_c + 1; + variable_pos.assign(8); + + reserved_label.assign(128,1,1,1,~0U); + // reserved_label[0-31] are used to store the memory index of these variables: + // [0] = wh, [1] = whd, [2] = whds, [3] = pi, [4] = im, [5] = iM, [6] = ia, [7] = iv, + // [8] = is, [9] = ip, [10] = ic, [11] = in, [12] = xm, [13] = ym, [14] = zm, [15] = cm, [16] = xM, + // [17] = yM, [18] = zM, [19] = cM, [20] = i0...[29] = i9, [30] = interpolation, [31] = boundary + + // Compile expression into a sequence of opcodes. + s_op = ""; ss_op = expr._data; + const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0,false); + if (!_cimg_mp_is_constant(ind_result)) { + if (_cimg_mp_is_vector(ind_result)) + CImg(&mem[ind_result] + 1,_cimg_mp_size(ind_result),1,1,1,true). + fill(cimg::type::nan()); + else if (ind_result!=_cimg_mp_slot_t) mem[ind_result] = cimg::type::nan(); + } + + // Free resources used for compiling expression and prepare evaluation. + result_dim = _cimg_mp_size(ind_result); + if (mem._width>=256 && mem._width - mempos>=mem._width/2) mem.resize(mempos,1,1,1,-1); + result = mem._data + ind_result; + memtype.assign(); + constcache_vals.assign(); + constcache_inds.assign(); + level.assign(); + variable_pos.assign(); + reserved_label.assign(); + expr.assign(); + pexpr.assign(); + opcode.assign(); + opcode._is_shared = true; + + // Execute begin() bloc if any specified. + if (code_begin) { + mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_begin.end(); + for (p_code = code_begin; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + p_code_end = code.end(); + } + + _cimg_math_parser(): + code(_code),code_begin_t(_code_begin_t),code_end_t(_code_end_t), + p_code_end(0),p_break((CImg*)(cimg_ulong)-2), + imgin(CImg::const_empty()),listin(CImgList::const_empty()), + imgout(CImg::empty()),listout(CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),list_norm(_list_norm),debug_indent(0), + result_dim(0),break_type(0),constcache_size(0),is_parallelizable(true),is_fill(false), + need_input_copy(false),rng(0),calling_function(0) { + mem.assign(1 + _cimg_mp_slot_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()() + result = mem._data; + } + + _cimg_math_parser(const _cimg_math_parser& mp): + mem(mp.mem),code(mp.code),code_begin_t(mp.code_begin_t),code_end_t(mp.code_end_t), + p_code_end(mp.p_code_end),p_break(mp.p_break), + imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout), + img_stats(mp.img_stats),list_stats(mp.list_stats),list_median(mp.list_median),list_norm(mp.list_norm), + debug_indent(0),result_dim(mp.result_dim),break_type(0),constcache_size(0), + is_parallelizable(mp.is_parallelizable),is_fill(mp.is_fill), + need_input_copy(mp.need_input_copy),result(mem._data + (mp.result - mp.mem._data)), + rng((cimg::_rand(),cimg::rng())),calling_function(0) { + +#if cimg_use_openmp!=0 + mem[_cimg_mp_slot_t] = omp_get_thread_num(); + rng+=omp_get_thread_num(); +#endif + opcode.assign(); + opcode._is_shared = true; + } + + // Compilation procedure. + unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *const p_ref, + const bool is_critical) { + if (depth>256) { + cimg::strellipsize(expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Call stack overflow (infinite recursion?), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + (ss - 4)>expr._data?"...":"", + (ss - 4)>expr._data?ss - 4:expr._data, + se<&expr.back()?"...":""); + } + char c1, c2; + + // Simplify expression when possible. + do { + c2 = 0; + if (ssss && (cimg::is_blank(c1 = *(se - 1)) || c1==';')) --se; + } + while (*ss=='(' && *(se - 1)==')' && std::strchr(ss,')')==se - 1) { + ++ss; --se; c2 = 1; + } + } while (c2 && ss::%s: %s%s Missing %s, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + *s_op=='F'?"argument":"item", + (ss_op - 4)>expr._data?"...":"", + (ss_op - 4)>expr._data?ss_op - 4:expr._data, + ss_op + std::strlen(ss_op)<&expr.back()?"...":""); + } + + static const size_t siz_ref = 7*sizeof(unsigned int); + const char *const previous_s_op = s_op, *const previous_ss_op = ss_op; + const unsigned int depth1 = depth + 1; + unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6; + char + *const se1 = se - 1, *const se2 = se - 2, *const se3 = se - 3, + *const ss1 = ss + 1, *const ss2 = ss + 2, *const ss3 = ss + 3, *const ss4 = ss + 4, + *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8, + *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0; + double val = 0, val1, val2; + mp_func op; + return_new_comp = false; + + // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value + // linked to the returned memory slot (reference that cannot be determined at compile time). + // p_ref[0] can be { 0 = scalar (unlinked) | 1 = vector value | 2 = image value (offset) | + // 3 = image value (coordinates) | 4 = image value as a vector (offsets) | + // 5 = image value as a vector (coordinates) }. + // Depending on p_ref[0], the remaining p_ref[k] have the following meaning: + // When p_ref[0]==0, p_ref is actually unlinked. + // When p_ref[0]==1, p_ref = [ 1, vector_ind, offset ]. + // When p_ref[0]==2, p_ref = [ 2, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==3, p_ref = [ 3, image_ind (or ~0U), is_relative, x, y, z, c ]. + // When p_ref[0]==4, p_ref = [ 4, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==5, p_ref = [ 5, image_ind (or ~0U), is_relative, x, y, z ]. + if (p_ref) { *p_ref = 0; p_ref[1] = p_ref[2] = p_ref[3] = p_ref[4] = p_ref[5] = p_ref[6] = ~0U; } + + const char saved_char = *se; *se = 0; + const unsigned int clevel = level[ss - expr._data], clevel1 = clevel + 1; + bool is_sth, is_relative; + CImg ref; + CImg variable_name; + CImgList l_opcode; + + // Look for a single value or a pre-defined variable. + int nb = 0; + s = ss + (*ss=='+' || *ss=='-'?1:0); + if (*s=='i' || *s=='I' || *s=='n' || *s=='N') { // Particular cases : +/-NaN and +/-Inf + is_sth = *ss=='-'; + if (!cimg::strcasecmp(s,"inf")) { val = cimg::type::inf(); nb = 1; } + else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type::nan(); nb = 1; } + if (nb==1 && is_sth) val = -val; + } else if (*s=='0' && (s[1]=='x' || s[1]=='X')) { // Hexadecimal number + is_sth = *ss=='-'; + if (cimg_sscanf(s + 2,"%x%c",&arg1,&sep)==1) { + nb = 1; + val = (double)arg1; + if (is_sth) val = -val; + } + } + if (!nb) nb = cimg_sscanf(ss,"%lf%c%c",&val,&(sep=0),&(end=0)); + if (nb==1) _cimg_mp_constant(val); + if (nb==2 && sep=='%') _cimg_mp_constant(val/100); + + if (ss1==se) switch (*ss) { // One-char reserved variable + case 'c' : _cimg_mp_return(reserved_label[(int)'c']!=~0U?reserved_label[(int)'c']:_cimg_mp_slot_c); + case 'd' : _cimg_mp_return(reserved_label[(int)'d']!=~0U?reserved_label[(int)'d']:20); + case 'e' : _cimg_mp_return(reserved_label[(int)'e']!=~0U?reserved_label[(int)'e']:27); + case 'h' : _cimg_mp_return(reserved_label[(int)'h']!=~0U?reserved_label[(int)'h']:19); + case 'k' : + if (reserved_label[(int)'k']!=~0U) _cimg_mp_return(reserved_label[(int)'k']); + pos = get_mem_img_index(); + if (pos!=~0U) _cimg_mp_return(pos); + _cimg_mp_return_nan(); + case 'l' : _cimg_mp_return(reserved_label[(int)'l']!=~0U?reserved_label[(int)'l']:26); + case 'r' : _cimg_mp_return(reserved_label[(int)'r']!=~0U?reserved_label[(int)'r']:22); + case 's' : _cimg_mp_return(reserved_label[(int)'s']!=~0U?reserved_label[(int)'s']:21); + case 't' : _cimg_mp_return(reserved_label[(int)'t']!=~0U?reserved_label[(int)'t']:_cimg_mp_slot_t); + case 'w' : _cimg_mp_return(reserved_label[(int)'w']!=~0U?reserved_label[(int)'w']:18); + case 'x' : _cimg_mp_return(reserved_label[(int)'x']!=~0U?reserved_label[(int)'x']:_cimg_mp_slot_x); + case 'y' : _cimg_mp_return(reserved_label[(int)'y']!=~0U?reserved_label[(int)'y']:_cimg_mp_slot_y); + case 'z' : _cimg_mp_return(reserved_label[(int)'z']!=~0U?reserved_label[(int)'z']:_cimg_mp_slot_z); + case 'u' : + if (reserved_label[(int)'u']!=~0U) _cimg_mp_return(reserved_label[(int)'u']); + _cimg_mp_scalar2(mp_u,0,1); + case 'g' : + if (reserved_label[(int)'g']!=~0U) _cimg_mp_return(reserved_label[(int)'g']); + _cimg_mp_scalar0(mp_g); + case 'i' : + if (reserved_label[(int)'i']!=~0U) _cimg_mp_return(reserved_label[(int)'i']); + _cimg_mp_scalar0(mp_i); + case 'I' : + _cimg_mp_op("Variable 'I'"); + if (reserved_label[(int)'I']!=~0U) _cimg_mp_return(reserved_label[(int)'I']); + if (!imgin._spectrum) _cimg_mp_return(0); + need_input_copy = true; + pos = vector(imgin._spectrum); + CImg::vector((ulongT)mp_Joff,pos,0,0,imgin._spectrum).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + case 'R' : + if (reserved_label[(int)'R']!=~0U) _cimg_mp_return(reserved_label[(int)'R']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0,0,0); + case 'G' : + if (reserved_label[(int)'G']!=~0U) _cimg_mp_return(reserved_label[(int)'G']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1,0,0); + case 'B' : + if (reserved_label[(int)'B']!=~0U) _cimg_mp_return(reserved_label[(int)'B']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2,0,0); + case 'A' : + if (reserved_label[(int)'A']!=~0U) _cimg_mp_return(reserved_label[(int)'A']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3,0,0); + } + else if (ss2==se) { // Two-chars reserved variable + arg1 = arg2 = ~0U; + if (*ss=='w' && *ss1=='h') // wh + _cimg_mp_return(reserved_label[0]!=~0U?reserved_label[0]:23); + if (*ss=='p' && *ss1=='i') // pi + _cimg_mp_return(reserved_label[3]!=~0U?reserved_label[3]:28); + if (*ss=='i') { + if (*ss1>='0' && *ss1<='9') { // i0...i9 + pos = 20 + *ss1 - '0'; + if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,pos - 20,0,0); + } + switch (*ss1) { + case 'm' : arg1 = 4; arg2 = 0; break; // im + case 'M' : arg1 = 5; arg2 = 1; break; // iM + case 'a' : arg1 = 6; arg2 = 2; break; // ia + case 'v' : arg1 = 7; arg2 = 3; break; // iv + case 's' : arg1 = 8; arg2 = 12; break; // is + case 'p' : arg1 = 9; arg2 = 13; break; // ip + case 'c' : // ic + if (reserved_label[10]!=~0U) _cimg_mp_return(reserved_label[10]); + if (mem_img_median==~0U) mem_img_median = imgin?constant(imgin.median()):0; + _cimg_mp_return(mem_img_median); + break; + case 'n' : // in + if (reserved_label[11]!=~0U) _cimg_mp_return(reserved_label[11]); + if (mem_img_norm==~0U) mem_img_norm = imgin?constant(imgin.magnitude()):0; + _cimg_mp_return(mem_img_norm); + } + } + else if (*ss1=='m') switch (*ss) { + case 'x' : arg1 = 12; arg2 = 4; break; // xm + case 'y' : arg1 = 13; arg2 = 5; break; // ym + case 'z' : arg1 = 14; arg2 = 6; break; // zm + case 'c' : arg1 = 15; arg2 = 7; break; // cm + } + else if (*ss1=='M') switch (*ss) { + case 'x' : arg1 = 16; arg2 = 8; break; // xM + case 'y' : arg1 = 17; arg2 = 9; break; // yM + case 'z' : arg1 = 18; arg2 = 10; break; // zM + case 'c' : arg1 = 19; arg2 = 11; break; // cM + } + if (arg1!=~0U) { + if (reserved_label[arg1]!=~0U) _cimg_mp_return(reserved_label[arg1]); + if (!img_stats) { + img_stats.assign(1,14,1,1,0).fill(imgin.get_stats(),false); + mem_img_stats.assign(1,14,1,1,~0U); + } + if (mem_img_stats[arg2]==~0U) mem_img_stats[arg2] = constant(img_stats[arg2]); + _cimg_mp_return(mem_img_stats[arg2]); + } + } else if (ss3==se) { // Three-chars reserved variable + if (*ss=='w' && *ss1=='h' && *ss2=='d') // whd + _cimg_mp_return(reserved_label[1]!=~0U?reserved_label[1]:24); + } else if (ss4==se) { // Four-chars reserved variable + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='s') // whds + _cimg_mp_return(reserved_label[2]!=~0U?reserved_label[2]:25); + } + + pos = ~0U; + is_sth = false; + for (s0 = ss, s = ss1; s='i'?1:3,0); + if (_cimg_mp_is_vector(arg2)) { + if (p1!=~0U) { + _cimg_mp_check_constant_index(p1); + p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + p2 = listin[p3]._spectrum; + } else p2 = imgin._spectrum; + if (!p2) _cimg_mp_return(0); + _cimg_mp_check_type(arg2,2,2,p2); + } else p2 = 0; + + if (p_ref) { + *p_ref = _cimg_mp_is_vector(arg2)?4:2; + p_ref[1] = p1; + p_ref[2] = (unsigned int)is_relative; + p_ref[3] = arg1; + if (_cimg_mp_is_vector(arg2)) + set_reserved_vector(arg2); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; + if (_cimg_mp_is_comp(arg1)) memtype[arg1] = -1; + } + + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg1,_cimg_mp_size(arg2)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg1,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value + if (!is_critical) is_parallelizable = false; + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0='i'?1:3,0); + if (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + } else if (s1='i') + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg5,p1,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg5,p1,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg5,p1,arg1,arg2,arg3,_cimg_mp_size(arg5)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg5); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg5,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg5,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg5,arg1,arg2,arg3,_cimg_mp_size(arg5)).move_to(code); + } + _cimg_mp_return(arg5); + } + } + + // Assign vector value (direct). + if (l_variable_name>3 && *ve1==']' && *ss!='[') { + s0 = ve1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss && is_varname(ss,s0 - ss)) { + variable_name[s0 - ss] = 0; // Remove brackets in variable name + get_variable_pos(variable_name,arg1,arg2); + arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U; // Vector slot + if (arg1==~0U || _cimg_mp_is_scalar(arg1)) + compile(ss,s0,depth1,0,is_critical); // Variable does not exist or is not a vector -> error + + arg2 = compile(++s0,ve1,depth1,0,is_critical); // Index + arg3 = compile(s + 1,se,depth1,0,is_critical); // Value to assign + _cimg_mp_check_type(arg3,2,1,0); + + if (_cimg_mp_is_constant(arg2)) { // Constant index -> return corresponding variable slot directly + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_size(arg1)) { + arg1+=nb + 1; + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + _cimg_mp_return(arg1); + } + compile(ss,s,depth1,0,is_critical); // Out-of-bounds reference -> error + } + + // Case of non-constant index -> return assigned value + linked reference + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -1; // Prevent from being used in further optimization + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; + } + CImg::vector((ulongT)mp_vector_set_off,arg3,arg1,(ulongT)_cimg_mp_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg3); + } + } + + // Assign user-defined macro. + if (l_variable_name>2 && *ve1==')' && *ss!='(') { + s0 = ve1; while (s0>ss && *s0!='(') --s0; + if (is_varname(ss,s0 - ss) && std::strncmp(variable_name,"debug(",6) && + std::strncmp(variable_name,"print(",6)) { // Valid macro name + s0 = variable_name._data + (s0 - ss); + *s0 = 0; + s1 = variable_name._data + l_variable_name - 1; // Pointer to closing parenthesis + CImg(variable_name._data,(unsigned int)(s0 - variable_name._data + 1)).move_to(macro_def,0); + ++s; while (*s && cimg::is_blank(*s)) ++s; + CImg(s,(unsigned int)(se - s + 1)).move_to(macro_body,0); + + p1 = 1; // Index of current parsed argument + for (s = s0 + 1; s<=s1; ++p1, s = ns + 1) { // Parse function arguments + if (p1>24) { + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Too much specified arguments (>24) in macro " + "definition '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && p1==1) break; // Function has no arguments + + s2 = s; // Start of the argument name + is_sth = true; // is_valid_argument_name? + if (*s>='0' && *s<='9') is_sth = false; + else for (ns = s; ns::%s: %s: %s name specified for argument %u when defining " + "macro '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + is_sth?"Empty":"Invalid",p1, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (ns==s1 || *ns==',') { // New argument found + *s3 = 0; + p2 = (unsigned int)(s3 - s2); // Argument length + for (ps = std::strstr(macro_body[0],s2); ps; ps = std::strstr(ps,s2)) { // Replace by arg number + if (!((ps>macro_body[0]._data && is_varchar(*(ps - 1))) || + (ps + p2macro_body[0]._data && *(ps - 1)=='#') { // Remove pre-number sign + *(ps - 1) = (char)p1; + if (ps + p26 && !std::strncmp(variable_name,"const ",6); + s0 = variable_name._data; + if (is_const) { + s0+=6; while (cimg::is_blank(*s0)) ++s0; + variable_name.resize(variable_name.end() - s0,1,1,1,0,0,1); + } + if (is_varname(variable_name)) { // Valid variable name + + // Assign variable (direct). + get_variable_pos(variable_name,arg1,arg2); + arg3 = compile(s + 1,se,depth1,0,is_critical); + is_sth = return_new_comp; // is arg3 a new blank object? + if (is_const) _cimg_mp_check_constant(arg3,2,0); + arg1 = arg2!=~0U?reserved_label[arg2]:arg1!=~0U?variable_pos[arg1]:~0U; + + if (arg1==~0U) { // Create new variable + if (_cimg_mp_is_vector(arg3)) { // Vector variable + arg1 = is_sth || is_comp_vector(arg3)?arg3:vector_copy(arg3); + set_reserved_vector(arg1); // Prevent from being used in further optimization + } else { // Scalar variable + if (is_const) arg1 = arg3; + else { + arg1 = is_sth || _cimg_mp_is_comp(arg3)?arg3:scalar1(mp_copy,arg3); + memtype[arg1] = -1; + } + } + + if (arg2!=~0U) reserved_label[arg2] = arg1; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg1; + variable_name.move_to(variable_def); + } + + } else { // Variable already exists -> assign a new value + if (is_const || _cimg_mp_is_constant(arg1)) { + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid assignment of %sconst variable '%s'%s, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"already-defined ":"non-", + variable_name._data, + !_cimg_mp_is_constant(arg1) && is_const?" as a new const variable":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(arg3,2,_cimg_mp_is_vector(arg1)?3:1,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1)) { // Vector + if (_cimg_mp_is_vector(arg3)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg3,(ulongT)_cimg_mp_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_size(arg1),arg3). + move_to(code); + } else // Scalar + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + } + return_new_comp = false; + _cimg_mp_return(arg1); + } + + // Assign lvalue (variable name was not valid for a direct assignment). + arg1 = ~0U; + is_sth = (bool)std::strchr(variable_name,'?'); // Contains_ternary_operator? + if (is_sth) break; // Do nothing and make ternary operator prioritary over assignment + + if (l_variable_name>2 && (std::strchr(variable_name,'(') || std::strchr(variable_name,'['))) { + ref.assign(7); + arg1 = compile(ss,s,depth1,ref,is_critical); // Lvalue slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Value to assign + + if (*ref==1) { // Vector value (scalar): V[k] = scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)mp_vector_set_off,arg2,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(arg2); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg3).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg2,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg2,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg3).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg3,_cimg_mp_size(arg2)).move_to(code); + } + + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg3,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg2,p1,arg3,arg4,arg5).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg2,p1,arg3,arg4,arg5,_cimg_mp_size(arg2)).move_to(code); + } + + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg2,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg2,arg3,arg4,arg5,_cimg_mp_size(arg2)).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg2)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s = scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)mp_copy,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + } + + // No assignment expressions match -> error + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1!=~0U && _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Apply unary/binary/ternary operators. The operator precedences should be the same as in C++. + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps && + level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=) + _cimg_mp_op(*ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='"); + + ref.assign(7); + arg1 = compile(ss,ns,depth1,ref,is_critical); // Vector slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Right operand + _cimg_mp_check_type(arg1,1,2,2); + _cimg_mp_check_type(arg2,2,3,2); + if (_cimg_mp_is_vector(arg2)) { // Complex **= complex + if (*ps=='*') + CImg::vector((ulongT)mp_complex_mul,arg1,arg1,arg2).move_to(code); + else if (*ps=='/') + CImg::vector((ulongT)mp_complex_div_vv,arg1,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code); + } else { // Complex **= scalar + if (*ps=='*') { + if (arg2==1) _cimg_mp_return(arg1); + self_vector_s(arg1,mp_self_mul,arg2); + } else if (*ps=='/') { + if (arg2==1) _cimg_mp_return(arg1); + self_vector_s(arg1,mp_self_div,arg2); + } else { + if (arg2==1) _cimg_mp_return(arg1); + CImg::vector((ulongT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code); + } + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + + } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + + _cimg_mp_return(arg1); + } + + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='+' || *ps=='-' || *ps=='*' || *ps=='/' || *ps=='%' || + *ps=='&' || *ps=='^' || *ps=='|' || + (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) && + level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=) + switch (*ps) { + case '+' : op = mp_self_add; _cimg_mp_op("Operator '+='"); break; + case '-' : op = mp_self_sub; _cimg_mp_op("Operator '-='"); break; + case '*' : op = mp_self_mul; _cimg_mp_op("Operator '*='"); break; + case '/' : op = mp_self_div; _cimg_mp_op("Operator '/='"); break; + case '%' : op = mp_self_modulo; _cimg_mp_op("Operator '%='"); break; + case '<' : op = mp_self_bitwise_left_shift; _cimg_mp_op("Operator '<<='"); break; + case '>' : op = mp_self_bitwise_right_shift; _cimg_mp_op("Operator '>>='"); break; + case '&' : op = mp_self_bitwise_and; _cimg_mp_op("Operator '&='"); break; + case '|' : op = mp_self_bitwise_or; _cimg_mp_op("Operator '|='"); break; + default : op = mp_self_pow; _cimg_mp_op("Operator '^='"); break; + } + s1 = *ps=='>' || *ps=='<'?ns:ps; + + ref.assign(7); + arg1 = compile(ss,s1,depth1,ref,is_critical); // Variable slot + arg2 = compile(s + 1,se,depth1,0,is_critical); // Value to apply + + // Check for particular case to be simplified. + if ((op==mp_self_add || op==mp_self_sub) && !arg2) _cimg_mp_return(arg1); + if ((op==mp_self_mul || op==mp_self_div) && arg2==1) _cimg_mp_return(arg1); + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_reserved(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k] += scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(arg1); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,1,0); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) += value + if (!is_critical) is_parallelizable = false; + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg2)) self_vector_v(arg1,op,arg2); // Vector += vector + else self_vector_s(arg1,op,arg2); // Vector += scalar + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s += scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + + variable_name.assign(ss,(unsigned int)(s - ss)).back() = 0; + cimg::strpare(variable_name,false,true); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + for (s = ss1; s::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||') + _cimg_mp_op("Operator '||'"); + arg1 = compile(ss,s,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,1,0); + if (arg1>0 && arg1<=16) _cimg_mp_return(1); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] || mem[arg2]); + if (!arg1) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_or,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&') + _cimg_mp_op("Operator '&&'"); + arg1 = compile(ss,s,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,1,0); + if (!arg1) _cimg_mp_return(0); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] && mem[arg2]); + if (arg1>0 && arg1<=16) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_and,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|') + _cimg_mp_op("Operator '|'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1] | (longT)mem[arg2]); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_scalar2(mp_bitwise_or,arg1,arg2); + } + + for (s = se2; s>ss; --s) + if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&') + _cimg_mp_op("Operator '&'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1] & (longT)mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_bitwise_and,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=') + _cimg_mp_op("Operator '!='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + if (arg1==arg2) _cimg_mp_return(0); + p1 = _cimg_mp_size(arg1); + p2 = _cimg_mp_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(1); + pos = scalar(); + CImg::vector((ulongT)mp_vector_neq,pos,arg1,p1,arg2,p2,11,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]!=mem[arg2]); + _cimg_mp_scalar2(mp_neq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==') + _cimg_mp_op("Operator '=='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + if (arg1==arg2) _cimg_mp_return(1); + p1 = _cimg_mp_size(arg1); + p2 = _cimg_mp_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_vector_eq,pos,arg1,p1,arg2,p2,11,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]==mem[arg2]); + _cimg_mp_scalar2(mp_eq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=') + _cimg_mp_op("Operator '<='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]<=mem[arg2]); + if (arg1==arg2) _cimg_mp_return(1); + _cimg_mp_scalar2(mp_lte,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=') + _cimg_mp_op("Operator '>='"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>=mem[arg2]); + if (arg1==arg2) _cimg_mp_return(1); + _cimg_mp_scalar2(mp_gte,arg1,arg2); + } + + for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) + if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<') + _cimg_mp_op("Operator '<'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]ss; --s, --ns, --ps) + if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greater than ('>') + _cimg_mp_op("Operator '>'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>mem[arg2]); + if (arg1==arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_gt,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<') + _cimg_mp_op("Operator '<<'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_left_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]<<(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_left_shift,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>') + _cimg_mp_op("Operator '>>'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_right_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]>>(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_right_shift,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='+' && (*ns!='+' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Addition ('+') + _cimg_mp_op("Operator '+'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] + mem[arg2]); + if (code) { // Try to spot linear case 'a*b + c' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_linear_add,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_increment,arg1); + if (arg1==1) _cimg_mp_scalar1(mp_increment,arg2); + _cimg_mp_scalar2(mp_add,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='-' && (*ns!='-' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Subtraction ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_vector1_v(mp_minus,arg2); + _cimg_mp_vector2_sv(mp_sub,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] - mem[arg2]); + if (!arg1) _cimg_mp_scalar1(mp_minus,arg2); + if (code) { // Try to spot linear cases 'a*b - c' and 'c - a*b' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)(arg3==arg1?mp_linear_sub_left:mp_linear_sub_right), + arg3,arg4,arg5,arg3==arg1?arg2:arg1).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_decrement,arg1); + _cimg_mp_scalar2(mp_sub,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex multiplication ('**') + _cimg_mp_op("Operator '**'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_mul,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//') + _cimg_mp_op("Operator '//'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_vv,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_sv,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*') + _cimg_mp_op("Operator '*'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + p2 = _cimg_mp_size(arg2); + if (p2>0 && (ulongT)_cimg_mp_size(arg1)==(ulongT)p2*p2) { // Particular case of matrix multiplication + pos = vector(p2); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,p2,p2,1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + + if (code) { // Try to spot double multiplication 'a*b*c' + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_mul2,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/') + _cimg_mp_op("Operator '/'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2, ns = se1; s>ss; --s, --ns) + if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%') + _cimg_mp_op("Operator '%'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(cimg::mod(mem[arg1],mem[arg2])); + _cimg_mp_scalar2(mp_modulo,arg1,arg2); + } + + if (se1>ss) { + if (*ss=='+' && (*ss1!='+' || (ss2='0' && *ss2<='9'))) { // Unary plus ('+') + _cimg_mp_op("Operator '+'"); + _cimg_mp_return(compile(ss1,se,depth1,0,is_critical)); + } + + if (*ss=='-' && (*ss1!='-' || (ss2='0' && *ss2<='9'))) { // Unary minus ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]); + _cimg_mp_scalar1(mp_minus,arg1); + } + + if (*ss=='!') { // Logical not ('!') + _cimg_mp_op("Operator '!'"); + if (*ss1=='!') { // '!!expr' optimized as 'bool(expr)' + arg1 = compile(ss2,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((bool)mem[arg1]); + _cimg_mp_scalar1(mp_bool,arg1); + } + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]); + _cimg_mp_scalar1(mp_logical_not,arg1); + } + + if (*ss=='~') { // Bitwise not ('~') + _cimg_mp_op("Operator '~'"); + arg1 = compile(ss1,se,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned int)mem[arg1]); + _cimg_mp_scalar1(mp_bitwise_not,arg1); + } + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^') + _cimg_mp_op("Operator '^^'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 2,se,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + pos = vector(2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) + CImg::vector((ulongT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code); + else if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)mp_complex_pow_vs,pos,arg1,arg2).move_to(code); + else if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + CImg::vector((ulongT)mp_complex_pow_sv,pos,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_ss,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^') + _cimg_mp_op("Operator '^'"); + arg1 = compile(ss,s,depth1,0,is_critical); + arg2 = compile(s + 1,se,depth1,0,is_critical); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(std::pow(mem[arg1],mem[arg2])); + switch (arg2) { + case 0 : _cimg_mp_return(1); + case 2 : _cimg_mp_scalar1(mp_sqr,arg1); + case 3 : _cimg_mp_scalar1(mp_pow3,arg1); + case 4 : _cimg_mp_scalar1(mp_pow4,arg1); + default : + if (_cimg_mp_is_constant(arg2)) { + if (mem[arg2]==0.5) { _cimg_mp_scalar1(mp_sqrt,arg1); } + else if (mem[arg2]==0.25) { _cimg_mp_scalar1(mp_pow0_25,arg1); } + } + _cimg_mp_scalar2(mp_pow,arg1,arg2); + } + } + + // Percentage computation. + if (*se1=='%') { + arg1 = compile(ss,se1,depth1,0,is_critical); + arg2 = _cimg_mp_is_constant(arg1)?0:constant(100); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(mem[arg1]/100); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + is_sth = ss1ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment + if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) { + _cimg_mp_op("Operator '++'"); + op = mp_self_increment; + } else { + _cimg_mp_op("Operator '--'"); + op = mp_self_decrement; + } + ref.assign(7); + arg1 = is_sth?compile(ss2,se,depth1,ref,is_critical): + compile(ss,se2,depth1,ref,is_critical); // Variable slot + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_reserved(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (is_sth) pos = arg1; // Determine return index, depending on pre/post action + else { + if (_cimg_mp_is_vector(arg1)) pos = vector_copy(arg1); + else pos = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k]++ + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,1).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + _cimg_mp_return(pos); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off]++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++ + if (!is_critical) is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++ + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_reserved(arg1)) { // Scalar variable: s++ + CImg::vector((ulongT)op,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (is_sth) variable_name.assign(ss2,(unsigned int)(se - ss1)); + else variable_name.assign(ss,(unsigned int)(se1 - ss)); + variable_name.back() = 0; + cimg::strpare(variable_name,false,true); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Array-like access to vectors and image values 'i/j/I/J[_#ind,offset,_boundary]' and 'vector[offset]'. + if (*se1==']') { + _cimg_mp_op("Value accessor '[]'"); + + // Find opening bracket for the offset. + s0 = se1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { s1 = s0; do { --s1; } while (cimg::is_blank(*s1)); cimg::swap(*s0,*++s1); } + is_sth=s0>ss && *(s0-1)==']'; // Particular case s.a. '..[..][..]' ? + is_relative = *ss=='j' || *ss=='J'; + + if (!is_sth && (*ss=='I' || *ss=='J') && *ss1=='[' && + (reserved_label[(int)*ss]==~0U || + !_cimg_mp_is_vector(reserved_label[(int)*ss]))) { // Image value as a vector + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0::vector((ulongT)(is_relative?mp_list_Joff:mp_list_Ioff), + pos,p1,arg1,arg2==~0U?_cimg_mp_boundary:arg2,p2).move_to(code); + } else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Joff:mp_Ioff), + pos,arg1,arg2==~0U?_cimg_mp_boundary:arg2,p2).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!is_sth && (*ss=='i' || *ss=='j') && *ss1=='[' && + (reserved_label[(int)*ss]==~0U || + !_cimg_mp_is_vector(reserved_label[(int)*ss]))) { // Image value as a scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { // Vector element + arg1 = compile(ss,s0,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Array brackets used on non-vector variable '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + s1 = s0 + 1; while (s1 sub-vector extraction + p1 = _cimg_mp_size(arg1); + arg2 = compile(++s0,s1,depth1,0,is_critical); // Starting index + s0 = ++s1; while (s0::vector((ulongT)mp_vector_crop,pos,arg1,p1,arg2,arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // One argument -> vector value reference + arg2 = compile(++s0,se1,depth1,0,is_critical); + if (_cimg_mp_is_constant(arg2)) { // Constant index + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_size(arg1)) _cimg_mp_return(arg1 + 1 + nb); + variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Out-of-bounds reference '%s[%d]' " + "(vector '%s' has dimension %u), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data,nb, + variable_name._data,_cimg_mp_size(arg1), + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -1; // Prevent from being used in further optimization + } + pos = scalar3(mp_vector_off,arg1,_cimg_mp_size(arg1),arg2); + memtype[pos] = -1; // Prevent from being used in further optimization + _cimg_mp_return(pos); + } + } + + // Look for a function call, an access to image value, or a parenthesis. + if (*se1==')') { + if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref,is_critical)); // Simple parentheses + _cimg_mp_op("Value accessor '()'"); + is_relative = *ss=='j' || *ss=='J'; + s0 = s1 = std::strchr(ss,'('); if (s0) { do { --s1; } while (cimg::is_blank(*s1)); cimg::swap(*s0,*++s1); } + + // I/J(_#ind,_x,_y,_z,_interpolation,_boundary_conditions) + if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + if (s1::vector((ulongT)(is_relative?mp_list_Jxyz:mp_list_Ixyz), + pos,p1,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5,p2).move_to(code); + else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Jxyz:mp_Ixyz), + pos,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5,p2).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + // i/j(_#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions) + if ((*ss=='i' || *ss=='j') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + if (s1::vector((ulongT)(*ss3=='0'?mp_arg0:mp_arg),0,0,p2,arg1,arg2).move_to(l_opcode); + for (s = ++s2; s::vector(arg3).move_to(l_opcode); + ++p3; + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (_cimg_mp_is_constant(arg1)) { + p3-=1; // Number of args + if (*ss3=='0') arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1] + 1); + else arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1]); + if (arg1::vector((ulongT)mp_break,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"breakpoint(",11)) { // Break point (for abort test) + _cimg_mp_op("Function 'breakpoint()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_breakpoint,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"bool(",5)) { // Boolean cast + _cimg_mp_op("Function 'bool()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((bool)mem[arg1]); + _cimg_mp_scalar1(mp_bool,arg1); + } + + if (!std::strncmp(ss,"begin(",6)) { // Begin + _cimg_mp_op("Function 'begin()'"); + code.swap(code_begin); + arg1 = compile(ss6,se1,depth1,p_ref,true); + code.swap(code_begin); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"begin_t(",8)) { // Begin thread + _cimg_mp_op("Function 'begin_t()'"); + code.swap(code_begin_t); + arg1 = compile(ss8,se1,depth1,p_ref,true); + code.swap(code_begin_t); + _cimg_mp_return(arg1); + } + break; + + case 'c' : + if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value + _cimg_mp_op("Function 'cabs()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_scalar2(mp_complex_abs,arg1,0); + _cimg_mp_scalar2(mp_complex_abs,arg1 + 1,arg1 + 2); + } + + if (!std::strncmp(ss,"carg(",5)) { // Complex argument + _cimg_mp_op("Function 'carg()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_scalar2(mp_atan2,0,arg1); + _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1); + } + + if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root + _cimg_mp_op("Function 'cbrt()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::cbrt(mem[arg1])); + _cimg_mp_scalar1(mp_cbrt,arg1); + } + + if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate + _cimg_mp_op("Function 'cconj()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_conj,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_conj,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ceil(",5)) { // Ceil + _cimg_mp_op("Function 'ceil()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_ceil,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::ceil(mem[arg1])); + _cimg_mp_scalar1(mp_ceil,arg1); + } + + if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential + _cimg_mp_op("Function 'cexp()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_exp,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_exp,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm + _cimg_mp_op("Function 'clog()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_log,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_log,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ccos(",5)) { // Complex cosine + _cimg_mp_op("Function 'ccos()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_cos,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_cos,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"csin(",5)) { // Complex sine + _cimg_mp_op("Function 'csin()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_sin,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_sin,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ctan(",5)) { // Complex tangent + _cimg_mp_op("Function 'ctan()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_tan,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_tan,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ccosh(",6)) { // Complex hyperbolic cosine + _cimg_mp_op("Function 'ccosh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_cosh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_cosh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"csinh(",6)) { // Complex hyperbolic sine + _cimg_mp_op("Function 'csinh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_sinh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_sinh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ctanh(",6)) { // Complex hyperbolic tangent + _cimg_mp_op("Function 'ctanh()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,0,3,2); + pos = vector(2); + if (_cimg_mp_is_scalar(arg1)) CImg::vector((ulongT)mp_complex_tanh,pos,arg1,0).move_to(code); + else CImg::vector((ulongT)mp_complex_tanh,pos,arg1 + 1,arg1 + 2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"continue(",9)) { // Continue loop + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_continue,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"copy(",5)) { // Memory copy + _cimg_mp_op("Function 'copy()'"); + ref.assign(14); + s1 = ss5; while (s1=4 && arg4==~0U) arg4 = scalar1(mp_image_whd,ref[1]); + } + if (_cimg_mp_is_vector(arg2)) { + if (arg3==~0U) arg3 = constant(_cimg_mp_size(arg2)); + if (!ref[7]) ++arg2; + if (ref[7]>=4 && arg5==~0U) arg5 = scalar1(mp_image_whd,ref[8]); + } + if (arg3==~0U) arg3 = 1; + if (arg4==~0U) arg4 = 1; + if (arg5==~0U) arg5 = 1; + _cimg_mp_check_type(arg3,3,1,0); + _cimg_mp_check_type(arg4,4,1,0); + _cimg_mp_check_type(arg5,5,1,0); + _cimg_mp_check_type(arg6,5,1,0); + CImg(1,22).move_to(code); + code.back().get_shared_rows(0,7).fill((ulongT)mp_memcopy,p1,arg1,arg2,arg3,arg4,arg5,arg6); + code.back().get_shared_rows(8,21).fill(ref); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"cos(",4)) { // Cosine + _cimg_mp_op("Function 'cos()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1])); + _cimg_mp_scalar1(mp_cos,arg1); + } + + if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine + _cimg_mp_op("Function 'cosh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1])); + _cimg_mp_scalar1(mp_cosh,arg1); + } + + if (!std::strncmp(ss,"critical(",9)) { // Critical section (single thread at a time) + _cimg_mp_op("Function 'critical()'"); + p1 = code._width; + arg1 = compile(ss + 9,se1,depth1,p_ref,true); + CImg::vector((ulongT)mp_critical,arg1,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"crop(",5)) { // Image crop + _cimg_mp_op("Function 'crop()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::sequence(_cimg_mp_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_size(arg1)); + opcode.resize(1,std::min(opcode._height,4U),1,1,0).move_to(l_opcode); + is_sth = true; + } else { + _cimg_mp_check_type(arg1,pos + 1,1,0); + CImg::vector(arg1).move_to(l_opcode); + } + s = ns; + } + (l_opcode>'y').move_to(opcode); + + arg1 = 0; arg2 = (p1!=~0U); + switch (opcode._height) { + case 0 : case 1 : + CImg::vector(0,0,0,0,~0U,~0U,~0U,~0U,0).move_to(opcode); + break; + case 2 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,_cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + 2; + break; + case 3 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,opcode[2]).move_to(opcode); + arg1 = arg2 + 2; + break; + case 4 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,_cimg_mp_boundary). + move_to(opcode); + arg1 = arg2 + (is_sth?2:3); + break; + case 5 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,opcode[4]). + move_to(opcode); + arg1 = arg2 + (is_sth?2:3); + break; + case 6 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + _cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + (is_sth?2:4); + break; + case 7 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + opcode[6]).move_to(opcode); + arg1 = arg2 + (is_sth?2:4); + break; + case 8 : + CImg::vector(*opcode,opcode[1],opcode[2],opcode[3],opcode[4],opcode[5],opcode[6], + opcode[7],_cimg_mp_boundary).move_to(opcode); + arg1 = arg2 + (is_sth?2:5); + break; + case 9 : + arg1 = arg2 + (is_sth?2:5); + break; + default : // Error -> too much arguments + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Too much arguments specified, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + _cimg_mp_check_type((unsigned int)*opcode,arg2 + 1,1,0); + _cimg_mp_check_type((unsigned int)opcode[1],arg2 + 1 + (is_sth?0:1),1,0); + _cimg_mp_check_type((unsigned int)opcode[2],arg2 + 1 + (is_sth?0:2),1,0); + _cimg_mp_check_type((unsigned int)opcode[3],arg2 + 1 + (is_sth?0:3),1,0); + if (opcode[4]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[4],arg1,3); + opcode[4] = (ulongT)mem[opcode[4]]; + } + if (opcode[5]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[5],arg1 + 1,3); + opcode[5] = (ulongT)mem[opcode[5]]; + } + if (opcode[6]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[6],arg1 + 2,3); + opcode[6] = (ulongT)mem[opcode[6]]; + } + if (opcode[7]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[7],arg1 + 3,3); + opcode[7] = (ulongT)mem[opcode[7]]; + } + _cimg_mp_check_type((unsigned int)opcode[8],arg1 + 4,1,0); + + if (opcode[4]==(ulongT)~0U || opcode[5]==(ulongT)~0U || + opcode[6]==(ulongT)~0U || opcode[7]==(ulongT)~0U) { + p2 = 0; + if (p1!=~0U) { + _cimg_mp_check_constant(p1,1,1); + p2 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + } + const CImg &img = p1!=~0U?listin[p2]:imgin; + if (!img) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Cannot crop empty image when " + "some xyzc-coordinates are unspecified, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (opcode[4]==(ulongT)~0U) opcode[4] = (ulongT)img._width; + if (opcode[5]==(ulongT)~0U) opcode[5] = (ulongT)img._height; + if (opcode[6]==(ulongT)~0U) opcode[6] = (ulongT)img._depth; + if (opcode[7]==(ulongT)~0U) opcode[7] = (ulongT)img._spectrum; + } + + pos = vector((unsigned int)(opcode[4]*opcode[5]*opcode[6]*opcode[7])); + CImg::vector((ulongT)mp_crop, + pos,p1, + *opcode,opcode[1],opcode[2],opcode[3], + opcode[4],opcode[5],opcode[6],opcode[7], + opcode[8]).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cross(",6)) { // Cross product + _cimg_mp_op("Function 'cross()'"); + s1 = ss6; while (s1::vector((ulongT)mp_cross,pos,arg1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cut(",4)) { // Cut + _cimg_mp_op("Function 'cut()'"); + s1 = ss4; while (s1val2?val2:val); + } + _cimg_mp_scalar3(mp_cut,arg1,arg2,arg3); + } + + if (!std::strncmp(ss,"convolve(",9) || !std::strncmp(ss,"correlate(",10)) { // Convolve & Correlate + is_sth = *ss2=='n'; // is_convolve? + _cimg_mp_op(is_sth?"Function 'convolve()'":"Function 'correlate()'"); + op = is_sth?mp_convolve:mp_correlate; + const ulongT default_params[] = { (ulongT)op,0, // [0]=function, [1]=result vector + 0,0,0,0,0, // [2]=A, [3]=wA, [4]=hA, [5]=dA, [6]=sA + 0,0,0,0,0, // [7]=M, [8]=wM, [9]=hM, [10]=dM, [11]=sM + 1,0,1, // [12]=boundary_conditions, [13]=is_normalized, [14]=chan._mode + 11,11,11, // [15]=xcenter, [16]=ycenter, [17]=zcenter (default value:-1) + 0,0,0, // [18]=xstart, [19]=ystart, [20]=zstart + 11,11,11, // [21]=xend, [22]=yend, [23]=zend (default value: -1) + 1,1,1, // [24]=xstride, [25]=ystride, [26]=zstride + 1,1,1 }; // [27]=xdilation, [28]=ydilation, [29]=zdilation + + l_opcode.assign(); // Don't use 'opcode': it could be modified by further calls to 'compile()'! + CImg(default_params,1,sizeof(default_params)/sizeof(ulongT)).move_to(l_opcode); + + arg1 = 2; + for (s = std::strchr(ss,'(') + 1; s=opcode._height) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: %s arguments provided, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1<12?"Not enough":"Too much", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(opcode[2],1,2,0); // A + _cimg_mp_check_constant(opcode[3],2,3); // wA + _cimg_mp_check_constant(opcode[4],3,3); // hA + _cimg_mp_check_constant(opcode[5],4,3); // dA + _cimg_mp_check_constant(opcode[6],5,3); // sA + _cimg_mp_check_type(opcode[7],6,2,0); // M + _cimg_mp_check_constant(opcode[8],7,3); // wM + _cimg_mp_check_constant(opcode[9],8,3); // hM + _cimg_mp_check_constant(opcode[10],9,3); // dM + _cimg_mp_check_constant(opcode[11],10,3); // sM + _cimg_mp_check_type(opcode[12],11,1,0); // boundary_conditions + _cimg_mp_check_type(opcode[13],12,1,0); // is_normalized + _cimg_mp_check_constant(opcode[14],13,1); // channel_mode + _cimg_mp_check_type(opcode[15],14,1,0); // xcenter + _cimg_mp_check_type(opcode[16],15,1,0); // ycenter + _cimg_mp_check_type(opcode[17],16,1,0); // zcenter + _cimg_mp_check_constant(opcode[18],17,1); // xstart + _cimg_mp_check_constant(opcode[19],18,1); // ystart + _cimg_mp_check_constant(opcode[20],19,1); // zstart + _cimg_mp_check_constant(opcode[21],20,1); // xend + _cimg_mp_check_constant(opcode[22],21,1); // yend + _cimg_mp_check_constant(opcode[23],22,1); // zend + _cimg_mp_check_constant(opcode[24],23,3); // xstride + _cimg_mp_check_constant(opcode[25],24,3); // ystride + _cimg_mp_check_constant(opcode[26],25,3); // zstride + _cimg_mp_check_type(opcode[27],26,1,0); // xdilation + _cimg_mp_check_type(opcode[28],27,1,0); // ydilation + _cimg_mp_check_type(opcode[29],28,1,0); // zdilation + + const unsigned int + wA = (unsigned int)mem[opcode[3]], + hA = (unsigned int)mem[opcode[4]], + dA = (unsigned int)mem[opcode[5]], + sA = (unsigned int)mem[opcode[6]], + wM = (unsigned int)mem[opcode[8]], + hM = (unsigned int)mem[opcode[9]], + dM = (unsigned int)mem[opcode[10]], + sM = (unsigned int)mem[opcode[11]], + channel_mode = (unsigned int)mem[opcode[14]], + xstart = std::min((unsigned int)mem[opcode[18]],wA - 1), + ystart = std::min((unsigned int)mem[opcode[19]],hA - 1), + zstart = std::min((unsigned int)mem[opcode[20]],dA - 1), + xend = std::min((unsigned int)mem[opcode[21]],wA - 1), + yend = std::min((unsigned int)mem[opcode[22]],hA - 1), + zend = std::min((unsigned int)mem[opcode[23]],dA - 1); + + if (xstart>xend || ystart>yend || zstart>zend) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid xyz-start/end arguments " + "(start = (%u,%u,%u), end = (%u,%u,%u)), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + xstart,ystart,zstart,xend,yend,zend, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + const float + xstride = (float)mem[opcode[24]], + ystride = (float)mem[opcode[25]], + zstride = (float)mem[opcode[26]]; + + if (xstride<=0 || ystride<=0 || zstride<=0) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid stride arguments (%g,%g,%g), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + xstride,ystride,zstride, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + arg2 = 1 + (unsigned int)std::floor((xend - xstart)/xstride); + arg3 = 1 + (unsigned int)std::floor((yend - ystart)/ystride); + arg4 = 1 + (unsigned int)std::floor((zend + zstart)/zstride); + arg5 = channel_mode==0?sM:channel_mode==1?std::max(sA,sM):sA*sM; + + opcode[1] = pos = vector(arg2*arg3*arg4*arg5); + opcode[3] = (ulongT)wA; + opcode[4] = (ulongT)hA; + opcode[5] = (ulongT)dA; + opcode[6] = (ulongT)sA; + opcode[8] = (ulongT)wM; + opcode[9] = (ulongT)hM; + opcode[10] = (ulongT)dM; + opcode[11] = (ulongT)sM; + opcode[14] = (ulongT)channel_mode; + opcode[18] = (ulongT)xstart; + opcode[19] = (ulongT)ystart; + opcode[20] = (ulongT)zstart; + opcode[21] = (ulongT)xend; + opcode[22] = (ulongT)yend; + opcode[23] = (ulongT)zend; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'd' : + if (*ss1=='(') { // Image depth + _cimg_mp_op("Function 'd()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_d,p1); + } + + if (!std::strncmp(ss,"date(",5)) { // Current date or file date + _cimg_mp_op("Function 'date()'"); + s1 = ss5; while (s1::vector((ulongT)mp_date,pos,_cimg_mp_size(pos), + arg1,arg1==~0U?~0U:_cimg_mp_size(arg1), + arg2,arg2==~0U?~0U:_cimg_mp_size(arg2)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"debug(",6)) { // Print debug info + _cimg_mp_op("Function 'debug()'"); + p1 = code._width; + arg1 = compile(ss6,se1,depth1,p_ref,is_critical); + *se1 = 0; + variable_name.assign(CImg::string(ss6,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + ((CImg::vector((ulongT)mp_debug,arg1,0,code._width - p1), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code,p1); + *se1 = ')'; + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"display(",8)) { // Display memory, vector or image + _cimg_mp_op("Function 'display()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_display_memory,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return_nan(); + } + if (*ss8!='#') { // Vector + s1 = ss8; while (s1::string(ss8,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + if (_cimg_mp_is_vector(arg1)) + ((CImg::vector((ulongT)mp_vector_print,arg1,0,(ulongT)_cimg_mp_size(arg1),0), + variable_name)>'y').move_to(opcode); + else + ((CImg::vector((ulongT)mp_print,arg1,0,0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + + ((CImg::vector((ulongT)mp_display,arg1,0,(ulongT)_cimg_mp_size(arg1), + arg2,arg3,arg4,arg5), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *s1 = c1; + _cimg_mp_return(arg1); + + } else { // Image + p1 = compile(ss8 + 1,se1,depth1,0,is_critical); + _cimg_mp_check_list(true); + CImg::vector((ulongT)mp_image_display,_cimg_mp_slot_nan,p1).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"det(",4)) { // Matrix determinant + _cimg_mp_op("Function 'det()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + _cimg_mp_scalar2(mp_det,arg1,p1); + } + + if (!std::strncmp(ss,"diag(",5)) { // Diagonal matrix + _cimg_mp_op("Function 'diag()'"); + CImg::vector((ulongT)mp_diag,0,0).move_to(l_opcode); + for (s = ss5; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + arg1 = opcode._height - 3; + pos = vector(arg1*arg1); + opcode[1] = pos; + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"dot(",4)) { // Dot product + _cimg_mp_op("Function 'dot()'"); + s1 = ss4; while (s1::vector((ulongT)mp_do,p1,p2,arg2 - arg1,code._width - arg2,_cimg_mp_size(p1), + p1>=arg6 && !_cimg_mp_is_constant(p1), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"draw(",5)) { // Draw image + if (!is_critical) is_parallelizable = false; + _cimg_mp_op("Function 'draw()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s01) { + arg3 = arg2 + 1; + if (p2>2) { + arg4 = arg3 + 1; + if (p2>3) arg5 = arg4 + 1; + } + } + ++s0; + is_sth = true; + } else { + if (s0::vector((ulongT)mp_draw,arg1,(ulongT)_cimg_mp_size(arg1),p1,arg2,arg3,arg4,arg5, + 0,0,0,0,1,(ulongT)~0U,0,1).move_to(l_opcode); + + arg2 = arg3 = arg4 = arg5 = ~0U; + p2 = p1!=~0U?0:1; + if (s0::vector((ulongT)mp_echo,_cimg_mp_slot_nan,0).move_to(l_opcode); + for (s = ss5; s::vector(arg1,_cimg_mp_size(arg1)).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"eig(",4)) { // Matrix eigenvalues/eigenvector + _cimg_mp_op("Function 'eig()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + pos = vector((p1 + 1)*p1); + CImg::vector((ulongT)mp_matrix_eig,pos,arg1,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"ellipse(",8)) { // Ellipse/circle drawing + if (!is_critical) is_parallelizable = false; + _cimg_mp_op("Function 'ellipse()'"); + if (*ss8=='#') { // Index specified + s0 = ss + 9; while (s0::vector((ulongT)mp_ellipse,_cimg_mp_slot_nan,0,p1).move_to(l_opcode); + for (s = s0; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"erf(",4)) { // Error function + _cimg_mp_op("Function 'erf()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_erf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::erf(mem[arg1])); + _cimg_mp_scalar1(mp_erf,arg1); + } + + if (!std::strncmp(ss,"erfinv(",7)) { // Inverse of error function + _cimg_mp_op("Function 'erfinv()'"); + arg1 = compile(ss7,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_erfinv,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::erfinv(mem[arg1])); + _cimg_mp_scalar1(mp_erfinv,arg1); + } + + if (!std::strncmp(ss,"exp(",4)) { // Exponential + _cimg_mp_op("Function 'exp()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1])); + _cimg_mp_scalar1(mp_exp,arg1); + } + + if (!std::strncmp(ss,"expr(",5)) { // Vector from expression + _cimg_mp_op("Function 'expr()'"); + s1 = ss5; while (s1::vector((ulongT)mp_expr,pos,arg1,p1,arg2,arg3,arg4,arg5).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"eye(",4)) { // Identity matrix + _cimg_mp_op("Function 'eye()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_constant(arg1,1,3); + p1 = (unsigned int)mem[arg1]; + pos = vector(p1*p1); + CImg::vector((ulongT)mp_eye,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"end(",4)) { // End + _cimg_mp_op("Function 'end()'"); + code.swap(code_end); + compile(ss4,se1,depth1,p_ref,true); + code.swap(code_end); + is_end_code = true; + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"end_t(",6)) { // End thread + _cimg_mp_op("Function 'end_t()'"); + code.swap(code_end_t); + compile(ss6,se1,depth1,p_ref,true); + code.swap(code_end_t); + is_end_code = true; + _cimg_mp_return_nan(); + } + break; + + case 'f' : + if (!std::strncmp(ss,"f2ui(",5)) { // Special float->uint conversion + _cimg_mp_op("Function 'f2ui()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_f2ui,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((double)cimg::float2uint((float)mem[arg1])); + _cimg_mp_scalar1(mp_f2ui,arg1); + } + + if (!std::strncmp(ss,"fact(",5)) { // Factorial + _cimg_mp_op("Function 'fact()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_factorial,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::factorial((int)mem[arg1])); + _cimg_mp_scalar1(mp_factorial,arg1); + } + + if (!std::strncmp(ss,"fibo(",5)) { // Fibonacci + _cimg_mp_op("Function 'fibo()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_fibonacci,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::fibonacci((int)mem[arg1])); + _cimg_mp_scalar1(mp_fibonacci,arg1); + } + + if (!std::strncmp(ss,"fill(",5)) { // Fill + _cimg_mp_op("Function 'fill()'"); + s0 = ss5; while (s0::%s: %s: Target scalar is constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss>expr._data?"...":"",ss,se<&expr.back()?"...":""); + s1 = ++s0; while (s1::%s: %s: Invalid loop variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + get_variable_pos(variable_name,arg2,arg3); + arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot + if (arg2!=~0U && (!_cimg_mp_is_scalar(arg2) || + _cimg_mp_is_constant(arg2))) { // Variable is not a vector or is a constant -> error + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' " + "(expected 'scalar'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg2)._data,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (arg2==~0U) { // Variable does not exist -> create it + arg2 = scalar(); + if (arg3!=~0U) reserved_label[arg3] = arg2; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg2; + variable_name.move_to(variable_def); + } + memtype[arg2] = -1; + } + arg3 = compile(++s1,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg3,3,1,0); + } else { // Version with 2 arguments + arg2 = ~0U; + arg3 = compile(s0,se1,depth1,0,is_critical); + } + // arg2 = variable slot, arg3 = fill expression. + _cimg_mp_check_type(arg3,3,1,0); + CImg::vector((ulongT)mp_fill,arg1,_cimg_mp_size(arg1),arg2,arg3,code._width - p1). + move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"find(",5)) { // Find + _cimg_mp_op("Function 'find()'"); + + // First argument: data to look at. + s0 = ss5; while (s01) + _cimg_mp_scalar5(mp_list_find_seq,p1,arg2,_cimg_mp_size(arg2),arg3,arg4); + _cimg_mp_scalar4(mp_list_find,p1,arg2 + (_cimg_mp_size(arg2)?1:0),arg3,arg4); + } + if (_cimg_mp_size(arg2)>1) + _cimg_mp_scalar6(mp_find_seq,arg1,_cimg_mp_size(arg1),arg2,_cimg_mp_size(arg2),arg3,arg4); + _cimg_mp_scalar5(mp_find,arg1,_cimg_mp_size(arg1),arg2 + (_cimg_mp_size(arg2)?1:0),arg3,arg4); + } + + if (*ss1=='o' && *ss2=='r' && *ss3=='(') { // For loop + _cimg_mp_op("Function 'for()'"); + s1 = ss4; while (s1::vector((ulongT)mp_for,p3,(ulongT)_cimg_mp_size(p3),p2,arg2 - arg1,arg3 - arg2, + arg4 - arg3,code._width - arg4, + p3>=arg6 && !_cimg_mp_is_constant(p3), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p3); + } + + if (!std::strncmp(ss,"floor(",6)) { // Floor + _cimg_mp_op("Function 'floor()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_floor,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::floor(mem[arg1])); + _cimg_mp_scalar1(mp_floor,arg1); + } + + if (!std::strncmp(ss,"fsize(",6)) { // File size + _cimg_mp_op("Function 'fsize()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_type(arg1,1,2,0); + pos = scalar(); + CImg::vector((ulongT)mp_fsize,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'g' : + if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function + _cimg_mp_op("Function 'gauss()'"); + s1 = ss6; while (s1::vector((ulongT)mp_get,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + break; + + case 'h' : + if (*ss1=='(') { // Image height + _cimg_mp_op("Function 'h()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_h,p1); + } + break; + + case 'i' : + if (*ss1=='c' && *ss2=='(') { // Image median + _cimg_mp_op("Function 'ic()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + pos = scalar(); + CImg::vector((ulongT)mp_image_median,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (*ss1=='n' && *ss2=='(') { // Image norm + _cimg_mp_op("Function 'in()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + pos = scalar(); + CImg::vector((ulongT)mp_image_norm,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (*ss1=='f' && *ss2=='(') { // If..then[..else.] + _cimg_mp_op("Function 'if()'"); + s1 = ss3; while (s1::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"inrange(",8)) { // Check value range + _cimg_mp_op("Function 'inrange()'"); + s1 = ss8; while (s1=val1) + is_sth = (mem[arg4]?(val>=val1):(val>val1)) && (mem[arg5]?(val<=val2):(val=val2):(val>val2)) && (mem[arg4]?(val<=val1):(val::vector((ulongT)mp_inrange,pos,arg6,arg1,p1,arg2,p2,arg3,p3,arg4,arg5).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"int(",4)) { // Integer cast + _cimg_mp_op("Function 'int()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((longT)mem[arg1]); + _cimg_mp_scalar1(mp_int,arg1); + } + + if (!std::strncmp(ss,"invert(",7)) { // Matrix/scalar inversion + _cimg_mp_op("Function 'invert()'"); + s1 = ss7; while (s1::vector((ulongT)mp_matrix_invert,pos,arg1,p1,arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(1/mem[arg1]); + _cimg_mp_scalar2(mp_div,1,arg1); + } + + if (*ss1=='s') { // Family of 'is_?()' functions + + if (!std::strncmp(ss,"isbool(",7)) { // Is boolean? + _cimg_mp_op("Function 'isbool()'"); + if (ss7==se1) _cimg_mp_return(0); + try { arg1 = compile(ss7,se1,depth1,0,is_critical); } + catch(CImgException&) { _cimg_mp_return(0); } + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return(mem[arg1]==0. || mem[arg1]==1.); + _cimg_mp_scalar1(mp_isbool,arg1); + } + + if (!std::strncmp(ss,"isdir(",6)) { // Is directory? + _cimg_mp_op("Function 'isdir()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_isdir,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isfile(",7)) { // Is file? + _cimg_mp_op("Function 'isfile()'"); + arg1 = compile(ss7,se1,depth1,0,is_critical); + if (_cimg_mp_is_scalar(arg1)) _cimg_mp_return(0); + pos = scalar(); + CImg::vector((ulongT)mp_isfile,pos,arg1,(ulongT)_cimg_mp_size(arg1)).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector? + if (ss5>=se1) _cimg_mp_return(0); + _cimg_mp_op("Function 'isin()'"); + pos = scalar(); + CImg::vector((ulongT)mp_isin,pos,0).move_to(l_opcode); + for (s = ss5; s::sequence(_cimg_mp_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_size(arg1)). + move_to(l_opcode); + else CImg::vector(arg1).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isinf(",6)) { // Is infinite? + _cimg_mp_op("Function 'isinf()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_inf(mem[arg1])); + _cimg_mp_scalar1(mp_isinf,arg1); + } + + if (!std::strncmp(ss,"isint(",6)) { // Is integer? + _cimg_mp_op("Function 'isint()'"); + if (ss6==se1) _cimg_mp_return(0); + try { arg1 = compile(ss6,se1,depth1,0,is_critical); } + catch(CImgException&) { _cimg_mp_return(0); } + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)((double)(longT)mem[arg1]==mem[arg1])); + _cimg_mp_scalar1(mp_isint,arg1); + } + + if (!std::strncmp(ss,"isnan(",6)) { // Is NaN? + _cimg_mp_op("Function 'isnan()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_nan(mem[arg1])); + _cimg_mp_scalar1(mp_isnan,arg1); + } + + if (!std::strncmp(ss,"isnum(",6)) { // Is number? + _cimg_mp_op("Function 'isnum()'"); + val = 0; + if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1); + _cimg_mp_return(0); + } + + if (!std::strncmp(ss,"isexpr(",7)) { // Is valid expression? + _cimg_mp_op("Function 'isexpr()'"); + if (ss7==se1) _cimg_mp_return(0); + try { arg1 = compile(ss7,se1,depth1,0,is_critical); } + catch (CImgException&) { _cimg_mp_return(0); } + _cimg_mp_return(1); + } + } + break; + + case 'l' : + if (*ss1=='(') { // Size of image list + _cimg_mp_op("Function 'l()'"); + if (ss2!=se1) break; + _cimg_mp_scalar0(mp_list_l); + } + + if (!std::strncmp(ss,"lerp(",5)) { // Linear interpolation + _cimg_mp_op("Function 'lerp()'"); + s1 = ss5; while (s1::vector((ulongT)mp_vector_lerp,pos,p1,arg1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"log(",4)) { // Natural logarithm + _cimg_mp_op("Function 'log()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1])); + _cimg_mp_scalar1(mp_log,arg1); + } + + if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm + _cimg_mp_op("Function 'log2()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1])); + _cimg_mp_scalar1(mp_log2,arg1); + } + + if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm + _cimg_mp_op("Function 'log10()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1])); + _cimg_mp_scalar1(mp_log10,arg1); + } + + if (!std::strncmp(ss,"lowercase(",10)) { // Lower case + _cimg_mp_op("Function 'lowercase()'"); + arg1 = compile(ss + 10,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_lowercase,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::lowercase(mem[arg1])); + _cimg_mp_scalar1(mp_lowercase,arg1); + } + break; + + case 'm' : + if (!std::strncmp(ss,"mul(",4)) { // Matrix multiplication + _cimg_mp_op("Function 'mul()'"); + s1 = ss4; while (s1::%s: %s: Types of first and second arguments ('%s' and '%s') " + "do not match with third argument 'nb_colsB=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data,p3, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"mproj(",6)) { // Project matrix onto dictionary + _cimg_mp_op("Function 'mproj()'"); + s1 = ss6; while (s1::%s: %s: Type of first argument ('%s') " + "do not match with second argument 'nb_colsS=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,wS, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (wD*hD!=p2) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Type of third argument ('%s') " + "do not match with fourth argument 'nb_colsD=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg3)._data,wD, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (hS!=hD) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Type of first argument ('%s') " + "do not match with third argument ('%s'), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg3)._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(wS*wD); + CImg::vector((ulongT)mp_mproj,pos,arg1,wS,hS,arg3,wD,arg5,arg6,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"merge(",6)) { // Merge inter-thread variables + _cimg_mp_op("Function 'merge()'"); + s1 = ss6; while (s1::%s: %s: Merge has already been requested before " + "for specified variable " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (arg1==~0U) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid specified operator " + "(should be one of '=,+,-,*,/,min,max'), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + memmerge.resize(3,memmerge._height + 1,1,1,0,0); + memmerge(0,memmerge._height - 1) = (int)pos; + memmerge(1,memmerge._height - 1) = (int)_cimg_mp_size(pos); + memmerge(2,memmerge._height - 1) = (int)arg1; + _cimg_mp_return(pos); + } + break; + + case 'n' : +#ifdef cimg_mp_func_name + if (!std::strncmp(ss,"name(",5)) { // Get image name as a string vector + _cimg_mp_op("Function 'name()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::vector((ulongT)mp_name,pos,p1,arg1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + + if (!std::strncmp(ss,"narg(",5)) { // Number of arguments + _cimg_mp_op("Function 'narg()'"); + if (ss5>=se1) _cimg_mp_return(0); + arg1 = 0; + for (s = ss5; s::vector((ulongT)mp_norm0,pos,0).move_to(l_opcode); break; + case 1 : + CImg::vector((ulongT)mp_norm1,pos,0).move_to(l_opcode); break; + case 2 : + CImg::vector((ulongT)mp_norm2,pos,0).move_to(l_opcode); break; + case ~0U : + CImg::vector((ulongT)mp_norminf,pos,0).move_to(l_opcode); break; + default : + CImg::vector((ulongT)mp_normp,pos,0,(ulongT)(arg1==~0U?-1:(int)arg1)). + move_to(l_opcode); + } + for ( ; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + + (l_opcode>'y').move_to(opcode); + if (arg1>0 && opcode._height==4) // Special case with one argument and p>=1 + _cimg_mp_scalar1(mp_abs,opcode[3]); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'p' : + if (!std::strncmp(ss,"permut(",7)) { // Number of permutations + _cimg_mp_op("Function 'permut()'"); + s1 = ss7; while (s1::vector((ulongT)mp_polygon,_cimg_mp_slot_nan,0,p1).move_to(l_opcode); + for (s = s0; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return_nan(); + } + + if (!std::strncmp(ss,"print(",6) || !std::strncmp(ss,"prints(",7)) { // Print expressions + is_sth = ss[5]=='s'; // is prints() + _cimg_mp_op(is_sth?"Function 'prints()'":"Function 'print()'"); + s0 = is_sth?ss7:ss6; + if (*s0!='#' || is_sth) { // Regular expression + for (s = s0; s::string(s,true,true).unroll('y'),true); + cimg::strpare(variable_name,false,true); + if (_cimg_mp_is_vector(pos)) // Vector + ((CImg::vector((ulongT)mp_vector_print,pos,0,(ulongT)_cimg_mp_size(pos),is_sth?1:0), + variable_name)>'y').move_to(opcode); + else // Scalar + ((CImg::vector((ulongT)mp_print,pos,0,is_sth?1:0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *ns = c1; s = ns; + } + _cimg_mp_return(pos); + } else { // Image + p1 = compile(ss7,se1,depth1,0,is_critical); + _cimg_mp_check_list(true); + CImg::vector((ulongT)mp_image_print,_cimg_mp_slot_nan,p1).move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"pseudoinvert(",13)) { // Matrix/scalar pseudo-inversion + _cimg_mp_op("Function 'pseudoinvert()'"); + s1 = ss + 13; while (s1::%s: %s: Type of first argument ('%s') " + "does not match with second argument 'nb_colsA=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1); + CImg::vector((ulongT)mp_matrix_pseudoinvert,pos,arg1,p2,p3,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'r' : + if (!std::strncmp(ss,"ref(",4)) { // Variable declaration + _cimg_mp_op("Function 'ref()'"); + s1 = ss4; while (s1=se1 || !*s1) compile(s1,s1,depth1,0,is_critical); // Will throw missing argument error + arg3 = compile(ss4,s1++,depth1,p_ref,is_critical); + *se1 = 0; + + if (!is_varname(s1)) { // Invalid variable name + variable_name.assign(s1,(unsigned int)(se1 + 1 - s1)).back() = 0; + cimg::strellipsize(variable_name,64); + *se1 = ')'; + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid specified variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + get_variable_pos(s1,arg1,arg2); + if (arg2!=~0U) reserved_label[arg2] = arg3; + else if (arg1!=~0U) variable_pos[arg1] = arg3; + else { // New variable + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg3; + CImg::string(s1).move_to(variable_def); + } + if (_cimg_mp_is_vector(arg3)) + set_reserved_vector(arg3); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -1; + *se1 = ')'; + _cimg_mp_return(arg3); + } + + if (!std::strncmp(ss,"repeat(",7)) { // Repeat + _cimg_mp_op("Function 'repeat()'"); + s0 = ss7; while (s0::%s: %s: Invalid loop variable name '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + get_variable_pos(variable_name,arg2,arg3); + arg2 = arg3!=~0U?reserved_label[arg3]:arg2!=~0U?variable_pos[arg2]:~0U; // Variable slot + if (arg2!=~0U && (!_cimg_mp_is_scalar(arg2) || + _cimg_mp_is_constant(arg2))) { // Variable is not a vector or is a constant -> error + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Invalid type '%s' for variable '%s' " + "(expected 'scalar'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg2)._data,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (arg2==~0U) { // Variable does not exist -> create it + arg2 = scalar(); + if (arg3!=~0U) reserved_label[arg3] = arg2; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg2; + variable_name.move_to(variable_def); + } + memtype[arg2] = -1; + } + arg3 = compile(++s1,se1,depth1,0,is_critical); + } else { // Version with 2 arguments + arg2 = ~0U; + arg3 = compile(s0,se1,depth1,0,is_critical); + } + // arg2 = variable slot, arg3 = fill expression. + CImg::vector((ulongT)mp_repeat,arg3,arg1,arg2,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg3); + } + + if (!std::strncmp(ss,"resize(",7)) { // Vector or image resize + _cimg_mp_op("Function 'resize()'"); + if (*ss7!='#') { // Vector + s1 = ss7; while (s1::vector((ulongT)mp_vector_resize,pos,arg2,arg1,(ulongT)_cimg_mp_size(arg1), + arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + + } else { // Image + if (!is_critical) is_parallelizable = false; + s0 = ss8; while (s0::vector((ulongT)mp_image_resize,_cimg_mp_slot_nan,p1,~0U,~0U,~0U,~0U,1,0,0,0,0,0). + move_to(l_opcode); + pos = 0; + for (s = s0; s10) { + _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: %s arguments, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + pos<1?"Missing":"Too much", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + l_opcode[0].move_to(code); + _cimg_mp_return_nan(); + } + } + + if (!std::strncmp(ss,"reverse(",8)) { // Vector reverse + _cimg_mp_op("Function 'reverse()'"); + arg1 = compile(ss8,se1,depth1,0,is_critical); + if (!_cimg_mp_is_vector(arg1)) _cimg_mp_return(arg1); + p1 = _cimg_mp_size(arg1); + pos = vector(p1); + CImg::vector((ulongT)mp_vector_reverse,pos,arg1,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation + _cimg_mp_op(ss[2]=='l'?"Function 'rol()'":"Function 'ror()'"); + s1 = ss4; while (s11) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + arg4 = compile(++s1,se1,depth1,0,is_critical); + } else { + s2 = s1 + 1; while (s2::vector((ulongT)mp_rot3d,pos,arg1,arg2,arg3,arg4).move_to(code); + } else { // 2D rotation + _cimg_mp_check_type(arg1,1,1,0); + pos = vector(4); + CImg::vector((ulongT)mp_rot2d,pos,arg1).move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"round(",6)) { // Value rounding + _cimg_mp_op("Function 'round()'"); + s1 = ss6; while (s1::vector((ulongT)mp_run,0,0).move_to(l_opcode); + pos = 1; + for (s = ss4; s::vector(arg1,_cimg_mp_size(arg1)).move_to(l_opcode); + s = ns; + } + (l_opcode>'y').move_to(opcode); + pos = scalar(); + opcode[1] = pos; + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } +#endif + break; + + case 's' : + if (*ss1=='(') { // Image spectrum + _cimg_mp_op("Function 's()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_s,p1); + } + + if (!std::strncmp(ss,"same(",5)) { // Test if operands have the same values + _cimg_mp_op("Function 'same()'"); + s1 = ss5; while (s1::vector((ulongT)mp_shift,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sign(",5)) { // Sign + _cimg_mp_op("Function 'sign()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1])); + _cimg_mp_scalar1(mp_sign,arg1); + } + + if (!std::strncmp(ss,"sin(",4)) { // Sine + _cimg_mp_op("Function 'sin()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1])); + _cimg_mp_scalar1(mp_sin,arg1); + } + + if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal + _cimg_mp_op("Function 'sinc()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1])); + _cimg_mp_scalar1(mp_sinc,arg1); + } + + if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine + _cimg_mp_op("Function 'sinh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1])); + _cimg_mp_scalar1(mp_sinh,arg1); + } + + if (!std::strncmp(ss,"size(",5)) { // Vector size + _cimg_mp_op("Function 'size()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_size(arg1)); + } + + if (!std::strncmp(ss,"solve(",6)) { // Solve square linear system + _cimg_mp_op("Function 'solve()'"); + s1 = ss6; while (s1::%s: %s: Types of first and second arguments ('%s' and '%s') " + "do not match with third argument 'nb_colsB=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data,p3, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sort(",5)) { // Sort vector + _cimg_mp_op("Function 'sort()'"); + s1 = ss5; while (s1::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3,arg4).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sqr(",4)) { // Square + _cimg_mp_op("Function 'sqr()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1])); + _cimg_mp_scalar1(mp_sqr,arg1); + } + + if (!std::strncmp(ss,"sqrt(",5)) { // Square root + _cimg_mp_op("Function 'sqrt()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1])); + _cimg_mp_scalar1(mp_sqrt,arg1); + } + + if (!std::strncmp(ss,"srand(",6)) { // Set RNG seed + _cimg_mp_op("Function 'srand()'"); + arg1 = ss6::vector((ulongT)mp_image_stats,pos,p1).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + +#ifdef cimg_mp_func_store + if (!std::strncmp(ss,"store(",6)) { // Store vector to variable + _cimg_mp_op("Function 'store()'"); + s1 = ss6; while (s1::vector((ulongT)mp_store,_cimg_mp_slot_nan,arg1,p1,arg2,p2, + arg3,arg4,arg5,arg6,pos).move_to(code); + _cimg_mp_return_nan(); + } +#endif + + if (!std::strncmp(ss,"stov(",5)) { // String to double + _cimg_mp_op("Function 'stov()'"); + s1 = ss5; while (s1::vector((ulongT)mp_stov,pos,arg1,p1,arg2,arg3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"string(",7)) { // Construct string from list of arguments + _cimg_mp_op("Function 'string()'"); + CImg::vector((ulongT)mp_string,0,0,0).move_to(l_opcode); + + if (*ss7=='#') { // Output vector size specified, with '#' + s0 = ss8; while (s0::vector(arg2,p2).move_to(l_opcode); + s = ns; + } + if (arg1==~0U) arg1 = p1; + pos = vector(arg1,0); + (l_opcode>'y').move_to(opcode); + opcode[1] = pos; + opcode[2] = arg1; + opcode[3] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"svd(",4)) { // Matrix SVD + _cimg_mp_op("Function 'svd()'"); + s1 = ss4; while (s1::%s: %s: Type of first argument ('%s') " + "does not match with second argument 'nb_colsA=%u', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1 + p2 + p2*p2); + CImg::vector((ulongT)mp_matrix_svd,pos,arg1,p2,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"swap(",5)) { // Swap values + _cimg_mp_op("Function 'swap()'"); + s1 = ss5; while (s1::%s: %s: %s argument cannot be a constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"First":"Second", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + CImg::vector((ulongT)mp_swap,arg1,arg2,p1).move_to(code); + + // Write back values of linked arg1 and arg2. + const unsigned int *_ref = ref; + is_sth = true; // Is first argument? + do { + switch (*_ref) { + case 1 : // arg1: V[k] + arg3 = _ref[1]; // Vector slot + arg4 = _ref[2]; // Index + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_size(arg3),arg4). + move_to(code); + break; + case 2 : // arg1: i/j[_#ind,off] + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // Offset + if (p1!=~0U) { + if (listout) + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (imgout) + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + break; + case 3 : // arg1: i/j(_#ind,_x,_y,_z,_c) + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // X + arg4 = _ref[4]; // Y + arg5 = _ref[5]; // Z + arg6 = _ref[6]; // C + if (p1!=~0U) { + if (listout) + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (imgout) + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + break; + case 4: // arg1: I/J[_#ind,off] + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // Offset + if (p1!=~0U) { + if (listout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg1,p1,arg3).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + } + } else { + if (imgout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg1,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3,_cimg_mp_size(arg1)).move_to(code); + } + } + break; + case 5 : // arg1: I/J(_#ind,_x,_y,_z,_c) + if (!is_critical) is_parallelizable = false; + p1 = _ref[1]; // Index + is_relative = (bool)_ref[2]; + arg3 = _ref[3]; // X + arg4 = _ref[4]; // Y + arg5 = _ref[5]; // Z + if (p1!=~0U) { + if (listout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg1,p1,arg3,arg4,arg5).move_to(code); + else { + _cimg_mp_check_constant_index(p1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + } else { + if (imgout) { + if (_cimg_mp_is_scalar(arg1)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg1,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5,_cimg_mp_size(arg1)).move_to(code); + } + } + break; + } + + _ref+=7; + arg1 = arg2; + is_sth = !is_sth; + } while (!is_sth); + + if (p_ref) std::memcpy(p_ref,ref,siz_ref); + _cimg_mp_return(arg1); + } + break; + + case 't' : + if (!std::strncmp(ss,"tan(",4)) { // Tangent + _cimg_mp_op("Function 'tan()'"); + arg1 = compile(ss4,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1])); + _cimg_mp_scalar1(mp_tan,arg1); + } + + if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent + _cimg_mp_op("Function 'tanh()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1])); + _cimg_mp_scalar1(mp_tanh,arg1); + } + + if (!std::strncmp(ss,"trace(",6)) { // Matrix trace + _cimg_mp_op("Function 'trace()'"); + arg1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)cimg::round(std::sqrt((float)_cimg_mp_size(arg1))); + _cimg_mp_scalar2(mp_trace,arg1,p1); + } + + if (!std::strncmp(ss,"transpose(",10)) { // Matrix transpose + _cimg_mp_op("Function 'transpose()'"); + s1 = ss + 10; while (s1::%s: %s: Size of first argument ('%s') does not match " + "second argument 'nb_cols=%u', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,p2, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p3*p2); + CImg::vector((ulongT)mp_transpose,pos,arg1,p2,p3).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'u' : + if (*ss1=='(') { // Random value with uniform distribution + _cimg_mp_op("Function 'u()'"); + if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1); + s1 = ss2; while (s1float conversion + _cimg_mp_op("Function 'ui2f()'"); + arg1 = compile(ss5,se1,depth1,0,is_critical); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_ui2f,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((double)cimg::uint2float((unsigned int)mem[arg1])); + _cimg_mp_scalar1(mp_ui2f,arg1); + } + + if (!std::strncmp(ss,"unref(",6)) { // Un-reference variable + _cimg_mp_op("Function 'unref()'"); + arg1=~0U; + for (s0 = ss6; s0ss6 && *s0==',') ++s0; + s1 = s0; while (s1s0) { + *s1 = 0; + get_variable_pos(s0,arg1,arg2); + if (arg2!=~0U) reserved_label[arg2] = ~0U; + else if (arg1!=~0U) { + variable_def.remove(arg1); + if (arg10) || + !std::strncmp(ss,"vector(",7) || + (!std::strncmp(ss,"vector",6) && ss7::sequence(arg4,arg3 + 1,arg3 + arg4).move_to(l_opcode); + arg2+=arg4; + } else { CImg::vector(arg3).move_to(l_opcode); ++arg2; } + s = ns; + } + if (arg1==~0U) arg1 = arg2; + if (!arg1) _cimg_mp_return(0); + pos = vector(arg1); + l_opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"vmax(",5) || !std::strncmp(ss,"vmin(",5) || + !std::strncmp(ss,"vmaxabs(",8) || !std::strncmp(ss,"vminabs(",8) || + !std::strncmp(ss,"vmed(",5) || !std::strncmp(ss,"vkth(",5) || + !std::strncmp(ss,"vsum(",5) || !std::strncmp(ss,"vavg(",5) || + !std::strncmp(ss,"vstd(",5) || !std::strncmp(ss,"vvar(",5) || + !std::strncmp(ss,"vprod(",6) || + !std::strncmp(ss,"vargmin(",8) || !std::strncmp(ss,"vargmax(",8) || + !std::strncmp(ss,"vargminabs(",11) || !std::strncmp(ss,"vargmaxabs(",11) || + !std::strncmp(ss,"vargkth(",8)) { // Multi-argument vector functions + _cimg_mp_op(ss[1]=='a'?(ss[2]=='v'?"Function 'vavg()'": + ss[4]=='k'?"Function 'vargkth()'": + ss[5]=='i' && ss[7]=='('?"Function 'vargmin()'": + ss[5]=='i'?"Function vargminabs()'": + ss[7]=='('?"Function 'vargmax()'": + "Function 'vargmaxabs()'"): + ss[1]=='s'?(ss[2]=='u'?"Function 'vsum()'":"Function 'vstd()'"): + ss[1]=='k'?"Function 'vkth()'": + ss[1]=='p'?"Function 'vprod()'": + ss[1]=='v'?"Function 'vvar()'": + ss[2]=='i'?(ss[4]=='('?"Function 'vmin()'": + "Function 'vminabs()'"): + ss[2]=='a'?(ss[4]=='('?"Function 'vmax()'": + "Function 'vmaxabs()'"): + "Function 'vmed()'"); + op = ss[1]=='a'?(ss[2]=='v'?mp_vavg: + ss[4]=='k'?mp_vargkth: + ss[5]=='i' && ss[7]=='('?mp_vargmin: + ss[5]=='i'?mp_vargminabs: + ss[7]=='('?mp_vargmax:mp_vargmaxabs): + ss[1]=='s'?(ss[2]=='u'?mp_vsum:mp_vstd): + ss[1]=='k'?mp_vkth: + ss[1]=='p'?mp_vprod: + ss[1]=='v'?mp_vvar: + ss[2]=='i'?(ss[4]=='('?mp_vmin:mp_vminabs): + ss[2]=='a'?(ss[4]=='('?mp_vmax:mp_vmaxabs): + mp_vmedian; + CImg::vector((ulongT)op,0,0,0).move_to(l_opcode); + p1 = ~0U; + p3 = 1; + for (s = std::strchr(ss,'(') + 1; s::vector(arg2,p2).move_to(l_opcode); + s = ns; + ++p3; + } + (l_opcode>'y').move_to(opcode); + if (p1==~0U) { pos = scalar(); p1 = 0; } else pos = vector(p1); + opcode[1] = pos; + opcode[2] = p1; + opcode[3] = opcode._height; + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"vtos(",5)) { // Double(s) to string + _cimg_mp_op("Function 'vtos()'"); + s1 = ss5; while (s1::vector((ulongT)mp_vtos,pos,p1,arg1,_cimg_mp_size(arg1),arg2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + break; + + case 'w' : + if (*ss1=='(') { // Image width + _cimg_mp_op("Function 'w()'"); + if (*ss2=='#') { // Index specified + p1 = compile(ss3,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss2!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_w,p1); + } + + if (*ss1=='h' && *ss2=='(') { // Image width*height + _cimg_mp_op("Function 'wh()'"); + if (*ss3=='#') { // Index specified + p1 = compile(ss4,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss3!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_wh,p1); + } + + if (*ss1=='h' && *ss2=='d' && *ss3=='(') { // Image width*height*depth + _cimg_mp_op("Function 'whd()'"); + if (*ss4=='#') { // Index specified + p1 = compile(ss5,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss4!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_whd,p1); + } + + if (*ss1=='h' && *ss2=='d' && *ss3=='s' && *ss4=='(') { // Image width*height*depth*spectrum + _cimg_mp_op("Function 'whds()'"); + if (*ss5=='#') { // Index specified + p1 = compile(ss6,se1,depth1,0,is_critical); + _cimg_mp_check_list(false); + } else { if (ss5!=se1) break; p1 = ~0U; } + _cimg_mp_scalar1(mp_image_whds,p1); + } + + if (!std::strncmp(ss,"while(",6)) { // While...do + _cimg_mp_op("Function 'while()'"); + s0 = *ss5=='('?ss6:ss8; + s1 = s0; while (s1::vector((ulongT)mp_while,pos,arg1,p2 - p1,code._width - p2,arg2, + pos>=arg6 && !_cimg_mp_is_constant(pos), + arg1>=arg6 && !_cimg_mp_is_constant(arg1)).move_to(code,p1); + _cimg_mp_return(pos); + } + break; + + case 'x' : + if (!std::strncmp(ss,"xor(",4)) { // Xor + _cimg_mp_op("Function 'xor()'"); + s1 = ss4; while (s1::vector((ulongT)op,pos,0).move_to(l_opcode); + for (s = std::strchr(ss,'(') + 1; s::sequence(_cimg_mp_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_size(arg2)). + move_to(l_opcode); + else CImg::vector(arg2).move_to(l_opcode); + is_sth&=_cimg_mp_is_constant(arg2); + s = ns; + } + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (is_sth) _cimg_mp_constant(op(*this)); + opcode.move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // No corresponding built-in function -> Look for a user-defined macro call. + s0 = strchr(ss,'('); + if (s0) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + + // Count number of specified arguments. + p1 = 0; + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && !p1) break; + ns = s; while (ns _expr = macro_body[l]; // Expression to be substituted + + p1 = 1; // Index of current parsed argument + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { // Parse function arguments + while (*s && cimg::is_blank(*s)) ++s; + if (*s==')' && p1==1) break; // Function has no arguments + if (p1>p2) { ++p1; break; } + ns = s; while (ns _pexpr(_expr._width); + ns = _pexpr._data; + for (ps = _expr._data, c1 = ' '; *ps; ++ps) { + if (!cimg::is_blank(*ps)) c1 = *ps; + *(ns++) = c1; + } + *ns = 0; + + CImg _level = get_level(_expr); + expr.swap(_expr); + pexpr.swap(_pexpr); + level.swap(_level); + s0 = user_macro; + user_macro = macro_def[l]; + pos = compile(expr._data,expr._data + expr._width - 1,depth1,p_ref,is_critical); + user_macro = s0; + level.swap(_level); + pexpr.swap(_pexpr); + expr.swap(_expr); + _cimg_mp_return(pos); + } + + if (arg3) { // Macro name matched but number of arguments does not + CImg sig_nargs(arg3); + arg1 = 0; + cimglist_for(macro_def,l) if (!std::strcmp(macro_def[l],variable_name)) + sig_nargs[arg1++] = (unsigned int)macro_def[l].back(); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + if (sig_nargs._width>1) { + sig_nargs.sort(); + arg1 = sig_nargs.back(); + --sig_nargs._width; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %s or %u arguments), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,sig_nargs.value_string()._data,arg1, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %u argument%s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,*sig_nargs,*sig_nargs!=1?"s":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + } // if (se1==')') + + // Char / string initializer. + if (*se1=='\'' && + ((se1>ss && *ss=='\'') || + (se1>ss1 && *ss=='_' && *ss1=='\''))) { + if (*ss=='_') { _cimg_mp_op("Char initializer"); s1 = ss2; } + else { _cimg_mp_op("String initializer"); s1 = ss1; } + arg1 = (unsigned int)(se1 - s1); // Original string length + if (arg1) { + CImg(s1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + if (*ss=='_') { + if (arg1==1) _cimg_mp_constant((unsigned char)*variable_name); + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s: Literal %s contains more than one byte, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss1, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode); + std::memcpy((char*)l_opcode[1]._data,variable_name,arg1); + (l_opcode>'y').move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + } + + // Vector initializer [ ... ]. + if (*ss=='[' && *se1==']') { + _cimg_mp_op("Vector initializer"); + s1 = ss1; while (s1s1 && cimg::is_blank(*s2)) --s2; + if (s2>s1 && *s1=='\'' && *s2=='\'') { // Vector values provided as a string + arg1 = (unsigned int)(s2 - s1 - 1); // Original string length + if (arg1) { + CImg(s1 + 1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(l_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(l_opcode); + std::memcpy((char*)l_opcode[1]._data,variable_name,arg1); + (l_opcode>'y').move_to(code); + } else { // Vector values provided as list of items + arg1 = 0; // Number of specified values + if (*ss1!=']') for (s = ss1; s::sequence(arg3,arg2 + 1,arg2 + arg3).move_to(l_opcode); + arg1+=arg3; + } else { CImg::vector(arg2).move_to(l_opcode); ++arg1; } + s = ns; + } + if (!arg1) _cimg_mp_return(0); + pos = vector(arg1); + l_opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (l_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + } + return_new_comp = true; + _cimg_mp_return(pos); + } + + // Variables related to the input list of images. + if (*ss1=='#' && ss2::vector((ulongT)mp_list_Joff,pos,p1,0,0,p2).move_to(code); + return_new_comp = true; + _cimg_mp_return(pos); + case 'R' : // R#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0, + 0,_cimg_mp_boundary); + case 'G' : // G#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1, + 0,_cimg_mp_boundary); + case 'B' : // B#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2, + 0,_cimg_mp_boundary); + case 'A' : // A#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3, + 0,_cimg_mp_boundary); + } + } + + if (*ss1 && *ss2=='#' && ss3='0' && *ss1<='9') { // i0#ind...i9#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,*ss1 - '0', + 0,_cimg_mp_boundary); + } + + if (*ss1=='c') { // ic#ind + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_median) list_median.assign(listin._width); + if (!list_median[p1]) CImg::vector(listin[p1].median()).move_to(list_median[p1]); + _cimg_mp_constant(*list_median[p1]); + } + _cimg_mp_scalar1(mp_list_median,arg1); + } + + if (*ss1=='n') { // in#ind + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_norm) list_norm.assign(listin._width); + if (!list_norm[p1]) CImg::vector(listin[p1].magnitude()).move_to(list_norm[p1]); + _cimg_mp_constant(*list_norm[p1]); + } + _cimg_mp_scalar1(mp_list_norm,arg1); + } + + switch (*ss1) { + case 'm' : arg2 = 0; break; // im#ind + case 'M' : arg2 = 1; break; // iM#ind + case 'a' : arg2 = 2; break; // ia#ind + case 'v' : arg2 = 3; break; // iv#ind + case 's' : arg2 = 12; break; // is#ind + case 'p' : arg2 = 13; break; // ip#ind + } + } else if (*ss1=='m') switch (*ss) { + case 'x' : arg2 = 4; break; // xm#ind + case 'y' : arg2 = 5; break; // ym#ind + case 'z' : arg2 = 6; break; // zm#ind + case 'c' : arg2 = 7; break; // cm#ind + } else if (*ss1=='M') switch (*ss) { + case 'x' : arg2 = 8; break; // xM#ind + case 'y' : arg2 = 9; break; // yM#ind + case 'z' : arg2 = 10; break; // zM#ind + case 'c' : arg2 = 11; break; // cM#ind + } + if (arg2!=~0U) { + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_stats) list_stats.assign(listin._width); + if (!list_stats[p1]) list_stats[p1].assign(1,14,1,1,0).fill(listin[p1].get_stats(),false); + _cimg_mp_constant(list_stats(p1,arg2)); + } + _cimg_mp_scalar2(mp_list_stats,arg1,arg2); + } + } + + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='#' && ss4 error. + c1 = *se1; + _cimg_mp_strerr; + cimg::strellipsize(variable_name,64); + if (is_sth) + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Undefined variable '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + s1 = std::strchr(ss,'('); + s_op = s1 && c1==')'?"function call":"item"; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unrecognized %s '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + s_op,variable_name._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Evaluation procedure. + double operator()(const double x, const double y, const double z, const double c) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = code; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + return *result; + } + + // Evaluation procedure (return output values in vector 'output'). + template + void operator()(const double x, const double y, const double z, const double c, t *const output) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = code; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + if (result_dim) { + const double *ptrs = result + 1; + t *ptrd = output; + for (unsigned int k = 0; k_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + p_code_end = code.end(); + } + + // Evaluation procedure for end_t() bloc. + void end_t() { + if (!code_end_t) return; + if (imgin) { + mem[_cimg_mp_slot_x] = imgin._width - 1.; + mem[_cimg_mp_slot_y] = imgin._height - 1.; + mem[_cimg_mp_slot_z] = imgin._depth - 1.; + mem[_cimg_mp_slot_c] = imgin._spectrum - 1.; + } else mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_end_t.end(); + for (p_code = code_end_t; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + + // Evaluation procedure the end() bloc. + void end() { + if (!code_end) return; + if (imgin) { + mem[_cimg_mp_slot_x] = imgin._width - 1.; + mem[_cimg_mp_slot_y] = imgin._height - 1.; + mem[_cimg_mp_slot_z] = imgin._depth - 1.; + mem[_cimg_mp_slot_c] = imgin._spectrum - 1.; + } else mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0; + p_code_end = code_end.end(); + for (p_code = code_end; p_code_data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + + // Merge inter-thread variables. + // (argument 'mp' is the master instance). + void merge(_cimg_math_parser& mp) { + if (&mp==this) return; + cimg_rofY(mp.memmerge,k) { + const unsigned int + pos = (unsigned int)mp.memmerge(0,k), + siz = (unsigned int)mp.memmerge(1,k), + iop = (unsigned int)mp.memmerge(2,k); + if (!siz) switch (iop) { // Scalar value + case 0 : mp.mem[pos] = mem[pos]; break; // Assignment + case 1 : mp.mem[pos]+=mem[pos]; break; // Operator+ + case 2 : mp.mem[pos]-=mem[pos]; break; // Operator- + case 3 : mp.mem[pos]*=mem[pos]; break; // Operator* + case 4 : mp.mem[pos]/=mem[pos]; break; // Operator/ + case 5 : mp.mem[pos] = std::min(mp.mem[pos],mem[pos]); break; // Operator 'min' + case 6 : mp.mem[pos] = std::max(mp.mem[pos],mem[pos]); break; // Operator 'max' + } else switch (iop) { // Vector value + case 0 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true) = CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 1 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)+=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 2 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)-=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 3 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)*=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 4 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true)/=CImg(&mem[pos + 1],siz,1,1,1,true); + break; + case 5 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true).min(CImg(&mem[pos + 1],siz,1,1,1,true)); + break; + case 6 : + CImg(&mp.mem[pos + 1],siz,1,1,1,true).max(CImg(&mem[pos + 1],siz,1,1,1,true)); + break; + } + } + } + + // Return specified argument number as a string. + static const char *s_argth(const unsigned int n_arg) { + const char + *_s_arg[] = { "", "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth","Ninth", + "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", + "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "One of the" }; + return _s_arg[n_arg s_calling_function() const { + CImg res; + const unsigned int + l1 = calling_function?(unsigned int)std::strlen(calling_function):0U, + l2 = user_macro?(unsigned int)std::strlen(user_macro):0U; + if (l2) { + res.assign(l1 + l2 + 48); + cimg_snprintf(res,res._width,"%s(): When substituting function '%s()'",calling_function,user_macro); + } else { + res.assign(l1 + l2 + 4); + cimg_snprintf(res,res._width,"%s()",calling_function); + } + return res; + } + + // Return type of a memory element as a string. + CImg s_type(const unsigned int arg) const { + CImg res; + if (_cimg_mp_is_vector(arg)) { // Vector + CImg::string("vectorXXXXXXXXXXXXXXXX").move_to(res); + cimg_sprintf(res._data + 6,"%u",_cimg_mp_size(arg)); + } else if (_cimg_mp_is_constant(arg)) CImg::string("const scalar").move_to(res); // Const scalar + else CImg::string("scalar").move_to(res); // Scalar + return res; + } + + // Count parentheses/brackets level of each character of the expression. + CImg get_level(CImg& _expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res(_expr._width - 1); + unsigned int *pd = res._data; + int _level = 0; + for (const char *ps = _expr._data; *ps && _level>=0; ++ps) { + if (!is_escaped && !next_is_escaped && *ps=='\\') next_is_escaped = true; + if (!is_escaped && *ps=='\'') { // Non-escaped character + if (!mode && ps>_expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string + else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string + else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string + } + *(pd++) = (unsigned int)(mode>=1 || is_escaped?_level + (mode==1): + *ps=='(' || *ps=='['?_level++: + *ps==')' || *ps==']'?--_level: + _level); + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + if (mode) { + cimg::strellipsize(_expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unterminated string literal, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + _expr._data); + } + if (_level) { + cimg::strellipsize(_expr,64); + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: Unbalanced parentheses/brackets, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + _expr._data); + } + return res; + } + + // Find and return index of current image 'imgin' within image list 'listin'. + unsigned int get_mem_img_index() { + if (mem_img_index==~0U) { + if (&imgout>listout.data() && &imgout='0' && c2<='9') rp = 20 + c2 - '0'; // i0...i9 + else if (c2=='m') rp = 4; // im + else if (c2=='M') rp = 5; // iM + else if (c2=='a') rp = 6; // ia + else if (c2=='v') rp = 7; // iv + else if (c2=='s') rp = 8; // is + else if (c2=='p') rp = 9; // ip + else if (c2=='c') rp = 10; // ic + else if (c2=='n') rp = 11; // in + } else if (c2=='m') { + if (c1=='x') rp = 12; // xm + else if (c1=='y') rp = 13; // ym + else if (c1=='z') rp = 14; // zm + else if (c1=='c') rp = 15; // cm + } else if (c2=='M') { + if (c1=='x') rp = 16; // xM + else if (c1=='y') rp = 17; // yM + else if (c1=='z') rp = 18; // zM + else if (c1=='c') rp = 19; // cM + } + } else if (variable_name[1] && variable_name[2] && !variable_name[3]) { // Three-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + if (c1=='w' && c2=='h' && c3=='d') rp = 1; // whd + } else if (variable_name[1] && variable_name[2] && variable_name[3] && + !variable_name[4]) { // Four-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + c4 = variable_name[3]; + if (c1=='w' && c2=='h' && c3=='d' && c4=='s') rp = 2; // whds + } else if (!std::strcmp(variable_name,"interpolation")) rp = 30; // interpolation + else if (!std::strcmp(variable_name,"boundary")) rp = 31; // boundary + + if (rp!=~0U) { rpos = rp; return; } // One of the reserved labels + + // Multi-char variable name : check for existing variable with same name + cimglist_for(variable_def,i) + if (!std::strcmp(variable_name,variable_def[i])) { pos = i; break; } + } + + // Tell for each character of an expression if it is inside a string or not. + CImg is_inside_string(CImg& _expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res = CImg::string(_expr); + bool *pd = res._data; + for (const char *ps = _expr._data; *ps; ++ps) { + if (!next_is_escaped && *ps=='\\') next_is_escaped = true; + if (!is_escaped && *ps=='\'') { // Non-escaped character + if (!mode && ps>_expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string + else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string + else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string + } + *(pd++) = mode>=1 || is_escaped; + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + return res; + } + + // Return true if specified argument can be a part of an allowed variable name. + bool is_varchar(const char c) const { + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; + } + + // Return true if specified argument can be considered as a variable name. + bool is_varname(const char *const str, const unsigned int length=~0U) const { + if (*str>='0' && *str<='9') return false; + for (unsigned int l = 0; l128) return false; + const int *ptr = memtype.data(arg + 1); + bool is_tmp = true; + while (siz-->0) if (*(ptr++)) { is_tmp = false; break; } + return is_tmp; + } + + // Check if a memory slot is a positive integer constant scalar value. + // 'mode' can be: + // { 0=constant | 1=integer constant | 2=positive integer constant | 3=strictly-positive integer constant } + void check_constant(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,1,0); + if (!(_cimg_mp_is_constant(arg) && + (!mode || (double)(int)mem[arg]==mem[arg]) && + (mode<2 || mem[arg]>=(mode==3)))) { + const char *const s_arg = s_argth(n_arg); + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') is not a%s constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_arg?" argument":" Argument",s_type(arg)._data, + !mode?"":mode==1?"n integer": + mode==2?" positive integer":" strictly positive integer", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check if an image index is a constant value. + void check_constant_index(const unsigned int arg, + char *const ss, char *const se, const char saved_char) { + if (arg!=~0U && !_cimg_mp_is_constant(arg)) { + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s Specified image index is not a constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check a matrix is square. + void check_matrix_square(const unsigned int arg, const unsigned int n_arg, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,2,0); + const unsigned int + siz = _cimg_mp_size(arg), + n = (unsigned int)cimg::round(std::sqrt((float)siz)); + if (n*n!=siz) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand":"Right-hand"; + else s_arg = !n_arg?"":n_arg==1?"First":n_arg==2?"Second":n_arg==3?"Third":"One"; + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') " + "cannot be considered as a square matrix, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?" argument":" Argument"):(*s_arg?" operand":" Operand"), + s_type(arg)._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check type compatibility for one argument. + // Bits of 'mode' tells what types are allowed: + // { 1 = scalar | 2 = vectorN }. + // If 'N' is not zero, it also restricts the vectors to be of size N only. + void check_type(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, const unsigned int N, + char *const ss, char *const se, const char saved_char) { + const bool + is_scalar = _cimg_mp_is_scalar(arg), + is_vector = _cimg_mp_is_vector(arg) && (!N || _cimg_mp_size(arg)==N); + bool cond = false; + if (mode&1) cond|=is_scalar; + if (mode&2) cond|=is_vector; + if (!cond) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand":"Right-hand"; + else s_arg = s_argth(n_arg); + CImg sb_type(32); + if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'"); + else if (mode==2) { + if (N) cimg_snprintf(sb_type,sb_type._width,"'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'vector'"); + } else { + if (N) cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector'"); + } + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s %s%s has invalid type '%s' (should be %s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?" argument":" Argument"):(*s_arg?" operand":" Operand"), + s_type(arg)._data,sb_type._data, + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check that listin or listout are not empty. + void check_list(const bool is_out, + char *const ss, char *const se, const char saved_char) { + if ((!is_out && !listin) || (is_out && !listout)) { + char *s0; _cimg_mp_strerr; + throw CImgArgumentException("[" cimg_appname "_math_parser] " + "CImg<%s>::%s: %s%s Invalid call with an empty image list, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0>expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Insert constant value in memory. + unsigned int constant(const double val) { + + // Search for built-in constant. + if (cimg::type::is_nan(val)) return _cimg_mp_slot_nan; + if (val==(double)(int)val) { + if (val>=0 && val<=10) return (unsigned int)val; + if (val<0 && val>=-5) return (unsigned int)(10 - val); + } + if (val==0.5) return 16; + + // Search for constant already requested before (in const cache). + unsigned int ind = ~0U; + if (constcache_size<1024) { + if (!constcache_size) { + constcache_vals.assign(16,1,1,1,0); + constcache_inds.assign(16,1,1,1,0); + *constcache_vals = val; + constcache_size = 1; + ind = 0; + } else { // Dichotomic search + const double val_beg = *constcache_vals, val_end = constcache_vals[constcache_size - 1]; + if (val_beg>=val) ind = 0; + else if (val_end==val) ind = constcache_size - 1; + else if (val_end=constcache_size || constcache_vals[ind]!=val) { + ++constcache_size; + if (constcache_size>constcache_vals._width) { + constcache_vals.resize(-200,1,1,1,0); + constcache_inds.resize(-200,1,1,1,0); + } + const int l = constcache_size - (int)ind - 1; + if (l>0) { + std::memmove(&constcache_vals[ind + 1],&constcache_vals[ind],l*sizeof(double)); + std::memmove(&constcache_inds[ind + 1],&constcache_inds[ind],l*sizeof(unsigned int)); + } + constcache_vals[ind] = val; + constcache_inds[ind] = 0; + } + } + if (constcache_inds[ind]) return constcache_inds[ind]; + } + + // Insert new constant in memory if necessary. + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(-200,1,1,1,0); } + const unsigned int pos = mempos++; + mem[pos] = val; + memtype[pos] = 1; // Set constant property + if (ind!=~0U) constcache_inds[ind] = pos; + return pos; + } + + // Insert new scalar in memory. + unsigned int scalar() { + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(mem._width,1,1,1,0); } + return mempos++; + } + + // Insert new vector of specified size in memory. + unsigned int vector(const unsigned int siz) { + if (mempos + siz>=mem._width) { + mem.resize(2*mem._width + siz,1,1,1,0); + memtype.resize(mem._width,1,1,1,0); + } + const unsigned int pos = mempos++; + mem[pos] = cimg::type::nan(); + memtype[pos] = siz + 1; + mempos+=siz; + return pos; + } + + // Insert new initialized vector. + unsigned int vector(const unsigned int siz, const double value) { + const unsigned int pos = vector(siz); + double *ptr = &mem[pos] + 1; + for (unsigned int i = 0; i::vector((ulongT)mp_vector_copy,pos,arg,siz).move_to(code); + return pos; + } + + // Set reserved status to all values of a vector. + void set_reserved_vector(const unsigned int arg) { + unsigned int siz = _cimg_mp_size(arg); + int *ptr = memtype.data(arg + 1); + while (siz-->0) *(ptr++) = -1; + } + + unsigned int scalar0(const mp_func op) { + const unsigned int pos = scalar(); + CImg::vector((ulongT)op,pos).move_to(code); + return_new_comp = true; + return pos; + } + + unsigned int scalar1(const mp_func op, const unsigned int arg1) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1) && op!=mp_copy?arg1: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1).move_to(code); + return pos; + } + + unsigned int scalar2(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2).move_to(code); + return pos; + } + + unsigned int scalar3(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3).move_to(code); + return pos; + } + + unsigned int scalar4(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4).move_to(code); + return pos; + } + + unsigned int scalar5(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5).move_to(code); + return pos; + } + + unsigned int scalar6(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code); + return pos; + } + + unsigned int scalar7(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6, + const unsigned int arg7) { + const unsigned int pos = + arg1!=~0U && arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2!=~0U && arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3!=~0U && arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4!=~0U && arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5!=~0U && arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6!=~0U && arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + arg7!=~0U && arg7>_cimg_mp_slot_c && _cimg_mp_is_comp(arg7)?arg7: + ((return_new_comp = true), scalar()); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6,arg7).move_to(code); + return pos; + } + + void self_vector_s(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_s,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1).move_to(code[code._width - 1 - siz + k]); + } + } + + void self_vector_v(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + } + + unsigned int vector1_v(const mp_func op, const unsigned int arg1) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_vv(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1:is_comp_vector(arg2)?arg2: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_vs(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vs,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector2_sv(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int + siz = _cimg_mp_size(arg2), + pos = is_comp_vector(arg2)?arg2: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_sv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector3_vss(const mp_func op, const unsigned int arg1, const unsigned int arg2, + const unsigned int arg3) { + const unsigned int + siz = _cimg_mp_size(arg1), + pos = is_comp_vector(arg1)?arg1: + ((return_new_comp = true), vector(siz)); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vss,pos,siz,(ulongT)op,arg1,arg2,arg3).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2,arg3).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + // Evaluation functions, known by the parser. + // Defining these functions 'static' ensures that sizeof(mp_func)==sizeof(ulongT), + // so we can store pointers to them directly in the opcode vectors. +#ifdef _mp_arg +#undef _mp_arg +#endif +#define _mp_arg(x) mp.mem[mp.opcode[x]] + + static double mp_abs(_cimg_math_parser& mp) { + return cimg::abs(_mp_arg(2)); + } + + static double mp_add(_cimg_math_parser& mp) { + return _mp_arg(2) + _mp_arg(3); + } + + static double mp_acos(_cimg_math_parser& mp) { + return std::acos(_mp_arg(2)); + } + + static double mp_acosh(_cimg_math_parser& mp) { + return cimg::acosh(_mp_arg(2)); + } + + static double mp_asinh(_cimg_math_parser& mp) { + return cimg::asinh(_mp_arg(2)); + } + + static double mp_atanh(_cimg_math_parser& mp) { + return cimg::atanh(_mp_arg(2)); + } + + static double mp_arg(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:(unsigned int)_ind, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_arg0(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:_ind + 1U, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_argkth(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = mp_kth(mp); + for (unsigned int i = 4; ival) { val = _val; argval = i - 3; } + } + return (double)argval; + } + + static double mp_argmaxabs(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3), absval = cimg::abs(val); + unsigned int argval = 0; + for (unsigned int i = 4; iabsval) { val = _val; absval = _absval; argval = i - 3; } + } + return (double)argval; + } + + static double mp_asin(_cimg_math_parser& mp) { + return std::asin(_mp_arg(2)); + } + + static double mp_atan(_cimg_math_parser& mp) { + return std::atan(_mp_arg(2)); + } + + static double mp_atan2(_cimg_math_parser& mp) { + return std::atan2(_mp_arg(2),_mp_arg(3)); + } + + static double mp_avg(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i>(unsigned int)_mp_arg(3)); + } + + static double mp_bitwise_xor(_cimg_math_parser& mp) { + return (double)((longT)_mp_arg(2) ^ (longT)_mp_arg(3)); + } + + static double mp_bool(_cimg_math_parser& mp) { + return (double)(bool)_mp_arg(2); + } + + static double mp_break(_cimg_math_parser& mp) { + mp.break_type = 1; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_breakpoint(_cimg_math_parser& mp) { + cimg_abort_init; + cimg_abort_test; + cimg::unused(mp); + return cimg::type::nan(); + } + +#ifdef cimg_mp_func_run + static double mp_run(_cimg_math_parser& mp) { + const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2; + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(3 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + CImg(1,1,1,1,0).move_to(_str); + CImg str = _str>'x'; + cimg_mp_func_run(str._data); + return cimg::type::nan(); + } +#endif + + static double mp_cbrt(_cimg_math_parser& mp) { + return cimg::cbrt(_mp_arg(2)); + } + + static double mp_ceil(_cimg_math_parser& mp) { + return std::ceil(_mp_arg(2)); + } + + static double mp_complex_abs(_cimg_math_parser& mp) { + return cimg::_hypot(_mp_arg(2),_mp_arg(3)); + } + + static double mp_complex_conj(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = real; + ptrd[1] = -imag; + return cimg::type::nan(); + } + + static double mp_complex_div_sv(_cimg_math_parser& mp) { + const double + *ptr2 = &_mp_arg(3) + 1, + r1 = _mp_arg(2), + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = r1*r2/denom; + *ptrd = -r1*i2/denom; + return cimg::type::nan(); + } + + static double mp_complex_div_vv(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = (r1*r2 + i1*i2)/denom; + *ptrd = (r2*i1 - r1*i2)/denom; + return cimg::type::nan(); + } + + static double mp_complex_exp(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), exp_real = std::exp(real); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = exp_real*std::cos(imag); + ptrd[1] = exp_real*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_log(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = 0.5*std::log(real*real + imag*imag); + ptrd[1] = std::atan2(imag,real); + return cimg::type::nan(); + } + + static double mp_complex_mul(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + *(ptrd++) = r1*r2 - i1*i2; + *(ptrd++) = r1*i2 + r2*i1; + return cimg::type::nan(); + } + + static void _mp_complex_pow(const double r1, const double i1, + const double r2, const double i2, + double *ptrd) { + double ro, io; + if (cimg::abs(i2)<1e-15) { // Exponent is real + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) { + if (cimg::abs(r2)<1e-15) { ro = 1; io = 0; } + else ro = io = 0; + } else { + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2), + phio = r2*phi1; + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + } else { // Exponent is complex + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) ro = io = 0; + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2)*std::exp(-i2*phi1), + phio = r2*phi1 + 0.5*i2*std::log(mod1_2); + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + *(ptrd++) = ro; + *ptrd = io; + } + + static double mp_complex_pow_ss(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_sv(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vs(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vv(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_cos(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::cos(real)*std::cosh(imag); + ptrd[1] = -std::sin(real)*std::sinh(imag); + return cimg::type::nan(); + } + + static double mp_complex_sin(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sin(real)*std::cosh(imag); + ptrd[1] = std::cos(real)*std::sinh(imag); + return cimg::type::nan(); + } + + static double mp_complex_tan(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), denom = std::cos(2*real) + std::cosh(2*imag); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sin(2*real)/denom; + ptrd[1] = std::sinh(2*imag)/denom; + return cimg::type::nan(); + } + + static double mp_complex_cosh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::cosh(real)*std::cos(imag); + ptrd[1] = std::sinh(real)*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_sinh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sinh(real)*std::cos(imag); + ptrd[1] = std::cosh(real)*std::sin(imag); + return cimg::type::nan(); + } + + static double mp_complex_tanh(_cimg_math_parser& mp) { + const double real = _mp_arg(2), imag = _mp_arg(3), denom = std::cosh(2*real) + std::cos(2*imag); + double *ptrd = &_mp_arg(1) + 1; + ptrd[0] = std::sinh(2*real)/denom; + ptrd[1] = std::sin(2*imag)/denom; + return cimg::type::nan(); + } + + static double mp_continue(_cimg_math_parser& mp) { + mp.break_type = 2; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_convolve(_cimg_math_parser &mp) { + return _mp_correlate(mp,true); + } + + static double mp_copy(_cimg_math_parser& mp) { + return _mp_arg(2); + } + + static double mp_correlate(_cimg_math_parser &mp) { + return _mp_correlate(mp,false); + } + + static double _mp_correlate(_cimg_math_parser &mp, bool is_convolve) { + double *ptrd = &_mp_arg(1) + 1; + const double *const ptrA = &_mp_arg(2) + 1, *const ptrM = &_mp_arg(7) + 1; + const unsigned int + wA = (unsigned int)mp.opcode[3], + hA = (unsigned int)mp.opcode[4], + dA = (unsigned int)mp.opcode[5], + sA = (unsigned int)mp.opcode[6], + wM = (unsigned int)mp.opcode[8], + hM = (unsigned int)mp.opcode[9], + dM = (unsigned int)mp.opcode[10], + sM = (unsigned int)mp.opcode[11], + boundary_conditions = (unsigned int)_mp_arg(12), + channel_mode = (unsigned int)mp.opcode[14], + xcenter = (unsigned int)_mp_arg(15), + ycenter = (unsigned int)_mp_arg(16), + zcenter = (unsigned int)_mp_arg(17), + xstart = (unsigned int)mp.opcode[18], + ystart = (unsigned int)mp.opcode[19], + zstart = (unsigned int)mp.opcode[20], + xend = (unsigned int)mp.opcode[21], + yend = (unsigned int)mp.opcode[22], + zend = (unsigned int)mp.opcode[23]; + const bool + is_normalized = (bool)_mp_arg(13); + const float + xstride = (float)_mp_arg(24), + ystride = (float)_mp_arg(25), + zstride = (float)_mp_arg(26), + xdilation = (float)_mp_arg(27), + ydilation = (float)_mp_arg(28), + zdilation = (float)_mp_arg(29); + CImg res; + if (is_convolve) res = CImg(ptrA,wA,hA,dA,sA,true). + get_convolve(CImg(ptrM,wM,hM,dM,sM,true), + boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter, + xstart,ystart,zstart, + xend,yend,zend, + xstride,ystride,zstride, + xdilation,ydilation,zdilation); + else res = CImg(ptrA,wA,hA,dA,sA,true). + get_correlate(CImg(ptrM,wM,hM,dM,sM,true), + boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter, + xstart,ystart,zstart, + xend,yend,zend, + xstride,ystride,zstride, + xdilation,ydilation,zdilation); + CImg(ptrd,res._width,res._height,res._depth,res._spectrum,true) = res; + return cimg::type::nan(); + } + + static double mp_cos(_cimg_math_parser& mp) { + return std::cos(_mp_arg(2)); + } + + static double mp_cosh(_cimg_math_parser& mp) { + return std::cosh(_mp_arg(2)); + } + + static double mp_critical(_cimg_math_parser& mp) { + const ulongT g_target = mp.opcode[1]; + cimg_pragma_openmp(critical(mp_critical)) + { + for (const CImg *const p_end = ++mp.p_code + mp.opcode[2]; + mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const unsigned int + dx = (unsigned int)mp.opcode[7], + dy = (unsigned int)mp.opcode[8], + dz = (unsigned int)mp.opcode[9], + dc = (unsigned int)mp.opcode[10]; + const unsigned int boundary_conditions = (unsigned int)_mp_arg(11); + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgin:mp.listin[ind]; + if (!img) std::memset(ptrd,0,dx*dy*dz*dc*sizeof(double)); + else CImg(ptrd,dx,dy,dz,dc,true) = img.get_crop(x,y,z,c, + x + dx - 1,y + dy - 1, + z + dz - 1,c + dc - 1, + boundary_conditions); + return cimg::type::nan(); + } + + static double mp_cross(_cimg_math_parser& mp) { + CImg + vout(&_mp_arg(1) + 1,1,3,1,1,true), + v1(&_mp_arg(2) + 1,1,3,1,1,true), + v2(&_mp_arg(3) + 1,1,3,1,1,true); + (vout = v1).cross(v2); + return cimg::type::nan(); + } + + static double mp_cut(_cimg_math_parser& mp) { + double val = _mp_arg(2), cmin = _mp_arg(3), cmax = _mp_arg(4); + return valcmax?cmax:val; + } + + static double mp_date(_cimg_math_parser& mp) { + const unsigned int + siz_out = (unsigned int)mp.opcode[2], + siz_arg1 = (unsigned int)mp.opcode[4], + siz_arg2 = (unsigned int)mp.opcode[6]; + double *ptr_out = &_mp_arg(1) + (siz_out?1:0); + const double + *ptr_arg1 = siz_arg1==~0U?0:&_mp_arg(3) + (siz_arg1?1:0), + *ptr_arg2 = siz_arg2==~0U?0:&_mp_arg(5) + 1; + + if (!ptr_arg2) { // No filename specified + if (!siz_arg1) return cimg::date((unsigned int)*ptr_arg1); + if (siz_arg1==~0U) for (unsigned int k = 0; k::nan(); + } + + // Filename specified. + CImg ss(siz_arg2 + 1); + cimg_forX(ss,i) ss[i] = (char)ptr_arg2[i]; + ss.back() = 0; + if (!siz_arg1) return cimg::fdate(ss,(unsigned int)*ptr_arg1); + for (unsigned int k = 0; k::nan(); + } + + static double mp_debug(_cimg_math_parser& mp) { + CImg expr(mp.opcode[2] - 4); + { + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + } + cimg::strellipsize(expr); + const ulongT g_target = mp.opcode[1]; + +#if cimg_use_openmp==0 + const unsigned int n_thread = 0; +#else + const unsigned int n_thread = omp_get_thread_num(); +#endif + cimg_pragma_openmp(critical(mp_debug)) + { + std::fprintf(cimg::output(), + "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c" + "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)mp.opcode[3],(unsigned int)g_target,mp.mem._width); + std::fflush(cimg::output()); + mp.debug_indent+=3; + } + const CImg *const p_end = ++mp.p_code + mp.opcode[3]; + CImg _op; + for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + + _op.assign(1,op._height - 1); + const ulongT *ptrs = op._data + 1; + for (ulongT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd mem[%u] = %.17g", + (void*)&mp,n_thread,mp.debug_indent,' ', + (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(), + (unsigned int)target,mp.mem[target]); + std::fflush(cimg::output()); + } + } + cimg_pragma_openmp(critical(mp_debug)) + { + mp.debug_indent-=3; + std::fprintf(cimg::output(), + "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c" + "End debugging expression '%s' -> mem[%u] = %.17g (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width); + std::fflush(cimg::output()); + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_decrement(_cimg_math_parser& mp) { + return _mp_arg(2) - 1; + } + + static double mp_det(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + return CImg(ptrs,k,k,1,1,true).det(); + } + + static double mp_diag(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2], siz = mp.opcode[2] - 3; + double *ptrd = &_mp_arg(1) + 1; + std::memset(ptrd,0,siz*siz*sizeof(double)); + for (unsigned int i = 3; i::nan(); + } + + static double mp_display_memory(_cimg_math_parser& mp) { + cimg::unused(mp); + std::fputc('\n',cimg::output()); + CImg title(128); + cimg_snprintf(title,title._width,"%s (%u)","[" cimg_appname "_math_parser] Memory snapshot",mp.mem._width); + mp.mem.display(title); + return cimg::type::nan(); + } + + static double mp_display(_cimg_math_parser& mp) { + const unsigned int + _siz = (unsigned int)mp.opcode[3], + siz = _siz?_siz:1; + const double *const ptr = &_mp_arg(1) + (_siz?1:0); + const int + w = (int)_mp_arg(4), + h = (int)_mp_arg(5), + d = (int)_mp_arg(6), + s = (int)_mp_arg(7); + CImg img; + if (w>0 && h>0 && d>0 && s>0) { + if ((unsigned int)w*h*d*s<=siz) img.assign(ptr,w,h,d,s,true); + else img.assign(ptr,siz).resize(w,h,d,s,-1); + } else img.assign(ptr,1,siz,1,1,true); + + CImg expr(mp.opcode[2] - 8); + const ulongT *ptrs = mp.opcode._data + 8; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + ((CImg::string("[" cimg_appname "_math_parser] ",false,true),expr)>'x').move_to(expr); + cimg::strellipsize(expr); + std::fputc('\n',cimg::output()); + img.display(expr._data); + return cimg::type::nan(); + } + + static double mp_div(_cimg_math_parser& mp) { + return _mp_arg(2)/_mp_arg(3); + } + + static double mp_dot(_cimg_math_parser& mp) { + const unsigned int siz = (unsigned int)mp.opcode[4]; + return CImg(&_mp_arg(2) + 1,1,siz,1,1,true). + dot(CImg(&_mp_arg(3) + 1,1,siz,1,1,true)); + } + + static double mp_do(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_body = ++mp.p_code, + *const p_cond = p_body + mp.opcode[3], + *const p_end = p_cond + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (mp.mem[mem_cond]); + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_draw(_cimg_math_parser& mp) { + const int x = (int)_mp_arg(4), y = (int)_mp_arg(5), z = (int)_mp_arg(6), c = (int)_mp_arg(7); + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + unsigned int + dx = (unsigned int)mp.opcode[8], + dy = (unsigned int)mp.opcode[9], + dz = (unsigned int)mp.opcode[10], + dc = (unsigned int)mp.opcode[11]; + dx = dx==~0U?img._width:(unsigned int)_mp_arg(8); + dy = dy==~0U?img._height:(unsigned int)_mp_arg(9); + dz = dz==~0U?img._depth:(unsigned int)_mp_arg(10); + dc = dc==~0U?img._spectrum:(unsigned int)_mp_arg(11); + + const ulongT sizS = mp.opcode[2]; + if (sizS<(ulongT)dx*dy*dz*dc) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': " + "Sprite dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + CImg S(&_mp_arg(1) + 1,dx,dy,dz,dc,true); + const float opacity = (float)_mp_arg(12); + + if (img._data) { + if (mp.opcode[13]!=~0U) { // Opacity mask specified + const ulongT sizM = mp.opcode[14]; + if (sizM<(ulongT)dx*dy*dz) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'draw()': " + "Mask dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + const CImg M(&_mp_arg(13) + 1,dx,dy,dz,(unsigned int)(sizM/(dx*dy*dz)),true); + img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(15)); + } else img.draw_image(x,y,z,c,S,opacity); + } + return cimg::type::nan(); + } + + static double mp_echo(_cimg_math_parser& mp) { + const unsigned int nb_args = (unsigned int)(mp.opcode[2] - 3)/2; + if (!nb_args) { std::fputc('\n',cimg::output()); return cimg::type::nan(); } // No arguments + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(3 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(3 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + CImg(1,1,1,1,0).move_to(_str); + const CImg str = _str>'x'; + std::fprintf(cimg::output(),"\n%s",str._data); + return cimg::type::nan(); + } + + static double mp_ellipse(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + CImg color(img._spectrum,1,1,1,0); + bool is_invalid_arguments = false, is_outlined = false; + float r1 = 0, r2 = 0, angle = 0, opacity = 1; + unsigned int i = 4, pattern = ~0U; + int x0 = 0, y0 = 0; + if (i>=i_end) is_invalid_arguments = true; + else { + x0 = (int)cimg::round(_mp_arg(i++)); + if (i>=i_end) is_invalid_arguments = true; + else { + y0 = (int)cimg::round(_mp_arg(i++)); + if (i>=i_end) is_invalid_arguments = true; + else { + r1 = (float)_mp_arg(i++); + if (i>=i_end) r2 = r1; + else { + r2 = (float)_mp_arg(i++); + if (i args(i_end - 4); + cimg_forX(args,k) args[k] = _mp_arg(4 + k); + if (ind==~0U) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'ellipse()': " + "Invalid arguments '%s'. ", + mp.imgin.pixel_type(),args.value_string()._data); + else + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'ellipse()': " + "Invalid arguments '#%u%s%s'. ", + mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data); + } + return cimg::type::nan(); + } + + static double mp_eq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)==_mp_arg(3)); + } + + static double mp_erf(_cimg_math_parser& mp) { + return std::erf(_mp_arg(2)); + } + + static double mp_erfinv(_cimg_math_parser& mp) { + return cimg::erfinv(_mp_arg(2)); + } + + static double mp_exp(_cimg_math_parser& mp) { + return std::exp(_mp_arg(2)); + } + + static double mp_expr(_cimg_math_parser& mp) { + const unsigned int + sizs = (unsigned int)mp.opcode[3], + w = (unsigned int)mp.opcode[4], + h = (unsigned int)mp.opcode[5], + d = (unsigned int)mp.opcode[6], + s = (unsigned int)mp.opcode[7], + sizd = w*h*d*s; + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1); + CImg ss(sizs + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + if (!sizd) return CImg(w,h,d,s,0).eval(ss,0,0,0,0,&mp.listin,&mp.listout); // Scalar result + CImg(++ptrd,w,h,d,s,true) = CImg(w,h,d,s,0).fill(ss,true,true,&mp.listin,&mp.listout); + return cimg::type::nan(); + } + + static double mp_eye(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int k = (unsigned int)mp.opcode[2]; + CImg(ptrd,k,k,1,1,true).identity_matrix(); + return cimg::type::nan(); + } + + static double mp_f2ui(_cimg_math_parser& mp) { + return (double)cimg::float2uint((float)_mp_arg(2)); + } + + static double mp_factorial(_cimg_math_parser& mp) { + return cimg::factorial((int)_mp_arg(2)); + } + + static double mp_fibonacci(_cimg_math_parser& mp) { + return cimg::fibonacci((int)_mp_arg(2)); + } + + static double mp_fill(_cimg_math_parser& mp) { + unsigned int siz = (unsigned int)mp.opcode[2]; + double + *ptrd = &_mp_arg(1), + *const ptrc = mp.opcode[3]!=~0U?&_mp_arg(3):0, + *const ptrs = &_mp_arg(4); + if (siz) ++ptrd; else ++siz; // Fill vector-valued slot + const CImg + *const p_body = ++mp.p_code, + *const p_end = p_body + mp.opcode[5]; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + unsigned int it = 0; + if (ptrc) { // Version with loop variable (3 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + else ptrd[it] = *ptrs; + ++it; + } + *ptrc = (double)it; + } else // Version without loop variable (2 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + else ptrd[it] = *ptrs; + ++it; + } + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return *ptrd; + } + + static double mp_find(_cimg_math_parser& mp) { + const int _step = (int)_mp_arg(6), step = _step?_step:-1; + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):step>0?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const double + *const ptrb = &_mp_arg(2) + 1, + *const ptre = ptrb + siz, + val = _mp_arg(4), + *ptr = ptrb + ind; + + // Forward search + if (step>0) { + while (ptr=ptre?-1.:(double)(ptr - ptrb); + } + + // Backward search. + while (ptr>=ptrb && *ptr!=val) ptr+=step; + return ptr0?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const double + *const ptr1b = &_mp_arg(2) + 1, + *const ptr1e = ptr1b + siz1, + *const ptr2b = &_mp_arg(4) + 1, + *const ptr2e = ptr2b + siz2, + *ptr1 = ptr1b + ind, + *p1 = 0, + *p2 = 0; + + // Forward search. + if (step>0) { + do { + while (ptr1=ptr1e) return -1.; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b && *ptr1!=*ptr2b) ptr1+=step; + if (ptr1=ptr1b); + return p2 + *const p_init = ++mp.p_code, + *const p_cond = p_init + mp.opcode[4], + *const p_body = p_cond + mp.opcode[5], + *const p_post = p_body + mp.opcode[6], + *const p_end = p_post + mp.opcode[7]; + const unsigned int vsiz = (unsigned int)mp.opcode[2]; + bool is_cond = false; + if (mp.opcode[8]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[9]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + for (mp.p_code = p_init; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + + if (!mp.break_type) do { + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) { + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + + for (mp.p_code = p_post; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_fsize(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const ulongT siz = (ulongT)mp.opcode[3]; + CImg ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::fsize(ss); + } + + static double mp_g(_cimg_math_parser& mp) { + cimg::unused(mp); + return cimg::grand(&mp.rng); + } + + static double mp_gauss(_cimg_math_parser& mp) { + const double x = _mp_arg(2), s = _mp_arg(3); + return std::exp(-x*x/(2*s*s))/(_mp_arg(4)?std::sqrt(2*s*s*cimg::PI):1); + } + +#ifdef cimg_mp_func_get + static double mp_get(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1); + const unsigned int + sizs = (unsigned int)mp.opcode[3], + sizd = (unsigned int)mp.opcode[4]; + const bool to_string = (bool)mp.opcode[5]; + CImg ss(sizs + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + if (sizd) cimg_mp_func_get(ptrd + 1,sizd,to_string,ss._data); + else cimg_mp_func_get(ptrd,0,to_string,ss._data); + return cimg::type::nan(); + } +#endif + + static double mp_gcd(_cimg_math_parser& mp) { + return cimg::gcd((long)_mp_arg(2),(long)_mp_arg(3)); + } + +#ifdef cimg_mp_func_name + static double mp_name(_cimg_math_parser& mp) { + double *const ptr = &_mp_arg(1) + 1; + const unsigned int siz = (unsigned int)mp.opcode[3]; + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind==~0U) std::memset(ptr,0,siz*sizeof(double)); + else { + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + cimg_mp_func_name(ind,ptr,siz); + } + return cimg::type::nan(); + } +#endif + + static double mp_gt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>_mp_arg(3)); + } + + static double mp_gte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>=_mp_arg(3)); + } + + static double mp_i(_cimg_math_parser& mp) { + return (double)mp.imgin.atXYZC((int)mp.mem[_cimg_mp_slot_x],(int)mp.mem[_cimg_mp_slot_y], + (int)mp.mem[_cimg_mp_slot_z],(int)mp.mem[_cimg_mp_slot_c],(T)0); + } + + static double mp_if(_cimg_math_parser& mp) { + const bool is_cond = (bool)_mp_arg(2); + const ulongT + mem_left = mp.opcode[3], + mem_right = mp.opcode[4]; + const CImg + *const p_right = ++mp.p_code + mp.opcode[5], + *const p_end = p_right + mp.opcode[6]; + const unsigned int vtarget = (unsigned int)mp.opcode[1], vsiz = (unsigned int)mp.opcode[7]; + if (is_cond) for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + else for (mp.p_code = p_right; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.p_code==mp.p_break) --mp.p_code; + else mp.p_code = p_end - 1; + if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[is_cond?mem_left:mem_right] + 1,sizeof(double)*vsiz); + return mp.mem[is_cond?mem_left:mem_right]; + } + + static double mp_image_d(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.depth(); + } + + static double mp_image_display(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + CImg title(256); + std::fputc('\n',cimg::output()); + cimg_snprintf(title,title._width,"[ Image #%u ]",ind); + img.display(title); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_h(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.height(); + } + + static double mp_image_median(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.median(); + } + + static double mp_image_norm(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.magnitude(); + } + + static double mp_image_print(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + CImg title(256); + std::fputc('\n',cimg::output()); + cimg_snprintf(title,title._width,"[ Image #%u ]",ind); + img.print(title); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_resize(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + const double + _w = mp.opcode[3]==~0U?-100:_mp_arg(3), + _h = mp.opcode[4]==~0U?-100:_mp_arg(4), + _d = mp.opcode[5]==~0U?-100:_mp_arg(5), + _s = mp.opcode[6]==~0U?-100:_mp_arg(6); + const unsigned int + w = (unsigned int)(_w>=0?_w:-_w*img.width()/100), + h = (unsigned int)(_h>=0?_h:-_h*img.height()/100), + d = (unsigned int)(_d>=0?_d:-_d*img.depth()/100), + s = (unsigned int)(_s>=0?_s:-_s*img.spectrum()/100), + interp = (int)_mp_arg(7); + if (mp.is_fill && img._data==mp.imgout._data) { + cimg::mutex(6,0); + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'resize()': " + "Cannot both fill and resize image (%u,%u,%u,%u) " + "to new dimensions (%u,%u,%u,%u).", + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,w,h,d,s); + } + const unsigned int + boundary = (int)_mp_arg(8); + const float + cx = (float)_mp_arg(9), + cy = (float)_mp_arg(10), + cz = (float)_mp_arg(11), + cc = (float)_mp_arg(12); + img.resize(w,h,d,s,interp,boundary,cx,cy,cz,cc); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_s(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.spectrum(); + } + + static double mp_image_sort(_cimg_math_parser& mp) { + const bool is_increasing = (bool)_mp_arg(3); + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listout.width()), + axis = (unsigned int)_mp_arg(4); + cimg::mutex(6); + CImg &img = mp.listout[ind]; + img.sort(is_increasing, + axis==0 || axis=='x'?'x': + axis==1 || axis=='y'?'y': + axis==2 || axis=='z'?'z': + axis==3 || axis=='c'?'c':0); + cimg::mutex(6,0); + return cimg::type::nan(); + } + + static double mp_image_stats(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind==~0U) CImg(ptrd,14,1,1,1,true) = mp.imgout.get_stats(); + else { + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg(ptrd,14,1,1,1,true) = mp.listout[ind].get_stats(); + } + return cimg::type::nan(); + } + + static double mp_image_w(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width(); + } + + static double mp_image_wh(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height(); + } + + static double mp_image_whd(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height()*img.depth(); + } + + static double mp_image_whds(_cimg_math_parser& mp) { + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + return (double)img.width()*img.height()*img.depth()*img.spectrum(); + } + + static double mp_increment(_cimg_math_parser& mp) { + return _mp_arg(2) + 1; + } + + static double mp_inrange(_cimg_math_parser& mp) { + const unsigned int sizd = (unsigned int)mp.opcode[2]; + const bool + include_m = (bool)_mp_arg(9), + include_M = (bool)_mp_arg(10); + if (!sizd) { // Scalar result + const double val = _mp_arg(3); + const double m = _mp_arg(5), M = _mp_arg(7); + if (M>=m) return (double)((include_m?(val>=m):(val>m)) && (include_M?(val<=M):(val=M):(val>M)) && (include_m?(val<=m):(val=m) + ptrd[k] = (double)((include_m?(val>=m):(val>m)) && (include_M?(val<=M):(val=M):(val>M)) && (include_m?(val<=m):(val::nan(); + } + + static double mp_int(_cimg_math_parser& mp) { + return (double)(longT)_mp_arg(2); + } + + static double mp_ioff(_cimg_math_parser& mp) { + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3); + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off>=0 && off ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::is_directory(ss); + } + + static double mp_isin(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = _mp_arg(3); + for (unsigned int i = 4; i::is_inf(_mp_arg(2)); + } + + static double mp_isint(_cimg_math_parser& mp) { + return (double)((double)(longT)_mp_arg(2)==_mp_arg(2)); + } + + static double mp_isfile(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const ulongT siz = (ulongT)mp.opcode[3]; + CImg ss(siz + 1); + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + return (double)cimg::is_file(ss); + } + + static double mp_isnan(_cimg_math_parser& mp) { + return (double)cimg::type::is_nan(_mp_arg(2)); + } + + static double mp_ixyzc(_cimg_math_parser& mp) { + const unsigned int + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.imgin; + const double + x = _mp_arg(2), y = _mp_arg(3), + z = _mp_arg(4), c = _mp_arg(5); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx &img = mp.imgin; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), + z = oz + _mp_arg(4), c = oc + _mp_arg(5); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx vals(i_end - 4); + double *p = vals.data(); + for (unsigned int i = 4; i &img = mp.listin[indi]; + const int _step = (int)_mp_arg(5), step = _step?_step:-1; + const ulongT siz = (ulongT)img.size(); + longT ind = (longT)(mp.opcode[4]!=_cimg_mp_slot_nan?_mp_arg(4):step>0?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const T + *const ptrb = img.data(), + *const ptre = img.end(), + *ptr = ptrb + ind; + const double val = _mp_arg(3); + + // Forward search + if (step>0) { + while (ptr=ptre?-1.:(double)(ptr - ptrb); + } + + // Backward search. + while (ptr>=ptrb && (double)*ptr!=val) ptr+=step; + return ptr &img = mp.listin[indi]; + const int _step = (bool)_mp_arg(6), step = _step?_step:-1; + const ulongT + siz1 = (ulongT)img.size(), + siz2 = (ulongT)mp.opcode[4]; + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):step>0?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const T + *const ptr1b = img.data(), + *const ptr1e = ptr1b + siz1, + *ptr1 = ptr1b + ind, + *p1 = 0; + const double + *const ptr2b = &_mp_arg(3) + 1, + *const ptr2e = ptr2b + siz2, + *p2 = 0; + + // Forward search. + if (step>0) { + do { + while (ptr1=ptr1e) return -1.; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b && *ptr1!=*ptr2b) ptr1+=step; + if (ptr1=ptr1b); + return p2 &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.listin[ind]; + const double + x = _mp_arg(3), y = _mp_arg(4), + z = _mp_arg(5), c = _mp_arg(6); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off>=0 && off &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), + z = oz + _mp_arg(5), c = oc + _mp_arg(6); + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._cubic_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.cubic_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + case 1 : // Linear interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), s2 = 2.f*img.spectrum(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), + mz = cimg::mod((float)z,d2), mc = cimg::mod((float)c,s2); + return (double)img._linear_atXYZ(mx=img._spectrum?img._spectrum - 1:c)); + default : // Dirichlet + if (c<0 || c>=img._spectrum) return (T)0; + return (double)img.linear_atXYZ((float)x,(float)y,(float)z,(int)c,(T)0); + } + default : // Nearest neighbor interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const int + w2 = 2*img.width(), h2 = 2*img.height(), d2 = 2*img.depth(), s2 = 2*img.spectrum(), + mx = cimg::mod((int)x,w2), my = cimg::mod((int)y,h2), + mz = cimg::mod((int)z,d2), mc = cimg::mod((int)c,s2); + return (double)img(mx::vector(mp.listin[ind].median()).move_to(mp.list_median[ind]); + return *mp.list_median[ind]; + } + + static double mp_list_norm(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + if (!mp.list_norm) mp.list_norm.assign(mp.listin._width); + if (!mp.list_norm[ind]) CImg::vector(mp.listin[ind].magnitude()).move_to(mp.list_norm[ind]); + return *mp.list_norm[ind]; + } + + static double mp_list_set_ioff(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), y = (int)_mp_arg(4), + z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Ixyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_set_Joff_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Jxyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_spectrum(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._spectrum; + } + + static double mp_list_stats(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + k = (unsigned int)mp.opcode[3]; + if (!mp.list_stats) mp.list_stats.assign(mp.listin._width); + if (!mp.list_stats[ind]) mp.list_stats[ind].assign(1,14,1,1,0).fill(mp.listin[ind].get_stats(),false); + return mp.list_stats(ind,k); + } + + static double mp_list_wh(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height; + } + + static double mp_list_whd(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth; + } + + static double mp_list_whds(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth*mp.listin[ind]._spectrum; + } + + static double mp_list_width(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width; + } + + static double mp_list_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4), + vsiz = (unsigned int)mp.opcode[5]; + const CImg &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_list_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7), + vsiz = (unsigned int)mp.opcode[8]; + const CImg &img = mp.listin[ind]; + const double x = _mp_arg(3), y = _mp_arg(4), z = _mp_arg(5); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_list_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4), + vsiz = (unsigned int)mp.opcode[5]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], oz = (int)mp.mem[_cimg_mp_slot_z]; + const CImg &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_list_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7), + vsiz = (unsigned int)mp.opcode[8]; + const CImg &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), z = oz + _mp_arg(5); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_log(_cimg_math_parser& mp) { + return std::log(_mp_arg(2)); + } + + static double mp_log10(_cimg_math_parser& mp) { + return std::log10(_mp_arg(2)); + } + + static double mp_log2(_cimg_math_parser& mp) { + return cimg::log2(_mp_arg(2)); + } + + static double mp_logical_and(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (!val_left) { mp.p_code = p_end - 1; return 0; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_logical_not(_cimg_math_parser& mp) { + return (double)!_mp_arg(2); + } + + static double mp_logical_or(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (val_left) { mp.p_code = p_end - 1; return 1; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_lowercase(_cimg_math_parser& mp) { + return cimg::lowercase(_mp_arg(2)); + } + + static double mp_lt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<_mp_arg(3)); + } + + static double mp_lte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<=_mp_arg(3)); + } + + static double mp_matrix_eig(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + CImg val, vec; + CImg(ptr1,k,k,1,1,true).symmetric_eigen(val,vec); + CImg(ptrd,1,k,1,1,true) = val; + CImg(ptrd + k,k,k,1,1,true) = vec.get_transpose(); + return cimg::type::nan(); + } + + static double mp_matrix_invert(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptr1 = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + const bool use_LU = (bool)_mp_arg(4); + CImg(ptrd,k,k,1,1,true) = CImg(ptr1,k,k,1,1,true).get_invert(use_LU); + return cimg::type::nan(); + } + + static double mp_matrix_mul(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr1,l,k,1,1,true)*CImg(ptr2,m,l,1,1,true); + return cimg::type::nan(); + } + + static double mp_matrix_pseudoinvert(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + const bool use_LU = (bool)_mp_arg(5); + CImg(ptrd,l,k,1,1,true) = CImg(ptr1,k,l,1,1,true).get_pseudoinvert(use_LU); + return cimg::type::nan(); + } + + static double mp_matrix_svd(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptr1 = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg U, S, V; + CImg(ptr1,k,l,1,1,true).SVD(U,S,V); + CImg(ptrd,k,l,1,1,true) = U; + CImg(ptrd + k*l,1,k,1,1,true) = S; + CImg(ptrd + k*l + k,k,k,1,1,true) = V; + return cimg::type::nan(); + } + + static double mp_max(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; iabsval) { val = _val; absval = _absval; } + } + return val; + } + + static double* _mp_memcopy_double(_cimg_math_parser& mp, const unsigned int ind, const ulongT *const p_ref, + const longT siz, const long inc) { + const longT + off = *p_ref?p_ref[1] + (longT)mp.mem[(longT)p_ref[2]] + 1:ind, + eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=mp.mem.width()) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds variable pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %u).", + mp.imgin.pixel_type(),siz,inc,off,eoff,mp.mem._width - 1); + return &mp.mem[off]; + } + + static float* _mp_memcopy_float(_cimg_math_parser& mp, const ulongT *const p_ref, + const longT siz, const long inc, const bool is_out) { + const unsigned ind = (unsigned int)p_ref[1]; + const CImg &img = is_out? + (ind==~0U?mp.imgout:mp.listout[cimg::mod((int)mp.mem[ind],mp.listout.width())]): + (ind==~0U?mp.imgin:mp.listin[cimg::mod((int)mp.mem[ind],mp.listin.width())]); + const bool is_relative = (bool)p_ref[2]; + int ox, oy, oz, oc; + longT off = 0; + if (is_relative) { + ox = (int)mp.mem[_cimg_mp_slot_x]; + oy = (int)mp.mem[_cimg_mp_slot_y]; + oz = (int)mp.mem[_cimg_mp_slot_z]; + oc = (int)mp.mem[_cimg_mp_slot_c]; + off = img.offset(ox,oy,oz,oc); + } + if ((*p_ref)%2) { + const int + x = (int)mp.mem[p_ref[3]], + y = (int)mp.mem[p_ref[4]], + z = (int)mp.mem[p_ref[5]], + c = *p_ref==5?0:(int)mp.mem[p_ref[6]]; + off+=img.offset(x,y,z,c); + } else off+=(longT)mp.mem[p_ref[3]]; + const longT eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=(longT)img.size()) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds image pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %lu).", + mp.imgin.pixel_type(),siz,inc,off,eoff,img.size() - 1); + return (float*)&img[off]; + } + + static double mp_memcopy(_cimg_math_parser& mp) { + longT siz = (longT)_mp_arg(4); + const longT inc_d = (longT)_mp_arg(5), inc_s = (longT)_mp_arg(6); + const float + _opacity = (float)_mp_arg(7), + opacity = (float)cimg::abs(_opacity), + omopacity = 1 - std::max(_opacity,0.f); + if (siz>0) { + const bool + is_doubled = mp.opcode[8]<=1, + is_doubles = mp.opcode[15]<=1; + if (is_doubled && is_doubles) { // (double*) <- (double*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(double)); + else std::memmove(ptrd,ptrs,siz*sizeof(double)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,double) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } else if (is_doubled && !is_doubles) { // (double*) <- (float*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s,false); + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + _opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else if (!is_doubled && is_doubles) { // (float*) <- (double*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d,true); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (_opacity>=1) while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = (float)(omopacity**ptrd + opacity**ptrs); ptrd+=inc_d; ptrs+=inc_s; } + } else { // (float*) <- (float*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d,true); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s,false); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(float)); + else std::memmove(ptrd,ptrs,siz*sizeof(float)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,float) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } + } + return _mp_arg(1); + } + + static double mp_min(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i(ptrd,wS,wD,1,1,true) = CImg(ptrS,wS,hS,1,1,false). + project_matrix(CImg(ptrD,wD,hS,1,1,true),method,max_iter,max_residual); + return cimg::type::nan(); + } + + static double mp_mul(_cimg_math_parser& mp) { + return _mp_arg(2)*_mp_arg(3); + } + + static double mp_mul2(_cimg_math_parser& mp) { + return _mp_arg(2)*_mp_arg(3)*_mp_arg(4); + } + + static double mp_neq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)!=_mp_arg(3)); + } + + static double mp_norm0(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + switch (i_end - 3) { + case 1 : return _mp_arg(3)!=0; + case 2 : return (_mp_arg(3)!=0) + (_mp_arg(4)!=0); + } + double res = 0; + for (unsigned int i = 3; ires) res = val; + } + return res; + } + + static double mp_normp(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + if (i_end==4) return cimg::abs(_mp_arg(3)); + const double p = (double)mp.opcode[3]; + double res = 0; + for (unsigned int i = 4; i0?res:0.; + } + + static double mp_permutations(_cimg_math_parser& mp) { + return cimg::permutations((int)_mp_arg(2),(int)_mp_arg(3),(bool)_mp_arg(4)); + } + + static double mp_polygon(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + unsigned int ind = (unsigned int)mp.opcode[3]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + bool is_invalid_arguments = i_end<=4, is_outlined = false; + if (!is_invalid_arguments) { + int nbv = (int)_mp_arg(4); + if (!nbv) is_invalid_arguments = true; + else { + if (nbv<0) { nbv = -nbv; is_outlined = true; } + CImg points(nbv,2,1,1,0); + CImg color(img._spectrum,1,1,1,0); + float opacity = 1; + unsigned int i = 5, pattern=~0U; + cimg_foroff(points,k) if (i args(i_end - 4); + cimg_forX(args,k) args[k] = _mp_arg(4 + k); + if (ind==~0U) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': " + "Invalid arguments '%s'. ", + mp.imgin.pixel_type(),args.value_string()._data); + else + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'polygon()': " + "Invalid arguments '#%u%s%s'. ", + mp.imgin.pixel_type(),ind,args._width?",":"",args.value_string()._data); + } + return cimg::type::nan(); + } + + static double mp_pow(_cimg_math_parser& mp) { + const double v = _mp_arg(2), p = _mp_arg(3); + return std::pow(v,p); + } + + static double mp_pow0_25(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return std::sqrt(std::sqrt(val)); + } + + static double mp_pow3(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val; + } + + static double mp_pow4(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val*val; + } + + static double mp_print(_cimg_math_parser& mp) { + const double val = _mp_arg(1); + const bool print_char = (bool)mp.opcode[3]; + cimg_pragma_openmp(critical(mp_print)) + { + CImg _expr(mp.opcode[2] - 4); + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(_expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(_expr); + cimg::mutex(6); + if (print_char) + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = %.17g = '%c'", + _expr._data,val,(int)val); + else + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = %.17g", + _expr._data,val); + std::fflush(cimg::output()); + cimg::mutex(6,0); + } + return val; + } + + static double mp_prod(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i + *const p_body = ++mp.p_code, + *const p_end = p_body + mp.opcode[4]; + + if (nb_it>0) { + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + double it = 0; + if (ptrc) { // Version with loop variable (3 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + ++it; + } + *ptrc = it; + } else // Version without loop variable (2 arguments) + while (it_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + ++it; + } + mp.break_type = _break_type; + } + + mp.p_code = p_end - 1; + return *ptrs; + } + + static double mp_rol(_cimg_math_parser& mp) { + return cimg::rol(_mp_arg(2),(unsigned int)_mp_arg(3)); + } + + static double mp_ror(_cimg_math_parser& mp) { + return cimg::ror(_mp_arg(2),(unsigned int)_mp_arg(3)); + } + + static double mp_rot2d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float + theta = (float)_mp_arg(2)*cimg::PI/180, + ca = std::cos(theta), + sa = std::sin(theta); + *(ptrd++) = ca; + *(ptrd++) = -sa; + *(ptrd++) = sa; + *ptrd = ca; + return cimg::type::nan(); + } + + static double mp_rot3d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5); + CImg(ptrd,3,3,1,1,true) = CImg::rotation_matrix(x,y,z,theta); + return cimg::type::nan(); + } + + static double mp_round(_cimg_math_parser& mp) { + return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4)); + } + + static double mp_self_add(_cimg_math_parser& mp) { + return _mp_arg(1)+=_mp_arg(2); + } + + static double mp_self_bitwise_and(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val & (longT)_mp_arg(2)); + } + + static double mp_self_bitwise_left_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val<<(unsigned int)_mp_arg(2)); + } + + static double mp_self_bitwise_or(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val | (longT)_mp_arg(2)); + } + + static double mp_self_bitwise_right_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val>>(unsigned int)_mp_arg(2)); + } + + static double mp_self_decrement(_cimg_math_parser& mp) { + return --_mp_arg(1); + } + + static double mp_self_increment(_cimg_math_parser& mp) { + return ++_mp_arg(1); + } + + static double mp_self_map_vector_s(_cimg_math_parser& mp) { // Vector += scalar + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2]; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode[2] = mp.opcode[4]; // Scalar argument + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1]; + while (siz-->0) { target = ptrd++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_map_vector_v(_cimg_math_parser& mp) { // Vector += vector + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1], &argument = mp.opcode[2]; + while (siz-->0) { target = ptrd++; argument = ptrs++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_mul(_cimg_math_parser& mp) { + return _mp_arg(1)*=_mp_arg(2); + } + + static double mp_self_div(_cimg_math_parser& mp) { + return _mp_arg(1)/=_mp_arg(2); + } + + static double mp_self_modulo(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = cimg::mod(val,_mp_arg(2)); + } + + static double mp_self_pow(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = std::pow(val,_mp_arg(2)); + } + + static double mp_self_sub(_cimg_math_parser& mp) { + return _mp_arg(1)-=_mp_arg(2); + } + + static double mp_set_ioff(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + x = (int)_mp_arg(2), y = (int)_mp_arg(3), + z = (int)_mp_arg(4), c = (int)_mp_arg(5); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Ixyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_set_Joff_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Jxyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_shift(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int siz = (unsigned int)mp.opcode[3]; + const int + shift = (int)_mp_arg(4), + boundary_conditions = (int)_mp_arg(5); + CImg(ptrd,siz,1,1,1,true) = CImg(ptrs,siz,1,1,1,true).shift(shift,0,0,0,boundary_conditions); + return cimg::type::nan(); + } + + static double mp_sign(_cimg_math_parser& mp) { + return cimg::sign(_mp_arg(2)); + } + + static double mp_sin(_cimg_math_parser& mp) { + return std::sin(_mp_arg(2)); + } + + static double mp_sinc(_cimg_math_parser& mp) { + return cimg::sinc(_mp_arg(2)); + } + + static double mp_sinh(_cimg_math_parser& mp) { + return std::sinh(_mp_arg(2)); + } + + static double mp_solve(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr2,m,l,1,1,false).solve(CImg(ptr1,k,l,1,1,true)); + return cimg::type::nan(); + } + + static double mp_sort(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const bool is_increasing = (bool)_mp_arg(4); + const unsigned int + siz = (unsigned int)mp.opcode[3], + nb_elts = mp.opcode[5]==~0U?siz:(unsigned int)_mp_arg(5), + siz_elt = (unsigned int)_mp_arg(6); + const ulongT sn = siz_elt*nb_elts; + if (sn>siz || siz_elt<1) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'sort()': " + "Arguments 'nb_elts=%g' and 'siz_elt=%g' are invalid " + "for sorting a vector of size %u.", + mp.imgin.pixel_type(),_mp_arg(5),_mp_arg(6),siz); + CImg(ptrd,siz_elt,nb_elts,1,1,true) = CImg(ptrs,siz_elt,nb_elts,1,1,true). + get_sort(is_increasing,siz_elt>1?'y':0); + if (sn(ptrd + sn,siz - sn,1,1,1,true) = CImg(ptrs + sn,siz - sn,1,1,1,true); + return cimg::type::nan(); + } + + static double mp_sqr(_cimg_math_parser& mp) { + return cimg::sqr(_mp_arg(2)); + } + + static double mp_sqrt(_cimg_math_parser& mp) { + return std::sqrt(_mp_arg(2)); + } + + static double mp_srand(_cimg_math_parser& mp) { + mp.rng = (cimg_uint64)_mp_arg(2); + return cimg::type::nan(); + } + + static double mp_srand0(_cimg_math_parser& mp) { + cimg::srand(&mp.rng); + +#if cimg_use_openmp!=0 + mp.rng+=omp_get_thread_num(); +#endif + return cimg::type::nan(); + } + + static double mp_std(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i0) mp.mem[ptrd++] = (double)*(ptrs++); + return cimg::type::nan(); + } + +#ifdef cimg_mp_func_store + static double mp_store(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2), + *ptr2 = &_mp_arg(4) + 1; + const unsigned int + siz1 = (unsigned int)mp.opcode[3], + siz2 = (unsigned int)mp.opcode[5]; + const int + w = (int)_mp_arg(6), + h = (int)_mp_arg(7), + d = (int)_mp_arg(8), + s = (int)_mp_arg(9); + + const bool is_compressed = (bool)_mp_arg(10); + if (w<0 || h<0 || d<0 || s<0) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'store()': " + "Specified image dimensions (%d,%d,%d,%d) are invalid.", + pixel_type(),w,h,d,s); + CImg ss(siz2 + 1); + cimg_for_inX(ss,0,ss.width() - 1,i) ss[i] = (char)ptr2[i]; + ss.back() = 0; + if (siz1) cimg_mp_func_store(ptr1 + 1,siz1, + (unsigned int)w,(unsigned int)h,(unsigned int)d,(unsigned int)s, + is_compressed,ss._data); + else cimg_mp_func_store(ptr1,1,(unsigned int)w,(unsigned int)h,(unsigned int)d,(unsigned int)s, + is_compressed,ss._data); + return cimg::type::nan(); + } +#endif + + static double mp_stov(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2); + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)_mp_arg(4); + const bool is_strict = (bool)_mp_arg(5); + double val = cimg::type::nan(); + if (ind<0 || ind>=(longT)siz) return val; + if (!siz) return *ptrs>='0' && *ptrs<='9'?*ptrs - '0':val; + + CImg ss(siz + 1 - ind); + ptrs+=1 + ind; + cimg_forX(ss,i) ss[i] = (char)ptrs[i]; + ss.back() = 0; + + const char *s = ss._data; + while (*s && *s<=32) ++s; + const bool is_negative = *s=='-'; + if (is_negative || *s=='+') ++s; + int err = 0; + char sep; + + if (*s=='0' && (s[1]=='x' || s[1]=='X') && s[2]>32) { // Hexadecimal number + unsigned int ival; + err = cimg_sscanf(s + 2,"%x%c",&ival,&sep); + if (err>0) val = (double)ival; + } else if (*s>32) { // Decimal number + err = cimg_sscanf(s,"%lf%c",&val,&sep); +#if cimg_OS==2 + // Check for +/-NaN and +/-inf as Microsoft's sscanf() version is not able + // to read those particular values. + if (!err && (*s=='i' || *s=='I' || *s=='n' || *s=='N')) { + if (!cimg::strncasecmp(s,"inf",3)) { val = cimg::type::inf(); err = 1 + (s[3]!=0); } + else if (!cimg::strncasecmp(s,"nan",3)) { val = cimg::type::nan(); err = 1 + (s[3]!=0); } + } +#endif + } + if (err<=0 || (is_strict && err!=1)) return cimg::type::nan(); + if (is_negative) val = -val; + return val; + } + + static double mp_string(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int nb_args = (unsigned int)(mp.opcode[3] - 3)/2; + CImgList _str; + CImg it; + for (unsigned int n = 0; n string + const double *ptr = &_mp_arg(4 + 2*n) + 1; + unsigned int l = 0; + while (l(ptr,l,1,1,1,true).move_to(_str); + } else { // Scalar argument -> number + it.assign(24); + cimg_snprintf(it,it._width,"%.17g",_mp_arg(4 + 2*n)); + CImg::string(it,false,true).move_to(_str); + } + } + const CImg str = _str>'x'; + const unsigned int sizd = std::min(str._width,(unsigned int)mp.opcode[2]); + std::memset(ptrd,0,mp.opcode[2]*sizeof(double)); + for (unsigned int k = 0; k::nan(); + } + + static double mp_sub(_cimg_math_parser& mp) { + return _mp_arg(2) - _mp_arg(3); + } + + static double mp_sum(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i(ptrs,k,k,1,1,true).trace(); + } + + static double mp_transpose(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg(ptrd,l,k,1,1,true) = CImg(ptrs,k,l,1,1,true).get_transpose(); + return cimg::type::nan(); + } + + static double mp_u(_cimg_math_parser& mp) { + return cimg::rand(_mp_arg(2),_mp_arg(3),&mp.rng); + } + + static double mp_ui2f(_cimg_math_parser& mp) { + return (double)cimg::uint2float((unsigned int)_mp_arg(2)); + } + + static double mp_uppercase(_cimg_math_parser& mp) { + return cimg::uppercase(_mp_arg(2)); + } + + static double mp_var(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i::nan(); + } + + static double mp_vector_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const longT + length = (longT)mp.opcode[3], + start = (longT)_mp_arg(4), + sublength = (longT)mp.opcode[5], + step = (longT)_mp_arg(6); + if (start<0 || start + step*(sublength-1)>=length) + throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Value accessor '[]': " + "Out-of-bounds sub-vector request " + "(length: %ld, start: %ld, sub-length: %ld, step: %ld).", + mp.imgin.pixel_type(),length,start,sublength,step); + ptrs+=start; + if (step==1) std::memcpy(ptrd,ptrs,sublength*sizeof(double)); + else for (longT k = 0; k::nan(); + } + + static double mp_vector_init(_cimg_math_parser& mp) { + unsigned int + ptrs = 4U, + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[3]; + switch (mp.opcode[2] - 4) { + case 0 : std::memset(mp.mem._data + ptrd,0,siz*sizeof(double)); break; // 0 values given + case 1 : { const double val = _mp_arg(ptrs); while (siz-->0) mp.mem[ptrd++] = val; } break; + default : while (siz-->0) { mp.mem[ptrd++] = _mp_arg(ptrs++); if (ptrs>=mp.opcode[2]) ptrs = 4U; } + } + return cimg::type::nan(); + } + + static double mp_vector_eq(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(4) + 1; + unsigned int p1 = (unsigned int)mp.opcode[3], p2 = (unsigned int)mp.opcode[5], n; + const int N = (int)_mp_arg(6); + const bool case_sensitive = (bool)_mp_arg(7); + bool still_equal = true; + double value; + if (!N) return true; + + // Compare all values. + if (N<0) { + if (p1>0 && p2>0) { // Vector == vector + if (p1!=p2) return false; + if (case_sensitive) + while (still_equal && p1--) still_equal = *(ptr1++)==*(ptr2++); + else + while (still_equal && p1--) + still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p1--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p2--) still_equal = *(ptr2++)==value; + return still_equal; + } else { // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + else return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + } + + // Compare only first N values. + if (p1>0 && p2>0) { // Vector == vector + n = cimg::min((unsigned int)N,p1,p2); + if (case_sensitive) + while (still_equal && n--) still_equal = *(ptr1++)==(*ptr2++); + else + while (still_equal && n--) still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + n = std::min((unsigned int)N,p1); + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + n = std::min((unsigned int)N,p2); + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr2++)==value; + return still_equal; + } // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + + static double mp_vector_lerp(_cimg_math_parser& mp) { + unsigned int siz = (unsigned int)mp.opcode[2]; + double *ptrd = &_mp_arg(1) + 1; + const double + *ptrs1 = &_mp_arg(3) + 1, + *ptrs2 = &_mp_arg(4) + 1, + t = _mp_arg(5); + for (unsigned int k = 0; k::nan(); + } + + static double mp_vector_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + return off>=0 && off<(int)siz?mp.mem[ptr + off]:cimg::type::nan(); + } + + static double mp_vector_map_sv(_cimg_math_parser& mp) { // Operator(scalar,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(4); + l_opcode[2] = mp.opcode[4]; // Scalar argument1 + l_opcode.swap(mp.opcode); + ulongT &argument2 = mp.opcode[3]; + while (siz-->0) { argument2 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_v(_cimg_math_parser& mp) { // Operator(vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode.swap(mp.opcode); + ulongT &argument = mp.opcode[2]; + while (siz-->0) { argument = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vs(_cimg_math_parser& mp) { // Operator(vector,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vss(_cimg_math_parser& mp) { // Operator(vector,scalar,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,5); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode[4] = mp.opcode[6]; // Scalar argument3 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vv(_cimg_math_parser& mp) { // Operator(vector,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs1 = (unsigned int)mp.opcode[4] + 1, + ptrs2 = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2], &argument2 = mp.opcode[3]; + while (siz-->0) { argument1 = ptrs1++; argument2 = ptrs2++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_neq(_cimg_math_parser& mp) { + return !mp_vector_eq(mp); + } + + static double mp_vector_print(_cimg_math_parser& mp) { + const bool print_string = (bool)mp.opcode[4]; + cimg_pragma_openmp(critical(mp_vector_print)) + { + CImg _expr(mp.opcode[2] - 5); + const ulongT *ptrs = mp.opcode._data + 5; + cimg_for(_expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(_expr); + unsigned int + ptr = (unsigned int)mp.opcode[1] + 1, + siz0 = (unsigned int)mp.opcode[3], + siz = siz0; + cimg::mutex(6); + std::fprintf(cimg::output(),"\n[" cimg_appname "_math_parser] %s = [ ",_expr._data); + unsigned int count = 0; + while (siz-->0) { + if (count>=64 && siz>=64) { + std::fprintf(cimg::output(),"...,"); + ptr = (unsigned int)mp.opcode[1] + 1 + siz0 - 64; + siz = 64; + } else std::fprintf(cimg::output(),"%.17g%s",mp.mem[ptr++],siz?",":""); + ++count; + } + if (print_string) { + CImg str(siz0 + 1); + ptr = (unsigned int)mp.opcode[1] + 1; + for (unsigned int k = 0; k::nan(); + } + + static double mp_vector_resize(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[2], p2 = (unsigned int)mp.opcode[4]; + const int + interpolation = (int)_mp_arg(5), + boundary_conditions = (int)_mp_arg(6); + if (p2) { // Resize vector + const double *const ptrs = &_mp_arg(3) + 1; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p2,1,1,1,true). + get_resize(p1,1,1,1,interpolation,boundary_conditions); + } else { // Resize scalar + const double value = _mp_arg(3); + CImg(ptrd,p1,1,1,1,true) = CImg(1,1,1,1,value).resize(p1,1,1,1,interpolation, + boundary_conditions); + } + return cimg::type::nan(); + } + + static double mp_vector_reverse(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[3]; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p1,1,1,1,true).get_mirror('x'); + return cimg::type::nan(); + } + + static double mp_vector_set_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + if (off>=0 && off<(int)siz) mp.mem[ptr + off] = _mp_arg(1); + return _mp_arg(1); + } + +#define _cimg_mp_vfunc(func) \ + const longT sizd = (longT)mp.opcode[2];\ + const unsigned int nbargs = (unsigned int)(mp.opcode[3] - 4)/2; \ + double *const ptrd = &_mp_arg(1) + (sizd?1:0); \ + cimg_pragma_openmp(parallel cimg_openmp_if_size(sizd,256)) \ + { CImg vec(nbargs); double res; \ + cimg_pragma_openmp(for) for (longT k = sizd?sizd - 1:0; k>=0; --k) { \ + cimg_forX(vec,n) vec[n] = *(&_mp_arg(4 + 2*n) + (k+1)*(mp.opcode[4 + 2*n + 1]?1:0)); \ + func; ptrd[k] = res; \ + }} \ + return sizd?cimg::type::nan():*ptrd; + + static double _mp_vargkth(CImg& vec) { + const double val = (+vec).get_shared_points(1,vec.width() - 1). + kth_smallest((ulongT)cimg::cut((longT)*vec - 1,(longT)0,(longT)vec.width() - 2)); + cimg_for_inX(vec,1,vec.width()-1,ind) if (vec[ind]==val) return ind - 1.; + return 1.; + } + + static double mp_vargkth(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = _mp_vargkth(vec)); + } + + static double mp_vargmax(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.max() - vec.data())); + } + + static double mp_vargmaxabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.maxabs() - vec.data())); + } + + static double mp_vargmin(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.min() - vec.data())); + } + + static double mp_vargminabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = (double)(&vec.minabs() - vec.data())); + } + + static double mp_vavg(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.mean()); + } + + static double mp_vkth(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.get_shared_points(1,vec.width() - 1). + kth_smallest((ulongT)cimg::cut((longT)*vec - 1,(longT)0,(longT)vec.width() - 2))); + } + + static double mp_vmax(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.max()); + } + + static double mp_vmaxabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.maxabs()); + } + + static double mp_vmedian(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.median()); + } + + static double mp_vmin(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.min()); + } + + static double mp_vminabs(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.minabs()); + } + + static double mp_vprod(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.product()); + } + + static double mp_vstd(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = std::sqrt(vec.get_stats()[3])); + } + + static double mp_vsum(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.sum()); + } + + static double mp_vvar(_cimg_math_parser& mp) { + _cimg_mp_vfunc(res = vec.get_stats()[3]); + } + + static double mp_vtos(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + sizd = (unsigned int)mp.opcode[2], + sizs = (unsigned int)mp.opcode[4]; + std::memset(ptrd,0,sizd*sizeof(double)); + const int nb_digits = (int)_mp_arg(5); + CImg format(8); + switch (nb_digits) { + case -1 : std::strcpy(format,"%g"); break; + case 0 : std::strcpy(format,"%.17g"); break; + default : cimg_snprintf(format,format._width,"%%.%dg",nb_digits); + } + CImg str; + if (sizs) { // Vector expression + const double *ptrs = &_mp_arg(3) + 1; + CImg(ptrs,sizs,1,1,1,true).value_string(',',sizd + 1,format).move_to(str); + } else { // Scalar expression + str.assign(sizd + 1); + cimg_snprintf(str,sizd + 1,format,_mp_arg(3)); + } + const unsigned int l = std::min(sizd,(unsigned int)std::strlen(str) + 1); + CImg(ptrd,l,1,1,1,true) = str.get_shared_points(0,l - 1); + return cimg::type::nan(); + } + + static double mp_while(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_cond = ++mp.p_code, + *const p_body = p_cond + mp.opcode[3], + *const p_end = p_body + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + bool is_cond = false; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_cond; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) // Evaluate body + for (mp.p_code = p_body; mp.p_code_data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3), + vsiz = (unsigned int)mp.opcode[4]; + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6), + vsiz = (unsigned int)mp.opcode[7]; + const CImg &img = mp.imgin; + const double x = _mp_arg(2), y = _mp_arg(3), z = _mp_arg(4); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + + static double mp_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3), + vsiz = (unsigned int)mp.opcode[4]; + const CImg &img = mp.imgin; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], + oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off>=0 && off::nan(); + } + if (img._data) switch (boundary_conditions) { + case 3 : { // Mirror + const longT whd2 = 2*whd, moff = cimg::mod(off,whd2); + ptrs = &img[moff::nan(); + } + case 2 : // Periodic + ptrs = &img[cimg::mod(off,whd)]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + case 1 : // Neumann + ptrs = off<0?&img[0]:&img[whd - 1]; + cimg_for_inC(img,0,vsiz - 1,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + default : // Dirichlet + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + std::memset(ptrd,0,vsiz*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6), + vsiz = (unsigned int)mp.opcode[7]; + const CImg &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), z = oz + _mp_arg(4); + const ulongT whd = (ulongT)img._width*img._height*img._depth; + const T *ptrs; + switch (interpolation) { + case 2 : // Cubic interpolation + switch (boundary_conditions) { + case 3 : { // Mirror + const float + w2 = 2.f*img.width(), h2 = 2.f*img.height(), d2 = 2.f*img.depth(), + mx = cimg::mod((float)x,w2), my = cimg::mod((float)y,h2), mz = cimg::mod((float)z,d2), + cx = mx::nan(); + } + +#undef _mp_arg + + }; // struct _cimg_math_parser {} + +#define _cimg_create_pointwise_functions(name,func,min_size) \ + CImg& name() { \ + if (is_empty()) return *this; \ + cimg_openmp_for(*this,func((double)*ptr),min_size); \ + return *this; \ + } \ + CImg get_##name() const { \ + return CImg(*this,false).name(); \ + } + + //! Compute the square value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square value \f$I_{(x,y,z,c)}^2\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqr().normalize(0,255)).display(); + \endcode + \image html ref_sqr.jpg + **/ + _cimg_create_pointwise_functions(sqr,cimg::sqr,524288) + + //! Compute the square root of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square root \f$\sqrt{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqrt().normalize(0,255)).display(); + \endcode + \image html ref_sqrt.jpg + **/ + _cimg_create_pointwise_functions(sqrt,std::sqrt,8192) + + //! Compute the exponential of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its exponential \f$e^{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(exp,std::exp,4096) + + //! Compute the logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its logarithm + \f$\mathrm{log}_{e}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log,std::log,262144) + + //! Compute the base-2 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-2 logarithm + \f$\mathrm{log}_{2}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log2,cimg::log2,4096) + + //! Compute the base-10 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-10 logarithm + \f$\mathrm{log}_{10}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(log10,std::log10,4096) + + //! Compute the absolute value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its absolute value \f$|I_{(x,y,z,c)}|\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(abs,cimg::abs,524288) + + //! Compute the sign of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sign + \f$\mathrm{sign}(I_{(x,y,z,c)})\f$. + \note + - The sign is set to: + - \c 1 if pixel value is strictly positive. + - \c -1 if pixel value is strictly negative. + - \c 0 if pixel value is equal to \c 0. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sign,cimg::sign,32768) + + //! Compute the cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its cosine \f$\cos(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(cos,std::cos,8192) + + //! Compute the sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sine \f$\sin(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sin,std::sin,8192) + + //! Compute the sinc of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sinc + \f$\mathrm{sinc}(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sinc,cimg::sinc,2048) + + //! Compute the tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its tangent \f$\tan(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(tan,std::tan,2048) + + //! Compute the hyperbolic cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic cosine + \f$\mathrm{cosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(cosh,std::cosh,2048) + + //! Compute the hyperbolic sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic sine + \f$\mathrm{sinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(sinh,std::sinh,2048) + + //! Compute the hyperbolic tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic tangent + \f$\mathrm{tanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(tanh,std::tanh,2048) + + //! Compute the arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosine + \f$\mathrm{acos}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(acos,std::acos,8192) + + //! Compute the arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arcsine + \f$\mathrm{asin}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(asin,std::asin,8192) + + //! Compute the arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent + \f$\mathrm{atan}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(atan,std::atan,8192) + + //! Compute the arctangent2 of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent2 + \f$\mathrm{atan2}(I_{(x,y,z,c)})\f$. + \param img Image whose pixel values specify the second argument of the \c atan2() function. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img_x(100,100,1,1,"x-w/2",false), // Define an horizontal centered gradient, from '-width/2' to 'width/2' + img_y(100,100,1,1,"y-h/2",false), // Define a vertical centered gradient, from '-height/2' to 'height/2' + img_atan2 = img_y.get_atan2(img_x); // Compute atan2(y,x) for each pixel value + (img_x,img_y,img_atan2).display(); + \endcode + **/ + template + CImg& atan2(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return atan2(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_atan2(const CImg& img) const { + return CImg(*this,false).atan2(img); + } + + //! Compute the hyperbolic arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosineh + \f$\mathrm{acosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(acosh,cimg::acosh,8192) + + //! Compute the hyperbolic arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic arcsine + \f$\mathrm{asinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(asinh,cimg::asinh,8192) + + //! Compute the hyperbolic arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic arctangent + \f$\mathrm{atanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + _cimg_create_pointwise_functions(atanh,cimg::atanh,8192) + + //! In-place pointwise multiplication. + /** + Compute the pointwise multiplication between the image instance and the specified input image \c img. + \param img Input image, as the second operand of the multiplication. + \note + - Similar to operator+=(const CImg&), except that it performs a pointwise multiplication + instead of an addition. + - It does \e not perform a \e matrix multiplication. For this purpose, use operator*=(const CImg&) instead. + \par Example + \code + CImg + img("reference.jpg"), + shade(img.width,img.height(),1,1,"-(x-w/2)^2-(y-h/2)^2",false); + shade.normalize(0,1); + (img,shade,img.get_mul(shade)).display(); + \endcode + **/ + template + CImg& mul(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return mul(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_mul(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).mul(img); + } + + //! In-place pointwise division. + /** + Similar to mul(const CImg&), except that it performs a pointwise division instead of a multiplication. + **/ + template + CImg& div(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return div(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_div(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).div(img); + } + + //! Raise each pixel value to a specified power. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its power \f$I_{(x,y,z,c)}^p\f$. + \param p Exponent value. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img0("reference.jpg"), // Load reference color image + img1 = (img0/255).pow(1.8)*=255, // Compute gamma correction, with gamma = 1.8 + img2 = (img0/255).pow(0.5)*=255; // Compute gamma correction, with gamma = 0.5 + (img0,img1,img2).display(); + \endcode + **/ + CImg& pow(const double p) { + if (is_empty()) return *this; + if (p==-4) { cimg_openmp_for(*this,1/(Tfloat)cimg::pow4(*ptr),32768); return *this; } + if (p==-3) { cimg_openmp_for(*this,1/(Tfloat)cimg::pow3(*ptr),32768); return *this; } + if (p==-2) { cimg_openmp_for(*this,1/(Tfloat)cimg::sqr(*ptr),32768); return *this; } + if (p==-1) { cimg_openmp_for(*this,1/(Tfloat)*ptr,32768); return *this; } + if (p==-0.5) { cimg_openmp_for(*this,1/std::sqrt((Tfloat)*ptr),8192); return *this; } + if (p==0) return fill((T)1); + if (p==0.5) return sqrt(); + if (p==1) return *this; + if (p==2) return sqr(); + if (p==3) { cimg_openmp_for(*this,cimg::pow3(*ptr),262144); return *this; } + if (p==4) { cimg_openmp_for(*this,cimg::pow4(*ptr),131072); return *this; } + cimg_openmp_for(*this,std::pow((Tfloat)*ptr,(Tfloat)p),1024); + return *this; + } + + //! Raise each pixel value to a specified power \newinstance. + CImg get_pow(const double p) const { + return CImg(*this,false).pow(p); + } + + //! Raise each pixel value to a power, specified from an expression. + /** + Similar to operator+=(const char*), except it performs a pointwise exponentiation instead of an addition. + **/ + CImg& pow(const char *const expression) { + return pow((+*this)._fill(expression,true,1,0,0,"pow",this)); + } + + //! Raise each pixel value to a power, specified from an expression \newinstance. + CImg get_pow(const char *const expression) const { + return CImg(*this,false).pow(expression); + } + + //! Raise each pixel value to a power, pointwisely specified from another image. + /** + Similar to operator+=(const CImg& img), except that it performs an exponentiation instead of an addition. + **/ + template + CImg& pow(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return pow(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_pow(const CImg& img) const { + return CImg(*this,false).pow(img); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(unsigned int), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::rol(*ptr,n),32768); + return *this; + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const unsigned int n=1) const { + return (+*this).rol(n); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const char*), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const char *const expression) { + return rol((+*this)._fill(expression,true,1,0,0,"rol",this)); + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const char *const expression) const { + return (+*this).rol(expression); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const CImg&), except that it performs a left rotation instead of a left shift. + **/ + template + CImg& rol(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return rol(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_rol(const CImg& img) const { + return (+*this).rol(img); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(unsigned int), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_openmp_for(*this,cimg::ror(*ptr,n),32768); + return *this; + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const unsigned int n=1) const { + return (+*this).ror(n); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const char*), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const char *const expression) { + return ror((+*this)._fill(expression,true,1,0,0,"ror",this)); + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const char *const expression) const { + return (+*this).ror(expression); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const CImg&), except that it performs a right rotation instead of a right shift. + **/ + template + CImg& ror(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return ror(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_ror(const CImg& img) const { + return (+*this).ror(img); + } + + //! Pointwise min operator between instance image and a value. + /** + \param val Value used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& min(const T& value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,std::min(*ptr,value),65536); + return *this; + } + + //! Pointwise min operator between instance image and a value \newinstance. + CImg get_min(const T& value) const { + return (+*this).min(value); + } + + //! Pointwise min operator between two images. + /** + \param img Image used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& min(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return min(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_min(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).min(img); + } + + //! Pointwise min operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& min(const char *const expression) { + return min((+*this)._fill(expression,true,1,0,0,"min",this)); + } + + //! Pointwise min operator between an image and an expression \newinstance. + CImg get_min(const char *const expression) const { + return CImg(*this,false).min(expression); + } + + //! Pointwise max operator between instance image and a value. + /** + \param val Value used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& max(const T& value) { + if (is_empty()) return *this; + cimg_openmp_for(*this,std::max(*ptr,value),65536); + return *this; + } + + //! Pointwise max operator between instance image and a value \newinstance. + CImg get_max(const T& value) const { + return (+*this).max(value); + } + + //! Pointwise max operator between two images. + /** + \param img Image used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& max(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return max(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_max(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).max(img); + } + + //! Pointwise max operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& max(const char *const expression) { + return max((+*this)._fill(expression,true,1,0,0,"max",this)); + } + + //! Pointwise max operator between an image and an expression \newinstance. + CImg get_max(const char *const expression) const { + return CImg(*this,false).max(expression); + } + + //! Pointwise minabs operator between instance image and a value. + /** + \param val Value used as the reference argument of the minabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& minabs(const T& value) { + if (is_empty()) return *this; + const T absvalue = cimg::abs(value); + cimg_openmp_for(*this,cimg::minabs(*ptr,value,absvalue),65536); + return *this; + } + + //! Pointwise minabs operator between instance image and a value \newinstance. + CImg get_minabs(const T& value) const { + return (+*this).minabs(value); + } + + //! Pointwise minabs operator between two images. + /** + \param img Image used as the reference argument of the minabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& minabs(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return minabs(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_minabs(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).minabs(img); + } + + //! Pointwise minabs operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{minabs}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& minabs(const char *const expression) { + return minabs((+*this)._fill(expression,true,1,0,0,"minabs",this)); + } + + //! Pointwise minabs operator between an image and an expression \newinstance. + CImg get_minabs(const char *const expression) const { + return CImg(*this,false).minabs(expression); + } + + //! Pointwise maxabs operator between instance image and a value. + /** + \param val Value used as the reference argument of the maxabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& maxabs(const T& value) { + if (is_empty()) return *this; + const T absvalue = cimg::abs(value); + cimg_openmp_for(*this,cimg::maxabs(*ptr,value,absvalue),65536); + return *this; + } + + //! Pointwise maxabs operator between instance image and a value \newinstance. + CImg get_maxabs(const T& value) const { + return (+*this).maxabs(value); + } + + //! Pointwise maxabs operator between two images. + /** + \param img Image used as the reference argument of the maxabs operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& maxabs(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return maxabs(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_maxabs(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).maxabs(img); + } + + //! Pointwise maxabs operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{maxabs}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& maxabs(const char *const expression) { + return maxabs((+*this)._fill(expression,true,1,0,0,"maxabs",this)); + } + + //! Pointwise maxabs operator between an image and an expression \newinstance. + CImg get_maxabs(const char *const expression) const { + return CImg(*this,false).maxabs(expression); + } + + //! Return a reference to the minimum pixel value. + /** + **/ + T& min() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min; + cimg_for(*this,ptrs,T) if (*ptrsmax_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value \const. + const T& max() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max; + cimg_for(*this,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value in absolute value. + /** + **/ + T& maxabs() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "maxabs(): Empty instance.", + cimg_instance); + T *ptr_maxabs = _data; + T maxabs_value = *ptr_maxabs; + cimg_for(*this,ptrs,T) { + const T ma = cimg::abs(*ptrs); + if (ma>maxabs_value) { maxabs_value = ma; ptr_maxabs = ptrs; } + } + return *ptr_maxabs; + } + + //! Return a reference to the maximum pixel value in absolute value \const. + const T& maxabs() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "maxabs(): Empty instance.", + cimg_instance); + const T *ptr_maxabs = _data; + T maxabs_value = *ptr_maxabs; + cimg_for(*this,ptrs,T) { + const T ma = cimg::abs(*ptrs); + if (ma>maxabs_value) { maxabs_value = ma; ptr_maxabs = ptrs; } + } + return *ptr_maxabs; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value. + /** + \param[out] max_val Maximum pixel value. + **/ + template + T& min_max(t& max_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value \const. + template + const T& min_max(t& max_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + const T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the maximum pixel value as well as the minimum pixel value. + /** + \param[out] min_val Minimum pixel value. + **/ + template + T& max_min(t& min_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val=size()) return max(); + CImg arr(*this,false); + ulongT l = 0, ir = size() - 1; + for ( ; ; ) { + if (ir<=l + 1) { + if (ir==l + 1 && arr[ir]>1; + cimg::swap(arr[mid],arr[l + 1]); + if (arr[l]>arr[ir]) cimg::swap(arr[l],arr[ir]); + if (arr[l + 1]>arr[ir]) cimg::swap(arr[l + 1],arr[ir]); + if (arr[l]>arr[l + 1]) cimg::swap(arr[l],arr[l + 1]); + ulongT i = l + 1, j = ir; + const T pivot = arr[l + 1]; + for ( ; ; ) { + do ++i; while (arr[i]pivot); + if (j=k) ir = j - 1; + if (j<=k) l = i; + } + } + } + + //! Return the median pixel value. + /** + **/ + T median() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "median(): Empty instance.", + cimg_instance); + const ulongT s = size(); + switch (s) { + case 1 : return _data[0]; + case 2 : return cimg::median(_data[0],_data[1]); + case 3 : return cimg::median(_data[0],_data[1],_data[2]); + case 5 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4]); + case 7 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6]); + case 9 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8]); + case 13 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8], + _data[9],_data[10],_data[11],_data[12]); + } + const T res = kth_smallest(s>>1); + return (s%2)?res:(T)((res + kth_smallest((s>>1) - 1))/2); + } + + //! Return the product of all the pixel values. + /** + **/ + double product() const { + if (is_empty()) return 0; + double res = 1; + cimg_for(*this,ptrs,T) res*=(double)*ptrs; + return res; + } + + //! Return the sum of all the pixel values. + /** + **/ + double sum() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res; + } + + //! Return the average pixel value. + /** + **/ + double mean() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res/size(); + } + + //! Return the variance of the pixel values. + /** + \param variance_method Method used to estimate the variance. Can be: + - \c 0: Second moment, computed as + \f$1/N \sum\limits_{k=1}^{N} (x_k - \bar x)^2 = + 1/N \left( \sum\limits_{k=1}^N x_k^2 - \left( \sum\limits_{k=1}^N x_k \right)^2 / N \right)\f$ + with \f$ \bar x = 1/N \sum\limits_{k=1}^N x_k \f$. + - \c 1: Best unbiased estimator, computed as \f$\frac{1}{N - 1} \sum\limits_{k=1}^{N} (x_k - \bar x)^2 \f$. + - \c 2: Least median of squares. + - \c 3: Least trimmed of squares. + **/ + double variance(const unsigned int variance_method=1) const { + double foo; + return variance_mean(variance_method,foo); + } + + //! Return the variance as well as the average of the pixel values. + /** + \param variance_method Method used to estimate the variance (see variance(const unsigned int) const). + \param[out] mean Average pixel value. + **/ + template + double variance_mean(const unsigned int variance_method, t& mean) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_mean(): Empty instance.", + cimg_instance); + + double variance = 0, average = 0; + const ulongT siz = size(); + switch (variance_method) { + case 0 : { // Least mean square (standard definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = (S2 - S*S/siz)/siz; + average = S; + } break; + case 1 : { // Least mean square (robust definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + average = S; + } break; + case 2 : { // Least Median of Squares (MAD) + CImg buf(*this,false); + buf.sort(); + const ulongT siz2 = siz>>1; + const double med_i = (double)buf[siz2]; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; *ptrs = (Tfloat)cimg::abs(val - med_i); average+=val; + } + buf.sort(); + const double sig = (double)(1.4828*buf[siz2]); + variance = sig*sig; + } break; + default : { // Least trimmed of Squares + CImg buf(*this,false); + const ulongT siz2 = siz>>1; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; (*ptrs)=(Tfloat)((*ptrs)*val); average+=val; + } + buf.sort(); + double a = 0; + const Tfloat *ptrs = buf._data; + for (ulongT j = 0; j0?variance:0; + } + + //! Return estimated variance of the noise. + /** + \param variance_method Method used to compute the variance (see variance(const unsigned int) const). + \note Because of structures such as edges in images it is + recommended to use a robust variance estimation. The variance of the + noise is estimated by computing the variance of the Laplacian \f$(\Delta + I)^2 \f$ scaled by a factor \f$c\f$ insuring \f$ c E[(\Delta I)^2]= + \sigma^2\f$ where \f$\sigma\f$ is the noise variance. + **/ + double variance_noise(const unsigned int variance_method=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_noise(): Empty instance.", + cimg_instance); + + const ulongT siz = size(); + if (!siz || !_data) return 0; + if (variance_method>1) { // Compute a scaled version of the Laplacian + CImg tmp(*this,false); + if (_depth==1) { + const double cste = 1./std::sqrt(20.); // Depends on how the Laplacian is computed + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*262144 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3(I,T); + cimg_for3x3(*this,x,y,0,c,I,T) { + tmp(x,y,c) = cste*((double)Inc + (double)Ipc + (double)Icn + + (double)Icp - 4*(double)Icc); + } + } + } else { + const double cste = 1./std::sqrt(42.); // Depends on how the Laplacian is computed + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*262144 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,T); + cimg_for3x3x3(*this,x,y,z,c,I,T) { + tmp(x,y,z,c) = cste*( + (double)Incc + (double)Ipcc + (double)Icnc + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + } + } + } + return tmp.variance(variance_method); + } + + // Version that doesn't need intermediate images. + double variance = 0, S = 0, S2 = 0; + if (_depth==1) { + const double cste = 1./std::sqrt(20.); + CImg_3x3(I,T); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,T) { + const double val = cste*((double)Inc + (double)Ipc + + (double)Icn + (double)Icp - 4*(double)Icc); + S+=val; S2+=val*val; + } + } else { + const double cste = 1./std::sqrt(42.); + CImg_3x3x3(I,T); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,T) { + const double val = cste * + ((double)Incc + (double)Ipcc + (double)Icnc + + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + S+=val; S2+=val*val; + } + } + if (variance_method) variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + else variance = (S2 - S*S/siz)/siz; + return variance>0?variance:0; + } + + //! Compute the MSE (Mean-Squared Error) between two images. + /** + \param img Image used as the second argument of the MSE operator. + **/ + template + double MSE(const CImg& img) const { + if (img.size()!=size()) + throw CImgArgumentException(_cimg_instance + "MSE(): Instance and specified image (%u,%u,%u,%u,%p) have different dimensions.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + double vMSE = 0; + const t* ptr2 = img._data; + cimg_for(*this,ptr1,T) { + const double diff = (double)*ptr1 - (double)*(ptr2++); + vMSE+=diff*diff; + } + const ulongT siz = img.size(); + if (siz) vMSE/=siz; + return vMSE; + } + + //! Compute the PSNR (Peak Signal-to-Noise Ratio) between two images. + /** + \param img Image used as the second argument of the PSNR operator. + \param max_value Maximum theoretical value of the signal. + **/ + template + double PSNR(const CImg& img, const double max_value=255) const { + const double vMSE = (double)std::sqrt(MSE(img)); + return (vMSE!=0)?(double)(20*std::log10(max_value/vMSE)):(double)(cimg::type::max()); + } + + //! Evaluate math formula. + /** + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,x,y,z,c,list_inputs,list_outputs); + } + + // Fast function to pre-evaluate common expressions. + // (return 'true' in case of success, and set value of 'res'). + template + bool __eval(const char *const expression, t &res) const { + if (!expression || !*expression) { res = (t)0; return true; } + const char c = *expression; + bool is_success = false; + char c1, end; + double val; + if (c>='0' && c<='9') { // Possible value + if (!expression[1]) { // Single digit + res = (t)(c - '0'); + is_success = true; + } else if (std::sscanf(expression,"%lf%c",&val,&end)==1) { // Single value + res = (t)val; + is_success = true; + } + } else if ((c=='+' || c=='-' || c=='!') && // +Value, -Value or !Value + (c1=expression[1])>='0' && c1<='0') { + if (!expression[2]) { // [+-!] + Single digit + const int ival = c1 - '0'; + res = (t)(c=='+'?ival:c=='-'?-ival:!ival); + is_success = true; + } else if (std::sscanf(expression + 1,"%lf%c",&val,&end)==1) { // [+-!] Single value + res = (t)(c=='+'?val:c=='-'?-val:(double)!val); + is_success = true; + } + } else if (!expression[1]) switch (*expression) { // Other common single-char expressions + case 'w' : res = (t)_width; is_success = true; break; + case 'h' : res = (t)_height; is_success = true; break; + case 'd' : res = (t)_depth; is_success = true; break; + case 's' : res = (t)_spectrum; is_success = true; break; + case 'r' : res = (t)_is_shared; is_success = true; break; + } + return is_success; + } + + double _eval(CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression || !*expression) return 0; + double _val = 0; + if (__eval(expression,_val)) return _val; + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs,false); + mp.begin_t(); + const double val = mp(x,y,z,c); + mp.end_t(); + mp.end(); + return val; + } + + //! Evaluate math formula. + /** + \param[out] output Contains values of output vector returned by the evaluated expression + (or is empty if the returned type is scalar). + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + void eval(CImg &output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + _eval(output,this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + template + void eval(CImg& output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + _eval(output,0,expression,x,y,z,c,list_inputs,list_outputs); + } + + template + void _eval(CImg& output, CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression || !*expression) { output.assign(1); *output = 0; return; } + double _val = 0; + if (__eval(expression,_val)) { output.assign(1); *output = _val; return; } + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs,false); + output.assign(1,std::max(1U,mp.result_dim)); + mp.begin_t(); + mp(x,y,z,c,output._data); + mp.end_t(); + mp.end(); + } + + //! Evaluate math formula on a set of variables. + /** + \param expression Math formula, as a C-string. + \param xyzc Set of values (x,y,z,c) used for the evaluation. + \param list_inputs A list of input images attached to the specified math formula. + \param[out] list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,xyzc,list_inputs,list_outputs); + } + + //! Evaluate math formula on a set of variables \const. + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,xyzc,list_inputs,list_outputs); + } + + template + CImg _eval(CImg *const output, const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + CImg res(1,xyzc.size()/4); + if (!expression || !*expression) return res.fill(0); + _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs,false); + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel if (res._height>=512)) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_eval)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + cimg_pragma_openmp(for) + for (int i = 0; i[min, max, mean, variance, xmin, ymin, zmin, cmin, xmax, ymax, zmax, cmax, sum, product]. + **/ + CImg get_stats(const unsigned int variance_method=1) const { + if (is_empty()) return CImg(); + const ulongT siz = size(); + const longT off_end = (longT)siz; + double S = 0, S2 = 0, P = 1; + longT offm = 0, offM = 0; + T m = *_data, M = m; + + cimg_pragma_openmp(parallel reduction(+:S,S2) reduction(*:P) cimg_openmp_if_size(siz,131072)) { + longT loffm = 0, loffM = 0; + T lm = *_data, lM = lm; + cimg_pragma_openmp(for) + for (longT off = 0; offlM) { lM = val; loffM = off; } + S+=_val; + S2+=_val*_val; + P*=_val; + } + cimg_pragma_openmp(critical(get_stats)) { + if (lmM || (lM==M && loffM1?(S2 - S*S/siz)/(siz - 1):0): + variance(variance_method)), + variance_value = _variance_value>0?_variance_value:0; + int + xm = 0, ym = 0, zm = 0, cm = 0, + xM = 0, yM = 0, zM = 0, cM = 0; + contains(_data[offm],xm,ym,zm,cm); + contains(_data[offM],xM,yM,zM,cM); + return CImg(1,14).fill((double)m,(double)M,mean_value,variance_value, + (double)xm,(double)ym,(double)zm,(double)cm, + (double)xM,(double)yM,(double)zM,(double)cM, + S,P); + } + + //! Compute statistics vector from the pixel values \inplace. + CImg& stats(const unsigned int variance_method=1) { + return get_stats(variance_method).move_to(*this); + } + + //@} + //------------------------------------- + // + //! \name Vector / Matrix Operations + //@{ + //------------------------------------- + + //! Compute norm of the image, viewed as a matrix. + /** + \param magnitude_type Norm type. Can be: + - \c -1: Linf-norm + - \c 0: L0-norm + - \c 1: L1-norm + - \c 2: L2-norm + **/ + double magnitude(const int magnitude_type=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "magnitude(): Empty instance.", + cimg_instance); + const ulongT siz = size(); + double res = 0; + switch (magnitude_type) { + case -1 : { + cimg_for(*this,ptrs,T) { const double val = (double)cimg::abs(*ptrs); if (val>res) res = val; } + } break; + case 1 : { + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(size(),8192)) + for (longT off = 0; off<(longT)siz; ++off) res+=(double)cimg::abs(_data[off]); + } break; + default : { + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(size(),8192)) + for (longT off = 0; off<(longT)siz; ++off) res+=(double)cimg::sqr(_data[off]); + res = (double)std::sqrt(res); + } + } + return res; + } + + //! Compute the trace of the image, viewed as a matrix. + /** + **/ + double trace() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "trace(): Empty instance.", + cimg_instance); + double res = 0; + cimg_forX(*this,k) res+=(double)(*this)(k,k); + return res; + } + + //! Compute the determinant of the image, viewed as a matrix. + /** + **/ + double det() const { + if (is_empty() || _width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "det(): Instance is not a square matrix.", + cimg_instance); + + switch (_width) { + case 1 : return (double)((*this)(0,0)); + case 2 : return (double)((*this)(0,0))*(double)((*this)(1,1)) - (double)((*this)(0,1))*(double)((*this)(1,0)); + case 3 : { + const double + a = (double)_data[0], d = (double)_data[1], g = (double)_data[2], + b = (double)_data[3], e = (double)_data[4], h = (double)_data[5], + c = (double)_data[6], f = (double)_data[7], i = (double)_data[8]; + return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e; + } + default : { + CImg lu(*this,false); + CImg indx; + bool d; + lu._LU(indx,d); + double res = d?(double)1:(double)-1; + cimg_forX(lu,i) res*=lu(i,i); + return res; + } + } + } + + //! Compute the dot product between instance and argument, viewed as matrices. + /** + \param img Image used as a second argument of the dot product. + **/ + template + double dot(const CImg& img) const { + const ulongT nb = std::min(size(),img.size()); + double res = 0; + cimg_pragma_openmp(parallel for reduction(+:res) cimg_openmp_if_size(nb,8192)) + for (longT off = 0; off<(longT)nb; ++off) res+=(double)_data[off]*(double)img[off]; + return res; + } + + //! Get vector-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + CImg res; + if (res._height!=_spectrum) res.assign(1,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + const T *ptrs = data(x,y,z); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get (square) matrix-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \note - The spectrum() of the image must be a square. + **/ + CImg get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const { + const int n = (int)cimg::round(std::sqrt((double)_spectrum)); + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(n,n); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get tensor-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + if (_spectrum==6) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd),*(ptrs + 3*whd),*(ptrs + 4*whd),*(ptrs + 5*whd)); + if (_spectrum==3) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd)); + return tensor(*ptrs); + } + + //! Set vector-valued pixel at specified position. + /** + \param vec Vector to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_vector_at(const CImg& vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0) { + if (x<_width && y<_height && z<_depth) { + const t *ptrs = vec._data; + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = data(x,y,z); + for (unsigned int k = std::min((unsigned int)vec.size(),_spectrum); k; --k) { + *ptrd = (T)*(ptrs++); ptrd+=whd; + } + } + return *this; + } + + //! Set (square) matrix-valued pixel at specified position. + /** + \param mat Matrix to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_matrix_at(const CImg& mat, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + return set_vector_at(mat,x,y,z); + } + + //! Set tensor-valued pixel at specified position. + /** + \param ten Tensor to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_tensor_at(const CImg& ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + T *ptrd = data(x,y,z,0); + const ulongT siz = (ulongT)_width*_height*_depth; + if (ten._height==2) { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[3]; + } + else { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[2]; ptrd+=siz; + *ptrd = (T)ten[4]; ptrd+=siz; + *ptrd = (T)ten[5]; ptrd+=siz; + *ptrd = (T)ten[8]; + } + return *this; + } + + //! Resize image to become a diagonal matrix. + /** + \note Transform the image as a diagonal matrix so that each of its initial value becomes a diagonal coefficient. + **/ + CImg& diagonal() { + return get_diagonal().move_to(*this); + } + + //! Resize image to become a diagonal matrix \newinstance. + CImg get_diagonal() const { + if (is_empty()) return *this; + const unsigned int siz = (unsigned int)size(); + CImg res(siz,siz,1,1,0); + cimg_foroff(*this,off) res((unsigned int)off,(unsigned int)off) = (*this)[off]; + return res; + } + + //! Replace the image by an identity matrix. + /** + \note If the instance image is not square, it is resized to a square matrix using its maximum + dimension as a reference. + **/ + CImg& identity_matrix() { + return identity_matrix(std::max(_width,_height)).move_to(*this); + } + + //! Replace the image by an identity matrix \newinstance. + CImg get_identity_matrix() const { + return identity_matrix(std::max(_width,_height)); + } + + //! Fill image with a linear sequence of values. + /** + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + CImg& sequence(const T& a0, const T& a1) { + if (is_empty()) return *this; + const ulongT siz = size() - 1; + T* ptr = _data; + if (siz) { + const double delta = (double)a1 - (double)a0; + cimg_foroff(*this,l) *(ptr++) = (T)(a0 + delta*l/siz); + } else *ptr = a0; + return *this; + } + + //! Fill image with a linear sequence of values \newinstance. + CImg get_sequence(const T& a0, const T& a1) const { + return (+*this).sequence(a0,a1); + } + + //! Transpose the image, viewed as a matrix. + /** + \note Equivalent to \code permute_axes("yxzc"); \endcode. + **/ + CImg& transpose() { + if (_width==1) { _width = _height; _height = 1; return *this; } + if (_height==1) { _height = _width; _width = 1; return *this; } + if (_width==_height) { + cimg_forYZC(*this,y,z,c) for (int x = y; x get_transpose() const { + return get_permute_axes("yxzc"); + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors. + /** + \param img Image used as the second argument of the cross product. + \note The first argument of the cross product is \c *this. + **/ + template + CImg& cross(const CImg& img) { + if (_width!=1 || _height<3 || img._width!=1 || img._height<3) + throw CImgInstanceException(_cimg_instance + "cross(): Instance and/or specified image (%u,%u,%u,%u,%p) are not 3D vectors.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + + const T x = (*this)[0], y = (*this)[1], z = (*this)[2]; + (*this)[0] = (T)(y*img[2] - z*img[1]); + (*this)[1] = (T)(z*img[0] - x*img[2]); + (*this)[2] = (T)(x*img[1] - y*img[0]); + return *this; + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3D vectors \newinstance. + template + CImg<_cimg_Tt> get_cross(const CImg& img) const { + return CImg<_cimg_Tt>(*this).cross(img); + } + + //! Invert the instance image, viewed as a matrix. + /** + \param use_LU Choose the inverting algorithm. Can be: + - \c true: LU-based matrix inversion. + - \c false: SVD-based matrix inversion. + **/ + CImg& invert(const bool use_LU=true) { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "invert(): Instance is not a square matrix.", + cimg_instance); + const double dete = _width>3?-1.:det(); + if (dete!=0. && _width==2) { + const double + a = _data[0], c = _data[1], + b = _data[2], d = _data[3]; + _data[0] = (T)(d/dete); _data[1] = (T)(-c/dete); + _data[2] = (T)(-b/dete); _data[3] = (T)(a/dete); + } else if (dete!=0. && _width==3) { + const double + a = _data[0], d = _data[1], g = _data[2], + b = _data[3], e = _data[4], h = _data[5], + c = _data[6], f = _data[7], i = _data[8]; + _data[0] = (T)((i*e - f*h)/dete), _data[1] = (T)((g*f - i*d)/dete), _data[2] = (T)((d*h - g*e)/dete); + _data[3] = (T)((h*c - i*b)/dete), _data[4] = (T)((i*a - c*g)/dete), _data[5] = (T)((g*b - a*h)/dete); + _data[6] = (T)((b*f - e*c)/dete), _data[7] = (T)((d*c - a*f)/dete), _data[8] = (T)((a*e - d*b)/dete); + } else { + +#ifdef cimg_use_lapack + int INFO = (int)use_LU, N = _width, LWORK = 4*N, *const IPIV = new int[N]; + Tfloat + *const lapA = new Tfloat[N*N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetri_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)(lapA[k*N + l]); else fill(0); + delete[] IPIV; delete[] lapA; delete[] WORK; +#else + if (use_LU) { // LU-based + CImg A(*this,false), indx; + bool d; + A._LU(indx,d); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16*16)) + cimg_forX(*this,j) { + CImg col(1,_width,1,1,0); + col(j) = 1; + col._solve(A,indx); + cimg_forX(*this,i) (*this)(j,i) = (T)col(i); + } + } else pseudoinvert(false); // SVD-based +#endif + } + return *this; + } + + //! Invert the instance image, viewed as a matrix \newinstance. + CImg get_invert(const bool use_LU=true) const { + return CImg(*this,false).invert(use_LU); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix. + /** + **/ + CImg& pseudoinvert(const bool use_LU=false) { + return get_pseudoinvert(use_LU).move_to(*this); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix \newinstance. + CImg get_pseudoinvert(const bool use_LU=false) const { + + // LU-based method. + if (use_LU) { + CImg AtA(width(),width()); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,128*128)) + cimg_forY(AtA,i) + for (int j = 0; j<=i; ++j) { + double res = 0; + cimg_forY(*this,k) res+=(*this)(i,k)*(*this)(j,k); + AtA(j,i) = AtA(i,j) = (Tfloat)res; + } + AtA.invert(true); + return AtA*get_transpose(); + } + + // SVD-based method. + CImg U, S, V; + SVD(U,S,V,false); + const Tfloat epsilon = (sizeof(Tfloat)<=4?5.96e-8f:1.11e-16f)*std::max(_width,_height)*S.max(); + cimg_forX(V,x) { + const Tfloat s = S(x), invs = s>epsilon?1/s:0; + cimg_forY(V,y) V(x,y)*=invs; + } + return V*U.transpose(); + } + + //! Solve a system of linear equations. + /** + \param A Matrix of the linear system. + \param use_LU In case of non square system (least-square solution), + choose between SVD-based (\c false) or LU-based (\c true) method. + LU method is faster for large matrices, but numerically less stable. + \note Solve \c AX = B where \c B=*this. + **/ + template + CImg& solve(const CImg& A, const bool use_LU=false) { + if (_depth!=1 || _spectrum!=1 || _height!=A._height || A._depth!=1 || A._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "solve(): Instance and specified matrix (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + + if (A.size()==1) return (*this)/=A[0]; + if (A._width==2 && A._height==2 && _height==2) { // 2x2 linear system + const double a = (double)A[0], b = (double)A[1], c = (double)A[2], d = (double)A[3], + fa = std::fabs(a), fb = std::fabs(b), fc = std::fabs(c), fd = std::fabs(d), + det = a*d - b*c, fM = cimg::max(fa,fb,fc,fd); + if (fM==fa) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), y = (a*v - c*u)/det; + (*this)(k,0) = (T)((u - b*y)/a); (*this)(k,1) = (T)y; + } else if (fM==fc) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), y = (a*v - c*u)/det; + (*this)(k,0) = (T)((v - d*y)/c); (*this)(k,1) = (T)y; + } else if (fM==fb) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), x = (d*u - b*v)/det; + (*this)(k,0) = (T)x; (*this)(k,1) = (T)((u - a*x)/b); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256)) + cimg_forX(*this,k) { + const double u = (double)(*this)(k,0), v = (double)(*this)(k,1), x = (d*u - b*v)/det; + (*this)(k,0) = (T)x; (*this)(k,1) = (T)((v - c*x)/d); + } + return *this; + } + + if (A._width==A._height) { // Square linear system +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N]; + Ttfloat + *const lapA = new Ttfloat[N*N], + *const lapB = new Ttfloat[N], + *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*N + l] = (Ttfloat)(A(k,l)); + cimg_forX(*this,i) { + cimg_forY(*this,j) lapB[j] = (Ttfloat)((*this)(i,j)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getrs(TRANS,N,lapA,IPIV,lapB,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrs_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forY(*this,j) (*this)(i,j) = (T)(lapB[j]); else cimg_forY(*this,j) (*this)(i,j) = (T)0; + } + delete[] IPIV; delete[] lapA; delete[] lapB; delete[] WORK; +#else + CImg lu(A,false); + CImg indx; + bool d; + lu._LU(indx,d); + CImg res(_width,A._width); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width*_height,16)) + cimg_forX(*this,i) res.draw_image(i,get_column(i)._solve(lu,indx)); + res.move_to(*this); +#endif + } else { // Least-square solution for non-square systems + +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width; + Ttfloat WORK_QUERY; + Ttfloat + * const lapA = new Ttfloat[M*N], + * const lapB = new Ttfloat[M*NRHS]; + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, &WORK_QUERY, LWORK, INFO); + LWORK = (int) WORK_QUERY; + Ttfloat *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*M + l] = (Ttfloat)(A(k,l)); + cimg_forXY(*this,k,l) lapB[k*M + l] = (Ttfloat)((*this)(k,l)); + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, WORK, LWORK, INFO); + if (INFO != 0) + cimg::warn(_cimg_instance + "solve(): LAPACK library function sgels() returned error code %d.", + cimg_instance, + INFO); + assign(NRHS, N); + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)lapB[k*M + l]; + else (A.get_pseudoinvert(use_LU)*(*this)).move_to(*this); + delete[] lapA; delete[] lapB; delete[] WORK; +#else + (A.get_pseudoinvert(use_LU)*(*this)).move_to(*this); +#endif + } + return *this; + } + + //! Solve a system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve(const CImg& A, const bool use_LU=false) const { + typedef _cimg_Ttfloat Ttfloat; + return CImg(*this,false).solve(A,use_LU); + } + + template + CImg& _solve(const CImg& A, const CImg& indx) { + typedef _cimg_Ttfloat Ttfloat; + const int N = height(); + int ii = -1; + Ttfloat sum; + for (int i = 0; i=0) for (int j = ii; j<=i - 1; ++j) sum-=A(j,i)*(*this)(j); + else if (sum!=0) ii = i; + (*this)(i) = (T)sum; + } + for (int i = N - 1; i>=0; --i) { + sum = (*this)(i); + for (int j = i + 1; j + CImg& solve_tridiagonal(const CImg& A) { + const unsigned int siz = (unsigned int)size(); + if (A._width!=3 || A._height!=siz) + throw CImgArgumentException(_cimg_instance + "solve_tridiagonal(): Instance and tridiagonal matrix " + "(%u,%u,%u,%u,%p) have incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = 1e-4f; + CImg B = A.get_column(1), V(*this,false); + for (int i = 1; i<(int)siz; ++i) { + const Ttfloat m = A(0,i)/(B[i - 1]?B[i - 1]:epsilon); + B[i] -= m*A(2,i - 1); + V[i] -= m*V[i - 1]; + } + (*this)[siz - 1] = (T)(V[siz - 1]/(B[siz - 1]?B[siz - 1]:epsilon)); + for (int i = (int)siz - 2; i>=0; --i) (*this)[i] = (T)((V[i] - A(2,i)*(*this)[i + 1])/(B[i]?B[i]:epsilon)); + return *this; + } + + //! Solve a tridiagonal system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve_tridiagonal(const CImg& A) const { + return CImg<_cimg_Ttfloat>(*this,false).solve_tridiagonal(A); + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& eigen(CImg& val, CImg &vec) const { + if (is_empty()) { val.assign(); vec.assign(); } + else { + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + + if (val.size()<(ulongT)_width) val.assign(1,_width); + if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width); + switch (_width) { + case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break; + case 2 : { + const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d; + double f = e*e - 4*(a*d - b*c); + if (f<0) cimg::warn(_cimg_instance + "eigen(): Complex eigenvalues found.", + cimg_instance); + f = std::sqrt(f); + const double + l1 = 0.5*(e - f), + l2 = 0.5*(e + f), + b2 = b*b, + norm1 = std::sqrt(cimg::sqr(l2 - a) + b2), + norm2 = std::sqrt(cimg::sqr(l1 - a) + b2); + val[0] = (t)l2; + val[1] = (t)l1; + if (norm1>0) { vec(0,0) = (t)(b/norm1); vec(0,1) = (t)((l2 - a)/norm1); } else { vec(0,0) = 1; vec(0,1) = 0; } + if (norm2>0) { vec(1,0) = (t)(b/norm2); vec(1,1) = (t)((l1 - a)/norm2); } else { vec(1,0) = 1; vec(1,1) = 0; } + } break; + default : + throw CImgInstanceException(_cimg_instance + "eigen(): Eigenvalues computation of general matrices is limited " + "to 2x2 matrices.", + cimg_instance); + } + } + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \return A list of two images [val; vec], whose meaning is similar as in eigen(CImg&,CImg&) const. + **/ + CImgList get_eigen() const { + CImgList res(2); + eigen(res[0],res[1]); + return res; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& symmetric_eigen(CImg& val, CImg& vec) const { + if (is_empty()) { val.assign(); vec.assign(); return *this; } + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + val.assign(1,_width); + vec.assign(_width,_width); + + if (_width==1) { val[0] = cimg::abs((*this)[0]); vec[0] = 1; return *this; } + if (_width==2) { + const double + a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], + e = a + d, f = std::sqrt(std::max(e*e - 4*(a*d - b*c),0.0)), + l1 = 0.5*(e - f), l2 = 0.5*(e + f), + n = std::sqrt(cimg::sqr(l2 - a) + b*b); + val[0] = (t)l2; + val[1] = (t)l1; + if (n>0) { vec[0] = (t)(b/n); vec[2] = (t)((l2 - a)/n); } else { vec[0] = 1; vec[2] = 0; } + vec[1] = -vec[2]; + vec[3] = vec[0]; + return *this; + } + +#ifdef cimg_use_lapack + char JOB = 'V', UPLO = 'U'; + int N = _width, LWORK = 4*N, INFO; + Tfloat + *const lapA = new Tfloat[N*N], + *const lapW = new Tfloat[N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.", + cimg_instance, + INFO); + if (!INFO) { + cimg_forY(val,i) val(i) = (T)lapW[N - 1 -i]; + cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N - 1 - k)*N + l]); + } else { val.fill(0); vec.fill(0); } + delete[] lapA; delete[] lapW; delete[] WORK; + +#else + CImg V(_width,_width); + Tfloat M = 0, m = (Tfloat)min_max(M), maxabs = cimg::max((Tfloat)1,cimg::abs(m),cimg::abs(M)); + (CImg(*this,false)/=maxabs).SVD(vec,val,V,false); + if (maxabs!=1) val*=maxabs; + + bool is_ambiguous = false; + float eig = 0; + cimg_forY(val,p) { // Check for ambiguous cases + if (val[p]>eig) eig = (float)val[p]; + t scal = 0; + cimg_forY(vec,y) scal+=vec(p,y)*V(p,y); + if (cimg::abs(scal)<0.9f) is_ambiguous = true; + if (scal<0) val[p] = -val[p]; + } + if (is_ambiguous) { + ++(eig*=2); + SVD(vec,val,V,false,40,eig); + val-=eig; + } + + CImg permutations; // Sort eigenvalues in decreasing order + CImg tmp(_width); + val.sort(permutations,false); + cimg_forY(vec,k) { + cimg_forY(permutations,y) tmp(y) = vec(permutations(y),k); + std::memcpy(vec.data(0,k),tmp._data,sizeof(t)*_width); + } +#endif + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \return A list of two images [val; vec], whose meaning are similar as in + symmetric_eigen(CImg&,CImg&) const. + **/ + CImgList get_symmetric_eigen() const { + CImgList res(2); + symmetric_eigen(res[0],res[1]); + return res; + } + + //! Sort pixel values and get sorting permutations. + /** + \param[out] permutations Permutation map used for the sorting. + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + **/ + template + CImg& sort(CImg& permutations, const bool is_increasing=true) { + permutations.assign(_width,_height,_depth,_spectrum); + if (is_empty()) return *this; + cimg_foroff(permutations,off) permutations[off] = (t)off; + return _quicksort(0,size() - 1,permutations,is_increasing,true); + } + + //! Sort pixel values and get sorting permutations \newinstance. + template + CImg get_sort(CImg& permutations, const bool is_increasing=true) const { + return (+*this).sort(permutations,is_increasing); + } + + //! Sort pixel values. + /** + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + \param axis Tells if the value sorting must be done along a specific axis. Can be: + - \c 0: All pixel values are sorted, independently on their initial position. + - \c 'x': Image columns are sorted, according to the first value in each column. + - \c 'y': Image rows are sorted, according to the first value in each row. + - \c 'z': Image slices are sorted, according to the first value in each slice. + - \c 'c': Image channels are sorted, according to the first value in each channel. + **/ + CImg& sort(const bool is_increasing=true, const char axis=0) { + if (is_empty()) return *this; + CImg perm; + switch (cimg::lowercase(axis)) { + case 0 : + _quicksort(0,size() - 1,perm,is_increasing,false); + break; + case 'x' : { + perm.assign(_width); + get_crop(0,0,0,0,_width - 1,0,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(perm[x],y,z,c); + } break; + case 'y' : { + perm.assign(_height); + get_crop(0,0,0,0,0,_height - 1,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,perm[y],z,c); + } break; + case 'z' : { + perm.assign(_depth); + get_crop(0,0,0,0,0,0,_depth - 1,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,perm[z],c); + } break; + case 'c' : { + perm.assign(_spectrum); + get_crop(0,0,0,0,0,0,0,_spectrum - 1).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,z,perm[c]); + } break; + default : + throw CImgArgumentException(_cimg_instance + "sort(): Invalid specified axis '%c' " + "(should be { x | y | z | c }).", + cimg_instance,axis); + } + return *this; + } + + //! Sort pixel values \newinstance. + CImg get_sort(const bool is_increasing=true, const char axis=0) const { + return (+*this).sort(is_increasing,axis); + } + + template + CImg& _quicksort(const long indm, const long indM, CImg& permutations, + const bool is_increasing, const bool is_permutations) { + if (indm(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]>(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]>(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } else { + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]<(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } + if (indM - indm>=3) { + const T pivot = (*this)[mid]; + long i = indm, j = indM; + if (is_increasing) { + do { + while ((*this)[i]pivot) --j; + if (i<=j) { + if (is_permutations) cimg::swap(permutations[i],permutations[j]); + cimg::swap((*this)[i++],(*this)[j--]); + } + } while (i<=j); + } else { + do { + while ((*this)[i]>pivot) ++i; + while ((*this)[j] A; // Input matrix (assumed to contain some values) + CImg<> U,S,V; + A.SVD(U,S,V) + \endcode + **/ + template + const CImg& SVD(CImg& U, CImg& S, CImg& V, const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = (Ttfloat)1e-25; + + if (is_empty()) { U.assign(); S.assign(); V.assign(); } + else if (_depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "SVD(): Instance has invalid dimensions (depth or channels different from 1).", + cimg_instance); + else { + U = *this; + if (lambda!=0) { + const unsigned int delta = std::min(U._width,U._height); + for (unsigned int i = 0; i rv1(_width); + Ttfloat anorm = 0, c, f, g = 0, h, s, scale = 0; + int l = 0; + + cimg_forX(U,i) { + l = i + 1; + rv1[i] = scale*g; + g = s = scale = 0; + if (i=0?-1:1)*std::sqrt(s)); + h = f*g - s; + U(i,i) = f - g; + for (int j = l; j=0?-1:1)*std::sqrt(s)); + h = f*g - s; + U(l,i) = f - g; + for (int k = l; k=0; --i) { + if (i=0; --i) { + l = i + 1; + g = S[i]; + for (int j = l; j=0; --k) { + int nm = 0; + for (unsigned int its = 0; its=1; --l) { + nm = l - 1; + if ((cimg::abs(rv1[l]) + anorm)==anorm) { flag = false; break; } + if ((cimg::abs(S[nm]) + anorm)==anorm) break; + } + if (flag) { + c = 0; + s = 1; + for (int i = l; i<=k; ++i) { + f = s*rv1[i]; + rv1[i] = c*rv1[i]; + if ((cimg::abs(f) + anorm)==anorm) break; + g = S[i]; + h = cimg::_hypot(f,g); + S[i] = h; + h = 1/h; + c = g*h; + s = -f*h; + cimg_forY(U,j) { + const t y = U(nm,j), z = U(i,j); + U(nm,j) = y*c + z*s; + U(i,j) = z*c - y*s; + } + } + } + + const t z = S[k]; + if (l==k) { if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); } break; } + nm = k - 1; + t x = S[l], y = S[nm]; + g = rv1[nm]; + h = rv1[k]; + f = ((y - z)*(y + z) + (g - h)*(g + h))/std::max(epsilon,(Ttfloat)2*h*y); + g = cimg::_hypot(f,(Ttfloat)1); + f = ((x - z)*(x + z) + h*((y/(f + (f>=0?g:-g))) - h))/std::max(epsilon,(Ttfloat)x); + c = s = 1; + for (int j = l; j<=nm; ++j) { + const int i = j + 1; + g = rv1[i]; + h = s*g; + g = c*g; + t y1 = S[i], z1 = cimg::_hypot(f,h); + rv1[j] = z1; + c = f/std::max(epsilon,(Ttfloat)z1); + s = h/std::max(epsilon,(Ttfloat)z1); + f = x*c + g*s; + g = g*c - x*s; + h = y1*s; + y1*=c; + cimg_forX(U,jj) { + const t x2 = V(j,jj), z2 = V(i,jj); + V(j,jj) = x2*c + z2*s; + V(i,jj) = z2*c - x2*s; + } + z1 = cimg::_hypot(f,h); + S[j] = z1; + if (z1) { + z1 = 1/std::max(epsilon,(Ttfloat)z1); + c = f*z1; + s = h*z1; + } + f = c*g + s*y1; + x = c*y1 - s*g; + cimg_forY(U,jj) { + const t y2 = U(j,jj), z2 = U(i,jj); + U(j,jj) = y2*c + z2*s; + U(i,jj) = z2*c - y2*s; + } + } + rv1[l] = 0; + rv1[k] = f; + S[k] = x; + } + } + + if (sorting) { + CImg permutations; + CImg tmp(_width); + S.sort(permutations,false); + cimg_forY(U,k) { + cimg_forY(permutations,y) tmp(y) = U(permutations(y),k); + std::memcpy(U.data(0,k),tmp._data,sizeof(t)*_width); + } + cimg_forY(V,k) { + cimg_forY(permutations,y) tmp(y) = V(permutations(y),k); + std::memcpy(V.data(0,k),tmp._data,sizeof(t)*_width); + } + } + } + return *this; + } + + //! Compute the SVD of the instance image, viewed as a general matrix. + /** + \return A list of three images [U; S; V], whose meaning is similar as in + SVD(CImg&,CImg&,CImg&,bool,unsigned int,float) const. + **/ + CImgList get_SVD(const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + CImgList res(3); + SVD(res[0],res[1],res[2],sorting,max_iteration,lambda); + return res; + } + + // [internal] Compute the LU decomposition of a permuted matrix. + template + CImg& _LU(CImg& indx, bool& d) { + const int N = width(); + int imax = 0; + CImg vv(N); + indx.assign(N); + d = true; + + bool return0 = false; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=512)) + cimg_forX(*this,i) { + Tfloat vmax = 0; + cimg_forX(*this,j) { + const Tfloat tmp = cimg::abs((*this)(j,i)); + if (tmp>vmax) vmax = tmp; + } + if (vmax==0) return0 = true; else vv[i] = 1/vmax; + } + if (return0) { indx.fill(0); return fill(0); } + + cimg_forX(*this,j) { + for (int i = 0; i=vmax) { vmax = tmp; imax = i; } + } + if (j!=imax) { + cimg_forX(*this,k) cimg::swap((*this)(k,imax),(*this)(k,j)); + d = !d; + vv[imax] = vv[j]; + } + indx[j] = (t)imax; + if ((*this)(j,j)==0) (*this)(j,j) = (T)1e-20; + if (j=3 = orthogonal matching pursuit where an orthogonal projection step is performed + every 'method-2' iterations. + \param max_iter Sets the max number of iterations processed for each signal. + If set to '0' (default), 'max_iter' is set to the number of dictionary columns. + (only meaningful for matching pursuit and its variants). + \param max_residual Gives a stopping criterion on signal reconstruction accuracy. + (only meaningful for matching pursuit and its variants). + \return A matrix W whose columns correspond to the sparse weights of associated to each input matrix column. + Thus, the matrix product D*W is an approximation of the input matrix. + **/ + template + CImg& project_matrix(const CImg& dictionary, const unsigned int method=0, + const unsigned int max_iter=0, const double max_residual=1e-6) { + return get_project_matrix(dictionary,method,max_iter,max_residual).move_to(*this); + } + + template + CImg get_project_matrix(const CImg& dictionary, const unsigned int method=0, + const unsigned int max_iter=0, const double max_residual=1e-6) const { + if (_depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "project_matrix(): Instance image is not a matrix.", + cimg_instance); + if (dictionary._height!=_height || dictionary._depth!=1 || dictionary._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "project_matrix(): Specified dictionary (%u,%u,%u,%u) has an invalid size.", + cimg_instance, + dictionary._width,dictionary._height,dictionary._depth,dictionary._spectrum); + + if (!method) return get_solve(dictionary,true); + CImg W(_width,dictionary._width,1,1,0); + + // Compute dictionary norm and normalize it. + CImg D(dictionary,false), Dnorm(D._width); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=2 && _width*_height>=32)) + cimg_forX(Dnorm,d) { + Tfloat norm = 0; + cimg_forY(D,y) norm+=cimg::sqr(D(d,y)); + Dnorm[d] = std::max((Tfloat)1e-8,std::sqrt(norm)); + } + cimg_forXY(D,d,y) D(d,y)/=Dnorm[d]; + + // Matching pursuit. + const unsigned int proj_step = method<3?1:method - 2; + bool is_orthoproj = false; + + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=2 && _width*_height>=32)) + cimg_forX(*this,x) { + CImg S = get_column(x); + const CImg S0 = method<2?CImg():S; + Tfloat residual = S.magnitude()/S._height; + const unsigned int nmax = max_iter?max_iter:D._width; + + for (unsigned int n = 0; nmax_residual; ++n) { + + // Find best matching column in D. + int dmax = 0; + Tfloat absdotmax = 0, dotmax = 0; + cimg_pragma_openmp(parallel for cimg_openmp_if(D._width>=2 && D._width*D._height>=32)) + cimg_forX(D,d) { + Tfloat _dot = 0; + cimg_forY(D,y) _dot+=S[y]*D(d,y); + Tfloat absdot = cimg::abs(_dot); + cimg_pragma_openmp(critical(get_project_matrix)) { + if (absdot>absdotmax) { + absdotmax = absdot; + dotmax = _dot; + dmax = d; + } + } + } + + if (!n || method<3 || n%proj_step) { + // Matching Pursuit: Subtract component to signal. + W(x,dmax)+=dotmax; + residual = 0; + cimg_forY(S,y) { + S[y]-=dotmax*D(dmax,y); + residual+=cimg::sqr(S[y]); + } + residual = std::sqrt(residual)/S._height; + is_orthoproj = false; + + } else { + // Orthogonal Matching Pursuit: Orthogonal projection step. + W(x,dmax) = 1; // Used as a marker only. + unsigned int nbW = 0; + cimg_forY(W,d) if (W(x,d)) ++nbW; + CImg sD(nbW,D._height); + CImg inds(nbW); + int sd = 0; + cimg_forY(W,d) if (W(x,d)) { + cimg_forY(sD,y) sD(sd,y) = D(d,y); + inds[sd++] = d; + } + S0.get_solve(sD,true).move_to(sD); // sD is now a one-column vector of weights + + // Recompute residual signal. + S = S0; + cimg_forY(sD,k) { + const Tfloat weight = sD[k]; + const unsigned int ind = inds[k]; + W(x,ind) = weight; + cimg_forY(S,y) S[y]-=weight*D(ind,y); + } + residual = S.magnitude()/S._height; + is_orthoproj = true; + } + } + + // Perform last orthoprojection step if needed. + if (method>=2 && !is_orthoproj) { + unsigned int nbW = 0; + cimg_forY(W,d) if (W(x,d)) ++nbW; + if (nbW) { // Avoid degenerated case where 0 coefs are used + CImg sD(nbW,D._height); + CImg inds(nbW); + int sd = 0; + cimg_forY(W,d) if (W(x,d)) { + cimg_forY(sD,y) sD(sd,y) = D(d,y); + inds[sd++] = d; + } + S0.get_solve(sD,true).move_to(sD); + cimg_forY(sD,k) W(x,inds[k]) = sD[k]; + } + } + } + + // Normalize resulting coefficients according to initial (non-normalized) dictionary. + cimg_forXY(W,x,y) W(x,y)/=Dnorm[y]; + return W; + } + + //! Compute minimal path in a graph, using the Dijkstra algorithm. + /** + \param distance An object having operator()(unsigned int i, unsigned int j) which returns distance + between two nodes (i,j). + \param nb_nodes Number of graph nodes. + \param starting_node Index of the starting node. + \param ending_node Index of the ending node (set to ~0U to ignore ending node). + \param previous_node Array that gives the previous node index in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + **/ + template + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + if (starting_node>=nb_nodes) + throw CImgArgumentException("CImg<%s>::dijkstra(): Specified index of starting node %u is higher " + "than number of nodes %u.", + pixel_type(),starting_node,nb_nodes); + CImg dist(1,nb_nodes,1,1,cimg::type::max()); + dist(starting_node) = 0; + previous_node.assign(1,nb_nodes,1,1,(t)-1); + previous_node(starting_node) = (t)starting_node; + CImg Q(nb_nodes); + cimg_forX(Q,u) Q(u) = (unsigned int)u; + cimg::swap(Q(starting_node),Q(0)); + unsigned int sizeQ = nb_nodes; + while (sizeQ) { + // Update neighbors from minimal vertex + const unsigned int umin = Q(0); + if (umin==ending_node) sizeQ = 0; + else { + const T dmin = dist(umin); + const T infty = cimg::type::max(); + for (unsigned int q = 1; qdist(Q(left))) || + (rightdist(Q(right)));) { + if (right + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node=~0U) { + CImg foo; + return dijkstra(distance,nb_nodes,starting_node,ending_node,foo); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + /** + \param starting_node Index of the starting node. + \param ending_node Index of the ending node. + \param previous_node Array that gives the previous node index in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + \note image instance corresponds to the adjacency matrix of the graph. + **/ + template + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + return get_dijkstra(starting_node,ending_node,previous_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + template + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) const { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "dijkstra(): Instance is not a graph adjacency matrix.", + cimg_instance); + + return dijkstra(*this,_width,starting_node,ending_node,previous_node); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) { + return get_dijkstra(starting_node,ending_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) const { + CImg foo; + return get_dijkstra(starting_node,ending_node,foo); + } + + //! Return an image containing the character codes of specified string. + /** + \param str input C-string to encode as an image. + \param is_last_zero Tells if the ending \c '0' character appear in the resulting image. + \param is_shared Return result that shares its buffer with \p str. + **/ + static CImg string(const char *const str, const bool is_last_zero=true, const bool is_shared=false) { + if (!str) return CImg(); + return CImg(str,(unsigned int)std::strlen(str) + (is_last_zero?1:0),1,1,1,is_shared); + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg row_vector(const T& a0) { + return vector(a0); + } + + //! Return a \c 2x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg row_vector(const T& a0, const T& a1) { + CImg r(2,1); + r[0] = a0; r[1] = a1; + return r; + } + + //! Return a \c 3x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg row_vector(const T& a0, const T& a1, const T& a2) { + CImg r(3,1); + r[0] = a0; r[1] = a1; r[2] = a2; + return r; + } + + //! Return a \c 4x1 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(4,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; + return r; + } + + //! Return a \c 5x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(5,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; + return r; + } + + //! Return a \c 6x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(6,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; + return r; + } + + //! Return a \c 7x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(7,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; + return r; + } + + //! Return a \c 8x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(8,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; + return r; + } + + //! Return a \c 9x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(9,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; + return r; + } + + //! Return a \c 10x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(10,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + return r; + } + + //! Return a \c 11x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(11,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; + return r; + } + + //! Return a \c 12x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(12,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; + return r; + } + + //! Return a \c 13x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(13,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; + return r; + } + + //! Return a \c 14x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(14,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; + return r; + } + + //! Return a \c 15x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(15,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; + return r; + } + + //! Return a \c 16x1 image containing specified values. + static CImg row_vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(16,1); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; r[15] = a15; + return r; + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg vector(const T& a0) { + CImg r(1,1); + r[0] = a0; + return r; + } + + //! Return a \c 1x2 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg vector(const T& a0, const T& a1) { + CImg r(1,2); + r[0] = a0; r[1] = a1; + return r; + } + + //! Return a \c 1x3 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2) { + CImg r(1,3); + r[0] = a0; r[1] = a1; r[2] = a2; + return r; + } + + //! Return a \c 1x4 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(1,4); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; + return r; + } + + //! Return a \c 1x5 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(1,5); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; + return r; + } + + //! Return a \c 1x6 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(1,6); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; + return r; + } + + //! Return a \c 1x7 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(1,7); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; + return r; + } + + //! Return a \c 1x8 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(1,8); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; + return r; + } + + //! Return a \c 1x9 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(1,9); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; + return r; + } + + //! Return a \c 1x10 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(1,10); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + return r; + } + + //! Return a \c 1x11 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(1,11); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; + return r; + } + + //! Return a \c 1x12 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(1,12); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; + return r; + } + + //! Return a \c 1x13 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(1,13); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; + return r; + } + + //! Return a \c 1x14 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(1,14); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; + return r; + } + + //! Return a \c 1x15 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(1,15); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; + return r; + } + + //! Return a \c 1x16 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(1,16); + r[0] = a0; r[1] = a1; r[2] = a2; r[3] = a3; r[4] = a4; r[5] = a5; r[6] = a6; r[7] = a7; r[8] = a8; r[9] = a9; + r[10] = a10; r[11] = a11; r[12] = a12; r[13] = a13; r[14] = a14; r[15] = a15; + return r; + } + + //! Return a 1x1 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg matrix(const T& a0) { + return vector(a0); + } + + //! Return a 2x2 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, + const T& a2, const T& a3) { + CImg r(2,2); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; + *(ptr++) = a2; *(ptr++) = a3; + return r; + } + + //! Return a 3x3 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + \param a4 Fifth matrix value. + \param a5 Sixth matrix value. + \param a6 Seventh matrix value. + \param a7 Eighth matrix value. + \param a8 Ninth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, const T& a2, + const T& a3, const T& a4, const T& a5, + const T& a6, const T& a7, const T& a8) { + CImg r(3,3); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; + *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; + *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; + return r; + } + + //! Return a 4x4 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(4,4); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; + return r; + } + + //! Return a 5x5 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, + const T& a5, const T& a6, const T& a7, const T& a8, const T& a9, + const T& a10, const T& a11, const T& a12, const T& a13, const T& a14, + const T& a15, const T& a16, const T& a17, const T& a18, const T& a19, + const T& a20, const T& a21, const T& a22, const T& a23, const T& a24) { + CImg r(5,5); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; + *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; *(ptr++) = a9; + *(ptr++) = a10; *(ptr++) = a11; *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; + *(ptr++) = a15; *(ptr++) = a16; *(ptr++) = a17; *(ptr++) = a18; *(ptr++) = a19; + *(ptr++) = a20; *(ptr++) = a21; *(ptr++) = a22; *(ptr++) = a23; *(ptr++) = a24; + return r; + } + + //! Return a 1x1 symmetric matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg tensor(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 symmetric matrix tensor containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2) { + return matrix(a0,a1,a1,a2); + } + + //! Return a 3x3 symmetric matrix containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + return matrix(a0,a1,a2,a1,a3,a4,a2,a4,a5); + } + + //! Return a 1x1 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1) { + return matrix(a0,0,0,a1); + } + + //! Return a 3x3 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2) { + return matrix(a0,0,0,0,a1,0,0,0,a2); + } + + //! Return a 4x4 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3) { + return matrix(a0,0,0,0,0,a1,0,0,0,0,a2,0,0,0,0,a3); + } + + //! Return a 5x5 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + return matrix(a0,0,0,0,0,0,a1,0,0,0,0,0,a2,0,0,0,0,0,a3,0,0,0,0,0,a4); + } + + //! Return a NxN identity matrix. + /** + \param N Dimension of the matrix. + **/ + static CImg identity_matrix(const unsigned int N) { + CImg res(N,N,1,1,0); + cimg_forX(res,x) res(x,x) = 1; + return res; + } + + //! Return a N-numbered sequence vector from \p a0 to \p a1. + /** + \param N Size of the resulting vector. + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + static CImg sequence(const unsigned int N, const T& a0, const T& a1) { + if (N) return CImg(1,N).sequence(a0,a1); + return CImg(); + } + + //! Return a 3x3 rotation matrix from an { axis + angle } or a quaternion. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or third quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + static CImg rotation_matrix(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + double X, Y, Z, W, N; + if (is_quaternion) { + N = std::sqrt((double)x*x + (double)y*y + (double)z*z + (double)w*w); + if (N>0) { X = x/N; Y = y/N; Z = z/N; W = w/N; } + else { X = Y = Z = 0; W = 1; } + return CImg::matrix((T)(X*X + Y*Y - Z*Z - W*W),(T)(2*Y*Z - 2*X*W),(T)(2*X*Z + 2*Y*W), + (T)(2*X*W + 2*Y*Z),(T)(X*X - Y*Y + Z*Z - W*W),(T)(2*Z*W - 2*X*Y), + (T)(2*Y*W - 2*X*Z),(T)(2*X*Y + 2*Z*W),(T)(X*X - Y*Y - Z*Z + W*W)); + } + N = cimg::hypot((double)x,(double)y,(double)z); + if (N>0) { X = x/N; Y = y/N; Z = z/N; } + else { X = Y = 0; Z = 1; } + const double ang = w*cimg::PI/180, c = std::cos(ang), omc = 1 - c, s = std::sin(ang); + return CImg::matrix((T)(X*X*omc + c),(T)(X*Y*omc - Z*s),(T)(X*Z*omc + Y*s), + (T)(X*Y*omc + Z*s),(T)(Y*Y*omc + c),(T)(Y*Z*omc - X*s), + (T)(X*Z*omc - Y*s),(T)(Y*Z*omc + X*s),(T)(Z*Z*omc + c)); + } + + //@} + //----------------------------------- + // + //! \name Value Manipulation + //@{ + //----------------------------------- + + //! Fill all pixel values with specified value. + /** + \param val Fill value. + **/ + CImg& fill(const T& val) { + if (is_empty()) return *this; + if (val && sizeof(T)!=1) cimg_for(*this,ptrd,T) *ptrd = val; + else std::memset(_data,(int)(ulongT)val,sizeof(T)*size()); // Double cast to allow val to be (void*) + return *this; + } + + //! Fill all pixel values with specified value \newinstance. + CImg get_fill(const T& val) const { + return CImg(_width,_height,_depth,_spectrum).fill(val); + } + + //! Fill sequentially all pixel values with specified values. + /** + \param val0 First fill value. + \param val1 Second fill value. + **/ + CImg& fill(const T& val0, const T& val1) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 1; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 2; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 3; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 4; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 5; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 6; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 7; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 8; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 9; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 10; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 11; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 12; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 13; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 14; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 15; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14,val15); + } + + //! Fill sequentially pixel values according to a given expression. + /** + \param expression C-string describing a math formula, or a sequence of values. + \param repeat_values In case a list of values is provided, tells if this list must be repeated for the filling. + \param allow_formula Tells that mathematical formulas are authorized for the filling. + \param list_inputs In case of a mathematical expression, attach a list of images to the specified expression. + \param[out] list_outputs In case of a math expression, list of images atatched to the specified expression. + **/ + CImg& fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _fill(expression,repeat_values,allow_formula?1:0,list_inputs,list_outputs,"fill",0); + } + + // 'formula_mode' = { 0 = does not allow formula | 1 = allow formula | + // 2 = allow formula and do not fill image values }. + CImg& _fill(const char *const expression, const bool repeat_values, const unsigned int formula_mode, + const CImgList *const list_inputs, CImgList *const list_outputs, + const char *const calling_function, const CImg *provides_copy) { + if (is_empty() || !expression || !*expression) return *this; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + CImg is_error; + bool is_value_sequence = false; + cimg_abort_init; + + if (formula_mode) { + + // Try to pre-detect regular value sequence to avoid exception thrown by _cimg_math_parser. + double value; + char sep; + const int err = cimg_sscanf(expression,"%lf %c",&value,&sep); + if (err==1 || (err==2 && sep==',')) { + if (err==1) { if (formula_mode==2) return *this; return fill((T)value); } + else is_value_sequence = true; + } + + // Try to fill values according to a formula. + _cimg_abort_init_openmp; + if (!is_value_sequence) try { + CImg base = provides_copy?provides_copy->get_shared():get_shared(); + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'), + calling_function,base,this,list_inputs,list_outputs,true); + if (!provides_copy && expression && *expression!='>' && *expression!='<' && *expression!=':' && + mp.need_input_copy) + base.assign().assign(*this,false); // Needs input copy + + // Determine 2nd largest image dimension (used as axis for inner loop in parallelized evaluation). + unsigned int M; + if (mp.result_dim) { + M = cimg::max(_width,_height,_depth); + M = M==_width?std::max(_height,_depth):M==_height?std::max(_width,_depth):std::max(_width,_height); + } else { + M = cimg::max(_width,_height,_depth,_spectrum); + M = M==_width?cimg::max(_height,_depth,_spectrum): + M==_height?cimg::max(_width,_depth,_spectrum): + M==_depth?cimg::max(_width,_height,_spectrum):cimg::max(_width,_height,_depth); + } + + bool do_in_parallel = false; +#if cimg_use_openmp!=0 + cimg_openmp_if(*expression=='*' || *expression==':' || + (mp.is_parallelizable && M>=(cimg_openmp_sizefactor)*320 && size()/M>=2)) + do_in_parallel = true; +#endif + if (mp.result_dim) { // Vector-valued expression + const unsigned int N = std::min(mp.result_dim,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = *expression=='<'?_data + _width*_height*_depth - 1:_data; + if (*expression=='<') { + CImg res(1,mp.result_dim); + mp.begin_t(); + cimg_rofYZ(*this,y,z) { + cimg_abort_test; + if (formula_mode==2) cimg_rofX(*this,x) mp(x,y,z,0); + else cimg_rofX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd--; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + mp.end_t(); + + } else if (*expression=='>' || !do_in_parallel) { + CImg res(1,mp.result_dim); + mp.begin_t(); + cimg_forYZ(*this,y,z) { + cimg_abort_test; + if (formula_mode==2) cimg_forX(*this,x) mp(x,y,z,0); + else cimg_forX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + mp.end_t(); + + } else { + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_fill)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + lmp.is_fill = true; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + +#define _cimg_fill_openmp_vector(_YZ,_y,_z,_X,_x,_sx,_sy,_sz,_off) \ + cimg_pragma_openmp(for cimg_openmp_collapse(2)) \ + cimg_for##_YZ(*this,_y,_z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + if (formula_mode==2) cimg_for##_X(*this,_x) lmp(x,y,z,0); \ + else { \ + CImg res(1,lmp.result_dim); \ + T *__ptrd = data(_sx,_sy,_sz,0); \ + const ulongT off = (ulongT)_off; \ + cimg_for##_X(*this,_x) { \ + lmp(x,y,z,0,res._data); \ + const double *ptrs = res._data; \ + T *_ptrd = __ptrd; \ + for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } \ + __ptrd+=off; \ + } \ + } \ + } _cimg_abort_catch_openmp _cimg_abort_catch_fill_openmp + + if (M==_width) { _cimg_fill_openmp_vector(YZ,y,z,X,x,0,y,z,1) } + else if (M==_height) { _cimg_fill_openmp_vector(XZ,x,z,Y,y,x,0,z,_width) } + else { _cimg_fill_openmp_vector(XY,x,y,Z,z,x,y,0,_width*_height) } + + lmp.end_t(); + cimg_pragma_openmp(barrier) cimg_pragma_openmp(critical) { lmp.merge(mp); } + if (&lmp!=&mp) delete &lmp; + } +#endif + } + + } else { // Scalar-valued expression + T *ptrd = *expression=='<'?end() - 1:_data; + if (*expression=='<') { + mp.begin_t(); + if (formula_mode==2) cimg_rofYZC(*this,y,z,c) { cimg_abort_test; cimg_rofX(*this,x) mp(x,y,z,c); } + else cimg_rofYZC(*this,y,z,c) { cimg_abort_test; cimg_rofX(*this,x) *(ptrd--) = (T)mp(x,y,z,c); } + mp.end_t(); + + } else if (*expression=='>' || !do_in_parallel) { + mp.begin_t(); + if (formula_mode==2) cimg_forYZC(*this,y,z,c) { cimg_abort_test; cimg_forX(*this,x) mp(x,y,z,c); } + else cimg_forYZC(*this,y,z,c) { cimg_abort_test; cimg_forX(*this,x) *(ptrd++) = (T)mp(x,y,z,c); } + mp.end_t(); + + } else { + +#if cimg_use_openmp!=0 + unsigned int tid = 0; + cimg_pragma_openmp(parallel) + { + _cimg_math_parser *_mp = 0; + cimg_pragma_openmp(critical(_fill)) { _mp = !tid?&mp:new _cimg_math_parser(mp); ++tid; } + _cimg_math_parser &lmp = *_mp; + lmp.is_fill = true; + cimg_pragma_openmp(barrier) + lmp.begin_t(); + +#define _cimg_fill_openmp_scalar(_YZC,_y,_z,_c,_X,_x,_sx,_sy,_sz,_sc,_off) \ + cimg_pragma_openmp(for cimg_openmp_collapse(3)) \ + cimg_for##_YZC(*this,_y,_z,_c) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + if (formula_mode==2) cimg_for##_X(*this,_x) lmp(x,y,z,c); \ + else { \ + T *_ptrd = data(_sx,_sy,_sz,_sc); \ + const ulongT off = (ulongT)_off; \ + cimg_for##_X(*this,_x) { *_ptrd = (T)lmp(x,y,z,c); _ptrd+=off; } \ + } \ + } _cimg_abort_catch_openmp _cimg_abort_catch_fill_openmp + + if (M==_width) { _cimg_fill_openmp_scalar(YZC,y,z,c,X,x,0,y,z,c,1) } + else if (M==_height) { _cimg_fill_openmp_scalar(XZC,x,z,c,Y,y,x,0,z,c,_width) } + else if (M==_depth) { _cimg_fill_openmp_scalar(XYC,x,y,c,Z,z,x,y,0,c,_width*_height) } + else { _cimg_fill_openmp_scalar(XYZ,x,y,z,C,c,x,y,z,0,_width*_height*_depth) } + + lmp.end_t(); + cimg_pragma_openmp(barrier) cimg_pragma_openmp(critical) { lmp.merge(mp); } + if (&lmp!=&mp) delete &lmp; + } +#endif + } + } + mp.end(); + } catch (CImgException& e) { CImg::string(e._message).move_to(is_error); } + } + + // Try to fill values according to a value sequence. + if (!formula_mode || is_value_sequence || is_error) { + CImg item(256); + char sep = 0; + const char *nexpression = expression; + ulongT nb = 0; + const ulongT siz = size(); + T *ptrd = _data; + for (double val = 0; *nexpression && nb0 && cimg_sscanf(item,"%lf",&val)==1 && (sep==',' || sep==';' || err==1)) { + nexpression+=std::strlen(item) + (err>1); + *(ptrd++) = (T)val; + } else break; + } + cimg::exception_mode(omode); + if (nb get_fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return (+*this).fill(expression,repeat_values,allow_formula?1:0,list_inputs,list_outputs); + } + + //! Fill sequentially pixel values according to the values found in another image. + /** + \param values Image containing the values used for the filling. + \param repeat_values In case there are less values than necessary in \c values, tells if these values must be + repeated for the filling. + **/ + template + CImg& fill(const CImg& values, const bool repeat_values=true) { + if (is_empty() || !values) return *this; + T *ptrd = _data, *ptre = ptrd + size(); + for (t *ptrs = values._data, *ptrs_end = ptrs + values.size(); ptrs + CImg get_fill(const CImg& values, const bool repeat_values=true) const { + return repeat_values?CImg(_width,_height,_depth,_spectrum).fill(values,repeat_values): + (+*this).fill(values,repeat_values); + } + + //! Fill pixel values along the X-axis at a specified pixel position. + /** + \param y Y-coordinate of the filled column. + \param z Z-coordinate of the filled column. + \param c C-coordinate of the filled column. + \param a0 First fill value. + **/ + CImg& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const int a0, ...) { +#define _cimg_fill1(x,y,z,c,off,siz,t) { \ + va_list ap; va_start(ap,a0); T *ptrd = data(x,y,z,c); *ptrd = (T)a0; \ + for (unsigned int k = 1; k& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const double a0, ...) { + if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,double); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position. + /** + \param x X-coordinate of the filled row. + \param z Z-coordinate of the filled row. + \param c C-coordinate of the filled row. + \param a0 First fill value. + **/ + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const int a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,int); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position \overloading. + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const double a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,double); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position. + /** + \param x X-coordinate of the filled slice. + \param y Y-coordinate of the filled slice. + \param c C-coordinate of the filled slice. + \param a0 First fill value. + **/ + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,int); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position \overloading. + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const double a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,double); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position. + /** + \param x X-coordinate of the filled channel. + \param y Y-coordinate of the filled channel. + \param z Z-coordinate of the filled channel. + \param a0 First filling value. + **/ + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const int a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,int); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position \overloading. + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const double a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,double); + return *this; + } + + //! Discard specified sequence of values in the image buffer, along a specific axis. + /** + \param values Sequence of values to discard. + \param axis Axis along which the values are discarded. If set to \c 0 (default value) + the method does it for all the buffer values and returns a one-column vector. + \note Discarded values will change the image geometry, so the resulting image + is returned as a one-column vector. + **/ + template + CImg& discard(const CImg& values, const char axis=0) { + if (is_empty() || !values) return *this; + return get_discard(values,axis).move_to(*this); + } + + template + CImg get_discard(const CImg& values, const char axis=0) const { + if (!values) return +*this; + CImg res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + ulongT j = 0; + unsigned int k = 0; + int i0 = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) { + if ((*this)(i)!=(T)values[j]) { + if (j) --i; + res.draw_image(k,get_columns(i0,i)); + k+=i - i0 + 1; i0 = i + 1; j = 0; + } else { ++j; if (j>=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = (int)i + 1; }} + } + if ((ulongT)i0& discard(const char axis=0) { + return get_discard(axis).move_to(*this); + } + + //! Discard neighboring duplicates in the image buffer, along the specified axis \newinstance. + CImg get_discard(const char axis=0) const { + CImg res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + T current = *_data?(T)0:(T)1; + int j = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) + if ((*this)(i)!=current) { res.draw_image(j++,get_column(i)); current = (*this)(i); } + res.resize(j,-100,-100,-100,0); + } break; + case 'y' : { + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { res.draw_image(0,j++,get_row(i)); current = (*this)(0,i); } + res.resize(-100,j,-100,-100,0); + } break; + case 'z' : { + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { res.draw_image(0,0,j++,get_slice(i)); current = (*this)(0,0,i); } + res.resize(-100,-100,j,-100,0); + } break; + case 'c' : { + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { res.draw_image(0,0,0,j++,get_channel(i)); current = (*this)(0,0,0,i); } + res.resize(-100,-100,-100,j,0); + } break; + default : { + res.unroll('y'); + cimg_foroff(*this,i) { + const T val = (*this)[i]; + if (val!=current) res[j++] = current = val; + } + res.resize(-100,j,-100,-100,0); + } + } + return res; + } + + //! Invert endianness of all pixel values. + /** + **/ + CImg& invert_endianness() { + cimg::invert_endianness(_data,size()); + return *this; + } + + //! Invert endianness of all pixel values \newinstance. + CImg get_invert_endianness() const { + return (+*this).invert_endianness(); + } + + //! Fill image with random values in specified range. + /** + \param val_min Minimal authorized random value. + \param val_max Maximal authorized random value. + \note Random variables are uniformly distributed in [val_min,val_max]. + **/ + CImg& rand(const T& val_min, const T& val_max) { + const float delta = (float)val_max - (float)val_min + (cimg::type::is_float()?0:1); + if (cimg::type::is_float()) cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),524288)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) _data[off] = (T)(val_min + delta*cimg::rand(1,&rng)); + cimg::srand(rng); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),524288)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) _data[off] = std::min(val_max,(T)(val_min + delta*cimg::rand(1,&rng))); + cimg::srand(rng); + } + return *this; + } + + //! Fill image with random values in specified range \newinstance. + CImg get_rand(const T& val_min, const T& val_max) const { + return (+*this).rand(val_min,val_max); + } + + //! Round pixel values. + /** + \param y Rounding precision. + \param rounding_type Rounding type. Can be: + - \c -1: Backward. + - \c 0: Nearest. + - \c 1: Forward. + **/ + CImg& round(const double y=1, const int rounding_type=0) { + if (y>0) cimg_openmp_for(*this,cimg::round(*ptr,y,rounding_type),8192); + return *this; + } + + //! Round pixel values \newinstance. + CImg get_round(const double y=1, const unsigned int rounding_type=0) const { + return (+*this).round(y,rounding_type); + } + + //! Add random noise to pixel values. + /** + \param sigma Amplitude of the random additive noise. If \p sigma<0, it stands for a percentage of the + global value range. + \param noise_type Type of additive noise (can be \p 0=gaussian, \p 1=uniform, \p 2=Salt and Pepper, + \p 3=Poisson or \p 4=Rician). + \return A reference to the modified image instance. + \note + - For Poisson noise (\p noise_type=3), parameter \p sigma is ignored, as Poisson noise only depends on + the image value itself. + - Function \p CImg::get_noise() is also defined. It returns a non-shared modified copy of the image instance. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_noise(40); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_noise.jpg + **/ + CImg& noise(const double sigma, const unsigned int noise_type=0) { + if (is_empty()) return *this; + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + Tfloat nsigma = (Tfloat)sigma, m = 0, M = 0; + if (nsigma==0 && noise_type!=3) return *this; + if (nsigma<0 || noise_type==2) m = (Tfloat)min_max(M); + if (nsigma<0) nsigma = (Tfloat)(-nsigma*(M-m)/100.); + switch (noise_type) { + case 0 : { // Gaussian noise + cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) { + Tfloat val = (Tfloat)(_data[off] + nsigma*cimg::grand(&rng)); + if (val>vmax) val = vmax; + if (valvmax) val = vmax; + if (val::is_float()) { --m; ++M; } + else { m = (Tfloat)cimg::type::min(); M = (Tfloat)cimg::type::max(); } + } + cimg_pragma_openmp(parallel cimg_openmp_if_size(size(),131072)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) if (cimg::rand(100,&rng)vmax) val = vmax; + if (val get_noise(const double sigma, const unsigned int noise_type=0) const { + return (+*this).noise(sigma,noise_type); + } + + //! Linearly normalize pixel values. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \param constant_case_ratio In case of instance image having a constant value, tell what ratio + of [min_value,max_value] is used to fill the normalized image + (=0 for min_value, =1 for max_value, =0.5 for (min_value + max_value)/2). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(160,220); + (img,res).display(); + \endcode + \image html ref_normalize2.jpg + **/ + CImg& normalize(const T& min_value, const T& max_value, + const float constant_case_ratio=0) { + if (is_empty()) return *this; + const T a = min_value get_normalize(const T& min_value, const T& max_value, + const float ratio_if_constant_image=0) const { + return CImg(*this,false).normalize((Tfloat)min_value,(Tfloat)max_value,ratio_if_constant_image); + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm. + /** + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_normalize.jpg + **/ + CImg& normalize() { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + T *ptrd = data(0,y,z,0); + cimg_forX(*this,x) { + const T *ptrs = ptrd; + float n = 0; + cimg_forC(*this,c) { n+=cimg::sqr((float)*ptrs); ptrs+=whd; } + n = (float)std::sqrt(n); + T *_ptrd = ptrd++; + if (n>0) cimg_forC(*this,c) { *_ptrd = (T)(*_ptrd/n); _ptrd+=whd; } + else cimg_forC(*this,c) { *_ptrd = (T)0; _ptrd+=whd; } + } + } + return *this; + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm \newinstance. + CImg get_normalize() const { + return CImg(*this,false).normalize(); + } + + //! Compute Lp-norm of each multi-valued pixel of the image instance. + /** + \param norm_type Type of computed vector norm (can be \p -1=Linf, or \p greater or equal than 0). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_norm(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_norm.jpg + **/ + CImg& norm(const int norm_type=2) { + if (_spectrum==1 && norm_type) return abs(); + return get_norm(norm_type).move_to(*this); + } + + //! Compute L2-norm of each multi-valued pixel of the image instance \newinstance. + CImg get_norm(const int norm_type=2) const { + if (is_empty()) return *this; + if (_spectrum==1 && norm_type) return get_abs(); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(_width,_height,_depth); + switch (norm_type) { + case -1 : { // Linf-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { const Tfloat val = (Tfloat)cimg::abs(*_ptrs); if (val>n) n = val; _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 0 : { // L0-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + unsigned int n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=*_ptrs==0?0:1; _ptrs+=whd; } + *(ptrd++) = (Tfloat)n; + } + } + } break; + case 1 : { // L1-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::abs(*_ptrs); _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 2 : { // L2-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::sqr((Tfloat)*_ptrs); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::sqrt((Tfloat)n); + } + } + } break; + default : { // Linf-norm + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=std::pow(cimg::abs((Tfloat)*_ptrs),(Tfloat)norm_type); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::pow((Tfloat)n,1/(Tfloat)norm_type); + } + } + } + } + return res; + } + + //! Cut pixel values in specified range. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_cut(160,220); + (img,res).display(); + \endcode + \image html ref_cut.jpg + **/ + CImg& cut(const T& min_value, const T& max_value) { + if (is_empty()) return *this; + const T a = min_value get_cut(const T& min_value, const T& max_value) const { + return (+*this).cut(min_value,max_value); + } + + //! Uniformly quantize pixel values. + /** + \param nb_levels Number of quantization levels. + \param keep_range Tells if resulting values keep the same range as the original ones. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_quantize(4); + (img,res).display(); + \endcode + \image html ref_quantize.jpg + **/ + CImg& quantize(const unsigned int nb_levels, const bool keep_range=true) { + if (!nb_levels) + throw CImgArgumentException(_cimg_instance + "quantize(): Invalid quantization request with 0 values.", + cimg_instance); + + if (is_empty()) return *this; + Tfloat m, M = (Tfloat)max_min(m), range = M - m; + if (range>0) { + if (keep_range) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range); + _data[off] = (T)(m + std::min(val,nb_levels - 1)*range/nb_levels); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const unsigned int val = (unsigned int)((_data[off] - m)*nb_levels/range); + _data[off] = (T)std::min(val,nb_levels - 1); + } + } + return *this; + } + + //! Uniformly quantize pixel values \newinstance. + CImg get_quantize(const unsigned int n, const bool keep_range=true) const { + return (+*this).quantize(n,keep_range); + } + + //! Threshold pixel values. + /** + \param value Threshold value + \param soft_threshold Tells if soft thresholding must be applied (instead of hard one). + \param strict_threshold Tells if threshold value is strict. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_threshold(128); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_threshold.jpg + **/ + CImg& threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) { + if (is_empty()) return *this; + if (strict_threshold) { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const T v = _data[off]; + _data[off] = v>value?(T)(v-value):v<-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),65536)) + cimg_rofoff(*this,off) _data[off] = _data[off]>value?(T)1:(T)0; + } else { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32768)) + cimg_rofoff(*this,off) { + const T v = _data[off]; + _data[off] = v>=value?(T)(v-value):v<=-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),65536)) + cimg_rofoff(*this,off) _data[off] = _data[off]>=value?(T)1:(T)0; + } + return *this; + } + + //! Threshold pixel values \newinstance. + CImg get_threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) const { + return (+*this).threshold(value,soft_threshold,strict_threshold); + } + + //! Compute the histogram of pixel values. + /** + \param nb_levels Number of desired histogram levels. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \note + - The histogram H of an image I is the 1D function where H(x) counts the number of occurrences of the value x + in the image I. + - The resulting histogram is always defined in 1D. Histograms of multi-valued images are not multi-dimensional. + \par Example + \code + const CImg img = CImg("reference.jpg").histogram(256); + img.display_graph(0,3); + \endcode + \image html ref_histogram.jpg + **/ + CImg& histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) { + return get_histogram(nb_levels,min_value,max_value).move_to(*this); + } + + //! Compute the histogram of pixel values \overloading. + CImg& histogram(const unsigned int nb_levels) { + return get_histogram(nb_levels).move_to(*this); + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) const { + if (!nb_levels || is_empty()) return CImg(); + const double + vmin = (double)(min_value res(nb_levels,1,1,1,0); + cimg_rof(*this,ptrs,T) { + const T val = *ptrs; + if (val>=vmin && val<=vmax) ++res[val==vmax?nb_levels - 1:(unsigned int)((val - vmin)*nb_levels/(vmax - vmin))]; + } + return res; + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels) const { + if (!nb_levels || is_empty()) return CImg(); + T vmax = 0, vmin = min_max(vmax); + return get_histogram(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values. + /** + \param nb_levels Number of histogram levels used for the equalization. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_equalize(256); + (img,res).display(); + \endcode + \image html ref_equalize.jpg + **/ + CImg& equalize(const unsigned int nb_levels, const T& min_value, const T& max_value) { + if (!nb_levels || is_empty()) return *this; + const T + vmin = min_value hist = get_histogram(nb_levels,vmin,vmax); + ulongT cumul = 0; + cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; } + if (!cumul) cumul = 1; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),1048576)) + cimg_rofoff(*this,off) { + const int pos = (int)((_data[off] - vmin)*(nb_levels - 1.)/(vmax - vmin)); + if (pos>=0 && pos<(int)nb_levels) _data[off] = (T)(vmin + (vmax - vmin)*hist[pos]/cumul); + } + return *this; + } + + //! Equalize histogram of pixel values \overloading. + CImg& equalize(const unsigned int nb_levels) { + if (!nb_levels || is_empty()) return *this; + T vmax = 0, vmin = min_max(vmax); + return equalize(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels, const T& val_min, const T& val_max) const { + return (+*this).equalize(nblevels,val_min,val_max); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels) const { + return (+*this).equalize(nblevels); + } + + //! Index multi-valued pixels regarding to a specified colormap. + /** + \param colormap Multi-valued colormap used as the basis for multi-valued pixel indexing. + \param dithering Level of dithering (0=disable, 1=standard level). + \param map_indexes Tell if the values of the resulting image are the colormap indices or the colormap vectors. + \note + - \p img.index(colormap,dithering,1) is equivalent to img.index(colormap,dithering,0).map(colormap). + \par Example + \code + const CImg img("reference.jpg"), colormap(3,1,1,3, 0,128,255, 0,128,255, 0,128,255); + const CImg res = img.get_index(colormap,1,true); + (img,res).display(); + \endcode + \image html ref_index.jpg + **/ + template + CImg& index(const CImg& colormap, const float dithering=1, const bool map_indexes=false) { + return get_index(colormap,dithering,map_indexes).move_to(*this); + } + + //! Index multi-valued pixels regarding to a specified colormap \newinstance. + template + CImg::Tuint> + get_index(const CImg& colormap, const float dithering=1, const bool map_indexes=true) const { + if (colormap._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "index(): Instance and specified colormap (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + typedef typename CImg::Tuint tuint; + if (is_empty()) return CImg(); + const ulongT + whd = (ulongT)_width*_height*_depth, + pwhd = (ulongT)colormap._width*colormap._height*colormap._depth; + CImg res(_width,_height,_depth,map_indexes?_spectrum:1); + if (dithering>0) { // Dithered versions + tuint *ptrd = res._data; + const float ndithering = cimg::cut(dithering,0,1)/16; + Tfloat valm = 0, valM = (Tfloat)max_min(valm); + if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; } + CImg cache = get_crop(-1,0,0,0,_width,1,0,_spectrum - 1); + Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0); + const ulongT cwhd = (ulongT)cache._width*cache._height*cache._depth; + switch (_spectrum) { + case 1 : { // Optimized for scalars + cimg_forYZ(*this,y,z) { + if (yvalM?valM:_val0; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1, + _val2 = (Tfloat)*ptrs2, val2 = _val2valM?valM:_val2; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrpvalM?valM:_val; + dist+=cimg::sqr((*_ptrs=val) - (Tfloat)*_ptrp); _ptrs+=cwhd; _ptrp+=pwhd; + } + if (dist=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs0 = data(0,y,z), *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd, + *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0=(cimg_openmp_sizefactor)*64 && + _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs = data(0,y,z), *ptrs_end = ptrs + _width; ptrs::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp img("reference.jpg"), + colormap1(3,1,1,3, 0,128,255, 0,128,255, 0,128,255), + colormap2(3,1,1,3, 255,0,0, 0,255,0, 0,0,255), + res = img.get_index(colormap1,0).map(colormap2); + (img,res).display(); + \endcode + \image html ref_map.jpg + **/ + template + CImg& map(const CImg& colormap, const unsigned int boundary_conditions=0) { + return get_map(colormap,boundary_conditions).move_to(*this); + } + + //! Map predefined colormap on the scalar (indexed) image instance \newinstance. + template + CImg get_map(const CImg& colormap, const unsigned int boundary_conditions=0) const { + const ulongT + whd = (ulongT)_width*_height*_depth, siz = size(), + cwhd = (ulongT)colormap._width*colormap._height*colormap._depth, + cwhd2 = 2*cwhd; + CImg res(_width,_height,_depth,_spectrum*colormap._spectrum); + switch (colormap._spectrum) { + + case 1 : { // Optimized for scalars + switch (boundary_conditions) { + case 3 : // Mirror + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),256)) + for (longT off = 0; off<(longT)siz; ++off) { + const ulongT ind = ((ulongT)_data[off])%cwhd2; + res[off] = colormap[ind& label(const bool is_high_connectivity=false, const Tfloat tolerance=0, + const bool is_L2_norm=true) { + if (is_empty()) return *this; + return get_label(is_high_connectivity,tolerance,is_L2_norm).move_to(*this); + } + + //! Label connected components \newinstance. + CImg get_label(const bool is_high_connectivity=false, const Tfloat tolerance=0, + const bool is_L2_norm=true) const { + if (is_empty()) return CImg(); + + // Create neighborhood tables. + int dx[13], dy[13], dz[13], nb = 0; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 0; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 0; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 0; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 0; + } + if (_depth>1) { // 3D version + dx[nb] = 0; dy[nb] = 0; dz[nb++]=1; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = -1; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = -1; + + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 1; + } + } + return _label(nb,dx,dy,dz,tolerance,is_L2_norm); + } + + //! Label connected components \overloading. + /** + \param connectivity_mask Mask of the neighboring pixels. + \param tolerance Tolerance used to determine if two neighboring pixels belong to the same region. + \param is_L2_norm If true, tolerance is compared against L2 difference, otherwise L1 is used. + **/ + template + CImg& label(const CImg& connectivity_mask, const Tfloat tolerance=0, + const bool is_L2_norm=true) { + if (is_empty()) return *this; + return get_label(connectivity_mask,tolerance,is_L2_norm).move_to(*this); + } + + //! Label connected components \newinstance. + template + CImg get_label(const CImg& connectivity_mask, const Tfloat tolerance=0, + const bool is_L2_norm=true) const { + if (is_empty()) return CImg(); + int nb = 0; + cimg_for(connectivity_mask,ptr,t) if (*ptr) ++nb; + CImg dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0); + nb = 0; + cimg_forXYZ(connectivity_mask,x,y,z) if ((x || y || z) && + connectivity_mask(x,y,z)) { + dx[nb] = x; dy[nb] = y; dz[nb++] = z; + } + return _label(nb,dx,dy,dz,tolerance,is_L2_norm); + } + + CImg _label(const unsigned int nb, const int *const dx, + const int *const dy, const int *const dz, + const Tfloat tolerance, const bool is_L2_norm) const { + CImg res(_width,_height,_depth); + const Tfloat _tolerance = _spectrum>1 && is_L2_norm?cimg::sqr(tolerance):tolerance; + + // Init label numbers. + ulongT *ptr = res.data(); + cimg_foroff(res,p) *(ptr++) = p; + + // For each neighbour-direction, label. + for (unsigned int n = 0; n& _system_strescape() { +#define cimg_system_strescape(c,s) case c : if (p!=ptrs) CImg(ptrs,(unsigned int)(p-ptrs),1,1,1,false).\ + move_to(list); \ + CImg(s,(unsigned int)std::strlen(s),1,1,1,false).move_to(list); ptrs = p + 1; break + CImgList list; + const T *ptrs = _data; + cimg_for(*this,p,T) switch ((int)*p) { + cimg_system_strescape('\\',"\\\\"); + cimg_system_strescape('\"',"\\\""); + cimg_system_strescape('!',"\"\\!\""); + cimg_system_strescape('`',"\\`"); + cimg_system_strescape('$',"\\$"); + } + if (ptrs(ptrs,(unsigned int)(end()-ptrs),1,1,1,false).move_to(list); + return (list>'x').move_to(*this); + } + + //@} + //--------------------------------- + // + //! \name Color Base Management + //@{ + //--------------------------------- + + //! Return colormap \e "default", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_default.jpg + **/ + static const CImg& default_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,256,1,3); + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap(0,index,0) = (Tuchar)r; + colormap(0,index,1) = (Tuchar)g; + colormap(0,index++,2) = (Tuchar)b; + } + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "HSV", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hsv.jpg + **/ + static const CImg& HSV_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + CImg tmp(1,256,1,3,1); + tmp.get_shared_channel(0).sequence(0,359); + colormap = tmp.HSVtoRGB(); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "lines", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_lines.jpg + **/ + static const CImg& lines_LUT256() { + static const unsigned char pal[] = { + 0,255,255,0,0,28,125,125,235,210,186,182,36,0,125,255, + 53,32,255,210,89,186,65,45,125,210,210,97,130,194,0,125, + 206,53,190,89,255,146,20,190,154,73,255,36,130,215,0,138, + 101,210,61,194,206,0,77,45,255,154,174,0,190,239,89,125, + 16,36,158,223,117,0,97,69,223,255,40,239,0,0,255,0, + 97,170,93,255,138,40,117,210,0,170,53,158,186,255,0,121, + 227,121,186,40,20,190,89,255,77,57,130,142,255,73,186,85, + 210,8,32,166,243,130,210,40,255,45,61,142,223,49,121,255, + 20,162,158,73,89,255,53,138,210,190,57,235,36,73,255,49, + 210,0,210,85,57,97,255,121,85,174,40,255,162,178,0,121, + 166,125,53,146,166,255,97,121,65,89,235,231,12,170,36,190, + 85,255,166,97,198,77,20,146,109,166,255,28,40,202,121,81, + 247,0,210,255,49,0,65,255,36,166,93,77,255,85,251,0, + 170,178,0,182,255,0,162,16,154,142,162,223,223,0,0,81, + 215,4,215,162,215,125,77,206,121,36,125,231,101,16,255,121, + 0,57,190,215,65,125,89,142,255,101,73,53,146,223,125,125, + 0,255,0,255,0,206,93,138,49,255,0,202,154,85,45,219, + 251,53,0,255,40,130,219,158,16,117,186,130,202,49,65,239, + 89,202,49,28,247,134,150,0,255,117,202,4,215,81,186,57, + 202,89,73,210,40,93,45,251,206,28,223,142,40,134,162,125, + 32,247,97,170,0,255,57,134,73,247,162,0,251,40,142,142, + 8,166,206,81,154,194,93,89,125,243,28,109,227,0,190,65, + 194,186,0,255,53,45,109,186,186,0,255,130,49,170,69,210, + 154,0,109,227,45,255,125,105,81,81,255,0,219,134,170,85, + 146,28,170,89,223,97,8,210,255,158,49,40,125,174,174,125, + 0,227,166,28,219,130,0,93,239,0,85,255,81,178,125,49, + 89,255,53,206,73,113,146,255,0,150,36,219,162,0,210,125, + 69,134,255,85,40,89,235,49,215,121,0,206,36,223,174,69, + 40,182,178,130,69,45,255,210,85,77,215,0,231,146,0,194, + 125,174,0,255,40,89,121,206,57,0,206,170,231,150,81,0, + 125,255,4,174,4,190,121,255,4,166,109,130,49,239,170,93, + 16,174,210,0,255,16,105,158,93,255,0,125,0,255,158,85, + 0,255,0,0,255,170,166,61,121,28,198,215,45,243,61,97, + 255,53,81,130,109,255,8,117,235,121,40,178,174,0,182,49, + 162,121,255,69,206,0,219,125,0,101,255,239,121,32,210,130, + 36,231,32,125,81,142,215,158,4,178,255,0,40,251,125,125, + 219,89,130,0,166,255,24,65,194,125,255,125,77,125,93,125, + 202,24,138,174,178,32,255,85,194,40,85,36,174,174,125,210, + 85,255,53,16,93,206,40,130,170,202,93,255,0,24,117,255, + 97,113,105,81,255,186,194,57,69,206,57,53,223,190,4,255, + 85,97,130,255,85,0,125,223,85,219,0,215,146,77,40,239, + 89,36,142,154,227,0,255,85,162,0,162,0,235,178,45,166, + 0,247,255,20,69,210,89,142,53,255,40,146,166,255,69,0, + 174,154,142,130,162,0,215,255,0,89,40,255,166,61,146,69, + 162,40,255,32,121,255,117,178,0,186,206,0,57,215,215,81, + 158,77,166,210,77,89,210,0,24,202,150,186,0,255,20,97, + 57,170,235,251,16,73,142,251,93,0,202,0,255,121,219,4, + 73,219,8,162,206,16,219,93,117,0,255,8,130,174,223,45 }; + static const CImg colormap(pal,1,256,1,3,false); + return colormap; + } + + //! Return colormap \e "hot", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hot.jpg + **/ + static const CImg& hot_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[1] = colormap[2] = colormap[3] = colormap[6] = colormap[7] = colormap[11] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cool", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cool.jpg + **/ + static const CImg& cool_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) colormap.assign(1,2,1,3).fill((T)0,(T)255,(T)255,(T)0,(T)255,(T)255).resize(1,256,1,3,3); + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "jet", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_jet.jpg + **/ + static const CImg& jet_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[2] = colormap[3] = colormap[5] = colormap[6] = colormap[8] = colormap[9] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "flag", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_flag.jpg + **/ + static const CImg& flag_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[0] = colormap[1] = colormap[5] = colormap[9] = colormap[10] = 255; + colormap.resize(1,256,1,3,0,2); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cube", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cube.jpg + **/ + static const CImg& cube_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,8,1,3,(T)0); + colormap[1] = colormap[3] = colormap[5] = colormap[7] = + colormap[10] = colormap[11] = colormap[12] = colormap[13] = + colormap[20] = colormap[21] = colormap[22] = colormap[23] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Convert pixel values from sRGB to RGB color spaces. + CImg& sRGBtoRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32)) + cimg_rofoff(*this,off) { + const Tfloat + sval = (Tfloat)_data[off]/255, + val = (Tfloat)(sval<=0.04045f?sval/12.92f:std::pow((sval + 0.055f)/(1.055f),2.4f)); + _data[off] = (T)cimg::cut(val*255,0,255); + } + return *this; + } + + //! Convert pixel values from sRGB to RGB color spaces \newinstance. + CImg get_sRGBtoRGB() const { + return CImg(*this,false).sRGBtoRGB(); + } + + //! Convert pixel values from RGB to sRGB color spaces. + CImg& RGBtosRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if_size(size(),32)) + cimg_rofoff(*this,off) { + const Tfloat + val = (Tfloat)_data[off]/255, + sval = (Tfloat)(val<=0.0031308f?val*12.92f:1.055f*std::pow(val,0.416667f) - 0.055f); + _data[off] = (T)cimg::cut(sval*255,0,255); + } + return *this; + } + + //! Convert pixel values from RGB to sRGB color spaces \newinstance. + CImg get_RGBtosRGB() const { + return CImg(*this,false).RGBtosRGB(); + } + + //! Convert pixel values from RGB to HSI color spaces. + CImg& RGBtoHSI() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSI(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSI() const { + return CImg(*this,false).RGBtoHSI(); + } + + //! Convert pixel values from HSI to RGB color spaces. + CImg& HSItoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSItoRGB(): Instance is not a HSI image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSItoRGB() const { + return CImg< Tuchar>(*this,false).HSItoRGB(); + } + + //! Convert pixel values from RGB to HSL color spaces. + CImg& RGBtoHSL() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSL(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSL() const { + return CImg(*this,false).RGBtoHSL(); + } + + //! Convert pixel values from HSL to RGB color spaces. + CImg& HSLtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSLtoRGB(): Instance is not a HSL image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSLtoRGB() const { + return CImg(*this,false).HSLtoRGB(); + } + + //! Convert pixel values from RGB to HSV color spaces. + CImg& RGBtoHSV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSV(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_RGBtoHSV() const { + return CImg(*this,false).RGBtoHSV(); + } + + //! Convert pixel values from HSV to RGB color spaces. + CImg& HSVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSVtoRGB(): Instance is not a HSV image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,256)) + for (longT N = 0; N get_HSVtoRGB() const { + return CImg(*this,false).HSVtoRGB(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& RGBtoYCbCr() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYCbCr(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,512)) + for (longT N = 0; N get_RGBtoYCbCr() const { + return CImg(*this,false).RGBtoYCbCr(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& YCbCrtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YCbCrtoRGB(): Instance is not a YCbCr image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,512)) + for (longT N = 0; N get_YCbCrtoRGB() const { + return CImg(*this,false).YCbCrtoRGB(); + } + + //! Convert pixel values from RGB to YUV color spaces. + CImg& RGBtoYUV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYUV(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,16384)) + for (longT N = 0; N get_RGBtoYUV() const { + return CImg(*this,false).RGBtoYUV(); + } + + //! Convert pixel values from YUV to RGB color spaces. + CImg& YUVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YUVtoRGB(): Instance is not a YUV image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,16384)) + for (longT N = 0; N get_YUVtoRGB() const { + return CImg< Tuchar>(*this,false).YUVtoRGB(); + } + + //! Convert pixel values from RGB to CMY color spaces. + CImg& RGBtoCMY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoCMY(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_RGBtoCMY() const { + return CImg(*this,false).RGBtoCMY(); + } + + //! Convert pixel values from CMY to RGB color spaces. + CImg& CMYtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoRGB(): Instance is not a CMY image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_CMYtoRGB() const { + return CImg(*this,false).CMYtoRGB(); + } + + //! Convert pixel values from CMY to CMYK color spaces. + CImg& CMYtoCMYK() { + return get_CMYtoCMYK().move_to(*this); + } + + //! Convert pixel values from CMY to CMYK color spaces \newinstance. + CImg get_CMYtoCMYK() const { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoCMYK(): Instance is not a CMY image.", + cimg_instance); + + CImg res(_width,_height,_depth,4); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024)) + for (longT N = 0; N=255) C = M = Y = 0; + else { const Tfloat K1 = 255 - K; C = 255*(C - K)/K1; M = 255*(M - K)/K1; Y = 255*(Y - K)/K1; } + pd1[N] = (Tfloat)cimg::cut(C,0,255), + pd2[N] = (Tfloat)cimg::cut(M,0,255), + pd3[N] = (Tfloat)cimg::cut(Y,0,255), + pd4[N] = (Tfloat)cimg::cut(K,0,255); + } + return res; + } + + //! Convert pixel values from CMYK to CMY color spaces. + CImg& CMYKtoCMY() { + return get_CMYKtoCMY().move_to(*this); + } + + //! Convert pixel values from CMYK to CMY color spaces \newinstance. + CImg get_CMYKtoCMY() const { + if (_spectrum!=4) + throw CImgInstanceException(_cimg_instance + "CMYKtoCMY(): Instance is not a CMYK image.", + cimg_instance); + + CImg res(_width,_height,_depth,3); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2), *ps4 = data(0,0,0,3); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024)) + for (longT N = 0; N& RGBtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoXYZ(): Instance is not a RGB image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_RGBtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).RGBtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to RGB color spaces. + /** + \param use_D65 Tell to use the D65 illuminant (D50 otherwise). + **/ + CImg& XYZtoRGB(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoRGB(): Instance is not a XYZ image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048)) + for (longT N = 0; N get_XYZtoRGB(const bool use_D65=true) const { + return CImg(*this,false).XYZtoRGB(use_D65); + } + + //! Convert pixel values from XYZ to Lab color spaces. + CImg& XYZtoLab(const bool use_D65=true) { +#define _cimg_Labf(x) (24389*(x)>216?cimg::cbrt(x):(24389*(x)/27 + 16)/116) + + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoLab(): Instance is not a XYZ image.", + cimg_instance); + const CImg white = CImg(1,1,1,3,255).RGBtoXYZ(use_D65); + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128)) + for (longT N = 0; N get_XYZtoLab(const bool use_D65=true) const { + return CImg(*this,false).XYZtoLab(use_D65); + } + + //! Convert pixel values from Lab to XYZ color spaces. + CImg& LabtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "LabtoXYZ(): Instance is not a Lab image.", + cimg_instance); + const CImg white = CImg(1,1,1,3,255).RGBtoXYZ(use_D65); + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128)) + for (longT N = 0; N216?cX*cX*cX:(116*cX - 16)*27/24389), + Y = (Tfloat)(27*L>216?cY*cY*cY:27*L/24389), + Z = (Tfloat)(24389*cZ>216?cZ*cZ*cZ:(116*cZ - 16)*27/24389); + p1[N] = (T)(X*white[0]); + p2[N] = (T)(Y*white[1]); + p3[N] = (T)(Z*white[2]); + } + return *this; + } + + //! Convert pixel values from Lab to XYZ color spaces \newinstance. + CImg get_LabtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).LabtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to xyY color spaces. + CImg& XYZtoxyY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoxyY(): Instance is not a XYZ image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096)) + for (longT N = 0; N0?sum:1; + p1[N] = (T)(X/nsum); + p2[N] = (T)(Y/nsum); + p3[N] = (T)Y; + } + return *this; + } + + //! Convert pixel values from XYZ to xyY color spaces \newinstance. + CImg get_XYZtoxyY() const { + return CImg(*this,false).XYZtoxyY(); + } + + //! Convert pixel values from xyY pixels to XYZ color spaces. + CImg& xyYtoXYZ() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "xyYtoXYZ(): Instance is not a xyY image.", + cimg_instance); + + T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2); + const longT whd = (longT)width()*height()*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,4096)) + for (longT N = 0; N0?py:1; + p1[N] = (T)(px*Y/ny); + p2[N] = (T)Y; + p3[N] = (T)((1 - px - py)*Y/ny); + } + return *this; + } + + //! Convert pixel values from xyY pixels to XYZ color spaces \newinstance. + CImg get_xyYtoXYZ() const { + return CImg(*this,false).xyYtoXYZ(); + } + + //! Convert pixel values from RGB to Lab color spaces. + CImg& RGBtoLab(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoLab(use_D65); + } + + //! Convert pixel values from RGB to Lab color spaces \newinstance. + CImg get_RGBtoLab(const bool use_D65=true) const { + return CImg(*this,false).RGBtoLab(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces. + CImg& LabtoRGB(const bool use_D65=true) { + return LabtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces \newinstance. + CImg get_LabtoRGB(const bool use_D65=true) const { + return CImg(*this,false).LabtoRGB(use_D65); + } + + //! Convert pixel values from RGB to xyY color spaces. + CImg& RGBtoxyY(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoxyY(); + } + + //! Convert pixel values from RGB to xyY color spaces \newinstance. + CImg get_RGBtoxyY(const bool use_D65=true) const { + return CImg(*this,false).RGBtoxyY(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces. + CImg& xyYtoRGB(const bool use_D65=true) { + return xyYtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces \newinstance. + CImg get_xyYtoRGB(const bool use_D65=true) const { + return CImg(*this,false).xyYtoRGB(use_D65); + } + + //! Convert pixel values from RGB to CMYK color spaces. + CImg& RGBtoCMYK() { + return RGBtoCMY().CMYtoCMYK(); + } + + //! Convert pixel values from RGB to CMYK color spaces \newinstance. + CImg get_RGBtoCMYK() const { + return CImg(*this,false).RGBtoCMYK(); + } + + //! Convert pixel values from CMYK to RGB color spaces. + CImg& CMYKtoRGB() { + return CMYKtoCMY().CMYtoRGB(); + } + + //! Convert pixel values from CMYK to RGB color spaces \newinstance. + CImg get_CMYKtoRGB() const { + return CImg(*this,false).CMYKtoRGB(); + } + + //@} + //------------------------------------------ + // + //! \name Geometric / Spatial Manipulation + //@{ + //------------------------------------------ + + static float _cimg_lanczos(const float x) { + if (x<=-2 || x>=2) return 0; + const float a = (float)cimg::PI*x, b = 0.5f*a; + return (float)(x?std::sin(a)*std::sin(b)/(a*b):1); + } + + //! Resize image to new dimensions. + /** + \param size_x Number of columns (new size along the X-axis). + \param size_y Number of rows (new size along the Y-axis). + \param size_z Number of slices (new size along the Z-axis). + \param size_c Number of vector-channels (new size along the C-axis). + \param interpolation_type Method of interpolation: + - -1 = no interpolation: raw memory resizing. + - 0 = no interpolation: additional space is filled according to \p boundary_conditions. + - 1 = nearest-neighbor interpolation. + - 2 = moving average interpolation. + - 3 = linear interpolation. + - 4 = grid interpolation. + - 5 = cubic interpolation. + - 6 = lanczos interpolation. + \param boundary_conditions Type of boundary conditions used if necessary. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). + **/ + CImg& resize(const int size_x, const int size_y=-100, + const int size_z=-100, const int size_c=-100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + if (!size_x || !size_y || !size_z || !size_c) return assign(); + const unsigned int + _sx = (unsigned int)(size_x<0?-size_x*width()/100:size_x), + _sy = (unsigned int)(size_y<0?-size_y*height()/100:size_y), + _sz = (unsigned int)(size_z<0?-size_z*depth()/100:size_z), + _sc = (unsigned int)(size_c<0?-size_c*spectrum()/100:size_c), + sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1; + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return *this; + if (is_empty()) return assign(sx,sy,sz,sc,(T)0); + if (interpolation_type==-1 && sx*sy*sz*sc==size()) { + _width = sx; _height = sy; _depth = sz; _spectrum = sc; + return *this; + } + return get_resize(sx,sy,sz,sc,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c).move_to(*this); + } + + //! Resize image to new dimensions \newinstance. + CImg get_resize(const int size_x, const int size_y = -100, + const int size_z = -100, const int size_c = -100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + if (centering_x<0 || centering_x>1 || centering_y<0 || centering_y>1 || + centering_z<0 || centering_z>1 || centering_c<0 || centering_c>1) + throw CImgArgumentException(_cimg_instance + "resize(): Specified centering arguments (%g,%g,%g,%g) are outside range [0,1].", + cimg_instance, + centering_x,centering_y,centering_z,centering_c); + + if (!size_x || !size_y || !size_z || !size_c) return CImg(); + const unsigned int + sx = std::max(1U,(unsigned int)(size_x>=0?size_x:-size_x*width()/100)), + sy = std::max(1U,(unsigned int)(size_y>=0?size_y:-size_y*height()/100)), + sz = std::max(1U,(unsigned int)(size_z>=0?size_z:-size_z*depth()/100)), + sc = std::max(1U,(unsigned int)(size_c>=0?size_c:-size_c*spectrum()/100)); + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return +*this; + if (is_empty()) return CImg(sx,sy,sz,sc,(T)0); + CImg res; + switch (interpolation_type) { + + // Raw resizing. + // + case -1 : + std::memcpy(res.assign(sx,sy,sz,sc,(T)0)._data,_data,sizeof(T)*std::min(size(),(ulongT)sx*sy*sz*sc)); + break; + + // No interpolation. + // + case 0 : { + const int + xc = (int)(centering_x*((int)sx - width())), + yc = (int)(centering_y*((int)sy - height())), + zc = (int)(centering_z*((int)sz - depth())), + cc = (int)(centering_c*((int)sc - spectrum())); + + switch (boundary_conditions) { + case 3 : { // Mirror + res.assign(sx,sy,sz,sc); + const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),1024*1024)) + cimg_forXYZC(res,x,y,z,c) { + const int + mx = cimg::mod(x - xc,w2), my = cimg::mod(y - yc,h2), + mz = cimg::mod(z - zc,d2), mc = cimg::mod(c - cc,s2); + res(x,y,z,c) = (*this)(mx sprite; + if (xc>0) { // X-backward + res.get_crop(xc,yc,zc,cc,xc,yc + height() - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc - 1; x>=0; --x) res.draw_image(x,yc,zc,cc,sprite); + } + if (xc + width()<(int)sx) { // X-forward + res.get_crop(xc + width() - 1,yc,zc,cc,xc + width() - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc + width(); x<(int)sx; ++x) res.draw_image(x,yc,zc,cc,sprite); + } + if (yc>0) { // Y-backward + res.get_crop(0,yc,zc,cc,sx - 1,yc,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc - 1; y>=0; --y) res.draw_image(0,y,zc,cc,sprite); + } + if (yc + height()<(int)sy) { // Y-forward + res.get_crop(0,yc + height() - 1,zc,cc,sx - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc + height(); y<(int)sy; ++y) res.draw_image(0,y,zc,cc,sprite); + } + if (zc>0) { // Z-backward + res.get_crop(0,0,zc,cc,sx - 1,sy - 1,zc,cc + spectrum() - 1).move_to(sprite); + for (int z = zc - 1; z>=0; --z) res.draw_image(0,0,z,cc,sprite); + } + if (zc + depth()<(int)sz) { // Z-forward + res.get_crop(0,0,zc +depth() - 1,cc,sx - 1,sy - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int z = zc + depth(); z<(int)sz; ++z) res.draw_image(0,0,z,cc,sprite); + } + if (cc>0) { // C-backward + res.get_crop(0,0,0,cc,sx - 1,sy - 1,sz - 1,cc).move_to(sprite); + for (int c = cc - 1; c>=0; --c) res.draw_image(0,0,0,c,sprite); + } + if (cc + spectrum()<(int)sc) { // C-forward + res.get_crop(0,0,0,cc + spectrum() - 1,sx - 1,sy - 1,sz - 1,cc + spectrum() - 1).move_to(sprite); + for (int c = cc + spectrum(); c<(int)sc; ++c) res.draw_image(0,0,0,c,sprite); + } + } break; + default : // Dirichlet + res.assign(sx,sy,sz,sc,(T)0).draw_image(xc,yc,zc,cc,*this); + } + break; + } break; + + // Nearest neighbor interpolation. + // + case 1 : { + res.assign(sx,sy,sz,sc); + CImg off_x(sx), off_y(sy + 1), off_z(sz + 1), off_c(sc + 1); + const ulongT + wh = (ulongT)_width*_height, + whd = (ulongT)_width*_height*_depth, + sxy = (ulongT)sx*sy, + sxyz = (ulongT)sx*sy*sz, + one = (ulongT)1; + if (sx==_width) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + cimg_forX(res,x) { + const ulongT old = curr; + curr = (x + one)*_width/sx; + *(poff_x++) = curr - old; + } + } + if (sy==_height) off_y.fill(_width); + else { + ulongT *poff_y = off_y._data, curr = 0; + cimg_forY(res,y) { + const ulongT old = curr; + curr = (y + one)*_height/sy; + *(poff_y++) = _width*(curr - old); + } + *poff_y = 0; + } + if (sz==_depth) off_z.fill(wh); + else { + ulongT *poff_z = off_z._data, curr = 0; + cimg_forZ(res,z) { + const ulongT old = curr; + curr = (z + one)*_depth/sz; + *(poff_z++) = wh*(curr - old); + } + *poff_z = 0; + } + if (sc==_spectrum) off_c.fill(whd); + else { + ulongT *poff_c = off_c._data, curr = 0; + cimg_forC(res,c) { + const ulongT old = curr; + curr = (c + one)*_spectrum/sc; + *(poff_c++) = whd*(curr - old); + } + *poff_c = 0; + } + + T *ptrd = res._data; + const T* ptrc = _data; + const ulongT *poff_c = off_c._data; + for (unsigned int c = 0; c_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(res); + else { + CImg tmp(sx,_height,_depth,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sx>=256 && _height*_depth*_spectrum>=256)) + cimg_forYZC(tmp,y,z,v) { + for (unsigned int a = _width*sx, b = _width, c = sx, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + tmp(t,y,z,v)+=(Tfloat)(*this)(s,y,z,v)*d; + if (!b) { tmp(t++,y,z,v)/=_width; b = _width; } + if (!c) { ++s; c = sx; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sy!=_height) { + if (sy>_height) get_resize(sx,sy,_depth,_spectrum,1).move_to(res); + else { + CImg tmp(sx,sy,_depth,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sy>=256 && _width*_depth*_spectrum>=256)) + cimg_forXZC(tmp,x,z,v) { + for (unsigned int a = _height*sy, b = _height, c = sy, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,t,z,v)+=(Tfloat)(*this)(x,s,z,v)*d; + else tmp(x,t,z,v)+=(Tfloat)res(x,s,z,v)*d; + if (!b) { tmp(x,t++,z,v)/=_height; b = _height; } + if (!c) { ++s; c = sy; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sz!=_depth) { + if (sz>_depth) get_resize(sx,sy,sz,_spectrum,1).move_to(res); + else { + CImg tmp(sx,sy,sz,_spectrum,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sz>=256 && _width*_height*_spectrum>=256)) + cimg_forXYC(tmp,x,y,v) { + for (unsigned int a = _depth*sz, b = _depth, c = sz, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,y,t,v)+=(Tfloat)(*this)(x,y,s,v)*d; + else tmp(x,y,t,v)+=(Tfloat)res(x,y,s,v)*d; + if (!b) { tmp(x,y,t++,v)/=_depth; b = _depth; } + if (!c) { ++s; c = sz; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + if (sc!=_spectrum) { + if (sc>_spectrum) get_resize(sx,sy,sz,sc,1).move_to(res); + else { + CImg tmp(sx,sy,sz,sc,0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(sc>=256 && _width*_height*_depth>=256)) + cimg_forXYZ(tmp,x,y,z) { + for (unsigned int a = _spectrum*sc, b = _spectrum, c = sc, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) tmp(x,y,z,t)+=(Tfloat)(*this)(x,y,z,s)*d; + else tmp(x,y,z,t)+=(Tfloat)res(x,y,z,s)*d; + if (!b) { tmp(x,y,z,t++)/=_spectrum; b = _spectrum; } + if (!c) { ++s; c = sc; } + } + } + tmp.move_to(res); + } + instance_first = false; + } + + } break; + + // Linear interpolation. + // + case 3 : { + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *ptrs = data(0,y,z,c), *const ptrsmax = ptrs + _width - 1; + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *ptrs = resx.data(x,0,z,c), *const ptrsmax = ptrs + (_height - 1)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *ptrs = resy.data(x,y,0,c), *const ptrsmax = ptrs + (_depth - 1)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *ptrs = resz.data(x,y,z,0), *const ptrsmax = ptrs + (_spectrum - 1)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrs resx, resy, resz, resc; + if (sx!=_width) { + if (sx<_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + resx.assign(sx,_height,_depth,_spectrum,(T)0); + const int dx = (int)(2*sx), dy = 2*width(); + int err = (int)(dy + centering_x*(sx*dy/width() - dy)), xs = 0; + cimg_forX(resx,x) if ((err-=dy)<=0) { + cimg_forYZC(resx,y,z,c) resx(x,y,z,c) = (*this)(xs,y,z,c); + ++xs; + err+=dx; + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (sy<_height) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + resy.assign(sx,sy,_depth,_spectrum,(T)0); + const int dx = (int)(2*sy), dy = 2*height(); + int err = (int)(dy + centering_y*(sy*dy/height() - dy)), ys = 0; + cimg_forY(resy,y) if ((err-=dy)<=0) { + cimg_forXZC(resy,x,z,c) resy(x,y,z,c) = resx(x,ys,z,c); + ++ys; + err+=dx; + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (sz<_depth) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + resz.assign(sx,sy,sz,_spectrum,(T)0); + const int dx = (int)(2*sz), dy = 2*depth(); + int err = (int)(dy + centering_z*(sz*dy/depth() - dy)), zs = 0; + cimg_forZ(resz,z) if ((err-=dy)<=0) { + cimg_forXYC(resz,x,y,c) resz(x,y,z,c) = resy(x,y,zs,c); + ++zs; + err+=dx; + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (sc<_spectrum) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + resc.assign(sx,sy,sz,sc,(T)0); + const int dx = (int)(2*sc), dy = 2*spectrum(); + int err = (int)(dy + centering_c*(sc*dy/spectrum() - dy)), cs = 0; + cimg_forC(resc,c) if ((err-=dy)<=0) { + cimg_forXYZ(resc,x,y,z) resc(x,y,z,c) = resz(x,y,z,cs); + ++cs; + err+=dx; + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Cubic interpolation. + // + case 5 : { + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_width - 2); + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - 1):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + 1):val1, + val3 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sx):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sx):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxy):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxyz):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Lanczos interpolation. + // + case 6 : { + const double vmin = (double)cimg::type::min(), vmax = (double)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg resx, resy, resz, resc; + double curr, old; + + if (sx!=_width) { + if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx); + else { + const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.)/(sx - 1):0): + (double)_width/sx; + resx.assign(sx,_height,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forX(resx,x) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(width() - 1.,curr + fx); + *(poff++) = (unsigned int)curr - (unsigned int)old; + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resx._width>=256 && resx._height*resx._depth*resx._spectrum>=256)) + cimg_forYZC(resx,y,z,c) { + const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + 1, + *const ptrsmax = ptrs0 + (_width - 2); + T *ptrd = resx.data(0,y,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - 1):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + 1):val2, + val4 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(height() - 1.,curr + fy); + *(poff++) = sx*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resy._height>=256 && resy._width*resy._depth*resy._spectrum>=256)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sx, + *const ptrsmax = ptrs0 + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sx):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sx):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sx):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.)/(sz - 1):0): + (double)_depth/sz; + const unsigned int sxy = sx*sy; + resz.assign(sx,sy,sz,_spectrum); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(depth() - 1.,curr + fz); + *(poff++) = sxy*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resz._depth>=256 && resz._width*resz._height*resz._spectrum>=256)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxy, + *const ptrsmax = ptrs0 + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sxy):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxy):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.)/(sc - 1):0): + (double)_spectrum/sc; + const unsigned int sxyz = sx*sy*sz; + resc.assign(sx,sy,sz,sc); + curr = old = 0; + { + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + curr = std::min(spectrum() - 1.,curr + fc); + *(poff++) = sxyz*((unsigned int)curr - (unsigned int)old); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(resc._spectrum>=256 && resc._width*resc._height*resc._depth>=256)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxyz, + *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + w0 = _cimg_lanczos(t + 2), + w1 = _cimg_lanczos(t + 1), + w2 = _cimg_lanczos(t), + w3 = _cimg_lanczos(t - 1), + w4 = _cimg_lanczos(t - 2), + val2 = (double)*ptrs, + val1 = ptrs>=ptrsmin?(double)*(ptrs - sxyz):val2, + val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxyz):val1, + val3 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val2, + val4 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Unknown interpolation. + // + default : + throw CImgArgumentException(_cimg_instance + "resize(): Invalid specified interpolation %d " + "(should be { -1=raw | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | " + "5=cubic | 6=lanczos }).", + cimg_instance, + interpolation_type); + } + return res; + } + + //! Resize image to dimensions of another image. + /** + \param src Reference image used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + template + CImg& resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of another image \newinstance. + template + CImg get_resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window. + /** + \param disp Reference display window used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + CImg& resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window \newinstance. + CImg get_resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to half-size along XY axes, using an optimized filter. + CImg& resize_halfXY() { + return get_resize_halfXY().move_to(*this); + } + + //! Resize image to half-size along XY axes, using an optimized filter \newinstance. + CImg get_resize_halfXY() const { + if (is_empty()) return *this; + static const Tfloat kernel[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f, + 0.1231940459f, 0.1935127547f, 0.1231940459f, + 0.07842776544f, 0.1231940459f, 0.07842776544f }; + CImg I(9), res(_width/2,_height/2,_depth,_spectrum); + T *ptrd = res._data; + cimg_forZC(*this,z,c) cimg_for3x3(*this,x,y,z,c,I,T) + if (x%2 && y%2) *(ptrd++) = (T) + (I[0]*kernel[0] + I[1]*kernel[1] + I[2]*kernel[2] + + I[3]*kernel[3] + I[4]*kernel[4] + I[5]*kernel[5] + + I[6]*kernel[6] + I[7]*kernel[7] + I[8]*kernel[8]); + return res; + } + + //! Resize image to double-size, using the Scale2X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_doubleXY() { + return get_resize_doubleXY().move_to(*this); + } + + //! Resize image to double-size, using the Scale2X algorithm \newinstance. + CImg get_resize_doubleXY() const { +#define _cimg_gs2x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=(res)._width, ptrd2+=(res)._width) + +#define _cimg_gs2x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs2x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(_width<<1,_height<<1,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width; + _cimg_gs2x_for3x3(*this,x,y,z,c,I,T) { + if (Icp!=Icn && Ipc!=Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = Ipc==Icn?Ipc:Icc; + *(ptrd2++) = Icn==Inc?Inc:Icc; + } else { *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; } + } + } + return res; + } + + //! Resize image to triple-size, using the Scale3X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_tripleXY() { + return get_resize_tripleXY().move_to(*this); + } + + //! Resize image to triple-size, using the Scale3X algorithm \newinstance. + CImg get_resize_tripleXY() const { +#define _cimg_gs3x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=2*(res)._width, ptrd2+=2*(res)._width, ptrd3+=2*(res)._width) + +#define _cimg_gs3x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs3x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(3*_width,3*_height,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width, + *ptrd3 = ptrd2 + res._width; + _cimg_gs3x_for3x3(*this,x,y,z,c,I,T) { + if (Icp != Icn && Ipc != Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = (Ipc==Icp && Icc!=Inp) || (Icp==Inc && Icc!=Ipp)?Icp:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = (Ipc==Icp && Icc!=Ipn) || (Ipc==Icn && Icc!=Ipp)?Ipc:Icc; + *(ptrd2++) = Icc; + *(ptrd2++) = (Icp==Inc && Icc!=Inn) || (Icn==Inc && Icc!=Inp)?Inc:Icc; + *(ptrd3++) = Ipc==Icn?Ipc:Icc; + *(ptrd3++) = (Ipc==Icn && Icc!=Inn) || (Icn==Inc && Icc!=Ipn)?Icn:Icc; + *(ptrd3++) = Icn==Inc?Inc:Icc; + } else { + *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd1++) = Icc; + *(ptrd2++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; + *(ptrd3++) = Icc; *(ptrd3++) = Icc; *(ptrd3++) = Icc; + } + } + } + return res; + } + + //! Mirror image content along specified axis. + /** + \param axis Mirror axis + **/ + CImg& mirror(const char axis) { + if (is_empty()) return *this; + T *pf, *pb, *buf = 0; + switch (cimg::lowercase(axis)) { + case 'x' : { + pf = _data; pb = data(_width - 1); + const unsigned int width2 = _width/2; + for (unsigned int yzv = 0; yzv<_height*_depth*_spectrum; ++yzv) { + for (unsigned int x = 0; x get_mirror(const char axis) const { + return (+*this).mirror(axis); + } + + //! Mirror image content along specified axes. + /** + \param axes Mirror axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& mirror(const char *const axes) { + for (const char *s = axes; *s; ++s) mirror(*s); + return *this; + } + + //! Mirror image content along specified axes \newinstance. + CImg get_mirror(const char *const axes) const { + return (+*this).mirror(axes); + } + + //! Shift image content. + /** + \param delta_x Amount of displacement along the X-axis. + \param delta_y Amount of displacement along the Y-axis. + \param delta_z Amount of displacement along the Z-axis. + \param delta_c Amount of displacement along the C-axis. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const unsigned int boundary_conditions=0) { + if (is_empty()) return *this; + if (boundary_conditions==3) + return get_crop(-delta_x,-delta_y,-delta_z,-delta_c, + width() - delta_x - 1, + height() - delta_y - 1, + depth() - delta_z - 1, + spectrum() - delta_c - 1,3).move_to(*this); + if (delta_x) // Shift along X-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_x,width()), ndelta_x = (ml<=width()/2)?ml:(ml-width()); + if (!ndelta_x) return *this; + CImg buf(cimg::abs(ndelta_x)); + if (ndelta_x>0) cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(0,y,z,c),ndelta_x*sizeof(T)); + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + std::memcpy(data(_width-ndelta_x,y,z,c),buf,ndelta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(_width + ndelta_x,y,z,c),-ndelta_x*sizeof(T)); + std::memmove(data(-ndelta_x,y,z,c),data(0,y,z,c),(_width + ndelta_x)*sizeof(T)); + std::memcpy(data(0,y,z,c),buf,-ndelta_x*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_x<0) { + const int ndelta_x = (-delta_x>=width())?width() - 1:-delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(_width - 1,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width())?width() - 1:delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(ndelta_x,y,z,c),data(0,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(0,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width()) return fill((T)0); + if (delta_x<0) cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(-delta_x,y,z,c),(_width + delta_x)*sizeof(T)); + std::memset(data(_width + delta_x,y,z,c),0,-delta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memmove(data(delta_x,y,z,c),data(0,y,z,c),(_width-delta_x)*sizeof(T)); + std::memset(data(0,y,z,c),0,delta_x*sizeof(T)); + } + } + + if (delta_y) // Shift along Y-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_y,height()), ndelta_y = (ml<=height()/2)?ml:(ml-height()); + if (!ndelta_y) return *this; + CImg buf(width(),cimg::abs(ndelta_y)); + if (ndelta_y>0) cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,0,z,c),_width*ndelta_y*sizeof(T)); + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + std::memcpy(data(0,_height-ndelta_y,z,c),buf,_width*ndelta_y*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,_height + ndelta_y,z,c),-ndelta_y*_width*sizeof(T)); + std::memmove(data(0,-ndelta_y,z,c),data(0,0,z,c),_width*(_height + ndelta_y)*sizeof(T)); + std::memcpy(data(0,0,z,c),buf,-ndelta_y*_width*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_y<0) { + const int ndelta_y = (-delta_y>=height())?height() - 1:-delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,_height-ndelta_y,z,c), *ptrs = data(0,_height - 1,z,c); + for (int l = 0; l=height())?height() - 1:delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,ndelta_y,z,c),data(0,0,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,1,z,c), *ptrs = data(0,0,z,c); + for (int l = 0; l=height()) return fill((T)0); + if (delta_y<0) cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,-delta_y,z,c),_width*(_height + delta_y)*sizeof(T)); + std::memset(data(0,_height + delta_y,z,c),0,-delta_y*_width*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memmove(data(0,delta_y,z,c),data(0,0,z,c),_width*(_height-delta_y)*sizeof(T)); + std::memset(data(0,0,z,c),0,delta_y*_width*sizeof(T)); + } + } + + if (delta_z) // Shift along Z-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_z,depth()), ndelta_z = (ml<=depth()/2)?ml:(ml-depth()); + if (!ndelta_z) return *this; + CImg buf(width(),height(),cimg::abs(ndelta_z)); + if (ndelta_z>0) cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,0,c),_width*_height*ndelta_z*sizeof(T)); + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,_depth-ndelta_z,c),buf,_width*_height*ndelta_z*sizeof(T)); + } else cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,_depth + ndelta_z,c),-ndelta_z*_width*_height*sizeof(T)); + std::memmove(data(0,0,-ndelta_z,c),data(0,0,0,c),_width*_height*(_depth + ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,0,c),buf,-ndelta_z*_width*_height*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_z<0) { + const int ndelta_z = (-delta_z>=depth())?depth() - 1:-delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,_depth-ndelta_z,c), *ptrs = data(0,0,_depth - 1,c); + for (int l = 0; l=depth())?depth() - 1:delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,ndelta_z,c),data(0,0,0,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,1,c), *ptrs = data(0,0,0,c); + for (int l = 0; l=depth()) return fill((T)0); + if (delta_z<0) cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,-delta_z,c),_width*_height*(_depth + delta_z)*sizeof(T)); + std::memset(data(0,0,_depth + delta_z,c),0,_width*_height*(-delta_z)*sizeof(T)); + } else cimg_forC(*this,c) { + std::memmove(data(0,0,delta_z,c),data(0,0,0,c),_width*_height*(_depth-delta_z)*sizeof(T)); + std::memset(data(0,0,0,c),0,delta_z*_width*_height*sizeof(T)); + } + } + + if (delta_c) // Shift along C-axis + switch (boundary_conditions) { + case 2 : { // Periodic + const int ml = cimg::mod(-delta_c,spectrum()), ndelta_c = (ml<=spectrum()/2)?ml:(ml-spectrum()); + if (!ndelta_c) return *this; + CImg buf(width(),height(),depth(),cimg::abs(ndelta_c)); + if (ndelta_c>0) { + std::memcpy(buf,_data,_width*_height*_depth*ndelta_c*sizeof(T)); + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + std::memcpy(data(0,0,0,_spectrum-ndelta_c),buf,_width*_height*_depth*ndelta_c*sizeof(T)); + } else { + std::memcpy(buf,data(0,0,0,_spectrum + ndelta_c),-ndelta_c*_width*_height*_depth*sizeof(T)); + std::memmove(data(0,0,0,-ndelta_c),_data,_width*_height*_depth*(_spectrum + ndelta_c)*sizeof(T)); + std::memcpy(_data,buf,-ndelta_c*_width*_height*_depth*sizeof(T)); + } + } break; + case 1 : // Neumann + if (delta_c<0) { + const int ndelta_c = (-delta_c>=spectrum())?spectrum() - 1:-delta_c; + if (!ndelta_c) return *this; + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,_spectrum-ndelta_c), *ptrs = data(0,0,0,_spectrum - 1); + for (int l = 0; l=spectrum())?spectrum() - 1:delta_c; + if (!ndelta_c) return *this; + std::memmove(data(0,0,0,ndelta_c),_data,_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,1); + for (int l = 0; l=spectrum()) return fill((T)0); + if (delta_c<0) { + std::memmove(_data,data(0,0,0,-delta_c),_width*_height*_depth*(_spectrum + delta_c)*sizeof(T)); + std::memset(data(0,0,0,_spectrum + delta_c),0,_width*_height*_depth*(-delta_c)*sizeof(T)); + } else { + std::memmove(data(0,0,0,delta_c),_data,_width*_height*_depth*(_spectrum-delta_c)*sizeof(T)); + std::memset(_data,0,delta_c*_width*_height*_depth*sizeof(T)); + } + } + return *this; + } + + //! Shift image content \newinstance. + CImg get_shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const unsigned int boundary_conditions=0) const { + return (+*this).shift(delta_x,delta_y,delta_z,delta_c,boundary_conditions); + } + + //! Permute axes order. + /** + \param axes_order Axes permutations, as a C-string of 4 characters. + This function permutes image content regarding the specified axes permutation. + **/ + CImg& permute_axes(const char *const axes_order) { + return get_permute_axes(axes_order).move_to(*this); + } + + //! Permute axes order \newinstance. + CImg get_permute_axes(const char *const axes_order) const { + const T foo = (T)0; + return _permute_axes(axes_order,foo); + } + + template + CImg _permute_axes(const char *const axes_order, const t&) const { + if (is_empty() || !axes_order) return CImg(*this,false); + CImg res; + const T* ptrs = _data; + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = (unsigned char)c; } + } + if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { + const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + ulongT wh, whd; + switch (code) { + case 0x0123 : // xyzc + return +*this; + case 0x0132 : // xycz + res.assign(_width,_height,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0213 : // xzyc + res.assign(_width,_depth,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x0231 : // xzcy + res.assign(_width,_depth,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x0312 : // xcyz + res.assign(_width,_spectrum,_height,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0321 : // xczy + res.assign(_width,_spectrum,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x1023 : // yxzc + res.assign(_height,_width,_depth,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1032 : // yxcz + res.assign(_height,_width,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1203 : // yzxc + res.assign(_height,_depth,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1230 : // yzcx + res.assign(_height,_depth,_spectrum,_width); + switch (_width) { + case 1 : { + t *ptr_r = res.data(0,0,0,0); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)*(ptrs++); + } + } break; + case 2 : { + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + ptrs+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + ptrs+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA + t + *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), + *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + *(ptr_a++) = (t)ptrs[3]; + ptrs+=4; + } + } break; + default : { + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++); + return res; + } + } + break; + case 0x1302 : // ycxz + res.assign(_height,_spectrum,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1320 : // yczx + res.assign(_height,_spectrum,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2013 : // zxyc + res.assign(_depth,_width,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2031 : // zxcy + res.assign(_depth,_width,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2103 : // zyxc + res.assign(_depth,_height,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2130 : // zycx + res.assign(_depth,_height,_spectrum,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2301 : // zcxy + res.assign(_depth,_spectrum,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2310 : // zcyx + res.assign(_depth,_spectrum,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3012 : // cxyz + res.assign(_spectrum,_width,_height,_depth); + switch (_spectrum) { + case 1 : { + const T *ptr_r = data(0,0,0,0); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++); + } break; + case 2 : { + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd[3] = (t)*(ptr_a++); + ptrd+=4; + } + } break; + default : { + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++); + } + } + break; + case 0x3021 : // cxzy + res.assign(_spectrum,_width,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3102 : // cyxz + res.assign(_spectrum,_height,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x3120 : // cyzx + res.assign(_spectrum,_height,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3201 : // czxy + res.assign(_spectrum,_depth,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3210 : // czyx + res.assign(_spectrum,_depth,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++); + break; + } + } + if (!res) + throw CImgArgumentException(_cimg_instance + "permute_axes(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + return res; + } + + //! Unroll pixel values along specified axis. + /** + \param axis Unroll axis (can be \c 'x', \c 'y', \c 'z' or c 'c'). + **/ + CImg& unroll(const char axis) { + const unsigned int siz = (unsigned int)size(); + if (siz) switch (cimg::lowercase(axis)) { + case 'x' : _width = siz; _height = _depth = _spectrum = 1; break; + case 'y' : _height = siz; _width = _depth = _spectrum = 1; break; + case 'z' : _depth = siz; _width = _height = _spectrum = 1; break; + case 'c' : _spectrum = siz; _width = _height = _depth = 1; break; + } + return *this; + } + + //! Unroll pixel values along specified axis \newinstance. + CImg get_unroll(const char axis) const { + return (+*this).unroll(axis); + } + + //! Rotate image with arbitrary angle. + /** + \param angle Rotation angle, in degrees. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. + Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \note The size of the image is modified. + **/ + CImg& rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle \newinstance. + CImg get_rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res; + const float nangle = cimg::mod(angle,360.f); + if (boundary_conditions!=1 && cimg::mod(nangle,90.f)==0) { // Optimized version for orthogonal angles + const int wm1 = width() - 1, hm1 = height() - 1; + const int iangle = (int)nangle/90; + switch (iangle) { + case 1 : { // 90 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(y,hm1 - x,z,c); + } break; + case 2 : { // 180 deg + res.assign(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - x,hm1 - y,z,c); + } break; + case 3 : { // 270 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - y,x,z,c); + } break; + default : // 0 deg + return *this; + } + } else { // Generic angle + const float + rad = (float)(nangle*cimg::PI/180.), + ca = (float)std::cos(rad), sa = (float)std::sin(rad), + ux = cimg::abs((_width - 1)*ca), uy = cimg::abs((_width - 1)*sa), + vx = cimg::abs((_height - 1)*sa), vy = cimg::abs((_height - 1)*ca), + w2 = 0.5f*(_width - 1), h2 = 0.5f*(_height - 1); + res.assign((int)cimg::round(1 + ux + vx),(int)cimg::round(1 + uy + vy),_depth,_spectrum); + const float rw2 = 0.5f*(res._width - 1), rh2 = 0.5f*(res._height - 1); + _rotate(res,nangle,interpolation,boundary_conditions,w2,h2,rw2,rh2); + } + return res; + } + + //! Rotate image with arbitrary angle, around a center point. + /** + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param interpolation Type of interpolation, { 0=nearest | 1=linear | 2=cubic | 3=mirror }. + \param boundary_conditions Boundary conditions, { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) { + return get_rotate(angle,cx,cy,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle, around a center point \newinstance. + CImg get_rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + _rotate(res,angle,interpolation,boundary_conditions,cx,cy,cx,cy); + return res; + } + + // [internal] Perform 2D rotation with arbitrary angle. + void _rotate(CImg& res, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, + const float rw2, const float rh2) const { + const float + rad = (float)(angle*cimg::PI/180.), + ca = (float)std::cos(rad), sa = (float)std::sin(rad); + + switch (boundary_conditions) { + case 3 : { // Mirror + + switch (interpolation) { + case 2 : { // Cubic interpolation + const float ww = 2.f*width(), hh = 2.f*height(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2, + mx = cimg::mod(w2 + xc*ca + yc*sa,ww), + my = cimg::mod(h2 - xc*sa + yc*ca,hh); + res(x,y,z,c) = _cubic_atXY_c(mx{ 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. + Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(u,v,w,nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) const { + if (is_empty()) return *this; + CImg res; + const float + w1 = _width - 1, h1 = _height - 1, d1 = _depth -1, + w2 = 0.5f*w1, h2 = 0.5f*h1, d2 = 0.5f*d1; + CImg R = CImg::rotation_matrix(u,v,w,angle); + const CImg + X = R*CImg(8,3,1,1, + 0.f,w1,w1,0.f,0.f,w1,w1,0.f, + 0.f,0.f,h1,h1,0.f,0.f,h1,h1, + 0.f,0.f,0.f,0.f,d1,d1,d1,d1); + float + xm, xM = X.get_shared_row(0).max_min(xm), + ym, yM = X.get_shared_row(1).max_min(ym), + zm, zM = X.get_shared_row(2).max_min(zm); + const int + dx = (int)cimg::round(xM - xm), + dy = (int)cimg::round(yM - ym), + dz = (int)cimg::round(zM - zm); + R.transpose(); + res.assign(1 + dx,1 + dy,1 + dz,_spectrum); + const float rw2 = 0.5f*dx, rh2 = 0.5f*dy, rd2 = 0.5f*dz; + _rotate(res,R,interpolation,boundary_conditions,w2,h2,d2,rw2,rh2,rd2); + return res; + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point. + /** + \param u X-coordinate of the 3D rotation axis. + \param v Y-coordinate of the 3D rotation axis. + \param w Z-coordinate of the 3D rotation axis. + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param cz Z-coordinate of the rotation center. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic | 3=mirror }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.f); + if (nangle==0.f) return *this; + return get_rotate(u,v,w,nangle,cx,cy,cz,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + CImg R = CImg::rotation_matrix(u,v,w,-angle); + _rotate(res,R,interpolation,boundary_conditions,cx,cy,cz,cx,cy,cz); + return res; + } + + // [internal] Perform 3D rotation with arbitrary axis and angle. + void _rotate(CImg& res, const CImg& R, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, const float d2, + const float rw2, const float rh2, const float rd2) const { + switch (boundary_conditions) { + case 3 : // Mirror + switch (interpolation) { + case 2 : { // Cubic interpolation + const float ww = 2.f*width(), hh = 2.f*height(), dd = 2.f*depth(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(res.size(),2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = cimg::mod((float)(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc),ww), + Y = cimg::mod((float)(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc),hh), + Z = cimg::mod((float)(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc),dd); + cimg_forC(res,c) res(x,y,z,c) = _cubic_atXYZ_c(X{ 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + template + CImg& warp(const CImg& p_warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + return get_warp(p_warp,mode,interpolation,boundary_conditions).move_to(*this); + } + + //! Warp image content by a warping field \newinstance + template + CImg get_warp(const CImg& p_warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty() || !p_warp) return *this; + if (mode && !is_sameXYZ(p_warp)) + throw CImgArgumentException(_cimg_instance + "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) " + "have different XYZ dimensions.", + cimg_instance, + p_warp._width,p_warp._height,p_warp._depth,p_warp._spectrum,p_warp._data); + + CImg res(p_warp._width,p_warp._height,p_warp._depth,_spectrum); + + if (p_warp._spectrum==1) { // 1D warping + if (mode>=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),x + (float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),(float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)), Y = y + (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)), Y = (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=3) { // Forward-relative warp + res.fill((T)0); + if (interpolation>=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++), + z + (float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = x + (int)cimg::round(*(ptrs0++)), + Y = y + (int)cimg::round(*(ptrs1++)), + Z = z + (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z=1) // Linear interpolation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(res.size(),4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = p_warp.data(0,y,z,0), *ptrs1 = p_warp.data(0,y,z,1), *ptrs2 = p_warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = (int)cimg::round(*(ptrs0++)), + Y = (int)cimg::round(*(ptrs1++)), + Z = (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) const { + if (is_empty() || _depth<2) return +*this; + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + const CImg + img_xy = get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1), + img_zy = get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).permute_axes("xzyc"). + resize(_depth,_height,1,-100,-1), + img_xz = get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1); + return CImg(_width + _depth,_height + _depth,1,_spectrum,cimg::min(img_xy.min(),img_zy.min(),img_xz.min())). + draw_image(0,0,img_xy).draw_image(img_xy._width,0,img_zy). + draw_image(0,img_xy._height,img_xz); + } + + //! Construct a 2D representation of a 3D image, with XY,XZ and YZ views \inplace. + CImg& projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) { + if (_depth<2) return *this; + return get_projections2d(x0,y0,z0).move_to(*this); + } + + //! Crop image region. + /** + \param x0 = X-coordinate of the upper-left crop rectangle corner. + \param y0 = Y-coordinate of the upper-left crop rectangle corner. + \param z0 = Z-coordinate of the upper-left crop rectangle corner. + \param c0 = C-coordinate of the upper-left crop rectangle corner. + \param x1 = X-coordinate of the lower-right crop rectangle corner. + \param y1 = Y-coordinate of the lower-right crop rectangle corner. + \param z1 = Z-coordinate of the lower-right crop rectangle corner. + \param c1 = C-coordinate of the lower-right crop rectangle corner. + \param boundary_conditions = Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + **/ + CImg& crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const unsigned int boundary_conditions=0) { + return get_crop(x0,y0,z0,c0,x1,y1,z1,c1,boundary_conditions).move_to(*this); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "crop(): Empty instance.", + cimg_instance); + const int + nx0 = x0=0 && nx1=0 && ny1=0 && nz1=0 && nc1 res(1U + nx1 - nx0,1U + ny1 - ny0,1U + nz1 - nz0,1U + nc1 - nc0); + if (nx0<0 || nx1>=width() || ny0<0 || ny1>=height() || nz0<0 || nz1>=depth() || nc0<0 || nc1>=spectrum()) + switch (_boundary_conditions) { + case 3 : { // Mirror + const int w2 = 2*width(), h2 = 2*height(), d2 = 2*depth(), s2 = 2*spectrum(); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) { + const int + mx = cimg::mod(nx0 + x,w2), + my = cimg::mod(ny0 + y,h2), + mz = cimg::mod(nz0 + z,d2), + mc = cimg::mod(nc0 + c,s2); + res(x,y,z,c) = (*this)(mx=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) { + res(x,y,z,c) = (*this)(cimg::mod(nx0 + x,width()),cimg::mod(ny0 + y,height()), + cimg::mod(nz0 + z,depth()),cimg::mod(nc0 + c,spectrum())); + } + } break; + case 1 : // Neumann + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(res,x,y,z,c) res(x,y,z,c) = _atXYZC(nx0 + x,ny0 + y,nz0 + z,nc0 + c); + break; + default : // Dirichlet + res.fill((T)0).draw_image(-nx0,-ny0,-nz0,-nc0,*this); + } + else res.draw_image(-nx0,-ny0,-nz0,-nc0,*this); + return res; + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const unsigned int boundary_conditions=0) { + return crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const unsigned int boundary_conditions=0) const { + return get_crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, + const int x1, const int y1, + const unsigned int boundary_conditions=0) { + return crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, + const int x1, const int y1, + const unsigned int boundary_conditions=0) const { + return get_crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int x1, const unsigned int boundary_conditions=0) { + return crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int x1, const unsigned int boundary_conditions=0) const { + return get_crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Autocrop image region, regarding the specified background value. + CImg& autocrop(const T& value, const char *const axes="czyx") { + if (is_empty()) return *this; + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + const CImg coords = _autocrop(value,axis); + if (coords[0]==-1 && coords[1]==-1) return assign(); // Image has only 'value' pixels + else switch (axis) { + case 'x' : { + const int x0 = coords[0], x1 = coords[1]; + if (x0>=0 && x1>=0) crop(x0,x1); + } break; + case 'y' : { + const int y0 = coords[0], y1 = coords[1]; + if (y0>=0 && y1>=0) crop(0,y0,_width - 1,y1); + } break; + case 'z' : { + const int z0 = coords[0], z1 = coords[1]; + if (z0>=0 && z1>=0) crop(0,0,z0,_width - 1,_height - 1,z1); + } break; + default : { + const int c0 = coords[0], c1 = coords[1]; + if (c0>=0 && c1>=0) crop(0,0,0,c0,_width - 1,_height - 1,_depth - 1,c1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background value \newinstance. + CImg get_autocrop(const T& value, const char *const axes="czyx") const { + return (+*this).autocrop(value,axes); + } + + //! Autocrop image region, regarding the specified background color. + /** + \param color Color used for the crop. If \c 0, color is guessed. + \param axes Axes used for the crop. + **/ + CImg& autocrop(const T *const color=0, const char *const axes="zyx") { + if (is_empty()) return *this; + if (!color) { // Guess color + const CImg col1 = get_vector_at(0,0,0); + const unsigned int w = _width, h = _height, d = _depth, s = _spectrum; + autocrop(col1,axes); + if (_width==w && _height==h && _depth==d && _spectrum==s) { + const CImg col2 = get_vector_at(w - 1,h - 1,d - 1); + autocrop(col2,axes); + } + return *this; + } + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + switch (axis) { + case 'x' : { + int x0 = width(), x1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'x'); + const int nx0 = coords[0], nx1 = coords[1]; + if (nx0>=0 && nx1>=0) { x0 = std::min(x0,nx0); x1 = std::max(x1,nx1); } + } + if (x0==width() && x1==-1) return assign(); else crop(x0,x1); + } break; + case 'y' : { + int y0 = height(), y1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'y'); + const int ny0 = coords[0], ny1 = coords[1]; + if (ny0>=0 && ny1>=0) { y0 = std::min(y0,ny0); y1 = std::max(y1,ny1); } + } + if (y0==height() && y1==-1) return assign(); else crop(0,y0,_width - 1,y1); + } break; + default : { + int z0 = depth(), z1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'z'); + const int nz0 = coords[0], nz1 = coords[1]; + if (nz0>=0 && nz1>=0) { z0 = std::min(z0,nz0); z1 = std::max(z1,nz1); } + } + if (z0==depth() && z1==-1) return assign(); else crop(0,0,z0,_width - 1,_height - 1,z1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background color \newinstance. + CImg get_autocrop(const T *const color=0, const char *const axes="zyx") const { + return (+*this).autocrop(color,axes); + } + + CImg _autocrop(const T& value, const char axis) const { + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { + int x0 = -1, x1 = -1; + cimg_forX(*this,x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x0 = x; x = width(); y = height(); z = depth(); c = spectrum(); } + if (x0>=0) { + for (int x = width() - 1; x>=0; --x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x1 = x; x = 0; y = height(); z = depth(); c = spectrum(); } + } + res = CImg::vector(x0,x1); + } break; + case 'y' : { + int y0 = -1, y1 = -1; + cimg_forY(*this,y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y0 = y; x = width(); y = height(); z = depth(); c = spectrum(); } + if (y0>=0) { + for (int y = height() - 1; y>=0; --y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y1 = y; x = width(); y = 0; z = depth(); c = spectrum(); } + } + res = CImg::vector(y0,y1); + } break; + case 'z' : { + int z0 = -1, z1 = -1; + cimg_forZ(*this,z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z0 = z; x = width(); y = height(); z = depth(); c = spectrum(); } + if (z0>=0) { + for (int z = depth() - 1; z>=0; --z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z1 = z; x = width(); y = height(); z = 0; c = spectrum(); } + } + res = CImg::vector(z0,z1); + } break; + default : { + int c0 = -1, c1 = -1; + cimg_forC(*this,c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c0 = c; x = width(); y = height(); z = depth(); c = spectrum(); } + if (c0>=0) { + for (int c = spectrum() - 1; c>=0; --c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c1 = c; x = width(); y = height(); z = depth(); c = 0; } + } + res = CImg::vector(c0,c1); + } + } + return res; + } + + //! Return specified image column. + /** + \param x0 Image column. + **/ + CImg get_column(const int x0) const { + return get_columns(x0,x0); + } + + //! Return specified image column \inplace. + CImg& column(const int x0) { + return columns(x0,x0); + } + + //! Return specified range of image columns. + /** + \param x0 Starting image column. + \param x1 Ending image column. + **/ + CImg& columns(const int x0, const int x1) { + return get_columns(x0,x1).move_to(*this); + } + + //! Return specified range of image columns \inplace. + CImg get_columns(const int x0, const int x1) const { + return get_crop(x0,0,0,0,x1,height() - 1,depth() - 1,spectrum() - 1); + } + + //! Return specified image row. + CImg get_row(const int y0) const { + return get_rows(y0,y0); + } + + //! Return specified image row \inplace. + /** + \param y0 Image row. + **/ + CImg& row(const int y0) { + return rows(y0,y0); + } + + //! Return specified range of image rows. + /** + \param y0 Starting image row. + \param y1 Ending image row. + **/ + CImg get_rows(const int y0, const int y1) const { + return get_crop(0,y0,0,0,width() - 1,y1,depth() - 1,spectrum() - 1); + } + + //! Return specified range of image rows \inplace. + CImg& rows(const int y0, const int y1) { + return get_rows(y0,y1).move_to(*this); + } + + //! Return specified image slice. + /** + \param z0 Image slice. + **/ + CImg get_slice(const int z0) const { + return get_slices(z0,z0); + } + + //! Return specified image slice \inplace. + CImg& slice(const int z0) { + return slices(z0,z0); + } + + //! Return specified range of image slices. + /** + \param z0 Starting image slice. + \param z1 Ending image slice. + **/ + CImg get_slices(const int z0, const int z1) const { + return get_crop(0,0,z0,0,width() - 1,height() - 1,z1,spectrum() - 1); + } + + //! Return specified range of image slices \inplace. + CImg& slices(const int z0, const int z1) { + return get_slices(z0,z1).move_to(*this); + } + + //! Return specified image channel. + /** + \param c0 Image channel. + **/ + CImg get_channel(const int c0) const { + return get_channels(c0,c0); + } + + //! Return specified image channel \inplace. + CImg& channel(const int c0) { + return channels(c0,c0); + } + + //! Return specified range of image channels. + /** + \param c0 Starting image channel. + \param c1 Ending image channel. + **/ + CImg get_channels(const int c0, const int c1) const { + return get_crop(0,0,0,c0,width() - 1,height() - 1,depth() - 1,c1); + } + + //! Return specified range of image channels \inplace. + CImg& channels(const int c0, const int c1) { + return get_channels(c0,c1).move_to(*this); + } + + //! Return stream line of a 2D or 3D vector field. + CImg get_streamline(const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false) const { + if (_spectrum!=2 && _spectrum!=3) + throw CImgInstanceException(_cimg_instance + "streamline(): Instance is not a 2D or 3D vector field.", + cimg_instance); + if (_spectrum==2) { + if (is_oriented_only) { + typename CImg::_functor4d_streamline2d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.f,_height - 1.f,0.f); + } else { + typename CImg::_functor4d_streamline2d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.f,_height - 1.f,0.f); + } + } + if (is_oriented_only) { + typename CImg::_functor4d_streamline3d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.f,_height - 1.f,_depth - 1.f); + } + typename CImg::_functor4d_streamline3d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.f,_height - 1.f,_depth - 1.f); + } + + //! Return stream line of a 3D vector field. + /** + \param func Vector field function. + \param x X-coordinate of the starting point of the streamline. + \param y Y-coordinate of the starting point of the streamline. + \param z Z-coordinate of the starting point of the streamline. + \param L Streamline length. + \param dl Streamline length increment. + \param interpolation_type Type of interpolation. + Can be { 0=nearest int | 1=linear | 2=2nd-order RK | 3=4th-order RK. }. + \param is_backward_tracking Tells if the streamline is estimated forward or backward. + \param is_oriented_only Tells if the direction of the vectors must be ignored. + \param x0 X-coordinate of the first bounding-box vertex. + \param y0 Y-coordinate of the first bounding-box vertex. + \param z0 Z-coordinate of the first bounding-box vertex. + \param x1 X-coordinate of the second bounding-box vertex. + \param y1 Y-coordinate of the second bounding-box vertex. + \param z1 Z-coordinate of the second bounding-box vertex. + **/ + template + static CImg streamline(const tfunc& func, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + if (dl<=0) + throw CImgArgumentException("CImg<%s>::streamline(): Invalid specified integration length %g " + "(should be >0).", + pixel_type(), + dl); + + const bool is_bounded = (x0!=x1 || y0!=y1 || z0!=z1); + if (L<=0 || (is_bounded && (xx1 || yy1 || zz1))) return CImg(); + const unsigned int size_L = (unsigned int)cimg::round(L/dl + 1); + CImg coordinates(size_L,3); + const float dl2 = dl/2; + float + *ptr_x = coordinates.data(0,0), + *ptr_y = coordinates.data(0,1), + *ptr_z = coordinates.data(0,2), + pu = (float)(dl*func(x,y,z,0)), + pv = (float)(dl*func(x,y,z,1)), + pw = (float)(dl*func(x,y,z,2)), + X = x, Y = y, Z = z; + + switch (interpolation_type) { + case 0 : { // Nearest integer interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + const int + xi = (int)(X>0?X + 0.5f:X - 0.5f), + yi = (int)(Y>0?Y + 0.5f:Y - 0.5f), + zi = (int)(Z>0?Z + 0.5f:Z - 0.5f); + float + u = (float)(dl*func((float)xi,(float)yi,(float)zi,0)), + v = (float)(dl*func((float)xi,(float)yi,(float)zi,1)), + w = (float)(dl*func((float)xi,(float)yi,(float)zi,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 1 : { // First-order interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u = (float)(dl*func(X,Y,Z,0)), + v = (float)(dl*func(X,Y,Z,1)), + w = (float)(dl*func(X,Y,Z,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 2 : { // Second order interpolation + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u = (float)(dl*func(X + u0,Y + v0,Z + w0,0)), + v = (float)(dl*func(X + u0,Y + v0,Z + w0,1)), + w = (float)(dl*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + default : { // Fourth order interpolation + cimg_forX(coordinates,k) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,0)), + v1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,1)), + w1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u1*pu + v1*pv + w1*pw<0) { u1 = -u1; v1 = -v1; w1 = -w1; } + float + u2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,0)), + v2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,1)), + w2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u2 = -u2; v2 = -v2; w2 = -w2; } + float + u3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,0)), + v3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,1)), + w3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u3 = -u3; v3 = -v3; w3 = -w3; } + const float + u = (u0 + u3)/3 + (u1 + u2)/1.5f, + v = (v0 + v3)/3 + (v1 + v2)/1.5f, + w = (w0 + w3)/3 + (w1 + w2)/1.5f; + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } + } + if (ptr_x!=coordinates.data(0,1)) coordinates.resize((int)(ptr_x-coordinates.data()),3,1,1,0); + return coordinates; + } + + //! Return stream line of a 3D vector field \overloading. + static CImg streamline(const char *const expression, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=true, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + _functor4d_streamline_expr func(expression); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,is_oriented_only,x0,y0,z0,x1,y1,z1); + } + + struct _functor4d_streamline2d_directed { + const CImg& ref; + _functor4d_streamline2d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return c<2?(float)ref._linear_atXY(x,y,(int)z,c):0; + } + }; + + struct _functor4d_streamline3d_directed { + const CImg& ref; + _functor4d_streamline3d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref._linear_atXYZ(x,y,z,c); + } + }; + + struct _functor4d_streamline2d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline2d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,1,2); } + ~_functor4d_streamline2d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign2d(i,j) \ + if (I(i,j,0)*I(0,0,0) + I(i,j,1)*I(0,0,1)<0) { I(i,j,0) = -I(i,j,0); I(i,j,1) = -I(i,j,1); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z; + const float + dx = x - xi, + dy = y - yi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + I(0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,1) = (float)ref(xi,yi,zi,1); + I(1,0,0) = (float)ref(nxi,yi,zi,0); I(1,0,1) = (float)ref(nxi,yi,zi,1); + I(1,1,0) = (float)ref(nxi,nyi,zi,0); I(1,1,1) = (float)ref(nxi,nyi,zi,1); + I(0,1,0) = (float)ref(xi,nyi,zi,0); I(0,1,1) = (float)ref(xi,nyi,zi,1); + _cimg_vecalign2d(1,0); _cimg_vecalign2d(1,1); _cimg_vecalign2d(0,1); + } + return c<2?(float)pI->_linear_atXY(dx,dy,0,c):0; + } + }; + + struct _functor4d_streamline3d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline3d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,2,3); } + ~_functor4d_streamline3d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign3d(i,j,k) if (I(i,j,k,0)*I(0,0,0,0) + I(i,j,k,1)*I(0,0,0,1) + I(i,j,k,2)*I(0,0,0,2)<0) { \ + I(i,j,k,0) = -I(i,j,k,0); I(i,j,k,1) = -I(i,j,k,1); I(i,j,k,2) = -I(i,j,k,2); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z - (z>=0?0:1), nzi = zi + 1; + const float + dx = x - xi, + dy = y - yi, + dz = z - zi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + if (zi<0) zi = 0; + if (nzi<0) nzi = 0; + if (zi>=ref.depth()) zi = ref.depth() - 1; + if (nzi>=ref.depth()) nzi = ref.depth() - 1; + I(0,0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,0,1) = (float)ref(xi,yi,zi,1); + I(0,0,0,2) = (float)ref(xi,yi,zi,2); I(1,0,0,0) = (float)ref(nxi,yi,zi,0); + I(1,0,0,1) = (float)ref(nxi,yi,zi,1); I(1,0,0,2) = (float)ref(nxi,yi,zi,2); + I(1,1,0,0) = (float)ref(nxi,nyi,zi,0); I(1,1,0,1) = (float)ref(nxi,nyi,zi,1); + I(1,1,0,2) = (float)ref(nxi,nyi,zi,2); I(0,1,0,0) = (float)ref(xi,nyi,zi,0); + I(0,1,0,1) = (float)ref(xi,nyi,zi,1); I(0,1,0,2) = (float)ref(xi,nyi,zi,2); + I(0,0,1,0) = (float)ref(xi,yi,nzi,0); I(0,0,1,1) = (float)ref(xi,yi,nzi,1); + I(0,0,1,2) = (float)ref(xi,yi,nzi,2); I(1,0,1,0) = (float)ref(nxi,yi,nzi,0); + I(1,0,1,1) = (float)ref(nxi,yi,nzi,1); I(1,0,1,2) = (float)ref(nxi,yi,nzi,2); + I(1,1,1,0) = (float)ref(nxi,nyi,nzi,0); I(1,1,1,1) = (float)ref(nxi,nyi,nzi,1); + I(1,1,1,2) = (float)ref(nxi,nyi,nzi,2); I(0,1,1,0) = (float)ref(xi,nyi,nzi,0); + I(0,1,1,1) = (float)ref(xi,nyi,nzi,1); I(0,1,1,2) = (float)ref(xi,nyi,nzi,2); + _cimg_vecalign3d(1,0,0); _cimg_vecalign3d(1,1,0); _cimg_vecalign3d(0,1,0); + _cimg_vecalign3d(0,0,1); _cimg_vecalign3d(1,0,1); _cimg_vecalign3d(1,1,1); _cimg_vecalign3d(0,1,1); + } + return (float)pI->_linear_atXYZ(dx,dy,dz,c); + } + }; + + struct _functor4d_streamline_expr { + _cimg_math_parser *mp; + ~_functor4d_streamline_expr() { mp->end(); delete mp; } + _functor4d_streamline_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,"streamline",CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)(*mp)(x,y,z,c); + } + }; + + //! Return a shared-memory image referencing a range of pixels of the image instance. + /** + \param x0 X-coordinate of the starting pixel. + \param x1 X-coordinate of the ending pixel. + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(x0,y0,z0,c0), + end = (ulongT)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of pixels of the image instance \const. + const CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(x0,y0,z0,c0), + end = (ulongT)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance. + /** + \param y0 Y-coordinate of the starting row. + \param y1 Y-coordinate of the ending row. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(0,y0,z0,c0), + end = (ulongT)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance \const. + const CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(0,y0,z0,c0), + end = (ulongT)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing one row of the image instance. + /** + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared-memory image referencing one row of the image instance \const. + const CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) const { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared memory image referencing a range of slices of the image instance. + /** + \param z0 Z-coordinate of the starting slice. + \param z1 Z-coordinate of the ending slice. + \param c0 C-coordinate. + **/ + CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) { + const ulongT + beg = (ulongT)offset(0,0,z0,c0), + end = (ulongT)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared memory image referencing a range of slices of the image instance \const. + const CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) const { + const ulongT + beg = (ulongT)offset(0,0,z0,c0), + end = (ulongT)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared-memory image referencing one slice of the image instance. + /** + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing one slice of the image instance \const. + const CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) const { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing a range of channels of the image instance. + /** + \param c0 C-coordinate of the starting channel. + \param c1 C-coordinate of the ending channel. + **/ + CImg get_shared_channels(const unsigned int c0, const unsigned int c1) { + const ulongT + beg = (ulongT)offset(0,0,0,c0), + end = (ulongT)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing a range of channels of the image instance \const. + const CImg get_shared_channels(const unsigned int c0, const unsigned int c1) const { + const ulongT + beg = (ulongT)offset(0,0,0,c0), + end = (ulongT)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing one channel of the image instance. + /** + \param c0 C-coordinate. + **/ + CImg get_shared_channel(const unsigned int c0) { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory image referencing one channel of the image instance \const. + const CImg get_shared_channel(const unsigned int c0) const { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory version of the image instance. + CImg get_shared() { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Return a shared-memory version of the image instance \const. + const CImg get_shared() const { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Split image into a list along specified axis. + /** + \param axis Splitting axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param nb Number of split parts. + \note + - If \c nb==0, instance image is split into blocs of egal values along the specified axis. + - If \c nb<=0, instance image is split into blocs of -\c nb pixel wide. + - If \c nb>0, instance image is split into \c nb blocs. + **/ + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + + if (nb<0) { // Split by bloc size + const unsigned int dp = (unsigned int)(nb?-nb:1); + switch (_axis) { + case 'x': { + if (_width>dp) { + res.assign(_width/dp + (_width%dp?1:0),1,1); + const unsigned int pe = _width - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _height*_depth*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(p,0,0,0,p + dp - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop((res._width - 1)*dp,0,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'y': { + if (_height>dp) { + res.assign(_height/dp + (_height%dp?1:0),1,1); + const unsigned int pe = _height - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_depth*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,p,0,0,_width - 1,p + dp - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop(0,(res._width - 1)*dp,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'z': { + if (_depth>dp) { + res.assign(_depth/dp + (_depth%dp?1:0),1,1); + const unsigned int pe = _depth - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_height*_spectrum>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,0,p,0,_width - 1,_height - 1,p + dp - 1,_spectrum - 1).move_to(res[p/dp]); + get_crop(0,0,(res._width - 1)*dp,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } break; + case 'c' : { + if (_spectrum>dp) { + res.assign(_spectrum/dp + (_spectrum%dp?1:0),1,1); + const unsigned int pe = _spectrum - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 && + _width*_height*_depth>=128)) + for (int p = 0; p<(int)pe; p+=dp) + get_crop(0,0,0,p,_width - 1,_height - 1,_depth - 1,p + dp - 1).move_to(res[p/dp]); + get_crop(0,0,0,(res._width - 1)*dp,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back()); + } else res.assign(*this); + } + } + } else if (nb>0) { // Split by number of (non-homogeneous) blocs + const unsigned int siz = _axis=='x'?_width:_axis=='y'?_height:_axis=='z'?_depth:_axis=='c'?_spectrum:0; + if ((unsigned int)nb>siz) + throw CImgArgumentException(_cimg_instance + "get_split(): Instance cannot be split along %c-axis into %u blocs.", + cimg_instance, + axis,nb); + if (nb==1) res.assign(*this); + else { + int err = (int)siz; + unsigned int _p = 0; + switch (_axis) { + case 'x' : { + cimg_forX(*this,p) if ((err-=nb)<=0) { + get_crop(_p,0,0,0,p,_height - 1,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'y' : { + cimg_forY(*this,p) if ((err-=nb)<=0) { + get_crop(0,_p,0,0,_width - 1,p,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'z' : { + cimg_forZ(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,_p,0,_width - 1,_height - 1,p,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'c' : { + cimg_forC(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,0,_p,_width - 1,_height - 1,_depth - 1,p).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } + } + } + } else { // Split by egal values according to specified axis + T current = *_data; + switch (_axis) { + case 'x' : { + int i0 = 0; + cimg_forX(*this,i) + if ((*this)(i)!=current) { get_columns(i0,i - 1).move_to(res); i0 = i; current = (*this)(i); } + get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + int i0 = 0; + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { get_rows(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,i); } + get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + int i0 = 0; + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { get_slices(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,i); } + get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + int i0 = 0; + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { get_channels(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,0,i); } + get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + longT i0 = 0; + cimg_foroff(*this,i) + if ((*this)[i]!=current) { + CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = (longT)i; current = (*this)[i]; + } + CImg(_data + i0,1,(unsigned int)(size() - i0)).move_to(res); + } + } + } + return res; + } + + //! Split image into a list of sub-images, according to a specified splitting value sequence and optionally axis. + /** + \param values Splitting value sequence. + \param axis Axis along which the splitting is performed. Can be '0' to ignore axis. + \param keep_values Tells if the splitting sequence must be kept in the split blocs. + **/ + template + CImgList get_split(const CImg& values, const char axis=0, const bool keep_values=true) const { + typedef _cimg_Tt Tt; + + CImgList res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + if (!vsiz) return CImgList(*this); + if (vsiz==1) { // Split according to a single value + const T value = (T)*values; + switch (_axis) { + case 'x' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_width && (*this)(i)==value) ++i; + if (i>i0) { if (keep_values) get_columns(i0,i - 1).move_to(res); i0 = i; } + while (i<_width && (*this)(i)!=value) ++i; + if (i>i0) { get_columns(i0,i - 1).move_to(res); i0 = i; } + } while (i<_width); + } break; + case 'y' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_height && (*this)(0,i)==value) ++i; + if (i>i0) { if (keep_values) get_rows(i0,i - 1).move_to(res); i0 = i; } + while (i<_height && (*this)(0,i)!=value) ++i; + if (i>i0) { get_rows(i0,i - 1).move_to(res); i0 = i; } + } while (i<_height); + } break; + case 'z' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_depth && (*this)(0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_slices(i0,i - 1).move_to(res); i0 = i; } + while (i<_depth && (*this)(0,0,i)!=value) ++i; + if (i>i0) { get_slices(i0,i - 1).move_to(res); i0 = i; } + } while (i<_depth); + } break; + case 'c' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_spectrum && (*this)(0,0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_channels(i0,i - 1).move_to(res); i0 = i; } + while (i<_spectrum && (*this)(0,0,0,i)!=value) ++i; + if (i>i0) { get_channels(i0,i - 1).move_to(res); i0 = i; } + } while (i<_spectrum); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i = 0; + do { + while (ii0) { + if (keep_values) CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = i; + } + while (ii0) { CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; } + } while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_columns(i0,i1 - 1).move_to(res); + if (keep_values) get_columns(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_width); + if (i0<_width) get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_height && (Tt)(*this)(0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_rows(i0,i1 - 1).move_to(res); + if (keep_values) get_rows(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_height); + if (i0<_height) get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_depth && (Tt)(*this)(0,0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_slices(i0,i1 - 1).move_to(res); + if (keep_values) get_slices(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_depth); + if (i0<_depth) get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)(0,0,0,i)==(Tt)*values) { + i1 = i; j = 0; + while (i<_spectrum && (Tt)(*this)(0,0,0,i)==(Tt)values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_channels(i0,i1 - 1).move_to(res); + if (keep_values) get_channels(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_spectrum); + if (i0<_spectrum) get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i1 = 0, i = 0; + do { + if ((Tt)(*this)[i]==(Tt)*values) { + i1 = i; j = 0; + while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) CImg(_data + i0,1,(unsigned int)(i1 - i0)).move_to(res); + if (keep_values) CImg(_data + i1,1,(unsigned int)(i - i1)).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i(_data + i0,1,(unsigned int)(siz - i0)).move_to(res); + } break; + } + } + return res; + } + + //! Append two images along specified axis. + /** + \param img Image to append with instance image. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Append alignment in \c [0,1]. + **/ + template + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,true).insert(img).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \specialization. + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,img,true).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \const. + template + CImg<_cimg_Tt> get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList<_cimg_Tt>(*this,true).insert(img).get_append(axis,align); + } + + //! Append two images along specified axis \specialization. + CImg get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList(*this,img,true).get_append(axis,align); + } + + //@} + //--------------------------------------- + // + //! \name Filtering / Transforms + //@{ + //--------------------------------------- + + //! Correlate image by a kernel. + /** + \param kernel = the correlation kernel. + \param boundary_conditions Boundary condition. Can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. + \param is_normalized = enable local normalization. + \param channel mode Channel processing mode. Can be { 0=sum inputs | 1=one-for-one | 2=expand } + \param xcenter X-coordinate of the kernel center (~0U means 'centered'). + \param xstart Starting X-coordinate of the instance image. + \param xend Ending X-coordinate of the instance image. + \param xstride Stride along the X-axis. + \param xdilation Dilation along the X-axis. + \param ycenter Y-coordinate of the kernel center (~0U means 'centered'). + \param ystart Starting Y-coordinate of the instance image. + \param yend Ending Y-coordinate of the instance image. + \param ystride Stride along the Y-axis. + \param ydilation Dilation along the Y-axis. + \param zcenter Z-coordinate of the kernel center (~0U means 'centered'). + \param zstart Starting Z-coordinate of the instance image. + \param zend Ending Z-coordinate of the instance image. + \param zstride Stride along the Z-axis. + \param zdilation Dilation along the Z-axis. + \note + - The correlation of the image instance \p *this by the kernel \p kernel is defined to be: + res(x,y,z) = sum_{i,j,k} (*this)(\alpha_x\;x + \beta_x\;(i - c_x),\alpha_y\;y + \beta_y\;(j - + c_y),\alpha_z\;z + \beta_z\;(k - c_z))*kernel(i,j,k). + **/ + template + CImg& correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) { + if (is_empty() || !kernel) return *this; + return get_correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation).move_to(*this); + } + + template + CImg<_cimg_Ttfloat> get_correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, + const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, + const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) const { + return _correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation,false); + } + + //! Correlate image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> _correlate(const CImg& kernel, const unsigned int boundary_conditions, + const bool is_normalized, const unsigned int channel_mode, + const unsigned int xcenter, const unsigned int ycenter, const unsigned int zcenter, + const unsigned int xstart, const unsigned int ystart, const unsigned zstart, + const unsigned int xend, const unsigned int yend, const unsigned int zend, + const float xstride, const float ystride, const float zstride, + const float xdilation, const float ydilation, const float zdilation, + const bool is_convolve) const { + if (is_empty() || !kernel) return *this; + typedef _cimg_Ttfloat Ttfloat; + CImg res; + _cimg_abort_init_openmp; + cimg_abort_init; + + if (xstart>xend || ystart>yend || zstart>zend) + throw CImgArgumentException(_cimg_instance + "%s(): Invalid xyz-start/end arguments (start = (%u,%u,%u), end = (%u,%u,%u)).", + cimg_instance, + is_convolve?"convolve":"correlate", + xstart,ystart,zstart,xend,yend,zend); + if (xstride<=0 || ystride<=0 || zstride<=0) + throw CImgArgumentException(_cimg_instance + "%s(): Invalid stride arguments (%g,%g,%g).", + cimg_instance, + is_convolve?"convolve":"correlate", + xstride,ystride,zstride); + const int + _xstart = (int)std::min(xstart,_width - 1), + _ystart = (int)std::min(ystart,_height - 1), + _zstart = (int)std::min(zstart,_depth - 1), + _xend = (int)std::min(xend,_width - 1), + _yend = (int)std::min(yend,_height - 1), + _zend = (int)std::min(zend,_depth - 1), + nwidth = 1 + (int)std::floor((_xend - _xstart)/xstride), + nheight = 1 + (int)std::floor((_yend - _ystart)/ystride), + ndepth = 1 + (int)std::floor((_zend + _zstart)/zstride), + _xstride = (int)cimg::round(xstride), + _ystride = (int)cimg::round(ystride), + _zstride = (int)cimg::round(zstride); + + const ulongT + res_whd = (ulongT)nwidth*nheight*ndepth, + res_size = res_whd*res._spectrum; + const bool + is_inner_parallel = res_whd>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res_size>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + + int + _xcenter = xcenter==~0U?kernel.width()/2 - 1 + (kernel.width()%2):(int)std::min(xcenter,kernel._width - 1), + _ycenter = ycenter==~0U?kernel.height()/2 - 1 + (kernel.height()%2):(int)std::min(ycenter,kernel._height - 1), + _zcenter = zcenter==~0U?kernel.depth()/2 - 1 + (kernel.depth()%2):(int)std::min(zcenter,kernel._depth - 1), + _xdilation = (int)cimg::round(xdilation), + _ydilation = (int)cimg::round(ydilation), + _zdilation = (int)cimg::round(zdilation); + + const bool is_int_stride_dilation = + xstride==_xstride && ystride==_ystride && zstride==_zstride && + xdilation==_xdilation && ydilation==_ydilation && zdilation==_zdilation; + + CImg _kernel; + if (is_convolve) { // If convolution, go back to correlation + _kernel = CImg(kernel._data,kernel.size()/kernel._spectrum,1,1,kernel._spectrum,true). + get_mirror('x').resize(kernel,-1); + _xcenter = kernel.width() - 1 - _xcenter; + _ycenter = kernel.height() - 1 - _ycenter; + _zcenter = kernel.depth() - 1 - _zcenter; + } else _kernel = kernel.get_shared(); + + if (_kernel._width==_kernel._height && _kernel._width>1 && _kernel._height>1 && + ((_kernel._depth==1 && _kernel._width<=5) || (_kernel._depth==_kernel._width && _kernel._width<=3)) && + boundary_conditions<=1 && channel_mode && + _xcenter==_kernel.width()/2 - 1 + (_kernel.width()%2) && + _ycenter==_kernel.height()/2 - 1 + (_kernel.height()%2) && + _zcenter==_kernel.depth()/2 - 1 + (_kernel.depth()%2) && + is_int_stride_dilation && _xdilation>=0 && _ydilation>=0 && _zdilation>=0) { + + // Optimized versions for centered 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 kernels. + const int dw = 1 - (_kernel.width()%2), dh = 1 - (_kernel.height()%2), dd = 1 - (_kernel.depth()%2); + if (dw || dh || dd) // Force kernel size to be odd + _kernel.get_resize(_kernel.width() + dw,_kernel.height() + dh,_kernel.depth() + dd,_kernel.spectrum(), + 0,0,1,1,1).move_to(_kernel.assign()); + + if (!boundary_conditions) { // Dirichlet -> Add a 1px zero border, then use _correlate() with Neumann + const int + dx = _kernel._width==1?0:1, + dy = _kernel._height==1?0:1, + dz = _kernel._depth==1?0:1; + return get_crop(-dx,-dy,-dz,width() - 1 + dx,height() - 1 + dy,depth() - 1 + dz). + _correlate(_kernel,true,is_normalized,channel_mode,_xcenter,_ycenter,_zcenter, + _xstart + dx,_ystart + dy,_zstart + dz,_xend + dx,_yend + dy,_zend + dz, + xstride,ystride,zstride,xdilation,ydilation,zdilation,false); + + } else { // Neumann boundaries + res.assign(nwidth,nheight,ndepth,std::max(_spectrum,_kernel._spectrum)); + + switch (_kernel._depth) { + case 3 : { // 3x3x3 centered kernel + cimg_forC(res,c) { + cimg_abort_test; + const CImg I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + const int w1 = I.width() - 1, h1 = I.height() - 1, d1 = I.depth() - 1; + CImg _res = res.get_shared_channel(c); + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,Z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, z = _zstart + _zstride*Z, + px = x - _xdilation>0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?z - _zdilation:0, nz = z + _zdilation0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?z - _zdilation:0, nz = z + _zdilation I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + const int w1 = I.width() - 1, h1 = I.height() - 1; + CImg _res = res.get_shared_channel(c); + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, + px = x - _xdilation>0?x - _xdilation:0, bx = px - _xdilation>0?px - _xdilation:0, + nx = x + _xdilation0?y - _ydilation:0, by = py - _ydilation>0?py - _ydilation:0, + ny = y + _ydilation0?x - _xdilation:0, bx = px - _xdilation>0?px - _xdilation:0, + nx = x + _xdilation0?y - _ydilation:0, by = py - _ydilation>0?py - _ydilation:0, + ny = y + _ydilation I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(c%kernel._spectrum); + CImg _res = res.get_shared_channel(c); + const int w1 = I.width() - 1, h1 = I.height() - 1; + if (is_normalized) { + const Ttfloat M = (Ttfloat)K.magnitude(2), M2 = M*M; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(_res.size(),16384)) + cimg_forXYZ(res,X,Y,z) { + const int + x = _xstart + _xstride*X, y = _ystart + _ystride*Y, + px = x - _xdilation>0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation0?x - _xdilation:0, nx = x + _xdilation0?y - _ydilation:0, ny = y + _ydilation res0 = res.get_shared_channel(0); + for (int c = 1; c K = _kernel.get_shared_channel(kc%_kernel._spectrum); + int w2 = 0, h2 = 0, d2 = 0; + Ttfloat M = 0, M2 = 0; + if (is_normalized) { M = (Ttfloat)K.magnitude(2); M2 = M*M; } + if (boundary_conditions>=3) { w2 = 2*width(); h2 = 2*height(); d2 = 2*depth(); } + res.fill(0); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + cimg_forXYZC(res,x,y,z,c) { + Ttfloat _val, val = 0, N = 0; + + if (is_int_stride_dilation) + cimg_forXYZ(_kernel,p,q,r) { + const int + ix = (int)xstart + _xstride*x + _xdilation*(p - _xcenter), + iy = (int)ystart + _ystride*y + _ydilation*(q - _ycenter), + iz = (int)zstart + _zstride*z + _zdilation*(r - _zcenter); + switch (boundary_conditions) { + case 0 : _val = atXYZ(ix,iy,iz,c,0); break; // Dirichlet + case 1 : _val = _atXYZ(ix,iy,iz,c); break; // Neumann + case 2 : _val = (*this)(cimg::mod(ix,width()),cimg::mod(iy,height()), // Periodic + cimg::mod(iz,depth()),c); break; + default : { // Mirror + const int mx = cimg::mod(ix,w2), my = cimg::mod(iy,h2), mz = cimg::mod(iz,d2); + _val = (*this)(mx I = get_shared_channel(c%_spectrum); + const CImg K = _kernel.get_shared_channel(channel_mode==1?c%_kernel._spectrum:c/_spectrum); + int w2 = 0, h2 = 0, d2 = 0; + Ttfloat M = 0, M2 = 0; + if (is_normalized) { M = (Ttfloat)K.magnitude(2); M2 = M*M; } + if (boundary_conditions>=3) { w2 = 2*I.width(); h2 = 2*I.height(); d2 = 2*I.depth(); } + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + cimg_forXYZ(res,x,y,z) { + Ttfloat _val, val = 0, N = 0; + + if (is_int_stride_dilation) + cimg_forXYZ(_kernel,p,q,r) { + const int + ix = (int)xstart + _xstride*x + _xdilation*(p - _xcenter), + iy = (int)ystart + _ystride*y + _ydilation*(q - _ycenter), + iz = (int)zstart + _zstride*z + _zdilation*(r - _zcenter); + switch (boundary_conditions) { + case 0 : _val = I.atXYZ(ix,iy,iz,0,0); break; // Dirichlet + case 1 : _val = I._atXYZ(ix,iy,iz); break; // Neumann + case 2 : _val = I(cimg::mod(ix,I.width()),cimg::mod(iy,I.height()), // Periodic + cimg::mod(iz,I.depth())); break; + default : { // Mirror + const int mx = cimg::mod(ix,w2), my = cimg::mod(iy,h2), mz = cimg::mod(iz,d2); + _val = I(mx + CImg& convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) { + if (is_empty() || !kernel) return *this; + return get_convolve(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation).move_to(*this); + } + + //! Convolve image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> get_convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false, const unsigned int channel_mode=1, + const unsigned int xcenter=~0U, const unsigned int ycenter=~0U, + const unsigned int zcenter=~0U, + const unsigned int xstart=0, const unsigned int ystart=0, const unsigned zstart=0, + const unsigned int xend=~0U, const unsigned int yend=~0U, + const unsigned int zend=~0U, + const float xstride=1, const float ystride=1, const float zstride=1, + const float xdilation=1, const float ydilation=1, const float zdilation=1) const { + return _correlate(kernel,boundary_conditions,is_normalized,channel_mode, + xcenter,ycenter,zcenter,xstart,ystart,zstart,xend,yend,zend, + xstride,ystride,zstride,xdilation,ydilation,zdilation,true); + } + + //! Cumulate image values, optionally along specified axis. + /** + \param axis Cumulation axis. Set it to 0 to cumulate all values globally without taking axes into account. + **/ + CImg& cumulate(const char axis=0) { + switch (cimg::lowercase(axis)) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { + T *ptrd = data(0,y,z,c); + Tlong cumul = (Tlong)0; + cimg_forX(*this,x) { cumul+=(Tlong)*ptrd; *(ptrd++) = (T)cumul; } + } + break; + case 'y' : { + const ulongT w = (ulongT)_width; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 && + _width*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { + T *ptrd = data(x,0,z,c); + Tlong cumul = (Tlong)0; + cimg_forY(*this,y) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=w; } + } + } break; + case 'z' : { + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 && + _width*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { + T *ptrd = data(x,y,0,c); + Tlong cumul = (Tlong)0; + cimg_forZ(*this,z) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=wh; } + } + } break; + case 'c' : { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(_spectrum>=(cimg_openmp_sizefactor)*512 && _width*_height*_depth>=16)) + cimg_forXYZ(*this,x,y,z) { + T *ptrd = data(x,y,z,0); + Tlong cumul = (Tlong)0; + cimg_forC(*this,c) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=whd; } + } + } break; + default : { // Global cumulation + Tlong cumul = (Tlong)0; + cimg_for(*this,ptrd,T) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; } + } + } + return *this; + } + + //! Cumulate image values, optionally along specified axis \newinstance. + CImg get_cumulate(const char axis=0) const { + return CImg(*this,false).cumulate(axis); + } + + //! Cumulate image values, along specified axes. + /** + \param axes Cumulation axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& cumulate(const char *const axes) { + for (const char *s = axes; *s; ++s) cumulate(*s); + return *this; + } + + //! Cumulate image values, along specified axes \newinstance. + CImg get_cumulate(const char *const axes) const { + return CImg(*this,false).cumulate(axes); + } + + //! Erode image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the erosion in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& erode(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_erode(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Erode image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_erode(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) const { + if (is_empty() || !kernel) return *this; + if (!is_real && kernel==0) return CImg(width(),height(),depth(),spectrum(),0); + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = kernel.depth()/2, + mx1 = kernel.width() - mx2 - 1, my1 = kernel.height() - my2 - 1, mz1 = kernel.depth() - mz2 - 1, + mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2; + const bool + is_inner_parallel = _width*_height*_depth>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res.size()>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + _cimg_abort_init_openmp; + cimg_abort_init; + cimg_pragma_openmp(parallel for cimg_openmp_if(!is_inner_parallel && is_outer_parallel)) + cimg_forC(res,c) _cimg_abort_try_openmp { + cimg_abort_test; + const CImg img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real erosion + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img(x + xm,y + ym,z + zm) - mval); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img._atXYZ(x + xm,y + ym,z + zm) - mval); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) - mval); + if (cval::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img(x + xm,y + ym,z + zm); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img._atXYZ(x + xm,y + ym,z + zm); + if (cval=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval& erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) { + if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this; + if (sx>1 && _width>1) { // Along X-axis + const int L = width(), off = 1, s = (int)sx, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = buf._data, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; }} + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _height>1) { // Along Y-axis + const int L = height(), off = width(), s = (int)sy, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _depth>1) { // Along Z-axis + const int L = depth(), off = width()*height(), s = (int)sz, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::min(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val get_erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).erode(sx,sy,sz); + } + + //! Erode the image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& erode(const unsigned int s) { + return erode(s,s,s); + } + + //! Erode the image by a square structuring element of specified size \newinstance. + CImg get_erode(const unsigned int s) const { + return (+*this).erode(s); + } + + //! Dilate image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the dilation in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& dilate(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_dilate(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Dilate image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_dilate(const CImg& kernel, const bool boundary_conditions=true, + const bool is_real=false) const { + if (is_empty() || !kernel || (!is_real && kernel==0)) return *this; + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx1 = kernel.width()/2, my1 = kernel.height()/2, mz1 = kernel.depth()/2, + mx2 = kernel.width() - mx1 - 1, my2 = kernel.height() - my1 - 1, mz2 = kernel.depth() - mz1 - 1, + mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2; + const bool + is_inner_parallel = _width*_height*_depth>=(cimg_openmp_sizefactor)*32768, + is_outer_parallel = res.size()>=(cimg_openmp_sizefactor)*32768; + cimg::unused(is_inner_parallel,is_outer_parallel); + _cimg_abort_init_openmp; + cimg_abort_init; + cimg_pragma_openmp(parallel for cimg_openmp_if(!is_inner_parallel && is_outer_parallel)) + cimg_forC(res,c) _cimg_abort_try_openmp { + cimg_abort_test; + const CImg img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real dilation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } _cimg_abort_catch_openmp2 + if (boundary_conditions) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img._atXYZ(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(*this,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const t mval = K(mx2 - xm,my2 - ym,mz2 - zm); + const Tt cval = (Tt)(img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + } else { // Binary dilation + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(is_inner_parallel)) + for (int z = mz1; z::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } _cimg_abort_catch_openmp2 + if (boundary_conditions) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img._atXYZ(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(is_inner_parallel)) + cimg_forYZ(res,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx2 - xm,my2 - ym,mz2 - zm)) { + const Tt cval = (Tt)img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } _cimg_abort_catch_openmp2 + } + } _cimg_abort_catch_openmp + cimg_abort_test; + return res; + } + + //! Dilate image by a rectangular structuring element of specified size. + /** + \param sx Width of the structuring element. + \param sy Height of the structuring element. + \param sz Depth of the structuring element. + **/ + CImg& dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) { + if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this; + if (sx>1 && _width>1) { // Along X-axis + const int L = width(), off = 1, s = (int)sx, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(0,y,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + if (sy>1 && _height>1) { // Along Y-axis + const int L = height(), off = width(), s = (int)sy, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,0,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + if (sz>1 && _depth>1) { // Along Z-axis + const int L = depth(), off = width()*height(), s = (int)sz, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::max(cur,*ptrse); cimg_forX(buf,k) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,y,0,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + return *this; + } + + //! Dilate image by a rectangular structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).dilate(sx,sy,sz); + } + + //! Dilate image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& dilate(const unsigned int s) { + return dilate(s,s,s); + } + + //! Dilate image by a square structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int s) const { + return (+*this).dilate(s); + } + + //! Compute watershed transform. + /** + \param priority Priority map. + \param is_high_connectivity Boolean that choose between 4(false)- or 8(true)-connectivity + in 2D case, and between 6(false)- or 26(true)-connectivity in 3D case. + \note Non-zero values of the instance instance are propagated to zero-valued ones according to + specified the priority map. + **/ + template + CImg& watershed(const CImg& priority, const bool is_high_connectivity=false) { +#define _cimg_watershed_init(cond,X,Y,Z) \ + if (cond && !(*this)(X,Y,Z)) Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,nb_seeds) + +#define _cimg_watershed_propagate(cond,X,Y,Z) \ + if (cond) { \ + if ((*this)(X,Y,Z)) { \ + ns = labels(X,Y,Z) - 1; xs = seeds(ns,0); ys = seeds(ns,1); zs = seeds(ns,2); \ + d = cimg::sqr((float)x - xs) + cimg::sqr((float)y - ys) + cimg::sqr((float)z - zs); \ + if (d labels(_width,_height,_depth,1,0), seeds(64,3); + CImg::type> Q; + unsigned int sizeQ = 0; + int px, nx, py, ny, pz, nz; + bool is_px, is_nx, is_py, is_ny, is_pz, is_nz; + const bool is_3d = _depth>1; + + // Find seed points and insert them in priority queue. + unsigned int nb_seeds = 0; + const T *ptrs = _data; + cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) { // 3D version + if (nb_seeds>=seeds._width) seeds.resize(2*seeds._width,3,1,1,0); + seeds(nb_seeds,0) = x; seeds(nb_seeds,1) = y; seeds(nb_seeds++,2) = z; + px = x - 1; nx = x + 1; + py = y - 1; ny = y + 1; + pz = z - 1; nz = z + 1; + is_px = px>=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz::inf(); + T nlabel = (T)0; + _cimg_watershed_propagate(is_px,px,y,z); + _cimg_watershed_propagate(is_nx,nx,y,z); + _cimg_watershed_propagate(is_py,x,py,z); + _cimg_watershed_propagate(is_ny,x,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_pz,x,y,pz); + _cimg_watershed_propagate(is_nz,x,y,nz); + } + if (is_high_connectivity) { + _cimg_watershed_propagate(is_px && is_py,px,py,z); + _cimg_watershed_propagate(is_nx && is_py,nx,py,z); + _cimg_watershed_propagate(is_px && is_ny,px,ny,z); + _cimg_watershed_propagate(is_nx && is_ny,nx,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_px && is_pz,px,y,pz); + _cimg_watershed_propagate(is_nx && is_pz,nx,y,pz); + _cimg_watershed_propagate(is_px && is_nz,px,y,nz); + _cimg_watershed_propagate(is_nx && is_nz,nx,y,nz); + _cimg_watershed_propagate(is_py && is_pz,x,py,pz); + _cimg_watershed_propagate(is_ny && is_pz,x,ny,pz); + _cimg_watershed_propagate(is_py && is_nz,x,py,nz); + _cimg_watershed_propagate(is_ny && is_nz,x,ny,nz); + _cimg_watershed_propagate(is_px && is_py && is_pz,px,py,pz); + _cimg_watershed_propagate(is_nx && is_py && is_pz,nx,py,pz); + _cimg_watershed_propagate(is_px && is_ny && is_pz,px,ny,pz); + _cimg_watershed_propagate(is_nx && is_ny && is_pz,nx,ny,pz); + _cimg_watershed_propagate(is_px && is_py && is_nz,px,py,nz); + _cimg_watershed_propagate(is_nx && is_py && is_nz,nx,py,nz); + _cimg_watershed_propagate(is_px && is_ny && is_nz,px,ny,nz); + _cimg_watershed_propagate(is_nx && is_ny && is_nz,nx,ny,nz); + } + } + (*this)(x,y,z) = nlabel; + labels(x,y,z) = ++nmin; + } + return *this; + } + + //! Compute watershed transform \newinstance. + template + CImg get_watershed(const CImg& priority, const bool is_high_connectivity=false) const { + return (+*this).watershed(priority,is_high_connectivity); + } + + // [internal] Insert/Remove items in priority queue, for watershed/distance transforms. + template + bool _priority_queue_insert(CImg& is_queued, unsigned int& siz, const tv value, + const unsigned int x, const unsigned int y, const unsigned int z, + const unsigned int n=1) { + if (is_queued(x,y,z)) return false; + is_queued(x,y,z) = (tq)n; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; + (*this)(siz - 1,1) = (T)x; + (*this)(siz - 1,2) = (T)y; + (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(tv)(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); + cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); + cimg::swap((*this)(pos,3),(*this)(par,3)); + } + return true; + } + + CImg& _priority_queue_remove(unsigned int& siz) { + (*this)(0,0) = (*this)(--siz,0); + (*this)(0,1) = (*this)(siz,1); + (*this)(0,2) = (*this)(siz,2); + (*this)(0,3) = (*this)(siz,3); + const float value = (*this)(0,0); + unsigned int pos = 0, swap = 0; + do { + const unsigned int left = 2*pos + 1, right = left + 1; + if (right(*this)(right,0)?left:right; + else if (left{ 0=smooth-filter | 1=1st-derivative | 2=2nd-derivative }. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + **/ + CImg& deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) { +#define _cimg_deriche_apply \ + CImg Y(N); \ + double *ptrY = Y._data, yb = 0, yp = 0; \ + T xp = (T)0; \ + if (boundary_conditions) { xp = *ptrX; yb = yp = (double)(coefp*xp); } \ + for (int m = 0; m=0; --n) { \ + const T xc = *(ptrX-=off); \ + const double yc = (double)(a2*xn + a3*xa - b1*yn - b2*ya); \ + xa = xn; xn = xc; ya = yn; yn = yc; \ + *ptrX = (T)(*(--ptrY)+yc); \ + } + const char naxis = cimg::lowercase(axis); + const double nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width: + naxis=='y'?_height: + naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.1f && !order)) return *this; + const double + nnsigma = nsigma<0.1f?0.1f:nsigma, + alpha = 1.695f/nnsigma, + ema = std::exp(-alpha), + ema2 = std::exp(-2*alpha), + b1 = -2*ema, + b2 = ema2; + double a0 = 0, a1 = 0, a2 = 0, a3 = 0, coefp = 0, coefn = 0; + switch (order) { + case 0 : { + const double k = (1-ema)*(1-ema)/(1 + 2*alpha*ema-ema2); + a0 = k; + a1 = k*(alpha - 1)*ema; + a2 = k*(alpha + 1)*ema; + a3 = -k*ema2; + } break; + case 1 : { + const double k = -(1-ema)*(1-ema)*(1-ema)/(2*(ema + 1)*ema); + a0 = a3 = 0; + a1 = k*ema; + a2 = -a1; + } break; + case 2 : { + const double + ea = std::exp(-alpha), + k = -(ema2 - 1)/(2*alpha*ema), + kn = (-2*(-1 + 3*ea - 3*ea*ea + ea*ea*ea)/(3*ea + 1 + 3*ea*ea + ea*ea*ea)); + a0 = kn; + a1 = -kn*(1 + k*alpha)*ema; + a2 = kn*(1 - k*alpha)*ema; + a3 = -kn*ema2; + } break; + default : + throw CImgArgumentException(_cimg_instance + "deriche(): Invalid specified filter order %u " + "(should be { 0=smoothing | 1=1st-derivative | 2=2nd-derivative }).", + cimg_instance, + order); + } + coefp = (a0 + a1)/(1 + b1 + b2); + coefn = (a2 + a3)/(1 + b1 + b2); + switch (naxis) { + case 'x' : { + const int N = width(); + const ulongT off = 1U; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { T *ptrX = data(0,y,z,c); _cimg_deriche_apply; } + } break; + case 'y' : { + const int N = height(); + const ulongT off = (ulongT)_width; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { T *ptrX = data(x,0,z,c); _cimg_deriche_apply; } + } break; + case 'z' : { + const int N = depth(); + const ulongT off = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { T *ptrX = data(x,y,0,c); _cimg_deriche_apply; } + } break; + default : { + const int N = spectrum(); + const ulongT off = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) { T *ptrX = data(x,y,z,0); _cimg_deriche_apply; } + } + } + return *this; + } + + //! Apply recursive Deriche filter \newinstance. + CImg get_deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).deriche(sigma,order,axis,boundary_conditions); + } + + // [internal] Apply a recursive filter (used by CImg::vanvliet()). + /* + \param ptr the pointer of the data + \param filter the coefficient of the filter in the following order [n,n - 1,n - 2,n - 3]. + \param N size of the data + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivative, 2nd derivative, 3rd derivative + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note Boundary condition using B. Triggs method (IEEE trans on Sig Proc 2005). + */ + static void _cimg_recursive_apply(T *data, const double filter[], const int N, const ulongT off, + const unsigned int order, const bool boundary_conditions) { + double val[4] = { 0 }; // res[n,n - 1,n - 2,n - 3,..] or res[n,n + 1,n + 2,n + 3,..] + const double + sumsq = filter[0], sum = sumsq * sumsq, + a1 = filter[1], a2 = filter[2], a3 = filter[3], + scaleM = 1. / ( (1. + a1 - a2 + a3) * (1. - a1 - a2 - a3) * (1. + a2 + (a1 - a3) * a3) ); + double M[9]; // Triggs matrix + M[0] = scaleM * (-a3 * a1 + 1. - a3 * a3 - a2); + M[1] = scaleM * (a3 + a1) * (a2 + a3 * a1); + M[2] = scaleM * a3 * (a1 + a3 * a2); + M[3] = scaleM * (a1 + a3 * a2); + M[4] = -scaleM * (a2 - 1.) * (a2 + a3 * a1); + M[5] = -scaleM * a3 * (a3 * a1 + a3 * a3 + a2 - 1.); + M[6] = scaleM * (a3 * a1 + a2 + a1 * a1 - a2 * a2); + M[7] = scaleM * (a1 * a2 + a3 * a2 * a2 - a1 * a3 * a3 - a3 * a3 * a3 - a3 * a2 + a3); + M[8] = scaleM * a3 * (a1 + a3 * a2); + switch (order) { + case 0 : { + const double iplus = (boundary_conditions?data[(N - 1)*off]:(T)0); + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 1; k<4; ++k) val[k] = (boundary_conditions?*data/sumsq:0); + } else { + // Apply Triggs boundary conditions + const double + uplus = iplus/(1. - a1 - a2 - a3), vplus = uplus/(1. - a1 - a2 - a3), + unp = val[1] - uplus, unp1 = val[2] - uplus, unp2 = val[3] - uplus; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2 + vplus) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2 + vplus) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2 + vplus) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) val[k] = val[k - 1]; + } + if (!pass) data -= off; + } + } break; + case 1 : { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + } else { data-=off;} + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 2: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 3: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + // Apply Triggs boundary conditions + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + } + } + + //! Van Vliet recursive Gaussian filter. + /** + \param sigma standard deviation of the Gaussian filter + \param order the order of the filter 0,1,2,3 + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note dirichlet boundary condition has a strange behavior + + I.T. Young, L.J. van Vliet, M. van Ginkel, Recursive Gabor filtering. + IEEE Trans. Sig. Proc., vol. 50, pp. 2799-2805, 2002. + + (this is an improvement over Young-Van Vliet, Sig. Proc. 44, 1995) + + Boundary conditions (only for order 0) using Triggs matrix, from + B. Triggs and M. Sdika. Boundary conditions for Young-van Vliet + recursive filtering. IEEE Trans. Signal Processing, + vol. 54, pp. 2365-2367, 2006. + **/ + CImg& vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) { + if (is_empty()) return *this; + if (!cimg::type::is_float()) + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions).move_to(*this); + const char naxis = cimg::lowercase(axis); + const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.5f && !order)) return *this; + const double + nnsigma = nsigma<0.5f?0.5f:nsigma, + m0 = 1.16680, m1 = 1.10783, m2 = 1.40586, + m1sq = m1 * m1, m2sq = m2 * m2, + q = (nnsigma<3.556?-0.2568 + 0.5784*nnsigma + 0.0561*nnsigma*nnsigma:2.5091 + 0.9804*(nnsigma - 3.556)), + qsq = q * q, + scale = (m0 + q) * (m1sq + m2sq + 2 * m1 * q + qsq), + b1 = -q * (2 * m0 * m1 + m1sq + m2sq + (2 * m0 + 4 * m1) * q + 3 * qsq) / scale, + b2 = qsq * (m0 + 2 * m1 + 3 * q) / scale, + b3 = -qsq * q / scale, + B = ( m0 * (m1sq + m2sq) ) / scale; + double filter[4]; + filter[0] = B; filter[1] = -b1; filter[2] = -b2; filter[3] = -b3; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_recursive_apply(data(0,y,z,c),filter,_width,1U,order,boundary_conditions); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_recursive_apply(data(x,0,z,c),filter,_height,(ulongT)_width,order,boundary_conditions); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(ulongT)_width*_height, + order,boundary_conditions); + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions); + } + } + return *this; + } + + //! Blur image using Van Vliet recursive Gaussian filter. \newinstance. + CImg get_vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions); + } + + //! Blur image. + /** + \param sigma_x Standard deviation of the blur, along the X-axis. + \param sigma_y Standard deviation of the blur, along the Y-axis. + \param sigma_z Standard deviation of the blur, along the Z-axis. + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param is_gaussian Tells if the blur uses a gaussian (\c true) or quasi-gaussian (\c false) kernel. + \note + - The blur is computed as a 0-order Vanvliet (gaussian) or Deriche filter (quasi-gaussian). + - This is a recursive algorithm, not depending on the values of the standard deviations. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=true) { + if (is_empty()) return *this; + if (is_gaussian) { + if (_width>1) vanvliet(sigma_x,0,'x',boundary_conditions); + if (_height>1) vanvliet(sigma_y,0,'y',boundary_conditions); + if (_depth>1) vanvliet(sigma_z,0,'z',boundary_conditions); + } else { + if (_width>1) deriche(sigma_x,0,'x',boundary_conditions); + if (_height>1) deriche(sigma_y,0,'y',boundary_conditions); + if (_depth>1) deriche(sigma_z,0,'z',boundary_conditions); + } + return *this; + } + + //! Blur image \newinstance. + CImg get_blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=true) const { + return CImg(*this,false).blur(sigma_x,sigma_y,sigma_z,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically. + /** + \param sigma Standard deviation of the blur. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \param is_gaussian Use a gaussian kernel (VanVliet) is set, a quasi-gaussian (Deriche) otherwise. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=true) { + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur(nsigma,nsigma,nsigma,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically \newinstance. + CImg get_blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=true) const { + return CImg(*this,false).blur(sigma,boundary_conditions,is_gaussian); + } + + //! Blur image anisotropically, directed by a field of diffusion tensors. + /** + \param G Field of square roots of diffusion tensors/vectors used to drive the smoothing. + \param amplitude Amplitude of the smoothing. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=1) { + + // Check arguments and init variables + if (!is_sameXYZ(G) || (G._spectrum!=3 && G._spectrum!=6)) + throw CImgArgumentException(_cimg_instance + "blur_anisotropic(): Invalid specified diffusion tensor field (%u,%u,%u,%u,%p).", + cimg_instance, + G._width,G._height,G._depth,G._spectrum,G._data); + if (is_empty() || dl<0) return *this; + const float namplitude = amplitude>=0?amplitude:-amplitude*cimg::max(_width,_height,_depth)/100; + unsigned int iamplitude = cimg::round(namplitude); + const bool is_3d = (G._spectrum==6); + T val_min, val_max = max_min(val_min); + _cimg_abort_init_openmp; + cimg_abort_init; + + if (da<=0) { // Iterated oriented Laplacians + CImg velocity(_width,_height,_depth,_spectrum); + for (unsigned int iteration = 0; iterationveloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + else // 2D version + cimg_forZC(*this,z,c) { + cimg_abort_test; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + veloc = (Tfloat)(G(x,y,0,0)*ixx + 2*G(x,y,0,1)*ixy + G(x,y,0,2)*iyy); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + if (veloc_max>0) *this+=(velocity*=dl/veloc_max); + } + } else { // LIC-based smoothing + const ulongT whd = (ulongT)_width*_height*_depth; + const float sqrt2amplitude = (float)std::sqrt(2*namplitude); + const int dx1 = width() - 1, dy1 = height() - 1, dz1 = depth() - 1; + CImg res(_width,_height,_depth,_spectrum,0), W(_width,_height,_depth,is_3d?4:3), val(_spectrum,1,1,1,0); + int N = 0; + if (is_3d) { // 3D version + for (float phi = cimg::mod(180.f,da)/2.f; phi<=180; phi+=da) { + const float phir = (float)(phi*cimg::PI/180), datmp = (float)(da/std::cos(phir)), + da2 = datmp<1?360.f:datmp; + for (float theta = 0; theta<360; (theta+=da2),++N) { + const float + thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)*std::cos(phir)), + vy = (float)(std::sin(thetar)*std::cos(phir)), + vz = (float)std::sin(phir); + const t + *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2), + *pd = G.data(0,0,0,3), *pe = G.data(0,0,0,4), *pf = G.data(0,0,0,5); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2), *pd3 = W.data(0,0,0,3); + cimg_forXYZ(G,xg,yg,zg) { + const t a = *(pa++), b = *(pb++), c = *(pc++), d = *(pd++), e = *(pe++), f = *(pf++); + const float + u = (float)(a*vx + b*vy + c*vz), + v = (float)(b*vx + d*vy + e*vz), + w = (float)(c*vx + e*vy + f*vz), + n = 1e-5f + cimg::hypot(u,v,w), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)(w*dln); + *(pd3++) = (Tfloat)n; + } + + cimg_abort_test; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && _height*_depth>=2) + firstprivate(val)) + cimg_forYZ(*this,y,z) _cimg_abort_try_openmp2 { + cimg_abort_test2; + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,z,3), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y, + Z = (float)z; + switch (interpolation_type) { + case 0 : { // Nearest neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f), + cz = (int)(Z + 0.5f); + const float + u = (float)W(cx,cy,cz,0), + v = (float)W(cx,cy,cz,1), + w = (float)W(cx,cy,cz,2); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,cz,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,cz,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u = (float)(W._linear_atXYZ(X,Y,Z,0)), + v = (float)(W._linear_atXYZ(X,Y,Z,1)), + w = (float)(W._linear_atXYZ(X,Y,Z,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + default : { // 2nd order Runge Kutta + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)), + v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)), + w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)), + u = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,0)), + v = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,1)), + w = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + } + Tfloat *ptrd = res.data(x,y,z); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,z,c)); ptrd+=whd; } + } + } _cimg_abort_catch_openmp2 + } + } + } else { // 2D LIC algorithm + for (float theta = cimg::mod(360.f,da)/2.f; theta<360; (theta+=da),++N) { + const float thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar)); + const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2); + cimg_forXY(G,xg,yg) { + const t a = *(pa++), b = *(pb++), c = *(pc++); + const float + u = (float)(a*vx + b*vy), + v = (float)(b*vx + c*vy), + n = std::max(1e-5f,cimg::hypot(u,v)), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)n; + } + + cimg_abort_test; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && _height>=2) + firstprivate(val)) + cimg_forY(*this,y) _cimg_abort_try_openmp2 { + cimg_abort_test2; + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,0,2), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y; + switch (interpolation_type) { + case 0 : { // Nearest-neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f); + const float + u = (float)W(cx,cy,0,0), + v = (float)W(cx,cy,0,1); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u = (float)(W._linear_atXY(X,Y,0,0)), + v = (float)(W._linear_atXY(X,Y,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + default : { // 2nd-order Runge-kutta interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)), + v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)), + u = (float)(W._linear_atXY(X + u0,Y + v0,0,0)), + v = (float)(W._linear_atXY(X + u0,Y + v0,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } + } + Tfloat *ptrd = res.data(x,y); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,0,c)); ptrd+=whd; } + } + } _cimg_abort_catch_openmp2 + } + } + const Tfloat *ptrs = res._data; + cimg_for(*this,ptrd,T) { + const Tfloat _val = *(ptrs++)/N; + *ptrd = _valval_max?val_max:(T)_val); + } + } + cimg_abort_test; + return *this; + } + + //! Blur image anisotropically, directed by a field of diffusion tensors \newinstance. + template + CImg get_blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way. + /** + \param amplitude Amplitude of the smoothing. + \param sharpness Sharpness. + \param anisotropy Anisotropy. + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + CImg& blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) { + const float nalpha = alpha>=0?alpha:-alpha*cimg::max(_width,_height,_depth)/100; + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur_anisotropic(get_diffusion_tensors(sharpness,anisotropy,nalpha,nsigma,interpolation_type!=3), + amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way \newinstance. + CImg get_blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, + const float da=30, const float gauss_prec=2, + const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec, + interpolation_type,is_fast_approx); + } + + //! Blur image, with the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_x Amount of blur along the X-axis. + \param sigma_y Amount of blur along the Y-axis. + \param sigma_z Amount of blur along the Z-axis. + \param sigma_r Amount of blur along the value axis. + \param sampling_x Amount of downsampling along the X-axis used for the approximation. + Defaults (0) to sigma_x. + \param sampling_y Amount of downsampling along the Y-axis used for the approximation. + Defaults (0) to sigma_y. + \param sampling_z Amount of downsampling along the Z-axis used for the approximation. + Defaults (0) to sigma_z. + \param sampling_r Amount of downsampling along the value axis used for the approximation. + Defaults (0) to sigma_r. + \note This algorithm uses the optimisation technique proposed by S. Paris and F. Durand, in ECCV'2006 + (extended for 3D volumetric images). + It is based on the reference implementation http://people.csail.mit.edu/jiawen/software/bilateralFilter.m + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_bilateral(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || (!sigma_x && !sigma_y && !sigma_z)) return *this; + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return blur(sigma_x,sigma_y,sigma_z); + const float + edge_delta = (float)(edge_max - edge_min), + _sigma_x = sigma_x>=0?sigma_x:-sigma_x*_width/100, + _sigma_y = sigma_y>=0?sigma_y:-sigma_y*_height/100, + _sigma_z = sigma_z>=0?sigma_z:-sigma_z*_depth/100, + _sigma_r = sigma_r>=0?sigma_r:-sigma_r*edge_delta/100, + _sampling_x = sampling_x?sampling_x:std::max(_sigma_x,1.f), + _sampling_y = sampling_y?sampling_y:std::max(_sigma_y,1.f), + _sampling_z = sampling_z?sampling_z:std::max(_sigma_z,1.f), + _sampling_r = sampling_r?sampling_r:std::max(_sigma_r,edge_delta/256), + derived_sigma_x = _sigma_x / _sampling_x, + derived_sigma_y = _sigma_y / _sampling_y, + derived_sigma_z = _sigma_z / _sampling_z, + derived_sigma_r = _sigma_r / _sampling_r; + const int + padding_x = (int)(2*derived_sigma_x) + 1, + padding_y = (int)(2*derived_sigma_y) + 1, + padding_z = (int)(2*derived_sigma_z) + 1, + padding_r = (int)(2*derived_sigma_r) + 1; + const unsigned int + bx = (unsigned int)((_width - 1)/_sampling_x + 1 + 2*padding_x), + by = (unsigned int)((_height - 1)/_sampling_y + 1 + 2*padding_y), + bz = (unsigned int)((_depth - 1)/_sampling_z + 1 + 2*padding_z), + br = (unsigned int)(edge_delta/_sampling_r + 1 + 2*padding_r); + if (bx>0 || by>0 || bz>0 || br>0) { + const bool is_3d = (_depth>1); + if (is_3d) { // 3D version of the algorithm + CImg bgrid(bx,by,bz,br), bgridw(bx,by,bz,br); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); bgridw.fill(0); + cimg_forXYZ(*this,x,y,z) { + const T val = (*this)(x,y,z,c); + const float edge = (float)_guide(x,y,z); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + Z = (int)cimg::round(z/_sampling_z) + padding_z, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,Z,R)+=(float)val; + bgridw(X,Y,Z,R)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + bgridw.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),4096)) + cimg_forXYZ(*this,x,y,z) { + const float edge = (float)_guide(x,y,z); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + Z = z/_sampling_z + padding_z, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid._linear_atXYZC(X,Y,Z,R), bval1 = bgridw._linear_atXYZC(X,Y,Z,R); + (*this)(x,y,z,c) = (T)(bval0/bval1); + } + } + } else { // 2D version of the algorithm + CImg bgrid(bx,by,br,2); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); + cimg_forXY(*this,x,y) { + const T val = (*this)(x,y,c); + const float edge = (float)_guide(x,y); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,R,0)+=(float)val; + bgrid(X,Y,R,1)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,0,true).blur(0,0,derived_sigma_r,false); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(size(),4096)) + cimg_forXY(*this,x,y) { + const float edge = (float)_guide(x,y); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid._linear_atXYZ(X,Y,R,0), bval1 = bgrid._linear_atXYZ(X,Y,R,1); + (*this)(x,y,c) = (T)(bval0/bval1); + } + } + } + } + return *this; + } + + //! Blur image, with the joint bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) const { + return CImg(*this,false).blur_bilateral(guide,sigma_x,sigma_y,sigma_z,sigma_r, + sampling_x,sampling_y,sampling_z,sampling_r); + } + + //! Blur image using the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param sampling_s Amount of downsampling along the XYZ-axes used for the approximation. Defaults to sigma_s. + \param sampling_r Amount of downsampling along the value axis used for the approximation. Defaults to sigma_r. + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) { + const float _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100; + return blur_bilateral(guide,_sigma_s,_sigma_s,_sigma_s,sigma_r,sampling_s,sampling_s,sampling_s,sampling_r); + } + + //! Blur image using the bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) const { + return CImg(*this,false).blur_bilateral(guide,sigma_s,sigma_r,sampling_s,sampling_r); + } + + // [internal] Apply a box filter (used by CImg::boxfilter() and CImg::blur_box()). + /* + \param ptr the pointer of the data + \param N size of the data + \param boxsize Size of the box filter (can be subpixel). + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivative and 2nd derivative. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + */ + static void _cimg_blur_box_apply(T *ptr, const float boxsize, const int N, const ulongT off, + const int order, const bool boundary_conditions, + const unsigned int nb_iter) { + // Smooth. + if (boxsize>1 && nb_iter) { + const int w2 = (int)(boxsize - 1)/2; + const unsigned int winsize = 2*w2 + 1U; + const double frac = (boxsize - winsize)/2.; + CImg win(winsize); + for (unsigned int iter = 0; iter=N) return boundary_conditions?ptr[(N - 1)*off]:T(); + return ptr[x*off]; + } + + // Apply box filter of order 0,1,2. + /** + \param boxsize Size of the box window (can be subpixel) + \param order the order of the filter 0,1 or 2. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \param nb_iter Number of filter iterations. + **/ + CImg& boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true, + const unsigned int nb_iter=1) { + if (is_empty() || !boxsize || (boxsize<=1 && !order)) return *this; + const char naxis = cimg::lowercase(axis); + const float nboxsize = boxsize>=0?boxsize:-boxsize* + (naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_blur_box_apply(data(0,y,z,c),nboxsize,_width,1U,order,boundary_conditions,nb_iter); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_blur_box_apply(data(x,0,z,c),nboxsize,_height,(ulongT)_width,order,boundary_conditions,nb_iter); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_blur_box_apply(data(x,y,0,c),nboxsize,_depth,(ulongT)_width*_height,order,boundary_conditions,nb_iter); + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_blur_box_apply(data(x,y,z,0),nboxsize,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions,nb_iter); + } + } + return *this; + } + + // Apply box filter of order 0,1 or 2 \newinstance. + CImg get_boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true, + const unsigned int nb_iter=1) const { + return CImg(*this,false).boxfilter(boxsize,order,axis,boundary_conditions,nb_iter); + } + + //! Blur image with a box filter. + /** + \param boxsize_x Size of the box window, along the X-axis (can be subpixel). + \param boxsize_y Size of the box window, along the Y-axis (can be subpixel). + \param boxsize_z Size of the box window, along the Z-axis (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param nb_iter Number of filter iterations. + \note + - This is a recursive algorithm, not depending on the values of the box kernel size. + \see blur(). + **/ + CImg& blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true, + const unsigned int nb_iter=1) { + if (is_empty()) return *this; + if (_width>1) boxfilter(boxsize_x,0,'x',boundary_conditions,nb_iter); + if (_height>1) boxfilter(boxsize_y,0,'y',boundary_conditions,nb_iter); + if (_depth>1) boxfilter(boxsize_z,0,'z',boundary_conditions,nb_iter); + return *this; + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize_x,boxsize_y,boxsize_z,boundary_conditions); + } + + //! Blur image with a box filter. + /** + \param boxsize Size of the box window (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \see deriche(), vanvliet(). + **/ + CImg& blur_box(const float boxsize, const bool boundary_conditions=true) { + const float nboxsize = boxsize>=0?boxsize:-boxsize*cimg::max(_width,_height,_depth)/100; + return blur_box(nboxsize,nboxsize,nboxsize,boundary_conditions); + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize, const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize,boundary_conditions); + } + + //! Blur image, with the image guided filter. + /** + \param guide Image used to guide the smoothing process. + \param radius Spatial radius. If negative, it is expressed as a percentage of the largest image size. + \param regularization Regularization parameter. + If negative, it is expressed as a percentage of the guide value range. + \note This method implements the filtering algorithm described in: + He, Kaiming; Sun, Jian; Tang, Xiaoou, "Guided Image Filtering," Pattern Analysis and Machine Intelligence, + IEEE Transactions on , vol.35, no.6, pp.1397,1409, June 2013 + **/ + template + CImg& blur_guided(const CImg& guide, const float radius, const float regularization) { + return get_blur_guided(guide,radius,regularization).move_to(*this); + } + + //! Blur image, with the image guided filter \newinstance. + template + CImg get_blur_guided(const CImg& guide, const float radius, const float regularization) const { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_guided(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !radius) return *this; + const int _radius = radius>=0?(int)radius:(int)(-radius*cimg::max(_width,_height,_depth)/100); + float _regularization = regularization; + if (regularization<0) { + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return *this; + _regularization = -regularization*(edge_max - edge_min)/100; + } + _regularization = std::max(_regularization,0.01f); + const unsigned int psize = (unsigned int)(1 + 2*_radius); + CImg + mean_p = get_blur_box(psize,true), + mean_I = guide.get_blur_box(psize,true).resize(mean_p), + cov_Ip = get_mul(guide).blur_box(psize,true)-=mean_p.get_mul(mean_I), + var_I = guide.get_sqr().blur_box(psize,true)-=mean_I.get_sqr(), + &a = cov_Ip.div(var_I+=_regularization), + &b = mean_p-=a.get_mul(mean_I); + a.blur_box(psize,true); + b.blur_box(psize,true); + return a.mul(guide)+=b; + } + + //! Blur image using patch-based space. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param patch_size Size of the patches. + \param lookup_size Size of the window to search similar patches. + \param smoothness Smoothness for the patch comparison. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_patch(const CImg& guide, + const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + if (is_empty() || !patch_size || !lookup_size) return *this; + return get_blur_patch(guide,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx).move_to(*this); + } + + //! Blur image using patch-based space \newinstance. + template + CImg get_blur_patch(const CImg& guide, + const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + +#define _cimg_blur_patch3d_fast(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) \ + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) \ + firstprivate(P,Q)) \ + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N##x##N(res,x,y,z); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,x,y,z,c,pP,tfloat); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + tfloat sum_weights = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) \ + if (cimg::abs(_guide(x,y,z,0) - _guide(p,q,r,0))3?0:1; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); \ + } \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch3d(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) \ + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) \ + firstprivate(P,Q)) \ + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N##x##N(res,x,y,z); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,x,y,z,c,pP,tfloat); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + tfloat sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { \ + tfloat *pQ = Q._data; cimg_forC(_guide,c) { cimg_get##N##x##N##x##N(_guide,p,q,r,c,pQ,tfloat); pQ+=N3; } \ + tfloat distance2 = 0; \ + pQ = Q._data; cimg_for(P,_pP,tfloat) { const tfloat dI = *_pP - *(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const tfloat dx = (tfloat)p - x, dy = (tfloat)q - y, dz = (tfloat)r - z, \ + alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight_max*(*this)(x,y,z,c); \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch2d_fast(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) \ + firstprivate(P,Q)) \ + cimg_forXY(res,x,y) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N(res,x,y); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,x,y,0,c,pP,tfloat); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + tfloat sum_weights = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) \ + if (cimg::abs(_guide(x,y,0,0) - _guide(p,q,0,0))3?0:1; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); \ + } \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } _cimg_abort_catch_openmp } + +#define _cimg_blur_patch2d(N) { \ + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) \ + firstprivate(P,Q)) \ + cimg_forXY(res,x,y) _cimg_abort_try_openmp { \ + cimg_abort_test; \ + cimg_def##N##x##N(res,x,y); \ + tfloat *pP = P._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,x,y,0,c,pP,tfloat); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + tfloat sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { \ + tfloat *pQ = Q._data; cimg_forC(_guide,c) { cimg_get##N##x##N(_guide,p,q,0,c,pQ,tfloat); pQ+=N2; } \ + tfloat distance2 = 0; \ + pQ = Q._data; cimg_for(P,_pP,tfloat) { const tfloat dI = *_pP - *(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const tfloat dx = (tfloat)p - x, dy = (tfloat)q - y, \ + alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight_max*(*this)(x,y,c); \ + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } _cimg_abort_catch_openmp } + + typedef _cimg_tfloat tfloat; + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_patch(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !patch_size || !lookup_size) return +*this; + Tfloat val_min, val_max = (Tfloat)max_min(val_min); + _cimg_abort_init_openmp; + cimg_abort_init; + + CImg res(_width,_height,_depth,_spectrum,0); + const CImg + __guide = guide?CImg(guide,guide.pixel_type()==cimg::type::string()): + CImg(*this,pixel_type()==cimg::type::string()), + _guide = smoothness>0?__guide.get_blur(smoothness):__guide.get_shared(); + CImg P(_guide._spectrum*patch_size*patch_size*(_depth>1?patch_size:1)), Q(P); + + t guide_min = (t)0, guide_max = (t)0; + if (sigma_r<0) guide_max = guide.max_min(guide_min); + const float + guide_delta = (float)(guide_max - guide_min), + _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100, + _sigma_r = sigma_r>=0?sigma_r:-sigma_r*guide_delta/100, + sigma_s2 = _sigma_s*_sigma_s, + sigma_r2 = _sigma_r*_sigma_r, + sigma_r3 = 3*_sigma_r, + Pnorm = P.size()*sigma_r2; + const int rsize2 = (int)lookup_size/2, rsize1 = (int)lookup_size - rsize2 - 1; + const unsigned int N2 = patch_size*patch_size, N3 = N2*patch_size; + cimg::unused(N2,N3); + if (_depth>1) switch (patch_size) { // 3D + case 2 : if (is_fast_approx) _cimg_blur_patch3d_fast(2) else _cimg_blur_patch3d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch3d_fast(3) else _cimg_blur_patch3d(3) break; + default : { + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) + firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { // Fast + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + tfloat sum_weights = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) + if (cimg::abs(_guide(x,y,z,0) - _guide(p,q,r,0))3?0:1; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); + } + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } _cimg_abort_catch_openmp + } else { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height*res._depth>=4) + firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) _cimg_abort_try_openmp { // Exact + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + tfloat sum_weights = 0, weight_max = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { + (Q = _guide.get_crop(p - psize1,q - psize1,r - psize1,p + psize2,q + psize2,r + psize2,true))-=P; + const tfloat + dx = (tfloat)x - p, dy = (tfloat)y - q, dz = (tfloat)z - r, + distance2 = (tfloat)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2), + weight = std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight*(*this)(p,q,r,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=(Tfloat)weight_max*(*this)(x,y,z,c); + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,z,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } _cimg_abort_catch_openmp + } + } + } else switch (patch_size) { // 2D + case 2 : if (is_fast_approx) _cimg_blur_patch2d_fast(2) else _cimg_blur_patch2d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch2d_fast(3) else _cimg_blur_patch2d(3) break; + case 4 : if (is_fast_approx) _cimg_blur_patch2d_fast(4) else _cimg_blur_patch2d(4) break; + case 5 : if (is_fast_approx) _cimg_blur_patch2d_fast(5) else _cimg_blur_patch2d(5) break; + case 6 : if (is_fast_approx) _cimg_blur_patch2d_fast(6) else _cimg_blur_patch2d(6) break; + case 7 : if (is_fast_approx) _cimg_blur_patch2d_fast(7) else _cimg_blur_patch2d(7) break; + case 8 : if (is_fast_approx) _cimg_blur_patch2d_fast(8) else _cimg_blur_patch2d(8) break; + case 9 : if (is_fast_approx) _cimg_blur_patch2d_fast(9) else _cimg_blur_patch2d(9) break; + default : { // Fast + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) { + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) + firstprivate(P,Q)) + cimg_forXY(res,x,y) _cimg_abort_try_openmp { // Fast + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + tfloat sum_weights = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) + if (cimg::abs(_guide(x,y,0) - _guide(p,q,0))3?0:1; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); + } + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } _cimg_abort_catch_openmp + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*32 && res._height>=4) + firstprivate(P,Q)) + cimg_forXY(res,x,y) _cimg_abort_try_openmp { // Exact + cimg_abort_test; + P = _guide.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + tfloat sum_weights = 0, weight_max = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { + (Q = _guide.get_crop(p - psize1,q - psize1,p + psize2,q + psize2,true))-=P; + const tfloat + dx = (tfloat)x - p, dy = (tfloat)y - q, + distance2 = (tfloat)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2), + weight = std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight*(*this)(p,q,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=(Tfloat)weight_max*(*this)(x,y,c); + if (sum_weights>1e-10) cimg_forC(res,c) res(x,y,c)/=(Tfloat)sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } _cimg_abort_catch_openmp + } + } + } + return res.cut(val_min,val_max); + } + + //! Blur image using patch-based space \simplification. + CImg& blur_patch(const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + return blur_patch(*this,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx); + } + + //! Blur image using patch-based space \simplification \newinstance. + CImg get_blur_patch(const float sigma_s, const float sigma_r, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + return get_blur_patch(*this,sigma_s,sigma_r,patch_size,lookup_size,smoothness,is_fast_approx); + } + + //! Blur image with the median filter. + /** + \param n Size of the median filter. + \param threshold Threshold used to discard pixels too far from the current pixel value in the median computation. + **/ + CImg& blur_median(const unsigned int n, const float threshold=0) { + if (!n) return *this; + return get_blur_median(n,threshold).move_to(*this); + } + + //! Blur image with the median filter \newinstance. + CImg get_blur_median(const unsigned int n, const float threshold=0) const { + if (is_empty() || n<=1) return +*this; + CImg res(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg::unused(ptrd); + const int hr = (int)n/2, hl = n - hr - 1; + if (res._depth!=1) { // 3D + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // With threshold + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + const Tfloat val0 = (Tfloat)(*this)(x,y,z,c); + CImg values(n*n*n); + unsigned int nb_values = 0; + T *_ptrd = values.data(); + cimg_for_inXYZ(*this,nx0,ny0,nz0,nx1,ny1,nz1,p,q,r) + if (cimg::abs((*this)(p,q,r,c) - val0)<=threshold) { *(_ptrd++) = (*this)(p,q,r,c); ++nb_values; } + res(x,y,z,c) = nb_values?values.get_shared_points(0,nb_values - 1).median():(*this)(x,y,z,c); + } + else + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // Without threshold + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + res(x,y,z,c) = get_crop(nx0,ny0,nz0,c,nx1,ny1,nz1,c).median(); + } + } else { + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && + _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { // With threshold + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + const Tfloat val0 = (Tfloat)(*this)(x,y,c); + CImg values(n*n); + unsigned int nb_values = 0; + T *_ptrd = values.data(); + cimg_for_inXY(*this,nx0,ny0,nx1,ny1,p,q) + if (cimg::abs((*this)(p,q,c) - val0)<=threshold) { *(_ptrd++) = (*this)(p,q,c); ++nb_values; } + res(x,y,c) = nb_values?values.get_shared_points(0,nb_values - 1).median():(*this)(x,y,c); + } + else { + const int + w1 = width() - 1, h1 = height() - 1, + w2 = width() - 2, h2 = height() - 2, + w3 = width() - 3, h3 = height() - 3, + w4 = width() - 4, h4 = height() - 4; + switch (n) { // Without threshold + case 3 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(9); + cimg_for_in3x3(*this,1,1,w2,h2,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6],I[7],I[8]); + cimg_for_borderXY(*this,x,y,1) + res(x,y,c) = get_crop(std::max(0,x - 1),std::max(0,y - 1),0,c, + std::min(w1,x + 1),std::min(h1,y + 1),0,c).median(); + } + } break; + case 5 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(25); + cimg_for_in5x5(*this,2,2,w3,h3,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4], + I[5],I[6],I[7],I[8],I[9], + I[10],I[11],I[12],I[13],I[14], + I[15],I[16],I[17],I[18],I[19], + I[20],I[21],I[22],I[23],I[24]); + cimg_for_borderXY(*this,x,y,2) + res(x,y,c) = get_crop(std::max(0,x - 2),std::max(0,y - 2),0,c, + std::min(w1,x + 2),std::min(h1,y + 2),0,c).median(); + } + } break; + case 7 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg I(49); + cimg_for_in7x7(*this,3,3,w4,h4,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6], + I[7],I[8],I[9],I[10],I[11],I[12],I[13], + I[14],I[15],I[16],I[17],I[18],I[19],I[20], + I[21],I[22],I[23],I[24],I[25],I[26],I[27], + I[28],I[29],I[30],I[31],I[32],I[33],I[34], + I[35],I[36],I[37],I[38],I[39],I[40],I[41], + I[42],I[43],I[44],I[45],I[46],I[47],I[48]); + cimg_for_borderXY(*this,x,y,3) + res(x,y,c) = get_crop(std::max(0,x - 3),std::max(0,y - 3),0,c, + std::min(w1,x + 3),std::min(h1,y + 3),0,c).median(); + } + } break; + default : { + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*16 && _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + res(x,y,c) = get_crop(nx0,ny0,0,c,nx1,ny1,0,c).median(); + } + } + } + } + } + return res; + } + + //! Sharpen image. + /** + \param amplitude Sharpening amplitude + \param sharpen_type Select sharpening method. Can be { false=inverse diffusion | true=shock filters }. + \param edge Edge threshold (shock filters only). + \param alpha Gradient smoothness (shock filters only). + \param sigma Tensor smoothness (shock filters only). + **/ + CImg& sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) { + if (is_empty()) return *this; + T val_min, val_max = max_min(val_min); + const float nedge = edge/2; + CImg velocity(_width,_height,_depth,_spectrum), _veloc_max(_spectrum); + + if (_depth>1) { // 3D + if (sharpen_type) { // Shock filters + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*32 && + _height*_depth>=16)) + cimg_forYZ(G,y,z) { + Tfloat *ptrG0 = G.data(0,y,z,0), *ptrG1 = G.data(0,y,z,1), + *ptrG2 = G.data(0,y,z,2), *ptrG3 = G.data(0,y,z,3); + CImg val, vec; + cimg_forX(G,x) { + G.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + if (val[2]<0) val[2] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = vec(0,2); + *(ptrG3++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1] + val[2],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + u = G(x,y,z,0), + v = G(x,y,z,1), + w = G(x,y,z,2), + amp = G(x,y,z,3), + ixx = Incc + Ipcc - 2*Iccc, + ixy = (Innc + Ippc - Inpc - Ipnc)/4, + ixz = (Incn + Ipcp - Incp - Ipcn)/4, + iyy = Icnc + Icpc - 2*Iccc, + iyz = (Icnn + Icpp - Icnp - Icpn)/4, + izz = Iccn + Iccp - 2*Iccc, + ixf = Incc - Iccc, + ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, + iyb = Iccc - Icpc, + izf = Iccn - Iccc, + izb = Iccc - Iccp, + itt = u*u*ixx + v*v*iyy + w*w*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb) + w*cimg::minmod(izf,izb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat veloc = -Ipcc - Incc - Icpc - Icnc - Iccp - Iccn + 6*Iccc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else { // 2D + if (sharpen_type) { // Shock filters + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*32 && + _height>=(cimg_openmp_sizefactor)*16)) + cimg_forY(G,y) { + CImg val, vec; + Tfloat *ptrG0 = G.data(0,y,0,0), *ptrG1 = G.data(0,y,0,1), *ptrG2 = G.data(0,y,0,2); + cimg_forX(G,x) { + G.get_tensor_at(x,y).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + u = G(x,y,0), + v = G(x,y,1), + amp = G(x,y,2), + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + ixf = Inc - Icc, + ixb = Icc - Ipc, + iyf = Icn - Icc, + iyb = Icc - Icp, + itt = u*u*ixx + v*v*iyy + 2*u*v*ixy, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*512 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat veloc = -Ipc - Inc - Icp - Icn + 4*Icc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } + const Tfloat veloc_max = _veloc_max.max(); + if (veloc_max<=0) return *this; + return ((velocity*=amplitude/veloc_max)+=*this).cut(val_min,val_max).move_to(*this); + } + + //! Sharpen image \newinstance. + CImg get_sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) const { + return (+*this).sharpen(amplitude,sharpen_type,edge,alpha,sigma); + } + + //! Return image gradient. + /** + \param axes Axes considered for the gradient computation, as a C-string (e.g "xy"). + \param scheme = Numerical scheme used for the gradient computation: + - -1 = Backward finite differences + - 0 = Centered finite differences (default) + - 1 = Forward finite differences + - 2 = Using Sobel kernels + - 3 = Using rotation invariant kernels + - 4 = Using Deriche recursive filter. + - 5 = Using Van Vliet recursive filter. + **/ + CImgList get_gradient(const char *const axes=0, const int scheme=0) const { + CImgList res; + char __axes[4] = { 0 }; + const char *_axes = axes?axes:__axes; + if (!axes) { + unsigned int k = 0; + if (_width>1) __axes[k++] = 'x'; + if (_height>1) __axes[k++] = 'y'; + if (_depth>1) __axes[k++] = 'z'; + } + + CImg grad; + while (*_axes) { + const char axis = cimg::lowercase(*(_axes++)); + if (axis!='x' && axis!='y' && axis!='z') + throw CImgArgumentException(_cimg_instance + "get_gradient(): Invalid specified axes '%s'.", + cimg_instance, + axes); + const longT off = axis=='x'?1:axis=='y'?_width:_width*_height; + if ((axis=='x' && _width==1) || (axis=='y' && _height==1) || (axis=='z' && _depth==1)) { + grad.assign(_width,_height,_depth,_spectrum,0).move_to(res); + continue; + } + + const int _scheme = axis=='z' && (scheme==2 || scheme==3)?0:scheme; + switch (_scheme) { + case -1 : { // Backward finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && !x) || (axis=='y' && !y) || (axis=='z' && !z)) + grad[pos] = 0; + else + grad[pos] = (Tfloat)_data[pos] - _data[pos - off]; + } + grad.move_to(res); + } break; + case 1 : { // Forward finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && x==width() - 1) || (axis=='y' && y==height() - 1) || (axis=='z' && z==depth() - 1)) + grad[pos] = 0; + else + grad[pos] = (Tfloat)_data[pos + off] - _data[pos]; + } + grad.move_to(res); + } break; + case 2 : { // Sobel scheme + grad.assign(_width,_height,_depth,_spectrum); + if (axis=='x') // X-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = - Ipp + Inp - 2*Ipc + 2*Inc - Ipn + Inn; + } + else // Y-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = - Ipp - 2*Icp - Inp + Ipn + 2*Icn + Inn; + } + grad.move_to(res); + } break; + case 3 : { // Rotation invariant scheme + const Tfloat a = (Tfloat)(0.25f*(2 - std::sqrt(2.f))), b = (Tfloat)(0.5f*(std::sqrt(2.f) - 1)); + grad.assign(_width,_height,_depth,_spectrum); + if (axis=='x') // X-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn; + } + else // Y-axis + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) grad(x,y,z,c) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn; + } + grad.move_to(res); + } break; + case 4 : // Deriche filter + get_deriche(0,1,axis).move_to(res); + break; + case 5 : // Van Vliet filter + get_vanvliet(0,1,axis).move_to(res); + break; + default : { // Central finite differences + grad.assign(_width,_height,_depth,_spectrum); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) cimg_openmp_if_size(size(),16384)) + cimg_forXYZC(*this,x,y,z,c) { + const ulongT pos = offset(x,y,z,c); + if ((axis=='x' && !x) || (axis=='y' && !y) || (axis=='z' && !z)) + grad[pos] = ((Tfloat)_data[pos + off] - _data[pos])/2; + else if ((axis=='x' && x==width() - 1) || (axis=='y' && y==height() - 1) || (axis=='z' && z==depth() - 1)) + grad[pos] = ((Tfloat)_data[pos] - _data[pos - off])/2; + else + grad[pos] = ((Tfloat)_data[pos + off] - _data[pos - off])/2; + } + grad.move_to(res); + } break; + } + } + return res; + } + + //! Return image hessian. + /** + \param axes Axes considered for the hessian computation, as a C-string (e.g "xy"). + **/ + CImgList get_hessian(const char *const axes=0) const { + CImgList res; + char __axes[12] = { 0 }; + const char *_axes = axes?axes:__axes; + if (!axes) { + unsigned int k = 0; + if (_width>1) { __axes[k++] = 'x'; __axes[k++] = 'x'; } + if (_width>1 && _height>1) { __axes[k++] = 'x'; __axes[k++] = 'y'; } + if (_width>1 && _depth>1) { __axes[k++] = 'x'; __axes[k++] = 'z'; } + if (_height>1) { __axes[k++] = 'y'; __axes[k++] = 'y'; } + if (_height>1 && _depth>1) { __axes[k++] = 'y'; __axes[k++] = 'z'; } + if (_depth>1) { __axes[k++] = 'z'; __axes[k++] = 'z'; } + } + const unsigned int len = (unsigned int)std::strlen(_axes); + if (len%2) + throw CImgArgumentException(_cimg_instance + "get_hessian(): Invalid specified axes '%s'.", + cimg_instance, + axes); + CImg hess; + for (unsigned int k = 0; k=(cimg_openmp_sizefactor)*16384 && + _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Inn + Ipp - Inp - Ipn)/4; + } + else if (axis1=='x' && axis2=='z') // Ixz + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*16384 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Incn + Ipcp - Incp - Ipcn)/4; + } + else // Iyz + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*16384 && + _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) hess(x,y,z,c) = (Icnn + Icpp - Icnp - Icpn)/4; + } + hess.move_to(res); + } + return res; + } + + //! Compute image Laplacian. + CImg& laplacian() { + return get_laplacian().move_to(*this); + } + + //! Compute image Laplacian \newinstance. + CImg get_laplacian() const { + if (is_empty()) return CImg(); + CImg res(_width,_height,_depth,_spectrum); + if (_depth>1) { // 3D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Incc + Ipcc + Icnc + Icpc + Iccn + Iccp - 6*Iccc; + } + } else if (_height>1) { // 2D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc + Icn + Icp - 4*Icc; + } + } else { // 1D + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*1048576 && + _height*_depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc - 2*Icc; + } + } + return res; + } + + //! Compute the structure tensor field of an image. + /** + \param is_fwbw_scheme scheme. Can be { false=centered | true=forward-backward } + **/ + CImg& structure_tensors(const bool is_fwbw_scheme=false) { + return get_structure_tensors(is_fwbw_scheme).move_to(*this); + } + + //! Compute the structure tensor field of an image \newinstance. + CImg get_structure_tensors(const bool is_fwbw_scheme=false) const { + if (is_empty()) return *this; + CImg res; + if (_depth>1) { // 3D + res.assign(_width,_height,_depth,6,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ix = (Incc - Ipcc)/2, + iy = (Icnc - Icpc)/2, + iz = (Iccn - Iccp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=ix*iz; + *(ptrd3++)+=iy*iy; + *(ptrd4++)+=iy*iz; + *(ptrd5++)+=iz*iz; + } + } + } else { // Forward/backward finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1048576 && + _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixf = Incc - Iccc, ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, iyb = Iccc - Icpc, + izf = Iccn - Iccc, izb = Iccc - Iccp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4; + *(ptrd3++)+=(iyf*iyf + iyb*iyb)/2; + *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4; + *(ptrd5++)+=(izf*izf + izb*izb)/2; + } + } + } + } else { // 2D + res.assign(_width,_height,_depth,3,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ix = (Inc - Ipc)/2, + iy = (Icn - Icp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=iy*iy; + } + } + } else { // Forward/backward finite differences (version 2) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=(cimg_openmp_sizefactor)*1048576 && + _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ixf = Inc - Icc, ixb = Icc - Ipc, + iyf = Icn - Icc, iyb = Icc - Icp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2; + } + } + } + } + return res; + } + + //! Compute field of diffusion tensors for edge-preserving smoothing. + /** + \param sharpness Sharpness + \param anisotropy Anisotropy + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param is_sqrt Tells if the square root of the tensor field is computed instead. + **/ + CImg& diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) { + CImg res; + const float + nsharpness = std::max(sharpness,1e-5f), + power1 = (is_sqrt?0.5f:1)*nsharpness, + power2 = power1/(1e-7f + 1 - anisotropy); + blur(alpha).normalize(0,(T)255); + + if (_depth>1) { // 3D + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height*_depth>=(cimg_openmp_sizefactor)*256)) + cimg_forYZ(*this,y,z) { + Tfloat + *ptrd0 = res.data(0,y,z,0), *ptrd1 = res.data(0,y,z,1), *ptrd2 = res.data(0,y,z,2), + *ptrd3 = res.data(0,y,z,3), *ptrd4 = res.data(0,y,z,4), *ptrd5 = res.data(0,y,z,5); + CImg val(3), vec(3,3); + cimg_forX(*this,x) { + res.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + const float + _l1 = val[2], _l2 = val[1], _l3 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, l3 = _l3>0?_l3:0, + ux = vec(0,0), uy = vec(0,1), uz = vec(0,2), + vx = vec(1,0), vy = vec(1,1), vz = vec(1,2), + wx = vec(2,0), wy = vec(2,1), wz = vec(2,2), + n1 = (float)std::pow(1 + l1 + l2 + l3,-power1), + n2 = (float)std::pow(1 + l1 + l2 + l3,-power2); + *(ptrd0++) = n1*(ux*ux + vx*vx) + n2*wx*wx; + *(ptrd1++) = n1*(ux*uy + vx*vy) + n2*wx*wy; + *(ptrd2++) = n1*(ux*uz + vx*vz) + n2*wx*wz; + *(ptrd3++) = n1*(uy*uy + vy*vy) + n2*wy*wy; + *(ptrd4++) = n1*(uy*uz + vy*vz) + n2*wy*wz; + *(ptrd5++) = n1*(uz*uz + vz*vz) + n2*wz*wz; + } + } + } else { // for 2D images + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*256 && + _height>=(cimg_openmp_sizefactor)*256)) + cimg_forY(*this,y) { + Tfloat *ptrd0 = res.data(0,y,0,0), *ptrd1 = res.data(0,y,0,1), *ptrd2 = res.data(0,y,0,2); + CImg val(2), vec(2,2); + cimg_forX(*this,x) { + res.get_tensor_at(x,y).symmetric_eigen(val,vec); + const float + _l1 = val[1], _l2 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, + ux = vec(1,0), uy = vec(1,1), + vx = vec(0,0), vy = vec(0,1), + n1 = (float)std::pow(1 + l1 + l2,-power1), + n2 = (float)std::pow(1 + l1 + l2,-power2); + *(ptrd0++) = n1*ux*ux + n2*vx*vx; + *(ptrd1++) = n1*ux*uy + n2*vx*vy; + *(ptrd2++) = n1*uy*uy + n2*vy*vy; + } + } + } + return res.move_to(*this); + } + + //! Compute field of diffusion tensors for edge-preserving smoothing \newinstance. + CImg get_diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) const { + return CImg(*this,false).diffusion_tensors(sharpness,anisotropy,alpha,sigma,is_sqrt); + } + + //! Estimate displacement field between two images. + /** + \param source Reference image. + \param smoothness Smoothness of estimated displacement field. + \param precision Precision required for algorithm convergence. + \param nb_scales Number of scales used to estimate the displacement field. + \param iteration_max Maximum number of iterations allowed for one scale. + \param is_backward If false, match I2(X + U(X)) = I1(X), else match I2(X) = I1(X - U(X)). + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + **/ + CImg& displacement(const CImg& source, const float smoothness=0.1f, const float precision=5.f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) { + return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward,guide). + move_to(*this); + } + + //! Estimate displacement field between two images \newinstance. + CImg get_displacement(const CImg& source, + const float smoothness=0.1f, const float precision=5.f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) const { + if (is_empty() || !source) return +*this; + if (!is_sameXYZC(source)) + throw CImgArgumentException(_cimg_instance + "displacement(): Instance and source image (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + source._width,source._height,source._depth,source._spectrum,source._data); + if (precision<0) + throw CImgArgumentException(_cimg_instance + "displacement(): Invalid specified precision %g " + "(should be >=0)", + cimg_instance, + precision); + + const bool is_3d = source._depth>1; + const unsigned int constraint = is_3d?3:2; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum0?nb_scales: + (unsigned int)cimg::round(std::log(mins/8.)/std::log(1.5),1,1); + + const float _precision = (float)std::pow(10.,-(double)precision); + float sm, sM = source.max_min(sm), tm, tM = max_min(tm); + const float sdelta = sm==sM?1:(sM - sm), tdelta = tm==tM?1:(tM - tm); + + CImg U, V; + floatT bound = 0; + for (int scale = (int)_nb_scales - 1; scale>=0; --scale) { + const float factor = (float)std::pow(1.5,(double)scale); + const unsigned int + _sw = (unsigned int)(_width/factor), sw = _sw?_sw:1, + _sh = (unsigned int)(_height/factor), sh = _sh?_sh:1, + _sd = (unsigned int)(_depth/factor), sd = _sd?_sd:1; + if (sw<5 && sh<5 && (!is_3d || sd<5)) continue; // Skip too small scales + const CImg + I1 = (source.get_resize(sw,sh,sd,-100,2)-=sm)/=sdelta, + I2 = (get_resize(I1,2)-=tm)/=tdelta; + if (guide._spectrum>constraint) guide.get_resize(I2._width,I2._height,I2._depth,-100,1).move_to(V); + if (U) (U*=1.5f).resize(I2._width,I2._height,I2._depth,-100,3); + else { + if (guide) + guide.get_shared_channels(0,is_3d?2:1).get_resize(I2._width,I2._height,I2._depth,-100,2).move_to(U); + else U.assign(I2._width,I2._height,I2._depth,is_3d?3:2,0); + } + + float dt = 2, energy = cimg::type::max(); + const CImgList dI = is_backward?I1.get_gradient():I2.get_gradient(); + cimg_abort_init; + + for (unsigned int iteration = 0; iteration=0) // Isotropic regularization + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height*_depth>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,_x,_y,_z) if (V(_x,_y,_z,3)) { // Apply constraints + U(_x,_y,_z,0) = V(_x,_y,_z,0)/factor; + U(_x,_y,_z,1) = V(_x,_y,_z,1)/factor; + U(_x,_y,_z,2) = V(_x,_y,_z,2)/factor; + } + } else { // Anisotropic regularization + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height*_depth>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,_x,_y,_z) if (V(_x,_y,_z,3)) { // Apply constraints + U(_x,_y,_z,0) = V(_x,_y,_z,0)/factor; + U(_x,_y,_z,1) = V(_x,_y,_z,1)/factor; + U(_x,_y,_z,2) = V(_x,_y,_z,2)/factor; + } + } + } + } else { // 2D version + if (smoothness>=0) // Isotropic regularization + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXY(V,_x,_y) if (V(_x,_y,2)) { // Apply constraints + U(_x,_y,0) = V(_x,_y,0)/factor; + U(_x,_y,1) = V(_x,_y,1)/factor; + } + } else { // Anisotropic regularization + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*8 && + _width>=(cimg_openmp_sizefactor)*16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXY(V,_x,_y) if (V(_x,_y,2)) { // Apply constraints + U(_x,_y,0) = V(_x,_y,0)/factor; + U(_x,_y,1) = V(_x,_y,1)/factor; + } + } + } + } + const float d_energy = (_energy - energy)/(sw*sh*sd); + if (d_energy<=0 && -d_energy<_precision) break; + if (d_energy>0) dt*=0.5f; + energy = _energy; + } + } + return U; + } + + //! Compute correspondence map between two images, using a patch-matching algorithm. + /** + \param patch_image The image containing the reference patches to match with the instance image. + \param patch_width Width of the patch used for matching. + \param patch_height Height of the patch used for matching. + \param patch_depth Depth of the patch used for matching. + \param nb_iterations Number of patch-match iterations. + \param nb_randoms Number of randomization attempts (per pixel). + \param patch_penalization Penalization factor in score related patch occurrences. + if negative, also tells that identity result is not avoided. + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + \param[out] matching_score Returned as the image of matching scores. + **/ + template + CImg& matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + CImg &matching_score) { + return get_matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide,matching_score).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \newinstance. + template + CImg get_matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + CImg &matching_score) const { + return _matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization, + guide,true,matching_score); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg& matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5, + const float patch_penalization=0, + const CImg &guide=CImg::const_empty()) { + return get_matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg get_matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5, + const float patch_penalization=0, + const CImg &guide=CImg::const_empty()) const { + CImg matching_score; + return _matchpatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,patch_penalization,guide,false,matching_score); + } + + template + CImg _matchpatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth, + const unsigned int nb_iterations, + const unsigned int nb_randoms, + const float patch_penalization, + const CImg &guide, + const bool is_matching_score, + CImg &matching_score) const { + if (is_empty()) return CImg::const_empty(); + if (patch_image._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Instance image and specified patch image (%u,%u,%u,%u,%p) " + "have different spectrums.", + cimg_instance, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + if (patch_width>_width || patch_height>_height || patch_depth>_depth) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the instance image.", + cimg_instance,patch_width,patch_height,patch_depth); + if (patch_width>patch_image._width || patch_height>patch_image._height || patch_depth>patch_image._depth) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the patch image image (%u,%u,%u,%u,%p).", + cimg_instance,patch_width,patch_height,patch_depth, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + const unsigned int + _constraint = patch_image._depth>1?3:2, + constraint = guide._spectrum>_constraint?_constraint:0; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum<_constraint)) + throw CImgArgumentException(_cimg_instance + "matchpatch(): Specified guide (%u,%u,%u,%u,%p) has invalid dimensions " + "considering instance and patch image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + + CImg a_map(_width,_height,_depth,patch_image._depth>1?3:2); + CImg is_updated(_width,_height,_depth,1,3); + CImg score(_width,_height,_depth); + CImg occ; + const float _patch_penalization = cimg::abs(patch_penalization); + const bool allow_identity = patch_penalization>=0; + if (_patch_penalization!=0) occ.assign(patch_image._width,patch_image._height,patch_image._depth,1,0); + const int + psizew = (int)patch_width, psizew1 = psizew/2, psizew2 = psizew - psizew1 - 1, + psizeh = (int)patch_height, psizeh1 = psizeh/2, psizeh2 = psizeh - psizeh1 - 1, + psized = (int)patch_depth, psized1 = psized/2, psized2 = psized - psized1 - 1; + + // Interleave image buffers to speed up patch comparison (cache-friendly). + CImg in_this = get_permute_axes("cxyz"); + in_this._width = _width*_spectrum; + in_this._height = _height; + in_this._depth = _depth; + in_this._spectrum = 1; + CImg in_patch = patch_image.get_permute_axes("cxyz"); + in_patch._width = patch_image._width*patch_image._spectrum; + in_patch._height = patch_image._height; + in_patch._depth = patch_image._depth; + in_patch._spectrum = 1; + + if (_depth>1 || patch_image._depth>1) { // 3D version + + // Initialize correspondence map. + if (guide) + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if_size(_width,64)) + cimg_forXYZ(*this,x,y,z) { // User-defined initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(_width,64)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for cimg_openmp_collapse(2)) + cimg_forXYZ(*this,x,y,z) { // Random initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } + cimg::srand(rng); + } + + // Start iteration loop. + cimg_abort_init; + for (unsigned int iter = 0; iter=(cimg_openmp_sizefactor)*64 && + iter0 && (is_updated(x - 1,y,z)&cmask)) { // Compare with left neighbor + u = a_map(x - 1,y,z,0); + v = a_map(x - 1,y,z,1); + w = a_map(x - 1,y,z,2); + if (u>=cx1 - 1 && u=cy1 && v=cz1 && w0 && (is_updated(x,y - 1,z)&cmask)) { // Compare with up neighbor + u = a_map(x,y - 1,z,0); + v = a_map(x,y - 1,z,1); + w = a_map(x,y - 1,z,2); + if (u>=cx1 && u=cy1 - 1 && v=cz1 && w0 && (is_updated(x,y,z - 1)&cmask)) { // Compare with backward neighbor + u = a_map(x,y,z - 1,0); + v = a_map(x,y,z - 1,1); + w = a_map(x,y,z - 1,2); + if (u>=cx1 && u=cy1 && v=cz1 - 1 && w=cx1 + 1 && u=cy1 && v=cz1 && w=cx1 && u=cy1 + 1 && v=cz1 && w=cx1 && u=cy1 && v=cz1 + 1 && w::inf()); + } else cimg_pragma_openmp(parallel cimg_openmp_if_size(_width,64)) { + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + +#if cimg_use_openmp!=0 + rng+=omp_get_thread_num(); +#endif + cimg_pragma_openmp(for) + cimg_forXY(*this,x,y) { // Random initialization + const int + cx1 = x<=psizew1?x:(x::inf()); + } + cimg::srand(rng); + } + + // Start iteration loop. + cimg_abort_init; + for (unsigned int iter = 0; iter=(cimg_openmp_sizefactor)*64 && + iter0 && (is_updated(x - 1,y)&cmask)) { // Compare with left neighbor + u = a_map(x - 1,y,0); + v = a_map(x - 1,y,1); + if (u>=cx1 - 1 && u=cy1 && v0 && (is_updated(x,y - 1)&cmask)) { // Compare with up neighbor + u = a_map(x,y - 1,0); + v = a_map(x,y - 1,1); + if (u>=cx1 && u=cy1 - 1 && v=cx1 + 1 && u=cy1 && v=cx1 && u=cy1 + 1 && v& img1, const CImg& img2, const CImg& occ, + const unsigned int psizew, const unsigned int psizeh, + const unsigned int psized, const unsigned int psizec, + const int x1, const int y1, const int z1, + const int x2, const int y2, const int z2, + const int xc, const int yc, const int zc, + const float patch_penalization, + const bool allow_identity, + const float max_score) { // 3D version + if (!allow_identity && cimg::hypot((float)x1-x2,(float)y1-y2,(float)z1-z2)::inf(); + const T *p1 = img1.data(x1*psizec,y1,z1), *p2 = img2.data(x2*psizec,y2,z2); + const unsigned int psizewc = psizew*psizec; + const ulongT + offx1 = (ulongT)img1._width - psizewc, + offx2 = (ulongT)img2._width - psizewc, + offy1 = (ulongT)img1._width*img1._height - (ulongT)psizeh*img1._width, + offy2 = (ulongT)img2._width*img2._height - (ulongT)psizeh*img2._width; + float ssd = 0; + for (unsigned int k = 0; kmax_score) return max_score; + p1+=offx1; p2+=offx2; + } + p1+=offy1; p2+=offy2; + } + return patch_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + + patch_penalization*psizewc*psizeh*psized*occ(xc,yc,zc)/100); + } + + static float _matchpatch(const CImg& img1, const CImg& img2, const CImg& occ, + const unsigned int psizew, const unsigned int psizeh, const unsigned int psizec, + const int x1, const int y1, + const int x2, const int y2, + const int xc, const int yc, + const float patch_penalization, + const bool allow_identity, + const float max_score) { // 2D version + if (!allow_identity && cimg::hypot((float)x1-x2,(float)y1-y2)::inf(); + const T *p1 = img1.data(x1*psizec,y1), *p2 = img2.data(x2*psizec,y2); + const unsigned int psizewc = psizew*psizec; + const ulongT + offx1 = (ulongT)img1._width - psizewc, + offx2 = (ulongT)img2._width - psizewc; + float ssd = 0; + for (unsigned int j = 0; jmax_score) return max_score; + p1+=offx1; p2+=offx2; + } + return patch_penalization==0?ssd:cimg::sqr(std::sqrt(ssd) + + patch_penalization*psizewc*psizeh*occ(xc,yc)/100); + } + + //! Compute Euclidean distance function to a specified value. + /** + \param value Reference value. + \param metric Type of metric. Can be { 0=Chebyshev | 1=Manhattan | 2=Euclidean | 3=Squared-euclidean }. + \note + The distance transform implementation has been submitted by A. Meijster, and implements + the article 'W.H. Hesselink, A. Meijster, J.B.T.M. Roerdink, + "A general algorithm for computing distance transforms in linear time.", + In: Mathematical Morphology and its Applications to Image and Signal Processing, + J. Goutsias, L. Vincent, and D.S. Bloomberg (eds.), Kluwer, 2000, pp. 331-340.' + The submitted code has then been modified to fit CImg coding style and constraints. + **/ + CImg& distance(const T& value, const unsigned int metric=2) { + if (is_empty()) return *this; + if (cimg::type::string()!=pixel_type()) // For datatype < int + return CImg(*this,false).distance((Tint)value,metric). + cut((Tint)cimg::type::min(),(Tint)cimg::type::max()).move_to(*this); + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,(T)0:(T)std::max(0,99999999); // (avoid VC++ warning) + if (!is_value) return fill(cimg::type::max()); + switch (metric) { + case 0 : return _distance_core(_distance_sep_cdt,_distance_dist_cdt); // Chebyshev + case 1 : return _distance_core(_distance_sep_mdt,_distance_dist_mdt); // Manhattan + case 3 : return _distance_core(_distance_sep_edt,_distance_dist_edt); // Squared Euclidean + default : return _distance_core(_distance_sep_edt,_distance_dist_edt).sqrt(); // Euclidean + } + return *this; + } + + //! Compute distance to a specified value \newinstance. + CImg get_distance(const T& value, const unsigned int metric=2) const { + return CImg(*this,false).distance((Tfloat)value,metric); + } + + static longT _distance_sep_edt(const longT i, const longT u, const longT *const g) { + return (u*u - i*i + g[u] - g[i])/(2*(u - i)); + } + + static longT _distance_dist_edt(const longT x, const longT i, const longT *const g) { + return (x - i)*(x - i) + g[i]; + } + + static longT _distance_sep_mdt(const longT i, const longT u, const longT *const g) { + return (u - i<=g[u] - g[i]?999999999:(g[u] - g[i] + u + i)/2); + } + + static longT _distance_dist_mdt(const longT x, const longT i, const longT *const g) { + return (x=0) && f(t[q],s[q],g)>f(t[q],u,g)) { --q; } + if (q<0) { q = 0; s[0] = u; } + else { const longT w = 1 + sep(s[q], u, g); if (w<(longT)len) { ++q; s[q] = u; t[q] = w; }} + } + for (int u = (int)len - 1; u>=0; --u) { dt[u] = f(u,s[q],g); if (u==t[q]) --q; } // Backward scan + } + + CImg& _distance_core(longT (*const sep)(const longT, const longT, const longT *const), + longT (*const f)(const longT, const longT, const longT *const)) { + // Check for g++ 4.9.X, as OpenMP seems to crash for this particular function. I have no clues why. +#define cimg_is_gcc49x (__GNUC__==4 && __GNUC_MINOR__==9) + + const ulongT wh = (ulongT)_width*_height; +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) +#endif + cimg_forC(*this,c) { + CImg g(_width), dt(_width), s(_width), t(_width); + CImg img = get_shared_channel(c); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) cimg_openmp_if(_width>=(cimg_openmp_sizefactor)*512 && + _height*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forYZ(*this,y,z) { // Over X-direction + cimg_forX(*this,x) g[x] = (longT)img(x,y,z,0,wh); + _distance_scan(_width,g,sep,f,s,t,dt); + cimg_forX(*this,x) img(x,y,z,0,wh) = (T)dt[x]; + } + if (_height>1) { + g.assign(_height); dt.assign(_height); s.assign(_height); t.assign(_height); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_height>=(cimg_openmp_sizefactor)*512 && _width*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXZ(*this,x,z) { // Over Y-direction + cimg_forY(*this,y) g[y] = (longT)img(x,y,z,0,wh); + _distance_scan(_height,g,sep,f,s,t,dt); + cimg_forY(*this,y) img(x,y,z,0,wh) = (T)dt[y]; + } + } + if (_depth>1) { + g.assign(_depth); dt.assign(_depth); s.assign(_depth); t.assign(_depth); +#if cimg_use_openmp!=0 && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if(_depth>=(cimg_openmp_sizefactor)*512 && _width*_height>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXY(*this,x,y) { // Over Z-direction + cimg_forZ(*this,z) g[z] = (longT)img(x,y,z,0,wh); + _distance_scan(_depth,g,sep,f,s,t,dt); + cimg_forZ(*this,z) img(x,y,z,0,wh) = (T)dt[z]; + } + } + } + return *this; + } + + //! Compute chamfer distance to a specified value, with a custom metric. + /** + \param value Reference value. + \param metric_mask Metric mask. + \note The algorithm code has been initially proposed by A. Meijster, and modified by D. Tschumperlé. + **/ + template + CImg& distance(const T& value, const CImg& metric_mask) { + if (is_empty()) return *this; + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,0:(T)999999999; + if (!is_value) return fill(cimg::type::max()); + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg img = get_shared_channel(c); + cimg_pragma_openmp(parallel for cimg_openmp_collapse(3) + cimg_openmp_if(_width*_height*_depth>=(cimg_openmp_sizefactor)*1024)) + cimg_forXYZ(metric_mask,dx,dy,dz) { + const t weight = metric_mask(dx,dy,dz); + if (weight) { + for (int z = dz, nz = 0; z=0; --z,--nz) { // Backward scan + for (int y = height() - 1 - dy, ny = height() - 1; y>=0; --y,--ny) { + for (int x = width() - 1 - dx, nx = width() - 1; x>=0; --x,--nx) { + const T dd = img(nx,ny,nz,0,wh) + weight; + if (dd + CImg get_distance(const T& value, const CImg& metric_mask) const { + return CImg(*this,false).distance(value,metric_mask); + } + + //! Compute distance to a specified value, according to a custom metric (use dijkstra algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + \param is_high_connectivity Tells if the algorithm uses low or high connectivity. + \param[out] return_path An image containing the nodes of the minimal path. + **/ + template + CImg& distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) { + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm) \newinstance. + template + CImg::type> + get_distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) const { + if (is_empty()) return return_path.assign(); + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_dijkstra(): image instance and metric map (%u,%u,%u,%u) " + "have incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + typedef typename cimg::superset::type td; // Type used for computing cumulative distances + CImg result(_width,_height,_depth,_spectrum), Q; + CImg is_queued(_width,_height,_depth,1); + if (return_path) return_path.assign(_width,_height,_depth,_spectrum); + + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + CImg path = return_path?return_path.get_shared_channel(c):CImg(); + unsigned int sizeQ = 0; + + // Detect initial seeds. + is_queued.fill(0); + cimg_forXYZ(img,x,y,z) if (img(x,y,z)==value) { + Q._priority_queue_insert(is_queued,sizeQ,0,x,y,z); + res(x,y,z) = 0; + if (path) path(x,y,z) = (to)0; + } + + // Start distance propagation. + while (sizeQ) { + + // Get and remove point with minimal potential from the queue. + const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3); + const td P = (td)-Q(0,0); + Q._priority_queue_remove(sizeQ); + + // Update neighbors. + td npot = 0; + if (x - 1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x - 1,y,z) + P),x - 1,y,z)) { + res(x - 1,y,z) = npot; if (path) path(x - 1,y,z) = (to)2; + } + if (x + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y - 1,z) + P),x,y - 1,z)) { + res(x,y - 1,z) = npot; if (path) path(x,y - 1,z) = (to)8; + } + if (y + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y,z - 1) + P),x,y,z - 1)) { + res(x,y,z - 1) = npot; if (path) path(x,y,z - 1) = (to)32; + } + if (z + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y - 1,z) + P)),x - 1,y - 1,z)) { + res(x - 1,y - 1,z) = npot; if (path) path(x - 1,y - 1,z) = (to)10; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x + 1,y - 1,z) + P)),x + 1,y - 1,z)) { + res(x + 1,y - 1,z) = npot; if (path) path(x + 1,y - 1,z) = (to)9; + } + if (x - 1>=0 && y + 1=0) { // Diagonal neighbors on slice z - 1 + if (x - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z - 1) + P)),x - 1,y,z - 1)) { + res(x - 1,y,z - 1) = npot; if (path) path(x - 1,y,z - 1) = (to)34; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z - 1) + P)),x,y - 1,z - 1)) { + res(x,y - 1,z - 1) = npot; if (path) path(x,y - 1,z - 1) = (to)40; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z - 1) + P)), + x - 1,y - 1,z - 1)) { + res(x - 1,y - 1,z - 1) = npot; if (path) path(x - 1,y - 1,z - 1) = (to)42; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z - 1) + P)), + x + 1,y - 1,z - 1)) { + res(x + 1,y - 1,z - 1) = npot; if (path) path(x + 1,y - 1,z - 1) = (to)41; + } + if (x - 1>=0 && y + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z + 1) + P)),x - 1,y,z + 1)) { + res(x - 1,y,z + 1) = npot; if (path) path(x - 1,y,z + 1) = (to)18; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z + 1) + P)),x,y - 1,z + 1)) { + res(x,y - 1,z + 1) = npot; if (path) path(x,y - 1,z + 1) = (to)24; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z + 1) + P)), + x - 1,y - 1,z + 1)) { + res(x - 1,y - 1,z + 1) = npot; if (path) path(x - 1,y - 1,z + 1) = (to)26; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z + 1) + P)), + x + 1,y - 1,z + 1)) { + res(x + 1,y - 1,z + 1) = npot; if (path) path(x + 1,y - 1,z + 1) = (to)25; + } + if (x - 1>=0 && y + 1 + CImg& distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) { + return get_distance_dijkstra(value,metric,is_high_connectivity).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm). \newinstance. + template + CImg get_distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) const { + CImg return_path; + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + **/ + template + CImg& distance_eikonal(const T& value, const CImg& metric) { + return get_distance_eikonal(value,metric).move_to(*this); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + template + CImg get_distance_eikonal(const T& value, const CImg& metric) const { + if (is_empty()) return *this; + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have " + "incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + CImg result(_width,_height,_depth,_spectrum,cimg::type::max()), Q; + CImg state(_width,_height,_depth); // -1=far away, 0=narrow, 1=frozen + + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2) firstprivate(Q,state)) + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + unsigned int sizeQ = 0; + state.fill(-1); + + // Detect initial seeds. + Tfloat *ptr1 = res._data; char *ptr2 = state._data; + cimg_for(img,ptr0,T) { if (*ptr0==value) { *ptr1 = 0; *ptr2 = 1; } ++ptr1; ++ptr2; } + + // Initialize seeds neighbors. + ptr2 = state._data; + cimg_forXYZ(img,x,y,z) if (*(ptr2++)==1) { + if (x - 1>=0 && state(x - 1,y,z)==-1) { + const Tfloat dist = res(x - 1,y,z) = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x - 1,y,z); + } + if (x + 1=0 && state(x,y - 1,z)==-1) { + const Tfloat dist = res(x,y - 1,z) = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y - 1,z); + } + if (y + 1=0 && state(x,y,z - 1)==-1) { + const Tfloat dist = res(x,y,z - 1) = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z - 1); + } + if (z + 1=0) { + if (x - 1>=0 && state(x - 1,y,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + if (dist=0 && state(x,y - 1,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + if (dist=0 && state(x,y,z - 1)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + if (dist& res, const Tfloat P, + const int x=0, const int y=0, const int z=0) const { + const Tfloat M = (Tfloat)cimg::type::max(); + T T1 = (T)std::min(x - 1>=0?res(x - 1,y,z):M,x + 11) { // 3D + T + T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1=0?res(x,y,z - 1):M,z + 1T2) cimg::swap(T1,T2); + if (T2>T3) cimg::swap(T2,T3); + if (T1>T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T31) { // 2D + T T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T2 + void _eik_priority_queue_insert(CImg& state, unsigned int& siz, const t value, + const unsigned int x, const unsigned int y, const unsigned int z) { + if (state(x,y,z)>0) return; + state(x,y,z) = 0; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(t)(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3)); + } + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE. + /** + \param nb_iterations Number of PDE iterations. + \param band_size Size of the narrow band. + \param time_step Time step of the PDE iterations. + **/ + CImg& distance_eikonal(const unsigned int nb_iterations, const float band_size=0, const float time_step=0.5f) { + if (is_empty()) return *this; + CImg velocity(*this,false); + for (unsigned int iteration = 0; iteration1) { // 3D + CImg_3x3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) if (band_size<=0 || cimg::abs(Iccc)0?(Incc - Iccc):(Iccc - Ipcc), + iy = gy*sgn>0?(Icnc - Iccc):(Iccc - Icpc), + iz = gz*sgn>0?(Iccn - Iccc):(Iccc - Iccp), + ng = 1e-5f + cimg::hypot(gx,gy,gz), + ngx = gx/ng, + ngy = gy/ng, + ngz = gz/ng, + veloc = sgn*(ngx*ix + ngy*iy + ngz*iz - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } else { // 2D version + CImg_3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,Tfloat) if (band_size<=0 || cimg::abs(Icc)0?(Inc - Icc):(Icc - Ipc), + iy = gy*sgn>0?(Icn - Icc):(Icc - Icp), + ng = std::max((Tfloat)1e-5,cimg::hypot(gx,gy)), + ngx = gx/ng, + ngy = gy/ng, + veloc = sgn*(ngx*ix + ngy*iy - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } + if (veloc_max>0) *this+=(velocity*=time_step/veloc_max); + } + return *this; + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE \newinstance. + CImg get_distance_eikonal(const unsigned int nb_iterations, const float band_size=0, + const float time_step=0.5f) const { + return CImg(*this,false).distance_eikonal(nb_iterations,band_size,time_step); + } + + //! Compute Haar multiscale wavelet transform. + /** + \param axis Axis considered for the transform. + \param invert Set inverse of direct transform. + \param nb_scales Number of scales used for the transform. + **/ + CImg& haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(axis,invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const { + if (is_empty() || !nb_scales) return +*this; + CImg res; + const Tfloat sqrt2 = std::sqrt(2.f); + if (nb_scales==1) { + switch (cimg::lowercase(axis)) { // Single scale transform + case 'x' : { + const unsigned int w = _width/2; + if (w) { + if ((w%2) && w!=1) + throw CImgInstanceException(_cimg_instance + "haar(): Sub-image width %u is not even.", + cimg_instance, + w); + + res.assign(_width,_height,_depth,_spectrum); + if (invert) cimg_forYZC(*this,y,z,c) { // Inverse transform along X + for (unsigned int x = 0, xw = w, x2 = 0; x& haar(const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const bool invert=false, const unsigned int nb_scales=1) const { + CImg res; + if (nb_scales==1) { // Single scale transform + if (_width>1) get_haar('x',invert,1).move_to(res); + if (_height>1) { if (res) res.haar('y',invert,1); else get_haar('y',invert,1).move_to(res); } + if (_depth>1) { if (res) res.haar('z',invert,1); else get_haar('z',invert,1).move_to(res); } + if (res) return res; + } else { // Multi-scale transform + if (invert) { // Inverse transform + res.assign(*this,false); + if (_width>1) { + if (_height>1) { + if (_depth>1) { + unsigned int w = _width, h = _height, d = _depth; + for (unsigned int s = 1; w && h && d && s1) { + unsigned int w = _width, d = _depth; + for (unsigned int s = 1; w && d && s1) { + if (_depth>1) { + unsigned int h = _height, d = _depth; + for (unsigned int s = 1; h && d && s1) { + unsigned int d = _depth; + for (unsigned int s = 1; d && s1) { + if (_height>1) { + if (_depth>1) + for (unsigned int s = 1, w = _width/2, h = _height/2, d = _depth/2; w && h && d && s1) for (unsigned int s = 1, w = _width/2, d = _depth/2; w && d && s1) { + if (_depth>1) + for (unsigned int s = 1, h = _height/2, d = _depth/2; h && d && s1) for (unsigned int s = 1, d = _depth/2; d && s get_FFT(const char axis, const bool is_inverse=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],axis,is_inverse); + return res; + } + + //! Compute n-D Fast Fourier Transform. + /* + \param is_inverse Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + CImgList get_FFT(const bool is_inverse=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],is_inverse); + return res; + } + + //! Compute 1D Fast Fourier Transform, along a specified axis. + /** + \param[in,out] real Real part of the pixel values. + \param[in,out] imag Imaginary part of the pixel values. + \param axis Axis along which the FFT is computed. + \param is_inverse Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + static void FFT(CImg& real, CImg& imag, const char axis, const bool is_inverse=false, + const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part is empty.", + pixel_type()); + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + const char _axis = cimg::lowercase(axis); + if (_axis!='x' && _axis!='y' && _axis!='z') + throw CImgArgumentException("CImgList<%s>::FFT(): Invalid specified axis '%c' for real and imaginary parts " + "(%u,%u,%u,%u) " + "(should be { x | y | z }).", + pixel_type(),axis, + real._width,real._height,real._depth,real._spectrum); + cimg::unused(nb_threads); +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus()); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) + throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u) along the X-axis.", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width*real._height*real._depth), + real._width,real._height,real._depth,real._spectrum); + double *const ptrf = (double*)data_in; + fftw_plan data_plan = + _axis=='x'?fftw_plan_many_dft(1,(int*)&real._width,real.height()*real.depth(), + data_in,0,1,real.width(), + data_in,0,1,real.width(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + _axis=='y'?fftw_plan_many_dft(1,(int*)&real._height,real.width()*real.depth(), + data_in,0,1,real.height(), + data_in,0,1,real.height(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + fftw_plan_many_dft(1,(int*)&real._depth,real.width()*real.height(), + data_in,0,1,real.depth(), + data_in,0,1,real.depth(), + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + CImg realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c); + switch (_axis) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(x + (ulongT)y*realc._width + (ulongT)z*realc._width*realc._height); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + break; + case 'y' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(y + (ulongT)x*realc._height + (ulongT)z*realc._width*realc._height); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + break; + default : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = realc.offset(x,y,z), + j = 2*(z + (ulongT)x*realc._depth + (ulongT)y*realc._width*realc._depth); + ptrf[j] = (double)realc[i]; + ptrf[j + 1] = (double)imagc[i]; + } + } + + fftw_execute(data_plan); + + const double a = is_inverse?1.0/(_axis=='x'?real.width():_axis=='y'?real.height():real.depth()):1.0; + switch (_axis) { + case 'x' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(x + (ulongT)y*realc._width + (ulongT)z*realc._width*realc._height), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + break; + case 'y' : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(y + (ulongT)x*realc._height + (ulongT)z*realc._width*realc._height), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + break; + default : + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_forXYZ(realc,x,y,z) { + const ulongT + i = 2*(z + (ulongT)x*realc._depth + (ulongT)y*realc._width*realc._depth), + j = realc.offset(x,y,z); + realc[j] = (T)(a*ptrf[i]); + imagc[j] = (T)(a*ptrf[i + 1]); + } + } + } + + fftw_destroy_plan(data_plan); + fftw_free(data_in); +#ifndef cimg_use_fftw3_singlethread + fftw_cleanup_threads(); +#endif + cimg::mutex(12,0); +#else + switch (_axis) { + case 'x' : { // Fourier along X, using built-in functions + const unsigned int N = real._width, N2 = N>>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the X-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forYZC(real,y,z,c) { + cimg::swap(real(i,y,z,c),real(j,y,z,c)); + cimg::swap(imag(i,y,z,c),imag(j,y,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = delta>>1; + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Y-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXZC(real,x,z,c) { + cimg::swap(real(x,i,z,c),real(x,j,z,c)); + cimg::swap(imag(x,i,z,c),imag(x,j,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Z-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXYC(real,x,y,c) { + cimg::swap(real(x,y,i,c),real(x,y,j,c)); + cimg::swap(imag(x,y,i,c),imag(x,y,j,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i& real, CImg& imag, const bool is_inverse=false, + const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImgList<%s>::FFT(): Empty specified real part.", + pixel_type()); + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + cimg::unused(nb_threads); +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + fftw_plan_with_nthreads(nb_threads?nb_threads:cimg::nb_cpus()); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) + throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u).", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width* + real._height*real._depth*real._spectrum), + real._width,real._height,real._depth,real._spectrum); + double *const ptrf = (double*)data_in; + fftw_plan data_plan = + real._depth>1?fftw_plan_dft_3d(real._depth,real._height,real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + real._height>1?fftw_plan_dft_2d(real._height,real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE): + fftw_plan_dft_1d(real._width,data_in,data_in, + is_inverse?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + CImg realc = real.get_shared_channel(c), imagc = imag.get_shared_channel(c); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; ptrf[i2] = (double)realc[i]; ptrf[i2 + 1] = (double)imagc[i]; } + fftw_execute(data_plan); + if (is_inverse) { + const double a = 1.0/(real.width()*real.height()*real.depth()); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)(a*ptrf[i2]); imagc[i] = (T)(a*ptrf[i2 + 1]); } + } else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(real.width()*real.height()*real.depth(),125000)) + cimg_rofoff(realc,i) { const ulongT i2 = 2*i; realc[i] = (T)ptrf[i2]; imagc[i] = (T)ptrf[i2 + 1]; } + } + fftw_destroy_plan(data_plan); + fftw_free(data_in); +#ifndef cimg_use_fftw3_singlethread + fftw_cleanup_threads(); +#endif + cimg::mutex(12,0); +#else + if (real._depth>1) FFT(real,imag,'z',is_inverse); + if (real._height>1) FFT(real,imag,'y',is_inverse); + if (real._width>1) FFT(real,imag,'x',is_inverse); +#endif + } + + //@} + //------------------------------------- + // + //! \name 3D Objects Management + //@{ + //------------------------------------- + + //! Rotate 3D object's vertices. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or second quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + CImg& rotate_object3d(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + return get_rotate_object3d(x,y,z,w,is_quaternion).move_to(*this); + } + + CImg get_rotate_object3d(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) const { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "rotate_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + return CImg::rotation_matrix(x,y,z,w,is_quaternion)**this; + } + + //! Shift 3D object's vertices. + /** + \param tx X-coordinate of the 3D displacement vector. + \param ty Y-coordinate of the 3D displacement vector. + \param tz Z-coordinate of the 3D displacement vector. + **/ + CImg& shift_object3d(const float tx, const float ty=0, const float tz=0) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + get_shared_row(0)+=tx; get_shared_row(1)+=ty; get_shared_row(2)+=tz; + return *this; + } + + //! Shift 3D object's vertices \newinstance. + CImg get_shift_object3d(const float tx, const float ty=0, const float tz=0) const { + return CImg(*this,false).shift_object3d(tx,ty,tz); + } + + //! Shift 3D object's vertices, so that it becomes centered. + /** + \note The object center is computed as its barycenter. + **/ + CImg& shift_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + xcoords-=(xm + xM)/2; ycoords-=(ym + yM)/2; zcoords-=(zm + zM)/2; + return *this; + } + + //! Shift 3D object's vertices, so that it becomes centered \newinstance. + CImg get_shift_object3d() const { + return CImg(*this,false).shift_object3d(); + } + + //! Resize 3D object. + /** + \param sx Width of the 3D object's bounding box. + \param sy Height of the 3D object's bounding box. + \param sz Depth of the 3D object's bounding box. + **/ + CImg& resize_object3d(const float sx, const float sy=-100, const float sz=-100) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + if (xm0) xcoords*=sx/(xM-xm); else xcoords*=-sx/100; } + if (ym0) ycoords*=sy/(yM-ym); else ycoords*=-sy/100; } + if (zm0) zcoords*=sz/(zM-zm); else zcoords*=-sz/100; } + return *this; + } + + //! Resize 3D object \newinstance. + CImg get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const { + return CImg(*this,false).resize_object3d(sx,sy,sz); + } + + //! Resize 3D object to unit size. + CImg resize_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + const float dx = xM - xm, dy = yM - ym, dz = zM - zm, dmax = cimg::max(dx,dy,dz); + if (dmax>0) { xcoords/=dmax; ycoords/=dmax; zcoords/=dmax; } + return *this; + } + + //! Resize 3D object to unit size \newinstance. + CImg get_resize_object3d() const { + return CImg(*this,false).resize_object3d(); + } + + //! Merge two 3D objects together. + /** + \param[in,out] primitives Primitives data of the current 3D object. + \param obj_vertices Vertices data of the additional 3D object. + \param obj_primitives Primitives data of the additional 3D object. + **/ + template + CImg& append_object3d(CImgList& primitives, const CImg& obj_vertices, + const CImgList& obj_primitives) { + if (!obj_vertices || !obj_primitives) return *this; + if (obj_vertices._height!=3 || obj_vertices._depth>1 || obj_vertices._spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Specified vertice image (%u,%u,%u,%u,%p) is not a " + "set of 3D vertices.", + cimg_instance, + obj_vertices._width,obj_vertices._height, + obj_vertices._depth,obj_vertices._spectrum,obj_vertices._data); + + if (is_empty()) { primitives.assign(obj_primitives); return assign(obj_vertices); } + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Instance is not a set of 3D vertices.", + cimg_instance); + + const unsigned int P = _width; + append(obj_vertices,'x'); + const unsigned int N = primitives._width; + primitives.insert(obj_primitives); + for (unsigned int i = N; i &p = primitives[i]; + switch (p.size()) { + case 1 : p[0]+=P; break; // Point + case 5 : p[0]+=P; p[1]+=P; break; // Sphere + case 2 : case 6 : p[0]+=P; p[1]+=P; break; // Segment + case 3 : case 9 : p[0]+=P; p[1]+=P; p[2]+=P; break; // Triangle + case 4 : case 12 : p[0]+=P; p[1]+=P; p[2]+=P; p[3]+=P; break; // Rectangle + } + } + return *this; + } + + //! Texturize primitives of a 3D object. + /** + \param[in,out] primitives Primitives data of the 3D object. + \param[in,out] colors Colors data of the 3D object. + \param texture Texture image to map to 3D object. + \param coords Texture-mapping coordinates. + **/ + template + const CImg& texturize_object3d(CImgList& primitives, CImgList& colors, + const CImg& texture, const CImg& coords=CImg::const_empty()) const { + if (is_empty()) return *this; + if (_height!=3) + throw CImgInstanceException(_cimg_instance + "texturize_object3d(): image instance is not a set of 3D points.", + cimg_instance); + if (coords && (coords._width!=_width || coords._height!=2)) + throw CImgArgumentException(_cimg_instance + "texturize_object3d(): Invalid specified texture coordinates (%u,%u,%u,%u,%p).", + cimg_instance, + coords._width,coords._height,coords._depth,coords._spectrum,coords._data); + CImg _coords; + if (!coords) { // If no texture coordinates specified, do a default XY-projection + _coords.assign(_width,2); + float + xmin, xmax = (float)get_shared_row(0).max_min(xmin), + ymin, ymax = (float)get_shared_row(1).max_min(ymin), + dx = xmax>xmin?xmax-xmin:1, + dy = ymax>ymin?ymax-ymin:1; + cimg_forX(*this,p) { + _coords(p,0) = (int)(((*this)(p,0) - xmin)*texture._width/dx); + _coords(p,1) = (int)(((*this)(p,1) - ymin)*texture._height/dy); + } + } else _coords = coords; + + int texture_ind = -1; + cimglist_for(primitives,l) { + CImg &p = primitives[l]; + const unsigned int siz = p.size(); + switch (siz) { + case 1 : { // Point + const unsigned int i0 = (unsigned int)p[0]; + const int x0 = _coords(i0,0), y0 = _coords(i0,1); + texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).move_to(colors[l]); + } break; + case 2 : case 6 : { // Line + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,x0,y0,x1,y1).move_to(p); + } break; + case 3 : case 9 : { // Triangle + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,x0,y0,x1,y1,x2,y2).move_to(p); + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2], i3 = (unsigned int)p[3]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1), + x3 = _coords(i3,0), y3 = _coords(i3,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,i3,x0,y0,x1,y1,x2,y2,x3,y3).move_to(p); + } break; + } + } + return *this; + } + + //! Generate a 3D elevation of the image instance. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param[out] colors The returned list of the 3D object colors. + \param elevation The input elevation map. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + CImgList colors3d; + const CImg points3d = img.get_elevation3d(faces3d,colors3d,img.get_norm()*0.2); + CImg().display_object3d("Elevation3d",points3d,faces3d,colors3d); + \endcode + \image html ref_elevation3d.jpg + **/ + template + CImg get_elevation3d(CImgList& primitives, CImgList& colors, const CImg& elevation) const { + if (!is_sameXY(elevation) || elevation._depth>1 || elevation._spectrum>1) + throw CImgArgumentException(_cimg_instance + "get_elevation3d(): Instance and specified elevation (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + elevation._width,elevation._height,elevation._depth, + elevation._spectrum,elevation._data); + if (is_empty()) return *this; + float m, M = (float)max_min(m); + if (M==m) ++M; + colors.assign(); + const unsigned int size_x1 = _width - 1, size_y1 = _height - 1; + for (unsigned int y = 0; y1?((*this)(x,y,1) - m)*255/(M-m):r), + b = (unsigned char)(_spectrum>2?((*this)(x,y,2) - m)*255/(M-m):_spectrum>1?0:r); + CImg::vector((tc)r,(tc)g,(tc)b).move_to(colors); + } + const typename CImg::_functor2d_int func(elevation); + return elevation3d(primitives,func,0,0,_width - 1.f,_height - 1.f,_width,_height); + } + + //! Generate the 3D projection planes of the image instance. + /** + \param[out] primitives Primitives data of the returned 3D object. + \param[out] colors Colors data of the returned 3D object. + \param x0 X-coordinate of the projection point. + \param y0 Y-coordinate of the projection point. + \param z0 Z-coordinate of the projection point. + \param normalize_colors Tells if the created textures have normalized colors. + **/ + template + CImg get_projections3d(CImgList& primitives, CImgList& colors, + const unsigned int x0, const unsigned int y0, const unsigned int z0, + const bool normalize_colors=false) const { + float m = 0, M = 0, delta = 1; + if (normalize_colors) { m = (float)min_max(M); delta = 255/(m==M?1:M-m); } + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + CImg img_xy, img_xz, img_yz; + if (normalize_colors) { + ((get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1)-=m)*=delta).move_to(img_xy); + ((get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_width,_depth,1,-100,-1). + move_to(img_xz); + ((get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_height,_depth,1,-100,-1). + move_to(img_yz); + } else { + get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1).move_to(img_xy); + get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1).move_to(img_xz); + get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).resize(_height,_depth,1,-100,-1).move_to(img_yz); + } + CImg points(12,3,1,1, + 0,_width - 1,_width - 1,0, 0,_width - 1,_width - 1,0, _x0,_x0,_x0,_x0, + 0,0,_height - 1,_height - 1, _y0,_y0,_y0,_y0, 0,_height - 1,_height - 1,0, + _z0,_z0,_z0,_z0, 0,0,_depth - 1,_depth - 1, 0,0,_depth - 1,_depth - 1); + primitives.assign(); + CImg::vector(0,1,2,3,0,0,img_xy._width - 1,0,img_xy._width - 1,img_xy._height - 1,0,img_xy._height - 1). + move_to(primitives); + CImg::vector(4,5,6,7,0,0,img_xz._width - 1,0,img_xz._width - 1,img_xz._height - 1,0,img_xz._height - 1). + move_to(primitives); + CImg::vector(8,9,10,11,0,0,img_yz._width - 1,0,img_yz._width - 1,img_yz._height - 1,0,img_yz._height - 1). + move_to(primitives); + colors.assign(); + img_xy.move_to(colors); + img_xz.move_to(colors); + img_yz.move_to(colors); + return points; + } + + //! Generate a isoline of the image instance as a 3D object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3D object colors. + \param size_x The number of subdivisions along the X-axis. + \param size_y The number of subdisivions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + const CImg points3d = img.get_isoline3d(faces3d,100); + CImg().display_object3d("Isoline3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isoline3d.jpg + **/ + template + CImg get_isoline3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a scalar image.", + cimg_instance); + if (_depth>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a 2D image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100) || (size_x==width() && size_y==height())) { + const _functor2d_int func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.f,height() - 1.f,width(),height()); + } else { + const _functor2d_float func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.f,height() - 1.f,size_x,size_y); + } + return vertices; + } + + //! Compute isolines of a function, as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Elevation functor. Must have operator()(x,y) defined. + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static CImg isoline3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + CImgList vertices; + primitives.assign(); + typename CImg::_functor_isoline3d add_vertex(vertices); + typename CImg::_functor_isoline3d add_segment(primitives); + isoline3d(add_vertex,add_segment,func,isovalue,x0,y0,x1,y1,size_x,size_y); + return vertices>'x'; + } + + //! Compute isolines of a function, as a 3D object. + /** + \param[out] add_vertex : Functor with operator()(x,y,z) defined for adding new vertex. + \param[out] add_segment : Functor with operator()(i,j) defined for adding new segment. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static void isoline3d(tv& add_vertex, tf& add_segment, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x, const int size_y) { + static const unsigned int edges[16] = { 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc, + 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 }; + static const int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 }, + { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 }, + { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 }, + { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } }; + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nxm1 = nx - 1, + nym1 = ny - 1; + + if (!nxm1 || !nym1) return; + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1; + CImg indices1(nx,1,1,2,-1), indices2(nx,1,1,2); + CImg values1(nx), values2(nx); + float X = x0, Y = y0, nX = X + dx, nY = Y + dy; + int nb_vertices = 0; + + // Fill first line with values + cimg_forX(values1,x) { values1(x) = (float)func(X,Y); X+=dx; } + + // Run the marching squares algorithm + for (unsigned int yi = 0, nyi = 1; yi + static CImg isoline3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return isoline3d(primitives,func,isovalue,x0,y0,x1,y1,size_x,size_y); + } + + template + static int _isoline3d_index(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int nx) { + switch (edge) { + case 0 : return (int)indices1(x,0); + case 1 : return (int)indices1(nx,1); + case 2 : return (int)indices2(x,0); + case 3 : return (int)indices1(x,1); + } + return 0; + } + + //! Generate an isosurface of the image instance as a 3D object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3D object colors. + \param size_x Number of subdivisions along the X-axis. + \param size_y Number of subdisivions along the Y-axis. + \param size_z Number of subdisivions along the Z-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img = CImg("reference.jpg").resize(-100,-100,20); + CImgList faces3d; + const CImg points3d = img.get_isosurface3d(faces3d,100); + CImg().display_object3d("Isosurface3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isosurface3d.jpg + **/ + template + CImg get_isosurface3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100, const int size_z=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isosurface3d(): Instance is not a scalar image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100 && size_z==-100) || (size_x==width() && size_y==height() && size_z==depth())) { + const _functor3d_int func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f, + width(),height(),depth()); + } else { + const _functor3d_float func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.f,height() - 1.f,depth() - 1.f, + size_x,size_y,size_z); + } + return vertices; + } + + //! Compute isosurface of a function, as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static CImg isosurface3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x=32, const int size_y=32, const int size_z=32) { + CImgList vertices; + primitives.assign(); + typename CImg::_functor_isosurface3d add_vertex(vertices); + typename CImg::_functor_isosurface3d add_triangle(primitives); + isosurface3d(add_vertex,add_triangle,func,isovalue,x0,y0,z0,x1,y1,z1,size_x,size_y,size_z); + return vertices>'x'; + } + + //! Compute isosurface of a function, as a 3D object. + /** + \param[out] add_vertex : Functor with operator()(x,y,z) defined for adding new vertex. + \param[out] add_triangle : Functor with operator()(i,j) defined for adding new segment. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static void isosurface3d(tv& add_vertex, tf& add_triangle, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x, const int size_y, const int size_z) { + static const unsigned int edges[256] = { + 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, + 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, + 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, + 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, + 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, + 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, + 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, + 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, + 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, + 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, + 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, + 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, + 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, + 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 + }; + + static const int triangles[256][16] = { + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, + { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, + { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, + { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, + { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, + { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, + { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, + { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, + { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, + { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, + { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, + { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, + { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, + { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, + { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, + { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, + { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, + { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, + { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, + { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, + { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, + { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, + { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, + { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, + { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, + { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, + { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, + { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, + { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, + { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, + { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, + { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, + { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, + { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, + { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, + { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, + { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, + { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, + { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, + { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, + { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, + { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, + { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, + { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, + { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, + { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, + { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, + { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, + { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, + { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, + { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, + { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, + { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, + { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, + { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, + { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, + { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, + { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, + { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, + { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, + { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, + { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, + { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, + { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, + { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, + { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, + { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, + { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, + { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, + { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, + { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, + { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, + { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, + { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, + { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, + { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, + { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, + { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, + { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, + { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, + { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, + { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, + { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, + { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, + { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, + { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, + { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, + { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, + { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, + { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, + { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, + { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, + { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } + }; + + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + _nz = (unsigned int)(size_z>=0?size_z:cimg::round((z1-z0)*-size_z/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nz = _nz?_nz:1, + nxm1 = nx - 1, + nym1 = ny - 1, + nzm1 = nz - 1; + if (!nxm1 || !nym1 || !nzm1) return; + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1, dz = (z1 - z0)/nzm1; + CImg indices1(nx,ny,1,3,-1), indices2(indices1); + CImg values1(nx,ny), values2(nx,ny); + float X = 0, Y = 0, Z = 0, nX = 0, nY = 0, nZ = 0; + int nb_vertices = 0; + + // Fill the first plane with function values + Y = y0; + cimg_forY(values1,y) { + X = x0; + cimg_forX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=dx; } + Y+=dy; + } + + // Run Marching Cubes algorithm + Z = z0; nZ = Z + dz; + for (unsigned int zi = 0; zi + static CImg isosurface3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int dx=32, const int dy=32, const int dz=32) { + const _functor3d_expr func(expression); + return isosurface3d(primitives,func,isovalue,x0,y0,z0,x1,y1,z1,dx,dy,dz); + } + + template + static int _isosurface3d_index(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int y, + const unsigned int nx, const unsigned int ny) { + switch (edge) { + case 0 : return indices1(x,y,0); + case 1 : return indices1(nx,y,1); + case 2 : return indices1(x,ny,0); + case 3 : return indices1(x,y,1); + case 4 : return indices2(x,y,0); + case 5 : return indices2(nx,y,1); + case 6 : return indices2(x,ny,0); + case 7 : return indices2(x,y,1); + case 8 : return indices1(x,y,2); + case 9 : return indices1(nx,y,2); + case 10 : return indices1(nx,ny,2); + case 11 : return indices1(x,ny,2); + } + return 0; + } + + // Define functors for accessing image values (used in previous functions). + struct _functor2d_int { + const CImg& ref; + _functor2d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref((int)x,(int)y); + } + }; + + struct _functor2d_float { + const CImg& ref; + _functor2d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref._linear_atXY(x,y); + } + }; + + struct _functor2d_expr { + _cimg_math_parser *mp; + ~_functor2d_expr() { mp->end(); delete mp; } + _functor2d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y) const { + return (float)(*mp)(x,y,0,0); + } + }; + + struct _functor3d_int { + const CImg& ref; + _functor3d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref((int)x,(int)y,(int)z); + } + }; + + struct _functor3d_float { + const CImg& ref; + _functor3d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref._linear_atXYZ(x,y,z); + } + }; + + struct _functor3d_expr { + _cimg_math_parser *mp; + ~_functor3d_expr() { mp->end(); delete mp; } + _functor3d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z) const { + return (float)(*mp)(x,y,z,0); + } + }; + + struct _functor4d_int { + const CImg& ref; + _functor4d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref((int)x,(int)y,(int)z,c); + } + }; + + struct _functor_isoline3d { + CImgList& list; + _functor_isoline3d(CImgList& _list):list(_list) {} + template + void operator()(const t x, const t y, const t z) { CImg::vector((T)x,(T)y,(T)z).move_to(list); } + template + void operator()(const t i, const t j) { CImg::vector((T)i,(T)j).move_to(list); } + }; + + struct _functor_isosurface3d { + CImgList& list; + _functor_isosurface3d(CImgList& _list):list(_list) {} + template + void operator()(const t x, const t y, const t z) { CImg::vector((T)x,(T)y,(T)z).move_to(list); } + }; + + //! Compute 3D elevation of a function as a 3D object. + /** + \param[out] primitives Primitives data of the resulting 3D object. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + **/ + template + static CImg elevation3d(CImgList& primitives, const tfunc& func, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const float + nx0 = x0=0?size_x:(nx1-nx0)*-size_x/100), + nsize_x = _nsize_x?_nsize_x:1, nsize_x1 = nsize_x - 1, + _nsize_y = (unsigned int)(size_y>=0?size_y:(ny1-ny0)*-size_y/100), + nsize_y = _nsize_y?_nsize_y:1, nsize_y1 = nsize_y - 1; + if (nsize_x<2 || nsize_y<2) + throw CImgArgumentException("CImg<%s>::elevation3d(): Invalid specified size (%d,%d).", + pixel_type(), + nsize_x,nsize_y); + + CImg vertices(nsize_x*nsize_y,3); + floatT *ptr_x = vertices.data(0,0), *ptr_y = vertices.data(0,1), *ptr_z = vertices.data(0,2); + for (unsigned int y = 0; y + static CImg elevation3d(CImgList& primitives, const char *const expression, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return elevation3d(primitives,func,x0,y0,x1,y1,size_x,size_y); + } + + //! Generate a 3D box object. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the box (dimension along the X-axis). + \param size_y The height of the box (dimension along the Y-axis). + \param size_z The depth of the box (dimension along the Z-axis). + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::box3d(faces3d,10,20,30); + CImg().display_object3d("Box3d",points3d,faces3d); + \endcode + \image html ref_box3d.jpg + **/ + template + static CImg box3d(CImgList& primitives, + const float size_x=200, const float size_y=100, const float size_z=100) { + primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 0,1,5,4, 3,7,6,2, 0,4,7,3, 1,2,6,5); + return CImg(8,3,1,1, + 0.,size_x,size_x, 0., 0.,size_x,size_x, 0., + 0., 0.,size_y,size_y, 0., 0.,size_y,size_y, + 0., 0., 0., 0.,size_z,size_z,size_z,size_z); + } + + //! Generate a 3D cone. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cone basis. + \param size_z The cone's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cone3d(faces3d,50); + CImg().display_object3d("Cone3d",points3d,faces3d); + \endcode + \image html ref_cone3d.jpg + **/ + template + static CImg cone3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,size_z, + 0.,0.,0.); + for (float delta = 360.f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0).move_to(vertices); + } + const unsigned int nbr = vertices._width - 2; + for (unsigned int p = 0; p::vector(1,next,curr).move_to(primitives); + CImg::vector(0,curr,next).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D cylinder. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cylinder basis. + \param size_z The cylinder's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cylinder3d(faces3d,50); + CImg().display_object3d("Cylinder3d",points3d,faces3d); + \endcode + \image html ref_cylinder3d.jpg + **/ + template + static CImg cylinder3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,0., + 0.,0.,size_z); + for (float delta = 360.f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0.f).move_to(vertices); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),size_z).move_to(vertices); + } + const unsigned int nbr = (vertices._width - 2)/2; + for (unsigned int p = 0; p::vector(0,next,curr).move_to(primitives); + CImg::vector(1,curr + 1,next + 1).move_to(primitives); + CImg::vector(curr,next,next + 1,curr + 1).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D torus. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius1 The large radius. + \param radius2 The small radius. + \param subdivisions1 The number of angular subdivisions for the large radius. + \param subdivisions2 The number of angular subdivisions for the small radius. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::torus3d(faces3d,20,4); + CImg().display_object3d("Torus3d",points3d,faces3d); + \endcode + \image html ref_torus3d.jpg + **/ + template + static CImg torus3d(CImgList& primitives, + const float radius1=100, const float radius2=30, + const unsigned int subdivisions1=24, const unsigned int subdivisions2=12) { + primitives.assign(); + if (!subdivisions1 || !subdivisions2) return CImg(); + CImgList vertices; + for (unsigned int v = 0; v::vector(x,y,z).move_to(vertices); + } + } + for (unsigned int vv = 0; vv::vector(svv + nu,svv + uu,snv + uu,snv + nu).move_to(primitives); + } + } + return vertices>'x'; + } + + //! Generate a 3D XY-plane. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the plane (dimension along the X-axis). + \param size_y The height of the plane (dimensions along the Y-axis). + \param subdivisions_x The number of planar subdivisions along the X-axis. + \param subdivisions_y The number of planar subdivisions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::plane3d(faces3d,100,50); + CImg().display_object3d("Plane3d",points3d,faces3d); + \endcode + \image html ref_plane3d.jpg + **/ + template + static CImg plane3d(CImgList& primitives, + const float size_x=100, const float size_y=100, + const unsigned int subdivisions_x=10, const unsigned int subdivisions_y=10) { + primitives.assign(); + if (!subdivisions_x || !subdivisions_y) return CImg(); + CImgList vertices; + const unsigned int w = subdivisions_x + 1, h = subdivisions_y + 1; + const float fx = (float)size_x/w, fy = (float)size_y/h; + for (unsigned int y = 0; y::vector(fx*x,fy*y,0).move_to(vertices); + for (unsigned int y = 0; y::vector(off1,off4,off3,off2).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3D sphere. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the sphere (dimension along the X-axis). + \param subdivisions The number of recursive subdivisions from an initial icosahedron. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::sphere3d(faces3d,100,4); + CImg().display_object3d("Sphere3d",points3d,faces3d); + \endcode + \image html ref_sphere3d.jpg + **/ + template + static CImg sphere3d(CImgList& primitives, + const float radius=50, const unsigned int subdivisions=3) { + + // Create initial icosahedron + primitives.assign(); + const double tmp = (1 + std::sqrt(5.f))/2, a = 1./std::sqrt(1 + tmp*tmp), b = tmp*a; + CImgList vertices(12,1,3,1,1, b,a,0., -b,a,0., -b,-a,0., b,-a,0., a,0.,b, a,0.,-b, + -a,0.,-b, -a,0.,b, 0.,b,a, 0.,-b,a, 0.,-b,-a, 0.,b,-a); + primitives.assign(20,1,3,1,1, 4,8,7, 4,7,9, 5,6,11, 5,10,6, 0,4,3, 0,3,5, 2,7,1, 2,1,6, + 8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3, + 5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2); + // edge - length/2 + float he = (float)a; + + // Recurse subdivisions + for (unsigned int i = 0; i::vector(nx0,ny0,nz0).move_to(vertices); i0 = vertices.width() - 1; } + if (i1<0) { CImg::vector(nx1,ny1,nz1).move_to(vertices); i1 = vertices.width() - 1; } + if (i2<0) { CImg::vector(nx2,ny2,nz2).move_to(vertices); i2 = vertices.width() - 1; } + primitives.remove(0); + CImg::vector(p0,i0,i1).move_to(primitives); + CImg::vector((tf)i0,(tf)p1,(tf)i2).move_to(primitives); + CImg::vector((tf)i1,(tf)i2,(tf)p2).move_to(primitives); + CImg::vector((tf)i1,(tf)i0,(tf)i2).move_to(primitives); + } + } + return (vertices>'x')*=radius; + } + + //! Generate a 3D ellipsoid. + /** + \param[out] primitives The returned list of the 3D object primitives + (template type \e tf should be at least \e unsigned \e int). + \param tensor The tensor which gives the shape and size of the ellipsoid. + \param subdivisions The number of recursive subdivisions from an initial stretched icosahedron. + \return The N vertices (xi,yi,zi) of the 3D object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg tensor = CImg::diagonal(10,7,3), + points3d = CImg::ellipsoid3d(faces3d,tensor,4); + CImg().display_object3d("Ellipsoid3d",points3d,faces3d); + \endcode + \image html ref_ellipsoid3d.jpg + **/ + template + static CImg ellipsoid3d(CImgList& primitives, + const CImg& tensor, const unsigned int subdivisions=3) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImg S, V; + tensor.symmetric_eigen(S,V); + const float orient = + (V(0,1)*V(1,2) - V(0,2)*V(1,1))*V(2,0) + + (V(0,2)*V(1,0) - V(0,0)*V(1,2))*V(2,1) + + (V(0,0)*V(1,1) - V(0,1)*V(1,0))*V(2,2); + if (orient<0) { V(2,0) = -V(2,0); V(2,1) = -V(2,1); V(2,2) = -V(2,2); } + const float l0 = S[0], l1 = S[1], l2 = S[2]; + CImg vertices = sphere3d(primitives,1.,subdivisions); + vertices.get_shared_row(0)*=l0; + vertices.get_shared_row(1)*=l1; + vertices.get_shared_row(2)*=l2; + return V*vertices; + } + + //! Convert 3D object into a CImg3d representation. + /** + \param primitives Primitives data of the 3D object. + \param colors Colors data of the 3D object. + \param opacities Opacities data of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + **/ + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \overloading. + CImg& object3dtoCImg3d(const bool full_check=true) { + return get_object3dtoCImg3d(full_check).move_to(*this); + } + + //! Convert 3D object into a CImg3d representation \newinstance. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "object3dtoCImg3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,_width,primitives._width,error_message.data()); + CImg res(1,_size_object3dtoCImg3d(primitives,colors,opacities)); + float *ptrd = res._data; + + // Put magick number. + *(ptrd++) = 'C' + 0.5f; *(ptrd++) = 'I' + 0.5f; *(ptrd++) = 'm' + 0.5f; + *(ptrd++) = 'g' + 0.5f; *(ptrd++) = '3' + 0.5f; *(ptrd++) = 'd' + 0.5f; + + // Put number of vertices and primitives. + *(ptrd++) = cimg::uint2float(_width); + *(ptrd++) = cimg::uint2float(primitives._width); + + // Put vertex data. + if (is_empty() || !primitives) return res; + const T *ptrx = data(0,0), *ptry = data(0,1), *ptrz = data(0,2); + cimg_forX(*this,p) { + *(ptrd++) = (float)*(ptrx++); + *(ptrd++) = (float)*(ptry++); + *(ptrd++) = (float)*(ptrz++); + } + + // Put primitive data. + cimglist_for(primitives,p) { + *(ptrd++) = (float)primitives[p].size(); + const tp *ptrp = primitives[p]._data; + cimg_foroff(primitives[p],i) *(ptrd++) = cimg::uint2float((unsigned int)*(ptrp++)); + } + + // Put color/texture data. + const unsigned int csiz = std::min(colors._width,primitives._width); + for (int c = 0; c<(int)csiz; ++c) { + const CImg& color = colors[c]; + const tc *ptrc = color._data; + if (color.size()==3) { *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*ptrc; } + else { + *(ptrd++) = -128.f; + int shared_ind = -1; + if (color.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImgList& opacities, float *ptrd) const { + cimglist_for(opacities,o) { + const CImg& opacity = opacities[o]; + const to *ptro = opacity._data; + if (opacity.size()==1) *(ptrd++) = (float)*ptro; + else { + *(ptrd++) = -128.f; + int shared_ind = -1; + if (opacity.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImg& opacities, float *ptrd) const { + const to *ptro = opacities._data; + cimg_foroff(opacities,o) *(ptrd++) = (float)*(ptro++); + return ptrd; + } + + template + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImgList& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + if (colors[c].is_shared()) siz+=4; + else { const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; } + } + if (colors._width + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImg& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; + } + if (colors._width + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) const { + CImgList opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3D object into a CImg3d representation \overloading. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) const { + CImgList colors, opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3D object into a CImg3d representation \overloading. + CImg get_object3dtoCImg3d(const bool full_check=true) const { + CImgList opacities, colors; + CImgList primitives(width(),1,1,1,1); + cimglist_for(primitives,p) primitives(p,0) = p; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert CImg3d representation into a 3D object. + /** + \param[out] primitives Primitives data of the 3D object. + \param[out] colors Colors data of the 3D object. + \param[out] opacities Opacities data of the 3D object. + \param full_check Tells if full checking of the 3D object must be performed. + **/ + template + CImg& CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) { + return get_CImg3dtoobject3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert CImg3d representation into a 3D object \newinstance. + template + CImg get_CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_CImg3d(full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "CImg3dtoobject3d(): image instance is not a CImg3d (%s).", + cimg_instance,error_message.data()); + const T *ptrs = _data + 6; + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + const CImg points = CImg(ptrs,3,nb_points,1,1,true).get_transpose(); + ptrs+=3*nb_points; + primitives.assign(nb_primitives); + cimglist_for(primitives,p) { + const unsigned int nb_inds = (unsigned int)*(ptrs++); + primitives[p].assign(1,nb_inds); + tp *ptrp = primitives[p]._data; + for (unsigned int i = 0; i::max(),(T)cimg::type::max()); \ + const float _sc_nopacity = cimg::abs((float)opacity), _sc_copacity = 1 - std::max((float)opacity,0.f); \ + const ulongT _sc_whd = (ulongT)_width*_height*_depth; \ + cimg::unused(_sc_maxval); + +#define cimg_draw_scanline(x0,x1,y,color,opacity,brightness) \ + _draw_scanline(x0,x1,y,color,opacity,brightness,_sc_nopacity,_sc_copacity,_sc_whd,_sc_maxval) + + // [internal] The following _draw_scanline() routines are *non user-friendly functions*, + // used only for internal purpose. + // Pre-requisites: x0<=x1, y-coordinate is valid, col is valid. + template + CImg& _draw_scanline(const int x0, const int x1, const int y, + const tc *const color, const float opacity, + const float brightness, + const float nopacity, const float copacity, const ulongT whd, const T _sc_maxval) { + const int nx0 = x0>0?x0:0, nx1 = x1=0) { + const tc *col = color; + const ulongT off = whd - dx - 1; + T *ptrd = data(nx0,y); + if (opacity>=1) { // ** Opaque drawing ** + if (brightness==1) { // Brightness==1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)*(col++); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)*(col++); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else if (brightness<1) { // Brightness<1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else { // Brightness>1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*_sc_maxval); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*_sc_maxval); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } + } else { // ** Transparent drawing ** + if (brightness==1) { // Brightness==1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else if (brightness<=1) { // Brightness<1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*brightness*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else { // Brightness>1 + cimg_forC(*this,c) { + const Tfloat val = ((2-brightness)**(col++) + (brightness - 1)*_sc_maxval)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } + } + } + return *this; + } + + //! Draw a 3D point. + /** + \param x0 X-coordinate of the point. + \param y0 Y-coordinate of the point. + \param z0 Z-coordinate of the point. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - To set pixel values without clipping needs, you should use the faster CImg::operator()() function. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_point(50,50,color); + \endcode + **/ + template + CImg& draw_point(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_point(): Specified color is (null).", + cimg_instance); + if (x0>=0 && y0>=0 && z0>=0 && x0=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } + } + return *this; + } + + //! Draw a 2D point \simplification. + template + CImg& draw_point(const int x0, const int y0, + const tc *const color, const float opacity=1) { + return draw_point(x0,y0,0,color,opacity); + } + + // Draw a points cloud. + /** + \param points Image of vertices coordinates. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_point(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_point(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),color,opacity); + } break; + default : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),(int)points(i,2),color,opacity); + } + } + return *this; + } + + //! Draw a 2D line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + \note + - Line routine uses Bresenham's algorithm. + - Set \p init_hatch = false to draw consecutive hatched segments without breaking the line pattern. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,color); + \endcode + **/ + template + CImg& draw_line(int x0, int y0, + int x1, int y1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !opacity || !pattern || + std::min(y0,y1)>=height() || std::max(y0,y1)<0 || + std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1); + dx01*=-1; dy01*=-1; + } + + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + const int + step = y0<=y1?1:-1,hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + T *const ptrd = is_horizontal?data(y,x):data(x,y); + cimg_forC(*this,c) { + const T val = color[c]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a 2D line, with z-buffering. + /** + \param zbuffer Zbuffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + **/ + template + CImg& draw_line(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_line(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float diz01 = iz1 - iz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1); + dx01*=-1; dy01*=-1; diz01*=-1; + } + + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float iz = iz0 + diz01*yy0/dy01; + tz *const ptrz = is_horizontal?zbuffer.data(y,x):zbuffer.data(x,y); + + if (x>=0 && x<=w1 && pattern&hatch && iz>=*ptrz) { + *ptrz = (tz)iz; + T *const ptrd = is_horizontal?data(y,x):data(x,y); + cimg_forC(*this,c) { + const T val = color[c]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + \note + - Line routine uses the well known Bresenham's algorithm. + \par Example: + \code + CImg img(100,100,1,3,0), texture("texture256x256.ppm"); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,texture,0,0,255,255); + \endcode + **/ + template + CImg& draw_line(int x0, int y0, + int x1, int y1, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + + if (is_empty() || !opacity || !pattern) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_line(x0,y0,x1,y1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + int + dtx01 = tx1 - tx0, dty01 = ty1 - ty0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1); + dx01*=-1; dy01*=-1; dtx01*=-1; dty01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy01ty = dy01*cimg::sign(dty01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01, + tx = tx0 + (dtx01*yy0 + hdy01tx)/dy01, + ty = ty0 + (dty01*yy0 + hdy01ty)/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line, with perspective correction. + /** + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(int x0, int y0, const float z0, + int x1, int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float + diz01 = iz1 - iz0, + txz0 = tx0*iz0, txz1 = tx1*iz1, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, + dtxz01 = txz1 - txz0, dtyz01 = tyz1 - tyz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1,txz0,txz1,tyz0,tyz1); + dx01*=-1; dy01*=-1; diz01*=-1; dtxz01*=-1; dtyz01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float + iz = iz0 + diz01*yy0/dy01, + txz = txz0 + dtxz01*yy0/dy01, + tyz = tyz0 + dtyz01*yy0/dy01; + if (x>=0 && x<=w1 && pattern&hatch) { + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a textured 2D line, with perspective correction and z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + + if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0) return *this; + + float iz0 = 1/z0, iz1 = 1/z1; + int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dy01 = y1 - y0; + float + diz01 = iz1 - iz0, + txz0 = tx0*iz0, txz1 = tx1*iz1, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, + dtxz01 = txz1 - txz0, dtyz01 = tyz1 - tyz0; + + const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01); + if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01); + if (pattern==~0U && y0>y1) { + cimg::swap(x0,x1,y0,y1,iz0,iz1,txz0,txz1,tyz0,tyz1); + dx01*=-1; dy01*=-1; diz01*=-1; dtxz01*=-1; dtyz01*=-1; + } + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + cimg_init_scanline(opacity); + + const int + step = y0<=y1?1:-1, hdy01 = dy01*cimg::sign(dx01)/2, + cy0 = cimg::cut(y0,0,h1), cy1 = cimg::cut(y1,0,h1) + step; + dy01+=dy01?0:1; + + for (int y = cy0; y!=cy1; y+=step) { + const int + yy0 = y - y0, + x = x0 + (dx01*yy0 + hdy01)/dy01; + const float + iz = iz0 + diz01*yy0/dy01, + txz = txz0 + dtxz01*yy0/dy01, + tyz = tyz0 + dtyz01*yy0/dy01; + tz *const ptrz = is_horizontal?zbuffer.data(y,x):zbuffer.data(x,y); + + if (x>=0 && x<=w1 && pattern&hatch && iz>=*ptrz) { + *ptrz = (tz)iz; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + T *const ptrd = is_horizontal?data(y,x):data(x,y); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const T val = color[c*twhd]; + ptrd[c*_sc_whd] = opacity>=1?val:(T)(val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + if (!(hatch>>=1)) hatch = ~0U - (~0U>>1); + } + return *this; + } + + //! Draw a set of consecutive lines. + /** + \param points Coordinates of vertices, stored as a list of vectors. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If set to true, init hatch motif. + \note + - This function uses several call to the single CImg::draw_line() procedure, + depending on the vectors size in \p points. + **/ + template + CImg& draw_line(const CImg& points, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + default : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + int ox = x0, oy = y0; + for (unsigned int i = 1; i + CImg& draw_arrow(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1, + const float angle=30, const float length=-10, + const unsigned int pattern=~0U) { + if (is_empty()) return *this; + const float u = (float)(x0 - x1), v = (float)(y0 - y1), sq = u*u + v*v, + deg = (float)(angle*cimg::PI/180), ang = (sq>0)?(float)std::atan2(v,u):0.f, + l = (length>=0)?length:-length*(float)std::sqrt(sq)/100; + if (sq>0) { + const float + cl = (float)std::cos(ang - deg), sl = (float)std::sin(ang - deg), + cr = (float)std::cos(ang + deg), sr = (float)std::sin(ang + deg); + const int + xl = x1 + (int)(l*cl), yl = y1 + (int)(l*sl), + xr = x1 + (int)(l*cr), yr = y1 + (int)(l*sr), + xc = x1 + (int)((l + 1)*(cl + cr))/2, yc = y1 + (int)((l + 1)*(sl + sr))/2; + draw_line(x0,y0,xc,yc,color,opacity,pattern).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity); + } else draw_point(x0,y0,color,opacity); + return *this; + } + + //! Draw a 2D spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + \note + - The curve is a 2D cubic Bezier spline, from the set of specified starting/ending points + and corresponding velocity vectors. + - The spline is drawn as a sequence of connected segments. The \p precision parameter sets the + average number of pixels in each drawn segment. + - A cubic Bezier curve is sometimes defined by a set of 4 points { (\p x0,\p y0), (\p xa,\p ya), + (\p xb,\p yb), (\p x1,\p y1) } where (\p x0,\p y0) is the starting point, (\p x1,\p y1) is the ending point + and (\p xa,\p ya), (\p xb,\p yb) are two + \e control points. + The starting and ending velocities (\p u0,\p v0) and (\p u1,\p v1) can be deduced easily from + the control points as + \p u0 = (\p xa - \p x0), \p v0 = (\p ya - \p y0), \p u1 = (\p x1 - \p xb) and \p v1 = (\p y1 - \p yb). + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,255,255 }; + img.draw_spline(30,30,0,100,90,40,0,-100,color); + \endcode + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const tc *const color, const float opacity=1, + const float precision=0.25, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Specified color is (null).", + cimg_instance); + if (x0==x1 && y0==y1) return draw_point(x0,y0,color,opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0; + for (float t = 0; t<1; t+=_precision) { + const float t2 = t*t, t3 = t2*t; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), + ny = (int)(ay*t3 + by*t2 + v0*t + y0); + draw_line(ox,oy,nx,ny,color,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; + } + return draw_line(ox,oy,x1,y1,color,opacity,pattern,false); + } + + //! Draw a textured 2D spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param texture Texture image defining line pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch if \c true, reinit hatch motif. + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const CImg& texture, + const int tx0, const int ty0, const int tx1, const int ty1, + const float opacity=1, + const float precision=4, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_empty()) return *this; + if (is_overlapped(texture)) + return draw_spline(x0,y0,u0,v0,x1,y1,u1,v1,+texture,tx0,ty0,tx1,ty1,precision,opacity,pattern,init_hatch); + if (x0==x1 && y0==y1) + return draw_point(x0,y0,texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).data(), + opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0, otx = tx0, oty = ty0; + for (float t1 = 0; t1<1; t1+=_precision) { + const float t2 = t1*t1, t3 = t2*t1; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t1 + x0), + ny = (int)(ay*t3 + by*t2 + v0*t1 + y0), + ntx = tx0 + (int)((tx1 - tx0)*t1), + nty = ty0 + (int)((ty1 - ty0)*t1); + draw_line(ox,oy,nx,ny,texture,otx,oty,ntx,nty,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; otx = ntx; oty = nty; + } + return draw_line(ox,oy,x1,y1,texture,otx,oty,tx1,ty1,opacity,pattern,false); + } + + //! Draw a set of consecutive splines. + /** + \param points Vertices data. + \param tangents Tangents data. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param is_closed_set Tells if the drawn spline set is closed. + \param precision Precision of the drawing. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + **/ + template + CImg& draw_spline(const CImg& points, const CImg& tangents, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || !tangents || points._width<2 || tangents._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + default : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1); + int ox = x0, oy = y0; + float ou = u0, ov = v0; + for (unsigned int i = 1; i + CImg& draw_spline(const CImg& points, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + CImg tangents; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + tangents.assign(points._width,points._height); + cimg_forX(points,p) { + const unsigned int + p0 = is_closed_set?(p + points.width() - 1)%points.width():(p?p - 1:0), + p1 = is_closed_set?(p + 1)%points.width():(p + 1 + CImg& _draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, const float opacity, + const float brightness) { + if (y0>y1) cimg::swap(x0,x1,y0,y1); + if (y0>y2) cimg::swap(x0,x2,y0,y2); + if (y1>y2) cimg::swap(x1,x2,y1,y2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM); + cimg_draw_scanline(xm,xM,y,color,opacity,cbs); + } + return *this; + } + + //! Draw a filled 2D triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + _draw_triangle(x0,y0,x1,y1,x2,y2,color,opacity,1); + return *this; + } + + //! Draw a outlined 2D triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + draw_line(x0,y0,x1,y1,color,opacity,pattern,true). + draw_line(x1,y1,x2,y2,color,opacity,pattern,false). + draw_line(x2,y2,x0,y0,color,opacity,pattern,false); + return *this; + } + + //! Draw a filled 2D triangle, with z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param z0 Z-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param z1 Z-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param z2 Z-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param brightness Brightness factor. + **/ + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1; + + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param bs0 Brightness factor of the first vertex (in [0,2]). + \param bs1 brightness factor of the second vertex (in [0,2]). + \param bs2 brightness factor of the third vertex (in [0,2]). + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2D triangle, with z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, + float bs0, + float bs1, + float bs2, + float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c]*cbs:(2 - cbs)*color[c] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a color-interpolated 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color1 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the first vertex. + \param color2 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the second vertex. + \param color3 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc1 *const color1, + const tc2 *const color2, + const tc3 *const color3, + const float opacity=1) { + const unsigned char one = 1; + cimg_forC(*this,c) + get_shared_channel(c).draw_triangle(x0,y0,x1,y1,x2,y2,&one,color1[c],color2[c],color3[c],opacity); + return *this; + } + + //! Draw a textured 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param opacity Drawing opacity. + \param brightness Brightness factor of the drawing (in [0,2]). + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,ty1,tx2,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2; + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM; + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a 2D textured triangle, with perspective correction. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured 2D triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + const float cbs = cimg::cut(brightness,0,2); + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const Tfloat val = cbs<=1?color[c*twhd]*cbs:(2 - cbs)*color[c*twhd] + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a Phong-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const tc *const color, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + + const ulongT lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,lxm,lxM,lym,lyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dlxmM = lxM - lxm, dlymM = lyM - lym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a Phong-shaded 2D triangle, with z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const tc *const color, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (is_overlapped(light)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + const float diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1; + + const ulongT lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,lxm,lxM,lym,lyM,izm,izM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dlxmM = lxM - lxm, dlymM = lyM - lym; + const float dizmM = izM - izm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const int + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const tc col = color[c]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param bs0 Brightness factor of the first vertex. + \param bs1 Brightness factor of the second vertex. + \param bs2 Brightness factor of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + bs0,bs1,bs2,opacity); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2; + const float dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym; + const float dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM; + const float cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle, with perspective correction \overloading. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + bs0,bs1,bs2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2D triangle, with perspective correction and z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + float bs0, + float bs1, + float bs2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,bs0,bs1,bs2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,bs0,bs1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,bs0,bs2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,bs1,bs2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + dbs01 = bs1 - bs0, dbs02 = bs2 - bs0, dbs12 = bs2 - bs1; + + const ulongT twhd = (ulongT)texture._width*texture._height*texture._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txzm,txzM,tyzm,tyzM,izm,izM,bsm,bsM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float dizmM = izM - izm, dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, dbsmM = bsM - bsm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + cbs = cimg::cut(bsm + dbsmM*xxm/dxmM,0,2); + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz); + const tc *const color = &texture._atXY(tx,ty); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(int x0, int y0, + int x1, int y1, + int x2, int y2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + if (y0>y1) cimg::swap(x0,x1,y0,y1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2, + dtx01 = tx1 - tx0, dtx02 = tx2 - tx0, dtx12 = tx2 - tx1, + dty01 = ty1 - ty0, dty02 = ty2 - ty0, dty12 = ty2 - ty1, + hdy01tx = dy01*cimg::sign(dtx01)/2, hdy02tx = dy02*cimg::sign(dtx02)/2, hdy12tx = dy12*cimg::sign(dtx12)/2, + hdy01ty = dy01*cimg::sign(dty01)/2, hdy02ty = dy02*cimg::sign(dty02)/2, hdy12ty = dy12*cimg::sign(dty12)/2, + dlx01 = lx1 - lx0, dlx02 = lx2 - lx0, dlx12 = lx2 - lx1, + dly01 = ly1 - ly0, dly02 = ly2 - ly0, dly12 = ly2 - ly1, + hdy01lx = dy01*cimg::sign(dlx01)/2, hdy02lx = dy02*cimg::sign(dlx02)/2, hdy12lx = dy12*cimg::sign(dlx12)/2, + hdy01ly = dy01*cimg::sign(dly01)/2, hdy02ly = dy02*cimg::sign(dly02)/2, hdy12ly = dy12*cimg::sign(dly12)/2; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,txm,txM,tym,tyM,lxm,lxM,lym,lyM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int + dxmM = std::max(1,xM - xm), hdxmM = dxmM/2, + dtxmM = txM - txm, dtymM = tyM - tym, + dlxmM = lxM - lxm, dlymM = lyM - lym; + + for (int x = cxm; x<=cxM; ++x) { + const int + xxm = x - xm, + tx = (txm*dxmM + dtxmM*xxm + hdxmM)/dxmM, + ty = (tym*dxmM + dtymM*xxm + hdxmM)/dxmM, + lx = (lxm*dxmM + dlxmM*xxm + hdxmM)/dxmM, + ly = (lym*dxmM + dlymM*xxm + hdxmM)/dxmM; + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle, with perspective correction. + template + CImg& draw_triangle(int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2, + lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2, + dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1, + dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float + dizmM = izM - izm, + dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, + dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float + iz = izm + dizmM*xxm/dxmM, + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + lxz = lxzm + dlxzmM*xxm/dxmM, + lyz = lyzm + dlyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz), + lx = (int)cimg::round(lxz/iz), + ly = (int)cimg::round(lyz/iz); + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + ++ptrd; + } + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2D triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + int x0, int y0, const float z0, + int x1, int y1, const float z1, + int x2, int y2, const float z2, + const CImg& texture, + int tx0, int ty0, + int tx1, int ty1, + int tx2, int ty2, + const CImg& light, + int lx0, int ly0, + int lx1, int ly1, + int lx2, int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + +texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + + float iz0 = 1/z0, iz1 = 1/z1, iz2 = 1/z2; + if (y0>y1) cimg::swap(x0,x1,y0,y1,iz0,iz1,tx0,tx1,ty0,ty1,lx0,lx1,ly0,ly1); + if (y0>y2) cimg::swap(x0,x2,y0,y2,iz0,iz2,tx0,tx2,ty0,ty2,lx0,lx2,ly0,ly2); + if (y1>y2) cimg::swap(x1,x2,y1,y2,iz1,iz2,tx1,tx2,ty1,ty2,lx1,lx2,ly1,ly2); + if (y2<0 || y0>=height() || cimg::min(x0,x1,x2)>=width() || cimg::max(x0,x1,x2)<0 || !opacity) return *this; + + const int + w1 = width() - 1, h1 = height() - 1, + dx01 = x1 - x0, dx02 = x2 - x0, dx12 = x2 - x1, + dy01 = std::max(1,y1 - y0), dy02 = std::max(1,y2 - y0), dy12 = std::max(1,y2 - y1), + cy0 = cimg::cut(y0,0,h1), cy2 = cimg::cut(y2,0,h1), + hdy01 = dy01*cimg::sign(dx01)/2, hdy02 = dy02*cimg::sign(dx02)/2, hdy12 = dy12*cimg::sign(dx12)/2; + const float + diz01 = iz1 - iz0, diz02 = iz2 - iz0, diz12 = iz2 - iz1, + txz0 = tx0*iz0, txz1 = tx1*iz1, txz2 = tx2*iz2, + tyz0 = ty0*iz0, tyz1 = ty1*iz1, tyz2 = ty2*iz2, + dtxz01 = txz1 - txz0, dtxz02 = txz2 - txz0, dtxz12 = txz2 - txz1, + dtyz01 = tyz1 - tyz0, dtyz02 = tyz2 - tyz0, dtyz12 = tyz2 - tyz1, + lxz0 = lx0*iz0, lxz1 = lx1*iz1, lxz2 = lx2*iz2, + lyz0 = ly0*iz0, lyz1 = ly1*iz1, lyz2 = ly2*iz2, + dlxz01 = lxz1 - lxz0, dlxz02 = lxz2 - lxz0, dlxz12 = lxz2 - lxz1, + dlyz01 = lyz1 - lyz0, dlyz02 = lyz2 - lyz0, dlyz12 = lyz2 - lyz1; + + const ulongT + twhd = (ulongT)texture._width*texture._height*texture._depth, + lwhd = (ulongT)light._width*light._height*light._depth; + cimg_init_scanline(opacity); + + for (int y = cy0; y<=cy2; ++y) { + const int yy0 = y - y0, yy1 = y - y1; + int + xm = yxM) cimg::swap(xm,xM,izm,izM,txzm,txzM,tyzm,tyzM,lxzm,lxzM,lyzm,lyzM); + if (xM>=0 && xm<=w1) { + const int + cxm = cimg::cut(xm,0,w1), + cxM = cimg::cut(xM,0,w1); + T *ptrd = data(cxm,y); + tz *ptrz = zbuffer.data(cxm,y); + const int dxmM = std::max(1,xM - xm); + const float + dizmM = izM - izm, + dtxzmM = txzM - txzm, dtyzmM = tyzM - tyzm, + dlxzmM = lxzM - lxzm, dlyzmM = lyzM - lyzm; + + for (int x = cxm; x<=cxM; ++x) { + const int xxm = x - xm; + const float iz = izm + dizmM*xxm/dxmM; + if (iz>=*ptrz) { + *ptrz = (tz)iz; + const float + txz = txzm + dtxzmM*xxm/dxmM, + tyz = tyzm + dtyzmM*xxm/dxmM, + lxz = lxzm + dlxzmM*xxm/dxmM, + lyz = lyzm + dlyzmM*xxm/dxmM; + const int + tx = (int)cimg::round(txz/iz), + ty = (int)cimg::round(tyz/iz), + lx = (int)cimg::round(lxz/iz), + ly = (int)cimg::round(lyz/iz); + const tc *const color = &texture._atXY(tx,ty); + const tl *const lig = &light._atXY(lx,ly); + cimg_forC(*this,c) { + const tc col = color[c*twhd]; + const float cbs = cimg::cut((float)lig[c*lwhd],0,2); + const Tfloat val = cbs<=1?cbs*col:(2 - cbs)*col + (cbs - 1)*_sc_maxval; + ptrd[c*_sc_whd] = (T)(opacity>=1?val:val*_sc_nopacity + ptrd[c*_sc_whd]*_sc_copacity); + } + } + ++ptrd; ++ptrz; + } + } + } + return *this; + } + + //! Draw a filled 4D rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param z0 Z-coordinate of the upper-left rectangle corner. + \param c0 C-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param z1 Z-coordinate of the lower-right rectangle corner. + \param c1 C-coordinate of the lower-right rectangle corner. + \param val Scalar value used to fill the rectangle area. + \param opacity Drawing opacity. + **/ + CImg& draw_rectangle(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const T val, const float opacity=1) { + if (is_empty()) return *this; + const int + nx0 = x0=width()?width() - 1 - nx1:0) + (nx0<0?nx0:0), + ly = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0), + lz = (1 + nz1 - nz0) + (nz1>=depth()?depth() - 1 - nz1:0) + (nz0<0?nz0:0), + lc = (1 + nc1 - nc0) + (nc1>=spectrum()?spectrum() - 1 - nc1:0) + (nc0<0?nc0:0); + const ulongT + offX = (ulongT)_width - lx, + offY = (ulongT)_width*(_height - ly), + offZ = (ulongT)_width*_height*(_depth - lz); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + T *ptrd = data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0); + if (lx>0 && ly>0 && lz>0 && lc>0) + for (int v = 0; v=1) { + if (sizeof(T)!=1) { for (int x = 0; x + CImg& draw_rectangle(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_rectangle(): Specified color is (null).", + cimg_instance); + cimg_forC(*this,c) draw_rectangle(x0,y0,z0,c,x1,y1,z1,c,(T)color[c],opacity); + return *this; + } + + //! Draw a filled 2D rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1) { + return draw_rectangle(x0,y0,0,x1,y1,_depth - 1,color,opacity); + } + + //! Draw a outlined 2D rectangle \overloading. + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (y0==y1) return draw_line(x0,y0,x1,y0,color,opacity,pattern,true); + if (x0==x1) return draw_line(x0,y0,x0,y1,color,opacity,pattern,true); + const int + nx0 = x0 + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points.height()!=2) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set (%u,%u,%u,%u).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum); + if (points._width==1) return draw_point(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)),color,opacity); + if (points._width==2) return draw_line(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)), + cimg::uiround(points(1,0)),cimg::uiround(points(1,1)),color,opacity); + if (points._width==3) return draw_triangle(cimg::uiround(points(0,0)),cimg::uiround(points(0,1)), + cimg::uiround(points(1,0)),cimg::uiround(points(1,1)), + cimg::uiround(points(2,0)),cimg::uiround(points(2,1)),color,opacity); + cimg_init_scanline(opacity); + int + xmin = 0, ymin = 0, + xmax = points.get_shared_row(0).max_min(xmin), + ymax = points.get_shared_row(1).max_min(ymin); + if (xmax<0 || xmin>=width() || ymax<0 || ymin>=height()) return *this; + if (ymin==ymax) return draw_line(xmin,ymin,xmax,ymax,color,opacity); + + ymin = std::max(0,ymin); + ymax = std::min(height() - 1,ymax); + CImg Xs(points._width,ymax - ymin + 1); + CImg count(Xs._height,1,1,1,0); + unsigned int n = 0, nn = 1; + bool go_on = true; + + while (go_on) { + unsigned int an = (nn + 1)%points._width; + const int + x0 = cimg::uiround(points(n,0)), + y0 = cimg::uiround(points(n,1)); + if (points(nn,1)==y0) while (points(an,1)==y0) { nn = an; (an+=1)%=points._width; } + const int + x1 = cimg::uiround(points(nn,0)), + y1 = cimg::uiround(points(nn,1)); + unsigned int tn = an; + while (points(tn,1)==y1) (tn+=1)%=points._width; + + if (y0!=y1) { + const int + y2 = cimg::uiround(points(tn,1)), + x01 = x1 - x0, y01 = y1 - y0, y12 = y2 - y1, + step = cimg::sign(y01), + tmax = std::max(1,cimg::abs(y01)), htmax = tmax*cimg::sign(x01)/2, + tend = tmax - (step==cimg::sign(y12)); + unsigned int y = (unsigned int)y0 - ymin; + for (int t = 0; t<=tend; ++t, y+=step) + if (yn; + n = nn; + nn = an; + } + + cimg_pragma_openmp(parallel for cimg_openmp_if(Xs._height>=(cimg_openmp_sizefactor)*512)) + cimg_forY(Xs,y) { + const CImg Xsy = Xs.get_shared_points(0,count[y] - 1,y).sort(); + int px = width(); + for (unsigned int k = 0; k + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity, const unsigned int pattern) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points._width==1) return draw_point((int)points(0,0),(int)points(0,1),color,opacity); + if (points._width==2) return draw_line((int)points(0,0),(int)points(0,1), + (int)points(1,0),(int)points(1,1),color,opacity,pattern); + bool ninit_hatch = true; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set (%u,%u,%u,%u).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum); + default : { + CImg npoints(points._width,2); + int x = npoints(0,0) = (int)points(0,0), y = npoints(0,1) = (int)points(0,1); + unsigned int nb_points = 1; + for (unsigned int p = 1; p + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity=1) { + return _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,0U,true); + } + + //! Draw a filled 2D ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity=1) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity); + } + + //! Draw an outlined 2D ellipse. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param r1 First radius of the ellipse. + \param r2 Second radius of the ellipse. + \param angle Angle of the first radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity, const unsigned int pattern) { + if (pattern) _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,pattern,false); + return *this; + } + + //! Draw an outlined 2D ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity, + const unsigned int pattern) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity,pattern); + } + + template + CImg& _draw_ellipse(const int x0, const int y0, const float radius1, const float radius2, const float angle, + const tc *const color, const float opacity, + const unsigned int pattern, const bool is_filled) { + if (is_empty() || (!is_filled && !pattern)) return *this; + const float radiusM = std::max(radius1,radius2); + if (radius1<0 || radius2<0 || x0 - radiusM>=width() || y0 + radiusM<0 || y0 - radiusM>=height()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_ellipse(): Specified color is (null).", + cimg_instance); + const int iradius1 = (int)cimg::round(radius1), iradius2 = (int)cimg::round(radius2); + if (!iradius1 && !iradius2) return draw_point(x0,y0,color,opacity); + if (iradius1==iradius2) { + if (is_filled) return draw_circle(x0,y0,iradius1,color,opacity); + else if (pattern==~0U) return draw_circle(x0,y0,iradius1,color,opacity,pattern); + } + const float ang = (float)(angle*cimg::PI/180); + + if (!is_filled) { // Outlined + const float ca = std::cos(ang), sa = std::sin(ang); + CImg points((unsigned int)cimg::round(6*radiusM),2); + cimg_forX(points,k) { + const float + _ang = (float)(2*cimg::PI*k/points._width), + X = (float)(radius1*std::cos(_ang)), + Y = (float)(radius2*std::sin(_ang)); + points(k,0) = (int)cimg::round(x0 + (X*ca - Y*sa)); + points(k,1) = (int)cimg::round(y0 + (X*sa + Y*ca)); + } + draw_polygon(points,color,opacity,pattern); + } else { // Filled + cimg_init_scanline(opacity); + const float + ca = std::cos(ang), + sa = -std::sin(ang), + ca2 = ca*ca, + sa2 = sa*sa, + casa = ca*sa, + i1 = 1/cimg::sqr(radius1), + i2 = 1/cimg::sqr(radius2), + t1 = i1*ca2 + i2*sa2, + t2 = (i2 - i1)*casa, + t3 = i2*ca2 + i1*sa2, + t12 = t1*2; + const int + _ymin = (int)std::floor(y0 - radiusM), + _ymax = (int)std::ceil(y0 + radiusM), + ymin = _ymin<0?0:_ymin, + ymax = _ymax>=height()?height() - 1:_ymax; + for (int y = ymin; y<=ymax; ++y) { + const float + Y = y - y0 + 0.5f, + B = 2*t2*Y, + C = t3*Y*Y - 1, + D = B*B - 4*t1*C; + if (D>=0) { + const float sD = std::sqrt(D); + const int + xmin = (int)(x0 + cimg::round((-B - sD)/t12)), + xmax = (int)(x0 + cimg::round((-B + sD)/t12)); + cimg_draw_scanline(xmin,xmax,y,color,opacity,1); + } + } + } + return *this; + } + + //! Draw a filled 2D circle. + /** + \param x0 X-coordinate of the circle center. + \param y0 Y-coordinate of the circle center. + \param radius Circle radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - Circle version of the Bresenham's algorithm is used. + **/ + template + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (!radius) return draw_point(x0,y0,color,opacity); + cimg_init_scanline(opacity); + if (y0>=0 && y0=0) { + const int x1 = x0 - x, x2 = x0 + x, y1 = y0 - y, y2 = y0 + y; + if (y1>=0 && y1=0 && y2=0 && y1=0 && y2 + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (pattern!=~0U) return draw_ellipse(x0,y0,radius,radius,0,color,opacity,pattern); + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!radius) return draw_point(x0,y0,color,opacity); + + draw_point(x0 - radius,y0,color,opacity).draw_point(x0 + radius,y0,color,opacity). + draw_point(x0,y0 - radius,color,opacity).draw_point(x0,y0 + radius,color,opacity); + if (radius==1) return *this; + for (int f = 1 - radius, ddFx = 0, ddFy = -(radius<<1), x = 0, y = radius; x=0) { f+=(ddFy+=2); --y; } + ++x; ++(f+=(ddFx+=2)); + if (x!=y + 1) { + const int x1 = x0 - y, x2 = x0 + y, y1 = y0 - x, y2 = y0 + x, + x3 = x0 - x, x4 = x0 + x, y3 = y0 - y, y4 = y0 + y; + draw_point(x1,y1,color,opacity).draw_point(x1,y2,color,opacity). + draw_point(x2,y1,color,opacity).draw_point(x2,y2,color,opacity); + if (x!=y) + draw_point(x3,y3,color,opacity).draw_point(x4,y4,color,opacity). + draw_point(x4,y3,color,opacity).draw_point(x3,y4,color,opacity); + } + } + return *this; + } + + //! Draw an image. + /** + \param sprite Sprite image. + \param x0 X-coordinate of the sprite position. + \param y0 Y-coordinate of the sprite position. + \param z0 Z-coordinate of the sprite position. + \param c0 C-coordinate of the sprite position. + \param opacity Drawing opacity. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c=1) for (int x = 0; x& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + const ulongT slx = lx*sizeof(T); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c=1) std::memcpy(ptrd,ptrs,slx); + else for (int x = 0; x + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,z0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const CImg& sprite, const float opacity=1) { + return draw_image(0,sprite,opacity); + } + + //! Draw a masked image. + /** + \param sprite Sprite image. + \param mask Mask image. + \param x0 X-coordinate of the sprite position in the image instance. + \param y0 Y-coordinate of the sprite position in the image instance. + \param z0 Z-coordinate of the sprite position in the image instance. + \param c0 C-coordinate of the sprite position in the image instance. + \param mask_max_value Maximum pixel value of the mask image \c mask. + \param opacity Drawing opacity. + \note + - Pixel values of \c mask set the opacity of the corresponding pixels in \c sprite. + - Dimensions along x,y and z of \p sprite and \p mask must be the same. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + if (is_empty() || !sprite || !mask) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,mask,opacity,mask_max_value); + if (is_overlapped(mask)) return draw_image(x0,y0,z0,c0,sprite,+mask,opacity,mask_max_value); + if (mask._width!=sprite._width || mask._height!=sprite._height || mask._depth!=sprite._depth) + throw CImgArgumentException(_cimg_instance + "draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + sprite._width,sprite._height,sprite._depth,sprite._spectrum,sprite._data, + mask._width,mask._height,mask._depth,mask._spectrum,mask._data); + + const bool bx = x0<0, by = y0<0, bz = z0<0, bc = c0<0; + const int + dx0 = bx?0:x0, dy0 = by?0:y0, dz0 = bz?0:z0, dc0 = bc?0:c0, + sx0 = dx0 - x0, sy0 = dy0 - y0, sz0 = dz0 - z0, sc0 = dc0 - c0, + lx = sprite.width() - sx0 - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0), + ly = sprite.height() - sy0 - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0), + lz = sprite.depth() - sz0 - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0), + lc = sprite.spectrum() - sc0 - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0); + const ulongT msize = mask.size(); + + if (lx>0 && ly>0 && lz>0 && lc>0) { + for (int c = 0; c + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,z0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw an image. + template + CImg& draw_image(const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a text string. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Pointer to \c spectrum() consecutive values, defining the foreground drawing color. + \param background_color Pointer to \c spectrum() consecutive values, defining the background drawing color. + \param opacity Drawing opacity. + \param font Font used for drawing text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent background is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,(tc*)0,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent foreground is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,(tc*)0,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Array of spectrum() values of type \c T, + defining the foreground color (0 means 'transparent'). + \param background_color Array of spectrum() values of type \c T, + defining the background color (0 means 'transparent'). + \param opacity Drawing opacity. + \param font_height Height of the text font (exact match for 13,23,53,103, interpolated otherwise). + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + const CImgList& font = CImgList::font(font_height,true); + _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,true); + return *this; + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int background_color=0, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + cimg::unused(background_color); + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",foreground_color,(const tc*)0,opacity,font_height,tmp._data); + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",(tc*)0,background_color,opacity,font_height,tmp._data); + } + + template + CImg& _draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, + const bool is_native_font) { + if (!text) return *this; + if (!font) + throw CImgArgumentException(_cimg_instance + "draw_text(): Empty specified font.", + cimg_instance); + + const unsigned int text_length = (unsigned int)std::strlen(text); + const int padding_x = font[0]._height<48?1:font[0]._height<128?(int)std::ceil(font[0]._height/51.0f + 0.745f):4; + unsigned char o_ch, ch = 0; + int x, y, w; + CImg left_paddings(text_length,1,1,1,0); + const CImg empty = CImg::empty(); + + if (is_empty() || is_native_font) { + // Pre-compute necessary size of the image as well as left paddings of each character. + x = y = w = 0; + o_ch = 0; + for (unsigned int i = 0; iw) w = x; x = 0; break; + case '\t' : x+=4*font[(int)' ']._width; break; + case ' ' : x+=font[(int)' ']._width; break; + default : if (ch'9')) || o_ch==';' || o_ch==':' || o_ch=='!') + left_padding = 4*padding_x; + else if (((o_ch=='i' || o_ch=='l' || o_ch=='I' || o_ch=='J' || o_ch=='M' || o_ch=='N') && + ((ch>='0' && ch<='9') || + (ch>='a' && ch<='z' && ch!='v' && ch!='x' && ch!='y') || + (ch>='B' && ch<='Z' && ch!='J' && ch!='T' && ch!='V' && ch!='X' && ch!='Y'))) || + o_ch=='.' || o_ch=='\'' || ch=='\'') + left_padding = padding_x; + else if ((o_ch<'0' || o_ch>'9') && ch!='-') { + const CImg &mask = ch + 256U' ' && o_ch>' ' && mask._height>13) { + const CImg &o_mask = o_ch + 256U13) { + const int w1 = mask.width()>0?o_mask.width() - 1:0, w2 = w1>1?w1 - 1:0, w3 = w2>1?w2 - 1:0; + left_padding = -10; + cimg_forY(mask,k) { + const int + lpad = o_mask(w1,k)>=8?0: + o_mask._width<=2 || o_mask(w2,k)>=8?-1: + o_mask._width<=3 || o_mask(w3,k)>=8?-2:-3, + rpad = mask(0,k)>=8?0: + mask._width<=2 || mask(1,k)>=8?-1: + mask._width<=3 || mask(2,k)>=8?-2:-3; + left_padding = std::max(left_padding,lpad + rpad); + } + } + } + } + left_paddings[i] = left_padding; + } + x+=left_padding + font[ch]._width + padding_x; + o_ch = ch; + } + } + } + if (x!=0 || ch=='\n') { if (x>w) w = x; y+=font[0]._height; } + if (is_empty()) assign(x0 + w,y0 + y,1,is_native_font?1:font[0]._spectrum,(T)0); + } + + // Draw font characters on image. + x = x0; y = y0; + for (unsigned int i = 0; i letter = font[ch]; + if (letter) { + const CImg &mask = ch + 256Uletter._spectrum) + letter.assign(letter.get_resize(-100,-100,1,_spectrum,0,2),false); + const unsigned int cmin = std::min(_spectrum,letter._spectrum); + if (foreground_color) + for (unsigned int c = 0; c& __draw_text(const char *const text, unsigned int &font_size, const int is_down, ...) { + CImg tmp(2048); + std::va_list ap; + va_start(ap,is_down); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + CImg a_label, a_labelmask; + const unsigned char a_labelcolor = 255; + unsigned int ofs = font_size, fs = ofs; + do { // Determine best font size + a_label.assign().draw_text(0,0,"%s",&a_labelcolor,0,1,fs,tmp._data); + if (a_label._width<7*_width/10 && a_label._height>_height/20 && a_label._height<_height/5) { + font_size = fs; break; + } else if ((a_label._width>7*_width/10 || a_label._height>_height/5) && fs>13 && ofs>=fs) { + ofs = fs; fs = std::max(13U,(unsigned int)cimg::round(fs/1.25f)); + } else if (a_label._width<3*_width/10 && a_label._height<_height/20 && fs<64 && ofs<=fs) { + ofs = fs; fs = std::min(64U,(unsigned int)cimg::round(fs*1.25f)); + } else { font_size = fs; break; } + } while (true); + a_label.normalize(0,255); + a_label+=(255 - a_label.get_dilate(3)).normalize(0,80); + a_label.resize(-100,-100,1,3,1); + return draw_image(0,is_down?height() - a_label.height():0,a_label,0.85f); + } + + //! Draw a 2D vector field. + /** + \param flow Image of 2D vectors used as input data. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const t2 *const color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + return draw_quiver(flow,CImg(color,_spectrum,1,1,1,true),opacity,sampling,factor,is_arrow,pattern); + } + + //! Draw a 2D vector field, using a field of colors. + /** + \param flow Image of 2D vectors used as input data. + \param color Image of spectrum()-D vectors corresponding to the color of each arrow. + \param opacity Opacity of the drawing. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const CImg& color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + if (is_empty()) return *this; + if (!flow || flow._spectrum!=2) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).", + cimg_instance, + flow._width,flow._height,flow._depth,flow._spectrum,flow._data); + if (sampling<=0) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid sampling value %g " + "(should be >0)", + cimg_instance, + sampling); + const bool colorfield = (color._width==flow._width && color._height==flow._height && + color._depth==1 && color._spectrum==_spectrum); + if (is_overlapped(flow)) return draw_quiver(+flow,color,opacity,sampling,factor,is_arrow,pattern); + float vmax,fact; + if (factor<=0) { + float m, M = (float)flow.get_norm(2).max_min(m); + vmax = (float)std::max(cimg::abs(m),cimg::abs(M)); + if (!vmax) vmax = 1; + fact = -factor; + } else { fact = factor; vmax = 1; } + + for (unsigned int y = sampling/2; y<_height; y+=sampling) + for (unsigned int x = sampling/2; x<_width; x+=sampling) { + const unsigned int X = x*flow._width/_width, Y = y*flow._height/_height; + float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax; + if (is_arrow) { + const int xx = (int)(x + u), yy = (int)(y + v); + if (colorfield) draw_arrow(x,y,xx,yy,color.get_vector_at(X,Y)._data,opacity,45,sampling/5.f,pattern); + else draw_arrow(x,y,xx,yy,color._data,opacity,45,sampling/5.f,pattern); + } else { + if (colorfield) + draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color.get_vector_at(X,Y)._data,opacity,pattern); + else draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color._data,opacity,pattern); + } + } + return *this; + } + + //! Draw a labeled horizontal axis. + /** + \param values_x Values along the horizontal axis. + \param y Y-coordinate of the horizontal axis in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const CImg& values_x, const int y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true, const float round_x=0) { + if (is_empty()) return *this; + const int yt = (y + 3 + font_height)<_height?y + 3:y - 2 - (int)font_height; + const int siz = (int)values_x.size() - 1; + CImg txt(32); + CImg a_label; + if (siz<=0) { // Degenerated case + draw_line(0,y,_width - 1,y,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",round_x?cimg::round((double)*values_x,round_x):(double)*values_x); + a_label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _xt = (width() - a_label.width())/2, + xt = _xt<3?3:_xt + a_label.width()>=width() - 2?width() - 3 - a_label.width():_xt; + draw_point(width()/2,y - 1,color,opacity).draw_point(width()/2,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case + if (values_x[0]=width() - 2?width() - 3 - a_label.width():_xt; + draw_point(xi,y - 1,color,opacity).draw_point(xi,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw a labeled vertical axis. + /** + \param x X-coordinate of the vertical axis in the image instance. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const int x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true, const float round_y=0) { + if (is_empty()) return *this; + int siz = (int)values_y.size() - 1; + CImg txt(32); + CImg a_label; + if (siz<=0) { // Degenerated case + draw_line(x,0,x,_height - 1,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",round_y?cimg::round((double)*values_y,round_y):(double)*values_y); + a_label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _yt = (height() - a_label.height())/2, + yt = _yt<0?0:_yt + a_label.height()>=height()?height() - 1 - a_label.height():_yt, + _xt = x - 2 - a_label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,height()/2,color,opacity).draw_point(x + 1,height()/2,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case + if (values_y[0]=height()?height() - 1 - a_label.height():_yt, + _xt = x - 2 - a_label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,yi,color,opacity).draw_point(x + 1,yi,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes. + /** + \param values_x Values along the X-axis. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for the X-axis. + \param pattern_y Drawing pattern for the Y-axis. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axes(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13, const bool allow_zero=true, + const float round_x=0, const float round_y=0) { + if (is_empty()) return *this; + const CImg nvalues_x(values_x._data,values_x.size(),1,1,1,true); + const int sizx = (int)values_x.size() - 1, wm1 = width() - 1; + if (sizx>=0) { + float ox = (float)*nvalues_x; + for (unsigned int x = sizx?1U:0U; x<_width; ++x) { + const float nx = (float)nvalues_x._linear_atX((float)x*sizx/wm1); + if (nx*ox<=0) { + draw_axis(nx==0?x:x - 1,values_y,color,opacity,pattern_y,font_height,allow_zero,round_y); + break; + } + ox = nx; + } + } + const CImg nvalues_y(values_y._data,values_y.size(),1,1,1,true); + const int sizy = (int)values_y.size() - 1, hm1 = height() - 1; + if (sizy>0) { + float oy = (float)nvalues_y[0]; + for (unsigned int y = sizy?1U:0U; y<_height; ++y) { + const float ny = (float)nvalues_y._linear_atX((float)y*sizy/hm1); + if (ny*oy<=0) { + draw_axis(values_x,ny==0?y:y - 1,color,opacity,pattern_x,font_height,allow_zero,round_x); + break; + } + oy = ny; + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes \overloading. + template + CImg& draw_axes(const float x0, const float x1, const float y0, const float y1, + const tc *const color, const float opacity=1, + const int subdivisionx=-60, const int subdivisiony=-60, + const float precisionx=0, const float precisiony=0, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13) { + if (is_empty()) return *this; + const bool allow_zero = (x0*x1>0) || (y0*y1>0); + const float + dx = cimg::abs(x1 - x0), dy = cimg::abs(y1 - y0), + px = dx<=0?1:precisionx==0?(float)std::pow(10.,(int)std::log10(dx) - 2.):precisionx, + py = dy<=0?1:precisiony==0?(float)std::pow(10.,(int)std::log10(dy) - 2.):precisiony; + if (x0!=x1 && y0!=y1) + draw_axes(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1), + CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1), + color,opacity,pattern_x,pattern_y,font_height,allow_zero,px,py); + else if (x0==x1 && y0!=y1) + draw_axis((int)x0,CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1), + color,opacity,pattern_y,font_height,py); + else if (x0!=x1 && y0==y1) + draw_axis(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1),(int)y0, + color,opacity,pattern_x,font_height,px); + return *this; + } + + //! Draw 2D grid. + /** + \param values_x X-coordinates of the vertical lines. + \param values_y Y-coordinates of the horizontal lines. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for vertical lines. + \param pattern_y Drawing pattern for horizontal lines. + **/ + template + CImg& draw_grid(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + if (values_x) cimg_foroff(values_x,x) { + const int xi = (int)values_x[x]; + if (xi>=0 && xi=0 && yi + CImg& draw_grid(const float delta_x, const float delta_y, + const float offsetx, const float offsety, + const bool invertx, const bool inverty, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + CImg seqx, seqy; + if (delta_x!=0) { + const float dx = delta_x>0?delta_x:_width*-delta_x/100; + const unsigned int nx = (unsigned int)(_width/dx); + seqx = CImg::sequence(1 + nx,0,(unsigned int)(dx*nx)); + if (offsetx) cimg_foroff(seqx,x) seqx(x) = (unsigned int)cimg::mod(seqx(x) + offsetx,(float)_width); + if (invertx) cimg_foroff(seqx,x) seqx(x) = _width - 1 - seqx(x); + } + if (delta_y!=0) { + const float dy = delta_y>0?delta_y:_height*-delta_y/100; + const unsigned int ny = (unsigned int)(_height/dy); + seqy = CImg::sequence(1 + ny,0,(unsigned int)(dy*ny)); + if (offsety) cimg_foroff(seqy,y) seqy(y) = (unsigned int)cimg::mod(seqy(y) + offsety,(float)_height); + if (inverty) cimg_foroff(seqy,y) seqy(y) = _height - 1 - seqy(y); + } + return draw_grid(seqx,seqy,color,opacity,pattern_x,pattern_y); + } + + //! Draw 1D graph. + /** + \param data Image containing the graph values I = f(x). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + + \param plot_type Define the type of the plot: + - 0 = No plot. + - 1 = Plot using segments. + - 2 = Plot using cubic splines. + - 3 = Plot with bars. + \param vertex_type Define the type of points: + - 0 = No points. + - 1 = Point. + - 2 = Straight cross. + - 3 = Diagonal cross. + - 4 = Filled circle. + - 5 = Outlined circle. + - 6 = Square. + - 7 = Diamond. + \param ymin Lower bound of the y-range. + \param ymax Upper bound of the y-range. + \param pattern Drawing pattern. + \note + - if \c ymin==ymax==0, the y-range is computed automatically from the input samples. + **/ + template + CImg& draw_graph(const CImg& data, + const tc *const color, const float opacity=1, + const unsigned int plot_type=1, const int vertex_type=1, + const double ymin=0, const double ymax=0, const unsigned int pattern=~0U) { + if (is_empty() || _height<=1) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_graph(): Specified color is (null).", + cimg_instance); + + // Create shaded colors for displaying bar plots. + CImg color1, color2; + if (plot_type==3) { + color1.assign(_spectrum); color2.assign(_spectrum); + cimg_forC(*this,c) { + color1[c] = (tc)std::min((float)cimg::type::max(),(float)color[c]*1.2f); + color2[c] = (tc)(color[c]*0.4f); + } + } + + // Compute min/max and normalization factors. + const ulongT + siz = data.size(), + _siz1 = siz - (plot_type!=3), + siz1 = _siz1?_siz1:1; + const unsigned int + _width1 = _width - (plot_type!=3), + width1 = _width1?_width1:1; + double m = ymin, M = ymax; + if (ymin==ymax) m = (double)data.max_min(M); + if (m==M) { --m; ++M; } + const float ca = (float)(M-m)/(_height - 1); + bool init_hatch = true; + + // Draw graph edges + switch (plot_type%4) { + case 1 : { // Segments + int oX = 0, oY = (int)cimg::round((data[0] - m)/ca); + if (siz==1) { + const int Y = (int)cimg::round((*data - m)/ca); + draw_line(0,Y,width() - 1,Y,color,opacity,pattern); + } else { + const float fx = (float)_width/siz1; + for (ulongT off = 1; off ndata(data._data,siz,1,1,1,true); + int oY = (int)cimg::round((data[0] - m)/ca); + cimg_forX(*this,x) { + const int Y = (int)cimg::round((ndata._cubic_atX((float)x*siz1/width1)-m)/ca); + if (x>0) draw_line(x,oY,x + 1,Y,color,opacity,pattern,init_hatch); + init_hatch = false; + oY = Y; + } + } break; + case 3 : { // Bars + const int Y0 = (int)cimg::round(-m/ca); + const float fx = (float)_width/siz1; + int oX = 0; + cimg_foroff(data,off) { + const int + X = (int)cimg::round((off + 1)*fx) - 1, + Y = (int)cimg::round((data[off] - m)/ca); + draw_rectangle(oX,Y0,X,Y,color,opacity). + draw_line(oX,Y,oX,Y0,color2.data(),opacity). + draw_line(oX,Y0,X,Y0,Y<=Y0?color2.data():color1.data(),opacity). + draw_line(X,Y,X,Y0,color1.data(),opacity). + draw_line(oX,Y,X,Y,Y<=Y0?color1.data():color2.data(),opacity); + oX = X + 1; + } + } break; + default : break; // No edges + } + + // Draw graph points + const unsigned int wb2 = plot_type==3?_width1/(2*siz):0; + const float fx = (float)_width1/siz1; + switch (vertex_type%8) { + case 1 : { // Point + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_point(X,Y,color,opacity); + } + } break; + case 2 : { // Straight Cross + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X - 3,Y,X + 3,Y,color,opacity).draw_line(X,Y - 3,X,Y + 3,color,opacity); + } + } break; + case 3 : { // Diagonal Cross + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X - 3,Y - 3,X + 3,Y + 3,color,opacity).draw_line(X - 3,Y + 3,X + 3,Y - 3,color,opacity); + } + } break; + case 4 : { // Filled Circle + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity); + } + } break; + case 5 : { // Outlined circle + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity,~0U); + } + } break; + case 6 : { // Square + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_rectangle(X - 3,Y - 3,X + 3,Y + 3,color,opacity,~0U); + } + } break; + case 7 : { // Diamond + cimg_foroff(data,off) { + const int + X = (int)cimg::round(off*fx + wb2), + Y = (int)cimg::round((data[off]-m)/ca); + draw_line(X,Y - 4,X + 4,Y,color,opacity). + draw_line(X + 4,Y,X,Y + 4,color,opacity). + draw_line(X,Y + 4,X - 4,Y,color,opacity). + draw_line(X - 4,Y,X,Y - 4,color,opacity); + } + } break; + default : break; // No points + } + return *this; + } + + bool _draw_fill(const int x, const int y, const int z, + const CImg& ref, const float tolerance2) const { + const T *ptr1 = data(x,y,z), *ptr2 = ref._data; + const ulongT off = _width*_height*_depth; + float diff = 0; + cimg_forC(*this,c) { diff += cimg::sqr(*ptr1 - *(ptr2++)); ptr1+=off; } + return diff<=tolerance2; + } + + //! Draw filled 3D region with the flood fill algorithm. + /** + \param x0 X-coordinate of the starting point of the region to fill. + \param y0 Y-coordinate of the starting point of the region to fill. + \param z0 Z-coordinate of the starting point of the region to fill. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param[out] region Image that will contain the mask of the filled region mask, as an output. + \param tolerance Tolerance concerning neighborhood values. + \param opacity Opacity of the drawing. + \param is_high_connectivity Tells if 8-connexity must be used. + \return \c region is initialized with the binary mask of the filled region. + **/ + template + CImg& draw_fill(const int x0, const int y0, const int z0, + const tc *const color, const float opacity, + CImg ®ion, + const float tolerance = 0, + const bool is_high_connectivity = false) { +#define _draw_fill_push(x,y,z) if (N>=stack._width) stack.resize(2*N + 1,1,1,3,0); \ + stack[N] = x; stack(N,1) = y; stack(N++,2) = z +#define _draw_fill_pop(x,y,z) x = stack[--N]; y = stack(N,1); z = stack(N,2) +#define _draw_fill_is_inside(x,y,z) !_region(x,y,z) && _draw_fill(x,y,z,ref,tolerance2) + + if (!containsXYZC(x0,y0,z0,0)) return *this; + const float nopacity = cimg::abs((float)opacity), copacity = 1 - std::max((float)opacity,0.f); + const float tolerance2 = cimg::sqr(tolerance); + const CImg ref = get_vector_at(x0,y0,z0); + CImg stack(256,1,1,3); + CImg _region(_width,_height,_depth,1,0); + unsigned int N = 0; + int x, y, z; + + _draw_fill_push(x0,y0,z0); + while (N>0) { + _draw_fill_pop(x,y,z); + if (!_region(x,y,z)) { + const int yp = y - 1, yn = y + 1, zp = z - 1, zn = z + 1; + int xl = x, xr = x; + + // Using these booleans reduces the number of pushes drastically. + bool is_yp = false, is_yn = false, is_zp = false, is_zn = false; + for (int step = -1; step<2; step+=2) { + while (x>=0 && x=0 && _draw_fill_is_inside(x,yp,z)) { + if (!is_yp) { _draw_fill_push(x,yp,z); is_yp = true; } + } else is_yp = false; + if (yn1) { + if (zp>=0 && _draw_fill_is_inside(x,y,zp)) { + if (!is_zp) { _draw_fill_push(x,y,zp); is_zp = true; } + } else is_zp = false; + if (zn=0 && !is_yp) { + if (xp>=0 && _draw_fill_is_inside(xp,yp,z)) { + _draw_fill_push(xp,yp,z); if (step<0) is_yp = true; + } + if (xn0) is_yp = true; + } + } + if (yn=0 && _draw_fill_is_inside(xp,yn,z)) { + _draw_fill_push(xp,yn,z); if (step<0) is_yn = true; + } + if (xn0) is_yn = true; + } + } + if (depth()>1) { + if (zp>=0 && !is_zp) { + if (xp>=0 && _draw_fill_is_inside(xp,y,zp)) { + _draw_fill_push(xp,y,zp); if (step<0) is_zp = true; + } + if (xn0) is_zp = true; + } + + if (yp>=0 && !is_yp) { + if (_draw_fill_is_inside(x,yp,zp)) { _draw_fill_push(x,yp,zp); } + if (xp>=0 && _draw_fill_is_inside(xp,yp,zp)) { _draw_fill_push(xp,yp,zp); } + if (xn=0 && _draw_fill_is_inside(xp,yn,zp)) { _draw_fill_push(xp,yn,zp); } + if (xn=0 && _draw_fill_is_inside(xp,y,zn)) { + _draw_fill_push(xp,y,zn); if (step<0) is_zn = true; + } + if (xn0) is_zn = true; + } + + if (yp>=0 && !is_yp) { + if (_draw_fill_is_inside(x,yp,zn)) { _draw_fill_push(x,yp,zn); } + if (xp>=0 && _draw_fill_is_inside(xp,yp,zn)) { _draw_fill_push(xp,yp,zn); } + if (xn=0 && _draw_fill_is_inside(xp,yn,zn)) { _draw_fill_push(xp,yn,zn); } + if (xn + CImg& draw_fill(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1, + const float tolerance=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x0,y0,z0,color,opacity,tmp,tolerance,is_high_connexity); + } + + //! Draw filled 2D region with the flood fill algorithm \simplification. + template + CImg& draw_fill(const int x0, const int y0, + const tc *const color, const float opacity=1, + const float tolerance=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x0,y0,0,color,opacity,tmp,tolerance,is_high_connexity); + } + + //! Draw a random plasma texture. + /** + \param alpha Alpha-parameter. + \param beta Beta-parameter. + \param scale Scale-parameter. + \note Use the mid-point algorithm to render. + **/ + CImg& draw_plasma(const float alpha=1, const float beta=0, const unsigned int scale=8) { + if (is_empty()) return *this; + const int w = width(), h = height(); + const Tfloat m = (Tfloat)cimg::type::min(), M = (Tfloat)cimg::type::max(); + cimg_uint64 rng = (cimg::_rand(),cimg::rng()); + cimg_forZC(*this,z,c) { + CImg ref = get_shared_slice(z,c); + for (int delta = 1<1; delta>>=1) { + const int delta2 = delta>>1; + const float r = alpha*delta + beta; + + // Square step. + for (int y0 = 0; y0M?M:val); + } + + // Diamond steps. + for (int y = -delta2; yM?M:val); + } + for (int y0 = 0; y0M?M:val); + } + for (int y = -delta2; yM?M:val); + } + } + } + cimg::srand(rng); + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2D fractal. + /** + \param x0 X-coordinate of the upper-left pixel. + \param y0 Y-coordinate of the upper-left pixel. + \param x1 X-coordinate of the lower-right pixel. + \param y1 Y-coordinate of the lower-right pixel. + \param colormap Colormap. + \param opacity Drawing opacity. + \param z0r Real part of the upper-left fractal vertex. + \param z0i Imaginary part of the upper-left fractal vertex. + \param z1r Real part of the lower-right fractal vertex. + \param z1i Imaginary part of the lower-right fractal vertex. + \param iteration_max Maximum number of iterations for each estimated point. + \param is_normalized_iteration Tells if iterations are normalized. + \param is_julia_set Tells if the Mandelbrot or Julia set is rendered. + \param param_r Real part of the Julia set parameter. + \param param_i Imaginary part of the Julia set parameter. + \note Fractal rendering is done by the Escape Time Algorithm. + **/ + template + CImg& draw_mandelbrot(const int x0, const int y0, const int x1, const int y1, + const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + if (is_empty()) return *this; + CImg palette; + if (colormap) palette.assign(colormap._data,colormap.size()/colormap._spectrum,1,1,colormap._spectrum,true); + if (palette && palette._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_mandelbrot(): Instance and specified colormap (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f), ln2 = (float)std::log(2.); + const int + _x0 = cimg::cut(x0,0,width() - 1), + _y0 = cimg::cut(y0,0,height() - 1), + _x1 = cimg::cut(x1,0,width() - 1), + _y1 = cimg::cut(y1,0,height() - 1); + + cimg_pragma_openmp(parallel for cimg_openmp_collapse(2) + cimg_openmp_if((1 + _x1 - _x0)*(1 + _y1 - _y0)>=(cimg_openmp_sizefactor)*2048)) + for (int q = _y0; q<=_y1; ++q) + for (int p = _x0; p<=_x1; ++p) { + unsigned int iteration = 0; + const double x = z0r + p*(z1r-z0r)/_width, y = z0i + q*(z1i-z0i)/_height; + double zr, zi, cr, ci; + if (is_julia_set) { zr = x; zi = y; cr = param_r; ci = param_i; } + else { zr = param_r; zi = param_i; cr = x; ci = y; } + for (iteration=1; zr*zr + zi*zi<=4 && iteration<=iteration_max; ++iteration) { + const double temp = zr*zr - zi*zi + cr; + zi = 2*zr*zi + ci; + zr = temp; + } + if (iteration>iteration_max) { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette(0,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(0,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)0; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)((*this)(p,q,0,c)*copacity); + } + } else if (is_normalized_iteration) { + const float + normz = (float)cimg::abs(zr*zr + zi*zi), + niteration = (float)(iteration + 1 - std::log(std::log(normz))/ln2); + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._linear_atX(niteration,c); + else cimg_forC(*this,c) + (*this)(p,q,0,c) = (T)(palette._linear_atX(niteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)niteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(niteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } else { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._atX(iteration,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(iteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)iteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(iteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } + } + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2D fractal \overloading. + template + CImg& draw_mandelbrot(const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + return draw_mandelbrot(0,0,_width - 1,_height - 1,colormap,opacity, + z0r,z0i,z1r,z1i,iteration_max,is_normalized_iteration,is_julia_set,param_r,param_i); + } + + //! Draw a 1D gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param sigma Standard variation of the gaussian distribution. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float sigma, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + const float sigma2 = 2*sigma*sigma, nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forX(*this,x) { + const float dx = (x - xc), val = (float)std::exp(-dx*dx/sigma2); + T *ptrd = data(x,0,0,0); + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 2D gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param yc Y-coordinate of the gaussian center. + \param tensor Covariance matrix (must be 2x2). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float yc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (tensor._width!=2 || tensor._height!=2 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 2x2 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + typedef typename CImg::Tfloat tfloat; + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/=-2.; + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + float dy = -yc; + cimg_forY(*this,y) { + float dx = -xc; + cimg_forX(*this,x) { + const float val = (float)std::exp(a*dx*dx + b*dx*dy + c*dy*dy); + T *ptrd = data(x,y,0,0); + if (opacity>=1) cimg_forC(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + ++dx; + } + ++dy; + } + return *this; + } + + //! Draw a 2D gaussian function \overloading. + template + CImg& draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, + const tc *const color, const float opacity=1) { + const double + a = r1*ru*ru + r2*rv*rv, + b = (r1-r2)*ru*rv, + c = r1*rv*rv + r2*ru*ru; + const CImg tensor(2,2,1,1, a,b,b,c); + return draw_gaussian(xc,yc,tensor,color,opacity); + } + + //! Draw a 2D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,CImg::diagonal(sigma,sigma),color,opacity); + } + + //! Draw a 3D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + typedef typename CImg::Tfloat tfloat; + if (tensor._width!=3 || tensor._height!=3 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 3x3 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/=-2.; + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = 2*invT2(2,0), d = invT2(1,1), e = 2*invT2(2,1), f = invT2(2,2); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forXYZ(*this,x,y,z) { + const float + dx = (x - xc), dy = (y - yc), dz = (z - zc), + val = (float)std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz); + T *ptrd = data(x,y,z,0); + if (opacity>=1) cimg_forC(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 3D gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,zc,CImg::diagonal(sigma,sigma,sigma),color,opacity); + } + + //! Draw a 3D object. + /** + \param x0 X-coordinate of the 3D object position + \param y0 Y-coordinate of the 3D object position + \param z0 Z-coordinate of the 3D object position + \param vertices Image Nx3 describing 3D point coordinates + \param primitives List of P primitives + \param colors List of P color (or textures) + \param opacities Image or list of P opacities + \param render_type d Render type (0=Points, 1=Lines, 2=Faces (no light), 3=Faces (flat), 4=Faces(Gouraud) + \param is_double_sided Tells if object faces have two sides or are oriented. + \param focale length of the focale (0 for parallel projection) + \param lightx X-coordinate of the light + \param lighty Y-coordinate of the light + \param lightz Z-coordinate of the light + \param specular_lightness Amount of specular light. + \param specular_shininess Shininess of the object + \param g_opacity Global opacity of the object. + **/ + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } +#endif + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,1); + } +#endif + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + //! Draw a 3D object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,zbuffer); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const float g_opacity=1) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,g_opacity,zbuffer); + } +#endif + + template + static float __draw_object3d(const CImgList& opacities, const unsigned int n_primitive, CImg& opacity) { + if (n_primitive>=opacities._width || opacities[n_primitive].is_empty()) { opacity.assign(); return 1; } + if (opacities[n_primitive].size()==1) { opacity.assign(); return opacities(n_primitive,0); } + opacity.assign(opacities[n_primitive],true); + return 1.f; + } + + template + static float __draw_object3d(const CImg& opacities, const unsigned int n_primitive, CImg& opacity) { + opacity.assign(); + return n_primitive>=opacities._width?1.f:(float)opacities[n_primitive]; + } + + template + static float ___draw_object3d(const CImgList& opacities, const unsigned int n_primitive) { + return n_primitive + static float ___draw_object3d(const CImg& opacities, const unsigned int n_primitive) { + return n_primitive + CImg& _draw_object3d(void *const pboard, CImg& zbuffer, + const float X, const float Y, const float Z, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float g_opacity, const float sprite_scale) { + typedef typename cimg::superset2::type tpfloat; + typedef typename to::value_type _to; + if (is_empty() || !vertices || !primitives) return *this; + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,false,error_message)) + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); +#ifndef cimg_use_board + if (pboard) return *this; +#endif + if (render_type==5) cimg::mutex(10); // Static variable used in this case, breaks thread-safety + + const float + nspec = 1 - (specular_lightness<0.f?0.f:(specular_lightness>1.f?1.f:specular_lightness)), + nspec2 = 1 + (specular_shininess<0.f?0.f:specular_shininess), + nsl1 = (nspec2 - 1)/cimg::sqr(nspec - 1), + nsl2 = 1 - 2*nsl1*nspec, + nsl3 = nspec2 - nsl1 - nsl2; + + // Create light texture for phong-like rendering. + CImg light_texture; + if (render_type==5) { + if (colors._width>primitives._width) { + static CImg default_light_texture; + static const tc *lptr = 0; + static tc ref_values[64] = { 0 }; + const CImg& img = colors.back(); + bool is_same_texture = (lptr==img._data); + if (is_same_texture) + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + if (ref_values[r++]!=img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum)) { + is_same_texture = false; break; + } + if (!is_same_texture || default_light_texture._spectrum<_spectrum) { + (default_light_texture.assign(img,false)/=255).resize(-100,-100,1,_spectrum); + lptr = colors.back().data(); + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + ref_values[r++] = img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum); + } + light_texture.assign(default_light_texture,true); + } else { + static CImg default_light_texture; + static float olightx = 0, olighty = 0, olightz = 0, ospecular_shininess = 0; + if (!default_light_texture || + lightx!=olightx || lighty!=olighty || lightz!=olightz || + specular_shininess!=ospecular_shininess || default_light_texture._spectrum<_spectrum) { + default_light_texture.assign(512,512); + const float + dlx = lightx - X, + dly = lighty - Y, + dlz = lightz - Z, + nl = cimg::hypot(dlx,dly,dlz), + nlx = (default_light_texture._width - 1)/2*(1 + dlx/nl), + nly = (default_light_texture._height - 1)/2*(1 + dly/nl), + white[] = { 1 }; + default_light_texture.draw_gaussian(nlx,nly,default_light_texture._width/3.f,white); + cimg_forXY(default_light_texture,x,y) { + const float factor = default_light_texture(x,y); + if (factor>nspec) default_light_texture(x,y) = std::min(2.f,nsl1*factor*factor + nsl2*factor + nsl3); + } + default_light_texture.resize(-100,-100,1,_spectrum); + olightx = lightx; olighty = lighty; olightz = lightz; ospecular_shininess = specular_shininess; + } + light_texture.assign(default_light_texture,true); + } + } + + // Compute 3D to 2D projection. + CImg projections(vertices._width,2); + tpfloat parallzmin = cimg::type::max(); + const float absfocale = focale?cimg::abs(focale):0; + if (absfocale) { + cimg_pragma_openmp(parallel for cimg_openmp_if_size(projections.size(),4096)) + cimg_forX(projections,l) { // Perspective projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + const tpfloat projectedz = z + Z + absfocale; + projections(l,1) = Y + absfocale*y/projectedz; + projections(l,0) = X + absfocale*x/projectedz; + } + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if_size(projections.size(),4096)) + cimg_forX(projections,l) { // Parallel projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + if (z visibles(primitives._width,1,1,1,~0U); + CImg zrange(primitives._width); + const tpfloat zmin = absfocale?(tpfloat)(1.5f - absfocale):cimg::type::min(); + bool is_forward = zbuffer?true:false; + + cimg_pragma_openmp(parallel for cimg_openmp_if_size(primitives.size(),4096)) + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + switch (primitive.size()) { + case 1 : { // Point + CImg<_to> _opacity; + __draw_object3d(opacities,l,_opacity); + if (l<=colors.width() && (colors[l].size()!=_spectrum || _opacity)) is_forward = false; + const unsigned int i0 = (unsigned int)primitive(0); + const tpfloat z0 = Z + vertices(i0,2); + if (z0>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = z0; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + Xc = 0.5f*((float)vertices(i0,0) + (float)vertices(i1,0)), + Yc = 0.5f*((float)vertices(i0,1) + (float)vertices(i1,1)), + Zc = 0.5f*((float)vertices(i0,2) + (float)vertices(i1,2)), + _zc = Z + Zc, + zc = _zc + _focale, + xc = X + Xc*(absfocale?absfocale/zc:1), + yc = Y + Yc*(absfocale?absfocale/zc:1), + radius = 0.5f*cimg::hypot(vertices(i1,0) - vertices(i0,0), + vertices(i1,1) - vertices(i0,1), + vertices(i1,2) - vertices(i0,2))*(absfocale?absfocale/zc:1), + xm = xc - radius, + ym = yc - radius, + xM = xc + radius, + yM = yc + radius; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && _zc>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = _zc; + } + is_forward = false; + } break; + case 2 : case 6 : { // Segment + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2); + tpfloat xm, xM, ym, yM; + if (x0=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1)/2; + } + } break; + case 3 : case 9 : { // Triangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (y0yM) yM = y2; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) { + const tpfloat d = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2)/3; + } + } + } break; + case 4 : case 12 : { // Quadrangle + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2), + x3 = projections(i3,0), y3 = projections(i3,1), z3 = Z + vertices(i3,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (x3xM) xM = x3; + if (y0yM) yM = y2; + if (y3yM) yM = y3; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin && z3>zmin) { + const float d = (x1 - x0)*(y2 - y0) - (x2 - x0)*(y1 - y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2 + z3)/4; + } + } + } break; + default : + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid primitive[%u] with size %u " + "(should have size 1,2,3,4,5,6,9 or 12).", + cimg_instance, + l,primitive.size()); + } + } + + // Force transparent primitives to be drawn last when zbuffer is activated + // (and if object contains no spheres or sprites). + if (is_forward) + cimglist_for(primitives,l) + if (___draw_object3d(opacities,l)!=1) zrange(l) = 2*zmax - zrange(l); + + // Sort only visibles primitives. + unsigned int *p_visibles = visibles._data; + tpfloat *p_zrange = zrange._data; + const tpfloat *ptrz = p_zrange; + cimg_for(visibles,ptr,unsigned int) { + if (*ptr!=~0U) { *(p_visibles++) = *ptr; *(p_zrange++) = *ptrz; } + ++ptrz; + } + const unsigned int nb_visibles = (unsigned int)(p_zrange - zrange._data); + if (!nb_visibles) { + if (render_type==5) cimg::mutex(10,0); + return *this; + } + CImg permutations; + CImg(zrange._data,nb_visibles,1,1,1,true).sort(permutations,is_forward); + + // Compute light properties + CImg lightprops; + switch (render_type) { + case 3 : { // Flat Shading + lightprops.assign(nb_visibles); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const CImg& primitive = primitives(visibles(permutations(l))); + const unsigned int psize = (unsigned int)primitive.size(); + if (psize==3 || psize==4 || psize==9 || psize==12) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nx = dy1*dz2 - dz1*dy2, + ny = dz1*dx2 - dx1*dz2, + nz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + (x0 + x1 + x2)/3 - lightx, + ly = Y + (y0 + y1 + y2)/3 - lighty, + lz = Z + (z0 + z1 + z2)/3 - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max(cimg::abs(-lx*nx - ly*ny - lz*nz)/(norm*nl),(tpfloat)0); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } else lightprops[l] = 1; + } + } break; + + case 4 : // Gouraud Shading + case 5 : { // Phong-Shading + CImg vertices_normals(vertices._width,6,1,1,0); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + for (int l = 0; l<(int)nb_visibles; ++l) { + const CImg& primitive = primitives[visibles(l)]; + const unsigned int psize = (unsigned int)primitive.size(); + const bool + triangle_flag = (psize==3) || (psize==9), + quadrangle_flag = (psize==4) || (psize==12); + if (triangle_flag || quadrangle_flag) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = quadrangle_flag?(unsigned int)primitive(3):0; + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nnx = dy1*dz2 - dz1*dy2, + nny = dz1*dx2 - dx1*dz2, + nnz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nnx,nny,nnz), + nx = nnx/norm, + ny = nny/norm, + nz = nnz/norm; + unsigned int ix = 0, iy = 1, iz = 2; + if (is_double_sided && nz>0) { ix = 3; iy = 4; iz = 5; } + vertices_normals(i0,ix)+=nx; vertices_normals(i0,iy)+=ny; vertices_normals(i0,iz)+=nz; + vertices_normals(i1,ix)+=nx; vertices_normals(i1,iy)+=ny; vertices_normals(i1,iz)+=nz; + vertices_normals(i2,ix)+=nx; vertices_normals(i2,iy)+=ny; vertices_normals(i2,iz)+=nz; + if (quadrangle_flag) { + vertices_normals(i3,ix)+=nx; vertices_normals(i3,iy)+=ny; vertices_normals(i3,iz)+=nz; + } + } + } + + if (is_double_sided) cimg_forX(vertices_normals,p) { + const float + nx0 = vertices_normals(p,0), ny0 = vertices_normals(p,1), nz0 = vertices_normals(p,2), + nx1 = vertices_normals(p,3), ny1 = vertices_normals(p,4), nz1 = vertices_normals(p,5), + n0 = nx0*nx0 + ny0*ny0 + nz0*nz0, n1 = nx1*nx1 + ny1*ny1 + nz1*nz1; + if (n1>n0) { + vertices_normals(p,0) = -nx1; + vertices_normals(p,1) = -ny1; + vertices_normals(p,2) = -nz1; + } + } + + if (render_type==4) { + lightprops.assign(vertices._width); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + vertices(l,0) - lightx, + ly = Y + vertices(l,1) - lighty, + lz = Z + vertices(l,2) - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max((-lx*nx - ly*ny - lz*nz)/(norm*nl),(tpfloat)0); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } + } else { + const unsigned int + lw2 = light_texture._width/2 - 1, + lh2 = light_texture._height/2 - 1; + lightprops.assign(vertices._width,2); + cimg_pragma_openmp(parallel for cimg_openmp_if_size(nb_visibles,4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + nnx = nx/norm, + nny = ny/norm; + lightprops(l,0) = lw2*(1 + nnx); + lightprops(l,1) = lh2*(1 + nny); + } + } + } break; + } + + // Draw visible primitives + const CImg default_color(1,_spectrum,1,1,(tc)200); + CImg<_to> _opacity; + + for (unsigned int l = 0; l& primitive = primitives[n_primitive]; + const CImg + &__color = n_primitive(), + _color = (__color && __color.size()!=_spectrum && __color._spectrum<_spectrum)? + __color.get_resize(-100,-100,-100,_spectrum,0):CImg(), + &color = _color?_color:(__color?__color:default_color); + const tc *const pcolor = color._data; + float opacity = __draw_object3d(opacities,n_primitive,_opacity); + if (_opacity.is_empty()) opacity*=g_opacity; + +#ifdef cimg_use_board + LibBoard::Board &board = *(LibBoard::Board*)pboard; +#endif + + switch (primitive.size()) { + case 1 : { // Colored point or sprite + const unsigned int n0 = (unsigned int)primitive[0]; + const int x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)); + + if (_opacity.is_empty()) { // Scalar opacity + + if (color.size()==_spectrum) { // Colored point + draw_point(x0,y0,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height()-(float)y0); + } +#endif + } else { // Sprite + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(color._width*factor), + _sh = (unsigned int)(color._height*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + draw_image(nx0,ny0,sprite,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } else { // Opacity mask + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(std::max(color._width,_opacity._width)*factor), + _sh = (unsigned int)(std::max(color._height,_opacity._height)*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + const CImg<_to> + _nopacity = (sw!=_opacity._width || sh!=_opacity._height)? + _opacity.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<_to>(), + &nopacity = _nopacity?_nopacity:_opacity; + draw_image(nx0,ny0,sprite,nopacity,g_opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } break; + case 2 : { // Colored line + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity); + else draw_line(x0,y0,x1,y1,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 5 : { // Colored sphere + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + is_wireframe = (unsigned int)primitive[2], + is_radius = (unsigned int)primitive[3]; + float Xc,Yc,Zc,radius; + if (is_radius) { + Xc = (float)vertices(n0,0); + Yc = (float)vertices(n0,1); + Zc = (float)vertices(n0,2); + radius = cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2)); + } else { + Xc = 0.5f*((float)vertices(n0,0) + (float)vertices(n1,0)); + Yc = 0.5f*((float)vertices(n0,1) + (float)vertices(n1,1)); + Zc = 0.5f*((float)vertices(n0,2) + (float)vertices(n1,2)); + radius = 0.5f*cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2)); + } + const float + zc = Z + Zc + _focale, + af = absfocale?absfocale/zc:1, + xc = X + Xc*af, + yc = Y + Yc*af; + radius*=af; + + switch (render_type) { + case 0 : + draw_point((int)xc,(int)yc,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot(xc,height() - yc); + } +#endif + break; + case 1 : + draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } +#endif + break; + default : + if (is_wireframe) draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + else draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + if (!is_wireframe) board.fillCircle(xc,height() - yc,radius); + else { + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } + } +#endif + break; + } + } break; + case 6 : { // Textured line + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for line primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + tx0 = (int)primitive[2], ty0 = (int)primitive[3], + tx1 = (int)primitive[4], ty1 = (int)primitive[5], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + else draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 3 : { // Colored triangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity).draw_point(x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x0,y0,z0,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x0,y0,x2,y2,pcolor,opacity). + draw_line(x1,y1,x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)); + else _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprops(n0),lightprops(n1),lightprops(n2),opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + } break; + } + } break; + case 4 : { // Colored quadrangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)), + x3 = cimg::uiround(projections(n3,0)), y3 = cimg::uiround(projections(n3,1)), + xc = (x0 + x1 + x2 + x3)/4, yc = (y0 + y1 + y2 + y3)/4; + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale, + zc = (z0 + z1 + z2 + z3)/4; + + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity). + draw_point(x2,y2,pcolor,opacity).draw_point(x3,y3,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,pcolor,opacity).draw_line(zbuffer,x3,y3,z3,x0,y0,z0,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x1,y1,x2,y2,pcolor,opacity). + draw_line(x2,y2,x3,y3,pcolor,opacity).draw_line(x3,y3,x0,y0,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity); + else + draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity).draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity,lightprops(l)); + else + _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)). + _draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp),(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3), + lightpropc = (lightprop0 + lightprop1 + lightprop2 + lightprop2)/4; + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,xc,yc,zc,pcolor,lightprop0,lightprop1,lightpropc,opacity). + draw_triangle(zbuffer,x1,y1,z1,x2,y2,z2,xc,yc,zc,pcolor,lightprop1,lightprop2,lightpropc,opacity). + draw_triangle(zbuffer,x2,y2,z2,x3,y3,z3,xc,yc,zc,pcolor,lightprop2,lightprop3,lightpropc,opacity). + draw_triangle(zbuffer,x3,y3,z3,x0,y0,z0,xc,yc,zc,pcolor,lightprop3,lightprop0,lightpropc,opacity); + else + draw_triangle(x0,y0,x1,y1,xc,yc,pcolor,lightprop0,lightprop1,lightpropc,opacity). + draw_triangle(x1,y1,x2,y2,xc,yc,pcolor,lightprop1,lightprop2,lightpropc,opacity). + draw_triangle(x2,y2,x3,y3,xc,yc,pcolor,lightprop2,lightprop3,lightpropc,opacity). + draw_triangle(x3,y3,x0,y0,xc,yc,pcolor,lightprop3,lightprop0,lightpropc,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)), + lx3 = (unsigned int)cimg::uiround(lightprops(n3,0)), ly3 = (unsigned int)cimg::uiround(lightprops(n3,1)), + lxc = (lx0 + lx1 + lx2 + lx3)/4, lyc = (ly0 + ly1 + ly2 + ly3)/4; + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,xc,yc,zc,pcolor,light_texture,lx0,ly0,lx1,ly1,lxc,lyc,opacity). + draw_triangle(zbuffer,x1,y1,z1,x2,y2,z2,xc,yc,zc,pcolor,light_texture,lx1,ly1,lx2,ly2,lxc,lyc,opacity). + draw_triangle(zbuffer,x2,y2,z2,x3,y3,z3,xc,yc,zc,pcolor,light_texture,lx2,ly2,lx3,ly3,lxc,lyc,opacity). + draw_triangle(zbuffer,x3,y3,z3,x0,y0,z0,xc,yc,zc,pcolor,light_texture,lx3,ly3,lx0,ly0,lxc,lyc,opacity); + else + draw_triangle(x0,y0,x1,y1,xc,yc,pcolor,light_texture,lx0,ly0,lx1,ly1,lxc,lyc,opacity). + draw_triangle(x1,y1,x2,y2,xc,yc,pcolor,light_texture,lx1,ly1,lx2,ly2,lxc,lyc,opacity). + draw_triangle(x2,y2,x3,y3,xc,yc,pcolor,light_texture,lx2,ly2,lx3,ly3,lxc,lyc,opacity). + draw_triangle(x3,y3,x0,y0,xc,yc,pcolor,light_texture,lx3,ly3,lx0,ly0,lxc,lyc,opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + case 9 : { // Textured triangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for triangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + tx0 = (int)primitive[3], ty0 = (int)primitive[4], + tx1 = (int)primitive[5], ty1 = (int)primitive[6], + tx2 = (int)primitive[7], ty2 = (int)primitive[8], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + break; + } + } break; + case 12 : { // Textured quadrangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for quadrangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + tx0 = (int)primitive[4], ty0 = (int)primitive[5], + tx1 = (int)primitive[6], ty1 = (int)primitive[7], + tx2 = (int)primitive[8], ty2 = (int)primitive[9], + tx3 = (int)primitive[10], ty3 = (int)primitive[11], + x0 = cimg::uiround(projections(n0,0)), y0 = cimg::uiround(projections(n0,1)), + x1 = cimg::uiround(projections(n1,0)), y1 = cimg::uiround(projections(n1,1)), + x2 = cimg::uiround(projections(n2,0)), y2 = cimg::uiround(projections(n2,1)), + x3 = cimg::uiround(projections(n3,0)), y3 = cimg::uiround(projections(n3,1)); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale; + + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity). + draw_point(x3,y3,color.get_vector_at(tx3<=0?0:tx3>=color.width()?color.width() - 1:tx3, + ty3<=0?0:ty3>=color.height()?color.height() - 1:ty3)._data,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1.f); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)cimg::uiround(lightprops(n0,0)), ly0 = (unsigned int)cimg::uiround(lightprops(n0,1)), + lx1 = (unsigned int)cimg::uiround(lightprops(n1,0)), ly1 = (unsigned int)cimg::uiround(lightprops(n1,1)), + lx2 = (unsigned int)cimg::uiround(lightprops(n2,0)), ly2 = (unsigned int)cimg::uiround(lightprops(n2,1)), + lx3 = (unsigned int)cimg::uiround(lightprops(n3,0)), ly3 = (unsigned int)cimg::uiround(lightprops(n3,1)); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + } + } + if (render_type==5) cimg::mutex(10,0); + return *this; + } + + //@} + //--------------------------- + // + //! \name Data Input + //@{ + //--------------------------- + + //! Launch simple interface to select a shape from an image. + /** + \param disp Display window to use. + \param feature_type Type of feature to select. Can be { 0=point | 1=line | 2=rectangle | 3=ellipse }. + \param XYZ Pointer to 3 values X,Y,Z which tells about the projection point coordinates, for volumetric images. + \param exit_on_anykey Exit function when any key is pressed. + **/ + CImg& select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) { + return get_select(disp,feature_type,XYZ,exit_on_anykey,is_deep_selection_default).move_to(*this); + } + + //! Simple interface to select a shape from an image \overloading. + CImg& select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) { + return get_select(title,feature_type,XYZ,exit_on_anykey,is_deep_selection_default).move_to(*this); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) const { + return _select(disp,0,feature_type,XYZ,0,0,0,exit_on_anykey,true,false,is_deep_selection_default); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false, + const bool is_deep_selection_default=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false,is_deep_selection_default); + } + + CImg _select(CImgDisplay &disp, const char *const title, + const unsigned int feature_type, unsigned int *const XYZ, + const int origX, const int origY, const int origZ, + const bool exit_on_anykey, + const bool reset_view3d, + const bool force_display_z_coord, + const bool is_deep_selection_default) const { + if (is_empty()) return CImg(1,feature_type==0?3:6,1,1,-1); + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + } else { + if (title) disp.set_title("%s",title); + disp.move_inside_screen(); + } + + CImg thumb; + if (width()>disp.screen_width() || height()>disp.screen_height()) + get_resize(cimg_fitscreen(width(),height(),depth()),depth(),-100).move_to(thumb); + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).set_wheel().show_mouse(); + + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + int area = 0, area_started = 0, area_clicked = 0, phase = 0, + X0 = (int)((XYZ?XYZ[0]:_width/2)%_width), + Y0 = (int)((XYZ?XYZ[1]:_height/2)%_height), + Z0 = (int)((XYZ?XYZ[2]:_depth/2)%_depth), + X1 =-1, Y1 = -1, Z1 = -1, + X3d = -1, Y3d = -1, + oX3d = X3d, oY3d = -1, + omx = -1, omy = -1; + float X = -1, Y = -1, Z = -1; + unsigned int key = 0, font_size = 32; + + bool is_deep_selection = is_deep_selection_default, + shape_selected = false, text_down = false, visible_cursor = true; + static CImg pose3d; + static bool is_view3d = false, is_axes = true; + if (reset_view3d) { pose3d.assign(); is_view3d = false; } + CImg points3d, opacities3d, sel_opacities3d; + CImgList primitives3d, sel_primitives3d; + CImgList colors3d, sel_colors3d; + CImg visu, visu0, view3d; + CImg text(1024); *text = 0; + + while (!key && !disp.is_closed() && !shape_selected) { + + // Handle mouse motion and selection + int + mx = disp.mouse_x(), + my = disp.mouse_y(); + + const float + mX = mx<0?-1.f:(float)mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my<0?-1.f:(float)my*(height() + (depth()>1?depth():0))/disp.height(); + + area = 0; + if (mX>=0 && mY>=0 && mX=0 && mX=height()) { area = 2; X = mX; Z = mY - _height; Y = (float)(phase?Y1:Y0); } + if (mY>=0 && mX>=width() && mY=width() && mY>=height()) area = 4; + if (disp.button()) { if (!area_clicked) area_clicked = area; } else area_clicked = 0; + + CImg filename(32); + + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(1); key = 0; } break; + case cimg::keyPAGEDOWN : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(-1); key = 0; } break; + case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_axes = !is_axes; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_view3d = !is_view3d; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).__draw_text(" Saving snapshot...",font_size,(int)text_down).display(disp); + visu0.save(filename); + (+visu0).__draw_text(" Snapshot '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + } + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).__draw_text(" Saving instance... ",font_size,(int)text_down).display(disp); + save(filename); + (+visu0).__draw_text(" Instance '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + } + + switch (area) { + + case 0 : // When mouse is out of image range + mx = my = -1; X = Y = Z = -1; + break; + + case 1 : case 2 : case 3 : { // When mouse is over the XY,XZ or YZ projections + const unsigned int but = disp.button(); + const bool b1 = (bool)(but&1), b2 = (bool)(but&2), b3 = (bool)(but&4); + + if (b1 && phase==1 && area_clicked==area) { // When selection has been started (1st step) + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } + if (!b1 && phase==2 && area_clicked!=area) { // When selection is at 2nd step (for volumes) + switch (area_started) { + case 1 : if (Z1!=(int)Z) visu0.assign(); Z1 = (int)Z; break; + case 2 : if (Y1!=(int)Y) visu0.assign(); Y1 = (int)Y; break; + case 3 : if (X1!=(int)X) visu0.assign(); X1 = (int)X; break; + } + } + if (b2 && area_clicked==area) { // When moving through the image/volume + if (phase) { + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } else { + if (_depth>1 && (X0!=(int)X || Y0!=(int)Y || Z0!=(int)Z)) visu0.assign(); + X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z; + } + } + if (b3) { // Reset selection + X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = area_clicked = area_started = 0; + visu0.assign(); + } + if (disp.wheel()) { // When moving through the slices of the volume (with mouse wheel) + if (_depth>1 && !disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT() && + !disp.is_keySHIFTLEFT() && !disp.is_keySHIFTRIGHT()) { + switch (area) { + case 1 : + if (phase) Z = (float)(Z1+=disp.wheel()); else Z = (float)(Z0+=disp.wheel()); + visu0.assign(); break; + case 2 : + if (phase) Y = (float)(Y1+=disp.wheel()); else Y = (float)(Y0+=disp.wheel()); + visu0.assign(); break; + case 3 : + if (phase) X = (float)(X1+=disp.wheel()); else X = (float)(X0+=disp.wheel()); + visu0.assign(); break; + } + disp.set_wheel(); + } else key = ~0U; + } + + if ((phase==0 && b1) || + (phase==1 && !b1) || + (phase==2 && b1)) switch (phase) { // Detect change of phase + case 0 : + if (area==area_clicked) { + X0 = X1 = (int)X; Y0 = Y1 = (int)Y; Z0 = Z1 = (int)Z; area_started = area; ++phase; + } break; + case 1 : + if (area==area_started) { + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; ++phase; + if (_depth>1) { + if (disp.is_keyCTRLLEFT()) is_deep_selection = !is_deep_selection_default; + if (is_deep_selection) ++phase; + } + } else if (!b1) { X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = 0; visu0.assign(); } + break; + case 2 : ++phase; break; + } + } break; + + case 4 : // When mouse is over the 3D view + if (is_view3d && points3d) { + X3d = mx - width()*disp.width()/(width() + (depth()>1?depth():0)); + Y3d = my - height()*disp.height()/(height() + (depth()>1?depth():0)); + if (oX3d<0) { oX3d = X3d; oY3d = Y3d; } + // Left + right buttons: reset. + if ((disp.button()&3)==3) { pose3d.assign(); view3d.assign(); oX3d = oY3d = X3d = Y3d = -1; } + else if (disp.button()&1 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Left button: rotate + const float + R = 0.45f*std::min(view3d._width,view3d._height), + R2 = R*R, + u0 = (float)(oX3d - view3d.width()/2), + v0 = (float)(oY3d - view3d.height()/2), + u1 = (float)(X3d - view3d.width()/2), + v1 = (float)(Y3d - view3d.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + pose3d.draw_image(CImg::rotation_matrix(u,v,w,-alpha)*pose3d.get_crop(0,0,2,2)); + view3d.assign(); + } else if (disp.button()&2 && pose3d && oY3d!=Y3d) { // Right button: zoom + pose3d(3,2)+=(Y3d - oY3d)*1.5f; view3d.assign(); + } + if (disp.wheel()) { // Wheel: zoom + pose3d(3,2)-=disp.wheel()*15; view3d.assign(); disp.set_wheel(); + } + if (disp.button()&4 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Middle button: shift + pose3d(3,0)-=oX3d - X3d; pose3d(3,1)-=oY3d - Y3d; view3d.assign(); + } + oX3d = X3d; oY3d = Y3d; + } + mx = my = -1; X = Y = Z = -1; + break; + } + + if (phase) { + if (!feature_type) shape_selected = phase?true:false; + else { + if (_depth>1) shape_selected = (phase==3)?true:false; + else shape_selected = (phase==2)?true:false; + } + } + + if (X0<0) X0 = 0; + if (X0>=width()) X0 = width() - 1; + if (Y0<0) Y0 = 0; + if (Y0>=height()) Y0 = height() - 1; + if (Z0<0) Z0 = 0; + if (Z0>=depth()) Z0 = depth() - 1; + if (X1<1) X1 = 0; + if (X1>=width()) X1 = width() - 1; + if (Y1<0) Y1 = 0; + if (Y1>=height()) Y1 = height() - 1; + if (Z1<0) Z1 = 0; + if (Z1>=depth()) Z1 = depth() - 1; + + // Draw visualization image on the display + if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) { + + if (!visu0) { // Create image of projected planes + if (thumb) thumb._get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + else _get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + visu0.resize(disp); + view3d.assign(); + points3d.assign(); + } + + if (is_view3d && _depth>1 && !view3d) { // Create 3D view for volumetric images + const unsigned int + _x3d = (unsigned int)cimg::round((float)_width*visu0._width/(_width + _depth),1,1), + _y3d = (unsigned int)cimg::round((float)_height*visu0._height/(_height + _depth),1,1), + x3d = _x3d>=visu0._width?visu0._width - 1:_x3d, + y3d = _y3d>=visu0._height?visu0._height - 1:_y3d; + CImg(1,2,1,1,64,128).resize(visu0._width - x3d,visu0._height - y3d,1,visu0._spectrum,3). + move_to(view3d); + if (!points3d) { + get_projections3d(primitives3d,colors3d,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0,true).move_to(points3d); + points3d.append(CImg(8,3,1,1, + 0,_width - 1,_width - 1,0,0,_width - 1,_width - 1,0, + 0,0,_height - 1,_height - 1,0,0,_height - 1,_height - 1, + 0,0,0,0,_depth - 1,_depth - 1,_depth - 1,_depth - 1),'x'); + CImg::vector(12,13).move_to(primitives3d); CImg::vector(13,14).move_to(primitives3d); + CImg::vector(14,15).move_to(primitives3d); CImg::vector(15,12).move_to(primitives3d); + CImg::vector(16,17).move_to(primitives3d); CImg::vector(17,18).move_to(primitives3d); + CImg::vector(18,19).move_to(primitives3d); CImg::vector(19,16).move_to(primitives3d); + CImg::vector(12,16).move_to(primitives3d); CImg::vector(13,17).move_to(primitives3d); + CImg::vector(14,18).move_to(primitives3d); CImg::vector(15,19).move_to(primitives3d); + colors3d.insert(12,CImg::vector(255,255,255)); + opacities3d.assign(primitives3d.width(),1,1,1,0.5f); + if (!phase) { + opacities3d[0] = opacities3d[1] = opacities3d[2] = 0.8f; + sel_primitives3d.assign(); + sel_colors3d.assign(); + sel_opacities3d.assign(); + } else { + if (feature_type==2) { + points3d.append(CImg(8,3,1,1, + X0,X1,X1,X0,X0,X1,X1,X0, + Y0,Y0,Y1,Y1,Y0,Y0,Y1,Y1, + Z0,Z0,Z0,Z0,Z1,Z1,Z1,Z1),'x'); + sel_primitives3d.assign(); + CImg::vector(20,21).move_to(sel_primitives3d); + CImg::vector(21,22).move_to(sel_primitives3d); + CImg::vector(22,23).move_to(sel_primitives3d); + CImg::vector(23,20).move_to(sel_primitives3d); + CImg::vector(24,25).move_to(sel_primitives3d); + CImg::vector(25,26).move_to(sel_primitives3d); + CImg::vector(26,27).move_to(sel_primitives3d); + CImg::vector(27,24).move_to(sel_primitives3d); + CImg::vector(20,24).move_to(sel_primitives3d); + CImg::vector(21,25).move_to(sel_primitives3d); + CImg::vector(22,26).move_to(sel_primitives3d); + CImg::vector(23,27).move_to(sel_primitives3d); + } else { + points3d.append(CImg(2,3,1,1, + X0,X1, + Y0,Y1, + Z0,Z1),'x'); + sel_primitives3d.assign(CImg::vector(20,21)); + } + sel_colors3d.assign(sel_primitives3d._width,CImg::vector(255,255,255)); + sel_opacities3d.assign(sel_primitives3d._width,1,1,1,0.8f); + } + points3d.shift_object3d(-0.5f*(_width - 1),-0.5f*(_height - 1),-0.5f*(_depth - 1)).resize_object3d(); + points3d*=0.75f*std::min(view3d._width,view3d._height); + } + + if (!pose3d) CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose3d); + CImg zbuffer3d(view3d._width,view3d._height,1,1,0); + const CImg rotated_points3d = pose3d.get_crop(0,0,2,2)*points3d; + if (sel_primitives3d) + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,sel_primitives3d,sel_colors3d,sel_opacities3d, + 2,true,500,0,0,0,0,0,1,zbuffer3d); + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,primitives3d,colors3d,opacities3d, + 2,true,500,0,0,0,0,0,1,zbuffer3d); + visu0.draw_image(x3d,y3d,view3d); + } + visu = visu0; + + if (X<0 || Y<0 || Z<0) { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + else { + if (is_axes) { if (visible_cursor) { disp.hide_mouse(); visible_cursor = false; }} + else { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + const int d = (depth()>1)?depth():0; + int _vX = (int)X, _vY = (int)Y, _vZ = (int)Z; + if (phase>=2) { _vX = X1; _vY = Y1; _vZ = Z1; } + int + w = disp.width(), W = width() + d, + h = disp.height(), H = height() + d, + _xp = (int)(_vX*(float)w/W), xp = _xp + ((int)(_xp*(float)W/w)!=_vX), + _yp = (int)(_vY*(float)h/H), yp = _yp + ((int)(_yp*(float)H/h)!=_vY), + _xn = (int)((_vX + 1.f)*w/W - 1), xn = _xn + ((int)((_xn + 1.f)*W/w)!=_vX + 1), + _yn = (int)((_vY + 1.f)*h/H - 1), yn = _yn + ((int)((_yn + 1.f)*H/h)!=_vY + 1), + _zxp = (int)((_vZ + width())*(float)w/W), zxp = _zxp + ((int)(_zxp*(float)W/w)!=_vZ + width()), + _zyp = (int)((_vZ + height())*(float)h/H), zyp = _zyp + ((int)(_zyp*(float)H/h)!=_vZ + height()), + _zxn = (int)((_vZ + width() + 1.f)*w/W - 1), + zxn = _zxn + ((int)((_zxn + 1.f)*W/w)!=_vZ + width() + 1), + _zyn = (int)((_vZ + height() + 1.f)*h/H - 1), + zyn = _zyn + ((int)((_zyn + 1.f)*H/h)!=_vZ + height() + 1), + _xM = (int)(width()*(float)w/W - 1), xM = _xM + ((int)((_xM + 1.f)*W/w)!=width()), + _yM = (int)(height()*(float)h/H - 1), yM = _yM + ((int)((_yM + 1.f)*H/h)!=height()), + xc = (xp + xn)/2, + yc = (yp + yn)/2, + zxc = (zxp + zxn)/2, + zyc = (zyp + zyn)/2, + xf = (int)(X*w/W), + yf = (int)(Y*h/H), + zxf = (int)((Z + width())*w/W), + zyf = (int)((Z + height())*h/H); + + if (is_axes) { // Draw axes + visu.draw_line(0,yf,visu.width() - 1,yf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,yf,visu.width() - 1,yf,background_color,0.7f,0x00FF00FF). + draw_line(xf,0,xf,visu.height() - 1,foreground_color,0.7f,0xFF00FF00). + draw_line(xf,0,xf,visu.height() - 1,background_color,0.7f,0x00FF00FF); + if (_depth>1) + visu.draw_line(zxf,0,zxf,yM,foreground_color,0.7f,0xFF00FF00). + draw_line(zxf,0,zxf,yM,background_color,0.7f,0x00FF00FF). + draw_line(0,zyf,xM,zyf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,zyf,xM,zyf,background_color,0.7f,0x00FF00FF); + } + + // Draw box cursor. + if (xn - xp>=4 && yn - yp>=4) + visu.draw_rectangle(xp,yp,xn,yn,foreground_color,0.2f). + draw_rectangle(xp,yp,xn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,yp,xn,yn,background_color,1,0x55555555); + if (_depth>1) { + if (yn - yp>=4 && zxn - zxp>=4) + visu.draw_rectangle(zxp,yp,zxn,yn,background_color,0.2f). + draw_rectangle(zxp,yp,zxn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(zxp,yp,zxn,yn,background_color,1,0x55555555); + if (xn - xp>=4 && zyn - zyp>=4) + visu.draw_rectangle(xp,zyp,xn,zyn,background_color,0.2f). + draw_rectangle(xp,zyp,xn,zyn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,zyp,xn,zyn,background_color,1,0x55555555); + } + + // Draw selection. + if (phase && (phase!=1 || area_started==area)) { + const int + _xp0 = (int)(X0*(float)w/W), xp0 = _xp0 + ((int)(_xp0*(float)W/w)!=X0), + _yp0 = (int)(Y0*(float)h/H), yp0 = _yp0 + ((int)(_yp0*(float)H/h)!=Y0), + _xn0 = (int)((X0 + 1.f)*w/W - 1), xn0 = _xn0 + ((int)((_xn0 + 1.f)*W/w)!=X0 + 1), + _yn0 = (int)((Y0 + 1.f)*h/H - 1), yn0 = _yn0 + ((int)((_yn0 + 1.f)*H/h)!=Y0 + 1), + _zxp0 = (int)((Z0 + width())*(float)w/W), zxp0 = _zxp0 + ((int)(_zxp0*(float)W/w)!=Z0 + width()), + _zyp0 = (int)((Z0 + height())*(float)h/H), zyp0 = _zyp0 + ((int)(_zyp0*(float)H/h)!=Z0 + height()), + _zxn0 = (int)((Z0 + width() + 1.f)*w/W - 1), + zxn0 = _zxn0 + ((int)((_zxn0 + 1.f)*W/w)!=Z0 + width() + 1), + _zyn0 = (int)((Z0 + height() + 1.f)*h/H - 1), + zyn0 = _zyn0 + ((int)((_zyn0 + 1.f)*H/h)!=Z0 + height() + 1), + xc0 = (xp0 + xn0)/2, + yc0 = (yp0 + yn0)/2, + zxc0 = (zxp0 + zxn0)/2, + zyc0 = (zyp0 + zyn0)/2; + + switch (feature_type) { + case 1 : { // Vector + visu.draw_arrow(xc0,yc0,xc,yc,background_color,0.9f,30,5,0x33333333). + draw_arrow(xc0,yc0,xc,yc,foreground_color,0.9f,30,5,0xCCCCCCCC); + if (d) { + visu.draw_arrow(zxc0,yc0,zxc,yc,background_color,0.9f,30,5,0x33333333). + draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.9f,30,5,0xCCCCCCCC). + draw_arrow(xc0,zyc0,xc,zyc,background_color,0.9f,30,5,0x33333333). + draw_arrow(xc0,zyc0,xc,zyc,foreground_color,0.9f,30,5,0xCCCCCCCC); + } + } break; + case 2 : { // Box + visu.draw_rectangle(X0=0 && my<13) text_down = true; else if (my>=visu.height() - 13) text_down = false; + if (!feature_type || !phase) { + if (X>=0 && Y>=0 && Z>=0 && X1 || force_display_z_coord) + cimg_snprintf(text,text._width," Point (%d,%d,%d) = [ ",origX + (int)X,origY + (int)Y,origZ + (int)Z); + else cimg_snprintf(text,text._width," Point (%d,%d) = [ ",origX + (int)X,origY + (int)Y); + CImg values = get_vector_at((int)X,(int)Y,(int)Z); + const bool is_large_spectrum = values._height>8; + if (is_large_spectrum) + values.draw_image(0,4,values.get_rows(values._height - 4,values._height - 1)).resize(1,8,1,1,0); + char *ctext = text._data + std::strlen(text), *const ltext = text._data + 512; + for (unsigned int c = 0; c::format_s(), + cimg::type::format(values[c])); + ctext += std::strlen(ctext); + if (c==3 && is_large_spectrum) { + cimg_snprintf(ctext,24," ..."); + ctext += std::strlen(ctext); + } + *(ctext++) = ' '; *ctext = 0; + } + std::strcpy(text._data + std::strlen(text),"] "); + } + } else switch (feature_type) { + case 1 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + length = cimg::round(cimg::hypot(dX,dY,dZ),0.1); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width," Vect (%d,%d,%d)-(%d,%d,%d), Length = %g ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1,length); + else if (_width!=1 && _height!=1) + cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g, Angle = %g\260 ", + origX + X0,origY + Y0,origX + X1,origY + Y1,length, + cimg::round(cimg::mod(180*std::atan2(-dY,-dX)/cimg::PI,360.),0.1)); + else + cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Length = %g ", + origX + X0,origY + Y0,origX + X1,origY + Y1,length); + } break; + case 2 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + length = cimg::round(cimg::hypot(dX,dY,dZ),0.1); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width, + " Box ( %d,%d,%d ) - ( %d,%d,%d )\n Size = ( %d,%d,%d ), Length = %g ", + origX + (X01 || force_display_z_coord) + cimg_snprintf(text,text._width," Ellipse ( %d,%d,%d ) - ( %d,%d,%d ), Radii = ( %d,%d,%d ) ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),1 + cimg::abs(Z0 - Z1)); + else cimg_snprintf(text,text._width," Ellipse ( %d,%d ) - ( %d,%d ), Radii = ( %d,%d ) ", + origX + X0,origY + Y0,origX + X1,origY + Y1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1)); + } + if (phase || (mx>=0 && my>=0)) visu.__draw_text("%s",font_size,(int)text_down,text._data); + } + + disp.display(visu); + } + if (!shape_selected) disp.wait(); + if (disp.is_resized()) { disp.resize(false)._is_resized = false; old_is_resized = true; visu0.assign(); } + omx = mx; omy = my; + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + + // Return result. + CImg res(1,feature_type==0?3:6,1,1,-1); + if (XYZ) { XYZ[0] = (unsigned int)X0; XYZ[1] = (unsigned int)Y0; XYZ[2] = (unsigned int)Z0; } + if (shape_selected) { + if (feature_type==2) { + if (is_deep_selection) switch (area_started) { + case 1 : Z0 = 0; Z1 = _depth - 1; break; + case 2 : Y0 = 0; Y1 = _height - 1; break; + case 3 : X0 = 0; X1 = _width - 1; break; + } + if (X0>X1) cimg::swap(X0,X1); + if (Y0>Y1) cimg::swap(Y0,Y1); + if (Z0>Z1) cimg::swap(Z0,Z1); + } + if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1; + switch (feature_type) { + case 1 : case 2 : res[0] = X0; res[1] = Y0; res[2] = Z0; res[3] = X1; res[4] = Y1; res[5] = Z1; break; + case 3 : + res[3] = cimg::abs(X1 - X0); res[4] = cimg::abs(Y1 - Y0); res[5] = cimg::abs(Z1 - Z0); + res[0] = X0; res[1] = Y0; res[2] = Z0; + break; + default : res[0] = X0; res[1] = Y0; res[2] = Z0; + } + } + if (!exit_on_anykey || !(disp.button()&4)) disp.set_button(); + if (!visible_cursor) disp.show_mouse(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + if (key!=~0U) disp.set_key(key); + return res; + } + + // Return a visualizable uchar8 image for display routines. + CImg _get_select(const CImgDisplay& disp, const int normalization, + const int x, const int y, const int z) const { + if (is_empty()) return CImg(1,1,1,1,0); + const CImg crop = get_shared_channels(0,std::min(2,spectrum() - 1)); + CImg img2d; + if (_depth>1) { + const int mdisp = std::min(disp.screen_width(),disp.screen_height()); + if (depth()>mdisp) { + crop.get_resize(-100,-100,mdisp,-100,0).move_to(img2d); + img2d.projections2d(x,y,z*img2d._depth/_depth); + } else crop.get_projections2d(x,y,z).move_to(img2d); + } else CImg(crop,false).move_to(img2d); + + // Check for inf and NaN values. + if (cimg::type::is_float() && normalization) { + bool is_inf = false, is_nan = false; + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) { is_inf = true; break; } + else if (cimg::type::is_nan(*ptr)) { is_nan = true; break; } + if (is_inf || is_nan) { + Tint m0 = (Tint)cimg::type::max(), M0 = (Tint)cimg::type::min(); + if (!normalization) { m0 = 0; M0 = 255; } + else if (normalization==2) { m0 = (Tint)disp._min; M0 = (Tint)disp._max; } + else + cimg_for(img2d,ptr,Tuchar) + if (!cimg::type::is_inf(*ptr) && !cimg::type::is_nan(*ptr)) { + if (*ptr<(Tuchar)m0) m0 = *ptr; + if (*ptr>(Tuchar)M0) M0 = *ptr; + } + const T + val_minf = (T)(normalization==1 || normalization==3?m0 - (M0 - m0)*20 - 1:m0), + val_pinf = (T)(normalization==1 || normalization==3?M0 + (M0 - m0)*20 + 1:M0); + if (is_nan) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_nan(*ptr)) *ptr = val_minf; // Replace NaN values + if (is_inf) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) *ptr = (float)*ptr<0?val_minf:val_pinf; // Replace +-inf values + } + } + + switch (normalization) { + case 1 : img2d.normalize((ucharT)0,(ucharT)255); break; + case 2 : { + const float m = disp._min, M = disp._max; + (img2d-=m)*=255.f/(M - m>0?M - m:1); + } break; + case 3 : + if (cimg::type::is_float()) img2d.normalize((ucharT)0,(ucharT)255); + else { + const float + m = (float)cimg::type::min(), + M = (float)cimg::type::max(); + (img2d-=m)*=255.f/(M - m>0?M - m:1); + } break; + } + if (img2d.spectrum()==2) img2d.channels(0,2); + return img2d; + } + + //! Select sub-graph in a graph. + CImg get_select_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "select_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title("CImg<%s>",pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth; + const unsigned int old_normalization = disp.normalization(); + disp.show().set_button().set_wheel()._normalization = 0; + + double nymin = ymin, nymax = ymax, nxmin = xmin, nxmax = xmax; + if (nymin==nymax) { nymin = (Tfloat)min_max(nymax); const double dy = nymax - nymin; nymin-=dy/20; nymax+=dy/20; } + if (nymin==nymax) { --nymin; ++nymax; } + if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.; } + + static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 }; + static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 }; + + CImg colormap(3,_spectrum); + if (_spectrum==1) { colormap[0] = colormap[1] = 120; colormap[2] = 200; } + else { + colormap(0,0) = 220; colormap(1,0) = 10; colormap(2,0) = 10; + if (_spectrum>1) { colormap(0,1) = 10; colormap(1,1) = 220; colormap(2,1) = 10; } + if (_spectrum>2) { colormap(0,2) = 10; colormap(1,2) = 10; colormap(2,2) = 220; } + if (_spectrum>3) { colormap(0,3) = 220; colormap(1,3) = 220; colormap(2,3) = 10; } + if (_spectrum>4) { colormap(0,4) = 220; colormap(1,4) = 10; colormap(2,4) = 220; } + if (_spectrum>5) { colormap(0,5) = 10; colormap(1,5) = 220; colormap(2,5) = 220; } + if (_spectrum>6) { + cimg_uint64 rng = 10; + cimg_for_inY(colormap,6,colormap.height()-1,k) { + colormap(0,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + colormap(1,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + colormap(2,k) = (unsigned char)(120 + cimg::rand(-100.f,100.f,&rng)); + } + } + } + + CImg visu0, visu, graph, text, axes; + int x0 = -1, x1 = -1, y0 = -1, y1 = -1, omouse_x = -2, omouse_y = -2; + const unsigned int one = plot_type==3?0U:1U; + unsigned int okey = 0, obutton = 0, font_size = 32; + CImg message(1024); + CImg_3x3(I,unsigned char); + + for (bool selected = false; !selected && !disp.is_closed() && !okey && !disp.wheel(); ) { + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + const unsigned int key = disp.key(), button = disp.button(); + + // Generate graph representation. + if (!visu0) { + visu0.assign(disp.width(),disp.height(),1,3,220); + const int gdimx = disp.width() - 32, gdimy = disp.height() - 32; + if (gdimx>0 && gdimy>0) { + graph.assign(gdimx,gdimy,1,3,255); + if (siz<32) { + if (siz>1) graph.draw_grid(gdimx/(float)(siz - one),gdimy/(float)(siz - one),0,0, + false,true,black,0.2f,0x33333333,0x33333333); + } else graph.draw_grid(-10,-10,0,0,false,true,black,0.2f,0x33333333,0x33333333); + cimg_forC(*this,c) + graph.draw_graph(get_shared_channel(c),&colormap(0,c),(plot_type!=3 || _spectrum==1)?1:0.6f, + plot_type,vertex_type,nymax,nymin); + + axes.assign(gdimx,gdimy,1,1,0); + const float + dx = (float)cimg::abs(nxmax - nxmin), dy = (float)cimg::abs(nymax - nymin), + px = (float)std::pow(10.,(int)std::log10(dx?dx:1) - 2.), + py = (float)std::pow(10.,(int)std::log10(dy?dy:1) - 2.); + const CImg + seqx = dx<=0?CImg::vector(nxmin): + CImg::sequence(1 + gdimx/60,nxmin,one?nxmax:nxmin + (nxmax - nxmin)*(siz + 1)/siz), + seqy = CImg::sequence(1 + gdimy/60,nymax,nymin); + + const bool allow_zero = (nxmin*nxmax>0) || (nymin*nymax>0); + axes.draw_axes(seqx,seqy,white,1,~0U,~0U,13,allow_zero,px,py); + if (nymin>0) axes.draw_axis(seqx,gdimy - 1,gray,1,~0U,13,allow_zero,px); + if (nymax<0) axes.draw_axis(seqx,0,gray,1,~0U,13,allow_zero,px); + if (nxmin>0) axes.draw_axis(0,seqy,gray,1,~0U,13,allow_zero,py); + if (nxmax<0) axes.draw_axis(gdimx - 1,seqy,gray,1,~0U,13,allow_zero,py); + + cimg_for3x3(axes,x,y,0,0,I,unsigned char) + if (Icc) { + if (Icc==255) cimg_forC(graph,c) graph(x,y,c) = 0; + else cimg_forC(graph,c) graph(x,y,c) = (unsigned char)(2*graph(x,y,c)/3); + } + else if (Ipc || Inc || Icp || Icn || Ipp || Inn || Ipn || Inp) + cimg_forC(graph,c) graph(x,y,c) = (unsigned char)((graph(x,y,c) + 511)/3); + + visu0.draw_image(16,16,graph); + visu0.draw_line(15,15,16 + gdimx,15,gray2).draw_line(16 + gdimx,15,16 + gdimx,16 + gdimy,gray2). + draw_line(16 + gdimx,16 + gdimy,15,16 + gdimy,white).draw_line(15,16 + gdimy,15,15,white); + } else graph.assign(); + text.assign().draw_text(0,0,labelx?labelx:"X-axis",white,ngray,1,13).resize(-100,-100,1,3); + visu0.draw_image((visu0.width() - text.width())/2,visu0.height() - 14,~text); + text.assign().draw_text(0,0,labely?labely:"Y-axis",white,ngray,1,13).rotate(-90).resize(-100,-100,1,3); + visu0.draw_image(1,(visu0.height() - text.height())/2,~text); + visu.assign(); + } + + // Generate and display current view. + if (!visu) { + visu.assign(visu0); + if (graph && x0>=0 && x1>=0) { + const int + nx0 = x0<=x1?x0:x1, + nx1 = x0<=x1?x1:x0, + ny0 = y0<=y1?y0:y1, + ny1 = y0<=y1?y1:y0, + sx0 = (int)(16 + nx0*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sx1 = (int)(15 + (nx1 + 1)*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sy0 = 16 + ny0, + sy1 = 16 + ny1; + if (y0>=0 && y1>=0) + visu.draw_rectangle(sx0,sy0,sx1,sy1,gray,0.5f).draw_rectangle(sx0,sy0,sx1,sy1,black,0.5f,0xCCCCCCCCU); + else visu.draw_rectangle(sx0,0,sx1,visu.height() - 17,gray,0.5f). + draw_line(sx0,16,sx0,visu.height() - 17,black,0.5f,0xCCCCCCCCU). + draw_line(sx1,16,sx1,visu.height() - 17,black,0.5f,0xCCCCCCCCU); + } + if (mouse_x>=16 && mouse_y>=16 && mouse_x=7) + cimg_snprintf(message,message._width,"Value[%u:%g] = ( %g %g %g ... %g %g %g )",x,cx, + (double)(*this)(x,0,0,0),(double)(*this)(x,0,0,1),(double)(*this)(x,0,0,2), + (double)(*this)(x,0,0,_spectrum - 4),(double)(*this)(x,0,0,_spectrum - 3), + (double)(*this)(x,0,0,_spectrum - 1)); + else { + cimg_snprintf(message,message._width,"Value[%u:%g] = ( ",x,cx); + cimg_forC(*this,c) cimg_sprintf(message._data + std::strlen(message),"%g ",(double)(*this)(x,0,0,c)); + cimg_sprintf(message._data + std::strlen(message),")"); + } + if (x0>=0 && x1>=0) { + const unsigned int + nx0 = (unsigned int)(x0<=x1?x0:x1), + nx1 = (unsigned int)(x0<=x1?x1:x0), + ny0 = (unsigned int)(y0<=y1?y0:y1), + ny1 = (unsigned int)(y0<=y1?y1:y0); + const double + cx0 = nxmin + nx0*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cx1 = nxmin + (nx1 + one)*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cy0 = nymax - ny0*(nymax - nymin)/(visu._height - 32), + cy1 = nymax - ny1*(nymax - nymin)/(visu._height - 32); + if (y0>=0 && y1>=0) + cimg_sprintf(message._data + std::strlen(message)," - Range ( %u:%g, %g ) - ( %u:%g, %g )", + x0,cx0,cy0,x1 + one,cx1,cy1); + else + cimg_sprintf(message._data + std::strlen(message)," - Range [ %u:%g - %u:%g ]", + x0,cx0,x1 + one,cx1); + } + text.assign().draw_text(0,0,message,white,ngray,1,13).resize(-100,-100,1,3); + visu.draw_image((visu.width() - text.width())/2,1,~text); + } + visu.display(disp); + } + + // Test keys. + CImg filename(32); + switch (okey = key) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : okey = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).__draw_text(" Saving snapshot... ",font_size,0).display(disp); + screen.save(filename); + (+screen).__draw_text(" Snapshot '%s' saved. ",font_size,0,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).__draw_text(" Saving instance... ",font_size,0).display(disp); + save(filename); + (+screen).__draw_text(" Instance '%s' saved. ",font_size,0,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + } + + // Handle mouse motion and mouse buttons. + if (obutton!=button || omouse_x!=mouse_x || omouse_y!=mouse_y) { + visu.assign(); + if (disp.mouse_x()>=0 && disp.mouse_y()>=0) { + const int + mx = (mouse_x - 16)*(int)(siz - one)/(disp.width() - 32), + cx = cimg::cut(mx,0,(int)(siz - 1 - one)), + my = mouse_y - 16, + cy = cimg::cut(my,0,disp.height() - 32); + if (button&1) { + if (!obutton) { x0 = cx; y0 = -1; } else { x1 = cx; y1 = -1; } + } + else if (button&2) { + if (!obutton) { x0 = cx; y0 = cy; } else { x1 = cx; y1 = cy; } + } + else if (obutton) { x1 = x1>=0?cx:-1; y1 = y1>=0?cy:-1; selected = true; } + } else if (!button && obutton) selected = true; + obutton = button; omouse_x = mouse_x; omouse_y = mouse_y; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (visu && visu0) disp.wait(); + if (!exit_on_anykey && okey && okey!=cimg::keyESC && + (okey!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + okey = 0; + } + } + + disp._normalization = old_normalization; + if (x1>=0 && x1(4,1,1,1,x0,y0,x1>=0?x1 + (int)one:-1,y1); + } + + //! Load image from a file. + /** + \param filename Filename, as a C-string. + \note The extension of \c filename defines the file format. If no filename + extension is provided, CImg::get_load() will try to load the file as a .cimg or .cimgz file. + **/ + CImg& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load(): Specified filename is (null).", + cimg_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimg_load_plugin + cimg_load_plugin(filename); +#endif +#ifdef cimg_load_plugin1 + cimg_load_plugin1(filename); +#endif +#ifdef cimg_load_plugin2 + cimg_load_plugin2(filename); +#endif +#ifdef cimg_load_plugin3 + cimg_load_plugin3(filename); +#endif +#ifdef cimg_load_plugin4 + cimg_load_plugin4(filename); +#endif +#ifdef cimg_load_plugin5 + cimg_load_plugin5(filename); +#endif +#ifdef cimg_load_plugin6 + cimg_load_plugin6(filename); +#endif +#ifdef cimg_load_plugin7 + cimg_load_plugin7(filename); +#endif +#ifdef cimg_load_plugin8 + cimg_load_plugin8(filename); +#endif + // Text formats + if (!cimg::strcasecmp(ext,"asc")) load_ascii(filename); + else if (!cimg::strcasecmp(ext,"csv") || + !cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) load_dlm(filename); + else if (!cimg::strcasecmp(ext,"pdf")) load_pdf_external(filename); + + // 2D binary formats + else if (!cimg::strcasecmp(ext,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) load_jpeg(filename); + else if (!cimg::strcasecmp(ext,"png")) load_png(filename); + else if (!cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"pnm") || + !cimg::strcasecmp(ext,"pbm") || + !cimg::strcasecmp(ext,"pnk")) load_pnm(filename); + else if (!cimg::strcasecmp(ext,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"exr")) load_exr(filename); + else if (!cimg::strcasecmp(ext,"cr2") || + !cimg::strcasecmp(ext,"crw") || + !cimg::strcasecmp(ext,"dcr") || + !cimg::strcasecmp(ext,"mrw") || + !cimg::strcasecmp(ext,"nef") || + !cimg::strcasecmp(ext,"orf") || + !cimg::strcasecmp(ext,"pix") || + !cimg::strcasecmp(ext,"ptx") || + !cimg::strcasecmp(ext,"raf") || + !cimg::strcasecmp(ext,"srf")) load_dcraw_external(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"heic") || + !cimg::strcasecmp(ext,"avif")) load_heif(filename); + + // 3D binary formats + else if (!cimg::strcasecmp(ext,"dcm") || + !cimg::strcasecmp(ext,"dicom")) load_medcon_external(filename); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) load_analyze(filename); + else if (!cimg::strcasecmp(ext,"par") || + !cimg::strcasecmp(ext,"rec")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"mnc")) load_minc2(filename); + else if (!cimg::strcasecmp(ext,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(ext,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) return load_cimg(filename); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + + // Image sequences + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded) { + std::FILE *file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to open file '%s'.", + cimg_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + cimg::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"pnm")) load_pnm(filename); + else if (!cimg::strcasecmp(f_type,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(f_type,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(f_type,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(f_type,"jpg")) load_jpeg(filename); + else if (!cimg::strcasecmp(f_type,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(f_type,"png")) load_png(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"dcm")) load_medcon_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file with other means. + if (!is_loaded) { + try { + load_other(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image from a file \newinstance. + static CImg get_load(const char *const filename) { + return CImg().load(filename); + } + + //! Load image from an ascii file. + /** + \param filename Filename, as a C -string. + **/ + CImg& load_ascii(const char *const filename) { + return _load_ascii(0,filename); + } + + //! Load image from an ascii file \inplace. + static CImg get_load_ascii(const char *const filename) { + return CImg().load_ascii(filename); + } + + //! Load image from an ascii file \overloading. + CImg& load_ascii(std::FILE *const file) { + return _load_ascii(file,0); + } + + //! Loadimage from an ascii file \newinstance. + static CImg get_load_ascii(std::FILE *const file) { + return CImg().load_ascii(file); + } + + CImg& _load_ascii(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_ascii(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg line(256); *line = 0; + int err = std::fscanf(nfile,"%255[^\n]",line._data); + unsigned int dx = 0, dy = 1, dz = 1, dc = 1; + cimg_sscanf(line,"%u%*c%u%*c%u%*c%u",&dx,&dy,&dz,&dc); + err = std::fscanf(nfile,"%*[^0-9.eEinfa+-]"); + if (!dx || !dy || !dz || !dc) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_ascii(): Invalid ascii header in file '%s', image dimensions are set " + "to (%u,%u,%u,%u).", + cimg_instance, + filename?filename:"(FILE*)",dx,dy,dz,dc); + } + assign(dx,dy,dz,dc); + const ulongT siz = size(); + ulongT off = 0; + double val; + T *ptr = _data; + for (err = 1, off = 0; off& load_dlm(const char *const filename) { + return _load_dlm(0,filename); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(const char *const filename) { + return CImg().load_dlm(filename); + } + + //! Load image from a DLM file \overloading. + CImg& load_dlm(std::FILE *const file) { + return _load_dlm(file,0); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(std::FILE *const file) { + return CImg().load_dlm(file); + } + + CImg& _load_dlm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_dlm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + CImg delimiter(256), tmp(256); *delimiter = *tmp = 0; + unsigned int cdx = 0, dx = 0, dy = 0; + int err = 0; + double val; + assign(256,256,1,1,(T)0); + while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) { + if (err>0) (*this)(cdx++,dy) = (T)val; + if (cdx>=_width) resize(3*_width/2,_height,1,1,0); + char c = 0; + if (!cimg_sscanf(delimiter,"%255[^\n]%c",tmp._data,&c) || c=='\n') { + dx = std::max(cdx,dx); + if (++dy>=_height) resize(_width,3*_height/2,1,1,0); + cdx = 0; + } + } + if (cdx && err==1) { dx = cdx; ++dy; } + if (!dx || !dy) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_dlm(): Invalid DLM file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + resize(dx,dy,1,1,0); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a BMP file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_bmp(const char *const filename) { + return _load_bmp(0,filename); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(const char *const filename) { + return CImg().load_bmp(filename); + } + + //! Load image from a BMP file \overloading. + CImg& load_bmp(std::FILE *const file) { + return _load_bmp(file,0); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(std::FILE *const file) { + return CImg().load_bmp(file); + } + + CImg& _load_bmp(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_bmp(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(54); + cimg::fread(header._data,54,nfile); + if (*header!='B' || header[1]!='M') { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_bmp(): Invalid BMP file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read header and pixel buffer + int + file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24), + offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24), + header_size = header[0x0E] + (header[0x0F]<<8) + (header[0x10]<<16) + (header[0x11]<<24), + dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24), + dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24), + compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24), + nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24), + bpp = header[0x1C] + (header[0x1D]<<8); + + if (!file_size || file_size==offset) { + cimg::fseek(nfile,0,SEEK_END); + file_size = (int)cimg::ftell(nfile); + cimg::fseek(nfile,54,SEEK_SET); + } + if (header_size>40) cimg::fseek(nfile,header_size - 40,SEEK_CUR); + + const int + dx_bytes = (bpp==1)?(dx/8 + (dx%8?1:0)):((bpp==4)?(dx/2 + (dx%2)):(int)((longT)dx*bpp/8)), + align_bytes = (4 - dx_bytes%4)%4; + const ulongT + cimg_iobuffer = (ulongT)24*1024*1024, + buf_size = (ulongT)cimg::abs(dy)*(dx_bytes + align_bytes); + + CImg colormap; + if (bpp<16) { if (!nb_colors) nb_colors = 1<0) cimg::fseek(nfile,xoffset,SEEK_CUR); + + CImg buffer; + if (buf_size=2) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0x80, val = 0; + cimg_forX(*this,x) { + if (mask==0x80) val = *(ptrs++); + const unsigned char *col = (unsigned char*)(colormap._data + (val&mask?1:0)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask); + } + ptrs+=align_bytes; + } + } break; + case 4 : { // 16 colors + if (colormap._width>=16) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0xF0, val = 0; + cimg_forX(*this,x) { + if (mask==0xF0) val = *(ptrs++); + const unsigned char color = (unsigned char)((mask<16)?(val&mask):((val&mask)>>4)); + const unsigned char *col = (unsigned char*)(colormap._data + color); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask,4); + } + ptrs+=align_bytes; + } + } break; + case 8 : { // 256 colors + if (colormap._width>=256) for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char *col = (unsigned char*)(colormap._data + *(ptrs++)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + } + ptrs+=align_bytes; + } + } break; + case 16 : { // 16 bits colors (RGB565) + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char c1 = *(ptrs++), c2 = *(ptrs++); + const unsigned short col = (unsigned short)c2<<8 | c1; + (*this)(x,y,2) = (T)((col&0x1F)<<3); + (*this)(x,y,1) = (T)(((col>>5)&0x3F)<<3); + (*this)(x,y,0) = (T)(((col>>11)&0x1F)<<3); + } + ptrs+=align_bytes; + } + } break; + case 24 : { // 24 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + } + ptrs+=align_bytes; + } + } break; + case 32 : { // 32 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break; + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + ++ptrs; + } + ptrs+=align_bytes; + } + } break; + } + if (dy<0) mirror('y'); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a JPEG file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_jpeg(const char *const filename) { + return _load_jpeg(0,filename); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(const char *const filename) { + return CImg().load_jpeg(filename); + } + + //! Load image from a JPEG file \overloading. + CImg& load_jpeg(std::FILE *const file) { + return _load_jpeg(file,0); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(std::FILE *const file) { + return CImg().load_jpeg(file); + } + + // Custom error handler for libjpeg. +#ifdef cimg_use_jpeg + struct _cimg_error_mgr { + struct jpeg_error_mgr original; + jmp_buf setjmp_buffer; + char message[JMSG_LENGTH_MAX]; + }; + + typedef struct _cimg_error_mgr *_cimg_error_ptr; + + METHODDEF(void) _cimg_jpeg_error_exit(j_common_ptr cinfo) { + _cimg_error_ptr c_err = (_cimg_error_ptr) cinfo->err; // Return control to the setjmp point + (*cinfo->err->format_message)(cinfo,c_err->message); + jpeg_destroy(cinfo); // Clean memory and temp files + longjmp(c_err->setjmp_buffer,1); + } +#endif + + CImg& _load_jpeg(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_jpeg(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_jpeg + if (file) + throw CImgIOException(_cimg_instance + "load_jpeg(): Unable to load data from '(FILE*)' unless libjpeg is enabled.", + cimg_instance); + else return load_other(filename); +#else + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + struct jpeg_decompress_struct cinfo; + struct _cimg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.original); + jerr.original.error_exit = _cimg_jpeg_error_exit; + if (setjmp(jerr.setjmp_buffer)) { // JPEG error + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_jpeg(): Error message returned by libjpeg: %s.", + cimg_instance,jerr.message); + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo,nfile); + jpeg_read_header(&cinfo,TRUE); + jpeg_start_decompress(&cinfo); + + if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) { + if (!file) { + cimg::fclose(nfile); + return load_other(filename); + } else + throw CImgIOException(_cimg_instance + "load_jpeg(): Failed to load JPEG data from file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + } + CImg buffer(cinfo.output_width*cinfo.output_components); + JSAMPROW row_pointer[1]; + try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); } + catch (...) { if (!file) cimg::fclose(nfile); throw; } + T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height, + *ptr_a = _data + 3UL*_width*_height; + while (cinfo.output_scanline + // This is experimental code, not much tested, use with care. + CImg& load_magick(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_magick(): Specified filename is (null).", + cimg_instance); + +#ifdef cimg_use_magick + Magick::Image image(filename); + const unsigned int W = image.size().width(), H = image.size().height(); + switch (image.type()) { + case Magick::PaletteMatteType : + case Magick::TrueColorMatteType : + case Magick::ColorSeparationType : { + assign(W,H,1,4); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + case Magick::PaletteType : + case Magick::TrueColorType : { + assign(W,H,1,3); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + ++pixels; + } + } break; + case Magick::GrayscaleMatteType : { + assign(W,H,1,2); + T *ptr_r = data(0,0,0,0), *ptr_a = data(0,0,0,1); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + default : { + assign(W,H,1,1); + T *ptr_r = data(0,0,0,0); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + ++pixels; + } + } + } + return *this; +#else + throw CImgIOException(_cimg_instance + "load_magick(): Unable to load file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Load image from a file, using Magick++ library \newinstance. + static CImg get_load_magick(const char *const filename) { + return CImg().load_magick(filename); + } + + //! Load image from a PNG file. + /** + \param filename Filename, as a C-string. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + **/ + CImg& load_png(const char *const filename, unsigned int *const bits_per_value=0) { + return _load_png(0,filename,bits_per_value); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(const char *const filename, unsigned int *const bits_per_value=0) { + return CImg().load_png(filename,bits_per_value); + } + + //! Load image from a PNG file \overloading. + CImg& load_png(std::FILE *const file, unsigned int *const bits_per_value=0) { + return _load_png(file,0,bits_per_value); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(std::FILE *const file, unsigned int *const bits_per_value=0) { + return CImg().load_png(file,bits_per_value); + } + + // (Note: Most of this function has been written by Eric Fausett) + CImg& _load_png(std::FILE *const file, const char *const filename, unsigned int *const bits_per_value) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_png(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_png + cimg::unused(bits_per_value); + if (file) + throw CImgIOException(_cimg_instance + "load_png(): Unable to load data from '(FILE*)' unless libpng is enabled.", + cimg_instance); + + else return load_other(filename); +#else + // Open file and check for PNG validity +#if defined __GNUC__ + const char *volatile nfilename = filename; // Use 'volatile' to avoid (wrong) g++ warning + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb"); +#else + const char *nfilename = filename; + std::FILE *nfile = file?file:cimg::fopen(nfilename,"rb"); +#endif + unsigned char pngCheck[8] = { 0 }; + cimg::fread(pngCheck,8,(std::FILE*)nfile); + if (png_sig_cmp(pngCheck,0,8)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Invalid PNG file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Setup PNG structures for read + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn); + if (!png_ptr) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'png_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,(png_infopp)0,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'info_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'end_info' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Error handling callback for png file reading + if (setjmp(png_jmpbuf(png_ptr))) { + if (!file) cimg::fclose((std::FILE*)nfile); + png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Encountered unknown fatal error in libpng for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + png_set_sig_bytes(png_ptr, 8); + + // Get PNG Header Info up to data block + png_read_info(png_ptr,info_ptr); + png_uint_32 W, H; + int bit_depth, color_type, interlace_type; + bool is_gray = false; + png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,(int*)0,(int*)0); + if (bits_per_value) *bits_per_value = (unsigned int)bit_depth; + + // Transforms to unify image data + if (color_type==PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + color_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + } + if (color_type==PNG_COLOR_TYPE_GRAY && bit_depth<8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + is_gray = true; + bit_depth = 8; + } + if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_ptr); + color_type |= PNG_COLOR_MASK_ALPHA; + } + if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + color_type |= PNG_COLOR_MASK_COLOR; + is_gray = true; + } + if (color_type==PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr,0xffffU,PNG_FILLER_AFTER); + + png_read_update_info(png_ptr,info_ptr); + if (bit_depth!=8 && bit_depth!=16) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Invalid bit depth %u in file '%s'.", + cimg_instance, + bit_depth,nfilename?nfilename:"(FILE*)"); + } + const int byte_depth = bit_depth>>3; + + // Allocate memory for image reading + png_bytep *const imgData = new png_bytep[H]; + for (unsigned int row = 0; row& load_pnm(const char *const filename) { + return _load_pnm(0,filename); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(const char *const filename) { + return CImg().load_pnm(filename); + } + + //! Load image from a PNM file \overloading. + CImg& load_pnm(std::FILE *const file) { + return _load_pnm(file,0); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(std::FILE *const file) { + return CImg().load_pnm(file); + } + + CImg& _load_pnm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pnm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + unsigned int ppm_type, W, H, D = 1, colormax = 255; + CImg item(16384,1,1,1,0); + int err, rval, gval, bval; + const longT cimg_iobuffer = (longT)24*1024*1024; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%u",&ppm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %u %u %u %u",&W,&H,&D,&colormax))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): WIDTH and HEIGHT fields undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (ppm_type!=1 && ppm_type!=4) { + if (err==2 || (err==3 && (ppm_type==5 || ppm_type==7 || ppm_type==8 || ppm_type==9))) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%u",&colormax)!=1) + cimg::warn(_cimg_instance + "load_pnm(): COLORMAX field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else { colormax = D; D = 1; } + } + std::fgetc(nfile); + + if (filename) { // Check that dimensions specified in file does not exceed the buffer dimension + const cimg_int64 siz = cimg::fsize(filename); + if (W*H*D>siz) + throw CImgIOException(_cimg_instance + "load_pnm(): Specified image dimensions in file '%s' exceed file size.", + cimg_instance, + filename); + } + + switch (ppm_type) { + case 1 : { // 2D B&W ascii + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)(rval?0:255); else break; } + } break; + case 2 : { // 2D grey ascii + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)rval; else break; } + } break; + case 3 : { // 2D color ascii + assign(W,H,1,3); + T *ptrd = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forXY(*this,x,y) { + if (std::fscanf(nfile,"%d %d %d",&rval,&gval,&bval)==3) { + *(ptrd++) = (T)rval; *(ptr_g++) = (T)gval; *(ptr_b++) = (T)bval; + } else break; + } + } break; + case 4 : { // 2D b&w binary (support 3D PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + unsigned int w = 0, h = 0, d = 0; + for (longT to_read = (longT)((W/8 + (W%8?1:0))*H*D); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + unsigned char mask = 0, val = 0; + for (ulongT off = (ulongT)raw._width; off || mask; mask>>=1) { + if (!mask) { if (off--) val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?0:255); + if (++w==W) { w = 0; mask = 0; if (++h==H) { h = 0; if (++d==D) break; }} + } + } + } break; + case 5 : case 7 : { // 2D/3D grey binary (support 3D PINK extension) + if (colormax<256) { // 8 bits + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } else { // 16 bits + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } + } break; + case 6 : { // 2D color binary + if (colormax<256) { // 8 bits + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { // 16 bits + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } + } break; + case 8 : { // 2D/3D grey binary with int32 integers (PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const int *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + case 9 : { // 2D/3D grey binary with float values (PINK extension) + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const float *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + default : + assign(); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM type 'P%d' found, but type is not supported.", + cimg_instance, + filename?filename:"(FILE*)",ppm_type); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PFM file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pfm(const char *const filename) { + return _load_pfm(0,filename); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(const char *const filename) { + return CImg().load_pfm(filename); + } + + //! Load image from a PFM file \overloading. + CImg& load_pfm(std::FILE *const file) { + return _load_pfm(file,0); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(std::FILE *const file) { + return CImg().load_pfm(file); + } + + CImg& _load_pfm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pfm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + char pfm_type; + CImg item(16384,1,1,1,0); + int W = 0, H = 0, err = 0; + double scale = 0; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%c",&pfm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): PFM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %d %d",&W,&H))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH and HEIGHT fields are undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else if (W<=0 || H<=0) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH (%d) and HEIGHT (%d) fields are invalid in file '%s'.", + cimg_instance,W,H, + filename?filename:"(FILE*)"); + } + if (err==2) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%lf",&scale)!=1) + cimg::warn(_cimg_instance + "load_pfm(): SCALE field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + std::fgetc(nfile); + const bool is_color = (pfm_type=='F'), is_inverted = (scale>0)!=cimg::endianness(); + if (is_color) { + assign(W,H,1,3,(T)0); + CImg buf(3*W); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forY(*this,y) { + cimg::fread(buf._data,3*W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,3*W); + const float *ptrs = buf._data; + cimg_forX(*this,x) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { + assign(W,H,1,1,(T)0); + CImg buf(W); + T *ptrd = data(0,0,0,0); + cimg_forY(*this,y) { + cimg::fread(buf._data,W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,W); + const float *ptrs = buf._data; + cimg_forX(*this,x) *(ptrd++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return mirror('y'); // Most of the .pfm files are flipped along the y-axis + } + + //! Load image from a RGB file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(0,filename,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(filename,dimw,dimh); + } + + //! Load image from a RGB file \overloading. + CImg& load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(file,0,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(file,dimw,dimh); + } + + CImg& _load_rgb(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgb(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/3UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a RGBA file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(0,filename,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(filename,dimw,dimh); + } + + //! Load image from a RGBA file \overloading. + CImg& load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(file,0,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(file,dimw,dimh); + } + + CImg& _load_rgba(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgba(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,4); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2), + *ptr_a = data(0,0,0,3); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/4UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a TIFF file. + /** + \param filename Filename, as a C-string. + \param first_frame First frame to read (for multi-pages tiff). + \param last_frame Last frame to read (for multi-pages tiff). + \param step_frame Step value of frame reading. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + \param[out] voxel_size Voxel size, as stored in the filename. + \param[out] description Description, as stored in the filename. + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tiff is not defined at compile time the + function uses CImg& load_other(const char*). + **/ + CImg& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Specified filename is (null).", + cimg_instance); + + const unsigned int + nfirst_frame = first_frame1) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.", + cimg_instance, + filename); + return load_other(filename); +#else +#if cimg_verbosity<3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimg_instance + "load_tiff(): File '%s' contains %u image(s) while specified frame range is [%u,%u] (step %u).", + cimg_instance, + filename,nb_images,nfirst_frame,nlast_frame,nstep_frame); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + TIFFSetDirectory(tif,0); + CImg frame; + for (unsigned int l = nfirst_frame; l<=nlast_frame; l+=nstep_frame) { + frame._load_tiff(tif,l,bits_per_value,voxel_size,description); + if (l==nfirst_frame) + assign(frame._width,frame._height,1 + (nlast_frame - nfirst_frame)/nstep_frame,frame._spectrum); + if (frame._width>_width || frame._height>_height || frame._spectrum>_spectrum) + resize(std::max(frame._width,_width), + std::max(frame._height,_height),-100, + std::max(frame._spectrum,_spectrum),0); + draw_image(0,0,(l - nfirst_frame)/nstep_frame,frame); + } + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "load_tiff(): Failed to open file '%s'.", + cimg_instance, + filename); + return *this; +#endif + } + + //! Load image from a TIFF file \newinstance. + static CImg get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + return CImg().load_tiff(filename,first_frame,last_frame,step_frame,bits_per_value,voxel_size,description); + } + + // (Original contribution by Jerome Boulanger). +#ifdef cimg_use_tiff + template + void _load_tiff_tiled_contig(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int row = 0; row + void _load_tiff_tiled_separate(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int vv = 0; vv + void _load_tiff_contig(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (row = 0; rowny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, 0); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0; rr + void _load_tiff_separate(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (unsigned int vv = 0; vvny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, vv); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0;rr& _load_tiff(TIFF *const tif, const unsigned int directory, unsigned int *const bits_per_value, + float *const voxel_size, CImg *const description) { + if (!TIFFSetDirectory(tif,directory)) return assign(); + uint16 samplesperpixel = 1, bitspersample = 8, photo = 0; + uint16 sampleformat = 1; + uint32 nx = 1, ny = 1; + const char *const filename = TIFFFileName(tif); + const bool is_spp = (bool)TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel); + TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx); + TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleformat); + TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample); + TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo); + if (bits_per_value) *bits_per_value = (unsigned int)bitspersample; + if (voxel_size) { + const char *s_description = 0; + float vx = 0, vy = 0, vz = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) { + const char *s_desc = std::strstr(s_description,"VX="); + if (s_desc && cimg_sscanf(s_desc,"VX=%f VY=%f VZ=%f",&vx,&vy,&vz)==3) { // CImg format + voxel_size[0] = vx; voxel_size[1] = vy; voxel_size[2] = vz; + } + s_desc = std::strstr(s_description,"spacing="); + if (s_desc && cimg_sscanf(s_desc,"spacing=%f",&vz)==1) { // Fiji format + voxel_size[2] = vz; + } + } + TIFFGetField(tif,TIFFTAG_XRESOLUTION,voxel_size); + TIFFGetField(tif,TIFFTAG_YRESOLUTION,voxel_size + 1); + voxel_size[0] = 1.f/voxel_size[0]; + voxel_size[1] = 1.f/voxel_size[1]; + } + if (description) { + const char *s_description = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) + CImg::string(s_description).move_to(*description); + } + const unsigned int spectrum = !is_spp || photo>=3?(photo>1?3:1):samplesperpixel; + assign(nx,ny,1,spectrum); + + if ((photo>=3 && sampleformat==1 && + (bitspersample==4 || bitspersample==8) && + (samplesperpixel==1 || samplesperpixel==3 || samplesperpixel==4)) || + (bitspersample==1 && samplesperpixel==1)) { + // Special case for unsigned color images. + uint32 *const raster = (uint32*)_TIFFmalloc(nx*ny*sizeof(uint32)); + if (!raster) { + _TIFFfree(raster); TIFFClose(tif); + throw CImgException(_cimg_instance + "load_tiff(): Failed to allocate memory (%s) for file '%s'.", + cimg_instance, + cimg::strbuffersize(nx*ny*sizeof(uint32)),filename); + } + TIFFReadRGBAImage(tif,nx,ny,raster,0); + switch (spectrum) { + case 1 : + cimg_forXY(*this,x,y) + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]); + break; + case 3 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + } + break; + case 4 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny - 1 - y) + x]); + } + break; + } + _TIFFfree(raster); + } else { // Other cases + uint16 config; + TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config); + if (TIFFIsTiled(tif)) { + uint32 tw = 1, th = 1; + TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw); + TIFFGetField(tif,TIFFTAG_TILELENGTH,&th); + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + } + } else { + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 64 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + } + } + } + return *this; + } +#endif + + //! Load image from a MINC2 file. + /** + \param filename Filename, as a C-string. + **/ + // (Original code by Haz-Edine Assemlal). + CImg& load_minc2(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_minc2(): Specified filename is (null).", + cimg_instance); +#ifndef cimg_use_minc2 + return load_other(filename); +#else + minc::minc_1_reader rdr; + rdr.open(filename); + assign(rdr.ndim(1)?rdr.ndim(1):1, + rdr.ndim(2)?rdr.ndim(2):1, + rdr.ndim(3)?rdr.ndim(3):1, + rdr.ndim(4)?rdr.ndim(4):1); + if (pixel_type()==cimg::type::string()) + rdr.setup_read_byte(); + else if (pixel_type()==cimg::type::string()) + rdr.setup_read_int(); + else if (pixel_type()==cimg::type::string()) + rdr.setup_read_double(); + else + rdr.setup_read_float(); + minc::load_standard_volume(rdr,this->_data); + return *this; +#endif + } + + //! Load image from a MINC2 file \newinstance. + static CImg get_load_minc2(const char *const filename) { + return CImg().load_analyze(filename); + } + + //! Load image from an ANALYZE7.5/NIFTI file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_analyze(const char *const filename, float *const voxel_size=0) { + return _load_analyze(0,filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(const char *const filename, float *const voxel_size=0) { + return CImg().load_analyze(filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \overloading. + CImg& load_analyze(std::FILE *const file, float *const voxel_size=0) { + return _load_analyze(file,0,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(std::FILE *const file, float *const voxel_size=0) { + return CImg().load_analyze(file,voxel_size); + } + + CImg& _load_analyze(std::FILE *const file, const char *const filename, float *const voxel_size=0) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_analyze(): Specified filename is (null).", + cimg_instance); + + std::FILE *nfile_header = 0, *nfile = 0; + if (!file) { + CImg body(1024); + const char *const ext = cimg::split_filename(filename,body); + if (!cimg::strcasecmp(ext,"hdr")) { // File is an Analyze header file + nfile_header = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".img"); + nfile = cimg::fopen(body,"rb"); + } else if (!cimg::strcasecmp(ext,"img")) { // File is an Analyze data file + nfile = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".hdr"); + nfile_header = cimg::fopen(body,"rb"); + } else nfile_header = nfile = cimg::fopen(filename,"rb"); // File is a Niftii file + } else nfile_header = nfile = file; // File is a Niftii file + if (!nfile || !nfile_header) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid Analyze7.5 or NIFTI header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + // Read header. + bool endian = false; + unsigned int header_size; + cimg::fread(&header_size,1,nfile_header); + if (!header_size) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid zero-size header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (header_size>=4096) { endian = true; cimg::invert_endianness(header_size); } + + unsigned char *const header = new unsigned char[header_size]; + cimg::fread(header + 4,header_size - 4,nfile_header); + if (!file && nfile_header!=nfile) cimg::fclose(nfile_header); + if (endian) { + cimg::invert_endianness((short*)(header + 40),5); + cimg::invert_endianness((short*)(header + 70),1); + cimg::invert_endianness((short*)(header + 72),1); + cimg::invert_endianness((float*)(header + 76),4); + cimg::invert_endianness((float*)(header + 108),1); + cimg::invert_endianness((float*)(header + 112),1); + } + + if (nfile_header==nfile) { + const unsigned int vox_offset = (unsigned int)*(float*)(header + 108); + std::fseek(nfile,vox_offset,SEEK_SET); + } + + unsigned short *dim = (unsigned short*)(header + 40), dimx = 1, dimy = 1, dimz = 1, dimv = 1; + if (!dim[0]) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with zero dimensions.", + cimg_instance, + filename?filename:"(FILE*)"); + + if (dim[0]>4) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with %u dimensions, reading only the 4 first.", + cimg_instance, + filename?filename:"(FILE*)",dim[0]); + + if (dim[0]>=1) dimx = dim[1]; + if (dim[0]>=2) dimy = dim[2]; + if (dim[0]>=3) dimz = dim[3]; + if (dim[0]>=4) dimv = dim[4]; + float scalefactor = *(float*)(header + 112); if (scalefactor==0) scalefactor = 1; + const unsigned short datatype = *(unsigned short*)(header + 70); + if (voxel_size) { + const float *vsize = (float*)(header + 76); + voxel_size[0] = vsize[1]; voxel_size[1] = vsize[2]; voxel_size[2] = vsize[3]; + } + delete[] header; + + // Read pixel data. + assign(dimx,dimy,dimz,dimv); + const size_t pdim = (size_t)dimx*dimy*dimz*dimv; + switch (datatype) { + case 2 : { + unsigned char *const buffer = new unsigned char[pdim]; + cimg::fread(buffer,pdim,nfile); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 4 : { + short *const buffer = new short[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 8 : { + int *const buffer = new int[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 16 : { + float *const buffer = new float[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 64 : { + double *const buffer = new double[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_analyze(): Unable to load datatype %d in file '%s'", + cimg_instance, + datatype,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a .cimg[z] file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(const char *const filename, const char axis='z', const float align=0) { + return CImg().load_cimg(filename,axis,align); + } + + //! Load image from a .cimg[z] file \overloading. + CImg& load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + return CImg().load_cimg(file,axis,align); + } + + //! Load sub-images of a .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Starting frame. + \param n1 Ending frame (~0U for max). + \param x0 X-coordinate of the starting sub-image vertex. + \param y0 Y-coordinate of the starting sub-image vertex. + \param z0 Z-coordinate of the starting sub-image vertex. + \param c0 C-coordinate of the starting sub-image vertex. + \param x1 X-coordinate of the ending sub-image vertex (~0U for max). + \param y1 Y-coordinate of the ending sub-image vertex (~0U for max). + \param z1 Z-coordinate of the ending sub-image vertex (~0U for max). + \param c1 C-coordinate of the ending sub-image vertex (~0U for max). + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load sub-images of a .cimg file \overloading. + CImg& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load image from an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_inr(const char *const filename, float *const voxel_size=0) { + return _load_inr(0,filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(const char *const filename, float *const voxel_size=0) { + return CImg().load_inr(filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \overloading. + CImg& load_inr(std::FILE *const file, float *const voxel_size=0) { + return _load_inr(file,0,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(std::FILE *const file, float *voxel_size=0) { + return CImg().load_inr(file,voxel_size); + } + + static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) { + CImg item(1024), tmp1(64), tmp2(64); + *item = *tmp1 = *tmp2 = 0; + out[0] = std::fscanf(file,"%63s",item._data); + out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1; + if (cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0) + throw CImgIOException("CImg<%s>::load_inr(): INRIMAGE-4 header not found.", + pixel_type()); + + while (std::fscanf(file," %63[^\n]%*c",item._data)!=EOF && std::strncmp(item,"##}",3)) { + cimg_sscanf(item," XDIM%*[^0-9]%d",out); + cimg_sscanf(item," YDIM%*[^0-9]%d",out + 1); + cimg_sscanf(item," ZDIM%*[^0-9]%d",out + 2); + cimg_sscanf(item," VDIM%*[^0-9]%d",out + 3); + cimg_sscanf(item," PIXSIZE%*[^0-9]%d",out + 6); + if (voxel_size) { + cimg_sscanf(item," VX%*[^0-9.+-]%f",voxel_size); + cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1); + cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2); + } + if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1; + switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) { + case 0 : break; + case 2 : + out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; + std::strncpy(tmp1,tmp2,tmp1._width - 1); // fallthrough + case 1 : + if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5)) out[4] = 0; + if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1; + if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2; + if (out[4]>=0) break; // fallthrough + default : + throw CImgIOException("CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.", + pixel_type(), + tmp2._data); + } + } + if (out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0) + throw CImgIOException("CImg<%s>::load_inr(): Invalid dimensions (%d,%d,%d,%d) defined in header.", + pixel_type(), + out[0],out[1],out[2],out[3]); + if (out[4]<0 || out[5]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete pixel type defined in header.", + pixel_type()); + if (out[6]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete PIXSIZE field defined in header.", + pixel_type()); + if (out[7]<0) + throw CImgIOException("CImg<%s>::load_inr(): Big/Little Endian coding type undefined in header.", + pixel_type()); + } + + CImg& _load_inr(std::FILE *const file, const char *const filename, float *const voxel_size) { +#define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \ + if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \ + Ts *xval, *const val = new Ts[(size_t)fopt[0]*fopt[3]]; \ + cimg_forYZ(*this,y,z) { \ + cimg::fread(val,fopt[0]*fopt[3],nfile); \ + if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \ + xval = val; cimg_forX(*this,x) cimg_forC(*this,c) (*this)(x,y,z,c) = (T)*(xval++); \ + } \ + delete[] val; \ + loaded = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_inr(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + int fopt[8], endian = cimg::endianness()?1:0; + bool loaded = false; + if (voxel_size) voxel_size[0] = voxel_size[1] = voxel_size[2] = 1; + _load_inr_header(nfile,fopt,voxel_size); + assign(fopt[0],fopt[1],fopt[2],fopt[3]); + _cimg_load_inr_case(0,0,8,unsigned char); + _cimg_load_inr_case(0,1,8,char); + _cimg_load_inr_case(0,0,16,unsigned short); + _cimg_load_inr_case(0,1,16,short); + _cimg_load_inr_case(0,0,32,unsigned int); + _cimg_load_inr_case(0,1,32,int); + _cimg_load_inr_case(1,0,32,float); + _cimg_load_inr_case(1,1,32,float); + _cimg_load_inr_case(1,0,64,double); + _cimg_load_inr_case(1,1,64,double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_inr(): Unknown pixel type defined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a EXR file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_exr(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_exr(): Specified filename is (null).", + cimg_instance); +#if defined(cimg_use_openexr) + Imf::RgbaInputFile file(filename); + Imath::Box2i dw = file.dataWindow(); + const int + inwidth = dw.max.x - dw.min.x + 1, + inheight = dw.max.y - dw.min.y + 1; + Imf::Array2D pixels; + pixels.resizeErase(inheight,inwidth); + file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y*inwidth, 1, inwidth); + file.readPixels(dw.min.y, dw.max.y); + assign(inwidth,inheight,1,4); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + cimg_forXY(*this,x,y) { + *(ptr_r++) = (T)pixels[y][x].r; + *(ptr_g++) = (T)pixels[y][x].g; + *(ptr_b++) = (T)pixels[y][x].b; + *(ptr_a++) = (T)pixels[y][x].a; + } + return *this; +#elif defined(cimg_use_tinyexr) + float *res; + const char *err = 0; + int width = 0, height = 0; + const int ret = LoadEXR(&res,&width,&height,filename,&err); + if (ret) throw CImgIOException(_cimg_instance + "load_exr(): Unable to load EXR file '%s'.", + cimg_instance,filename); + CImg(res,4,width,height,1,true).get_permute_axes("yzcx").move_to(*this); + std::free(res); + return *this; +#else + return load_other(filename); +#endif + } + + //! Load image from a EXR file \newinstance. + static CImg get_load_exr(const char *const filename) { + return CImg().load_exr(filename); + } + + //! Load image from a PANDORE-5 file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pandore(const char *const filename) { + return _load_pandore(0,filename); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(const char *const filename) { + return CImg().load_pandore(filename); + } + + //! Load image from a PANDORE-5 file \overloading. + CImg& load_pandore(std::FILE *const file) { + return _load_pandore(file,0); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(std::FILE *const file) { + return CImg().load_pandore(file); + } + + CImg& _load_pandore(std::FILE *const file, const char *const filename) { +#define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \ + cimg::fread(dims,nbdim,nfile); \ + if (endian) cimg::invert_endianness(dims,nbdim); \ + assign(nwidth,nheight,ndepth,ndim); \ + const size_t siz = size(); \ + stype *buffer = new stype[siz]; \ + cimg::fread(buffer,siz,nfile); \ + if (endian) cimg::invert_endianness(buffer,siz); \ + T *ptrd = _data; \ + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \ + buffer-=siz; \ + delete[] buffer + +#define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \ + if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \ + else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \ + else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \ + else throw CImgIOException(_cimg_instance \ + "load_pandore(): Unknown pixel datatype in file '%s'.", \ + cimg_instance, \ + filename?filename:"(FILE*)"); } + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pandore(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(32); + cimg::fread(header._data,12,nfile); + if (cimg::strncasecmp("PANDORE",header,7)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): PANDORE header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + unsigned int imageid, dims[8] = { 0 }; + int ptbuf[4] = { 0 }; + cimg::fread(&imageid,1,nfile); + const bool endian = imageid>255; + if (endian) cimg::invert_endianness(imageid); + cimg::fread(header._data,20,nfile); + + switch (imageid) { + case 2 : _cimg_load_pandore_case(2,dims[1],1,1,1,unsigned char,unsigned char,unsigned char,1); break; + case 3 : _cimg_load_pandore_case(2,dims[1],1,1,1,long,int,short,4); break; + case 4 : _cimg_load_pandore_case(2,dims[1],1,1,1,double,float,float,4); break; + case 5 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,unsigned char,unsigned char,unsigned char,1); break; + case 6 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,long,int,short,4); break; + case 7 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,double,float,float,4); break; + case 8 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,unsigned char,unsigned char,unsigned char,1); break; + case 9 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,long,int,short,4); break; + case 10 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,double,float,float,4); break; + case 11 : { // Region 1D + cimg::fread(dims,3,nfile); + if (endian) cimg::invert_endianness(dims,3); + assign(dims[1],1,1,1); + const unsigned siz = size(); + if (dims[2]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[2]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 12 : { // Region 2D + cimg::fread(dims,4,nfile); + if (endian) cimg::invert_endianness(dims,4); + assign(dims[2],dims[1],1,1); + const size_t siz = size(); + if (dims[3]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[3]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 13 : { // Region 3D + cimg::fread(dims,5,nfile); + if (endian) cimg::invert_endianness(dims,5); + assign(dims[3],dims[2],dims[1],1); + const size_t siz = size(); + if (dims[4]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[4]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 16 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,unsigned char,unsigned char,unsigned char,1); break; + case 17 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,long,int,short,4); break; + case 18 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,double,float,float,4); break; + case 19 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,unsigned char,unsigned char,unsigned char,1); break; + case 20 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,long,int,short,4); break; + case 21 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,double,float,float,4); break; + case 22 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 23 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],long,int,short,4); break; + case 24 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 25 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],double,float,float,4); break; + case 26 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 27 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],long,int,short,4); break; + case 28 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 29 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],double,float,float,4); break; + case 30 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned char,unsigned char,unsigned char,1); + break; + case 31 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],long,int,short,4); break; + case 32 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned long,unsigned int,unsigned short,4); + break; + case 33 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break; + case 34 : { // Points 1D + cimg::fread(ptbuf,1,nfile); + if (endian) cimg::invert_endianness(ptbuf,1); + assign(1); (*this)(0) = (T)ptbuf[0]; + } break; + case 35 : { // Points 2D + cimg::fread(ptbuf,2,nfile); + if (endian) cimg::invert_endianness(ptbuf,2); + assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0]; + } break; + case 36 : { // Points 3D + cimg::fread(ptbuf,3,nfile); + if (endian) cimg::invert_endianness(ptbuf,3); + assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0]; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): Unable to load data with ID_type %u in file '%s'.", + cimg_instance, + imageid,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PAR-REC (Philips) file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_parrec(const char *const filename, const char axis='c', const float align=0) { + CImgList list; + list.load_parrec(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a PAR-REC (Philips) file \newinstance. + static CImg get_load_parrec(const char *const filename, const char axis='c', const float align=0) { + return CImg().load_parrec(filename,axis,align); + } + + //! Load image from a raw binary file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the image buffer. + \param size_y Height of the image buffer. + \param size_z Depth of the image buffer. + \param size_c Spectrum of the image buffer. + \param is_multiplexed Tells if the image values are multiplexed along the C-axis. + \param invert_endianness Tells if the endianness of the image buffer must be inverted. + \param offset Starting offset of the read in the specified file. + **/ + CImg& load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(0,filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \overloading. + CImg& load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(file,0,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(file,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + CImg& _load_raw(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const bool is_multiplexed, const bool invert_endianness, + const ulongT offset) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename is (null).", + cimg_instance); + if (cimg::is_directory(filename)) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename '%s' is a directory.", + cimg_instance,filename); + const bool is_bool = pixel_type()==cimg::type::string(); + ulongT siz = (ulongT)size_x*size_y*size_z*size_c; + unsigned int + _size_x = size_x, + _size_y = size_y, + _size_z = size_z, + _size_c = size_c; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + if (!siz) { // Retrieve file size + const longT fpos = cimg::ftell(nfile); + if (fpos<0) throw CImgArgumentException(_cimg_instance + "load_raw(): Cannot determine size of input file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + cimg::fseek(nfile,0,SEEK_END); + siz = (ulongT)cimg::ftell(nfile); + if (!is_bool) { siz/=sizeof(T); _size_y = (unsigned int)siz; } + else _size_y = (unsigned int)(siz*8); + _size_x = _size_z = _size_c = 1; + cimg::fseek(nfile,fpos,SEEK_SET); + } + cimg::fseek(nfile,(longT)offset,SEEK_SET); + assign(_size_x,_size_y,_size_z,_size_c,0); + + if (is_bool) { // Boolean data (bitwise) + unsigned char *const buf = new unsigned char[siz]; + cimg::fread(buf,siz,nfile); + _uchar2bool(buf,siz,is_multiplexed); + delete[] buf; + } else { // Non-boolean data + if (siz && (!is_multiplexed || size_c==1)) { // Non-multiplexed + cimg::fread(_data,siz,nfile); + if (invert_endianness) cimg::invert_endianness(_data,siz); + } else if (siz) { // Multiplexed + CImg buf(1,1,1,_size_c); + cimg_forXYZ(*this,x,y,z) { + cimg::fread(buf._data,_size_c,nfile); + if (invert_endianness) cimg::invert_endianness(buf._data,_size_c); + set_vector_at(buf,x,y,z); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image sequence from a YUV file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the frames. + \param size_y Height of the frames. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param yuv2rgb Tells if the YUV to RGB transform must be applied. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + **/ + CImg& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load image sequence from a YUV file \overloading. + CImg& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load 3D object from a .OFF file. + /** + \param[out] primitives Primitives data of the 3D object. + \param[out] colors Colors data of the 3D object. + \param filename Filename, as a C-string. + **/ + template + CImg& load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return _load_off(primitives,colors,0,filename); + } + + //! Load 3D object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return CImg().load_off(primitives,colors,filename); + } + + //! Load 3D object from a .OFF file \overloading. + template + CImg& load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return _load_off(primitives,colors,file,0); + } + + //! Load 3D object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return CImg().load_off(primitives,colors,file); + } + + template + CImg& _load_off(CImgList& primitives, CImgList& colors, + std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_off(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + unsigned int nb_points = 0, nb_primitives = 0, nb_read = 0; + CImg line(256); *line = 0; + int err; + + // Skip comments, and read magic string OFF + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if (cimg::strncasecmp(line,"OFF",3) && cimg::strncasecmp(line,"COFF",4)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): OFF header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%u%u%*[^\n] ",&nb_points,&nb_primitives))!=2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Invalid number of vertices or primitives specified in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read points data + assign(nb_points,3); + float X = 0, Y = 0, Z = 0; + cimg_forX(*this,l) { + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%f%f%f%*[^\n] ",&X,&Y,&Z))!=3) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Failed to read vertex %u/%u in file '%s'.", + cimg_instance, + l + 1,nb_points,filename?filename:"(FILE*)"); + } + (*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z; + } + + // Read primitive data + primitives.assign(); + colors.assign(); + bool stop_flag = false; + while (!stop_flag) { + float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f; + unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0; + *line = 0; + if ((err = std::fscanf(nfile,"%u",&prim))!=1) stop_flag = true; + else { + ++nb_read; + switch (prim) { + case 1 : { + if ((err = std::fscanf(nfile,"%u%255[^\n] ",&i0,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 2 : { + if ((err = std::fscanf(nfile,"%u%u%255[^\n] ",&i0,&i1,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 3 : { + if ((err = std::fscanf(nfile,"%u%u%u%255[^\n] ",&i0,&i1,&i2,line._data))<3) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 4 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,line._data))<4) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 5 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,line._data))<5) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 6 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,line._data))<6) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 7 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i4,i3,i1).move_to(primitives); + CImg::vector(i0,i6,i5,i4).move_to(primitives); + CImg::vector(i3,i2,i1).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + case 8 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + CImg::vector(i0,i7,i6,i5).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + default : + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.", + cimg_instance, + nb_read,nb_primitives,prim,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } + } + } + if (!file) cimg::fclose(nfile); + if (primitives._width!=nb_primitives) + cimg::warn(_cimg_instance + "load_off(): Only %u/%u primitives read from file '%s'.", + cimg_instance, + primitives._width,nb_primitives,filename?filename:"(FILE*)"); + return *this; + } + + //! Load image sequence from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param axis Alignment axis. + \param align Appending alignment. + **/ + CImg& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return get_load_video(filename,first_frame,last_frame,step_frame,axis,align).move_to(*this); + } + + //! Load image sequence from a video file, using OpenCV library \newinstance. + static CImg get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame).get_append(axis,align); + } + + //! Load image sequence using custom's external tool 'custom'. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_custom_external(const char *const filename, const char axis='z', const float align=0) { + return get_load_custom_external(filename,axis,align).move_to(*this); + } + + //! Load image sequence using custom's external tool 'custom' \newinstance. + static CImg get_load_custom_external(const char *const filename, const char axis='z', const float align=0) { + return CImgList().load_custom_external(filename).get_append(axis,align); + } + + //! Load gif file, using Imagemagick or GraphicsMagicks's external tools. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return get_load_gif_external(filename,axis,align).move_to(*this); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tool 'convert' \newinstance. + static CImg get_load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return CImgList().load_gif_external(filename).get_append(axis,align); + } + + //! Load image from a HEIC file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_heif(const char *const filename) { + return _load_heif(filename); + } + + //! Load image from a HEIC file \newinstance. + static CImg get_load_heif(const char *const filename) { + return CImg().load_heif(filename); + } + + CImg& _load_heif(const char *const filename) { +#ifndef cimg_use_heif + return load_other(filename); +#else + try { + heif::Context ctx; + ctx.read_from_file(filename); + + heif::ImageHandle handle = ctx.get_primary_image_handle(); + const heif::Image image = + handle.decode_image(heif_colorspace_RGB,handle.has_alpha_channel()?heif_chroma_interleaved_RGBA: + heif_chroma_interleaved_RGB); + const int + W = image.get_width(heif_channel_interleaved), + H = image.get_height(heif_channel_interleaved), + S = handle.has_alpha_channel()?4:3; + assign(W,H,1,S); + + int stride; + const unsigned char *const buffer = image.get_plane(heif_channel_interleaved,&stride); + T *ptr_r = _data, *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = S>3?data(0,0,0,3):0; + cimg_forY(*this,y) { + const unsigned char *ptrs = buffer + y*stride; + if (ptr_a) cimg_forX(*this,x) { // RGBA + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + else cimg_forX(*this,x) { // RGB + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } catch (const heif::Error& e) { + throw CImgInstanceException(_cimg_instance + "load_heif(): Unable to decode image: %s", + cimg_instance, + e.get_message().c_str()); + } catch (...) { + throw; + } + return *this; +#endif + } + + //! Load image using GraphicsMagick's external tool 'gm'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_graphicsmagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + if (!cimg::system("which gm")) { + cimg_snprintf(command,command._width,"%s convert \"%s\" %s:-", + cimg::graphicsmagick_path(), + s_filename.data(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { +#ifdef cimg_use_png + load_png(file); +#else + load_pnm(file); +#endif + } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' " + "with external command 'gm'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(), + cimg_file_separator, + cimg::filenamerand(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" convert \"%s\" \"%s\"", + cimg::graphicsmagick_path(), + s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::graphicsmagick_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.", + cimg_instance, + filename); + + } else cimg::fclose(file); +#ifdef cimg_use_png + load_png(filename_tmp); +#else + load_pnm(filename_tmp); +#endif + std::remove(filename_tmp); + return *this; + } + + //! Load image using GraphicsMagick's external tool 'gm' \newinstance. + static CImg get_load_graphicsmagick_external(const char *const filename) { + return CImg().load_graphicsmagick_external(filename); + } + + //! Load gzipped image file, using external tool 'gunzip'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimg_instance + "load_gzip_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + const char + *const ext = cimg::split_filename(filename,body), + *const ext2 = cimg::split_filename(body,0); + + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_gzip_external(): Failed to load file '%s' with external command 'gunzip'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load gzipped image file, using external tool 'gunzip' \newinstance. + static CImg get_load_gzip_external(const char *const filename) { + return CImg().load_gzip_external(filename); + } + + //! Load image using ImageMagick's external tool 'convert'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_imagemagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_imagemagick_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + if (!cimg::system("which convert")) { + cimg_snprintf(command,command._width,"%s%s \"%s\" %s:-", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { +#ifdef cimg_use_png + load_png(file); +#else + load_pnm(file); +#endif + } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(), + cimg_file_separator, + cimg::filenamerand(), +#ifdef cimg_use_png + "png" +#else + "pnm" +#endif + ); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\"%s \"%s\" \"%s\"", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::imagemagick_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + + } else cimg::fclose(file); +#ifdef cimg_use_png + load_png(filename_tmp); +#else + load_pnm(filename_tmp); +#endif + std::remove(filename_tmp); + return *this; + } + + //! Load image using ImageMagick's external tool 'convert' \newinstance. + static CImg get_load_imagemagick_external(const char *const filename) { + return CImg().load_imagemagick_external(filename); + } + + //! Load image from a DICOM file, using Medcon's external tool 'medcon'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_medcon_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_medcon_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + cimg::fclose(cimg::fopen(filename,"r")); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -w -c anlz -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::medcon_path()); + cimg::split_filename(filename_tmp,body); + + cimg_snprintf(command,command._width,"%s.hdr",body._data); + file = cimg::std_fopen(command,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s.hdr",body._data); + file = cimg::std_fopen(command,"rb"); + if (!file) { + throw CImgIOException(_cimg_instance + "load_medcon_external(): Failed to load file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + load_analyze(command); + std::remove(command); + cimg::split_filename(command,body); + cimg_snprintf(command,command._width,"%s.img",body._data); + std::remove(command); + return *this; + } + + //! Load image from a DICOM file, using Medcon's external tool 'medcon' \newinstance. + static CImg get_load_medcon_external(const char *const filename) { + return CImg().load_medcon_external(filename); + } + + //! Load image from a .pdf file. + /** + \param filename Filename, as a C-string. + \param resolution Image resolution. + **/ + CImg& load_pdf_external(const char *const filename, const unsigned int resolution=400) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_pdf_external(): Specified filename is (null).", + cimg_instance); + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o - -r%u \"%s\"", + resolution,s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_pdf_external(): Failed to load file '%s' with external command 'gs'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"gs -q -dNOPAUSE -sDEVICE=ppmraw -o \"%s\" -r%u \"%s\"", + CImg::string(filename_tmp)._system_strescape().data(),resolution,s_filename.data()); + cimg::system(command,"gs"); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_pdf_external(): Failed to load file '%s' with external command 'gs'.", + cimg_instance, + filename); + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a .pdf file \newinstance. + static CImg get_load_pdf_external(const char *const filename, const unsigned int resolution=400) { + return CImg().load_pdf_external(filename,resolution); + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_dcraw_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_dcraw_external(): Specified filename is (null).", + cimg_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"%s -w -4 -c \"%s\"", + cimg::dcraw_path(),s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -w -4 -c \"%s\" > \"%s\"", + cimg::dcraw_path(),s_filename.data(),CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::dcraw_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw' \newinstance. + static CImg get_load_dcraw_external(const char *const filename) { + return CImg().load_dcraw_external(filename); + } + +#ifdef cimg_use_opencv + + // Convert a continuous cv::Mat to a CImg. + static CImg _cvmat2cimg(const cv::Mat &src) { + if (src.channels()==1) return CImg(src.ptr(),src.cols,src.rows,1,1); + else if (src.channels()==3) { // BGR + CImg res(src.cols,src.rows,1,src.channels()); + const unsigned char *ptrs = src.ptr(); + unsigned char *pR = res.data(), *pG = res.data(0,0,0,1), *pB = res.data(0,0,0,2); + cimg_forXY(res,x,y) { *(pB++) = *(ptrs++); *(pG++) = *(ptrs++); *(pR++) = *(ptrs++); } + return res; + } + return CImg(src.ptr(),src.channels(),src.cols,src.rows,1,true).get_permute_axes("yzcx"); + } + + // Convert a CImg to a cv::Mat. + cv::Mat _cimg2cvmat() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Instance image is empty.", + cimg_instance); + if (_spectrum==2) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Invalid number of channels (should be '1' or '3+').", + cimg_instance); + if (_depth!=1) + throw CImgInstanceException(_cimg_instance + "_cimg2cvmat() : Invalid number of slices (should be '1').", + cimg_instance); + int mat_type = -1; + if (pixel_type()==cimg::type::string()) mat_type = CV_8UC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_8SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_16UC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_16SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_32SC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_32FC1; + if (pixel_type()==cimg::type::string()) mat_type = CV_64FC1; + if (mat_type<0) + throw CImgInstanceException(_cimg_instance + "_cvmat2cimg() : pixel type '%s' is not supported.", + cimg_instance,pixel_type()); + cv::Mat res; + std::vector channels(_spectrum); + if (_spectrum>1) { + cimg_forC(*this,c) + channels[c] = cv::Mat(_height,_width,mat_type,_data + _width*_height*(_spectrum - 1 - c)); + cv::merge(channels,res); + } else res = cv::Mat(_height,_width,mat_type,_data).clone(); + return res; + } + +#endif + + //! Load image from a camera stream, using OpenCV. + /** + \param index Index of the camera to capture images from (from 0 to 63). + \param capture_width Width of the desired image ('0' stands for default value). + \param capture_height Height of the desired image ('0' stands for default value). + \param skip_frames Number of frames to skip before the capture. + \param release_camera Tells if the camera resource must be released at the end of the method. + **/ + CImg& load_camera(const unsigned int camera_index=0, + const unsigned int capture_width=0, const unsigned int capture_height=0, + const unsigned int skip_frames=0, const bool release_camera=true) { +#ifdef cimg_use_opencv + if (camera_index>=64) + throw CImgArgumentException(_cimg_instance + "load_camera(): Invalid request for camera #%u " + "(no more than 100 cameras can be managed simultaneously).", + cimg_instance, + camera_index); + static cv::VideoCapture *captures[64] = { 0 }; + static unsigned int captures_w[64], captures_h[64]; + if (release_camera) { + cimg::mutex(9); + if (captures[camera_index]) captures[camera_index]->release(); + delete captures[camera_index]; + captures[camera_index] = 0; + captures_w[camera_index] = captures_h[camera_index] = 0; + cimg::mutex(9,0); + return *this; + } + if (!captures[camera_index]) { + cimg::mutex(9); + captures[camera_index] = new cv::VideoCapture(camera_index); + captures_w[camera_index] = captures_h[camera_index] = 0; + if (!captures[camera_index]->isOpened()) { + delete captures[camera_index]; + captures[camera_index] = 0; + cimg::mutex(9,0); + throw CImgIOException(_cimg_instance + "load_camera(): Failed to initialize camera #%u.", + cimg_instance, + camera_index); + } + cimg::mutex(9,0); + } + cimg::mutex(9); + if (capture_width!=captures_w[camera_index]) { + captures[camera_index]->set(_cimg_cap_prop_frame_width,capture_width); + captures_w[camera_index] = capture_width; + } + if (capture_height!=captures_h[camera_index]) { + captures[camera_index]->set(_cimg_cap_prop_frame_height,capture_height); + captures_h[camera_index] = capture_height; + } + for (unsigned int i = 0; igrab(); + cv::Mat cvimg; + captures[camera_index]->read(cvimg); + if (cvimg.empty()) assign(); else _cvmat2cimg(cvimg).move_to(*this); + cimg::mutex(9,0); + return *this; +#else + cimg::unused(camera_index,skip_frames,release_camera,capture_width,capture_height); + throw CImgIOException(_cimg_instance + "load_camera(): This function requires features from the OpenCV library " + "('-Dcimg_use_opencv' must be defined).", + cimg_instance); +#endif + } + + //! Load image from a camera stream, using OpenCV \newinstance. + static CImg get_load_camera(const unsigned int camera_index=0, + const unsigned int capture_width=0, const unsigned int capture_height=0, + const unsigned int skip_frames=0, const bool release_camera=true) { + return CImg().load_camera(camera_index,capture_width,capture_height,skip_frames,release_camera); + } + + //! Load image using various non-native ways. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_other(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_other(): Specified filename is (null).", + cimg_instance); + + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_magick(filename); } + catch (CImgException&) { + try { load_imagemagick_external(filename); } + catch (CImgException&) { + try { load_graphicsmagick_external(filename); } + catch (CImgException&) { + try { load_cimg(filename); } + catch (CImgException&) { + try { + cimg::fclose(cimg::fopen(filename,"rb")); + } catch (CImgException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to open file '%s'.", + cimg_instance, + filename); + } + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image using various non-native ways \newinstance. + static CImg get_load_other(const char *const filename) { + return CImg().load_other(filename); + } + + //@} + //--------------------------- + // + //! \name Data Output + //@{ + //--------------------------- + + //! Display information about the image data. + /** + \param title Name for the considered image. + \param display_stats Tells to compute and display image statistics. + **/ + const CImg& print(const char *const title=0, const bool display_stats=true) const { + + int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0; + CImg st; + if (!is_empty() && display_stats) { + st = get_stats(); + xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7]; + xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11]; + } + + const ulongT siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1, + mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U, width1 = _width - 1; + + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImg<%s>",pixel_type()); + + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p", + cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal, + cimg::t_bold,cimg::t_normal,(void*)this, + cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum, + (unsigned long)(mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20))), + mdisp==0?"b":(mdisp==1?"Kio":"Mio"), + cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin()); + if (_data) + std::fprintf(cimg::output(),"..%p (%s) = [ ",(void*)((char*)end() - 1),_is_shared?"shared":"non-shared"); + else std::fprintf(cimg::output()," (%s) = [ ",_is_shared?"shared":"non-shared"); + + if (!is_empty()) cimg_foroff(*this,off) { + std::fprintf(cimg::output(),"%g",(double)_data[off]); + if (off!=siz1) std::fprintf(cimg::output(),"%s",off%_width==width1?" ; ":" "); + if (off==7 && siz>16) { off = siz1 - 8; std::fprintf(cimg::output(),"... "); } + } + if (!is_empty() && display_stats) + std::fprintf(cimg::output(), + " ], %smin%s = %g, %smax%s = %g, %smean%s = %g, %sstd%s = %g, %scoords_min%s = (%u,%u,%u,%u), " + "%scoords_max%s = (%u,%u,%u,%u).\n", + cimg::t_bold,cimg::t_normal,st[0], + cimg::t_bold,cimg::t_normal,st[1], + cimg::t_bold,cimg::t_normal,st[2], + cimg::t_bold,cimg::t_normal,std::sqrt(st[3]), + cimg::t_bold,cimg::t_normal,xm,ym,zm,vm, + cimg::t_bold,cimg::t_normal,xM,yM,zM,vM); + else std::fprintf(cimg::output(),"%s].\n",is_empty()?"":" "); + std::fflush(cimg::output()); + return *this; + } + + //! Display image into a CImgDisplay window. + /** + \param disp Display window. + **/ + const CImg& display(CImgDisplay& disp) const { + disp.display(*this); + return *this; + } + + //! Display image into a CImgDisplay window, in an interactive way. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + return _display(disp,0,display_info,XYZ,exit_on_anykey,false); + } + + //! Display image into an interactive window. + /** + \param title Window title + \param display_info Tells if image information are displayed on the standard output. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display(disp,title,display_info,XYZ,exit_on_anykey,false); + } + + const CImg& _display(CImgDisplay &disp, const char *const title, const bool display_info, + unsigned int *const XYZ, const bool exit_on_anykey, + const bool exit_on_singleclick) const { + unsigned int oldw = 0, oldh = 0, _XYZ[3] = { 0 }, key = 0; + int x0 = 0, y0 = 0, z0 = 0, x1 = width() - 1, y1 = height() - 1, z1 = depth() - 1, + old_mouse_x = -1, old_mouse_y = -1; + + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + else disp.set_title("%s",title); + } else if (title) disp.set_title("%s",title); + disp.show().flush(); + + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(dtitle); + + CImg zoom; + for (bool reset_view = true, resize_disp = false, is_first_select = true; !key && !disp.is_closed(); ) { + if (reset_view) { + if (XYZ) { _XYZ[0] = XYZ[0]; _XYZ[1] = XYZ[1]; _XYZ[2] = XYZ[2]; } + else { + _XYZ[0] = (unsigned int)(x0 + x1 + 1)/2; + _XYZ[1] = (unsigned int)(y0 + y1 + 1)/2; + _XYZ[2] = (unsigned int)(z0 + z1 + 1)/2; + } + x0 = 0; y0 = 0; z0 = 0; x1 = width() - 1; y1 = height() - 1; z1 = depth() - 1; + disp.resize(cimg_fitscreen(_width,_height,_depth),false); + oldw = disp._width; oldh = disp._height; + resize_disp = true; + reset_view = false; + } + if (!x0 && !y0 && !z0 && x1==width() - 1 && y1==height() - 1 && z1==depth() - 1) { + if (is_empty()) zoom.assign(1,1,1,1,(T)0); else zoom.assign(); + } else zoom = get_crop(x0,y0,z0,x1,y1,z1); + + const CImg& visu = zoom?zoom:*this; + const unsigned int + dx = 1U + x1 - x0, dy = 1U + y1 - y0, dz = 1U + z1 - z0, + tw = dx + (dz>1?dz:0U), th = dy + (dz>1?dz:0U); + if (!is_empty() && !disp.is_fullscreen() && resize_disp) { + const float + ttw = (float)tw*disp.width()/oldw, tth = (float)th*disp.height()/oldh, + dM = std::max(ttw,tth), diM = (float)std::max(disp.width(),disp.height()); + const unsigned int + imgw = (unsigned int)(ttw*diM/dM), imgh = (unsigned int)(tth*diM/dM); + disp.set_fullscreen(false).resize(cimg_fitscreen(imgw,imgh,1),false); + resize_disp = false; + } + oldw = tw; oldh = th; + + bool + go_up = false, go_down = false, go_left = false, go_right = false, + go_inc = false, go_dec = false, go_in = false, go_out = false, + go_in_center = false; + + disp.set_title("%s",dtitle._data); + if (_width>1 && visu._width==1) disp.set_title("%s | x=%u",disp._title,x0); + if (_height>1 && visu._height==1) disp.set_title("%s | y=%u",disp._title,y0); + if (_depth>1 && visu._depth==1) disp.set_title("%s | z=%u",disp._title,z0); + + disp._mouse_x = old_mouse_x; disp._mouse_y = old_mouse_y; + CImg selection = visu._select(disp,0,2,_XYZ,x0,y0,z0,true,is_first_select,_depth>1,true); + old_mouse_x = disp._mouse_x; old_mouse_y = disp._mouse_y; + is_first_select = false; + + if (disp.wheel()) { + if ((disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) && + (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT())) { + go_left = !(go_right = disp.wheel()>0); + } else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) { + go_down = !(go_up = disp.wheel()>0); + } else if (depth()==1 || disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + go_out = !(go_in = disp.wheel()>0); go_in_center = false; + } + disp.set_wheel(); + } + + const int + sx0 = selection(0), sy0 = selection(1), sz0 = selection(2), + sx1 = selection(3), sy1 = selection(4), sz1 = selection(5); + if (sx0>=0 && sy0>=0 && sz0>=0 && sx1>=0 && sy1>=0 && sz1>=0) { + x1 = x0 + sx1; y1 = y0 + sy1; z1 = z0 + sz1; + x0+=sx0; y0+=sy0; z0+=sz0; + if ((sx0==sx1 && sy0==sy1) || (_depth>1 && sx0==sx1 && sz0==sz1) || (_depth>1 && sy0==sy1 && sz0==sz1)) { + if (exit_on_singleclick && (!zoom || is_empty())) break; else reset_view = true; + } + resize_disp = true; + } else switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : key = 0; break; + case cimg::keyP : if (visu._depth>1 && (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT())) { + // Special mode: play stack of frames + const unsigned int + w1 = visu._width*disp.width()/(visu._width + (visu._depth>1?visu._depth:0)), + h1 = visu._height*disp.height()/(visu._height + (visu._depth>1?visu._depth:0)); + float frame_timing = 5; + bool is_stopped = false; + disp.set_key(key,false).set_wheel().resize(cimg_fitscreen(w1,h1,1),false); key = 0; + for (unsigned int timer = 0; !key && !disp.is_closed() && !disp.button(); ) { + if (disp.is_resized()) disp.resize(false); + if (!timer) { + visu.get_slice((int)_XYZ[2]).display(disp.set_title("%s | z=%d",dtitle.data(),_XYZ[2])); + (++_XYZ[2])%=visu._depth; + } + if (!is_stopped) { if (++timer>(unsigned int)frame_timing) timer = 0; } else timer = ~0U; + if (disp.wheel()) { frame_timing-=disp.wheel()/3.f; disp.set_wheel(); } + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : frame_timing-=0.3f; key = 0; break; + case cimg::keyPAGEDOWN : frame_timing+=0.3f; key = 0; break; + case cimg::keySPACE : is_stopped = !is_stopped; disp.set_key(key,false); key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyARROWUP : is_stopped = true; timer = 0; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyARROWDOWN : is_stopped = true; + (_XYZ[2]+=visu._depth - 2)%=visu._depth; timer = 0; key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false).set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(_width,_height,_depth),false).set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false). + toggle_fullscreen().set_key(key,false); key = 0; + } break; + } + frame_timing = frame_timing<1?1:(frame_timing>39?39:frame_timing); + disp.wait(20); + } + const unsigned int + w2 = (visu._width + (visu._depth>1?visu._depth:0))*disp.width()/visu._width, + h2 = (visu._height + (visu._depth>1?visu._depth:0))*disp.height()/visu._height; + disp.resize(cimg_fitscreen(w2,h2,1),false).set_title(dtitle.data()).set_key().set_button().set_wheel(); + key = 0; + } break; + case cimg::keyHOME : reset_view = resize_disp = true; key = 0; break; + case cimg::keyPADADD : go_in = true; go_in_center = true; key = 0; break; + case cimg::keyPADSUB : go_out = true; key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyPAD4: go_left = true; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6: go_right = true; key = 0; break; + case cimg::keyARROWUP : case cimg::keyPAD8: go_up = true; key = 0; break; + case cimg::keyARROWDOWN : case cimg::keyPAD2: go_down = true; key = 0; break; + case cimg::keyPAD7 : go_up = go_left = true; key = 0; break; + case cimg::keyPAD9 : go_up = go_right = true; key = 0; break; + case cimg::keyPAD1 : go_down = go_left = true; key = 0; break; + case cimg::keyPAD3 : go_down = go_right = true; key = 0; break; + case cimg::keyPAGEUP : go_inc = true; key = 0; break; + case cimg::keyPAGEDOWN : go_dec = true; key = 0; break; + } + if (go_in) { + const int + mx = go_in_center?disp.width()/2:disp.mouse_x(), + my = go_in_center?disp.height()/2:disp.mouse_y(), + mX = mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my*(height() + (depth()>1?depth():0))/disp.height(); + int X = (int)_XYZ[0], Y = (int)_XYZ[1], Z = (int)_XYZ[2]; + if (mX=height()) { + X = x0 + mX*(1 + x1 - x0)/width(); Z = z0 + (mY - height())*(1 + z1 - z0)/depth(); + } + if (mX>=width() && mY4) { x0 = X - 3*(X - x0)/4; x1 = X + 3*(x1 - X)/4; } + if (y1 - y0>4) { y0 = Y - 3*(Y - y0)/4; y1 = Y + 3*(y1 - Y)/4; } + if (z1 - z0>4) { z0 = Z - 3*(Z - z0)/4; z1 = Z + 3*(z1 - Z)/4; } + } + if (go_out) { + const int + delta_x = (x1 - x0)/8, delta_y = (y1 - y0)/8, delta_z = (z1 - z0)/8, + ndelta_x = delta_x?delta_x:(_width>1), + ndelta_y = delta_y?delta_y:(_height>1), + ndelta_z = delta_z?delta_z:(_depth>1); + x0-=ndelta_x; y0-=ndelta_y; z0-=ndelta_z; + x1+=ndelta_x; y1+=ndelta_y; z1+=ndelta_z; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=width()) x1 = width() - 1; } + if (y0<0) { y1-=y0; y0 = 0; if (y1>=height()) y1 = height() - 1; } + if (z0<0) { z1-=z0; z0 = 0; if (z1>=depth()) z1 = depth() - 1; } + if (x1>=width()) { x0-=(x1 - width() + 1); x1 = width() - 1; if (x0<0) x0 = 0; } + if (y1>=height()) { y0-=(y1 - height() + 1); y1 = height() - 1; if (y0<0) y0 = 0; } + if (z1>=depth()) { z0-=(z1 - depth() + 1); z1 = depth() - 1; if (z0<0) z0 = 0; } + const float + ratio = (float)(x1-x0)/(y1-y0), + ratiow = (float)disp._width/disp._height, + sub = std::min(cimg::abs(ratio - ratiow),cimg::abs(1/ratio-1/ratiow)); + if (sub>0.01) resize_disp = true; + } + if (go_left) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + } + if (go_right) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x1+ndelta1); + if (y0 - ndelta>=0) { y0-=ndelta; y1-=ndelta; } + else { y1-=y0; y0 = 0; } + } + if (go_down) { + const int delta = (y1 - y0)/4, ndelta = delta?delta:(_height>1); + if (y1+ndelta1); + if (z0 - ndelta>=0) { z0-=ndelta; z1-=ndelta; } + else { z1-=z0; z0 = 0; } + } + if (go_dec) { + const int delta = (z1 - z0)/4, ndelta = delta?delta:(_depth>1); + if (z1+ndelta + const CImg& display_object3d(CImgDisplay& disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return _display_object3d(disp,0,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3D in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + template + const CImg& _display_object3d(CImgDisplay& disp, const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering, + const int render_static, const int render_motion, + const bool is_double_sided, const float focale, + const float light_x, const float light_y, const float light_z, + const float specular_lightness, const float specular_shininess, + const bool display_axes, float *const pose_matrix, + const bool exit_on_anykey) const { + typedef typename cimg::superset::type tpfloat; + + // Check input arguments + if (is_empty()) { + CImg background; + if (colors && colors[0].size()==1) background.assign(1,2,1,1,64,128); + else background.assign(1,2,1,3,32,64,32,116,64,96); + if (disp) background.resize(disp.width(),disp.height(),1,-100,3); + else background.resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),1,-100,3); + return background._display_object3d(disp,title,vertices,primitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } else { if (disp) disp.resize(*this,false); } + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgArgumentException(_cimg_instance + "display_object3d(): Invalid specified 3D object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); + if (vertices._width && !primitives) { + CImgList nprimitives(vertices._width,1,1,1,1); + cimglist_for(nprimitives,l) nprimitives(l,0) = (tf)l; + return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3); + if (!title) disp.set_title("CImg<%s> (%u vertices, %u primitives)", + pixel_type(),vertices._width,primitives._width); + } else if (title) disp.set_title("%s",title); + + // Init 3D objects and compute object statistics + CImg + pose, + rotated_vertices(vertices._width,3), + bbox_vertices, rotated_bbox_vertices, + axes_vertices, rotated_axes_vertices, + bbox_opacities, axes_opacities; + CImgList bbox_primitives, axes_primitives; + CImgList reverse_primitives; + CImgList bbox_colors, bbox_colors2, axes_colors; + unsigned int ns_width = 0, ns_height = 0; + int _is_double_sided = (int)is_double_sided; + bool ndisplay_axes = display_axes; + const CImg + background_color(1,1,1,_spectrum,0), + foreground_color(1,1,1,_spectrum,(T)std::min((int)cimg::type::max(),255)); + float + Xoff = 0, Yoff = 0, Zoff = 0, sprite_scale = 1, + xm = 0, xM = vertices?vertices.get_shared_row(0).max_min(xm):0, + ym = 0, yM = vertices?vertices.get_shared_row(1).max_min(ym):0, + zm = 0, zM = vertices?vertices.get_shared_row(2).max_min(zm):0; + const float delta = cimg::max(xM - xm,yM - ym,zM - zm); + + rotated_bbox_vertices = bbox_vertices.assign(8,3,1,1, + xm,xM,xM,xm,xm,xM,xM,xm, + ym,ym,yM,yM,ym,ym,yM,yM, + zm,zm,zm,zm,zM,zM,zM,zM); + bbox_primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 1,2,6,5, 0,4,7,3, 0,1,5,4, 2,3,7,6); + bbox_colors.assign(6,_spectrum,1,1,1,background_color[0]); + bbox_colors2.assign(6,_spectrum,1,1,1,foreground_color[0]); + bbox_opacities.assign(bbox_colors._width,1,1,1,0.3f); + + rotated_axes_vertices = axes_vertices.assign(7,3,1,1, + 0,20,0,0,22,-6,-6, + 0,0,20,0,-6,22,-6, + 0,0,0,20,0,0,22); + axes_opacities.assign(3,1,1,1,1); + axes_colors.assign(3,_spectrum,1,1,1,foreground_color[0]); + axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3); + + // Begin user interaction loop + CImg visu0(*this,false), visu; + CImg zbuffer(visu0.width(),visu0.height(),1,1,0); + bool init_pose = true, clicked = false, redraw = true; + unsigned int key = 0, font_size = 32; + int + x0 = 0, y0 = 0, x1 = 0, y1 = 0, + nrender_static = render_static, + nrender_motion = render_motion; + disp.show().flush(); + + while (!disp.is_closed() && !key) { + + // Init object pose + if (init_pose) { + const float + ratio = delta>0?(2.f*std::min(disp.width(),disp.height())/(3.f*delta)):1, + dx = (xM + xm)/2, dy = (yM + ym)/2, dz = (zM + zm)/2; + if (centering) + CImg(4,3,1,1, ratio,0.,0.,-ratio*dx, 0.,ratio,0.,-ratio*dy, 0.,0.,ratio,-ratio*dz).move_to(pose); + else CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose); + if (pose_matrix) { + CImg pose0(pose_matrix,4,3,1,1,false); + pose0.resize(4,4,1,1,0); pose.resize(4,4,1,1,0); + pose0(3,3) = pose(3,3) = 1; + (pose0*pose).get_crop(0,0,3,2).move_to(pose); + Xoff = pose_matrix[12]; Yoff = pose_matrix[13]; Zoff = pose_matrix[14]; sprite_scale = pose_matrix[15]; + } else { Xoff = Yoff = Zoff = 0; sprite_scale = 1; } + init_pose = false; + redraw = true; + } + + // Rotate and draw 3D object + if (redraw) { + const float + r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0), + r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1), + r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2); + if ((clicked && nrender_motion>=0) || (!clicked && nrender_static>=0)) { + const tp *const pv0 = vertices.data(), *const pv1 = vertices.data(0,1), *const pv2 = vertices.data(0,2); + float + *const prv0 = rotated_vertices.data(), + *const prv1 = rotated_vertices.data(0,1), + *const prv2 = rotated_vertices.data(0,2); + cimg_pragma_openmp(parallel for cimg_openmp_if(vertices.width()>(cimg_openmp_sizefactor)*1024)) + cimg_forX(vertices,l) { + const float x = (float)pv0[l], y = (float)pv1[l], z = (float)pv2[l]; + prv0[l] = r00*x + r10*y + r20*z + r30; + prv1[l] = r01*x + r11*y + r21*z + r31; + prv2[l] = r02*x + r12*y + r22*z + r32; + } + } + else cimg_forX(bbox_vertices,l) { + const float x = bbox_vertices(l,0), y = bbox_vertices(l,1), z = bbox_vertices(l,2); + rotated_bbox_vertices(l,0) = r00*x + r10*y + r20*z + r30; + rotated_bbox_vertices(l,1) = r01*x + r11*y + r21*z + r31; + rotated_bbox_vertices(l,2) = r02*x + r12*y + r22*z + r32; + } + + // Draw objects + const bool render_with_zbuffer = !clicked && nrender_static>0; + visu = visu0; + if ((clicked && nrender_motion<0) || (!clicked && nrender_static<0)) + visu.draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors,bbox_opacities,2,false,focale). + draw_object3d(Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors2,1,false,focale); + else visu._draw_object3d((void*)0,render_with_zbuffer?zbuffer.fill(0):CImg::empty(), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static,_is_double_sided==1,focale, + width()/2.f + light_x,height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1,sprite_scale); + // Draw axes + if (ndisplay_axes) { + const float + n = 1e-8f + cimg::hypot(r00,r01,r02), + _r00 = r00/n, _r10 = r10/n, _r20 = r20/n, + _r01 = r01/n, _r11 = r11/n, _r21 = r21/n, + _r02 = r01/n, _r12 = r12/n, _r22 = r22/n, + Xaxes = 25, Yaxes = visu._height - 38.f; + cimg_forX(axes_vertices,l) { + const float + x = axes_vertices(l,0), + y = axes_vertices(l,1), + z = axes_vertices(l,2); + rotated_axes_vertices(l,0) = _r00*x + _r10*y + _r20*z; + rotated_axes_vertices(l,1) = _r01*x + _r11*y + _r21*z; + rotated_axes_vertices(l,2) = _r02*x + _r12*y + _r22*z; + } + axes_opacities(0,0) = (rotated_axes_vertices(1,2)>0)?0.5f:1.f; + axes_opacities(1,0) = (rotated_axes_vertices(2,2)>0)?0.5f:1.f; + axes_opacities(2,0) = (rotated_axes_vertices(3,2)>0)?0.5f:1.f; + visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_vertices,axes_primitives, + axes_colors,axes_opacities,1,false,focale). + draw_text((int)(Xaxes + rotated_axes_vertices(4,0)), + (int)(Yaxes + rotated_axes_vertices(4,1)), + "X",axes_colors[0]._data,0,axes_opacities(0,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(5,0)), + (int)(Yaxes + rotated_axes_vertices(5,1)), + "Y",axes_colors[1]._data,0,axes_opacities(1,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(6,0)), + (int)(Yaxes + rotated_axes_vertices(6,1)), + "Z",axes_colors[2]._data,0,axes_opacities(2,0),13); + } + visu.display(disp); + if (!clicked || nrender_motion==nrender_static) redraw = false; + } + + // Handle user interaction + if (!redraw) disp.wait(); + if ((disp.button() || disp.wheel()) && disp.mouse_x()>=0 && disp.mouse_y()>=0) { + redraw = true; + if (!clicked) { x0 = x1 = disp.mouse_x(); y0 = y1 = disp.mouse_y(); if (!disp.wheel()) clicked = true; } + else { x1 = disp.mouse_x(); y1 = disp.mouse_y(); } + const bool is_keyCTRL = disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT(); + if (disp.button()&1 && !is_keyCTRL) { + const float + R = 0.45f*std::min(disp.width(),disp.height()), + R2 = R*R, + u0 = (float)(x0 - disp.width()/2), + v0 = (float)(y0 - disp.height()/2), + u1 = (float)(x1 - disp.width()/2), + v1 = (float)(y1 - disp.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + (CImg::rotation_matrix(u,v,w,-alpha)*pose).move_to(pose); + x0 = x1; y0 = y1; + } + if (disp.button()&2 && !is_keyCTRL) { + if (focale>0) Zoff-=(y0 - y1)*focale/400; + else { const float s = std::exp((y0 - y1)/400.f); pose*=s; sprite_scale*=s; } + x0 = x1; y0 = y1; + } + if (disp.wheel()) { + if (focale>0) Zoff-=disp.wheel()*focale/20; + else { const float s = std::exp(disp.wheel()/20.f); pose*=s; sprite_scale*=s; } + disp.set_wheel(); + } + if (disp.button()&4 || (disp.button()&1 && is_keyCTRL)) { + Xoff+=(x1 - x0); Yoff+=(y1 - y0); x0 = x1; y0 = y1; + } + if ((disp.button()&1) && (disp.button()&2) && !is_keyCTRL) { + init_pose = true; disp.set_button(); x0 = x1; y0 = y1; + pose = CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0); + } + } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; } + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD: if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + if (!ns_width || !ns_height || + ns_width>(unsigned int)disp.screen_width() || ns_height>(unsigned int)disp.screen_height()) { + ns_width = disp.screen_width()*3U/4; + ns_height = disp.screen_height()*3U/4; + } + if (disp.is_fullscreen()) disp.resize(ns_width,ns_height,false); + else { + ns_width = disp._width; ns_height = disp._height; + disp.resize(disp.screen_width(),disp.screen_height(),false); + } + disp.toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyT : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Switch single/double-sided primitives. + if (--_is_double_sided==-2) _is_double_sided = 1; + if (_is_double_sided>=0) reverse_primitives.assign(); + else primitives.get_reverse_object3d().move_to(reverse_primitives); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyZ : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Enable/disable Z-buffer + if (zbuffer) zbuffer.assign(); + else zbuffer.assign(visu0.width(),visu0.height(),1,1,0); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyX : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Show/hide 3D axes + ndisplay_axes = !ndisplay_axes; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF1 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to points + nrender_motion = (nrender_static==0 && nrender_motion!=0)?0:-1; nrender_static = 0; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF2 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to lines + nrender_motion = (nrender_static==1 && nrender_motion!=1)?1:-1; nrender_static = 1; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF3 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat + nrender_motion = (nrender_static==2 && nrender_motion!=2)?2:-1; nrender_static = 2; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF4 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat-shaded + nrender_motion = (nrender_static==3 && nrender_motion!=3)?3:-1; nrender_static = 3; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF5 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Set rendering mode to gouraud-shaded. + nrender_motion = (nrender_static==4 && nrender_motion!=4)?4:-1; nrender_static = 4; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF6 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to phong-shaded + nrender_motion = (nrender_static==5 && nrender_motion!=5)?5:-1; nrender_static = 5; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save snapshot + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving snapshot... ",font_size,0).display(disp); + visu.save(filename); + (+visu).__draw_text(" Snapshot '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyG : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .off file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.off",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving object... ",font_size,0).display(disp); + vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .cimg file + static unsigned int snap_number = 0; + std::FILE *file; + do { + +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving object... ",font_size,0).display(disp); + vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities). + save(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + +#ifdef cimg_use_board + case cimg::keyP : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .EPS file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.eps",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving EPS snapshot... ",font_size,0).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1, + sprite_scale); + board.saveEPS(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .SVG file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.svg",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).__draw_text(" Saving SVG snapshot... ",font_size,0).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.f,Yoff + visu._height/2.f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.f + light_x,visu.height()/2.f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,1, + sprite_scale); + board.saveSVG(filename); + (+visu).__draw_text(" Object '%s' saved. ",font_size,0,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; +#endif + } + if (disp.is_resized()) { + disp.resize(false); visu0 = get_resize(disp,1); + if (zbuffer) zbuffer.assign(disp.width(),disp.height()); + redraw = true; + } + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + if (pose_matrix) { + std::memcpy(pose_matrix,pose._data,12*sizeof(float)); + pose_matrix[12] = Xoff; pose_matrix[13] = Yoff; pose_matrix[14] = Zoff; pose_matrix[15] = sprite_scale; + } + disp.set_button().set_key(key); + return *this; + } + + //! Display 1D graph in an interactive window. + /** + \param disp Display window. + \param plot_type Plot type. Can be { 0=points | 1=segments | 2=splines | 3=bars }. + \param vertex_type Vertex type. + \param labelx Title for the horizontal axis, as a C-string. + \param xmin Minimum value along the X-axis. + \param xmax Maximum value along the X-axis. + \param labely Title for the vertical axis, as a C-string. + \param ymin Minimum value along the X-axis. + \param ymax Maximum value along the X-axis. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImg& display_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + //! Display 1D graph in an interactive window \overloading. + const CImg& display_graph(const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + const CImg& _display_graph(CImgDisplay &disp, const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "display_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title(title?"%s":"CImg<%s>",title?title:pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth, siz1 = std::max((ulongT)1,siz - 1); + const unsigned int old_normalization = disp.normalization(); + disp.show().flush()._normalization = 0; + + double y0 = ymin, y1 = ymax, nxmin = xmin, nxmax = xmax; + if (nxmin==nxmax) { nxmin = 0; nxmax = siz1; } + int x0 = 0, x1 = width()*height()*depth() - 1, key = 0; + + for (bool reset_view = true; !key && !disp.is_closed(); ) { + if (reset_view) { x0 = 0; x1 = width()*height()*depth() - 1; y0 = ymin; y1 = ymax; reset_view = false; } + CImg zoom(x1 - x0 + 1,1,1,spectrum()); + cimg_forC(*this,c) zoom.get_shared_channel(c) = CImg(data(x0,0,0,c),x1 - x0 + 1,1,1,1,true); + if (y0==y1) { y0 = zoom.min_max(y1); const double dy = y1 - y0; y0-=dy/20; y1+=dy/20; } + if (y0==y1) { --y0; ++y1; } + + const CImg selection = zoom.get_select_graph(disp,plot_type,vertex_type, + labelx, + nxmin + x0*(nxmax - nxmin)/siz1, + nxmin + x1*(nxmax - nxmin)/siz1, + labely,y0,y1,true); + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + if (selection[0]>=0) { + if (selection[2]<0) reset_view = true; + else { + x1 = x0 + selection[2]; x0+=selection[0]; + if (selection[1]>=0 && selection[3]>=0) { + y0 = y1 - selection[3]*(y1 - y0)/(disp.height() - 32); + y1-=selection[1]*(y1 - y0)/(disp.height() - 32); + } + } + } else { + bool go_in = false, go_out = false, go_left = false, go_right = false, go_up = false, go_down = false; + switch (key = (int)disp.key()) { + case cimg::keyHOME : reset_view = true; key = 0; disp.set_key(); break; + case cimg::keyPADADD : go_in = true; go_out = false; key = 0; disp.set_key(); break; + case cimg::keyPADSUB : go_out = true; go_in = false; key = 0; disp.set_key(); break; + case cimg::keyARROWLEFT : case cimg::keyPAD4 : go_left = true; go_right = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6 : go_right = true; go_left = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWUP : case cimg::keyPAD8 : go_up = true; go_down = false; key = 0; disp.set_key(); break; + case cimg::keyARROWDOWN : case cimg::keyPAD2 : go_down = true; go_up = false; key = 0; disp.set_key(); break; + case cimg::keyPAD7 : go_left = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD9 : go_right = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD1 : go_left = true; go_down = true; key = 0; disp.set_key(); break; + case cimg::keyPAD3 : go_right = true; go_down = true; key = 0; disp.set_key(); break; + } + if (disp.wheel()) { + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_up = !(go_down = disp.wheel()<0); + else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) go_left = !(go_right = disp.wheel()>0); + else go_out = !(go_in = disp.wheel()>0); + key = 0; + } + + if (go_in) { + const int + xsiz = x1 - x0, + mx = (mouse_x - 16)*xsiz/(disp.width() - 32), + cx = x0 + cimg::cut(mx,0,xsiz); + if (x1 - x0>4) { + x0 = cx - 7*(cx - x0)/8; x1 = cx + 7*(x1 - cx)/8; + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + const double + ysiz = y1 - y0, + my = (mouse_y - 16)*ysiz/(disp.height() - 32), + cy = y1 - cimg::cut(my,0.,ysiz); + y0 = cy - 7*(cy - y0)/8; y1 = cy + 7*(y1 - cy)/8; + } else y0 = y1 = 0; + } + } + if (go_out) { + if (x0>0 || x1<(int)siz1) { + const int delta_x = (x1 - x0)/8, ndelta_x = delta_x?delta_x:(siz>1); + const double ndelta_y = (y1 - y0)/8; + x0-=ndelta_x; x1+=ndelta_x; + y0-=ndelta_y; y1+=ndelta_y; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=(int)siz) x1 = (int)siz1; } + if (x1>=(int)siz) { x0-=(x1 - siz1); x1 = (int)siz1; if (x0<0) x0 = 0; } + } + } + if (go_left) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + go_left = false; + } + if (go_right) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x1 + ndelta<(int)siz) { x0+=ndelta; x1+=ndelta; } + else { x0+=(siz1 - x1); x1 = (int)siz1; } + go_right = false; + } + if (go_up) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0+=ndelta; y1+=ndelta; + go_up = false; + } + if (go_down) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0-=ndelta; y1-=ndelta; + go_down = false; + } + } + if (!exit_on_anykey && key && key!=(int)cimg::keyESC && + (key!=(int)cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + key = 0; + } + } + disp._normalization = old_normalization; + return *this; + } + + //! Save image as a file. + /** + \param filename Filename, as a C-string. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + \note + - The used file format is defined by the file extension in the filename \p filename. + - Parameter \p number can be used to add a 6-digit number to the filename before saving. + + **/ + const CImg& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save(): Specified filename is (null).", + cimg_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:(number>=0)?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimg_save_plugin + cimg_save_plugin(fn); +#endif +#ifdef cimg_save_plugin1 + cimg_save_plugin1(fn); +#endif +#ifdef cimg_save_plugin2 + cimg_save_plugin2(fn); +#endif +#ifdef cimg_save_plugin3 + cimg_save_plugin3(fn); +#endif +#ifdef cimg_save_plugin4 + cimg_save_plugin4(fn); +#endif +#ifdef cimg_save_plugin5 + cimg_save_plugin5(fn); +#endif +#ifdef cimg_save_plugin6 + cimg_save_plugin6(fn); +#endif +#ifdef cimg_save_plugin7 + cimg_save_plugin7(fn); +#endif +#ifdef cimg_save_plugin8 + cimg_save_plugin8(fn); +#endif + // Text formats + if (!cimg::strcasecmp(ext,"asc")) return save_ascii(fn); + else if (!cimg::strcasecmp(ext,"csv") || + !cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) return save_dlm(fn); + else if (!cimg::strcasecmp(ext,"cpp") || + !cimg::strcasecmp(ext,"hpp") || + !cimg::strcasecmp(ext,"h") || + !cimg::strcasecmp(ext,"c")) return save_cpp(fn); + + // 2D binary formats + else if (!cimg::strcasecmp(ext,"bmp")) return save_bmp(fn); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) return save_jpeg(fn); + else if (!cimg::strcasecmp(ext,"rgb")) return save_rgb(fn); + else if (!cimg::strcasecmp(ext,"rgba")) return save_rgba(fn); + else if (!cimg::strcasecmp(ext,"png")) return save_png(fn); + else if (!cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pnm")) return save_pnm(fn); + else if (!cimg::strcasecmp(ext,"pnk")) return save_pnk(fn); + else if (!cimg::strcasecmp(ext,"pfm")) return save_pfm(fn); + else if (!cimg::strcasecmp(ext,"exr")) return save_exr(fn); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); + + // 3D binary formats + else if (!*ext) { +#ifdef cimg_use_zlib + return save_cimg(fn,true); +#else + return save_cimg(fn,false); +#endif + } else if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg")) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"dcm")) return save_medcon_external(fn); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) return save_analyze(fn); + else if (!cimg::strcasecmp(ext,"inr")) return save_inr(fn); + else if (!cimg::strcasecmp(ext,"mnc")) return save_minc2(fn); + else if (!cimg::strcasecmp(ext,"pan")) return save_pandore(fn); + else if (!cimg::strcasecmp(ext,"raw")) return save_raw(fn); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + + // Image sequences + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,444,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); + return save_other(fn); + } + + //! Save image as an ascii file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_ascii(const char *const filename) const { + return _save_ascii(0,filename); + } + + //! Save image as an Ascii file \overloading. + const CImg& save_ascii(std::FILE *const file) const { + return _save_ascii(file,0); + } + + const CImg& _save_ascii(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_ascii(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + std::fprintf(nfile,"%u %u %u %u\n",_width,_height,_depth,_spectrum); + const T* ptrs = _data; + cimg_forYZC(*this,y,z,c) { + cimg_forX(*this,x) std::fprintf(nfile,"%.17g ",(double)*(ptrs++)); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a .cpp source file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_cpp(const char *const filename) const { + return _save_cpp(0,filename); + } + + //! Save image as a .cpp source file \overloading. + const CImg& save_cpp(std::FILE *const file) const { + return _save_cpp(file,0); + } + + const CImg& _save_cpp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_cpp(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + CImg varname(1024); *varname = 0; + if (filename) cimg_sscanf(cimg::basename(filename),"%1023[a-zA-Z0-9_]",varname._data); + if (!*varname) cimg_snprintf(varname,varname._width,"unnamed"); + std::fprintf(nfile, + "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n" + "%s data_%s[] = { %s\n ", + varname._data,_width,_height,_depth,_spectrum,pixel_type(),pixel_type(),varname._data, + is_empty()?"};":""); + if (!is_empty()) for (ulongT off = 0, siz = size() - 1; off<=siz; ++off) { + std::fprintf(nfile,cimg::type::format(),cimg::type::format((*this)[off])); + if (off==siz) std::fprintf(nfile," };\n"); + else if (!((off + 1)%16)) std::fprintf(nfile,",\n "); + else std::fprintf(nfile,", "); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a DLM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_dlm(const char *const filename) const { + return _save_dlm(0,filename); + } + + //! Save image as a DLM file \overloading. + const CImg& save_dlm(std::FILE *const file) const { + return _save_dlm(file,0); + } + + const CImg& _save_dlm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_dlm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is volumetric, values along Z will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + const T* ptrs = _data; + cimg_forYZC(*this,y,z,c) { + cimg_forX(*this,x) std::fprintf(nfile,"%.17g%s",(double)*(ptrs++),(x==width() - 1)?"":","); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a BMP file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_bmp(const char *const filename) const { + return _save_bmp(0,filename); + } + + //! Save image as a BMP file \overloading. + const CImg& save_bmp(std::FILE *const file) const { + return _save_bmp(file,0); + } + + const CImg& _save_bmp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_bmp(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_bmp(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_bmp(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(54,1,1,1,0); + unsigned char align_buf[4] = { 0 }; + const unsigned int + align = (4 - (3*_width)%4)%4, + buf_size = (3*_width + align)*height(), + file_size = 54 + buf_size; + header[0] = 'B'; header[1] = 'M'; + header[0x02] = file_size&0xFF; + header[0x03] = (file_size>>8)&0xFF; + header[0x04] = (file_size>>16)&0xFF; + header[0x05] = (file_size>>24)&0xFF; + header[0x0A] = 0x36; + header[0x0E] = 0x28; + header[0x12] = _width&0xFF; + header[0x13] = (_width>>8)&0xFF; + header[0x14] = (_width>>16)&0xFF; + header[0x15] = (_width>>24)&0xFF; + header[0x16] = _height&0xFF; + header[0x17] = (_height>>8)&0xFF; + header[0x18] = (_height>>16)&0xFF; + header[0x19] = (_height>>24)&0xFF; + header[0x1A] = 1; + header[0x1B] = 0; + header[0x1C] = 24; + header[0x1D] = 0; + header[0x22] = buf_size&0xFF; + header[0x23] = (buf_size>>8)&0xFF; + header[0x24] = (buf_size>>16)&0xFF; + header[0x25] = (buf_size>>24)&0xFF; + header[0x27] = 0x1; + header[0x2B] = 0x1; + cimg::fwrite(header._data,54,nfile); + + const T + *ptr_r = data(0,_height - 1,0,0), + *ptr_g = (_spectrum>=2)?data(0,_height - 1,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,_height - 1,0,2):0; + + switch (_spectrum) { + case 1 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + const unsigned char val = (unsigned char)*(ptr_r++); + std::fputc(val,nfile); std::fputc(val,nfile); std::fputc(val,nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; + } + } break; + case 2 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc(0,nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; + } + } break; + default : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc((unsigned char)(*(ptr_b++)),nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; ptr_b-=2*_width; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a JPEG file. + /** + \param filename Filename, as a C-string. + \param quality Image quality (in %) + **/ + const CImg& save_jpeg(const char *const filename, const unsigned int quality=100) const { + return _save_jpeg(0,filename,quality); + } + + //! Save image as a JPEG file \overloading. + const CImg& save_jpeg(std::FILE *const file, const unsigned int quality=100) const { + return _save_jpeg(file,0,quality); + } + + const CImg& _save_jpeg(std::FILE *const file, const char *const filename, const unsigned int quality) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_jpeg(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + +#ifndef cimg_use_jpeg + if (!file) return save_other(filename,quality); + else throw CImgIOException(_cimg_instance + "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.", + cimg_instance); +#else + unsigned int dimbuf = 0; + J_COLOR_SPACE colortype = JCS_RGB; + + switch (_spectrum) { + case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE; break; + case 2 : dimbuf = 3; colortype = JCS_RGB; break; + case 3 : dimbuf = 3; colortype = JCS_RGB; break; + default : dimbuf = 4; colortype = JCS_CMYK; break; + } + + // Call libjpeg functions + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + jpeg_stdio_dest(&cinfo,nfile); + cinfo.image_width = _width; + cinfo.image_height = _height; + cinfo.input_components = dimbuf; + cinfo.in_color_space = colortype; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE); + jpeg_start_compress(&cinfo,TRUE); + + JSAMPROW row_pointer[1]; + CImg buffer(_width*dimbuf); + + while (cinfo.next_scanline& save_magick(const char *const filename, const unsigned int bytes_per_pixel=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_magick(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_magick + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_magick(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_magick(): Instance is multispectral, only the three first channels will be " + "saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_magick(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + Magick::Image image(Magick::Geometry(_width,_height),"black"); + image.type(Magick::TrueColorType); + image.depth(bytes_per_pixel?(8*bytes_per_pixel):(stmax>=256?16:8)); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = _spectrum>1?data(0,0,0,1):0, + *ptr_b = _spectrum>2?data(0,0,0,2):0; + Magick::PixelPacket *pixels = image.getPixels(0,0,_width,_height); + switch (_spectrum) { + case 1 : // Scalar images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = pixels->green = pixels->blue = (Magick::Quantum)*(ptr_r++); + ++pixels; + } + break; + case 2 : // RG images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = 0; ++pixels; + } + break; + default : // RGB images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = (Magick::Quantum)*(ptr_b++); + ++pixels; + } + } + image.syncPixels(); + image.write(filename); + return *this; +#else + cimg::unused(bytes_per_pixel); + throw CImgIOException(_cimg_instance + "save_magick(): Unable to save file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Save image as a PNG file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving, when possible. + **/ + const CImg& save_png(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_png(0,filename,bytes_per_pixel); + } + + //! Save image as a PNG file \overloading. + const CImg& save_png(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_png(file,0,bytes_per_pixel); + } + + const CImg& _save_png(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_png(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + +#ifndef cimg_use_png + cimg::unused(bytes_per_pixel); + if (!file) return save_other(filename); + else throw CImgIOException(_cimg_instance + "save_png(): Unable to save data in '(*FILE)' unless libpng is enabled.", + cimg_instance); +#else + +#if defined __GNUC__ + const char *volatile nfilename = filename; // Use 'volatile' to avoid (wrong) g++ warning + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"wb"); + volatile double stmin, stmax = (double)max_min(stmin); +#else + const char *nfilename = filename; + std::FILE *nfile = file?file:cimg::fopen(nfilename,"wb"); + double stmin, stmax = (double)max_min(stmin); +#endif + + if (_depth>1) + cimg::warn(_cimg_instance + "save_png(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>4) + cimg::warn(_cimg_instance + "save_png(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_png(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + // Setup PNG structures for write + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,user_error_ptr, user_error_fn, + user_warning_fn); + if (!png_ptr){ + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'png_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)0); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'info_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + + const int bit_depth = bytes_per_pixel?(bytes_per_pixel*8):(stmax>=256?16:8); + + int color_type; + switch (spectrum()) { + case 1 : color_type = PNG_COLOR_TYPE_GRAY; break; + case 2 : color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; + case 3 : color_type = PNG_COLOR_TYPE_RGB; break; + default : color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + const int interlace_type = PNG_INTERLACE_NONE; + const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT; + const int filter_method = PNG_FILTER_TYPE_DEFAULT; + png_set_IHDR(png_ptr,info_ptr,_width,_height,bit_depth,color_type,interlace_type,compression_type,filter_method); + png_write_info(png_ptr,info_ptr); + const int byte_depth = bit_depth>>3; + const int numChan = spectrum()>4?4:spectrum(); + const int pixel_bit_depth_flag = numChan * (bit_depth - 1); + + // Allocate Memory for Image Save and Fill pixel data + png_bytep *const imgData = new png_byte*[_height]; + for (unsigned int row = 0; row<_height; ++row) imgData[row] = new png_byte[byte_depth*numChan*_width]; + const T *pC0 = data(0,0,0,0); + switch (pixel_bit_depth_flag) { + case 7 : { // Gray 8-bit + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) *(ptrd++) = (unsigned char)*(pC0++); + } + } break; + case 14 : { // Gray w/ Alpha 8-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + } + } + } break; + case 21 : { // RGB 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + } + } + } break; + case 28 : { // RGB x/ Alpha 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y){ + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x){ + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + *(ptrd++) = (unsigned char)*(pC3++); + } + } + } break; + case 15 : { // Gray 16-bit + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) *(ptrd++) = (unsigned short)*(pC0++); + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],_width); + } + } break; + case 30 : { // Gray w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],2*_width); + } + } break; + case 45 : { // RGB 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],3*_width); + } + } break; + case 60 : { // RGB w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + *(ptrd++) = (unsigned short)*(pC3++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],4*_width); + } + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_write_image(png_ptr,imgData); + png_write_end(png_ptr,info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + // Deallocate Image Write Memory + cimg_forY(*this,n) delete[] imgData[n]; + delete[] imgData; + + if (!file) cimg::fclose(nfile); + return *this; +#endif + } + + //! Save image as a PNM file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving. + **/ + const CImg& save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(0,filename,bytes_per_pixel); + } + + //! Save image as a PNM file \overloading. + const CImg& save_pnm(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(file,0,bytes_per_pixel); + } + + const CImg& _save_pnm(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_pnm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pnm(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_pnm(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + stmin,stmax,filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const ulongT buf_size = std::min((ulongT)(1024*1024),(ulongT)(_width*_height*(_spectrum==1?1UL:3UL))); + + std::fprintf(nfile,"P%c\n%u %u\n%u\n", + (_spectrum==1?'5':'6'),_width,_height,stmax<256?255:(stmax<4096?4095:65535)); + + switch (_spectrum) { + case 1 : { // Scalar image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PGM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr_r++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Binary PGM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned short)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + } break; + case 2 : { // RG image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = 0; + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } break; + default : { // RGB image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = (unsigned char)*(ptr_b++); + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = (unsigned short)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PNK file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pnk(const char *const filename) const { + return _save_pnk(0,filename); + } + + //! Save image as a PNK file \overloading. + const CImg& save_pnk(std::FILE *const file) const { + return _save_pnk(file,0); + } + + const CImg& _save_pnk(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnk(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + const ulongT buf_size = std::min((ulongT)1024*1024,(ulongT)_width*_height*_depth); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T *ptr = data(0,0,0,0); + + if (!cimg::type::is_float() && sizeof(T)==1 && _depth<2) // Can be saved as regular PNM file + _save_pnm(file,filename,0); + else if (!cimg::type::is_float() && sizeof(T)==1) { // Save as extended P5 file: Binary byte-valued 3D + std::fprintf(nfile,"P5\n%u %u %u\n255\n",_width,_height,_depth); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else if (!cimg::type::is_float()) { // Save as P8: Binary int32-valued 3D + if (_depth>1) std::fprintf(nfile,"P8\n%u %u %u\n%d\n",_width,_height,_depth,(int)max()); + else std::fprintf(nfile,"P8\n%u %u\n%d\n",_width,_height,(int)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + int *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (int)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Save as P9: Binary float-valued 3D + if (_depth>1) std::fprintf(nfile,"P9\n%u %u %u\n%g\n",_width,_height,_depth,(double)max()); + else std::fprintf(nfile,"P9\n%u %u\n%g\n",_width,_height,(double)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PFM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pfm(const char *const filename) const { + get_mirror('y')._save_pfm(0,filename); + return *this; + } + + //! Save image as a PFM file \overloading. + const CImg& save_pfm(std::FILE *const file) const { + get_mirror('y')._save_pfm(file,0); + return *this; + } + + const CImg& _save_pfm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pfm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pfm(): image instance is multispectral, only the three first channels will be saved " + "in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const unsigned int buf_size = std::min(1024*1024U,_width*_height*(_spectrum==1?1:3)); + + std::fprintf(nfile,"P%c\n%u %u\n1.0\n", + (_spectrum==1?'f':'F'),_width,_height); + + switch (_spectrum) { + case 1 : { // Scalar image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,(ulongT)buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } break; + case 2 : { // RG image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } break; + default : { // RGB image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = (float)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a RGB file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_rgb(const char *const filename) const { + return _save_rgb(0,filename); + } + + //! Save image as a RGB file \overloading. + const CImg& save_rgb(std::FILE *const file) const { + return _save_rgb(file,0); + } + + const CImg& _save_rgb(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgb(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=3) + cimg::warn(_cimg_instance + "save_rgb(): image instance has not exactly 3 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0; + switch (_spectrum) { + case 1 : { // Scalar image + for (ulongT k = 0; k& save_rgba(const char *const filename) const { + return _save_rgba(0,filename); + } + + //! Save image as a RGBA file \overloading. + const CImg& save_rgba(std::FILE *const file) const { + return _save_rgba(file,0); + } + + const CImg& _save_rgba(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgba(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=4) + cimg::warn(_cimg_instance + "save_rgba(): image instance has not exactly 4 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[4*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0, + *ptr4 = _spectrum>3?data(0,0,0,3):0; + switch (_spectrum) { + case 1 : { // Scalar images + for (ulongT k = 0; k{ 0=None | 1=LZW | 2=JPEG }. + \param[out] voxel_size Voxel size, to be stored in the filename. + \param[out] description Description, to be stored in the filename. + \param use_bigtiff Allow to save big tiff files (>4Gb). + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tiff is not defined at compile time the + function uses CImg&save_other(const char*). + **/ + const CImg& save_tiff(const char *const filename, const unsigned int compression_type=0, + + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_tiff(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_tiff + const bool + _use_bigtiff = use_bigtiff && sizeof(ulongT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "save_tiff(): Failed to open file '%s' for writing.", + cimg_instance, + filename); + return *this; +#else + cimg::unused(compression_type,voxel_size,description,use_bigtiff); + return save_other(filename); +#endif + } + +#ifdef cimg_use_tiff + +#define _cimg_save_tiff(types,typed,compression_type) if (!std::strcmp(types,pixel_type())) { \ + const typed foo = (typed)0; return _save_tiff(tif,directory,z,foo,compression_type,voxel_size,description); } + + // [internal] Save a plane into a tiff file + template + const CImg& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, const t& pixel_t, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + if (is_empty() || !tif || pixel_t) return *this; + const char *const filename = TIFFFileName(tif); + uint32 rowsperstrip = (uint32)-1; + uint16 spp = _spectrum, bpp = sizeof(t)*8, photometric; + if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB; + else photometric = PHOTOMETRIC_MINISBLACK; + TIFFSetDirectory(tif,directory); + TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,_width); + TIFFSetField(tif,TIFFTAG_IMAGELENGTH,_height); + if (voxel_size) { + const float vx = voxel_size[0], vy = voxel_size[1], vz = voxel_size[2]; + TIFFSetField(tif,TIFFTAG_RESOLUTIONUNIT,RESUNIT_NONE); + TIFFSetField(tif,TIFFTAG_XRESOLUTION,1.f/vx); + TIFFSetField(tif,TIFFTAG_YRESOLUTION,1.f/vy); + CImg s_description(256); + cimg_snprintf(s_description,s_description._width,"VX=%g VY=%g VZ=%g spacing=%g",vx,vy,vz,vz); + TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,s_description.data()); + } + if (description) TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,description); + TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); + TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp); + if (cimg::type::is_float()) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,3); + else if (cimg::type::min()==0) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,1); + else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2); + double valm, valM = max_min(valm); + TIFFSetField(tif,TIFFTAG_SMINSAMPLEVALUE,valm); + TIFFSetField(tif,TIFFTAG_SMAXSAMPLEVALUE,valM); + TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp); + TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); + TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric); + TIFFSetField(tif,TIFFTAG_COMPRESSION,compression_type==2?COMPRESSION_JPEG: + compression_type==1?COMPRESSION_LZW:COMPRESSION_NONE); + rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip); + TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip); + TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB); + TIFFSetField(tif,TIFFTAG_SOFTWARE,"CImg"); + + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + for (unsigned int row = 0; row<_height; row+=rowsperstrip) { + uint32 nrow = (row + rowsperstrip>_height?_height - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif,row,0); + tsize_t i = 0; + for (unsigned int rr = 0; rr& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + _cimg_save_tiff("bool",unsigned char,compression_type); + _cimg_save_tiff("unsigned char",unsigned char,compression_type); + _cimg_save_tiff("char",char,compression_type); + _cimg_save_tiff("unsigned short",unsigned short,compression_type); + _cimg_save_tiff("short",short,compression_type); + _cimg_save_tiff("unsigned int",unsigned int,compression_type); + _cimg_save_tiff("int",int,compression_type); + _cimg_save_tiff("unsigned int64",unsigned int,compression_type); + _cimg_save_tiff("int64",int,compression_type); + _cimg_save_tiff("float",float,compression_type); + _cimg_save_tiff("double",float,compression_type); + const char *const filename = TIFFFileName(tif); + throw CImgInstanceException(_cimg_instance + "save_tiff(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + return *this; + } +#endif + + //! Save image as a MINC2 file. + /** + \param filename Filename, as a C-string. + \param imitate_file If non-zero, reference filename, as a C-string, to borrow header from. + **/ + const CImg& save_minc2(const char *const filename, + const char *const imitate_file=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_minc2(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_minc2 + cimg::unused(imitate_file); + return save_other(filename); +#else + minc::minc_1_writer wtr; + if (imitate_file) + wtr.open(filename, imitate_file); + else { + minc::minc_info di; + if (width()) di.push_back(minc::dim_info(width(),width()*0.5,-1,minc::dim_info::DIM_X)); + if (height()) di.push_back(minc::dim_info(height(),height()*0.5,-1,minc::dim_info::DIM_Y)); + if (depth()) di.push_back(minc::dim_info(depth(),depth()*0.5,-1,minc::dim_info::DIM_Z)); + if (spectrum()) di.push_back(minc::dim_info(spectrum(),spectrum()*0.5,-1,minc::dim_info::DIM_TIME)); + wtr.open(filename,di,1,NC_FLOAT,0); + } + if (pixel_type()==cimg::type::string()) + wtr.setup_write_byte(); + else if (pixel_type()==cimg::type::string()) + wtr.setup_write_int(); + else if (pixel_type()==cimg::type::string()) + wtr.setup_write_double(); + else + wtr.setup_write_float(); + minc::save_standard_volume(wtr, this->_data); + return *this; +#endif + } + + //! Save image as an ANALYZE7.5 or NIFTI file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 consecutive values that tell about the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_analyze(const char *const filename, const float *const voxel_size=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_analyze(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + std::FILE *file; + CImg hname(1024), iname(1024); + const char *const ext = cimg::split_filename(filename); + short datatype = -1; + if (!*ext) { + cimg_snprintf(hname,hname._width,"%s.hdr",filename); + cimg_snprintf(iname,iname._width,"%s.img",filename); + } + if (!cimg::strncasecmp(ext,"hdr",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(iname._data + std::strlen(iname) - 3,"img"); + } + if (!cimg::strncasecmp(ext,"img",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(hname._data + std::strlen(iname) - 3,"hdr"); + } + if (!cimg::strncasecmp(ext,"nii",3)) { + std::strncpy(hname,filename,hname._width - 1); *iname = 0; + } + + CImg header(*iname?348:352,1,1,1,0); + int *const iheader = (int*)header._data; + *iheader = 348; + std::strcpy(header._data + 4,"CImg"); + std::strcpy(header._data + 14," "); + ((short*)&(header[36]))[0] = 4096; + ((char*)&(header[38]))[0] = 114; + ((short*)&(header[40]))[0] = 4; + ((short*)&(header[40]))[1] = (short)_width; + ((short*)&(header[40]))[2] = (short)_height; + ((short*)&(header[40]))[3] = (short)_depth; + ((short*)&(header[40]))[4] = (short)_spectrum; + if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"unsigned int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16; + if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64; + if (datatype<0) + throw CImgIOException(_cimg_instance + "save_analyze(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename); + + ((short*)&(header[70]))[0] = datatype; + ((short*)&(header[72]))[0] = sizeof(T); + ((float*)&(header[108]))[0] = (float)(*iname?0:header.width()); + ((float*)&(header[112]))[0] = 1; + ((float*)&(header[76]))[0] = 0; + if (voxel_size) { + ((float*)&(header[76]))[1] = voxel_size[0]; + ((float*)&(header[76]))[2] = voxel_size[1]; + ((float*)&(header[76]))[3] = voxel_size[2]; + } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1; + file = cimg::fopen(hname,"wb"); + cimg::fwrite(header._data,header.width(),file); + if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); } + cimg::fwrite(_data,size(),file); + cimg::fclose(file); + return *this; + } + + //! Save image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param is_compressed Tells if the file contains compressed image data. + **/ + const CImg& save_cimg(const char *const filename, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(filename,is_compressed); + return *this; + } + + //! Save image as a .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(file,is_compressed); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Index of the image inside the file. + \param x0 X-coordinate of the sub-image location. + \param y0 Y-coordinate of the sub-image location. + \param z0 Z-coordinate of the sub-image location. + \param c0 C-coordinate of the sub-image location. + **/ + const CImg& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(filename,n0,x0,y0,z0,c0); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(file,n0,x0,y0,z0,c0); + return *this; + } + + //! Save blank image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param dx Width of the image. + \param dy Height of the image. + \param dz Depth of the image. + \param dc Number of channels of the image. + \note + - All pixel values of the saved image are set to \c 0. + - Use this method to save large images without having to instantiate and allocate them. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(filename,1,dx,dy,dz,dc); + } + + //! Save blank image as a .cimg file \overloading. + /** + Same as save_empty_cimg(const char *,unsigned int,unsigned int,unsigned int,unsigned int) + with a file stream argument instead of a filename string. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(file,1,dx,dy,dz,dc); + } + + //! Save image as an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 values specifying the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_inr(const char *const filename, const float *const voxel_size=0) const { + return _save_inr(0,filename,voxel_size); + } + + //! Save image as an INRIMAGE-4 file \overloading. + const CImg& save_inr(std::FILE *const file, const float *const voxel_size=0) const { + return _save_inr(file,0,voxel_size); + } + + const CImg& _save_inr(std::FILE *const file, const char *const filename, const float *const voxel_size) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_inr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + int inrpixsize = -1; + const char *inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) { + inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"char")) { + inrtype = "fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) { + inrtype = "unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"short")) { + inrtype = "fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) { + inrtype = "unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"int")) { + inrtype = "fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"float")) { + inrtype = "float\nPIXSIZE=32 bits"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"double")) { + inrtype = "float\nPIXSIZE=64 bits"; inrpixsize = 8; + } + if (inrpixsize<=0) + throw CImgIOException(_cimg_instance + "save_inr(): Unsupported pixel type '%s' for file '%s'", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(257); + int err = cimg_snprintf(header,header._width,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n", + _width,_height,_depth,_spectrum); + if (voxel_size) err+=cimg_sprintf(header._data + err,"VX=%g\nVY=%g\nVZ=%g\n", + voxel_size[0],voxel_size[1],voxel_size[2]); + err+=cimg_sprintf(header._data + err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm"); + std::memset(header._data + err,'\n',252 - err); + std::memcpy(header._data + 252,"##}\n",4); + cimg::fwrite(header._data,256,nfile); + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as an OpenEXR file. + /** + \param filename Filename, as a C-string. + \note The OpenEXR file format is described here. + **/ + const CImg& save_exr(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_exr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_exr(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + +#ifndef cimg_use_openexr + return save_other(filename); +#else + Imf::Rgba *const ptrd0 = new Imf::Rgba[(size_t)_width*_height], *ptrd = ptrd0, rgba; + switch (_spectrum) { + case 1 : { // Grayscale image + for (const T *ptr_r = data(), *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_rPandore file specifications + for more information). + **/ + const CImg& save_pandore(const char *const filename, const unsigned int colorspace=0) const { + return _save_pandore(0,filename,colorspace); + } + + //! Save image as a Pandore-5 file \overloading. + /** + Same as save_pandore(const char *,unsigned int) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_pandore(std::FILE *const file, const unsigned int colorspace=0) const { + return _save_pandore(file,0,colorspace); + } + + unsigned int _save_pandore_header_length(unsigned int id, unsigned int *dims, const unsigned int colorspace) const { + unsigned int nbdims = 0; + if (id==2 || id==3 || id==4) { + dims[0] = 1; dims[1] = _width; nbdims = 2; + } + if (id==5 || id==6 || id==7) { + dims[0] = 1; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==8 || id==9 || id==10) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + if (id==16 || id==17 || id==18) { + dims[0] = 3; dims[1] = _height; dims[2] = _width; dims[3] = colorspace; nbdims = 4; + } + if (id==19 || id==20 || id==21) { + dims[0] = 3; dims[1] = _depth; dims[2] = _height; dims[3] = _width; dims[4] = colorspace; nbdims = 5; + } + if (id==22 || id==23 || id==25) { + dims[0] = _spectrum; dims[1] = _width; nbdims = 2; + } + if (id==26 || id==27 || id==29) { + dims[0] = _spectrum; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==30 || id==31 || id==33) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + return nbdims; + } + + const CImg& _save_pandore(std::FILE *const file, const char *const filename, + const unsigned int colorspace) const { + +#define __cimg_save_pandore_case(dtype) \ + dtype *buffer = new dtype[size()]; \ + const T *ptrs = _data; \ + cimg_foroff(*this,off) *(buffer++) = (dtype)(*(ptrs++)); \ + buffer-=size(); \ + cimg::fwrite(buffer,size(),nfile); \ + delete[] buffer + +#define _cimg_save_pandore_case(sy,sz,sv,stype,id) \ + if (!saved && (sy?(sy==_height):true) && (sz?(sz==_depth):true) && \ + (sv?(sv==_spectrum):true) && !std::strcmp(stype,pixel_type())) { \ + unsigned int *iheader = (unsigned int*)(header + 12); \ + nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \ + cimg::fwrite(header,36,nfile); \ + if (sizeof(unsigned long)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned long)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned int)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned int)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned short)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned short)dims[d]; \ + cimg::fwrite(ndims._data,nbdims,nfile); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \ + __cimg_save_pandore_case(unsigned char); \ + } else if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \ + if (sizeof(unsigned long)==4) { __cimg_save_pandore_case(unsigned long); } \ + else if (sizeof(unsigned int)==4) { __cimg_save_pandore_case(unsigned int); } \ + else if (sizeof(unsigned short)==4) { __cimg_save_pandore_case(unsigned short); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \ + if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \ + else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pandore(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0, + 0,0,0,0,'C','I','m','g',0,0,0,0,0, + 'N','o',' ','d','a','t','e',0,0,0,0 }; + unsigned int nbdims, dims[5] = { 0 }; + bool saved = false; + _cimg_save_pandore_case(1,1,1,"unsigned char",2); + _cimg_save_pandore_case(1,1,1,"char",3); + _cimg_save_pandore_case(1,1,1,"unsigned short",3); + _cimg_save_pandore_case(1,1,1,"short",3); + _cimg_save_pandore_case(1,1,1,"unsigned int",3); + _cimg_save_pandore_case(1,1,1,"int",3); + _cimg_save_pandore_case(1,1,1,"unsigned int64",3); + _cimg_save_pandore_case(1,1,1,"int64",3); + _cimg_save_pandore_case(1,1,1,"float",4); + _cimg_save_pandore_case(1,1,1,"double",4); + + _cimg_save_pandore_case(0,1,1,"unsigned char",5); + _cimg_save_pandore_case(0,1,1,"char",6); + _cimg_save_pandore_case(0,1,1,"unsigned short",6); + _cimg_save_pandore_case(0,1,1,"short",6); + _cimg_save_pandore_case(0,1,1,"unsigned int",6); + _cimg_save_pandore_case(0,1,1,"int",6); + _cimg_save_pandore_case(0,1,1,"unsigned int64",6); + _cimg_save_pandore_case(0,1,1,"int64",6); + _cimg_save_pandore_case(0,1,1,"float",7); + _cimg_save_pandore_case(0,1,1,"double",7); + + _cimg_save_pandore_case(0,0,1,"unsigned char",8); + _cimg_save_pandore_case(0,0,1,"char",9); + _cimg_save_pandore_case(0,0,1,"unsigned short",9); + _cimg_save_pandore_case(0,0,1,"short",9); + _cimg_save_pandore_case(0,0,1,"unsigned int",9); + _cimg_save_pandore_case(0,0,1,"int",9); + _cimg_save_pandore_case(0,0,1,"unsigned int64",9); + _cimg_save_pandore_case(0,0,1,"int64",9); + _cimg_save_pandore_case(0,0,1,"float",10); + _cimg_save_pandore_case(0,0,1,"double",10); + + _cimg_save_pandore_case(0,1,3,"unsigned char",16); + _cimg_save_pandore_case(0,1,3,"char",17); + _cimg_save_pandore_case(0,1,3,"unsigned short",17); + _cimg_save_pandore_case(0,1,3,"short",17); + _cimg_save_pandore_case(0,1,3,"unsigned int",17); + _cimg_save_pandore_case(0,1,3,"int",17); + _cimg_save_pandore_case(0,1,3,"unsigned int64",17); + _cimg_save_pandore_case(0,1,3,"int64",17); + _cimg_save_pandore_case(0,1,3,"float",18); + _cimg_save_pandore_case(0,1,3,"double",18); + + _cimg_save_pandore_case(0,0,3,"unsigned char",19); + _cimg_save_pandore_case(0,0,3,"char",20); + _cimg_save_pandore_case(0,0,3,"unsigned short",20); + _cimg_save_pandore_case(0,0,3,"short",20); + _cimg_save_pandore_case(0,0,3,"unsigned int",20); + _cimg_save_pandore_case(0,0,3,"int",20); + _cimg_save_pandore_case(0,0,3,"unsigned int64",20); + _cimg_save_pandore_case(0,0,3,"int64",20); + _cimg_save_pandore_case(0,0,3,"float",21); + _cimg_save_pandore_case(0,0,3,"double",21); + + _cimg_save_pandore_case(1,1,0,"unsigned char",22); + _cimg_save_pandore_case(1,1,0,"char",23); + _cimg_save_pandore_case(1,1,0,"unsigned short",23); + _cimg_save_pandore_case(1,1,0,"short",23); + _cimg_save_pandore_case(1,1,0,"unsigned int",23); + _cimg_save_pandore_case(1,1,0,"int",23); + _cimg_save_pandore_case(1,1,0,"unsigned int64",23); + _cimg_save_pandore_case(1,1,0,"int64",23); + _cimg_save_pandore_case(1,1,0,"float",25); + _cimg_save_pandore_case(1,1,0,"double",25); + + _cimg_save_pandore_case(0,1,0,"unsigned char",26); + _cimg_save_pandore_case(0,1,0,"char",27); + _cimg_save_pandore_case(0,1,0,"unsigned short",27); + _cimg_save_pandore_case(0,1,0,"short",27); + _cimg_save_pandore_case(0,1,0,"unsigned int",27); + _cimg_save_pandore_case(0,1,0,"int",27); + _cimg_save_pandore_case(0,1,0,"unsigned int64",27); + _cimg_save_pandore_case(0,1,0,"int64",27); + _cimg_save_pandore_case(0,1,0,"float",29); + _cimg_save_pandore_case(0,1,0,"double",29); + + _cimg_save_pandore_case(0,0,0,"unsigned char",30); + _cimg_save_pandore_case(0,0,0,"char",31); + _cimg_save_pandore_case(0,0,0,"unsigned short",31); + _cimg_save_pandore_case(0,0,0,"short",31); + _cimg_save_pandore_case(0,0,0,"unsigned int",31); + _cimg_save_pandore_case(0,0,0,"int",31); + _cimg_save_pandore_case(0,0,0,"unsigned int64",31); + _cimg_save_pandore_case(0,0,0,"int64",31); + _cimg_save_pandore_case(0,0,0,"float",33); + _cimg_save_pandore_case(0,0,0,"double",33); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a raw data file. + /** + \param filename Filename, as a C-string. + \param is_multiplexed Tells if the image channels are stored in a multiplexed way (\c true) or not (\c false). + \note The .raw format does not store the image dimensions in the output file, + so you have to keep track of them somewhere to be able to read the file correctly afterwards. + **/ + const CImg& save_raw(const char *const filename, const bool is_multiplexed=false) const { + return _save_raw(0,filename,is_multiplexed); + } + + //! Save image as a raw data file \overloading. + /** + Same as save_raw(const char *,bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_raw(std::FILE *const file, const bool is_multiplexed=false) const { + return _save_raw(file,0,is_multiplexed); + } + + const CImg& _save_raw(std::FILE *const file, const char *const filename, const bool is_multiplexed) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_raw(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (pixel_type()==cimg::type::string()) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = _bool2uchar(siz,is_multiplexed); + cimg::fwrite(buf,siz,nfile); + delete[] buf; + } else { // Non boolean data + if (!is_multiplexed || _spectrum==1) cimg::fwrite(_data,size(),nfile); // Non-multiplexed + else { // Multiplexed + CImg buf(_spectrum); + cimg_forXYZ(*this,x,y,z) { + cimg_forC(*this,c) buf[c] = (*this)(x,y,z,c); + cimg::fwrite(buf._data,_spectrum,nfile); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + // Return unsigned char buffer that encodes data of a CImg instance bitwise. + // (buffer needs to be deallocated afterwards, with delete[]). + const unsigned char *_bool2uchar(ulongT &siz, const bool is_multiplexed) const { + const ulongT _siz = size(); + siz = _siz/8 + (_siz%8?1:0); + unsigned char *const buf = new unsigned char[siz], *ptrd = buf, val = 0, bit = 0; + + if (!is_multiplexed || _spectrum==1) // Non-multiplexed + cimg_for(*this,ptrs,T) { (val<<=1)|=(*ptrs?1:0); if (++bit==8) { *(ptrd++) = val; val = bit = 0; }} + else // Multiplexed + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) { + (val<<=1)|=((*this)(x,y,z,c)?1:0); if (++bit==8) { *(ptrd++) = val; val = bit = 0; } + } + if (bit) *ptrd = val; + return buf; + } + + // Fill CImg instance from bitwise data encoded in an unsigned char buffer. + void _uchar2bool(const unsigned char *buf, const ulongT siz, const bool is_multiplexed) { + const ulongT S = std::min(siz*8,size()); + const unsigned char *ptrs = buf; + unsigned char val = 0, mask = 0; + T *ptrd = _data; + if (S && (!is_multiplexed || _spectrum==1)) // Non-multiplexed + for (ulongT off = 0; off>=1)) { val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?1:0); + } + else if (S) { // Multiplexed + ulongT off = 0; + for (int z = 0; z>=1)) { val = *(ptrs++); ++off; mask = 128; } + (*this)(x,y,z,c) = (T)((val&mask)?1:0); + } + } + } + + //! Save image as a .yuv video file. + /** + \param filename Filename, as a C-string. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if pixel values of the instance image are RGB-coded (\c true) or YUV-coded (\c false). + \note Each slice of the instance image is considered to be a single frame of the output video file. + **/ + const CImg& save_yuv(const char *const filename, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + CImgList(*this,true).save_yuv(filename,chroma_subsampling,is_rgb); + return *this; + } + + //! Save image as a .yuv video file \overloading. + /** + Same as save_yuv(const char*,const unsigned int,const bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_yuv(std::FILE *const file, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + CImgList(*this,true).save_yuv(file,chroma_subsampling,is_rgb); + return *this; + } + + //! Save 3D object as an Object File Format (.off) file. + /** + \param filename Filename, as a C-string. + \param primitives List of 3D object primitives. + \param colors List of 3D object colors. + \note + - Instance image contains the vertices data of the 3D object. + - Textured, transparent or sphere-shaped primitives cannot be managed by the .off file format. + Such primitives will be lost or simplified during file saving. + - The .off file format is described here. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + const char *const filename) const { + return _save_off(primitives,colors,0,filename); + } + + //! Save 3D object as an Object File Format (.off) file \overloading. + /** + Same as save_off(const CImgList&,const CImgList&,const char*) const + with a file stream argument instead of a filename string. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file) const { + return _save_off(primitives,colors,file,0); + } + + template + const CImg& _save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_off(): Specified filename is (null).", + cimg_instance); + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "save_off(): Empty instance, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + CImgList opacities; + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgInstanceException(_cimg_instance + "save_off(): Invalid specified 3D object, for file '%s' (%s).", + cimg_instance, + filename?filename:"(FILE*)",error_message.data()); + + const CImg default_color(1,3,1,1,(tc)std::min((int)cimg::type::max(),200)); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + unsigned int supported_primitives = 0; + cimglist_for(primitives,l) if (primitives[l].size()!=5) ++supported_primitives; + std::fprintf(nfile,"OFF\n%u %u %u\n",_width,supported_primitives,3*primitives._width); + cimg_forX(*this,i) std::fprintf(nfile,"%f %f %f\n", + (float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2))); + cimglist_for(primitives,l) { + const CImg& color = l1?color[1]:r)/255.f, b = (csiz>2?color[2]:g)/255.f; + switch (psiz) { + case 1 : std::fprintf(nfile,"1 %u %f %f %f\n", + (unsigned int)primitives(l,0),r,g,b); break; + case 2 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 3 : std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),r,g,b); break; + case 4 : std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),r,g,b); break; + case 5 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 6 : { + const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 9 : { + const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 12 : { + const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5); + const float + rt = color.atXY(xt,yt,0)/255.f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.f; + std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save volumetric image as a video (using the OpenCV library when available). + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImg& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { + if (is_empty()) { CImgList().save_video(filename,fps,codec,keep_open); return *this; } + CImgList list; + get_split('z').move_to(list); + list.save_video(filename,fps,codec,keep_open); + return *this; + } + + //! Save volumetric image as a video, using custom external binary. + /** + \param filename Filename, as a C-string. + \param fps Video framerate. + \param codec Video codec, as a C-string. + \param bitrate Video bitrate. + \note + - Each slice of the instance image is considered to be a single frame of the output video file. + - This method uses \c custom, an external executable binary provided by + custom. + It must be installed for the method to succeed. + **/ + const CImg& save_custom_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_custom_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImgList list; + get_split('z').move_to(list); + list.save_custom_external(filename,fps,codec,bitrate); + return *this; + } + + //! Save image using gzip external binary. + /** + \param filename Filename, as a C-string. + \note This method uses \c gzip, an external executable binary provided by + gzip. + It must be installed for the method to succeed. + **/ + const CImg& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_gzip_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::gzip_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimg_instance, + filename); + + else cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using GraphicsMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c gm, an external executable binary provided by + GraphicsMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + +#ifdef cimg_use_png +#define _cimg_sge_extension1 "png" +#define _cimg_sge_extension2 "png" +#else +#define _cimg_sge_extension1 "pgm" +#define _cimg_sge_extension2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(), + _spectrum==1?_cimg_sge_extension1:_cimg_sge_extension2); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"\"%s\" convert -quality %u \"%s\" \"%s\"", + cimg::graphicsmagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::graphicsmagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_graphicsmagick_external(): Failed to save file '%s' with external command 'gm'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using ImageMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c convert, an external executable binary provided by + ImageMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_imagemagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_imagemagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick only writes the first image slice.", + cimg_instance,filename); +#ifdef cimg_use_png +#define _cimg_sie_extension1 "png" +#define _cimg_sie_extension2 "png" +#else +#define _cimg_sie_extension1 "pgm" +#define _cimg_sie_extension2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",cimg::temporary_path(), + cimg_file_separator,cimg::filenamerand(),_spectrum==1?_cimg_sie_extension1:_cimg_sie_extension2); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"\"%s\" -quality %u \"%s\" \"%s\"", + cimg::imagemagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::imagemagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_imagemagick_external(): Failed to save file '%s' with " + "external command 'magick/convert'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image as a Dicom file. + /** + \param filename Filename, as a C-string. + \note This method uses \c medcon, an external executable binary provided by + (X)Medcon. + It must be installed for the method to succeed. + **/ + const CImg& save_medcon_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_medcon_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save_analyze(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -w -c dicom -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::medcon_path()); + std::remove(filename_tmp); + cimg::split_filename(filename_tmp,body); + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.img",body._data); + std::remove(filename_tmp); + + file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s",filename); + file = cimg::std_fopen(command,"rb"); + if (!file) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "save_medcon_external(): Failed to save file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + std::rename(command,filename); + return *this; + } + + // Save image for non natively supported formats. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note + - The filename extension tells about the desired file format. + - This method tries to save the instance image as a file, using external tools from + ImageMagick or + GraphicsMagick. + At least one of these tool must be installed for the method to succeed. + - It is recommended to use the generic method save(const char*, int) const instead, + as it can handle some file formats natively. + **/ + const CImg& save_other(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_other(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick or GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + + const unsigned int omode = cimg::exception_mode(); + bool is_saved = true; + cimg::exception_mode(0); + try { save_magick(filename); } + catch (CImgException&) { + try { save_imagemagick_external(filename,quality); } + catch (CImgException&) { + try { save_graphicsmagick_external(filename,quality); } + catch (CImgException&) { + is_saved = false; + } + } + } + cimg::exception_mode(omode); + if (!is_saved) + throw CImgIOException(_cimg_instance + "save_other(): Failed to save file '%s'. Format is not natively supported, " + "and no external commands succeeded.", + cimg_instance, + filename); + return *this; + } + + //! Serialize a CImg instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { + return CImgList(*this,true).get_serialize(is_compressed); + } + + // [internal] Return a 40x38 color logo of a 'danger' item. + static CImg _logo40x38() { + CImg res(40,38,1,3); + const unsigned char *ptrs = cimg::logo40x38; + T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2); + for (ulongT off = 0; off<(ulongT)res._width*res._height;) { + const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++); + for (unsigned int l = 0; l structure + # + # + # + #------------------------------------------ + */ + //! Represent a list of images CImg. + template + struct CImgList { + unsigned int _width, _allocated_width; + CImg *_data; + + //! Simple iterator type, to loop through each image of a list. + /** + \note + - The \c CImgList::iterator type is defined as a CImg*. + - You may use it like this: + \code + CImgList<> list; // Assuming this image list is not empty + for (CImgList<>::iterator it = list.begin(); it* iterator; + + //! Simple const iterator type, to loop through each image of a \c const list instance. + /** + \note + - The \c CImgList::const_iterator type is defined to be a const CImg*. + - Similar to CImgList::iterator, but for constant list instances. + **/ + typedef const CImg* const_iterator; + + //! Pixel value type. + /** + Refer to the pixels value type of the images in the list. + \note + - The \c CImgList::value_type type of a \c CImgList is defined to be a \c T. + It is then similar to CImg::value_type. + - \c CImgList::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimglist_plugin +#include cimglist_plugin +#endif +#ifdef cimglist_plugin1 +#include cimglist_plugin1 +#endif +#ifdef cimglist_plugin2 +#include cimglist_plugin2 +#endif +#ifdef cimglist_plugin3 +#include cimglist_plugin3 +#endif +#ifdef cimglist_plugin4 +#include cimglist_plugin4 +#endif +#ifdef cimglist_plugin5 +#include cimglist_plugin5 +#endif +#ifdef cimglist_plugin6 +#include cimglist_plugin6 +#endif +#ifdef cimglist_plugin7 +#include cimglist_plugin7 +#endif +#ifdef cimglist_plugin8 +#include cimglist_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + Destroy current list instance. + \note + - Any allocated buffer is deallocated. + - Destroying an empty list does nothing actually. + **/ + ~CImgList() { + delete[] _data; + } + + //! Default constructor. + /** + Construct a new empty list instance. + \note + - An empty list has no pixel data and its dimension width() is set to \c 0, as well as its + image buffer pointer data(). + - An empty list may be reassigned afterwards, with the family of the assign() methods. + In all cases, the type of pixels stays \c T. + **/ + CImgList(): + _width(0),_allocated_width(0),_data(0) {} + + //! Construct list containing empty images. + /** + \param n Number of empty images. + \note Useful when you know by advance the number of images you want to manage, as + it will allocate the right amount of memory for the list, without needs for reallocation + (that may occur when starting from an empty list and inserting several images in it). + **/ + explicit CImgList(const unsigned int n):_width(n) { + if (n) _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + else { _allocated_width = 0; _data = 0; } + } + + //! Construct list containing images of specified size. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \note Pixel values are not initialized and may probably contain garbage. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + } + + //! Construct list containing images of specified size, and initialize pixel values. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val Initialization value for images pixels. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + } + + //! Construct list containing images of specified size, and initialize pixel values from a sequence of integers. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val0 First value of the initializing integers sequence. + \param val1 Second value of the initializing integers sequence. + \warning You must specify at least width*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...): + _width(0),_allocated_width(0),_data(0) { +#define _CImgList_stdarg(t) { \ + assign(n,width,height,depth,spectrum); \ + const ulongT siz = (ulongT)width*height*depth*spectrum, nsiz = siz*n; \ + T *ptrd = _data->_data; \ + va_list ap; \ + va_start(ap,val1); \ + for (ulongT l = 0, s = 0, i = 0; iwidth*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const double val0, const double val1, ...): + _width(0),_allocated_width(0),_data(0) { + _CImgList_stdarg(double); + } + + //! Construct list containing copies of an input image. + /** + \param n Number of images. + \param img Input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of \c img. + **/ + template + CImgList(const unsigned int n, const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + } + + //! Construct list from one image. + /** + \param img Input image to copy in the constructed list. + \param is_shared Tells if the element of the list is a shared or non-shared copy of \c img. + **/ + template + explicit CImgList(const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(1); + _data[0].assign(img,is_shared); + } + + //! Construct list from two images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + } + + //! Construct list from three images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + } + + //! Construct list from four images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + } + + //! Construct list from five images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + } + + //! Construct list from six images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + } + + //! Construct list from seven images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + } + + //! Construct list from eight images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param img8 Eighth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + } + + //! Construct list copy. + /** + \param list Input list to copy. + \note The shared state of each element of the constructed list is kept the same as in \c list. + **/ + template + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + } + + //! Construct list copy \specialization. + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],list[l]._is_shared); + } + + //! Construct list copy, and force the shared state of the list elements. + /** + \param list Input list to copy. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImgList& list, const bool is_shared):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],is_shared); + } + + //! Construct list by reading the content of a file. + /** + \param filename Filename, as a C-string. + **/ + explicit CImgList(const char *const filename):_width(0),_allocated_width(0),_data(0) { + assign(filename); + } + + //! Construct list from the content of a display window. + /** + \param disp Display window to get content from. + \note Constructed list contains a single image only. + **/ + explicit CImgList(const CImgDisplay& disp):_width(0),_allocated_width(0),_data(0) { + assign(disp); + } + + //! Return a list with elements being shared copies of images in the list instance. + /** + \note list2 = list1.get_shared() is equivalent to list2.assign(list1,true). + **/ + CImgList get_shared() { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Return a list with elements being shared copies of images in the list instance \const. + const CImgList get_shared() const { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Destructor \inplace. + /** + \see CImgList(). + **/ + CImgList& assign() { + delete[] _data; + _width = _allocated_width = 0; + _data = 0; + return *this; + } + + //! Destructor \inplace. + /** + Equivalent to assign(). + \note Only here for compatibility with STL naming conventions. + **/ + CImgList& clear() { + return assign(); + } + + //! Construct list containing empty images \inplace. + /** + \see CImgList(unsigned int). + **/ + CImgList& assign(const unsigned int n) { + if (!n) return assign(); + if (_allocated_width(n<<2)) { + delete[] _data; + _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + } + _width = n; + return *this; + } + + //! Construct list containing images of specified size \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + return *this; + } + + //! Construct list containing images of specified size, and initialize pixel values \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const T). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of integers \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const int, const int, ...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...) { + _CImgList_stdarg(int); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of doubles \inplace. + /** + \see CImgList(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,const double,const double,...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, + const double val0, const double val1, ...) { + _CImgList_stdarg(double); + return *this; + } + + //! Construct list containing copies of an input image \inplace. + /** + \see CImgList(unsigned int, const CImg&, bool). + **/ + template + CImgList& assign(const unsigned int n, const CImg& img, const bool is_shared=false) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + return *this; + } + + //! Construct list from one image \inplace. + /** + \see CImgList(const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img, const bool is_shared=false) { + assign(1); + _data[0].assign(img,is_shared); + return *this; + } + + //! Construct list from two images \inplace. + /** + \see CImgList(const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const bool is_shared=false) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + return *this; + } + + //! Construct list from three images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + return *this; + } + + //! Construct list from four images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + return *this; + } + + //! Construct list from five images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + return *this; + } + + //! Construct list from six images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + return *this; + } + + //! Construct list from seven images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, + const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + return *this; + } + + //! Construct list from eight images \inplace. + /** + \see CImgList(const CImg&,const CImg&,const CImg&,const CImg&,const CImg&,const CImg&, + const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + return *this; + } + + //! Construct list as a copy of an existing list and force the shared state of the list elements \inplace. + /** + \see CImgList(const CImgList&, bool is_shared). + **/ + template + CImgList& assign(const CImgList& list, const bool is_shared=false) { + cimg::unused(is_shared); + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + return *this; + } + + //! Construct list as a copy of an existing list and force shared state of elements \inplace \specialization. + CImgList& assign(const CImgList& list, const bool is_shared=false) { + if (this==&list) return *this; + CImgList res(list._width); + cimglist_for(res,l) res[l].assign(list[l],is_shared); + return res.move_to(*this); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& assign(const char *const filename) { + return load(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& assign(const CImgDisplay &disp) { + return assign(CImg(disp)); + } + + //! Transfer the content of the list instance to another list. + /** + \param list Destination list. + \note When returning, the current list instance is empty and the initial content of \c list is destroyed. + **/ + template + CImgList& move_to(CImgList& list) { + list.assign(_width); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[l]); + assign(); + return list; + } + + //! Transfer the content of the list instance at a specified position in another list. + /** + \param list Destination list. + \param pos Index of the insertion in the list. + \note When returning, the list instance is empty and the initial content of \c list is preserved + (only images indexes may be modified). + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos) { + if (is_empty()) return list; + const unsigned int npos = pos>list._width?list._width:pos; + list.insert(_width,npos); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[npos + l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[npos + l]); + assign(); + return list; + } + + //! Swap all fields between two list instances. + /** + \param list List to swap fields with. + \note Can be used to exchange the content of two lists in a fast way. + **/ + CImgList& swap(CImgList& list) { + cimg::swap(_width,list._width,_allocated_width,list._allocated_width); + cimg::swap(_data,list._data); + return list; + } + + //! Return a reference to an empty list. + /** + \note Can be used to define default values in a function taking a CImgList as an argument. + \code + void f(const CImgList& list=CImgList::empty()); + \endcode + **/ + static CImgList& empty() { + static CImgList _empty; + return _empty.assign(); + } + + //! Return a reference to an empty list \const. + static const CImgList& const_empty() { + static const CImgList _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Return a reference to one image element of the list. + /** + \param pos Index of the image element. + **/ + CImg& operator()(const unsigned int pos) { +#if cimg_verbosity>=3 + if (pos>=_width) { + cimg::warn(_cimglist_instance + "operator(): Invalid image request, at position [%u].", + cimglist_instance, + pos); + return *_data; + } +#endif + return _data[pos]; + } + + //! Return a reference to one image of the list. + /** + \param pos Index of the image element. + **/ + const CImg& operator()(const unsigned int pos) const { + return const_cast*>(this)->operator()(pos); + } + + //! Return a reference to one pixel value of one image of the list. + /** + \param pos Index of the image element. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list(n,x,y,z,c) is equivalent to list[n](x,y,z,c). + **/ + T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + return (*this)[pos](x,y,z,c); + } + + //! Return a reference to one pixel value of one image of the list \const. + const T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return (*this)[pos](x,y,z,c); + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + operator CImg*() { + return _data; + } + + //! Return pointer to the first image of the list \const. + operator const CImg*() const { + return _data; + } + + //! Construct list from one image \inplace. + /** + \param img Input image to copy in the constructed list. + \note list = img; is equivalent to list.assign(img);. + **/ + template + CImgList& operator=(const CImg& img) { + return assign(img); + } + + //! Construct list from another list. + /** + \param list Input list to copy. + \note list1 = list2 is equivalent to list1.assign(list2);. + **/ + template + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list from another list \specialization. + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& operator=(const char *const filename) { + return assign(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return a non-shared copy of a list. + /** + \note +list is equivalent to CImgList(list,false). + It forces the copy to have non-shared elements. + **/ + CImgList operator+() const { + return CImgList(*this,false); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end. + /** + \param img Image inserted at the end of the instance copy. + \note Define a convenient way to create temporary lists of images, as in the following code: + \code + (img1,img2,img3,img4).display("My four images"); + \endcode + **/ + template + CImgList& operator,(const CImg& img) { + return insert(img); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end \const. + template + CImgList operator,(const CImg& img) const { + return (+*this).insert(img); + } + + //! Return a copy of the list instance, where all elements of input list \c list have been inserted at the end. + /** + \param list List inserted at the end of the instance copy. + **/ + template + CImgList& operator,(const CImgList& list) { + return insert(list); + } + + //! Return a copy of the list instance, where all elements of input \c list have been inserted at the end \const. + template + CImgList& operator,(const CImgList& list) const { + return (+*this).insert(list); + } + + //! Return image corresponding to the appending of all images of the instance list along specified axis. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \note list>'x' is equivalent to list.get_append('x'). + **/ + CImg operator>(const char axis) const { + return get_append(axis,0); + } + + //! Return list corresponding to the splitting of all images of the instance list along specified axis. + /** + \param axis Axis used for image splitting. + \note list<'x' is equivalent to list.get_split('x'). + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to size() but returns result as a (signed) integer. + **/ + int width() const { + return (int)_width; + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to width() but returns result as an unsigned integer. + **/ + unsigned int size() const { + return _width; + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + CImg *data() { + return _data; + } + + //! Return pointer to the first image of the list \const. + const CImg *data() const { + return _data; + } + + //! Return pointer to the pos-th image of the list. + /** + \param pos Index of the image element to access. + \note list.data(n); is equivalent to list.data + n;. + **/ +#if cimg_verbosity>=3 + CImg *data(const unsigned int pos) { + if (pos>=size()) + cimg::warn(_cimglist_instance + "data(): Invalid pointer request, at position [%u].", + cimglist_instance, + pos); + return _data + pos; + } + + const CImg *data(const unsigned int l) const { + return const_cast*>(this)->data(l); + } +#else + CImg *data(const unsigned int l) { + return _data + l; + } + + //! Return pointer to the pos-th image of the list \const. + const CImg *data(const unsigned int l) const { + return _data + l; + } +#endif + + //! Return iterator to the first image of the list. + /** + **/ + iterator begin() { + return _data; + } + + //! Return iterator to the first image of the list \const. + const_iterator begin() const { + return _data; + } + + //! Return iterator to one position after the last image of the list. + /** + **/ + iterator end() { + return _data + _width; + } + + //! Return iterator to one position after the last image of the list \const. + const_iterator end() const { + return _data + _width; + } + + //! Return reference to the first image of the list. + /** + **/ + CImg& front() { + return *_data; + } + + //! Return reference to the first image of the list \const. + const CImg& front() const { + return *_data; + } + + //! Return a reference to the last image of the list. + /** + **/ + const CImg& back() const { + return *(_data + _width - 1); + } + + //! Return a reference to the last image of the list \const. + CImg& back() { + return *(_data + _width - 1); + } + + //! Return pos-th image of the list. + /** + \param pos Index of the image element to access. + **/ + CImg& at(const int pos) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "at(): Empty instance.", + cimglist_instance); + + return _data[cimg::cut(pos,0,width() - 1)]; + } + + //! Access to pixel value with Dirichlet boundary conditions. + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions. + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + T& _atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + T _atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + T& _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + T _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 coordinates (\c pos, \c x,\c y). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + T& _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + T _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 coordinates (\c pos,\c x). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 coordinates (\c pos,\c x) \const. + T atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 coordinates (\c pos, \c x) \const. + T atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + T& _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + T _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the coordinate (\c pos). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=width())?(cimg::temporary(out_value)=out_value):(*this)(pos,x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the coordinate (\c pos) \const. + T atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=width())?out_value:(*this)(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos). + /** + \param pos Index of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the coordinate (\c pos) \const. + T atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + T& _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + T _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Return \c true if list is empty. + /** + **/ + bool is_empty() const { + return (!_data || !_width); + } + + //! Test if number of image elements is equal to specified value. + /** + \param size_n Number of image elements to test. + **/ + bool is_sameN(const unsigned int size_n) const { + return _width==size_n; + } + + //! Test if number of image elements is equal between two images lists. + /** + \param list Input list to compare with. + **/ + template + bool is_sameN(const CImgList& list) const { + return is_sameN(list._width); + } + + // Define useful functions to check list dimensions. + // (cannot be documented because macro-generated). +#define _cimglist_def_is_same1(axis) \ + bool is_same##axis(const unsigned int val) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(val); \ + return res; \ + } \ + bool is_sameN##axis(const unsigned int n, const unsigned int val) const { \ + return is_sameN(n) && is_same##axis(val); \ + } \ + +#define _cimglist_def_is_same2(axis1,axis2) \ + bool is_same##axis1##axis2(const unsigned int val1, const unsigned int val2) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2(val1,val2); \ + return res; \ + } \ + bool is_sameN##axis1##axis2(const unsigned int n, const unsigned int val1, const unsigned int val2) const { \ + return is_sameN(n) && is_same##axis1##axis2(val1,val2); \ + } \ + +#define _cimglist_def_is_same3(axis1,axis2,axis3) \ + bool is_same##axis1##axis2##axis3(const unsigned int val1, const unsigned int val2, \ + const unsigned int val3) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2##axis3(val1,val2,val3); \ + return res; \ + } \ + bool is_sameN##axis1##axis2##axis3(const unsigned int n, const unsigned int val1, \ + const unsigned int val2, const unsigned int val3) const { \ + return is_sameN(n) && is_same##axis1##axis2##axis3(val1,val2,val3); \ + } \ + +#define _cimglist_def_is_same(axis) \ + template bool is_same##axis(const CImg& img) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(img); \ + return res; \ + } \ + template bool is_same##axis(const CImgList& list) const { \ + const unsigned int lmin = std::min(_width,list._width); \ + bool res = true; \ + for (unsigned int l = 0; l bool is_sameN##axis(const unsigned int n, const CImg& img) const { \ + return (is_sameN(n) && is_same##axis(img)); \ + } \ + template bool is_sameN##axis(const CImgList& list) const { \ + return (is_sameN(list) && is_same##axis(list)); \ + } + + _cimglist_def_is_same(XY) + _cimglist_def_is_same(XZ) + _cimglist_def_is_same(XC) + _cimglist_def_is_same(YZ) + _cimglist_def_is_same(YC) + _cimglist_def_is_same(XYZ) + _cimglist_def_is_same(XYC) + _cimglist_def_is_same(YZC) + _cimglist_def_is_same(XYZC) + _cimglist_def_is_same1(X) + _cimglist_def_is_same1(Y) + _cimglist_def_is_same1(Z) + _cimglist_def_is_same1(C) + _cimglist_def_is_same2(X,Y) + _cimglist_def_is_same2(X,Z) + _cimglist_def_is_same2(X,C) + _cimglist_def_is_same2(Y,Z) + _cimglist_def_is_same2(Y,C) + _cimglist_def_is_same2(Z,C) + _cimglist_def_is_same3(X,Y,Z) + _cimglist_def_is_same3(X,Y,C) + _cimglist_def_is_same3(X,Z,C) + _cimglist_def_is_same3(Y,Z,C) + + //! Test if dimensions of each image of the list match specified arguments. + /** + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameXYZC(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + bool res = true; + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_sameXYZC(dx,dy,dz,dc); + return res; + } + + //! Test if list dimensions match specified arguments. + /** + \param n Number of images in the list. + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameNXYZC(const unsigned int n, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + return is_sameN(n) && is_sameXYZC(dx,dy,dz,dc); + } + + //! Test if list contains one particular pixel location. + /** + \param n Index of the image whom checked pixel value belong to. + \param x X-coordinate of the checked pixel value. + \param y Y-coordinate of the checked pixel value. + \param z Z-coordinate of the checked pixel value. + \param c C-coordinate of the checked pixel value. + **/ + bool containsNXYZC(const int n, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) return false; + return n>=0 && n=0 && x<_data[n].width() && y>=0 && y<_data[n].height() && + z>=0 && z<_data[n].depth() && c>=0 && c<_data[n].spectrum(); + } + + //! Test if list contains image with specified index. + /** + \param n Index of the checked image. + **/ + bool containsN(const int n) const { + if (is_empty()) return false; + return n>=0 && n + bool contains(const T& pixel, t& n, t& x, t&y, t& z, t& c) const { + if (is_empty()) return false; + cimglist_for(*this,l) if (_data[l].contains(pixel,x,y,z,c)) { n = (t)l; return true; } + return false; + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \param[out] z Z-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y,z). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y, t& z) const { + t c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y) const { + t z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x). + **/ + template + bool contains(const T& pixel, t& n, t& x) const { + t y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \note If true, set coordinates (n). + **/ + template + bool contains(const T& pixel, t& n) const { + t x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + **/ + bool contains(const T& pixel) const { + unsigned int n, x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if the list contains the image 'img'. + /** + \param img Reference to image to test. + \param[out] n Index of image in the list, if test succeeds. + \note If true, returns the position (n) of the image in the list. + **/ + template + bool contains(const CImg& img, t& n) const { + if (is_empty()) return false; + const CImg *const ptr = &img; + cimglist_for(*this,i) if (_data + i==ptr) { n = (t)i; return true; } + return false; + } + + //! Test if the list contains the image img. + /** + \param img Reference to image to test. + **/ + bool contains(const CImg& img) const { + unsigned int n; + return contains(img,n); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + //! Return a reference to the minimum pixel value of the instance list. + /** + **/ + T& min() { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the maximum pixel value of the instance list \const. + const T& max() const { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T max_value = *ptr_max; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + T& min_max(t& max_val) { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min_max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well \const. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + const T& min_max(t& max_val) const { + bool is_all_empty = true; + T *ptr_min = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_min = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "min_max(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the minimum value as well. + /** + \param[out] min_val Value of the minimum value found. + **/ + template + T& max_min(t& min_val) { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max_min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + bool is_all_empty = true; + T *ptr_max = 0; + cimglist_for(*this,l) if (!_data[l].is_empty()) { + ptr_max = _data[l]._data; + is_all_empty = false; + break; + } + if (is_all_empty) + throw CImgInstanceException(_cimglist_instance + "max_min(): %s.", + _data?"List of empty images":"Empty instance", + cimglist_instance); + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + if (is_shared) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified shared image " + "CImg<%s>(%u,%u,%u,%u,%p) at position %u (pixel types are different).", + cimglist_instance, + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data,npos); + + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list + _data = new_data; + *_data = img; + } else { + if (new_data) { // Insert with re-allocation + if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos); + if (npos!=_width - 1) + std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + std::memset((void*)_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else if (npos!=_width - 1) // Insert without re-allocation + std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \specialization. + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list + _data = new_data; + if (is_shared && img) { + _data->_width = img._width; + _data->_height = img._height; + _data->_depth = img._depth; + _data->_spectrum = img._spectrum; + _data->_is_shared = true; + _data->_data = img._data; + } else *_data = img; + } + else { + if (new_data) { // Insert with re-allocation + if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos); + if (npos!=_width - 1) + std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + new_data[npos]._width = img._width; + new_data[npos]._height = img._height; + new_data[npos]._depth = img._depth; + new_data[npos]._spectrum = img._spectrum; + new_data[npos]._is_shared = true; + new_data[npos]._data = img._data; + } else { + new_data[npos]._width = new_data[npos]._height = new_data[npos]._depth = new_data[npos]._spectrum = 0; + new_data[npos]._data = 0; + new_data[npos] = img; + } + std::memset((void*)_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else { // Insert without re-allocation + if (npos!=_width - 1) + std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + _data[npos]._width = img._width; + _data[npos]._height = img._height; + _data[npos]._depth = img._depth; + _data[npos]._spectrum = img._spectrum; + _data[npos]._is_shared = true; + _data[npos]._data = img._data; + } else { + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + } + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \newinstance. + template + CImgList get_insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(img,pos,is_shared); + } + + //! Insert n empty images img into the current image list, at position \p pos. + /** + \param n Number of empty images to insert. + \param pos Index of the insertion. + **/ + CImgList& insert(const unsigned int n, const unsigned int pos=~0U) { + CImg empty; + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i get_insert(const unsigned int n, const unsigned int pos=~0U) const { + return (+*this).insert(n,pos); + } + + //! Insert \c n copies of the image \c img into the current image list, at position \c pos. + /** + \param n Number of image copies to insert. + \param img Image to insert by copy. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of \c img or not. + **/ + template + CImgList& insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + insert(img,npos,is_shared); + for (unsigned int i = 1; i + CImgList get_insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,img,pos,is_shared); + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos. + /** + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if ((void*)this!=(void*)&list) cimglist_for(list,l) insert(list[l],npos + l,is_shared); + else insert(CImgList(list),npos,is_shared); + return *this; + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos \newinstance. + template + CImgList get_insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(list,pos,is_shared); + } + + //! Insert n copies of the list \c list at position \c pos of the current list. + /** + \param n Number of list copies to insert. + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i + CImgList get_insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,list,pos,is_shared); + } + + //! Remove all images between from indexes. + /** + \param pos1 Starting index of the removal. + \param pos2 Ending index of the removal. + **/ + CImgList& remove(const unsigned int pos1, const unsigned int pos2) { + const unsigned int + npos1 = pos1=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + else { + if (tpos2>=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + + for (unsigned int k = npos1; k<=npos2; ++k) _data[k].assign(); + const unsigned int nb = 1 + npos2 - npos1; + if (!(_width-=nb)) return assign(); + if (_width>(_allocated_width>>4) || _allocated_width<=16) { // Removing items without reallocation + if (npos1!=_width) + std::memmove((void*)(_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg)*(_width - npos1)); + std::memset((void*)(_data + _width),0,sizeof(CImg)*nb); + } else { // Removing items with reallocation + _allocated_width>>=4; + while (_allocated_width>16 && _width<(_allocated_width>>1)) _allocated_width>>=1; + CImg *const new_data = new CImg[_allocated_width]; + if (npos1) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg)*npos1); + if (npos1!=_width) + std::memcpy((void*)(new_data + npos1),(void*)(_data + npos2 + 1),sizeof(CImg)*(_width - npos1)); + if (_width!=_allocated_width) + std::memset((void*)(new_data + _width),0,sizeof(CImg)*(_allocated_width - _width)); + std::memset((void*)_data,0,sizeof(CImg)*(_width + nb)); + delete[] _data; + _data = new_data; + } + } + return *this; + } + + //! Remove all images between from indexes \newinstance. + CImgList get_remove(const unsigned int pos1, const unsigned int pos2) const { + return (+*this).remove(pos1,pos2); + } + + //! Remove image at index \c pos from the image list. + /** + \param pos Index of the image to remove. + **/ + CImgList& remove(const unsigned int pos) { + return remove(pos,pos); + } + + //! Remove image at index \c pos from the image list \newinstance. + CImgList get_remove(const unsigned int pos) const { + return (+*this).remove(pos); + } + + //! Remove last image. + /** + **/ + CImgList& remove() { + return remove(_width - 1); + } + + //! Remove last image \newinstance. + CImgList get_remove() const { + return (+*this).remove(); + } + + //! Reverse list order. + CImgList& reverse() { + for (unsigned int l = 0; l<_width/2; ++l) (*this)[l].swap((*this)[_width - 1 - l]); + return *this; + } + + //! Reverse list order \newinstance. + CImgList get_reverse() const { + return (+*this).reverse(); + } + + //! Return a sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList& images(const unsigned int pos0, const unsigned int pos1) { + return get_images(pos0,pos1).move_to(*this); + } + + //! Return a sublist \newinstance. + CImgList get_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l]); + return res; + } + + //! Return a shared sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a shared sublist \newinstance. + const CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a single image which is the appending of all images of the current CImgList instance. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg get_append(const char axis, const float align=0) const { + if (is_empty()) return CImg(); + if (_width==1) return +((*this)[0]); + unsigned int dx = 0, dy = 0, dz = 0, dc = 0, pos = 0; + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { // Along the X-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx+=img._width; + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._height==1 && img._depth==1 && img._spectrum==1 && + res._height==1 && res._depth==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._width); + else + res.draw_image(pos, + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._width; + } + } break; + case 'y' : { // Along the Y-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy+=img._height; + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._depth==1 && img._spectrum==1 && + res._width==1 && res._depth==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._height); + else + res.draw_image((int)(align*(dx - img._width)), + pos, + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._height; + } + } break; + case 'z' : { // Along the Z-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz+=img._depth; + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._height==1 && img._spectrum==1 && + res._width==1 && res._height==1 && res._spectrum==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._depth); + else + res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + pos, + (int)(align*(dc - img._spectrum)), + img); + } + pos+=img._depth; + } + } break; + default : { // Along the C-axis + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc+=img._spectrum; + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + if (img._width==1 && img._height==1 && img._depth==1 && + res._width==1 && res._height==1 && res._depth==1) + std::memcpy(&res[pos],img._data,sizeof(T)*img._spectrum); + else + res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + pos, + img); + } + pos+=img._spectrum; + } + } + } + return res; + } + + //! Return a list where each image has been split along the specified axis. + /** + \param axis Axis to split images along. + \param nb Number of split parts for each image. + **/ + CImgList& split(const char axis, const int nb=-1) { + return get_split(axis,nb).move_to(*this); + } + + //! Return a list where each image has been split along the specified axis \newinstance. + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + cimglist_for(*this,l) _data[l].get_split(axis,nb).move_to(res,~0U); + return res; + } + + //! Insert image at the end of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_back(const CImg& img) { + return insert(img); + } + + //! Insert image at the front of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_front(const CImg& img) { + return insert(img,0); + } + + //! Insert list at the end of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_back(const CImgList& list) { + return insert(list); + } + + //! Insert list at the front of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_front(const CImgList& list) { + return insert(list,0); + } + + //! Remove last image. + /** + **/ + CImgList& pop_back() { + return remove(_width - 1); + } + + //! Remove first image. + /** + **/ + CImgList& pop_front() { + return remove(0); + } + + //! Remove image pointed by iterator. + /** + \param iter Iterator pointing to the image to remove. + **/ + CImgList& erase(const iterator iter) { + return remove(iter - _data); + } + + //@} + //---------------------------------- + // + //! \name Data Input + //@{ + //---------------------------------- + + //! Display a simple interactive interface to select images or sublists. + /** + \param disp Window instance to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \param exit_on_anykey Exit function when any key is pressed. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(CImgDisplay &disp, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + return _select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + //! Display a simple interactive interface to select images or sublists. + /** + \param title Title of a new window used to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \param exit_on_anykey Exit function when any key is pressed. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(const char *const title, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + CImg _select(CImgDisplay &disp, const char *const title, const bool feature_type, + const char axis, const float align, const bool exit_on_anykey, + const unsigned int orig, const bool resize_disp, + const bool exit_on_rightbutton, const bool exit_on_wheel) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "select(): Empty instance.", + cimglist_instance); + + // Create image correspondence table and get list dimensions for visualization. + CImgList _indices; + unsigned int max_width = 0, max_height = 0, sum_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + if (h>max_height) max_height = h; + sum_width+=w; sum_height+=h; + if (axis=='x') CImg(w,1,1,1,(unsigned int)l).move_to(_indices); + else CImg(h,1,1,1,(unsigned int)l).move_to(_indices); + } + const CImg indices0 = _indices>'x'; + + // Create display window. + if (!disp) { + if (axis=='x') disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1); + else disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1); + if (!title) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else { + if (title) disp.set_title("%s",title); + disp.move_inside_screen(); + } + if (resize_disp) { + if (axis=='x') disp.resize(cimg_fitscreen(sum_width,max_height,1),false); + else disp.resize(cimg_fitscreen(max_width,sum_height,1),false); + } + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).show_mouse(); + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + + // Enter event loop. + CImg visu0, visu; + CImg indices; + CImg positions(_width,4,1,1,-1); + int oindex0 = -1, oindex1 = -1, index0 = -1, index1 = -1; + bool is_clicked = false, is_selected = false, text_down = false, update_display = true; + unsigned int key = 0, font_size = 32; + + while (!is_selected && !disp.is_closed() && !key) { + + // Create background image. + if (!visu0) { + visu0.assign(disp._width,disp._height,1,3,0); visu.assign(); + (indices0.get_resize(axis=='x'?visu0._width:visu0._height,1)).move_to(indices); + unsigned int _ind = 0; + const CImg onexone(1,1,1,1,(T)0); + if (axis=='x') + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4)) + cimglist_for(*this,ind) { + unsigned int x0 = 0; + while (x0 &src = _data[ind]?_data[ind]:onexone; + CImg res; + src._get_select(disp,old_normalization,src._width/2,src._height/2,src._depth/2). + move_to(res); + const unsigned int h = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,true); + res.resize(x1 - x0,std::max(32U,h*disp._height/max_height),1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)x0; + positions(ind,1) = positions(ind,3) = (int)(align*(visu0.height() - res.height())); + positions(ind,2)+=res._width; + positions(ind,3)+=res._height - 1; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if_size(_width,4)) + cimglist_for(*this,ind) { + unsigned int y0 = 0; + while (y0 &src = _data[ind]?_data[ind]:onexone; + CImg res; + src._get_select(disp,old_normalization,(src._width - 1)/2,(src._height - 1)/2,(src._depth - 1)/2). + move_to(res); + const unsigned int w = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,false); + res.resize(std::max(32U,w*disp._width/max_width),y1 - y0,1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)(align*(visu0.width() - res.width())); + positions(ind,1) = positions(ind,3) = (int)y0; + positions(ind,2)+=res._width - 1; + positions(ind,3)+=res._height; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + if (axis=='x') --positions(_ind,2); else --positions(_ind,3); + update_display = true; + } + + if (!visu || oindex0!=index0 || oindex1!=index1) { + if (index0>=0 && index1>=0) { + visu.assign(visu0,false); + const int indm = std::min(index0,index1), indM = std::max(index0,index1); + for (int ind = indm; ind<=indM; ++ind) if (positions(ind,0)>=0) { + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + background_color,0.2f); + if ((axis=='x' && positions(ind,2) - positions(ind,0)>=8) || + (axis!='x' && positions(ind,3) - positions(ind,1)>=8)) + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + foreground_color,0.9f,0xAAAAAAAA); + } + if (is_clicked) visu.__draw_text(" Images #%u - #%u, Size = %u ",font_size,(int)text_down, + orig + indm,orig + indM,indM - indm + 1); + else visu.__draw_text(" Image #%u (%u,%u,%u,%u) ",font_size,(int)text_down, + orig + index0, + _data[index0]._width, + _data[index0]._height, + _data[index0]._depth, + _data[index0]._spectrum); + update_display = true; + } else visu.assign(); + } + if (!visu) { visu.assign(visu0,true); update_display = true; } + if (update_display) { visu.display(disp); update_display = false; } + disp.wait(); + + // Manage user events. + const int xm = disp.mouse_x(), ym = disp.mouse_y(); + int index = -1; + + if (xm>=0) { + index = (int)indices(axis=='x'?xm:ym); + if (disp.button()&1) { + if (!is_clicked) { is_clicked = true; oindex0 = index0; index0 = index; } + oindex1 = index1; index1 = index; + if (!feature_type) is_selected = true; + } else { + if (!is_clicked) { oindex0 = oindex1 = index0; index0 = index1 = index; } + else is_selected = true; + } + } else { + if (is_clicked) { + if (!(disp.button()&1)) { is_clicked = is_selected = false; index0 = index1 = -1; } + else index1 = -1; + } else index0 = index1 = -1; + } + + if (disp.button()&4) { is_clicked = is_selected = false; index0 = index1 = -1; } + if (disp.button()&2 && exit_on_rightbutton) { is_selected = true; index1 = index0 = -1; } + if (disp.wheel() && exit_on_wheel) is_selected = true; + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(axis=='x'?sum_width:max_width,axis=='x'?max_height:sum_height,1),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).__draw_text(" Saving snapshot... ",font_size,(int)text_down).display(disp); + visu0.save(filename); + (+visu0).__draw_text(" Snapshot '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + } + disp.set_key(key,false).wait(); key = 0; + } break; + case cimg::keyO : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=cimg::std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).__draw_text(" Saving instance... ",font_size,(int)text_down).display(disp); + save(filename); + (+visu0).__draw_text(" Instance '%s' saved. ",font_size,(int)text_down,filename._data).display(disp); + disp.set_key(key,false).wait(); key = 0; + } break; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (ym>=0 && ym<13) { if (!text_down) { visu.assign(); text_down = true; }} + else if (ym>=visu.height() - 13) { if (text_down) { visu.assign(); text_down = false; }} + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + CImg res(1,2,1,1,-1); + if (is_selected) { + if (feature_type) res.fill(std::min(index0,index1),std::max(index0,index1)); + else res.fill(index0); + } + if (!(disp.button()&2)) disp.set_button(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + disp.set_key(key); + return res; + } + + //! Load a list from a file. + /** + \param filename Filename to read data from. + **/ + CImgList& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load(): Specified filename is (null).", + cimglist_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const bool is_stdin = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimglist_load_plugin + cimglist_load_plugin(filename); +#endif +#ifdef cimglist_load_plugin1 + cimglist_load_plugin1(filename); +#endif +#ifdef cimglist_load_plugin2 + cimglist_load_plugin2(filename); +#endif +#ifdef cimglist_load_plugin3 + cimglist_load_plugin3(filename); +#endif +#ifdef cimglist_load_plugin4 + cimglist_load_plugin4(filename); +#endif +#ifdef cimglist_load_plugin5 + cimglist_load_plugin5(filename); +#endif +#ifdef cimglist_load_plugin6 + cimglist_load_plugin6(filename); +#endif +#ifdef cimglist_load_plugin7 + cimglist_load_plugin7(filename); +#endif +#ifdef cimglist_load_plugin8 + cimglist_load_plugin8(filename); +#endif + if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) load_cimg(filename); + else if (!cimg::strcasecmp(ext,"rec") || + !cimg::strcasecmp(ext,"par")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded && !is_stdin) { + std::FILE *const file = cimg::std_fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to open file '%s'.", + cimglist_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + cimg::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file as a single image. + if (!is_loaded) { + assign(1); + try { + _data->load(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to recognize format of file '%s'.", + cimglist_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load a list from a file \newinstance. + static CImgList get_load(const char *const filename) { + return CImgList().load(filename); + } + + //! Load a list from a .cimg file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_cimg(const char *const filename) { + return _load_cimg(0,filename); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename) { + return CImgList().load_cimg(filename); + } + + //! Load a list from a .cimg file. + /** + \param file File to read data from. + **/ + CImgList& load_cimg(std::FILE *const file) { + return _load_cimg(file,0); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file) { + return CImgList().load_cimg(file); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename) { +#ifdef cimg_use_zlib +#define _cimgz_load_cimg_case(Tss) { \ + Bytef *const cbuf = new Bytef[csiz]; \ + cimg::fread(cbuf,(size_t)csiz,nfile); \ + if (is_bool) { \ + CImg raw(W*H*D*C/8); \ + uLongf destlen = (uLongf)raw.size(); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,(uLong)csiz); \ + img.assign(W,H,D,C); \ + img._uchar2bool(raw,raw.size(),false); \ + } else { \ + CImg raw(W,H,D,C); \ + uLongf destlen = (uLongf)(raw.size()*sizeof(Tss)); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,(uLong)csiz); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } \ + delete[] cbuf; \ +} +#else +#define _cimgz_load_cimg_case(Tss) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Unable to load compressed data from file '%s' unless zlib is enabled.", \ + cimglist_instance, \ + filename?filename:"(FILE*)"); +#endif + +#define _cimg_load_cimg_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + const bool is_bool = cimg::type::string()==cimg::type::string(); \ + for (unsigned int l = 0; l=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; csiz = 0; \ + if ((err = cimg_sscanf(tmp,"%u %u %u %u #" cimg_fuint64,&W,&H,&D,&C,&csiz))<4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'.", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:("(FILE*)")); \ + if (W*H*D*C>0) { \ + CImg &img = _data[l]; \ + if (err==5) _cimgz_load_cimg_case(Tss) \ + else { \ + img.assign(W,H,D,C); \ + T *ptrd = img._data; \ + if (is_bool) { \ + CImg raw; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + CImg(ptrd,std::min(8*raw._width,(unsigned int)(img.end() - ptrd)),1,1,1,true).\ + _uchar2bool(raw,raw._width,false); \ + to_read-=raw._width; \ + } \ + } else { \ + CImg raw; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + const Tss *ptrs = raw._data; \ + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + to_read-=raw._width; \ + } \ + } \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + + const ulongT cimg_iobuffer = (ulongT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + cimg_uint64 csiz; + int i, err; + do { + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; + } while (*tmp=='#' && i>=0); + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + assign(N); + _cimg_load_cimg_case("bool",bool); + _cimg_load_cimg_case("unsigned_char",unsigned char); + _cimg_load_cimg_case("uchar",unsigned char); + _cimg_load_cimg_case("char",char); + _cimg_load_cimg_case("unsigned_short",unsigned short); + _cimg_load_cimg_case("ushort",unsigned short); + _cimg_load_cimg_case("short",short); + _cimg_load_cimg_case("unsigned_int",unsigned int); + _cimg_load_cimg_case("uint",unsigned int); + _cimg_load_cimg_case("int",int); + _cimg_load_cimg_case("unsigned_long",ulongT); + _cimg_load_cimg_case("ulong",ulongT); + _cimg_load_cimg_case("long",longT); + _cimg_load_cimg_case("unsigned_int64",uint64T); + _cimg_load_cimg_case("uint64",uint64T); + _cimg_load_cimg_case("int64",int64T); + _cimg_load_cimg_case("float",float); + _cimg_load_cimg_case("double",double); + + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a sublist list from a (non compressed) .cimg file. + /** + \param filename Filename to read data from. + \param n0 Starting index of images to read (~0U for max). + \param n1 Ending index of images to read (~0U for max). + \param x0 Starting X-coordinates of image regions to read. + \param y0 Starting Y-coordinates of image regions to read. + \param z0 Starting Z-coordinates of image regions to read. + \param c0 Starting C-coordinates of image regions to read. + \param x1 Ending X-coordinates of image regions to read (~0U for max). + \param y1 Ending Y-coordinates of image regions to read (~0U for max). + \param z1 Ending Z-coordinates of image regions to read (~0U for max). + \param c1 Ending C-coordinates of image regions to read (~0U for max). + **/ + CImgList& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(0,filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sublist list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \overloading. + CImgList& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(file,0,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { +#define _cimg_load_cimg_case2(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l<=nn1; ++l) { \ + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; \ + if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:"(FILE*)"); \ + if (W*H*D*C>0) { \ + if (l=W || ny0>=H || nz0>=D || nc0>=C) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const unsigned int \ + _nx1 = nx1==~0U?W - 1:nx1, \ + _ny1 = ny1==~0U?H - 1:ny1, \ + _nz1 = nz1==~0U?D - 1:nz1, \ + _nc1 = nc1==~0U?C - 1:nc1; \ + if (_nx1>=W || _ny1>=H || _nz1>=D || _nc1>=C) \ + throw CImgArgumentException(_cimglist_instance \ + "load_cimg(): Invalid specified coordinates " \ + "[%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " \ + "because image [%u] in file '%s' has size (%u,%u,%u,%u).", \ + cimglist_instance, \ + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,l,filename?filename:"(FILE*)",W,H,D,C); \ + CImg raw(1 + _nx1 - nx0); \ + CImg &img = _data[l - nn0]; \ + img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \ + T *ptrd = img._data; \ + ulongT skipvb = nc0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \ + const ulongT skipzb = nz0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \ + const ulongT skipyb = ny0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \ + const ulongT skipxb = nx0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \ + const Tss *ptrs = raw._data; \ + for (unsigned int off = raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + const ulongT skipxe = (W - 1 - _nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const ulongT skipye = (H - 1 - _ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const ulongT skipze = (D - 1 - _nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const ulongT skipve = (C - 1 - _nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + unsigned int + nn0 = std::min(n0,n1), nn1 = std::max(n0,n1), + nx0 = std::min(x0,x1), nx1 = std::max(x0,x1), + ny0 = std::min(y0,y1), ny1 = std::max(y0,y1), + nz0 = std::min(z0,z1), nz1 = std::max(z0,z1), + nc0 = std::min(c0,c1), nc1 = std::max(c0,c1); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + nn1 = n1==~0U?N - 1:n1; + if (nn1>=N) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " + "because file '%s' contains only %u images.", + cimglist_instance, + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,filename?filename:"(FILE*)",N); + assign(1 + nn1 - n0); + _cimg_load_cimg_case2("bool",bool); + _cimg_load_cimg_case2("unsigned_char",unsigned char); + _cimg_load_cimg_case2("uchar",unsigned char); + _cimg_load_cimg_case2("char",char); + _cimg_load_cimg_case2("unsigned_short",unsigned short); + _cimg_load_cimg_case2("ushort",unsigned short); + _cimg_load_cimg_case2("short",short); + _cimg_load_cimg_case2("unsigned_int",unsigned int); + _cimg_load_cimg_case2("uint",unsigned int); + _cimg_load_cimg_case2("int",int); + _cimg_load_cimg_case2("unsigned_long",ulongT); + _cimg_load_cimg_case2("ulong",ulongT); + _cimg_load_cimg_case2("long",longT); + _cimg_load_cimg_case2("unsigned_int64",uint64T); + _cimg_load_cimg_case2("uint64",uint64T); + _cimg_load_cimg_case2("int64",int64T); + _cimg_load_cimg_case2("float",float); + _cimg_load_cimg_case2("double",double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_parrec(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_parrec(): Specified filename is (null).", + cimglist_instance); + + CImg body(1024), filenamepar(1024), filenamerec(1024); + *body = *filenamepar = *filenamerec = 0; + const char *const ext = cimg::split_filename(filename,body); + if (!std::strcmp(ext,"par")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.rec",body._data); + } + if (!std::strcmp(ext,"PAR")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.REC",body._data); + } + if (!std::strcmp(ext,"rec")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.par",body._data); + } + if (!std::strcmp(ext,"REC")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.PAR",body._data); + } + std::FILE *file = cimg::fopen(filenamepar,"r"); + + // Parse header file + CImgList st_slices; + CImgList st_global; + CImg line(256); *line = 0; + int err; + do { err = std::fscanf(file,"%255[^\n]%*c",line._data); } while (err!=EOF && (*line=='#' || *line=='.')); + do { + unsigned int sn,size_x,size_y,pixsize; + float rs,ri,ss; + err = std::fscanf(file,"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&size_x,&size_y,&ri,&rs,&ss); + if (err==7) { + CImg::vector((float)sn,(float)pixsize,(float)size_x,(float)size_y,ri,rs,ss,0).move_to(st_slices); + unsigned int i; for (i = 0; i::vector(size_x,size_y,sn).move_to(st_global); + else { + CImg &vec = st_global[i]; + if (size_x>vec[0]) vec[0] = size_x; + if (size_y>vec[1]) vec[1] = size_y; + vec[2] = sn; + } + st_slices[st_slices._width - 1][7] = (float)i; + } + } while (err==7); + + // Read data + std::FILE *file2 = cimg::fopen(filenamerec,"rb"); + cimglist_for(st_global,l) { + const CImg& vec = st_global[l]; + CImg(vec[0],vec[1],vec[2]).move_to(*this); + } + + cimglist_for(st_slices,l) { + const CImg& vec = st_slices[l]; + const unsigned int + sn = (unsigned int)vec[0] - 1, + pixsize = (unsigned int)vec[1], + size_x = (unsigned int)vec[2], + size_y = (unsigned int)vec[3], + imn = (unsigned int)vec[7]; + const float ri = vec[4], rs = vec[5], ss = vec[6]; + switch (pixsize) { + case 8 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 16 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 32 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + default : + cimg::fclose(file); + cimg::fclose(file2); + throw CImgIOException(_cimglist_instance + "load_parrec(): Unsupported %d-bits pixel type for file '%s'.", + cimglist_instance, + pixsize,filename); + } + } + cimg::fclose(file); + cimg::fclose(file2); + if (!_width) + throw CImgIOException(_cimglist_instance + "load_parrec(): Failed to recognize valid PAR-REC data in file '%s'.", + cimglist_instance, + filename); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file \newinstance. + static CImgList get_load_parrec(const char *const filename) { + return CImgList().load_parrec(filename); + } + + //! Load a list from a YUV image sequence file. + /** + \param filename Filename to read data from. + \param size_x Width of the images. + \param size_y Height of the images. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param yuv2rgb Apply YUV to RGB transformation during reading. + **/ + CImgList& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(0,filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from a YUV image sequence file \newinstance. + static CImgList get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(filename,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \overloading. + CImgList& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(file,0,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \newinstance. + static CImgList get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int chroma_subsampling=444, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(file,size_x,size_y,chroma_subsampling, + first_frame,last_frame,step_frame,yuv2rgb); + } + + CImgList& _load_yuv(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int chroma_subsampling, + const unsigned int first_frame, const unsigned int last_frame, + const unsigned int step_frame, const bool yuv2rgb) { + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified filename is (null).", + cimglist_instance); + if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified chroma subsampling '%u' is invalid, for file '%s'.", + cimglist_instance, + chroma_subsampling,filename?filename:"(FILE*)"); + const unsigned int + cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1, + cfy = chroma_subsampling==420?2:1, + nfirst_frame = first_frame YUV(size_x,size_y,1,3), UV(size_x/cfx,size_y/cfy,1,2); + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool stop_flag = false; + int err; + if (nfirst_frame) { + err = cimg::fseek(nfile,(uint64T)nfirst_frame*(YUV._width*YUV._height + 2*UV._width*UV._height),SEEK_CUR); + if (err) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_yuv(): File '%s' doesn't contain frame number %u.", + cimglist_instance, + filename?filename:"(FILE*)",nfirst_frame); + } + } + unsigned int frame; + for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) { + YUV.get_shared_channel(0).fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(YUV._data),1,(size_t)YUV._width*YUV._height,nfile); + if (err!=(int)(YUV._width*YUV._height)) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + UV.fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(UV._data),1,(size_t)UV.size(),nfile); + if (err!=(int)(UV.size())) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + const ucharT *ptrs1 = UV._data, *ptrs2 = UV.data(0,0,0,1); + ucharT *ptrd1 = YUV.data(0,0,0,1), *ptrd2 = YUV.data(0,0,0,2); + const unsigned int wd = YUV._width; + switch (chroma_subsampling) { + case 420 : + cimg_forY(UV,y) { + cimg_forX(UV,x) { + const ucharT U = *(ptrs1++), V = *(ptrs2++); + ptrd1[wd] = U; *(ptrd1)++ = U; + ptrd1[wd] = U; *(ptrd1)++ = U; + ptrd2[wd] = V; *(ptrd2)++ = V; + ptrd2[wd] = V; *(ptrd2)++ = V; + } + ptrd1+=wd; ptrd2+=wd; + } + break; + case 422 : + cimg_forXY(UV,x,y) { + const ucharT U = *(ptrs1++), V = *(ptrs2++); + *(ptrd1++) = U; *(ptrd1++) = U; + *(ptrd2++) = V; *(ptrd2++) = V; + } + break; + default : + YUV.draw_image(0,0,0,1,UV); + } + if (yuv2rgb) YUV.YCbCrtoRGB(); + insert(YUV); + if (nstep_frame>1) cimg::fseek(nfile,(uint64T)(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR); + } + } + } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_yuv() : Missing data in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + if (stop_flag && nlast_frame!=~0U && frame!=nlast_frame) + cimg::warn(_cimglist_instance + "load_yuv(): Frame %d not reached since only %u frames were found in file '%s'.", + cimglist_instance, + nlast_frame,frame - 1,filename?filename:"(FILE*)"); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load an image from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read (can be higher than the actual number of frames, e.g. '~0U'). + \param step_frame Step value for frame reading. + \note If step_frame==0, the current video stream is forced to be released (without any frames read). + **/ + CImgList& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { +#ifndef cimg_use_opencv + if (first_frame || last_frame!=~0U || step_frame>1) + throw CImgArgumentException(_cimglist_instance + "load_video() : File '%s', arguments 'first_frame', 'last_frame' " + "and 'step_frame' requires features from the OpenCV library " + "('-Dcimg_use_opencv' must be defined).", + cimglist_instance,filename); + return load_custom_external(filename); +#else + static cv::VideoCapture *captures[32] = { 0 }; + static CImgList filenames(32); + static CImg positions(32,1,1,1,0); + static int last_used_index = -1; + + // Detect if a video capture already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Release stream if needed. + if (!step_frame || (index>=0 && positions[index]>first_frame)) { + if (index>=0) { + cimg::mutex(9); + captures[index]->release(); + delete captures[index]; + captures[index] = 0; + positions[index] = 0; + filenames[index].assign(); + if (last_used_index==index) last_used_index = -1; + index = -1; + cimg::mutex(9,0); + } else + if (filename) + cimg::warn(_cimglist_instance + "load_video() : File '%s', no opened video stream associated with filename found.", + cimglist_instance,filename); + else + cimg::warn(_cimglist_instance + "load_video() : No opened video stream found.", + cimglist_instance,filename); + if (!step_frame) return *this; + } + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_video(): No already open video reader found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', no video reader slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + cimg::mutex(9); + captures[index] = new cv::VideoCapture(filename); + positions[index] = 0; + if (!captures[index]->isOpened()) { + delete captures[index]; + captures[index] = 0; + cimg::mutex(9,0); + cimg::fclose(cimg::fopen(filename,"rb")); // Check file availability + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to detect format of video file.", + cimglist_instance,filename); + } + CImg::string(filename).move_to(filenames[index]); + cimg::mutex(9,0); + } + + cimg::mutex(9); + const unsigned int nb_frames = (unsigned int)std::max(0.,captures[index]->get(_cimg_cap_prop_frame_count)); + cimg::mutex(9,0); + assign(); + + // Skip frames if requested. + bool go_on = true; + unsigned int &pos = positions[index]; + while (posgrab()) { cimg::mutex(9,0); go_on = false; break; } + cimg::mutex(9,0); + ++pos; + } + + // Read and convert frames. + const unsigned int _last_frame = std::min(nb_frames?nb_frames - 1:~0U,last_frame); + while (go_on && pos<=_last_frame) { + cv::Mat cvimg; + cimg::mutex(9); + if (captures[index]->read(cvimg)) { CImg::_cvmat2cimg(cvimg).move_to(*this); ++pos; } + else go_on = false; + cimg::mutex(9,0); + if (go_on) + for (unsigned int i = 1; go_on && igrab()) go_on = false; + cimg::mutex(9,0); + } + } + + if (!go_on || (nb_frames && pos>=nb_frames)) { // Close video stream when necessary + cimg::mutex(9); + captures[index]->release(); + delete captures[index]; + captures[index] = 0; + filenames[index].assign(); + positions[index] = 0; + index = -1; + cimg::mutex(9,0); + } + + cimg::mutex(9); + last_used_index = index; + cimg::mutex(9,0); + + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to locate frame %u.", + cimglist_instance,filename,first_frame); + return *this; +#endif + } + + //! Load an image from a video file, using OpenCV library \newinstance. + static CImgList get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame); + } + + //! Load an image from a video file using the external tool 'custom'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_custom_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_custom_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%%6d.ppm",filename_tmp._data); + cimg_snprintf(command,command._width,"\"%s\" -v -8 -i \"%s\" \"%s\"", + cimg::custom_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp2)._system_strescape().data()); + cimg::system(command, cimg::custom_path()); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + unsigned int i = 1; + for (bool stop_flag = false; !stop_flag; ++i) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,i); + CImg img; + try { img.load_pnm(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + cimg::exception_mode(omode); + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_custom_external(): Failed to open file '%s' with external command 'custom'.", + cimglist_instance, + filename); + return *this; + } + + //! Load an image from a video file using the external tool 'custom' \newinstance. + static CImgList get_load_custom_external(const char *const filename) { + return CImgList().load_custom_external(filename); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gif_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_gif_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + if (!_load_gif_external(filename,false)) + if (!_load_gif_external(filename,true)) + try { assign(CImg().load_other(filename)); } catch (CImgException&) { assign(); } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_gif_external(): Failed to open file '%s'.", + cimglist_instance,filename); + return *this; + } + + CImgList& _load_gif_external(const char *const filename, const bool use_graphicsmagick=false) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.0",filename_tmp._data); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-0.png",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + if (use_graphicsmagick) cimg_snprintf(command,command._width,"%s convert \"%s\" \"%s.png\"", + cimg::graphicsmagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + else cimg_snprintf(command,command._width,"\"%s\" -coalesce \"%s\" \"%s.png\"", + cimg::imagemagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::imagemagick_path()); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + + // Try to read a single frame gif. + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png",filename_tmp._data); + CImg img; + try { img.load_png(filename_tmp2); } + catch (CImgException&) { } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + else { // Try to read animated gif + unsigned int i = 0; + for (bool stop_flag = false; !stop_flag; ++i) { + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.%u",filename_tmp._data,i); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-%u.png",filename_tmp._data,i); + try { img.load_png(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools \newinstance. + static CImgList get_load_gif_external(const char *const filename) { + return CImgList().load_gif_external(filename); + } + + //! Load a gzipped list, using external tool 'gunzip'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Specified filename is (null).", + cimglist_instance); + cimg::fclose(cimg::fopen(filename,"rb")); // Check if file exists + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command, cimg::gunzip_path()); + if (!(file=cimg::std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Failed to open file '%s'.", + cimglist_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load a gzipped list, using external tool 'gunzip' \newinstance. + static CImgList get_load_gzip_external(const char *const filename) { + return CImgList().load_gzip_external(filename); + } + + //! Load images from a TIFF file. + /** + \param filename Filename to read data from. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param[out] bits_per_value Number of bits used to store a scalar value in the image file. + \param[out] voxel_size Voxel size, as stored in the filename. + \param[out] description Description, as stored in the filename. + **/ + CImgList& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + const unsigned int + nfirst_frame = first_frame::get_load_tiff(filename)); +#else +#if cimg_verbosity<3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimglist_instance + "load_tiff(): Invalid specified frame range is [%u,%u] (step %u) since " + "file '%s' contains %u image(s).", + cimglist_instance, + nfirst_frame,nlast_frame,nstep_frame,filename,nb_images); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + assign(1 + (nlast_frame - nfirst_frame)/nstep_frame); + TIFFSetDirectory(tif,0); + cimglist_for(*this,l) + _data[l]._load_tiff(tif,nfirst_frame + l*nstep_frame,bits_per_value,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimglist_instance + "load_tiff(): Failed to open file '%s'.", + cimglist_instance, + filename); + return *this; +#endif + } + + //! Load a multi-page TIFF file \newinstance. + static CImgList get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, unsigned int *const bits_per_value=0, + float *const voxel_size=0, CImg *const description=0) { + return CImgList().load_tiff(filename,first_frame,last_frame,step_frame,bits_per_value,voxel_size,description); + } + + //@} + //---------------------------------- + // + //! \name Data Output + //@{ + //---------------------------------- + + //! Print information about the list on the standard output. + /** + \param title Label set to the information displayed. + \param display_stats Tells if image statistics must be computed and displayed. + **/ + const CImgList& print(const char *const title=0, const bool display_stats=true) const { + unsigned int msiz = 0; + cimglist_for(*this,l) msiz+=_data[l].size(); + msiz*=sizeof(T); + const unsigned int mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U; + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImgList<%s>",pixel_type()); + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%s>*)%p", + cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal, + cimg::t_bold,cimg::t_normal,(void*)this, + cimg::t_bold,cimg::t_normal,_width,_allocated_width, + mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)), + mdisp==0?"b":(mdisp==1?"Kio":"Mio"), + cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin()); + if (_data) std::fprintf(cimg::output(),"..%p.\n",(void*)((char*)end() - 1)); + else std::fprintf(cimg::output(),".\n"); + + char tmp[16] = { 0 }; + cimglist_for(*this,ll) { + cimg_snprintf(tmp,sizeof(tmp),"[%d]",ll); + std::fprintf(cimg::output()," "); + _data[ll].print(tmp,display_stats); + if (ll==3 && width()>8) { ll = width() - 5; std::fprintf(cimg::output()," ...\n"); } + } + std::fflush(cimg::output()); + return *this; + } + + //! Display the current CImgList instance in an existing CImgDisplay window (by reference). + /** + \param disp Reference to an existing CImgDisplay instance, where the current image list will be displayed. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + \note This function displays the list images of the current CImgList instance into an existing + CImgDisplay window. + Images of the list are appended in a single temporary image for visualization purposes. + The function returns immediately. + **/ + const CImgList& display(CImgDisplay &disp, const char axis='x', const float align=0) const { + disp.display(*this,axis,align); + return *this; + } + + //! Display the current CImgList instance in a new display window. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param axis Alignment axis for images viewing. + \param align Appending alignment. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + \note This function opens a new window with a specific title and displays the list images of the + current CImgList instance into it. + Images of the list are appended in a single temporary image for visualization purposes. + The function returns when a key is pressed or the display window is closed by the user. + **/ + const CImgList& display(CImgDisplay &disp, const bool display_info, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + bool is_exit = false; + return _display(disp,0,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + //! Display the current CImgList instance in a new display window. + /** + \param title Title of the opening display window. + \param display_info Tells if list information must be written on standard output. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + \param[in,out] XYZ Contains the XYZ coordinates at start / exit of the function. + \param exit_on_anykey Exit function when any key is pressed. + **/ + const CImgList& display(const char *const title=0, const bool display_info=true, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + CImgDisplay disp; + bool is_exit = false; + return _display(disp,title,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + const CImgList& _display(CImgDisplay &disp, const char *const title, const CImgList *const titles, + const bool display_info, const char axis, const float align, unsigned int *const XYZ, + const bool exit_on_anykey, const unsigned int orig, const bool is_first_call, + bool &is_exit) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "display(): Empty instance.", + cimglist_instance); + if (!disp) { + if (axis=='x') { + unsigned int sum_width = 0, max_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + sum_width+=w; + if (h>max_height) max_height = h; + } + disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:titles?titles->__display()._data:0,1); + } else { + unsigned int max_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + sum_height+=h; + } + disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:titles?titles->__display()._data:0,1); + } + if (!title && !titles) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else if (title) disp.set_title("%s",title); + else if (titles) disp.set_title("%s",titles->__display()._data); + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(disp.title()); + disp.show().flush(); + + if (_width==1) { + const unsigned int dw = disp._width, dh = disp._height; + if (!is_first_call) + disp.resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),false); + disp.set_title("%s (%ux%ux%ux%u)", + dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum); + _data[0]._display(disp,0,false,XYZ,exit_on_anykey,!is_first_call); + if (disp.key()) is_exit = true; + disp.resize(cimg_fitscreen(dw,dh,1),false).set_title("%s",dtitle.data()); + } else { + bool disp_resize = !is_first_call; + while (!disp.is_closed() && !is_exit) { + const CImg s = _select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true); + disp_resize = true; + if (s[0]<0 && !disp.wheel()) { // No selections done + if (disp.button()&2) { disp.flush(); break; } + is_exit = true; + } else if (disp.wheel()) { // Zoom in/out + const int wheel = disp.wheel(); + disp.set_wheel(); + if (!is_first_call && wheel<0) break; + if (wheel>0 && _width>=4) { + const unsigned int + delta = std::max(1U,(unsigned int)cimg::round(0.3*_width)), + ind0 = (unsigned int)std::max(0,s[0] - (int)delta), + ind1 = (unsigned int)std::min(width() - 1,s[0] + (int)delta); + if ((ind0!=0 || ind1!=_width - 1) && ind1 - ind0>=3) { + const CImgList sublist = get_shared_images(ind0,ind1); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(ind0,ind1); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + ind0,false,is_exit); + } + } + } else if (s[0]!=0 || s[1]!=width() - 1) { + const CImgList sublist = get_shared_images(s[0],s[1]); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(s[0],s[1]); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + s[0],false,is_exit); + } + disp.set_title("%s",dtitle.data()); + } + } + return *this; + } + + // [internal] Return string to describe display title. + CImg __display() const { + CImg res, str; + cimglist_for(*this,l) { + CImg::string((char*)_data[l]).move_to(str); + if (l!=width() - 1) { + str.resize(str._width + 1,1,1,1,0); + str[str._width - 2] = ','; + str[str._width - 1] = ' '; + } + res.append(str,'x'); + } + if (!res) return CImg(1,1,1,1,0).move_to(res); + cimg::strellipsize(res,128,false); + if (_width>1) { + const unsigned int l = (unsigned int)std::strlen(res); + if (res._width<=l + 16) res.resize(l + 16,1,1,1,0); + cimg_snprintf(res._data + l,16," (#%u)",_width); + } + return res; + } + + //! Save list into a file. + /** + \param filename Filename to write data to. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + **/ + const CImgList& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save(): Specified filename is (null).", + cimglist_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:number>=0?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimglist_save_plugin + cimglist_save_plugin(fn); +#endif +#ifdef cimglist_save_plugin1 + cimglist_save_plugin1(fn); +#endif +#ifdef cimglist_save_plugin2 + cimglist_save_plugin2(fn); +#endif +#ifdef cimglist_save_plugin3 + cimglist_save_plugin3(fn); +#endif +#ifdef cimglist_save_plugin4 + cimglist_save_plugin4(fn); +#endif +#ifdef cimglist_save_plugin5 + cimglist_save_plugin5(fn); +#endif +#ifdef cimglist_save_plugin6 + cimglist_save_plugin6(fn); +#endif +#ifdef cimglist_save_plugin7 + cimglist_save_plugin7(fn); +#endif +#ifdef cimglist_save_plugin8 + cimglist_save_plugin8(fn); +#endif + if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg") || !*ext) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,444,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); +#ifdef cimg_use_tiff + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); +#endif + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + else { + if (_width==1) _data[0].save(fn,-1); + else cimglist_for(*this,l) { _data[l].save(fn,is_stdout?-1:l); if (is_stdout) std::fputc(EOF,cimg::_stdout()); } + } + return *this; + } + + //! Tell if an image list can be saved as one single file. + /** + \param filename Filename, as a C-string. + \return \c true if the file format supports multiple images, \c false otherwise. + **/ + static bool is_saveable(const char *const filename) { + const char *const ext = cimg::split_filename(filename); + if (!cimg::strcasecmp(ext,"cimgz") || +#ifdef cimg_use_tiff + !cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff") || +#endif + !cimg::strcasecmp(ext,"yuv") || + !cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"webm") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return true; + return false; + } + + //! Save image sequence as a GIF animated file. + /** + \param filename Filename to write data to. + \param fps Number of desired frames per second. + \param nb_loops Number of loops (\c 0 for infinite looping). + **/ + const CImgList& save_gif_external(const char *const filename, const float fps=25, + const unsigned int nb_loops=0) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + +#ifdef cimg_use_png +#define _cimg_save_gif_extension "png" +#else +#define _cimg_save_gif_extension "ppm" +#endif + + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001." _cimg_save_gif_extension,filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u." _cimg_save_gif_extension,filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save(filename_tmp2); + else _data[l].save(filename_tmp2); + } + cimg_snprintf(command,command._width,"\"%s\" -delay %u -loop %u", + cimg::imagemagick_path(),(unsigned int)std::max(0.f,cimg::round(100/fps)),nb_loops); + CImg::string(command).move_to(filenames,0); + cimg_snprintf(command,command._width,"\"%s\"", + CImg::string(filename)._system_strescape().data()); + CImg::string(command).move_to(filenames); + CImg _command = filenames>'x'; + cimg_for(_command,p,char) if (!*p) *p = ' '; + _command.back() = 0; + + cimg::system(_command, cimg::imagemagick_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gif_external(): Failed to save file '%s' with external command 'magick/convert'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for_in(*this,1,filenames._width - 1,l) std::remove(filenames[l]); + return *this; + } + + //! Save list as a YUV image sequence file. + /** + \param filename Filename to write data to. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(const char *const filename=0, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + return _save_yuv(0,filename,chroma_subsampling,is_rgb); + } + + //! Save image sequence into a YUV file. + /** + \param file File to write data to. + \param chroma_subsampling Type of chroma subsampling. Can be { 420 | 422 | 444 }. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(std::FILE *const file, + const unsigned int chroma_subsampling=444, + const bool is_rgb=true) const { + return _save_yuv(file,0,chroma_subsampling,is_rgb); + } + + const CImgList& _save_yuv(std::FILE *const file, const char *const filename, + const unsigned int chroma_subsampling, + const bool is_rgb) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified filename is (null).", + cimglist_instance); + if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified chroma subsampling %u is invalid, for file '%s'.", + cimglist_instance, + chroma_subsampling,filename?filename:"(FILE*)"); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + const unsigned int + cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1, + cfy = chroma_subsampling==420?2:1, + w0 = (*this)[0]._width, h0 = (*this)[0]._height, + width0 = w0 + (w0%cfx), height0 = h0 + (h0%cfy); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + cimglist_for(*this,l) { + const CImg &frame = (*this)[l]; + cimg_forZ(frame,z) { + CImg YUV; + if (sizeof(T)==1 && !is_rgb && + frame._width==width0 && frame._height==height0 && frame._depth==1 && frame._spectrum==3) + YUV.assign((unsigned char*)frame._data,width0,height0,1,3,true); + else { + YUV = frame.get_slice(z); + if (YUV._width!=width0 || YUV._height!=height0) YUV.resize(width0,height0,1,-100,0); + if (YUV._spectrum!=3) YUV.resize(-100,-100,1,3,YUV._spectrum==1?1:0); + if (is_rgb) YUV.RGBtoYCbCr(); + } + if (chroma_subsampling==444) + cimg::fwrite(YUV._data,(size_t)YUV._width*YUV._height*3,nfile); + else { + cimg::fwrite(YUV._data,(size_t)YUV._width*YUV._height,nfile); + CImg UV = YUV.get_channels(1,2); + UV.resize(UV._width/cfx,UV._height/cfy,1,2,2); + cimg::fwrite(UV._data,(size_t)UV._width*UV._height*2,nfile); + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param filename Filename to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(const char *const filename, const bool is_compressed=false) const { + return _save_cimg(0,filename,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, const bool is_compressed) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "save_cimg(): Unable to save compressed data in file '%s' unless zlib is enabled, " + "saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); +#endif + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const bool is_bool = ptype==cimg::type::string(); + if (!is_bool && std::strstr(ptype,"unsigned")==ptype) + std::fprintf(nfile,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + std::fprintf(nfile,"%u %s %s_endian\n",_width,ptype,etype); + + cimglist_for(*this,l) { + const CImg& img = _data[l]; + std::fprintf(nfile,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + Bytef *cbuf = 0; + uLongf csiz = 0; + + if (is_bool) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = ref._bool2uchar(siz,false); + csiz = siz + siz/100 + 16; + cbuf = new Bytef[csiz]; + failed_to_compress = (bool)compress(cbuf,&csiz,(Bytef*)buf,siz); + if (!failed_to_compress) { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + } + delete[] buf; + } else { // Non-boolean data + const ulongT siz = sizeof(T)*ref.size(); + csiz = siz + siz/100 + 16; + cbuf = new Bytef[csiz]; + failed_to_compress = (bool)compress(cbuf,&csiz,(Bytef*)ref._data,siz); + if (!failed_to_compress) { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + } + } + if (failed_to_compress) + cimg::warn(_cimglist_instance + "save_cimg(): Failed to save compressed data for file '%s', saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); + delete[] cbuf; +#endif + } + if (failed_to_compress) { // Write non-compressed + std::fputc('\n',nfile); + if (is_bool) { // Boolean data (bitwise) + ulongT siz; + const unsigned char *const buf = ref._bool2uchar(siz,false); + cimg::fwrite(buf,siz,nfile); + delete[] buf; + } else cimg::fwrite(ref._data,ref.size(),nfile); // Non-boolean data + } + } else std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param file File to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(std::FILE *file, const bool is_compressed=false) const { + return _save_cimg(file,0,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { +#define _cimg_save_cimg_case(Ts,Tss) \ + if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l0) { \ + if (l=W || y0>=H || z0>=D || c0>=D) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const CImg& img = (*this)[l - n0]; \ + const T *ptrs = img._data; \ + const unsigned int \ + x1 = x0 + img._width - 1, \ + y1 = y0 + img._height - 1, \ + z1 = z0 + img._depth - 1, \ + c1 = c0 + img._spectrum - 1, \ + nx1 = x1>=W?W - 1:x1, \ + ny1 = y1>=H?H - 1:y1, \ + nz1 = z1>=D?D - 1:z1, \ + nc1 = c1>=C?C - 1:c1; \ + CImg raw(1 + nx1 - x0); \ + const unsigned int skipvb = c0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int v = 1 + nc1 - c0; v; --v) { \ + const unsigned int skipzb = z0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + nz1 - z0; z; --z) { \ + const unsigned int skipyb = y0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + ny1 - y0; y; --y) { \ + const unsigned int skipxb = x0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + raw.assign(ptrs, raw._width); \ + ptrs+=img._width; \ + if (endian) cimg::invert_endianness(raw._data,raw._width); \ + cimg::fwrite(raw._data,raw._width,nfile); \ + const unsigned int skipxe = (W - 1 - nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const unsigned int skipye = (H - 1 - ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const unsigned int skipze = (D - 1 - nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const unsigned int skipve = (C - 1 - nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_cimg(): Empty instance, for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb+"); + bool saved = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + const unsigned int lmax = std::min(N,n0 + _width); + _cimg_save_cimg_case("bool",bool); + _cimg_save_cimg_case("unsigned_char",unsigned char); + _cimg_save_cimg_case("uchar",unsigned char); + _cimg_save_cimg_case("char",char); + _cimg_save_cimg_case("unsigned_short",unsigned short); + _cimg_save_cimg_case("ushort",unsigned short); + _cimg_save_cimg_case("short",short); + _cimg_save_cimg_case("unsigned_int",unsigned int); + _cimg_save_cimg_case("uint",unsigned int); + _cimg_save_cimg_case("int",int); + _cimg_save_cimg_case("unsigned_int64",uint64T); + _cimg_save_cimg_case("uint64",uint64T); + _cimg_save_cimg_case("int64",int64T); + _cimg_save_cimg_case("float",float); + _cimg_save_cimg_case("double",double); + if (!saved) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): Unsupported data type '%s' for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)",str_pixeltype._data); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param filename Filename to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(0,filename,n0,x0,y0,z0,c0); + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param file File to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(file,0,n0,x0,y0,z0,c0); + } + + static void _save_empty_cimg(std::FILE *const file, const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT siz = (ulongT)dx*dy*dz*dc*sizeof(T); + std::fprintf(nfile,"%u %s\n",nb,pixel_type()); + for (unsigned int i=nb; i; --i) { + std::fprintf(nfile,"%u %u %u %u\n",dx,dy,dz,dc); + for (ulongT off = siz; off; --off) std::fputc(0,nfile); + } + if (!file) cimg::fclose(nfile); + } + + //! Save empty (non-compressed) .cimg file with specified dimensions. + /** + \param filename Filename to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(0,filename,nb,dx,dy,dz,dc); + } + + //! Save empty .cimg file with specified dimensions. + /** + \param file File to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(file,0,nb,dx,dy,dz,dc); + } + + //! Save list as a TIFF file. + /** + \param filename Filename to write data to. + \param compression_type Compression mode used to write data. + \param voxel_size Voxel size, to be stored in the filename. + \param description Description, to be stored in the filename. + \param use_bigtiff Allow to save big tiff files (>4Gb). + **/ + const CImgList& save_tiff(const char *const filename, const unsigned int compression_type=0, + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_tiff(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_tiff + if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,use_bigtiff); + else cimglist_for(*this,l) { + CImg nfilename(1024); + cimg::number_filename(filename,l,6,nfilename); + _data[l].save_tiff(nfilename,compression_type,voxel_size,description,use_bigtiff); + } +#else + ulongT siz = 0; + cimglist_for(*this,l) siz+=_data[l].size(); + const bool _use_bigtiff = use_bigtiff && sizeof(siz)>=8 && siz*sizeof(T)>=1UL<<31; // No bigtiff for small images + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + for (unsigned int dir = 0, l = 0; l<_width; ++l) { + const CImg& img = (*this)[l]; + cimg_forZ(img,z) img._save_tiff(tif,dir++,z,compression_type,voxel_size,description); + } + TIFFClose(tif); + } else + throw CImgIOException(_cimglist_instance + "save_tiff(): Failed to open stream for file '%s'.", + cimglist_instance, + filename); +#endif + return *this; + } + + //! Save list as a gzipped file, using external tool 'gzip'. + /** + \param filename Filename to write data to. + **/ + const CImgList& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Specified filename is (null).", + cimglist_instance); + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=cimg::std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + + if (is_saveable(body)) { + save(filename_tmp); + cimg_snprintf(command,command._width,"\"%s\" -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::gzip_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimglist_instance, + filename); + else cimg::fclose(file); + std::remove(filename_tmp); + } else { + CImg nfilename(1024); + cimglist_for(*this,l) { + cimg::number_filename(body,l,6,nfilename); + if (*ext) cimg_sprintf(nfilename._data + std::strlen(nfilename),".%s",ext); + _data[l].save_gzip_external(nfilename); + } + } + return *this; + } + + //! Save image sequence (using the OpenCV library when available). + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImgList& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { +#ifndef cimg_use_opencv + cimg::unused(codec,keep_open); + return save_custom_external(filename,fps); +#else + try { + static cv::VideoWriter *writers[32] = { 0 }; + static CImgList filenames(32); + static CImg sizes(32,2,1,1,0); + static int last_used_index = -1; + + // Detect if a video writer already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_video(): No already open video writer found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', no video writer slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_video(): Instance list is empty.", + cimglist_instance); + const unsigned int W = _data?_data[0]._width:0, H = _data?_data[0]._height:0; + if (!W || !H) + throw CImgInstanceException(_cimglist_instance + "save_video(): Frame [0] is an empty image.", + cimglist_instance); + const char + *const _codec = codec && *codec?codec:"h264", + codec0 = cimg::uppercase(_codec[0]), + codec1 = _codec[0]?cimg::uppercase(_codec[1]):0, + codec2 = _codec[1]?cimg::uppercase(_codec[2]):0, + codec3 = _codec[2]?cimg::uppercase(_codec[3]):0; + cimg::mutex(9); + writers[index] = new cv::VideoWriter(filename,_cimg_fourcc(codec0,codec1,codec2,codec3),fps,cv::Size(W,H)); + if (!writers[index]->isOpened()) { + delete writers[index]; + writers[index] = 0; + cimg::mutex(9,0); + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', unable to initialize video writer with codec '%c%c%c%c'.", + cimglist_instance,filename, + codec0,codec1,codec2,codec3); + } + CImg::string(filename).move_to(filenames[index]); + sizes(index,0) = W; + sizes(index,1) = H; + cimg::mutex(9,0); + } + + if (!is_empty()) { + const unsigned int W = sizes(index,0), H = sizes(index,1); + cimg::mutex(9); + cimglist_for(*this,l) { + CImg &src = _data[l]; + if (src.is_empty()) + cimg::warn(_cimglist_instance + "save_video(): Skip empty frame %d for file '%s'.", + cimglist_instance,l,filename); + if (src._depth>1 || src._spectrum>3) + cimg::warn(_cimglist_instance + "save_video(): Frame %u has incompatible dimension (%u,%u,%u,%u). " + "Some image data may be ignored when writing frame into video file '%s'.", + cimglist_instance,l,src._width,src._height,src._depth,src._spectrum,filename); + if (src._width==W && src._height==H && src._spectrum==3) + writers[index]->write(CImg(src)._cimg2cvmat()); + else { + CImg _src(src,false); + _src.channels(0,std::min(_src._spectrum - 1,2U)).resize(W,H); + _src.resize(W,H,1,3,_src._spectrum==1); + writers[index]->write(_src._cimg2cvmat()); + } + } + cimg::mutex(9,0); + } + + cimg::mutex(9); + if (!keep_open) { + delete writers[index]; + writers[index] = 0; + filenames[index].assign(); + sizes(index,0) = sizes(index,1) = 0; + last_used_index = -1; + } else last_used_index = index; + cimg::mutex(9,0); + } catch (CImgIOException &e) { + if (!keep_open) return save_custom_external(filename,fps); + throw e; + } + return *this; +#endif + } + + //! Save image sequence, using the external tool 'custom'. + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression. + \param bitrate Output bitrate + **/ + const CImgList& save_custom_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_custom_external(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + const char + *const ext = cimg::split_filename(filename), + *const _codec = codec?codec: + !cimg::strcasecmp(ext,"flv")?"flv": + !cimg::strcasecmp(ext,"mp4")?"h264":"mpeg2video"; + + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + cimglist_for(*this,l) if (!_data[l].is_sameXYZ(_data[0])) + throw CImgInstanceException(_cimglist_instance + "save_custom_external(): Invalid instance dimensions for file '%s'.", + cimglist_instance, + filename); + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=cimg::std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + CImg tmp = _data[l].get_shared(); + if (tmp._width%2 || tmp._height%2) // Force output to have an even number of columns and rows + tmp.assign(tmp.get_resize(tmp._width + (tmp._width%2),tmp._height + (tmp._height%2),1,-100,0),false); + if (tmp._depth>1 || tmp._spectrum!=3) // Force output to be one slice, in color + tmp.assign(tmp.get_resize(-100,-100,1,3),false); + tmp.save_pnm(filename_tmp2); + } + cimg_snprintf(command,command._width, + "\"%s\" -v -8 -y -i \"%s_%%6d.ppm\" -pix_fmt yuv420p -vcodec %s -b %uk -r %u \"%s\"", + cimg::custom_path(), + CImg::string(filename_tmp)._system_strescape().data(), + _codec,bitrate,fps, + CImg::string(filename)._system_strescape().data()); + cimg::system(command, cimg::custom_path()); + file = cimg::std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_custom_external(): Failed to save file '%s' with external command 'custom'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for(*this,l) std::remove(filenames[l]); + return *this; + } + + //! Serialize a CImgList instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "get_serialize(): Unable to compress data unless zlib is enabled, " + "storing them uncompressed.", + cimglist_instance); +#endif + CImgList stream; + CImg tmpstr(128); + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + if (std::strstr(ptype,"unsigned")==ptype) + cimg_snprintf(tmpstr,tmpstr._width,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + cimg_snprintf(tmpstr,tmpstr._width,"%u %s %s_endian\n",_width,ptype,etype); + CImg::string(tmpstr,false).move_to(stream); + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_snprintf(tmpstr,tmpstr._width,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + CImg::string(tmpstr,false).move_to(stream); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + const ulongT siz = sizeof(T)*ref.size(); + uLongf csiz = (ulongT)compressBound(siz); + Bytef *const cbuf = new Bytef[csiz]; + if (compress(cbuf,&csiz,(Bytef*)ref._data,siz)) + cimg::warn(_cimglist_instance + "get_serialize(): Failed to save compressed data, saving them uncompressed.", + cimglist_instance); + else { + cimg_snprintf(tmpstr,tmpstr._width," #%lu\n",csiz); + CImg::string(tmpstr,false).move_to(stream); + CImg(cbuf,csiz).move_to(stream); + delete[] cbuf; + failed_to_compress = false; + } +#endif + } + if (failed_to_compress) { // Write in a non-compressed way + CImg::string("\n",false).move_to(stream); + stream.insert(1); + stream.back().assign((unsigned char*)ref._data,ref.size()*sizeof(T),1,1,1,true); + } + } else CImg::string("\n",false).move_to(stream); + } + cimglist_apply(stream,unroll)('y'); + return stream>'y'; + } + + //! Unserialize a CImg serialized buffer into a CImgList list. + template + static CImgList get_unserialize(const CImg& buffer) { +#ifdef cimg_use_zlib +#define _cimgz_unserialize_case(Tss) { \ + Bytef *cbuf = 0; \ + if (sizeof(t)!=1 || buffer.pixel_type()==cimg::type::string()) { \ + cbuf = new Bytef[csiz]; Bytef *_cbuf = cbuf; \ + for (ulongT k = 0; k::get_unserialize(): Unable to unserialize compressed data " \ + "unless zlib is enabled.", \ + pixel_type()); +#endif + +#define _cimg_unserialize_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l::unserialize(): Invalid specified size (%u,%u,%u,%u) for " \ + "image #%u in serialized buffer.", \ + pixel_type(),W,H,D,C,l); \ + if (W*H*D*C>0) { \ + CImg raw; \ + CImg &img = res._data[l]; \ + if (err==5) _cimgz_unserialize_case(Tss) \ + else { \ + raw.assign(W,H,D,C); \ + CImg _raw((unsigned char*)raw._data,W*sizeof(Tss),H,D,C,true); \ + if (sizeof(t)==1) { std::memcpy(_raw,stream,_raw.size()); stream+=_raw.size(); } \ + else cimg_for(_raw,p,unsigned char) *p = (unsigned char)*(stream++); \ + } \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } \ + } \ + loaded = true; \ + } + + if (buffer.is_empty()) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Specified serialized buffer is (null).", + pixel_type()); + CImgList res; + const t *stream = buffer._data, *const estream = buffer._data + buffer.size(); + bool loaded = false, endian = cimg::endianness(), is_bytef = false; + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + uint64T csiz; + int i, err; + cimg::unused(is_bytef); + do { + j = 0; while ((i=(int)*stream)!='\n' && stream::get_unserialize(): CImg header not found in serialized buffer.", + pixel_type()); + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + res.assign(N); + _cimg_unserialize_case("bool",bool); + _cimg_unserialize_case("unsigned_char",unsigned char); + _cimg_unserialize_case("uchar",unsigned char); + _cimg_unserialize_case("char",char); + _cimg_unserialize_case("unsigned_short",unsigned short); + _cimg_unserialize_case("ushort",unsigned short); + _cimg_unserialize_case("short",short); + _cimg_unserialize_case("unsigned_int",unsigned int); + _cimg_unserialize_case("uint",unsigned int); + _cimg_unserialize_case("int",int); + _cimg_unserialize_case("unsigned_int64",uint64T); + _cimg_unserialize_case("uint64",uint64T); + _cimg_unserialize_case("int64",int64T); + _cimg_unserialize_case("float",float); + _cimg_unserialize_case("double",double); + if (!loaded) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Unsupported pixel type '%s' defined " + "in serialized buffer.", + pixel_type(),str_pixeltype._data); + return res; + } + + //@} + //---------------------------------- + // + //! \name Others + //@{ + //---------------------------------- + + //! Return a CImg pre-defined font with requested height. + /** + \param font_height Height of the desired font (exact match for 13,23,53,103). + \param is_variable_width Decide if the font has a variable (\c true) or fixed (\c false) width. + **/ + static const CImgList& font(const unsigned int requested_height, const bool is_variable_width=true) { + if (!requested_height) return CImgList::const_empty(); + cimg::mutex(11); + static const unsigned char font_resizemap[] = { + 0, 4, 7, 9, 11, 13, 15, 17, 19, 21, 22, 24, 26, 27, 29, 30, + 32, 33, 35, 36, 38, 39, 41, 42, 43, 45, 46, 47, 49, 50, 51, 52, + 54, 55, 56, 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 162, 163, 164, 164, 165, + 166, 167, 168, 169, 170, 170, 171, 172, 173, 174, 175, 176, 176, 177, 178, 179, + 180, 181, 181, 182, 183, 184, 185, 186, 186, 187, 188, 189, 190, 191, 191, 192, + 193, 194, 195, 196, 196, 197, 198, 199, 200, 200, 201, 202, 203, 204, 205, 205, + 206, 207, 208, 209, 209, 210, 211, 212, 213, 213, 214, 215, 216, 216, 217, 218, + 219, 220, 220, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 231, + 231, 232, 233, 234, 234, 235, 236, 237, 238, 238, 239, 240, 241, 241, 242, 243, + 244, 244, 245, 246, 247, 247, 248, 249, 250, 250, 251, 252, 253, 253, 254, 255 }; + static const char *const *font_data[] = { + cimg::data_font_small, + cimg::data_font_normal, + cimg::data_font_large, + cimg::data_font_huge }; + static const unsigned int + font_width[] = { 10,26,52,104 }, + font_height[] = { 13,32,64,128 }, + font_M[] = { 86,91,91,47 }, + font_chunk[] = { sizeof(cimg::data_font_small)/sizeof(char*), + sizeof(cimg::data_font_normal)/sizeof(char*), + sizeof(cimg::data_font_large)/sizeof(char*), + sizeof(cimg::data_font_huge)/sizeof(char*) }; + static const unsigned char font_is_binary[] = { 1,0,0,1 }; + static CImg font_base[4]; + + unsigned int ind = + requested_height<=font_height[0]?0U: + requested_height<=font_height[1]?1U: + requested_height<=font_height[2]?2U:3U; + + // Decompress nearest base font data if needed. + CImg &basef = font_base[ind]; + if (!basef) { + basef.assign(256*font_width[ind],font_height[ind]); + + unsigned char *ptrd = basef; + const unsigned char *const ptrde = basef.end(); + + // Recompose font data from several chunks, to deal with MS compiler limit with big strings (64 Kb). + CImg dataf; + for (unsigned int k = 0; k::string(font_data[ind][k],k==font_chunk[ind] - 1,true),'x'); + + // Uncompress font data (decode RLE). + const unsigned int M = font_M[ind]; + if (font_is_binary[ind]) + for (const char *ptrs = dataf; *ptrs; ++ptrs) { + const int _n = (int)(*ptrs - M - 32), v = _n>=0?255:0, n = _n>=0?_n:-_n; + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + else + for (const char *ptrs = dataf; *ptrs; ++ptrs) { + int n = (int)*ptrs - M - 32, v = 0; + if (n>=0) { v = 85*n; n = 1; } + else { + n = -n; + v = (int)*(++ptrs) - M - 32; + if (v<0) { v = 0; --ptrs; } else v*=85; + } + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + } + + // Find optimal font cache location to return. + static CImgList fonts[16]; + static bool is_variable_widths[16] = { 0 }; + ind = ~0U; + for (int i = 0; i<16; ++i) + if (!fonts[i] || (is_variable_widths[i]==is_variable_width && requested_height==fonts[i][0]._height)) { + ind = (unsigned int)i; break; // Found empty slot or cached font + } + if (ind==~0U) { // No empty slots nor existing font in cache + fonts->assign(); + std::memmove((void*)fonts,(void*)(fonts + 1),15*sizeof(CImgList)); + std::memmove(is_variable_widths,is_variable_widths + 1,15*sizeof(bool)); + std::memset((void*)(fonts + (ind=15)),0,sizeof(CImgList)); // Free a slot in cache for new font + } + CImgList &font = fonts[ind]; + + // Render requested font. + if (!font) { + is_variable_widths[ind] = is_variable_width; + basef.get_split('x',256).move_to(font); + +// cimg::tic(); + + if (requested_height!=font[0]._height) + cimglist_for(font,l) { + font[l].resize(std::max(1U,font[l]._width*requested_height/font[l]._height),requested_height,-100,-100,5); + cimg_for(font[l],ptr,ucharT) *ptr = font_resizemap[*ptr]; + } + +// cimg::toc(); +// std::exit(0); + + if (is_variable_width) { // Crop font + cimglist_for(font,l) { + CImg& letter = font[l]; + int xmin = letter.width(), xmax = 0; + cimg_forX(letter,x) { // Find xmin + cimg_forY(letter,y) if (letter(x,y)) { xmin = x; break; } + if (xmin!=letter.width()) break; + } + cimg_rofX(letter,x) { // Find xmax + cimg_forY(letter,y) if (letter(x,y)) { xmax = x; break; } + if (xmax) break; + } + if (xmin<=xmax) letter.crop(xmin,0,xmax,letter._height - 1); + } + font[(int)' '].resize(font[(int)'f']._width,-100,-100,-100,0); + if (' ' + 256& FFT(const char axis, const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + CImg::FFT(_data[0],_data[1],axis,invert); + return *this; + } + + //! Compute a 1-D Fast Fourier Transform, along specified axis \newinstance. + CImgList get_FFT(const char axis, const bool invert=false) const { + return CImgList(*this,false).FFT(axis,invert); + } + + //! Compute n-D Fast Fourier Transform. + /** + \param invert Tells if the direct (\c false) or inverse transform (\c true) is computed. + **/ + CImgList& FFT(const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + + CImg::FFT(_data[0],_data[1],invert); + return *this; + } + + //! Compute n-D Fast Fourier Transform \newinstance. + CImgList get_FFT(const bool invert=false) const { + return CImgList(*this,false).FFT(invert); + } + + //! Reverse primitives orientations of a 3D object. + /** + **/ + CImgList& reverse_object3d() { + cimglist_for(*this,l) { + CImg& p = _data[l]; + switch (p.size()) { + case 2 : case 3: cimg::swap(p[0],p[1]); break; + case 6 : cimg::swap(p[0],p[1],p[2],p[4],p[3],p[5]); break; + case 9 : cimg::swap(p[0],p[1],p[3],p[5],p[4],p[6]); break; + case 4 : cimg::swap(p[0],p[1],p[2],p[3]); break; + case 12 : cimg::swap(p[0],p[1],p[2],p[3],p[4],p[6],p[5],p[7],p[8],p[10],p[9],p[11]); break; + } + } + return *this; + } + + //! Reverse primitives orientations of a 3D object \newinstance. + CImgList get_reverse_object3d() const { + return (+*this).reverse_object3d(); + } + + //@} + }; // struct CImgList { ... + + // Completion of previously declared functions + //-------------------------------------------- + namespace cimg { + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + // (throw a CImgIOException when macro 'cimg_use_r' is defined). + inline FILE* _stdin(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stdin; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stdin(): Reference to 'stdin' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + inline FILE* _stdout(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stdout; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stdout(): Reference to 'stdout' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + inline FILE* _stderr(const bool throw_exception) { +#ifndef cimg_use_r + cimg::unused(throw_exception); + return stderr; +#else + if (throw_exception) { + cimg::exception_mode(0); + throw CImgIOException("cimg::stderr(): Reference to 'stderr' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + } + return 0; +#endif + } + + // Open a file (similar to std:: fopen(), but with wide character support on Windows). + inline std::FILE *std_fopen(const char *const path, const char *const mode) { + std::FILE *const res = std::fopen(path,mode); + if (res) return res; +#if cimg_OS==2 + // Try alternative method, with wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (err) { + CImg wpath((unsigned int)err); + err = MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err); + if (err) { // Convert 'mode' to a wide-character string + err = MultiByteToWideChar(CP_UTF8,0,mode,-1,0,0); + if (err) { + CImg wmode((unsigned int)err); + if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wmode,err)) + return _wfopen(wpath,wmode); + } + } + } +#endif + return 0; + } + + //! Search path of an executable (Windows only). +#if cimg_OS==2 + inline bool win_searchpath(const char *const exec_name, char *const res, const unsigned int size_res) { + char *ptr = 0; + DWORD err = SearchPathA(0,exec_name,0,size_res,res,&ptr); + return err!=0; + } +#endif + + //! Get the file or directory attributes with support for UTF-8 paths (Windows only). +#if cimg_OS==2 + inline DWORD win_getfileattributes(const char *const path) { + DWORD res = GetFileAttributesA(path); + if (res==INVALID_FILE_ATTRIBUTES) { + // Try alternative method, with wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (err) { + CImg wpath((unsigned int)err); + if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err)) res = GetFileAttributesW(wpath); + } + } + return res; + } +#endif + + //! Get/set path to the Program Files/ directory (Windows only). + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the program files. + **/ +#if cimg_OS==2 + inline const char* win_programfiles_path(const char *const user_path=0, const bool reinit_path=false) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(MAX_PATH); + *s_path = 0; + // Note: in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler). +#if !defined(__INTEL_COMPILER) + if (!SHGetSpecialFolderPathA(0,s_path,0x0026,false)) { + const char *const pfPath = std::getenv("PROGRAMFILES"); + if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH - 1); + else std::strcpy(s_path,"C:\\PROGRA~1"); + } +#else + std::strcpy(s_path,"C:\\PROGRA~1"); +#endif + } + cimg::mutex(7,0); + return s_path; + } +#endif + + //! Get/set path to the \c curl binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c curl binary. + **/ + inline const char *curl_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("curl.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\curl.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./curl"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c dcraw binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c dcraw binary. + **/ + inline const char *dcraw_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("dcraw.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\dcraw.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./dcraw"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the custom's \c custom binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c custom binary. + **/ + inline const char *custom_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("custom.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\custom.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"custom.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./custom"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"custom"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the GraphicsMagick's \c gm binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gm binary. + **/ + inline const char* graphicsmagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gm.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\gm.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gm"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gunzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gunzip binary. + **/ + inline const char *gunzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gunzip.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\gunzip.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gunzip"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gzip binary. + **/ + inline const char *gzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("gzip.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\gzip.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gzip"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the ImageMagick's \c convert binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c convert binary. + **/ + inline const char* imagemagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("magick.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + for (int l = 0; l<2 && !path_found; ++l) { + const char *const s_exe = l?"convert":"magick"; + cimg_snprintf(s_path,s_path._width,".\\%s.exe",s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",pf_path,k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\%s.exe",k,s_exe); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) cimg_snprintf(s_path,s_path._width,"%s.exe",s_exe); + } +#else + std::strcpy(s_path,"./magick"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + if (!path_found) { + std::strcpy(s_path,"./convert"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"convert"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the Medcon's \c medcon binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c medcon binary. + **/ + inline const char* medcon_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("medcon.exe",s_path,s_path._width)) path_found = true; + const char *const pf_path = win_programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\medcon.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.bat",pf_path); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.exe",pf_path); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + std::strcpy(s_path,"C:\\XMedCon\\bin\\medcon.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./medcon"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to store temporary files. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path where temporary files can be saved. + **/ + inline const char* temporary_path(const char *const user_path, const bool reinit_path) { +#define _cimg_test_temporary_path(p) \ + if (!path_found) { \ + cimg_snprintf(s_path,s_path._width,"%s",p); \ + cimg_snprintf(tmp,tmp._width,"%s%c%s",s_path.data(),cimg_file_separator,filename_tmp._data); \ + if ((file=cimg::std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } \ + } + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + CImg tmp(1024), filename_tmp(256); + std::FILE *file = 0; + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.tmp",cimg::filenamerand()); + char *tmpPath = std::getenv("TMP"); + if (!tmpPath) { tmpPath = std::getenv("TEMP"); winformat_string(tmpPath); } + if (tmpPath) _cimg_test_temporary_path(tmpPath); +#if cimg_OS==2 + _cimg_test_temporary_path("C:\\WINNT\\Temp"); + _cimg_test_temporary_path("C:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("C:\\Temp"); + _cimg_test_temporary_path("C:"); + _cimg_test_temporary_path("D:\\WINNT\\Temp"); + _cimg_test_temporary_path("D:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("D:\\Temp"); + _cimg_test_temporary_path("D:"); +#else + _cimg_test_temporary_path("/tmp"); + _cimg_test_temporary_path("/var/tmp"); +#endif + if (!path_found) { + *s_path = 0; + std::strncpy(tmp,filename_tmp,tmp._width - 1); + if ((file=cimg::std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } + } + if (!path_found) { + cimg::mutex(7,0); + throw CImgIOException("cimg::temporary_path(): Failed to locate path for writing temporary files.\n"); + } + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c wget binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c wget binary. + **/ + inline const char *wget_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (win_searchpath("wget.exe",s_path,s_path._width)) path_found = true; + if (!path_found) { + std::strcpy(s_path,".\\wget.exe"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./wget"); + if ((file=cimg::std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + + // [internal] Sorting function, used by cimg::files(). + inline int _sort_files(const void* a, const void* b) { + const CImg &sa = *(CImg*)a, &sb = *(CImg*)b; + return std::strcmp(sa._data,sb._data); + } + + //! Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str) { + if (!filename) { if (str) *str = 0; return 0; } + const unsigned int siz = (unsigned int)std::strlen(filename); + CImg format(16), body(siz + 32); + const char *const ext = cimg::split_filename(filename,body); + if (*ext) cimg_snprintf(format,format._width,"%%s_%%.%ud.%%s",digits); + else cimg_snprintf(format,format._width,"%%s_%%.%ud",digits); + cimg_snprintf(str,1024,format._data,body._data,number,ext); + return str; + } + + //! Return list of files/directories in specified directory. + /** + \param path Path to the directory. Set to 0 for current directory. + \param is_pattern Tell if specified path has a matching pattern in it. + \param mode Output type, can be primary { 0=files only | 1=folders only | 2=files + folders }. + \param include_path Tell if \c path must be included in resulting filenames. + \return A list of filenames. + **/ + inline CImgList files(const char *const path, const bool is_pattern=false, + const unsigned int mode=2, const bool include_path=false) { + if (!path || !*path) return files("*",true,mode,include_path); + CImgList res; + + // If path is a valid folder name, ignore argument 'is_pattern'. + const bool _is_pattern = is_pattern && !cimg::is_directory(path); + bool is_root = false, is_current = false; + cimg::unused(is_root,is_current); + + // Clean format of input path. + CImg pattern, _path = CImg::string(path); +#if cimg_OS==2 + for (char *ps = _path; *ps; ++ps) if (*ps=='\\') *ps='/'; +#endif + char *pd = _path; + for (char *ps = pd; *ps; ++ps) { if (*ps!='/' || *ps!=*(ps+1)) *(pd++) = *ps; } + *pd = 0; + unsigned int lp = (unsigned int)std::strlen(_path); + if (!_is_pattern && lp && _path[lp - 1]=='/') { + _path[lp - 1] = 0; --lp; +#if cimg_OS!=2 + is_root = !*_path; +#endif + } + + // Separate folder path and matching pattern. + if (_is_pattern) { + const unsigned int bpos = (unsigned int)(cimg::basename(_path,'/') - _path.data()); + CImg::string(_path).move_to(pattern); + if (bpos) { + _path[bpos - 1] = 0; // End 'path' at last slash +#if cimg_OS!=2 + is_root = !*_path; +#endif + } else { // No path to folder specified, assuming current folder + is_current = true; *_path = 0; + } + lp = (unsigned int)std::strlen(_path); + } + + // Windows version. +#if cimg_OS==2 + if (!_is_pattern) { + pattern.assign(lp + 3); + std::memcpy(pattern,_path,lp); + pattern[lp] = '/'; pattern[lp + 1] = '*'; pattern[lp + 2] = 0; + } + WIN32_FIND_DATAA file_data; + const HANDLE dir = FindFirstFileA(pattern.data(),&file_data); + if (dir==INVALID_HANDLE_VALUE) return CImgList::const_empty(); + do { + const char *const filename = file_data.cFileName; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode>=2) { + if (include_path) { + CImg full_filename((lp?lp+1:0) + lf + 1); + if (lp) { std::memcpy(full_filename,_path,lp); full_filename[lp] = '/'; } + std::memcpy(full_filename._data + (lp?lp + 1:0),filename,lf + 1); + full_filename.move_to(res); + } else CImg(filename,lf + 1).move_to(res); + } + } + } while (FindNextFileA(dir,&file_data)); + FindClose(dir); + + // Unix version (posix). +#elif cimg_OS == 1 + DIR *const dir = opendir(is_root?"/":is_current?".":_path.data()); + if (!dir) return CImgList::const_empty(); + struct dirent *ent; + while ((ent=readdir(dir))!=0) { + const char *const filename = ent->d_name; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + CImg full_filename(lp + lf + 2); + + if (!is_current) { + full_filename.assign(lp + lf + 2); + if (lp) std::memcpy(full_filename,_path,lp); + full_filename[lp] = '/'; + std::memcpy(full_filename._data + lp + 1,filename,lf + 1); + } else full_filename.assign(filename,lf + 1); + + struct stat st; + if (stat(full_filename,&st)==-1) continue; + const bool is_directory = (st.st_mode & S_IFDIR)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode==2) { + if (include_path) { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + full_filename.move_to(res); + } else { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + CImg(filename,lf + 1).move_to(res); + } + } + } + } + closedir(dir); +#endif + + // Sort resulting list by lexicographic order. + if (res._width>=2) std::qsort(res._data,res._width,sizeof(CImg),_sort_files); + + return res; + } + + //! Try to guess format from an image file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + \return C-string containing the guessed file format, or \c 0 if nothing has been guessed. + **/ + inline const char *ftype(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::ftype(): Specified filename is (null)."); + static const char + *const _pnm = "pnm", + *const _pfm = "pfm", + *const _bmp = "bmp", + *const _gif = "gif", + *const _jpg = "jpg", + *const _off = "off", + *const _pan = "pan", + *const _png = "png", + *const _tif = "tif", + *const _inr = "inr", + *const _dcm = "dcm"; + const char *f_type = 0; + CImg header; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + header._load_raw(file,filename,512,1,1,1,false,false,0); + const unsigned char *const uheader = (unsigned char*)header._data; + if (!std::strncmp(header,"OFF\n",4)) f_type = _off; // OFF + else if (!std::strncmp(header,"#INRIMAGE",9)) // INRIMAGE + f_type = _inr; + else if (!std::strncmp(header,"PANDORE",7)) // PANDORE + f_type = _pan; + else if (!std::strncmp(header.data() + 128,"DICM",4)) // DICOM + f_type = _dcm; + else if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) // JPEG + f_type = _jpg; + else if (header[0]=='B' && header[1]=='M') // BMP + f_type = _bmp; + else if (header[0]=='G' && header[1]=='I' && header[2]=='F' && header[3]=='8' && header[5]=='a' && + (header[4]=='7' || header[4]=='9')) // GIF + f_type = _gif; + else if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 && + uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) // PNG + f_type = _png; + else if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) // TIFF + f_type = _tif; + else { // PNM or PFM + CImgList _header = header.get_split(CImg::vector('\n'),0,false); + cimglist_for(_header,l) { + if (_header(l,0)=='#') continue; + if (_header[l]._width==2 && _header(l,0)=='P') { + const char c = _header(l,1); + if (c=='f' || c=='F') { f_type = _pfm; break; } + if (c>='1' && c<='9') { f_type = _pnm; break; } + } + f_type = 0; break; + } + } + } catch (CImgIOException&) { } + cimg::exception_mode(omode); + return f_type; + } + + //! Load file from network as a local temporary file. + /** + \param url URL of the filename, as a C-string. + \param[out] filename_local C-string containing the path to a local copy of \c filename. + \param timeout Maximum time (in seconds) authorized for downloading the file from the URL. + \param try_fallback When using libcurl, tells using system calls as fallbacks in case of libcurl failure. + \param referer Referer used, as a C-string. + \return Value of \c filename_local. + \note Use the \c libcurl library, or the external binaries \c wget or \c curl to perform the download. + **/ + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout, const bool try_fallback, + const char *const referer) { + if (!url) + throw CImgArgumentException("cimg::load_network(): Specified URL is (null)."); + if (!filename_local) + throw CImgArgumentException("cimg::load_network(): Specified destination string is (null)."); + if (!network_mode()) + throw CImgIOException("cimg::load_network(): Loading files from network is disabled."); + + const char *const __ext = cimg::split_filename(url), *const _ext = (*__ext && __ext>url)?__ext - 1:__ext; + CImg ext = CImg::string(_ext); + std::FILE *file = 0; + *filename_local = 0; + if (ext._width>16 || !cimg::strncasecmp(ext,"cgi",3)) *ext = 0; + else cimg::strwindows_reserved(ext); + do { + cimg_snprintf(filename_local,256,"%s%c%s%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext._data); + if ((file=cimg::std_fopen(filename_local,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_curl + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + CURL *curl = 0; + CURLcode res; + curl = curl_easy_init(); + if (curl) { + file = cimg::fopen(filename_local,"wb"); + curl_easy_setopt(curl,CURLOPT_URL,url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,0); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,file); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0L); + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L); + if (timeout) curl_easy_setopt(curl,CURLOPT_TIMEOUT,(long)timeout); + if (std::strchr(url,'?')) curl_easy_setopt(curl,CURLOPT_HTTPGET,1L); + if (referer) curl_easy_setopt(curl,CURLOPT_REFERER,referer); + res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + cimg::fseek(file,0,SEEK_END); // Check if file size is 0 + const cimg_ulong siz = cimg::ftell(file); + cimg::fclose(file); + if (siz>0 && res==CURLE_OK) { + cimg::exception_mode(omode); + return filename_local; + } else std::remove(filename_local); + } + } catch (...) { } + cimg::exception_mode(omode); + if (!try_fallback) throw CImgIOException("cimg::load_network(): Failed to load file '%s' with libcurl.",url); +#endif + + CImg command((unsigned int)std::strlen(url) + 64); + cimg::unused(try_fallback); + + // Try with 'curl' first. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" -e %s -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,timeout,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),timeout,filename_local, + CImg::string(url)._system_strescape().data()); + } else { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" -e %s -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),filename_local, + CImg::string(url)._system_strescape().data()); + } + cimg::system(command, cimg::curl_path()); + + if (!(file=cimg::std_fopen(filename_local,"rb"))) { + + // Try with 'wget' otherwise. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" --referer=%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,timeout,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),timeout,filename_local, + CImg::string(url)._system_strescape().data()); + } else { + if (referer) + cimg_snprintf(command,command._width,"\"%s\" --referer=%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,filename_local, + CImg::string(url)._system_strescape().data()); + else + cimg_snprintf(command,command._width,"\"%s\" -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),filename_local, + CImg::string(url)._system_strescape().data()); + } + cimg::system(command, cimg::wget_path()); + + if (!(file=cimg::std_fopen(filename_local,"rb"))) + throw CImgIOException("cimg::load_network(): Failed to load file '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + + // Try gunzip it. + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(filename_local,command); + cimg_snprintf(command,command._width,"\"%s\" --quiet \"%s.gz\"", + gunzip_path(),filename_local); + cimg::system(command, gunzip_path()); + file = cimg::std_fopen(filename_local,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(command,filename_local); + file = cimg::std_fopen(filename_local,"rb"); + } + } + cimg::fseek(file,0,SEEK_END); // Check if file size is 0 + if (std::ftell(file)<=0) + throw CImgIOException("cimg::load_network(): Failed to load URL '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + return filename_local; + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_uint64 tictoc(const bool is_tic) { + cimg::mutex(2); + static CImg times(64); + static unsigned int pos = 0; + const cimg_uint64 t1 = cimg::time(); + if (is_tic) { + // Tic + times[pos++] = t1; + if (pos>=times._width) + throw CImgArgumentException("cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'."); + cimg::mutex(2,0); + return t1; + } + + // Toc + if (!pos) + throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made."); + const cimg_uint64 + t0 = times[--pos], + dt = t1>=t0?(t1 - t0):cimg::type::max(); + const unsigned int + edays = (unsigned int)(dt/86400000.), + ehours = (unsigned int)((dt - edays*86400000.)/3600000.), + emin = (unsigned int)((dt - edays*86400000. - ehours*3600000.)/60000.), + esec = (unsigned int)((dt - edays*86400000. - ehours*3600000. - emin*60000.)/1000.), + ems = (unsigned int)(dt - edays*86400000. - ehours*3600000. - emin*60000. - esec*1000.); + if (!edays && !ehours && !emin && !esec) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ems,cimg::t_normal); + else { + if (!edays && !ehours && !emin) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",esec,ems,cimg::t_normal); + else { + if (!edays && !ehours) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",emin,esec,ems,cimg::t_normal); + else{ + if (!edays) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ehours,emin,esec,ems,cimg::t_normal); + else{ + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u days %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",edays,ehours,emin,esec,ems,cimg::t_normal); + } + } + } + } + cimg::mutex(2,0); + return dt; + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size) { + static CImg res(256); + cimg::mutex(5); + if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",(unsigned long)size,size>1?"s":""); + else if (size<1024*1024LU) { const float nsize = size/1024.f; cimg_snprintf(res,res._width,"%.1f Kio",nsize); } + else if (size<1024*1024*1024LU) { + const float nsize = size/(1024*1024.f); cimg_snprintf(res,res._width,"%.1f Mio",nsize); + } else { const float nsize = size/(1024*1024*1024.f); cimg_snprintf(res,res._width,"%.1f Gio",nsize); } + cimg::mutex(5,0); + return res; + } + + //! Display a simple dialog box, and wait for the user's response. + /** + \param title Title of the dialog window. + \param msg Main message displayed inside the dialog window. + \param button1_label Label of the 1st button. + \param button2_label Label of the 2nd button (\c 0 to hide button). + \param button3_label Label of the 3rd button (\c 0 to hide button). + \param button4_label Label of the 4th button (\c 0 to hide button). + \param button5_label Label of the 5th button (\c 0 to hide button). + \param button6_label Label of the 6th button (\c 0 to hide button). + \param logo Image logo displayed at the left of the main message. + \param is_centered Tells if the dialog window must be centered on the screen. + \return Index of clicked button (from \c 0 to \c 5), or \c -1 if the dialog window has been closed by the user. + \note + - Up to 6 buttons can be defined in the dialog window. + - The function returns when a user clicked one of the button or closed the dialog window. + - If a button text is set to 0, the corresponding button (and the following) will not appear in the dialog box. + At least one button must be specified. + **/ + template + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const CImg& logo, const bool is_centered=false) { +#if cimg_display==0 + cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + logo._data,is_centered); + throw CImgIOException("cimg::dialog(): No display available."); +#else + static const unsigned char + black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 }; + + // Create buttons and canvas graphics + CImgList buttons, cbuttons, sbuttons; + if (button1_label) { + CImg().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons); + if (button2_label) { + CImg().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons); + if (button3_label) { + CImg().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons); + if (button4_label) { + CImg().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons); + if (button5_label) { + CImg().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons); + if (button6_label) { + CImg().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons); + }}}}}} + if (!buttons._width) + throw CImgArgumentException("cimg::dialog(): No buttons have been defined."); + cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3); + + unsigned int bw = 0, bh = 0; + cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); } + bw+=8; bh+=8; + if (bw<64) bw = 64; + if (bw>128) bw = 128; + if (bh<24) bh = 24; + if (bh>48) bh = 48; + + CImg button(bw,bh,1,3); + button.draw_rectangle(0,0,bw - 1,bh - 1,gray); + button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white); + button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black); + button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2); + CImg sbutton(bw,bh,1,3); + sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray); + sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black); + sbutton.draw_line(bw - 1,bh - 1,0,bh - 1,black).draw_line(0,bh - 1,0,0,black); + sbutton.draw_line(1,1,bw - 2,1,white).draw_line(1,bh - 2,1,1,white); + sbutton.draw_line(bw - 2,1,bw - 2,bh - 2,black).draw_line(bw - 2,bh - 2,1,bh - 2,black); + sbutton.draw_line(2,bh - 3,bw - 3,bh - 3,gray2).draw_line(bw - 3,bh - 3,bw - 3,2,gray2); + sbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true). + draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + sbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false). + draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + CImg cbutton(bw,bh,1,3); + cbutton.draw_rectangle(0,0,bw - 1,bh - 1,black).draw_rectangle(1,1,bw - 2,bh - 2,gray2). + draw_rectangle(2,2,bw - 3,bh - 3,gray); + cbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true). + draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + cbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false). + draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + + cimglist_for(buttons,ll) { + CImg(cbutton). + draw_image(1 + (bw -buttons[ll].width())/2,1 + (bh - buttons[ll].height())/2,buttons[ll]). + move_to(cbuttons); + CImg(sbutton). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(sbuttons); + CImg(button). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(buttons[ll]); + } + + CImg canvas; + if (msg) + ((CImg().draw_text(0,0,"%s",gray,0,1,13,msg)*=-1)+=200).resize(-100,-100,1,3).move_to(canvas); + + const unsigned int + bwall = (buttons._width - 1)*(12 + bw) + bw, + w = cimg::max(196U,36 + logo._width + canvas._width,24 + bwall), + h = cimg::max(96U,36 + canvas._height + bh,36 + logo._height + bh), + lx = 12 + (canvas._data?0:((w - 24 - logo._width)/2)), + ly = (h - 12 - bh - logo._height)/2, + tx = lx + logo._width + 12, + ty = (h - 12 - bh - canvas._height)/2, + bx = (w - bwall)/2, + by = h - 12 - bh; + + if (canvas._data) + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black). + draw_image(tx,ty,canvas); + else + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black); + if (logo._data) canvas.draw_image(lx,ly,logo); + + unsigned int xbuttons[6] = { 0 }; + cimglist_for(buttons,lll) { + xbuttons[lll] = bx + (bw + 12)*lll; + canvas.draw_image(xbuttons[lll],by,buttons[lll]); + } + + // Open window and enter events loop + CImgDisplay disp(canvas,title?title:" ",0,false,is_centered?true:false); + if (is_centered) disp.move((CImgDisplay::screen_width() - disp.width())/2, + (CImgDisplay::screen_height() - disp.height())/2); + bool stop_flag = false, refresh = false; + int oselected = -1, oclicked = -1, selected = -1, clicked = -1; + while (!disp.is_closed() && !stop_flag) { + if (refresh) { + if (clicked>=0) + CImg(canvas).draw_image(xbuttons[clicked],by,cbuttons[clicked]).display(disp); + else { + if (selected>=0) + CImg(canvas).draw_image(xbuttons[selected],by,sbuttons[selected]).display(disp); + else canvas.display(disp); + } + refresh = false; + } + disp.wait(15); + if (disp.is_resized()) disp.resize(disp,false); + + if (disp.button()&1) { + oclicked = clicked; + clicked = -1; + cimglist_for(buttons,l) + if (disp.mouse_y()>=(int)by && disp.mouse_y()<(int)(by + bh) && + disp.mouse_x()>=(int)xbuttons[l] && disp.mouse_x()<(int)(xbuttons[l] + bw)) { + clicked = selected = l; + refresh = true; + } + if (clicked!=oclicked) refresh = true; + } else if (clicked>=0) stop_flag = true; + + if (disp.key()) { + oselected = selected; + switch (disp.key()) { + case cimg::keyESC : selected = -1; stop_flag = true; break; + case cimg::keyENTER : if (selected<0) selected = 0; stop_flag = true; break; + case cimg::keyTAB : + case cimg::keyARROWRIGHT : + case cimg::keyARROWDOWN : selected = (selected + 1)%buttons.width(); break; + case cimg::keyARROWLEFT : + case cimg::keyARROWUP : selected = (selected + buttons.width() - 1)%buttons.width(); break; + } + disp.set_key(); + if (selected!=oselected) refresh = true; + } + } + if (!disp) selected = -1; + return selected; +#endif + } + + //! Display a simple dialog box, and wait for the user's response \specialization. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const bool is_centered) { + return dialog(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + CImg::_logo40x38(),is_centered); + } + + //! Evaluate math expression. + /** + \param expression C-string describing the formula to evaluate. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \return Result of the formula evaluation. + \note Set \c expression to \c 0 to keep evaluating the last specified \c expression. + \par Example + \code + const double + res1 = cimg::eval("cos(x)^2 + sin(y)^2",2,2), // will return '1' + res2 = cimg::eval(0,1,1); // will return '1' too + \endcode + **/ + inline double eval(const char *const expression, const double x, const double y, const double z, const double c) { + static const CImg empty; + return empty.eval(expression,x,y,z,c); + } + + template + inline CImg::type> eval(const char *const expression, const CImg& xyzc) { + static const CImg empty; + return empty.eval(expression,xyzc); + } + + } // namespace cimg { ... +} // namespace cimg_library { ... + +//! Short alias name. +namespace cil = cimg_library_suffixed; + +#ifdef _cimg_redefine_False +#define False 0 +#endif +#ifdef _cimg_redefine_True +#define True 1 +#endif +#ifdef _cimg_redefine_Status +#define Status int +#endif +#ifdef _cimg_redefine_Success +#define Success 0 +#endif +#ifdef _cimg_redefine_min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_PI +#define PI 3.141592653589793238462643383 +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif + +// Local Variables: +// mode: c++ +// End: diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/demo.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/demo.h new file mode 100644 index 0000000..0aafc91 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/demo.h @@ -0,0 +1,136 @@ +/* + + */ + +#ifndef DEMO_H_ +#define DEMO_H_ +//ڴ˴ͷļ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" +#include "math.h" + +#include "demo_define.h" +#include "tool.h" +#include "inital_alg_params_ynr.h" +#include "inital_alg_params_gic.h" +#include "inital_alg_params_lsc.h" +#include "inital_alg_params_lsc2.h" +#include "inital_alg_params_rk_shapren_HW.h" +#include "inital_alg_params_rk_edgefilter.h" + +#include "initial_alg_params_bayernr.h" + +#include "inital_alg_params_rkuvnr.h" +#include "inital_alg_params_rk_cnr.h" + +#include "inital_alg_params_mfnr.h" +#include "rk_aiq_awb_algo_v200.h" +#define FILE_RAW_EXT ".raw" +#define FILE_YUV_EXT ".yuv" +#define FILE_DAT_EXT ".dat" + +typedef enum YUV_FILE_FMT +{ + F_YUV_420SP = 0x00, + F_YUV_420P = 0x01, + F_YUV_422I = 0x02, + F_YUV_422SP = 0x03, + F_YUV_422P = 0x04, + F_YUV_444I = 0x05, + + F_YUV_MAX = 0x10, +}YUV_FILE_FMT_t; + +typedef enum INPUT_FILE_FMT +{ + F_IN_FMT_RAW = 0x00, + F_IN_FMT_YUV, + + + F_IN_FMT_MAX = 0x10, +}INPUT_FILE_FMT_t; + + + +//˴ +typedef struct tag_config_com +{ + int exp_info_en ; + int framenum ; + int rawwid ; + int rawhgt ; + int rawbit ; + int bayerfmt ; + int yuvbit ; + int yuvfmt ; +}tag_config_com; + +typedef struct tag_config_txt +{ + tag_config_com config_com; + + int framecnt ; + int iso ; + int exptime[3] ; + int expgain[3] ; + int rgain ; + int bgain ; + int grgain ; + int gbgain ; + int dGain ; + int lux ; +}tag_config_txt; + +typedef struct tag_ST_DEMO_INPUT_PARAMS +{ + int width; //rawͼ + int height; //rawͼ + int bayerPattern; //bayer patternʽ:0--BGGR,1--GBRG,2--GRBG,3--RGGB + int yuvFmt; //yuv file ʽ: YUV_FILE_FMT_t + int bitValue; //rawλ + int hdr_framenum; + float expGain[MAX_HDR_FRM_NUM]; // + float expTime[MAX_HDR_FRM_NUM]; //عʱ + int rGain; //wb rgain + int bGain; //wb bgain + int grGain; //wb grgain + int gbGain; //wb gbgain + int dGain; //wb gbgain + int fileFmt; //input file format:INPUT_FILE_FMT_t + int width_full; //rawͼ + int height_full; //rawͼ + int crop_width; + int crop_height; + int crop_xoffset; + int crop_yoffset; + + char pathFileCfg[256];//configļ· + char pathRawData[256];//rawͼ· + char nameRawData[256];//rawͼ + char pathExpInfo[256];//exp_infoļ· + char pathReslut[256];//ļ· + char suffix[256]; // ļ׺ַ + char pathRtlin[256]; //rtl in path + int skip_num; + int frame_end; + + int hdr_proc_mode; + int out_mode; + + + char dbgFlg[1024]; // must > ISP_CAP_MAX + int config_full; + + int exp_info_en; + int file_info_en; + FILE *fp_exp_info; +}ST_DEMO_INPUT_PARAMS; + + + +//˴ + + + +#endif // DEMO_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/demo_define.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/demo_define.h new file mode 100644 index 0000000..da7d26e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/demo_define.h @@ -0,0 +1,44 @@ +/* + + */ + +#ifndef DEFINE_H_ +#define DEFINE_H_ +//ڴ˴ͷļ + + + +#define S7_EDGE 1 +#define GZ 2 +#define DVR 3 +/* +#define ISP_BAYER_NR 1 +#define ISP_DPC 2 +#define ISP_BLC 3 +#define ISP_STAT_3A 4 +#define ISP_LSC 5 +#define ISP_AWBG 6 +#define ISP_VHDM 7 +#define ISP_GAMMA 8 +#define ISP_CSM 9 +#define ISP_DRC 10 +#define ISP_RGB2YUV 11 +#define ISP_LCE 12 +#define ISP_Y_NR 13 +#define ISP_SHARPEN 14 +#define ISP_SCALING 15 +#define ISP_GIC 16 +#define ISP_UV_NR 17 +#define ISP_HDR_MERGE 18 +#define ISP_HDR_TMO 19 +#define ISP_DPN 20 +#define ISP_CTK 21 +#define ISP_WDR 22 +*/ +#define SAVE_RESULT 1 + + +//#define GET_LSC_CALIBRATION_DATA //ȡlens shadingУ궨 + + +#endif // DEFINE_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/amdgpu_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/amdgpu_drm.h new file mode 100644 index 0000000..4fe35d6 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/amdgpu_drm.h @@ -0,0 +1,1067 @@ +/* amdgpu_drm.h -- Public header for the amdgpu driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#ifndef __AMDGPU_DRM_H__ +#define __AMDGPU_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_AMDGPU_GEM_CREATE 0x00 +#define DRM_AMDGPU_GEM_MMAP 0x01 +#define DRM_AMDGPU_CTX 0x02 +#define DRM_AMDGPU_BO_LIST 0x03 +#define DRM_AMDGPU_CS 0x04 +#define DRM_AMDGPU_INFO 0x05 +#define DRM_AMDGPU_GEM_METADATA 0x06 +#define DRM_AMDGPU_GEM_WAIT_IDLE 0x07 +#define DRM_AMDGPU_GEM_VA 0x08 +#define DRM_AMDGPU_WAIT_CS 0x09 +#define DRM_AMDGPU_GEM_OP 0x10 +#define DRM_AMDGPU_GEM_USERPTR 0x11 +#define DRM_AMDGPU_WAIT_FENCES 0x12 +#define DRM_AMDGPU_VM 0x13 +#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14 +#define DRM_AMDGPU_SCHED 0x15 + +#define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) +#define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) +#define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx) +#define DRM_IOCTL_AMDGPU_BO_LIST DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_BO_LIST, union drm_amdgpu_bo_list) +#define DRM_IOCTL_AMDGPU_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CS, union drm_amdgpu_cs) +#define DRM_IOCTL_AMDGPU_INFO DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_INFO, struct drm_amdgpu_info) +#define DRM_IOCTL_AMDGPU_GEM_METADATA DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, struct drm_amdgpu_gem_metadata) +#define DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_WAIT_IDLE, union drm_amdgpu_gem_wait_idle) +#define DRM_IOCTL_AMDGPU_GEM_VA DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_VA, struct drm_amdgpu_gem_va) +#define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs) +#define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op) +#define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) +#define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences) +#define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm) +#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle) +#define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched) + +/** + * DOC: memory domains + * + * %AMDGPU_GEM_DOMAIN_CPU System memory that is not GPU accessible. + * Memory in this pool could be swapped out to disk if there is pressure. + * + * %AMDGPU_GEM_DOMAIN_GTT GPU accessible system memory, mapped into the + * GPU's virtual address space via gart. Gart memory linearizes non-contiguous + * pages of system memory, allows GPU access system memory in a linezrized + * fashion. + * + * %AMDGPU_GEM_DOMAIN_VRAM Local video memory. For APUs, it is memory + * carved out by the BIOS. + * + * %AMDGPU_GEM_DOMAIN_GDS Global on-chip data storage used to share data + * across shader threads. + * + * %AMDGPU_GEM_DOMAIN_GWS Global wave sync, used to synchronize the + * execution of all the waves on a device. + * + * %AMDGPU_GEM_DOMAIN_OA Ordered append, used by 3D or Compute engines + * for appending data. + */ +#define AMDGPU_GEM_DOMAIN_CPU 0x1 +#define AMDGPU_GEM_DOMAIN_GTT 0x2 +#define AMDGPU_GEM_DOMAIN_VRAM 0x4 +#define AMDGPU_GEM_DOMAIN_GDS 0x8 +#define AMDGPU_GEM_DOMAIN_GWS 0x10 +#define AMDGPU_GEM_DOMAIN_OA 0x20 +#define AMDGPU_GEM_DOMAIN_MASK (AMDGPU_GEM_DOMAIN_CPU | \ + AMDGPU_GEM_DOMAIN_GTT | \ + AMDGPU_GEM_DOMAIN_VRAM | \ + AMDGPU_GEM_DOMAIN_GDS | \ + AMDGPU_GEM_DOMAIN_GWS | \ + AMDGPU_GEM_DOMAIN_OA) + +/* Flag that CPU access will be required for the case of VRAM domain */ +#define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0) +/* Flag that CPU access will not work, this VRAM domain is invisible */ +#define AMDGPU_GEM_CREATE_NO_CPU_ACCESS (1 << 1) +/* Flag that USWC attributes should be used for GTT */ +#define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2) +/* Flag that the memory should be in VRAM and cleared */ +#define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3) +/* Flag that create shadow bo(GTT) while allocating vram bo */ +#define AMDGPU_GEM_CREATE_SHADOW (1 << 4) +/* Flag that allocating the BO should use linear VRAM */ +#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5) +/* Flag that BO is always valid in this VM */ +#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6) +/* Flag that BO sharing will be explicitly synchronized */ +#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7) +/* Flag that indicates allocating MQD gart on GFX9, where the mtype + * for the second page onward should be set to NC. + */ +#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8) +/* Flag that BO may contain sensitive data that must be wiped before + * releasing the memory + */ +#define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE (1 << 9) + +struct drm_amdgpu_gem_create_in { + /** the requested memory size */ + __u64 bo_size; + /** physical start_addr alignment in bytes for some HW requirements */ + __u64 alignment; + /** the requested memory domains */ + __u64 domains; + /** allocation flags */ + __u64 domain_flags; +}; + +struct drm_amdgpu_gem_create_out { + /** returned GEM object handle */ + __u32 handle; + __u32 _pad; +}; + +union drm_amdgpu_gem_create { + struct drm_amdgpu_gem_create_in in; + struct drm_amdgpu_gem_create_out out; +}; + +/** Opcode to create new residency list. */ +#define AMDGPU_BO_LIST_OP_CREATE 0 +/** Opcode to destroy previously created residency list */ +#define AMDGPU_BO_LIST_OP_DESTROY 1 +/** Opcode to update resource information in the list */ +#define AMDGPU_BO_LIST_OP_UPDATE 2 + +struct drm_amdgpu_bo_list_in { + /** Type of operation */ + __u32 operation; + /** Handle of list or 0 if we want to create one */ + __u32 list_handle; + /** Number of BOs in list */ + __u32 bo_number; + /** Size of each element describing BO */ + __u32 bo_info_size; + /** Pointer to array describing BOs */ + __u64 bo_info_ptr; +}; + +struct drm_amdgpu_bo_list_entry { + /** Handle of BO */ + __u32 bo_handle; + /** New (if specified) BO priority to be used during migration */ + __u32 bo_priority; +}; + +struct drm_amdgpu_bo_list_out { + /** Handle of resource list */ + __u32 list_handle; + __u32 _pad; +}; + +union drm_amdgpu_bo_list { + struct drm_amdgpu_bo_list_in in; + struct drm_amdgpu_bo_list_out out; +}; + +/* context related */ +#define AMDGPU_CTX_OP_ALLOC_CTX 1 +#define AMDGPU_CTX_OP_FREE_CTX 2 +#define AMDGPU_CTX_OP_QUERY_STATE 3 +#define AMDGPU_CTX_OP_QUERY_STATE2 4 + +/* GPU reset status */ +#define AMDGPU_CTX_NO_RESET 0 +/* this the context caused it */ +#define AMDGPU_CTX_GUILTY_RESET 1 +/* some other context caused it */ +#define AMDGPU_CTX_INNOCENT_RESET 2 +/* unknown cause */ +#define AMDGPU_CTX_UNKNOWN_RESET 3 + +/* indicate gpu reset occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_RESET (1<<0) +/* indicate vram lost occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1) +/* indicate some job from this context once cause gpu hang */ +#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY (1<<2) +/* indicate some errors are detected by RAS */ +#define AMDGPU_CTX_QUERY2_FLAGS_RAS_CE (1<<3) +#define AMDGPU_CTX_QUERY2_FLAGS_RAS_UE (1<<4) + +/* Context priority level */ +#define AMDGPU_CTX_PRIORITY_UNSET -2048 +#define AMDGPU_CTX_PRIORITY_VERY_LOW -1023 +#define AMDGPU_CTX_PRIORITY_LOW -512 +#define AMDGPU_CTX_PRIORITY_NORMAL 0 +/* + * When used in struct drm_amdgpu_ctx_in, a priority above NORMAL requires + * CAP_SYS_NICE or DRM_MASTER +*/ +#define AMDGPU_CTX_PRIORITY_HIGH 512 +#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023 + +struct drm_amdgpu_ctx_in { + /** AMDGPU_CTX_OP_* */ + __u32 op; + /** For future use, no flags defined so far */ + __u32 flags; + __u32 ctx_id; + /** AMDGPU_CTX_PRIORITY_* */ + __s32 priority; +}; + +union drm_amdgpu_ctx_out { + struct { + __u32 ctx_id; + __u32 _pad; + } alloc; + + struct { + /** For future use, no flags defined so far */ + __u64 flags; + /** Number of resets caused by this context so far. */ + __u32 hangs; + /** Reset status since the last call of the ioctl. */ + __u32 reset_status; + } state; +}; + +union drm_amdgpu_ctx { + struct drm_amdgpu_ctx_in in; + union drm_amdgpu_ctx_out out; +}; + +/* vm ioctl */ +#define AMDGPU_VM_OP_RESERVE_VMID 1 +#define AMDGPU_VM_OP_UNRESERVE_VMID 2 + +struct drm_amdgpu_vm_in { + /** AMDGPU_VM_OP_* */ + __u32 op; + __u32 flags; +}; + +struct drm_amdgpu_vm_out { + /** For future use, no flags defined so far */ + __u64 flags; +}; + +union drm_amdgpu_vm { + struct drm_amdgpu_vm_in in; + struct drm_amdgpu_vm_out out; +}; + +/* sched ioctl */ +#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE 1 +#define AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE 2 + +struct drm_amdgpu_sched_in { + /* AMDGPU_SCHED_OP_* */ + __u32 op; + __u32 fd; + /** AMDGPU_CTX_PRIORITY_* */ + __s32 priority; + __u32 ctx_id; +}; + +union drm_amdgpu_sched { + struct drm_amdgpu_sched_in in; +}; + +/* + * This is not a reliable API and you should expect it to fail for any + * number of reasons and have fallback path that do not use userptr to + * perform any operation. + */ +#define AMDGPU_GEM_USERPTR_READONLY (1 << 0) +#define AMDGPU_GEM_USERPTR_ANONONLY (1 << 1) +#define AMDGPU_GEM_USERPTR_VALIDATE (1 << 2) +#define AMDGPU_GEM_USERPTR_REGISTER (1 << 3) + +struct drm_amdgpu_gem_userptr { + __u64 addr; + __u64 size; + /* AMDGPU_GEM_USERPTR_* */ + __u32 flags; + /* Resulting GEM handle */ + __u32 handle; +}; + +/* SI-CI-VI: */ +/* same meaning as the GB_TILE_MODE and GL_MACRO_TILE_MODE fields */ +#define AMDGPU_TILING_ARRAY_MODE_SHIFT 0 +#define AMDGPU_TILING_ARRAY_MODE_MASK 0xf +#define AMDGPU_TILING_PIPE_CONFIG_SHIFT 4 +#define AMDGPU_TILING_PIPE_CONFIG_MASK 0x1f +#define AMDGPU_TILING_TILE_SPLIT_SHIFT 9 +#define AMDGPU_TILING_TILE_SPLIT_MASK 0x7 +#define AMDGPU_TILING_MICRO_TILE_MODE_SHIFT 12 +#define AMDGPU_TILING_MICRO_TILE_MODE_MASK 0x7 +#define AMDGPU_TILING_BANK_WIDTH_SHIFT 15 +#define AMDGPU_TILING_BANK_WIDTH_MASK 0x3 +#define AMDGPU_TILING_BANK_HEIGHT_SHIFT 17 +#define AMDGPU_TILING_BANK_HEIGHT_MASK 0x3 +#define AMDGPU_TILING_MACRO_TILE_ASPECT_SHIFT 19 +#define AMDGPU_TILING_MACRO_TILE_ASPECT_MASK 0x3 +#define AMDGPU_TILING_NUM_BANKS_SHIFT 21 +#define AMDGPU_TILING_NUM_BANKS_MASK 0x3 + +/* GFX9 and later: */ +#define AMDGPU_TILING_SWIZZLE_MODE_SHIFT 0 +#define AMDGPU_TILING_SWIZZLE_MODE_MASK 0x1f +#define AMDGPU_TILING_DCC_OFFSET_256B_SHIFT 5 +#define AMDGPU_TILING_DCC_OFFSET_256B_MASK 0xFFFFFF +#define AMDGPU_TILING_DCC_PITCH_MAX_SHIFT 29 +#define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43 +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1 + +/* Set/Get helpers for tiling flags. */ +#define AMDGPU_TILING_SET(field, value) \ + (((__u64)(value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT) +#define AMDGPU_TILING_GET(value, field) \ + (((__u64)(value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK) + +#define AMDGPU_GEM_METADATA_OP_SET_METADATA 1 +#define AMDGPU_GEM_METADATA_OP_GET_METADATA 2 + +/** The same structure is shared for input/output */ +struct drm_amdgpu_gem_metadata { + /** GEM Object handle */ + __u32 handle; + /** Do we want get or set metadata */ + __u32 op; + struct { + /** For future use, no flags defined so far */ + __u64 flags; + /** family specific tiling info */ + __u64 tiling_info; + __u32 data_size_bytes; + __u32 data[64]; + } data; +}; + +struct drm_amdgpu_gem_mmap_in { + /** the GEM object handle */ + __u32 handle; + __u32 _pad; +}; + +struct drm_amdgpu_gem_mmap_out { + /** mmap offset from the vma offset manager */ + __u64 addr_ptr; +}; + +union drm_amdgpu_gem_mmap { + struct drm_amdgpu_gem_mmap_in in; + struct drm_amdgpu_gem_mmap_out out; +}; + +struct drm_amdgpu_gem_wait_idle_in { + /** GEM object handle */ + __u32 handle; + /** For future use, no flags defined so far */ + __u32 flags; + /** Absolute timeout to wait */ + __u64 timeout; +}; + +struct drm_amdgpu_gem_wait_idle_out { + /** BO status: 0 - BO is idle, 1 - BO is busy */ + __u32 status; + /** Returned current memory domain */ + __u32 domain; +}; + +union drm_amdgpu_gem_wait_idle { + struct drm_amdgpu_gem_wait_idle_in in; + struct drm_amdgpu_gem_wait_idle_out out; +}; + +struct drm_amdgpu_wait_cs_in { + /* Command submission handle + * handle equals 0 means none to wait for + * handle equals ~0ull means wait for the latest sequence number + */ + __u64 handle; + /** Absolute timeout to wait */ + __u64 timeout; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; +}; + +struct drm_amdgpu_wait_cs_out { + /** CS status: 0 - CS completed, 1 - CS still busy */ + __u64 status; +}; + +union drm_amdgpu_wait_cs { + struct drm_amdgpu_wait_cs_in in; + struct drm_amdgpu_wait_cs_out out; +}; + +struct drm_amdgpu_fence { + __u32 ctx_id; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u64 seq_no; +}; + +struct drm_amdgpu_wait_fences_in { + /** This points to uint64_t * which points to fences */ + __u64 fences; + __u32 fence_count; + __u32 wait_all; + __u64 timeout_ns; +}; + +struct drm_amdgpu_wait_fences_out { + __u32 status; + __u32 first_signaled; +}; + +union drm_amdgpu_wait_fences { + struct drm_amdgpu_wait_fences_in in; + struct drm_amdgpu_wait_fences_out out; +}; + +#define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0 +#define AMDGPU_GEM_OP_SET_PLACEMENT 1 + +/* Sets or returns a value associated with a buffer. */ +struct drm_amdgpu_gem_op { + /** GEM object handle */ + __u32 handle; + /** AMDGPU_GEM_OP_* */ + __u32 op; + /** Input or return value */ + __u64 value; +}; + +#define AMDGPU_VA_OP_MAP 1 +#define AMDGPU_VA_OP_UNMAP 2 +#define AMDGPU_VA_OP_CLEAR 3 +#define AMDGPU_VA_OP_REPLACE 4 + +/* Delay the page table update till the next CS */ +#define AMDGPU_VM_DELAY_UPDATE (1 << 0) + +/* Mapping flags */ +/* readable mapping */ +#define AMDGPU_VM_PAGE_READABLE (1 << 1) +/* writable mapping */ +#define AMDGPU_VM_PAGE_WRITEABLE (1 << 2) +/* executable mapping, new for VI */ +#define AMDGPU_VM_PAGE_EXECUTABLE (1 << 3) +/* partially resident texture */ +#define AMDGPU_VM_PAGE_PRT (1 << 4) +/* MTYPE flags use bit 5 to 8 */ +#define AMDGPU_VM_MTYPE_MASK (0xf << 5) +/* Default MTYPE. Pre-AI must use this. Recommended for newer ASICs. */ +#define AMDGPU_VM_MTYPE_DEFAULT (0 << 5) +/* Use NC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_NC (1 << 5) +/* Use WC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_WC (2 << 5) +/* Use CC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_CC (3 << 5) +/* Use UC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_UC (4 << 5) + +struct drm_amdgpu_gem_va { + /** GEM object handle */ + __u32 handle; + __u32 _pad; + /** AMDGPU_VA_OP_* */ + __u32 operation; + /** AMDGPU_VM_PAGE_* */ + __u32 flags; + /** va address to assign . Must be correctly aligned.*/ + __u64 va_address; + /** Specify offset inside of BO to assign. Must be correctly aligned.*/ + __u64 offset_in_bo; + /** Specify mapping size. Must be correctly aligned. */ + __u64 map_size; +}; + +#define AMDGPU_HW_IP_GFX 0 +#define AMDGPU_HW_IP_COMPUTE 1 +#define AMDGPU_HW_IP_DMA 2 +#define AMDGPU_HW_IP_UVD 3 +#define AMDGPU_HW_IP_VCE 4 +#define AMDGPU_HW_IP_UVD_ENC 5 +#define AMDGPU_HW_IP_VCN_DEC 6 +#define AMDGPU_HW_IP_VCN_ENC 7 +#define AMDGPU_HW_IP_VCN_JPEG 8 +#define AMDGPU_HW_IP_NUM 9 + +#define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1 + +#define AMDGPU_CHUNK_ID_IB 0x01 +#define AMDGPU_CHUNK_ID_FENCE 0x02 +#define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03 +#define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04 +#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05 +#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06 +#define AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES 0x07 +#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT 0x08 +#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL 0x09 + +struct drm_amdgpu_cs_chunk { + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; +}; + +struct drm_amdgpu_cs_in { + /** Rendering context id */ + __u32 ctx_id; + /** Handle of resource list associated with CS */ + __u32 bo_list_handle; + __u32 num_chunks; + __u32 _pad; + /** this points to __u64 * which point to cs chunks */ + __u64 chunks; +}; + +struct drm_amdgpu_cs_out { + __u64 handle; +}; + +union drm_amdgpu_cs { + struct drm_amdgpu_cs_in in; + struct drm_amdgpu_cs_out out; +}; + +/* Specify flags to be used for IB */ + +/* This IB should be submitted to CE */ +#define AMDGPU_IB_FLAG_CE (1<<0) + +/* Preamble flag, which means the IB could be dropped if no context switch */ +#define AMDGPU_IB_FLAG_PREAMBLE (1<<1) + +/* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */ +#define AMDGPU_IB_FLAG_PREEMPT (1<<2) + +/* The IB fence should do the L2 writeback but not invalidate any shader + * caches (L2/vL1/sL1/I$). */ +#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3) + +/* Set GDS_COMPUTE_MAX_WAVE_ID = DEFAULT before PACKET3_INDIRECT_BUFFER. + * This will reset wave ID counters for the IB. + */ +#define AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID (1 << 4) + +struct drm_amdgpu_cs_chunk_ib { + __u32 _pad; + /** AMDGPU_IB_FLAG_* */ + __u32 flags; + /** Virtual address to begin IB execution */ + __u64 va_start; + /** Size of submission */ + __u32 ib_bytes; + /** HW IP to submit to */ + __u32 ip_type; + /** HW IP index of the same type to submit to */ + __u32 ip_instance; + /** Ring index to submit to */ + __u32 ring; +}; + +struct drm_amdgpu_cs_chunk_dep { + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; + __u64 handle; +}; + +struct drm_amdgpu_cs_chunk_fence { + __u32 handle; + __u32 offset; +}; + +struct drm_amdgpu_cs_chunk_sem { + __u32 handle; +}; + +struct drm_amdgpu_cs_chunk_syncobj { + __u32 handle; + __u32 flags; + __u64 point; +}; + +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2 + +union drm_amdgpu_fence_to_handle { + struct { + struct drm_amdgpu_fence fence; + __u32 what; + __u32 pad; + } in; + struct { + __u32 handle; + } out; +}; + +struct drm_amdgpu_cs_chunk_data { + union { + struct drm_amdgpu_cs_chunk_ib ib_data; + struct drm_amdgpu_cs_chunk_fence fence_data; + }; +}; + +/** + * Query h/w info: Flag that this is integrated (a.h.a. fusion) GPU + * + */ +#define AMDGPU_IDS_FLAGS_FUSION 0x1 +#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 + +/* indicate if acceleration can be working */ +#define AMDGPU_INFO_ACCEL_WORKING 0x00 +/* get the crtc_id from the mode object id? */ +#define AMDGPU_INFO_CRTC_FROM_ID 0x01 +/* query hw IP info */ +#define AMDGPU_INFO_HW_IP_INFO 0x02 +/* query hw IP instance count for the specified type */ +#define AMDGPU_INFO_HW_IP_COUNT 0x03 +/* timestamp for GL_ARB_timer_query */ +#define AMDGPU_INFO_TIMESTAMP 0x05 +/* Query the firmware version */ +#define AMDGPU_INFO_FW_VERSION 0x0e + /* Subquery id: Query VCE firmware version */ + #define AMDGPU_INFO_FW_VCE 0x1 + /* Subquery id: Query UVD firmware version */ + #define AMDGPU_INFO_FW_UVD 0x2 + /* Subquery id: Query GMC firmware version */ + #define AMDGPU_INFO_FW_GMC 0x03 + /* Subquery id: Query GFX ME firmware version */ + #define AMDGPU_INFO_FW_GFX_ME 0x04 + /* Subquery id: Query GFX PFP firmware version */ + #define AMDGPU_INFO_FW_GFX_PFP 0x05 + /* Subquery id: Query GFX CE firmware version */ + #define AMDGPU_INFO_FW_GFX_CE 0x06 + /* Subquery id: Query GFX RLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC 0x07 + /* Subquery id: Query GFX MEC firmware version */ + #define AMDGPU_INFO_FW_GFX_MEC 0x08 + /* Subquery id: Query SMC firmware version */ + #define AMDGPU_INFO_FW_SMC 0x0a + /* Subquery id: Query SDMA firmware version */ + #define AMDGPU_INFO_FW_SDMA 0x0b + /* Subquery id: Query PSP SOS firmware version */ + #define AMDGPU_INFO_FW_SOS 0x0c + /* Subquery id: Query PSP ASD firmware version */ + #define AMDGPU_INFO_FW_ASD 0x0d + /* Subquery id: Query VCN firmware version */ + #define AMDGPU_INFO_FW_VCN 0x0e + /* Subquery id: Query GFX RLC SRLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f + /* Subquery id: Query GFX RLC SRLG firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10 + /* Subquery id: Query GFX RLC SRLS firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11 + /* Subquery id: Query DMCU firmware version */ + #define AMDGPU_INFO_FW_DMCU 0x12 + #define AMDGPU_INFO_FW_TA 0x13 +/* number of bytes moved for TTM migration */ +#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f +/* the used VRAM size */ +#define AMDGPU_INFO_VRAM_USAGE 0x10 +/* the used GTT size */ +#define AMDGPU_INFO_GTT_USAGE 0x11 +/* Information about GDS, etc. resource configuration */ +#define AMDGPU_INFO_GDS_CONFIG 0x13 +/* Query information about VRAM and GTT domains */ +#define AMDGPU_INFO_VRAM_GTT 0x14 +/* Query information about register in MMR address space*/ +#define AMDGPU_INFO_READ_MMR_REG 0x15 +/* Query information about device: rev id, family, etc. */ +#define AMDGPU_INFO_DEV_INFO 0x16 +/* visible vram usage */ +#define AMDGPU_INFO_VIS_VRAM_USAGE 0x17 +/* number of TTM buffer evictions */ +#define AMDGPU_INFO_NUM_EVICTIONS 0x18 +/* Query memory about VRAM and GTT domains */ +#define AMDGPU_INFO_MEMORY 0x19 +/* Query vce clock table */ +#define AMDGPU_INFO_VCE_CLOCK_TABLE 0x1A +/* Query vbios related information */ +#define AMDGPU_INFO_VBIOS 0x1B + /* Subquery id: Query vbios size */ + #define AMDGPU_INFO_VBIOS_SIZE 0x1 + /* Subquery id: Query vbios image */ + #define AMDGPU_INFO_VBIOS_IMAGE 0x2 +/* Query UVD handles */ +#define AMDGPU_INFO_NUM_HANDLES 0x1C +/* Query sensor related information */ +#define AMDGPU_INFO_SENSOR 0x1D + /* Subquery id: Query GPU shader clock */ + #define AMDGPU_INFO_SENSOR_GFX_SCLK 0x1 + /* Subquery id: Query GPU memory clock */ + #define AMDGPU_INFO_SENSOR_GFX_MCLK 0x2 + /* Subquery id: Query GPU temperature */ + #define AMDGPU_INFO_SENSOR_GPU_TEMP 0x3 + /* Subquery id: Query GPU load */ + #define AMDGPU_INFO_SENSOR_GPU_LOAD 0x4 + /* Subquery id: Query average GPU power */ + #define AMDGPU_INFO_SENSOR_GPU_AVG_POWER 0x5 + /* Subquery id: Query northbridge voltage */ + #define AMDGPU_INFO_SENSOR_VDDNB 0x6 + /* Subquery id: Query graphics voltage */ + #define AMDGPU_INFO_SENSOR_VDDGFX 0x7 + /* Subquery id: Query GPU stable pstate shader clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK 0x8 + /* Subquery id: Query GPU stable pstate memory clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK 0x9 +/* Number of VRAM page faults on CPU access. */ +#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E +#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F +/* query ras mask of enabled features*/ +#define AMDGPU_INFO_RAS_ENABLED_FEATURES 0x20 + +/* RAS MASK: UMC (VRAM) */ +#define AMDGPU_INFO_RAS_ENABLED_UMC (1 << 0) +/* RAS MASK: SDMA */ +#define AMDGPU_INFO_RAS_ENABLED_SDMA (1 << 1) +/* RAS MASK: GFX */ +#define AMDGPU_INFO_RAS_ENABLED_GFX (1 << 2) +/* RAS MASK: MMHUB */ +#define AMDGPU_INFO_RAS_ENABLED_MMHUB (1 << 3) +/* RAS MASK: ATHUB */ +#define AMDGPU_INFO_RAS_ENABLED_ATHUB (1 << 4) +/* RAS MASK: PCIE */ +#define AMDGPU_INFO_RAS_ENABLED_PCIE (1 << 5) +/* RAS MASK: HDP */ +#define AMDGPU_INFO_RAS_ENABLED_HDP (1 << 6) +/* RAS MASK: XGMI */ +#define AMDGPU_INFO_RAS_ENABLED_XGMI (1 << 7) +/* RAS MASK: DF */ +#define AMDGPU_INFO_RAS_ENABLED_DF (1 << 8) +/* RAS MASK: SMN */ +#define AMDGPU_INFO_RAS_ENABLED_SMN (1 << 9) +/* RAS MASK: SEM */ +#define AMDGPU_INFO_RAS_ENABLED_SEM (1 << 10) +/* RAS MASK: MP0 */ +#define AMDGPU_INFO_RAS_ENABLED_MP0 (1 << 11) +/* RAS MASK: MP1 */ +#define AMDGPU_INFO_RAS_ENABLED_MP1 (1 << 12) +/* RAS MASK: FUSE */ +#define AMDGPU_INFO_RAS_ENABLED_FUSE (1 << 13) + +#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 +#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff +#define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8 +#define AMDGPU_INFO_MMR_SH_INDEX_MASK 0xff + +struct drm_amdgpu_query_fw { + /** AMDGPU_INFO_FW_* */ + __u32 fw_type; + /** + * Index of the IP if there are more IPs of + * the same type. + */ + __u32 ip_instance; + /** + * Index of the engine. Whether this is used depends + * on the firmware type. (e.g. MEC, SDMA) + */ + __u32 index; + __u32 _pad; +}; + +/* Input structure for the INFO ioctl */ +struct drm_amdgpu_info { + /* Where the return value will be stored */ + __u64 return_pointer; + /* The size of the return value. Just like "size" in "snprintf", + * it limits how many bytes the kernel can write. */ + __u32 return_size; + /* The query request id. */ + __u32 query; + + union { + struct { + __u32 id; + __u32 _pad; + } mode_crtc; + + struct { + /** AMDGPU_HW_IP_* */ + __u32 type; + /** + * Index of the IP if there are more IPs of the same + * type. Ignored by AMDGPU_INFO_HW_IP_COUNT. + */ + __u32 ip_instance; + } query_hw_ip; + + struct { + __u32 dword_offset; + /** number of registers to read */ + __u32 count; + __u32 instance; + /** For future use, no flags defined so far */ + __u32 flags; + } read_mmr_reg; + + struct drm_amdgpu_query_fw query_fw; + + struct { + __u32 type; + __u32 offset; + } vbios_info; + + struct { + __u32 type; + } sensor_info; + }; +}; + +struct drm_amdgpu_info_gds { + /** GDS GFX partition size */ + __u32 gds_gfx_partition_size; + /** GDS compute partition size */ + __u32 compute_partition_size; + /** total GDS memory size */ + __u32 gds_total_size; + /** GWS size per GFX partition */ + __u32 gws_per_gfx_partition; + /** GSW size per compute partition */ + __u32 gws_per_compute_partition; + /** OA size per GFX partition */ + __u32 oa_per_gfx_partition; + /** OA size per compute partition */ + __u32 oa_per_compute_partition; + __u32 _pad; +}; + +struct drm_amdgpu_info_vram_gtt { + __u64 vram_size; + __u64 vram_cpu_accessible_size; + __u64 gtt_size; +}; + +struct drm_amdgpu_heap_info { + /** max. physical memory */ + __u64 total_heap_size; + + /** Theoretical max. available memory in the given heap */ + __u64 usable_heap_size; + + /** + * Number of bytes allocated in the heap. This includes all processes + * and private allocations in the kernel. It changes when new buffers + * are allocated, freed, and moved. It cannot be larger than + * heap_size. + */ + __u64 heap_usage; + + /** + * Theoretical possible max. size of buffer which + * could be allocated in the given heap + */ + __u64 max_allocation; +}; + +struct drm_amdgpu_memory_info { + struct drm_amdgpu_heap_info vram; + struct drm_amdgpu_heap_info cpu_accessible_vram; + struct drm_amdgpu_heap_info gtt; +}; + +struct drm_amdgpu_info_firmware { + __u32 ver; + __u32 feature; +}; + +#define AMDGPU_VRAM_TYPE_UNKNOWN 0 +#define AMDGPU_VRAM_TYPE_GDDR1 1 +#define AMDGPU_VRAM_TYPE_DDR2 2 +#define AMDGPU_VRAM_TYPE_GDDR3 3 +#define AMDGPU_VRAM_TYPE_GDDR4 4 +#define AMDGPU_VRAM_TYPE_GDDR5 5 +#define AMDGPU_VRAM_TYPE_HBM 6 +#define AMDGPU_VRAM_TYPE_DDR3 7 +#define AMDGPU_VRAM_TYPE_DDR4 8 +#define AMDGPU_VRAM_TYPE_GDDR6 9 + +struct drm_amdgpu_info_device { + /** PCI Device ID */ + __u32 device_id; + /** Internal chip revision: A0, A1, etc.) */ + __u32 chip_rev; + __u32 external_rev; + /** Revision id in PCI Config space */ + __u32 pci_rev; + __u32 family; + __u32 num_shader_engines; + __u32 num_shader_arrays_per_engine; + /* in KHz */ + __u32 gpu_counter_freq; + __u64 max_engine_clock; + __u64 max_memory_clock; + /* cu information */ + __u32 cu_active_number; + /* NOTE: cu_ao_mask is INVALID, DON'T use it */ + __u32 cu_ao_mask; + __u32 cu_bitmap[4][4]; + /** Render backend pipe mask. One render backend is CB+DB. */ + __u32 enabled_rb_pipes_mask; + __u32 num_rb_pipes; + __u32 num_hw_gfx_contexts; + __u32 _pad; + __u64 ids_flags; + /** Starting virtual address for UMDs. */ + __u64 virtual_address_offset; + /** The maximum virtual address */ + __u64 virtual_address_max; + /** Required alignment of virtual addresses. */ + __u32 virtual_address_alignment; + /** Page table entry - fragment size */ + __u32 pte_fragment_size; + __u32 gart_page_size; + /** constant engine ram size*/ + __u32 ce_ram_size; + /** video memory type info*/ + __u32 vram_type; + /** video memory bit width*/ + __u32 vram_bit_width; + /* vce harvesting instance */ + __u32 vce_harvest_config; + /* gfx double offchip LDS buffers */ + __u32 gc_double_offchip_lds_buf; + /* NGG Primitive Buffer */ + __u64 prim_buf_gpu_addr; + /* NGG Position Buffer */ + __u64 pos_buf_gpu_addr; + /* NGG Control Sideband */ + __u64 cntl_sb_buf_gpu_addr; + /* NGG Parameter Cache */ + __u64 param_buf_gpu_addr; + __u32 prim_buf_size; + __u32 pos_buf_size; + __u32 cntl_sb_buf_size; + __u32 param_buf_size; + /* wavefront size*/ + __u32 wave_front_size; + /* shader visible vgprs*/ + __u32 num_shader_visible_vgprs; + /* CU per shader array*/ + __u32 num_cu_per_sh; + /* number of tcc blocks*/ + __u32 num_tcc_blocks; + /* gs vgt table depth*/ + __u32 gs_vgt_table_depth; + /* gs primitive buffer depth*/ + __u32 gs_prim_buffer_depth; + /* max gs wavefront per vgt*/ + __u32 max_gs_waves_per_vgt; + __u32 _pad1; + /* always on cu bitmap */ + __u32 cu_ao_bitmap[4][4]; + /** Starting high virtual address for UMDs. */ + __u64 high_va_offset; + /** The maximum high virtual address */ + __u64 high_va_max; + /* gfx10 pa_sc_tile_steering_override */ + __u32 pa_sc_tile_steering_override; + /* disabled TCCs */ + __u64 tcc_disabled_mask; +}; + +struct drm_amdgpu_info_hw_ip { + /** Version of h/w IP */ + __u32 hw_ip_version_major; + __u32 hw_ip_version_minor; + /** Capabilities */ + __u64 capabilities_flags; + /** command buffer address start alignment*/ + __u32 ib_start_alignment; + /** command buffer size alignment*/ + __u32 ib_size_alignment; + /** Bitmask of available rings. Bit 0 means ring 0, etc. */ + __u32 available_rings; + __u32 _pad; +}; + +struct drm_amdgpu_info_num_handles { + /** Max handles as supported by firmware for UVD */ + __u32 uvd_max_handles; + /** Handles currently in use for UVD */ + __u32 uvd_used_handles; +}; + +#define AMDGPU_VCE_CLOCK_TABLE_ENTRIES 6 + +struct drm_amdgpu_info_vce_clock_table_entry { + /** System clock */ + __u32 sclk; + /** Memory clock */ + __u32 mclk; + /** VCE clock */ + __u32 eclk; + __u32 pad; +}; + +struct drm_amdgpu_info_vce_clock_table { + struct drm_amdgpu_info_vce_clock_table_entry entries[AMDGPU_VCE_CLOCK_TABLE_ENTRIES]; + __u32 num_valid_entries; + __u32 pad; +}; + +/* + * Supported GPU families + */ +#define AMDGPU_FAMILY_UNKNOWN 0 +#define AMDGPU_FAMILY_SI 110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */ +#define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */ +#define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */ +#define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */ +#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */ +#define AMDGPU_FAMILY_AI 141 /* Vega10 */ +#define AMDGPU_FAMILY_RV 142 /* Raven */ +#define AMDGPU_FAMILY_NV 143 /* Navi10 */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm.h new file mode 100644 index 0000000..438abde --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm.h @@ -0,0 +1,1042 @@ +/** + * \file drm.h + * Header for the Direct Rendering Manager + * + * \author Rickard E. (Rik) Faith + * + * \par Acknowledgments: + * Dec 1999, Richard Henderson , move to generic \c cmpxchg. + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_H_ +#define _DRM_H_ + +#if defined(__linux__) + +#include +#include +typedef unsigned int drm_handle_t; + +#else /* One of the BSDs */ + +#include +#include +#include +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; +typedef size_t __kernel_size_t; +typedef unsigned long drm_handle_t; + +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ +#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ +#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ +#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ + +#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ +#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) +#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) +#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) + +typedef unsigned int drm_context_t; +typedef unsigned int drm_drawable_t; +typedef unsigned int drm_magic_t; + +/** + * Cliprect. + * + * \warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well + * + * \note KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ +struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +}; + +/** + * Drawable information. + */ +struct drm_drawable_info { + unsigned int num_rects; + struct drm_clip_rect *rects; +}; + +/** + * Texture region, + */ +struct drm_tex_region { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; + unsigned int age; +}; + +/** + * Hardware lock. + * + * The lock structure is a simple cache-line aligned integer. To avoid + * processor bus contention on a multiprocessor system, there should not be any + * other data stored in the same cache line. + */ +struct drm_hw_lock { + __volatile__ unsigned int lock; /**< lock variable */ + char padding[60]; /**< Pad to cache line */ +}; + +/** + * DRM_IOCTL_VERSION ioctl argument type. + * + * \sa drmGetVersion(). + */ +struct drm_version { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + __kernel_size_t name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + __kernel_size_t date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + __kernel_size_t desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +}; + +/** + * DRM_IOCTL_GET_UNIQUE ioctl argument type. + * + * \sa drmGetBusid() and drmSetBusId(). + */ +struct drm_unique { + __kernel_size_t unique_len; /**< Length of unique */ + char *unique; /**< Unique name for driver instantiation */ +}; + +struct drm_list { + int count; /**< Length of user-space structures */ + struct drm_version *version; +}; + +struct drm_block { + int unused; +}; + +/** + * DRM_IOCTL_CONTROL ioctl argument type. + * + * \sa drmCtlInstHandler() and drmCtlUninstHandler(). + */ +struct drm_control { + enum { + DRM_ADD_COMMAND, + DRM_RM_COMMAND, + DRM_INST_HANDLER, + DRM_UNINST_HANDLER + } func; + int irq; +}; + +/** + * Type of memory to map. + */ +enum drm_map_type { + _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ + _DRM_REGISTERS = 1, /**< no caching, no core dump */ + _DRM_SHM = 2, /**< shared, cached */ + _DRM_AGP = 3, /**< AGP/GART */ + _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ + _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ +}; + +/** + * Memory mapping flags. + */ +enum drm_map_flags { + _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ + _DRM_READ_ONLY = 0x02, + _DRM_LOCKED = 0x04, /**< shared, cached, locked */ + _DRM_KERNEL = 0x08, /**< kernel requires access */ + _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ + _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ + _DRM_REMOVABLE = 0x40, /**< Removable mapping */ + _DRM_DRIVER = 0x80 /**< Managed by driver */ +}; + +struct drm_ctx_priv_map { + unsigned int ctx_id; /**< Context requesting private mapping */ + void *handle; /**< Handle of map */ +}; + +/** + * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls + * argument type. + * + * \sa drmAddMap(). + */ +struct drm_map { + unsigned long offset; /**< Requested physical address (0 for SAREA)*/ + unsigned long size; /**< Requested physical size (bytes) */ + enum drm_map_type type; /**< Type of memory to map */ + enum drm_map_flags flags; /**< Flags */ + void *handle; /**< User-space: "Handle" to pass to mmap() */ + /**< Kernel-space: kernel-virtual address */ + int mtrr; /**< MTRR slot used */ + /* Private data */ +}; + +/** + * DRM_IOCTL_GET_CLIENT ioctl argument type. + */ +struct drm_client { + int idx; /**< Which client desired? */ + int auth; /**< Is client authenticated? */ + unsigned long pid; /**< Process ID */ + unsigned long uid; /**< User ID */ + unsigned long magic; /**< Magic */ + unsigned long iocs; /**< Ioctl count */ +}; + +enum drm_stat_type { + _DRM_STAT_LOCK, + _DRM_STAT_OPENS, + _DRM_STAT_CLOSES, + _DRM_STAT_IOCTLS, + _DRM_STAT_LOCKS, + _DRM_STAT_UNLOCKS, + _DRM_STAT_VALUE, /**< Generic value */ + _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ + _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ + + _DRM_STAT_IRQ, /**< IRQ */ + _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ + _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ + _DRM_STAT_DMA, /**< DMA */ + _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ + _DRM_STAT_MISSED /**< Missed DMA opportunity */ + /* Add to the *END* of the list */ +}; + +/** + * DRM_IOCTL_GET_STATS ioctl argument type. + */ +struct drm_stats { + unsigned long count; + struct { + unsigned long value; + enum drm_stat_type type; + } data[15]; +}; + +/** + * Hardware locking flags. + */ +enum drm_lock_flags { + _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +}; + +/** + * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. + * + * \sa drmGetLock() and drmUnlock(). + */ +struct drm_lock { + int context; + enum drm_lock_flags flags; +}; + +/** + * DMA flags + * + * \warning + * These values \e must match xf86drm.h. + * + * \sa drm_dma. + */ +enum drm_dma_flags { + /* Flags for DMA buffer dispatch */ + _DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note The buffer may not yet have + * been processed by the hardware -- + * getting a hardware lock with the + * hardware quiescent will ensure + * that the buffer has been + * processed. + */ + _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + + /* Flags for DMA buffer request */ + _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ +}; + +/** + * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. + * + * \sa drmAddBufs(). + */ +struct drm_buf_desc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ + enum { + _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ + _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ + _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ + _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ + } flags; + unsigned long agp_start; /**< + * Start address of where the AGP buffers are + * in the AGP aperture + */ +}; + +/** + * DRM_IOCTL_INFO_BUFS ioctl argument type. + */ +struct drm_buf_info { + int count; /**< Entries in list */ + struct drm_buf_desc *list; +}; + +/** + * DRM_IOCTL_FREE_BUFS ioctl argument type. + */ +struct drm_buf_free { + int count; + int *list; +}; + +/** + * Buffer information + * + * \sa drm_buf_map. + */ +struct drm_buf_pub { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + void *address; /**< Address of buffer */ +}; + +/** + * DRM_IOCTL_MAP_BUFS ioctl argument type. + */ +struct drm_buf_map { + int count; /**< Length of the buffer list */ +#ifdef __cplusplus + void *virt; +#else + void *virtual; /**< Mmap'd area in user-virtual */ +#endif + struct drm_buf_pub *list; /**< Buffer information */ +}; + +/** + * DRM_IOCTL_DMA ioctl argument type. + * + * Indices here refer to the offset into the buffer list in drm_buf_get. + * + * \sa drmDMA(). + */ +struct drm_dma { + int context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_indices; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send */ + enum drm_dma_flags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size for buffers */ + int *request_indices; /**< Buffer information */ + int *request_sizes; + int granted_count; /**< Number of buffers granted */ +}; + +enum drm_ctx_flags { + _DRM_CONTEXT_PRESERVED = 0x01, + _DRM_CONTEXT_2DONLY = 0x02 +}; + +/** + * DRM_IOCTL_ADD_CTX ioctl argument type. + * + * \sa drmCreateContext() and drmDestroyContext(). + */ +struct drm_ctx { + drm_context_t handle; + enum drm_ctx_flags flags; +}; + +/** + * DRM_IOCTL_RES_CTX ioctl argument type. + */ +struct drm_ctx_res { + int count; + struct drm_ctx *contexts; +}; + +/** + * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. + */ +struct drm_draw { + drm_drawable_t handle; +}; + +/** + * DRM_IOCTL_UPDATE_DRAW ioctl argument type. + */ +typedef enum { + DRM_DRAWABLE_CLIPRECTS +} drm_drawable_info_type_t; + +struct drm_update_draw { + drm_drawable_t handle; + unsigned int type; + unsigned int num; + unsigned long long data; +}; + +/** + * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. + */ +struct drm_auth { + drm_magic_t magic; +}; + +/** + * DRM_IOCTL_IRQ_BUSID ioctl argument type. + * + * \sa drmGetInterruptFromBusID(). + */ +struct drm_irq_busid { + int irq; /**< IRQ number */ + int busnum; /**< bus number */ + int devnum; /**< device number */ + int funcnum; /**< function number */ +}; + +enum drm_vblank_seq_type { + _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + _DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ +}; +#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) + +struct drm_wait_vblank_request { + enum drm_vblank_seq_type type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + enum drm_vblank_seq_type type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +/** + * DRM_IOCTL_WAIT_VBLANK ioctl argument type. + * + * \sa drmWaitVBlank(). + */ +union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +}; + +#define _DRM_PRE_MODESET 1 +#define _DRM_POST_MODESET 2 + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + __u32 crtc; + __u32 cmd; +}; + +/** + * DRM_IOCTL_AGP_ENABLE ioctl argument type. + * + * \sa drmAgpEnable(). + */ +struct drm_agp_mode { + unsigned long mode; /**< AGP mode */ +}; + +/** + * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. + * + * \sa drmAgpAlloc() and drmAgpFree(). + */ +struct drm_agp_buffer { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for binding / unbinding */ + unsigned long type; /**< Type of memory to allocate */ + unsigned long physical; /**< Physical used by i810 */ +}; + +/** + * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. + * + * \sa drmAgpBind() and drmAgpUnbind(). + */ +struct drm_agp_binding { + unsigned long handle; /**< From drm_agp_buffer */ + unsigned long offset; /**< In bytes -- will round to page boundary */ +}; + +/** + * DRM_IOCTL_AGP_INFO ioctl argument type. + * + * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), + * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), + * drmAgpVendorId() and drmAgpDeviceId(). + */ +struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +}; + +/** + * DRM_IOCTL_SG_ALLOC ioctl argument type. + */ +struct drm_scatter_gather { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for mapping / unmapping */ +}; + +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +}; + +/** DRM_IOCTL_GEM_CLOSE ioctl argument type */ +struct drm_gem_close { + /** Handle of the object to be closed. */ + __u32 handle; + __u32 pad; +}; + +/** DRM_IOCTL_GEM_FLINK ioctl argument type */ +struct drm_gem_flink { + /** Handle for the object being named */ + __u32 handle; + + /** Returned global name */ + __u32 name; +}; + +/** DRM_IOCTL_GEM_OPEN ioctl argument type */ +struct drm_gem_open { + /** Name of object being opened */ + __u32 name; + + /** Returned handle for the object */ + __u32 handle; + + /** Returned size of the object */ + __u64 size; +}; + +#define DRM_CAP_DUMB_BUFFER 0x1 +#define DRM_CAP_VBLANK_HIGH_CRTC 0x2 +#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 +#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 +#define DRM_CAP_PRIME 0x5 +#define DRM_PRIME_CAP_IMPORT 0x1 +#define DRM_PRIME_CAP_EXPORT 0x2 +#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 +#define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +/* + * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight + * combination for the hardware cursor. The intention is that a hardware + * agnostic userspace can query a cursor plane size to use. + * + * Note that the cross-driver contract is to merely return a valid size; + * drivers are free to attach another meaning on top, eg. i915 returns the + * maximum plane size. + */ +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#define DRM_CAP_ADDFB2_MODIFIERS 0x10 +#define DRM_CAP_PAGE_FLIP_TARGET 0x11 +#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 +#define DRM_CAP_SYNCOBJ 0x13 +#define DRM_CAP_SYNCOBJ_TIMELINE 0x14 + +/** DRM_IOCTL_GET_CAP ioctl argument type */ +struct drm_get_cap { + __u64 capability; + __u64 value; +}; + +/** + * DRM_CLIENT_CAP_STEREO_3D + * + * if set to 1, the DRM core will expose the stereo 3D capabilities of the + * monitor by advertising the supported 3D layouts in the flags of struct + * drm_mode_modeinfo. + */ +#define DRM_CLIENT_CAP_STEREO_3D 1 + +/** + * DRM_CLIENT_CAP_UNIVERSAL_PLANES + * + * If set to 1, the DRM core will expose all planes (overlay, primary, and + * cursor) to userspace. + */ +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 + +/** + * DRM_CLIENT_CAP_ATOMIC + * + * If set to 1, the DRM core will expose atomic properties to userspace + */ +#define DRM_CLIENT_CAP_ATOMIC 3 + +/** + * DRM_CLIENT_CAP_ASPECT_RATIO + * + * If set to 1, the DRM core will provide aspect ratio information in modes. + */ +#define DRM_CLIENT_CAP_ASPECT_RATIO 4 + +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 + +/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ +struct drm_set_client_cap { + __u64 capability; + __u64 value; +}; + +#define DRM_RDWR O_RDWR +#define DRM_CLOEXEC O_CLOEXEC +struct drm_prime_handle { + __u32 handle; + + /** Flags.. only applicable for handle->fd */ + __u32 flags; + + /** Returned dmabuf file descriptor */ + __s32 fd; +}; + +struct drm_syncobj_create { + __u32 handle; +#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) + __u32 flags; +}; + +struct drm_syncobj_destroy { + __u32 handle; + __u32 pad; +}; + +#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) +#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) +struct drm_syncobj_handle { + __u32 handle; + __u32 flags; + + __s32 fd; + __u32 pad; +}; + +struct drm_syncobj_transfer { + __u32 src_handle; + __u32 dst_handle; + __u64 src_point; + __u64 dst_point; + __u32 flags; + __u32 pad; +}; + +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ +struct drm_syncobj_wait { + __u64 handles; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + +struct drm_syncobj_timeline_wait { + __u64 handles; + /* wait on specific timeline point for every handles*/ + __u64 points; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + + +struct drm_syncobj_array { + __u64 handles; + __u32 count_handles; + __u32 pad; +}; + +struct drm_syncobj_timeline_array { + __u64 handles; + __u64 points; + __u32 count_handles; + __u32 pad; +}; + + +/* Query current scanout sequence number */ +struct drm_crtc_get_sequence { + __u32 crtc_id; /* requested crtc_id */ + __u32 active; /* return: crtc output is active */ + __u64 sequence; /* return: most recent vblank sequence */ + __s64 sequence_ns; /* return: most recent time of first pixel out */ +}; + +/* Queue event to be delivered at specified sequence. Time stamp marks + * when the first pixel of the refresh cycle leaves the display engine + * for the display + */ +#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ +#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ + +struct drm_crtc_queue_sequence { + __u32 crtc_id; + __u32 flags; + __u64 sequence; /* on input, target sequence. on output, actual sequence */ + __u64 user_data; /* user data passed to event */ +}; + +#if defined(__cplusplus) +} +#endif + +#include "drm_mode.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_IOCTL_BASE 'd' +#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) +#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) + +#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) +#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) +#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) +#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) +#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) +#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) +#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) +#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap) + +#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) +#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) +#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) +#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) +#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) +#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) +#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) +#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) +#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) +#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) +#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) + +#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) + +#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) +#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) + +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + +#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) +#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) +#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) +#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) +#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) +#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) +#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) +#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) +#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) +#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) +#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) +#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) +#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) + +#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) +#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) + +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) + +#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) +#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) + +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) + +#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) +#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) + +#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) + +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) +#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) +#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */ +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */ + +#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) +#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) +#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) +#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) + +#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) +#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) +#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) +#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) +#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) +#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) +#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) +#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) +#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) +#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) +#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) +#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) + +#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) +#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) +#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait) +#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array) +#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array) + +#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease) +#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees) +#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) +#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) + +#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) +#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array) +#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) +#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) + +/** + * Device specific ioctls should only be in their respective headers + * The device specific ioctl range is from 0x40 to 0x9f. + * Generic IOCTLS restart at 0xA0. + * + * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and + * drmCommandReadWrite(). + */ +#define DRM_COMMAND_BASE 0x40 +#define DRM_COMMAND_END 0xA0 + +/** + * Header for events written back to userspace on the drm fd. The + * type defines the type of event, the length specifies the total + * length of the event (including the header), and user_data is + * typically a 64 bit value passed with the ioctl that triggered the + * event. A read on the drm fd will always only return complete + * events, that is, if for example the read buffer is 100 bytes, and + * there are two 64 byte events pending, only one will be returned. + * + * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and + * up are chipset specific. + */ +struct drm_event { + __u32 type; + __u32 length; +}; + +#define DRM_EVENT_VBLANK 0x01 +#define DRM_EVENT_FLIP_COMPLETE 0x02 +#define DRM_EVENT_CRTC_SEQUENCE 0x03 + +struct drm_event_vblank { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 crtc_id; /* 0 on older kernels that do not support this */ +}; + +/* Event delivered at sequence. Time stamp marks when the first pixel + * of the refresh cycle leaves the display engine for the display + */ +struct drm_event_crtc_sequence { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; +}; + +/* typedef area */ +typedef struct drm_clip_rect drm_clip_rect_t; +typedef struct drm_drawable_info drm_drawable_info_t; +typedef struct drm_tex_region drm_tex_region_t; +typedef struct drm_hw_lock drm_hw_lock_t; +typedef struct drm_version drm_version_t; +typedef struct drm_unique drm_unique_t; +typedef struct drm_list drm_list_t; +typedef struct drm_block drm_block_t; +typedef struct drm_control drm_control_t; +typedef enum drm_map_type drm_map_type_t; +typedef enum drm_map_flags drm_map_flags_t; +typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; +typedef struct drm_map drm_map_t; +typedef struct drm_client drm_client_t; +typedef enum drm_stat_type drm_stat_type_t; +typedef struct drm_stats drm_stats_t; +typedef enum drm_lock_flags drm_lock_flags_t; +typedef struct drm_lock drm_lock_t; +typedef enum drm_dma_flags drm_dma_flags_t; +typedef struct drm_buf_desc drm_buf_desc_t; +typedef struct drm_buf_info drm_buf_info_t; +typedef struct drm_buf_free drm_buf_free_t; +typedef struct drm_buf_pub drm_buf_pub_t; +typedef struct drm_buf_map drm_buf_map_t; +typedef struct drm_dma drm_dma_t; +typedef union drm_wait_vblank drm_wait_vblank_t; +typedef struct drm_agp_mode drm_agp_mode_t; +typedef enum drm_ctx_flags drm_ctx_flags_t; +typedef struct drm_ctx drm_ctx_t; +typedef struct drm_ctx_res drm_ctx_res_t; +typedef struct drm_draw drm_draw_t; +typedef struct drm_update_draw drm_update_draw_t; +typedef struct drm_auth drm_auth_t; +typedef struct drm_irq_busid drm_irq_busid_t; +typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; + +typedef struct drm_agp_buffer drm_agp_buffer_t; +typedef struct drm_agp_binding drm_agp_binding_t; +typedef struct drm_agp_info drm_agp_info_t; +typedef struct drm_scatter_gather drm_scatter_gather_t; +typedef struct drm_set_version drm_set_version_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_fourcc.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_fourcc.h new file mode 100644 index 0000000..5c69090 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_fourcc.h @@ -0,0 +1,763 @@ +/* + * Copyright 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DRM_FOURCC_H +#define DRM_FOURCC_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * DOC: overview + * + * In the DRM subsystem, framebuffer pixel formats are described using the + * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the + * fourcc code, a Format Modifier may optionally be provided, in order to + * further describe the buffer's format - for example tiling or compression. + * + * Format Modifiers + * ---------------- + * + * Format modifiers are used in conjunction with a fourcc code, forming a + * unique fourcc:modifier pair. This format:modifier pair must fully define the + * format and data layout of the buffer, and should be the only way to describe + * that particular buffer. + * + * Having multiple fourcc:modifier pairs which describe the same layout should + * be avoided, as such aliases run the risk of different drivers exposing + * different names for the same data format, forcing userspace to understand + * that they are aliases. + * + * Format modifiers may change any property of the buffer, including the number + * of planes and/or the required allocation size. Format modifiers are + * vendor-namespaced, and as such the relationship between a fourcc code and a + * modifier is specific to the modifer being used. For example, some modifiers + * may preserve meaning - such as number of planes - from the fourcc code, + * whereas others may not. + * + * Vendors should document their modifier usage in as much detail as + * possible, to ensure maximum compatibility across devices, drivers and + * applications. + * + * The authoritative list of format modifier codes is found in + * `include/uapi/drm/drm_fourcc.h` + */ + +#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ + ((__u32)(c) << 16) | ((__u32)(d) << 24)) + +#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ + +/* Reserve 0 for the invalid format specifier */ +#define DRM_FORMAT_INVALID 0 + +/* color index */ +#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ + +/* 8 bpp Red */ +#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ + +/* 16 bpp Red */ +#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ + +/* 16 bpp RG */ +#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */ +#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ + +/* 32 bpp RG */ +#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */ +#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ + +/* 8 bpp RGB */ +#define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ +#define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ + +/* 16 bpp RGB */ +#define DRM_FORMAT_XRGB4444 fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ +#define DRM_FORMAT_XBGR4444 fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ +#define DRM_FORMAT_RGBX4444 fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ +#define DRM_FORMAT_BGRX4444 fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ + +#define DRM_FORMAT_ARGB4444 fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ +#define DRM_FORMAT_ABGR4444 fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ +#define DRM_FORMAT_RGBA4444 fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ +#define DRM_FORMAT_BGRA4444 fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ + +#define DRM_FORMAT_XRGB1555 fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ +#define DRM_FORMAT_XBGR1555 fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ +#define DRM_FORMAT_RGBX5551 fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ +#define DRM_FORMAT_BGRX5551 fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ + +#define DRM_FORMAT_ARGB1555 fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ +#define DRM_FORMAT_ABGR1555 fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ +#define DRM_FORMAT_RGBA5551 fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ +#define DRM_FORMAT_BGRA5551 fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ + +#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ +#define DRM_FORMAT_BGR565 fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ + +/* 24 bpp RGB */ +#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ +#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ + +/* 32 bpp RGB */ +#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ +#define DRM_FORMAT_RGBX8888 fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ +#define DRM_FORMAT_BGRX8888 fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ + +#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ +#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ +#define DRM_FORMAT_BGRA8888 fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ + +#define DRM_FORMAT_XRGB2101010 fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ +#define DRM_FORMAT_XBGR2101010 fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ +#define DRM_FORMAT_RGBX1010102 fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ +#define DRM_FORMAT_BGRX1010102 fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ + +#define DRM_FORMAT_ARGB2101010 fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ +#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ +#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ +#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ + +/* + * Floating point 64bpp RGB + * IEEE 754-2008 binary16 half-precision float + * [15:0] sign:exponent:mantissa 1:5:10 + */ +#define DRM_FORMAT_XRGB16161616F fourcc_code('X', 'R', '4', 'H') /* [63:0] x:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ + +#define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H') /* [63:0] A:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ + +/* packed YCbCr */ +#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ +#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ + +#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */ +#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */ + +/* + * packed Y2xx indicate for each component, xx valid data occupy msb + * 16-xx padding occupy lsb + */ +#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels */ +#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels */ +#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels */ + +/* + * packed Y4xx indicate for each component, xx valid data occupy msb + * 16-xx padding occupy lsb except Y410 + */ +#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */ +#define DRM_FORMAT_Y412 fourcc_code('Y', '4', '1', '2') /* [63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ +#define DRM_FORMAT_Y416 fourcc_code('Y', '4', '1', '6') /* [63:0] A:Cr:Y:Cb 16:16:16:16 little endian */ + +#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */ +#define DRM_FORMAT_XVYU12_16161616 fourcc_code('X', 'V', '3', '6') /* [63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ +#define DRM_FORMAT_XVYU16161616 fourcc_code('X', 'V', '4', '8') /* [63:0] X:Cr:Y:Cb 16:16:16:16 little endian */ + +/* + * packed YCbCr420 2x2 tiled formats + * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile + */ +/* [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ +#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0') +/* [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ +#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0') + +/* [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ +#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2') +/* [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ +#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2') + +/* + * 1-plane YUV 4:2:0 + * In these formats, the component ordering is specified (Y, followed by U + * then V), but the exact Linear layout is undefined. + * These formats can only be used with a non-Linear modifier. + */ +#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8') +#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0') + +/* + * 2 plane RGB + A + * index 0 = RGB plane, same format as the corresponding non _A8 format has + * index 1 = A plane, [7:0] A + */ +#define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8') +#define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8') +#define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8') +#define DRM_FORMAT_BGRX8888_A8 fourcc_code('B', 'X', 'A', '8') +#define DRM_FORMAT_RGB888_A8 fourcc_code('R', '8', 'A', '8') +#define DRM_FORMAT_BGR888_A8 fourcc_code('B', '8', 'A', '8') +#define DRM_FORMAT_RGB565_A8 fourcc_code('R', '5', 'A', '8') +#define DRM_FORMAT_BGR565_A8 fourcc_code('B', '5', 'A', '8') + +/* + * 2 plane YCbCr + * index 0 = Y plane, [7:0] Y + * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian + * or + * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian + */ +#define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ +#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + */ +#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0') /* 2x1 subsampled Cr:Cb plane, 10 bit per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + */ +#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y:x [12:4] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian + */ +#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane 12 bits per channel */ + +/* + * 2 plane YCbCr MSB aligned + * index 0 = Y plane, [15:0] Y little endian + * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian + */ +#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + +/* + * 3 plane YCbCr + * index 0: Y plane, [7:0] Y + * index 1: Cb plane, [7:0] Cb + * index 2: Cr plane, [7:0] Cr + * or + * index 1: Cr plane, [7:0] Cr + * index 2: Cb plane, [7:0] Cb + */ +#define DRM_FORMAT_YUV410 fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU410 fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU411 fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV420 fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU420 fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV422 fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU422 fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ +#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ +#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ + + +/* + * Format Modifiers: + * + * Format modifiers describe, typically, a re-ordering or modification + * of the data in a plane of an FB. This can be used to express tiled/ + * swizzled formats, or compression, or a combination of the two. + * + * The upper 8 bits of the format modifier are a vendor-id as assigned + * below. The lower 56 bits are assigned as vendor sees fit. + */ + +/* Vendor Ids: */ +#define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 +#define DRM_FORMAT_MOD_VENDOR_AMD 0x02 +#define DRM_FORMAT_MOD_VENDOR_NVIDIA 0x03 +#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 +#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 +#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06 +#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 +#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 +#define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 + +/* add more to the end as needed */ + +#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) + +#define fourcc_mod_code(vendor, val) \ + ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL)) + +/* + * Format Modifier tokens: + * + * When adding a new token please document the layout with a code comment, + * similar to the fourcc codes above. drm_fourcc.h is considered the + * authoritative source for all of these. + */ + +/* + * Invalid Modifier + * + * This modifier can be used as a sentinel to terminate the format modifiers + * list, or to initialize a variable with an invalid modifier. It might also be + * used to report an error back to userspace for certain APIs. + */ +#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) + +/* + * Linear Layout + * + * Just plain linear layout. Note that this is different from no specifying any + * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl), + * which tells the driver to also take driver-internal information into account + * and so might actually result in a tiled framebuffer. + */ +#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) + +/* Intel framebuffer modifiers */ + +/* + * Intel X-tiling layout + * + * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) + * in row-major layout. Within the tile bytes are laid out row-major, with + * a platform-dependent stride. On top of that the memory can apply + * platform-depending swizzling of some higher address bits into bit6. + * + * This format is highly platforms specific and not useful for cross-driver + * sharing. It exists since on a given platform it does uniquely identify the + * layout in a simple way for i915-specific userspace. + */ +#define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1) + +/* + * Intel Y-tiling layout + * + * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) + * in row-major layout. Within the tile bytes are laid out in OWORD (16 bytes) + * chunks column-major, with a platform-dependent height. On top of that the + * memory can apply platform-depending swizzling of some higher address bits + * into bit6. + * + * This format is highly platforms specific and not useful for cross-driver + * sharing. It exists since on a given platform it does uniquely identify the + * layout in a simple way for i915-specific userspace. + */ +#define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2) + +/* + * Intel Yf-tiling layout + * + * This is a tiled layout using 4Kb tiles in row-major layout. + * Within the tile pixels are laid out in 16 256 byte units / sub-tiles which + * are arranged in four groups (two wide, two high) with column-major layout. + * Each group therefore consists out of four 256 byte units, which are also laid + * out as 2x2 column-major. + * 256 byte units are made out of four 64 byte blocks of pixels, producing + * either a square block or a 2:1 unit. + * 64 byte blocks of pixels contain four pixel rows of 16 bytes, where the width + * in pixel depends on the pixel depth. + */ +#define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3) + +/* + * Intel color control surface (CCS) for render compression + * + * The framebuffer format must be one of the 8:8:8:8 RGB formats. + * The main surface will be plane index 0 and must be Y/Yf-tiled, + * the CCS will be plane index 1. + * + * Each CCS tile matches a 1024x512 pixel area of the main surface. + * To match certain aspects of the 3D hardware the CCS is + * considered to be made up of normal 128Bx32 Y tiles, Thus + * the CCS pitch must be specified in multiples of 128 bytes. + * + * In reality the CCS tile appears to be a 64Bx64 Y tile, composed + * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks. + * But that fact is not relevant unless the memory is accessed + * directly. + */ +#define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) +#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) + +/* + * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks + * + * Macroblocks are laid in a Z-shape, and each pixel data is following the + * standard NV12 style. + * As for NV12, an image is the result of two frame buffers: one for Y, + * one for the interleaved Cb/Cr components (1/2 the height of the Y buffer). + * Alignment requirements are (for each buffer): + * - multiple of 128 pixels for the width + * - multiple of 32 pixels for the height + * + * For more information: see https://linuxtv.org/downloads/v4l-dvb-apis/re32.html + */ +#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) + +/* + * Tiled, 16 (pixels) x 16 (lines) - sized macroblocks + * + * This is a simple tiled layout using tiles of 16x16 pixels in a row-major + * layout. For YCbCr formats Cb/Cr components are taken in such a way that + * they correspond to their 16x16 luma block. + */ +#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2) + +/* + * Qualcomm Compressed Format + * + * Refers to a compressed variant of the base format that is compressed. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + +/* Vivante framebuffer modifiers */ + +/* + * Vivante 4x4 tiling layout + * + * This is a simple tiled layout using tiles of 4x4 pixels in a row-major + * layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1) + +/* + * Vivante 64x64 super-tiling layout + * + * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile + * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row- + * major layout. + * + * For more information: see + * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling + */ +#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2) + +/* + * Vivante 4x4 tiling layout for dual-pipe + * + * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a + * different base address. Offsets from the base addresses are therefore halved + * compared to the non-split tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3) + +/* + * Vivante 64x64 super-tiling layout for dual-pipe + * + * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile + * starts at a different base address. Offsets from the base addresses are + * therefore halved compared to the non-split super-tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4) + +/* NVIDIA frame buffer modifiers */ + +/* + * Tegra Tiled Layout, used by Tegra 2, 3 and 4. + * + * Pixels are arranged in simple tiles of 16 x 16 bytes. + */ +#define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1) + +/* + * 16Bx2 Block Linear layout, used by desktop GPUs, and Tegra K1 and later + * + * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked + * vertically by a power of 2 (1 to 32 GOBs) to form a block. + * + * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape. + * + * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically. + * Valid values are: + * + * 0 == ONE_GOB + * 1 == TWO_GOBS + * 2 == FOUR_GOBS + * 3 == EIGHT_GOBS + * 4 == SIXTEEN_GOBS + * 5 == THIRTYTWO_GOBS + * + * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format + * in full detail. + */ +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \ + fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf)) + +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \ + fourcc_mod_code(NVIDIA, 0x10) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \ + fourcc_mod_code(NVIDIA, 0x11) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \ + fourcc_mod_code(NVIDIA, 0x12) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \ + fourcc_mod_code(NVIDIA, 0x13) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \ + fourcc_mod_code(NVIDIA, 0x14) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ + fourcc_mod_code(NVIDIA, 0x15) + +/* + * Some Broadcom modifiers take parameters, for example the number of + * vertical lines in the image. Reserve the lower 32 bits for modifier + * type, and the next 24 bits for parameters. Top 8 bits are the + * vendor code. + */ +#define __fourcc_mod_broadcom_param_shift 8 +#define __fourcc_mod_broadcom_param_bits 48 +#define fourcc_mod_broadcom_code(val, params) \ + fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val)) +#define fourcc_mod_broadcom_param(m) \ + ((int)(((m) >> __fourcc_mod_broadcom_param_shift) & \ + ((1ULL << __fourcc_mod_broadcom_param_bits) - 1))) +#define fourcc_mod_broadcom_mod(m) \ + ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << \ + __fourcc_mod_broadcom_param_shift)) + +/* + * Broadcom VC4 "T" format + * + * This is the primary layout that the V3D GPU can texture from (it + * can't do linear). The T format has: + * + * - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4 + * pixels at 32 bit depth. + * + * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually + * 16x16 pixels). + * + * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On + * even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows + * they're (TR, BR, BL, TL), where bottom left is start of memory. + * + * - an image made of 4k tiles in rows either left-to-right (even rows of 4k + * tiles) or right-to-left (odd rows of 4k tiles). + */ +#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1) + +/* + * Broadcom SAND format + * + * This is the native format that the H.264 codec block uses. For VC4 + * HVS, it is only valid for H.264 (NV12/21) and RGBA modes. + * + * The image can be considered to be split into columns, and the + * columns are placed consecutively into memory. The width of those + * columns can be either 32, 64, 128, or 256 pixels, but in practice + * only 128 pixel columns are used. + * + * The pitch between the start of each column is set to optimally + * switch between SDRAM banks. This is passed as the number of lines + * of column width in the modifier (we can't use the stride value due + * to various core checks that look at it , so you should set the + * stride to width*cpp). + * + * Note that the column height for this format modifier is the same + * for all of the planes, assuming that each column contains both Y + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. + */ + +#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(2, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(3, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(4, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(5, v) + +#define DRM_FORMAT_MOD_BROADCOM_SAND32 \ + DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND64 \ + DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND128 \ + DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND256 \ + DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) + +/* Broadcom UIF format + * + * This is the common format for the current Broadcom multimedia + * blocks, including V3D 3.x and newer, newer video codecs, and + * displays. + * + * The image consists of utiles (64b blocks), UIF blocks (2x2 utiles), + * and macroblocks (4x4 UIF blocks). Those 4x4 UIF block groups are + * stored in columns, with padding between the columns to ensure that + * moving from one column to the next doesn't hit the same SDRAM page + * bank. + * + * To calculate the padding, it is assumed that each hardware block + * and the software driving it knows the platform's SDRAM page size, + * number of banks, and XOR address, and that it's identical between + * all blocks using the format. This tiling modifier will use XOR as + * necessary to reduce the padding. If a hardware block can't do XOR, + * the assumption is that a no-XOR tiling modifier will be created. + */ +#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) + +/* + * Arm Framebuffer Compression (AFBC) modifiers + * + * AFBC is a proprietary lossless image compression protocol and format. + * It provides fine-grained random access and minimizes the amount of data + * transferred between IP blocks. + * + * AFBC has several features which may be supported and/or used, which are + * represented using bits in the modifier. Not all combinations are valid, + * and different devices or use-cases may support different combinations. + * + * Further information on the use of AFBC modifiers can be found in + * Documentation/gpu/afbc.rst + */ +#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) + +/* + * AFBC superblock size + * + * Indicates the superblock size(s) used for the AFBC buffer. The buffer + * size (in pixels) must be aligned to a multiple of the superblock size. + * Four lowest significant bits(LSBs) are reserved for block size. + * + * Where one superblock size is specified, it applies to all planes of the + * buffer (e.g. 16x16, 32x8). When multiple superblock sizes are specified, + * the first applies to the Luma plane and the second applies to the Chroma + * plane(s). e.g. (32x8_64x4 means 32x8 Luma, with 64x4 Chroma). + * Multiple superblock sizes are only valid for multi-plane YCbCr formats. + */ +#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf +#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 (3ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 (4ULL) + +/* + * AFBC lossless colorspace transform + * + * Indicates that the buffer makes use of the AFBC lossless colorspace + * transform. + */ +#define AFBC_FORMAT_MOD_YTR (1ULL << 4) + +/* + * AFBC block-split + * + * Indicates that the payload of each superblock is split. The second + * half of the payload is positioned at a predefined offset from the start + * of the superblock payload. + */ +#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5) + +/* + * AFBC sparse layout + * + * This flag indicates that the payload of each superblock must be stored at a + * predefined position relative to the other superblocks in the same AFBC + * buffer. This order is the same order used by the header buffer. In this mode + * each superblock is given the same amount of space as an uncompressed + * superblock of the particular format would require, rounding up to the next + * multiple of 128 bytes in size. + */ +#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6) + +/* + * AFBC copy-block restrict + * + * Buffers with this flag must obey the copy-block restriction. The restriction + * is such that there are no copy-blocks referring across the border of 8x8 + * blocks. For the subsampled data the 8x8 limitation is also subsampled. + */ +#define AFBC_FORMAT_MOD_CBR (1ULL << 7) + +/* + * AFBC tiled layout + * + * The tiled layout groups superblocks in 8x8 or 4x4 tiles, where all + * superblocks inside a tile are stored together in memory. 8x8 tiles are used + * for pixel formats up to and including 32 bpp while 4x4 tiles are used for + * larger bpp formats. The order between the tiles is scan line. + * When the tiled layout is used, the buffer size (in pixels) must be aligned + * to the tile size. + */ +#define AFBC_FORMAT_MOD_TILED (1ULL << 8) + +/* + * AFBC solid color blocks + * + * Indicates that the buffer makes use of solid-color blocks, whereby bandwidth + * can be reduced if a whole superblock is a single color. + */ +#define AFBC_FORMAT_MOD_SC (1ULL << 9) + +/* + * AFBC double-buffer + * + * Indicates that the buffer is allocated in a layout safe for front-buffer + * rendering. + */ +#define AFBC_FORMAT_MOD_DB (1ULL << 10) + +/* + * AFBC buffer content hints + * + * Indicates that the buffer includes per-superblock content hints. + */ +#define AFBC_FORMAT_MOD_BCH (1ULL << 11) + +/* + * Allwinner tiled modifier + * + * This tiling mode is implemented by the VPU found on all Allwinner platforms, + * codenamed sunxi. It is associated with a YUV format that uses either 2 or 3 + * planes. + * + * With this tiling, the luminance samples are disposed in tiles representing + * 32x32 pixels and the chrominance samples in tiles representing 32x64 pixels. + * The pixel order in each tile is linear and the tiles are disposed linearly, + * both in row-major order. + */ +#define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) + +#if defined(__cplusplus) +} +#endif + +#endif /* DRM_FOURCC_H */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_mode.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_mode.h new file mode 100644 index 0000000..5fe6c64 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_mode.h @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2007 Dave Airlie + * Copyright (c) 2007 Jakob Bornecrantz + * Copyright (c) 2008 Red Hat Inc. + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA + * Copyright (c) 2007-2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _DRM_MODE_H +#define _DRM_MODE_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */ +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) /* deprecated */ +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +#define DRM_MODE_TYPE_ALL (DRM_MODE_TYPE_PREFERRED | \ + DRM_MODE_TYPE_USERDEF | \ + DRM_MODE_TYPE_DRIVER) + +/* Video mode flags */ +/* bit compatible with the xrandr RR_ definitions (bits 0-13) + * + * ABI warning: Existing userspace really expects + * the mode flags to match the xrandr definitions. Any + * changes that don't match the xrandr definitions will + * likely need a new client cap or some other mechanism + * to avoid breaking existing userspace. This includes + * allocating new flags in the previously unused bits! + */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) /* deprecated */ +#define DRM_MODE_FLAG_PIXMUX (1<<11) /* deprecated */ +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) + /* + * When adding a new stereo mode don't forget to adjust DRM_MODE_FLAGS_3D_MAX + * (define not exposed to user space). + */ +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + +/* Picture aspect ratio options */ +#define DRM_MODE_PICTURE_ASPECT_NONE 0 +#define DRM_MODE_PICTURE_ASPECT_4_3 1 +#define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 + +/* Content type options */ +#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 +#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 +#define DRM_MODE_CONTENT_TYPE_PHOTO 2 +#define DRM_MODE_CONTENT_TYPE_CINEMA 3 +#define DRM_MODE_CONTENT_TYPE_GAME 4 + +/* Aspect ratio flag bitmask (4 bits 22:19) */ +#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) +#define DRM_MODE_FLAG_PIC_AR_NONE \ + (DRM_MODE_PICTURE_ASPECT_NONE<<19) +#define DRM_MODE_FLAG_PIC_AR_4_3 \ + (DRM_MODE_PICTURE_ASPECT_4_3<<19) +#define DRM_MODE_FLAG_PIC_AR_16_9 \ + (DRM_MODE_PICTURE_ASPECT_16_9<<19) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<19) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<19) + +#define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ + DRM_MODE_FLAG_NHSYNC | \ + DRM_MODE_FLAG_PVSYNC | \ + DRM_MODE_FLAG_NVSYNC | \ + DRM_MODE_FLAG_INTERLACE | \ + DRM_MODE_FLAG_DBLSCAN | \ + DRM_MODE_FLAG_CSYNC | \ + DRM_MODE_FLAG_PCSYNC | \ + DRM_MODE_FLAG_NCSYNC | \ + DRM_MODE_FLAG_HSKEW | \ + DRM_MODE_FLAG_DBLCLK | \ + DRM_MODE_FLAG_CLKDIV2 | \ + DRM_MODE_FLAG_3D_MASK) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NONE 0 /* Unmodified timing (display or + software can still scale) */ +#define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ +#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ +#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 +#define DRM_MODE_DITHERING_AUTO 2 + +/* Dirty info options */ +#define DRM_MODE_DIRTY_OFF 0 +#define DRM_MODE_DIRTY_ON 1 +#define DRM_MODE_DIRTY_ANNOTATE 2 + +/* Link Status options */ +#define DRM_MODE_LINK_STATUS_GOOD 0 +#define DRM_MODE_LINK_STATUS_BAD 1 + +/* + * DRM_MODE_ROTATE_ + * + * Signals that a drm plane is been rotated degrees in counter + * clockwise direction. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_ROTATE_0 (1<<0) +#define DRM_MODE_ROTATE_90 (1<<1) +#define DRM_MODE_ROTATE_180 (1<<2) +#define DRM_MODE_ROTATE_270 (1<<3) + +/* + * DRM_MODE_ROTATE_MASK + * + * Bitmask used to look for drm plane rotations. + */ +#define DRM_MODE_ROTATE_MASK (\ + DRM_MODE_ROTATE_0 | \ + DRM_MODE_ROTATE_90 | \ + DRM_MODE_ROTATE_180 | \ + DRM_MODE_ROTATE_270) + +/* + * DRM_MODE_REFLECT_ + * + * Signals that the contents of a drm plane is reflected along the axis, + * in the same way as mirroring. + * See kerneldoc chapter "Plane Composition Properties" for more details. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_REFLECT_X (1<<4) +#define DRM_MODE_REFLECT_Y (1<<5) + +/* + * DRM_MODE_REFLECT_MASK + * + * Bitmask used to look for drm plane reflections. + */ +#define DRM_MODE_REFLECT_MASK (\ + DRM_MODE_REFLECT_X | \ + DRM_MODE_REFLECT_Y) + +/* Content Protection Flags */ +#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED 0 +#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 +#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 + +struct drm_mode_modeinfo { + __u32 clock; + __u16 hdisplay; + __u16 hsync_start; + __u16 hsync_end; + __u16 htotal; + __u16 hskew; + __u16 vdisplay; + __u16 vsync_start; + __u16 vsync_end; + __u16 vtotal; + __u16 vscan; + + __u32 vrefresh; + + __u32 flags; + __u32 type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + __u64 fb_id_ptr; + __u64 crtc_id_ptr; + __u64 connector_id_ptr; + __u64 encoder_id_ptr; + __u32 count_fbs; + __u32 count_crtcs; + __u32 count_connectors; + __u32 count_encoders; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; +}; + +struct drm_mode_crtc { + __u64 set_connectors_ptr; + __u32 count_connectors; + + __u32 crtc_id; /**< Id */ + __u32 fb_id; /**< Id of framebuffer */ + + __u32 x; /**< x Position on the framebuffer */ + __u32 y; /**< y Position on the framebuffer */ + + __u32 gamma_size; + __u32 mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_PRESENT_TOP_FIELD (1<<0) +#define DRM_MODE_PRESENT_BOTTOM_FIELD (1<<1) + +/* Planes blend with or override other bits on the CRTC */ +struct drm_mode_set_plane { + __u32 plane_id; + __u32 crtc_id; + __u32 fb_id; /* fb object contains surface format type */ + __u32 flags; /* see above flags */ + + /* Signed dest location allows it to be partially off screen */ + __s32 crtc_x; + __s32 crtc_y; + __u32 crtc_w; + __u32 crtc_h; + + /* Source values are 16.16 fixed point */ + __u32 src_x; + __u32 src_y; + __u32 src_h; + __u32 src_w; +}; + +struct drm_mode_get_plane { + __u32 plane_id; + + __u32 crtc_id; + __u32 fb_id; + + __u32 possible_crtcs; + __u32 gamma_size; + + __u32 count_format_types; + __u64 format_type_ptr; +}; + +struct drm_mode_get_plane_res { + __u64 plane_id_ptr; + __u32 count_planes; +}; + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 + +struct drm_mode_get_encoder { + __u32 encoder_id; + __u32 encoder_type; + + __u32 crtc_id; /**< Id of crtc */ + + __u32 possible_crtcs; + __u32 possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +enum drm_mode_subconnector { + DRM_MODE_SUBCONNECTOR_Automatic = 0, + DRM_MODE_SUBCONNECTOR_Unknown = 0, + DRM_MODE_SUBCONNECTOR_DVID = 3, + DRM_MODE_SUBCONNECTOR_DVIA = 4, + DRM_MODE_SUBCONNECTOR_Composite = 5, + DRM_MODE_SUBCONNECTOR_SVIDEO = 6, + DRM_MODE_SUBCONNECTOR_Component = 8, + DRM_MODE_SUBCONNECTOR_SCART = 9, +}; + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 +#define DRM_MODE_CONNECTOR_WRITEBACK 18 + +struct drm_mode_get_connector { + + __u64 encoders_ptr; + __u64 modes_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + + __u32 count_modes; + __u32 count_props; + __u32 count_encoders; + + __u32 encoder_id; /**< Current Encoder */ + __u32 connector_id; /**< Id */ + __u32 connector_type; + __u32 connector_type_id; + + __u32 connection; + __u32 mm_width; /**< width in millimeters */ + __u32 mm_height; /**< height in millimeters */ + __u32 subpixel; + + __u32 pad; +}; + +#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) +#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ + +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, + * grab a chunk of the bits to use as integer type id. + */ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE(n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) + +/* the PROP_ATOMIC flag is used to hide properties from userspace that + * is not aware of atomic properties. This is mostly to work around + * older userspace (DDX drivers) that read/write each prop they find, + * without being aware that this could be triggering a lengthy modeset. + */ +#define DRM_MODE_PROP_ATOMIC 0x80000000 + +struct drm_mode_property_enum { + __u64 value; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + __u64 values_ptr; /* values and blob lengths */ + __u64 enum_blob_ptr; /* enum and blob id ptrs */ + + __u32 prop_id; + __u32 flags; + char name[DRM_PROP_NAME_LEN]; + + __u32 count_values; + /* This is only used to count enum values, not blobs. The _blobs is + * simply because of a historical reason, i.e. backwards compat. */ + __u32 count_enum_blobs; +}; + +struct drm_mode_connector_set_property { + __u64 value; + __u32 prop_id; + __u32 connector_id; +}; + +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee +#define DRM_MODE_OBJECT_ANY 0 + +struct drm_mode_obj_get_properties { + __u64 props_ptr; + __u64 prop_values_ptr; + __u32 count_props; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_obj_set_property { + __u64 value; + __u32 prop_id; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_get_blob { + __u32 blob_id; + __u32 length; + __u64 data; +}; + +struct drm_mode_fb_cmd { + __u32 fb_id; + __u32 width; + __u32 height; + __u32 pitch; + __u32 bpp; + __u32 depth; + /* driver specific handle */ + __u32 handle; +}; + +#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ +#define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[] */ + +struct drm_mode_fb_cmd2 { + __u32 fb_id; + __u32 width; + __u32 height; + __u32 pixel_format; /* fourcc code from drm_fourcc.h */ + __u32 flags; /* see above flags */ + + /* + * In case of planar formats, this ioctl allows up to 4 + * buffer objects with offsets and pitches per plane. + * The pitch and offset order is dictated by the fourcc, + * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: + * + * YUV 4:2:0 image with a plane of 8 bit Y samples + * followed by an interleaved U/V plane containing + * 8 bit 2x2 subsampled colour difference samples. + * + * So it would consist of Y as offsets[0] and UV as + * offsets[1]. Note that offsets[0] will generally + * be 0 (but this is not required). + * + * To accommodate tiled, compressed, etc formats, a + * modifier can be specified. The default value of zero + * indicates "native" format as specified by the fourcc. + * Vendor specific modifier token. Note that even though + * it looks like we have a modifier per-plane, we in fact + * do not. The modifier for each plane must be identical. + * Thus all combinations of different data layouts for + * multi plane formats must be enumerated as separate + * modifiers. + */ + __u32 handles[4]; + __u32 pitches[4]; /* pitch for each plane */ + __u32 offsets[4]; /* offset of each plane */ + __u64 modifier[4]; /* ie, tiling, compress */ +}; + +#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 +#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 +#define DRM_MODE_FB_DIRTY_FLAGS 0x03 + +#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256 + +/* + * Mark a region of a framebuffer as dirty. + * + * Some hardware does not automatically update display contents + * as a hardware or software draw to a framebuffer. This ioctl + * allows userspace to tell the kernel and the hardware what + * regions of the framebuffer have changed. + * + * The kernel or hardware is free to update more then just the + * region specified by the clip rects. The kernel or hardware + * may also delay and/or coalesce several calls to dirty into a + * single update. + * + * Userspace may annotate the updates, the annotates are a + * promise made by the caller that the change is either a copy + * of pixels or a fill of a single color in the region specified. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then + * the number of updated regions are half of num_clips given, + * where the clip rects are paired in src and dst. The width and + * height of each one of the pairs must match. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller + * promises that the region specified of the clip rects is filled + * completely with a single color as given in the color argument. + */ + +struct drm_mode_fb_dirty_cmd { + __u32 fb_id; + __u32 flags; + __u32 color; + __u32 num_clips; + __u64 clips_ptr; +}; + +struct drm_mode_mode_cmd { + __u32 connector_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 + +/* + * depending on the value in flags different members are used. + * + * CURSOR_BO uses + * crtc_id + * width + * height + * handle - if 0 turns the cursor off + * + * CURSOR_MOVE uses + * crtc_id + * x + * y + */ +struct drm_mode_cursor { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; +}; + +struct drm_mode_cursor2 { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; + __s32 hot_x; + __s32 hot_y; +}; + +struct drm_mode_crtc_lut { + __u32 crtc_id; + __u32 gamma_size; + + /* pointers to arrays */ + __u64 red; + __u64 green; + __u64 blue; +}; + +struct drm_color_ctm { + /* + * Conversion matrix in S31.32 sign-magnitude + * (not two's complement!) format. + */ + __u64 matrix[9]; +}; + +struct drm_color_lut { + /* + * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and + * 0xffff == 1.0. + */ + __u16 red; + __u16 green; + __u16 blue; + __u16 reserved; +}; + +#define DRM_MODE_PAGE_FLIP_EVENT 0x01 +#define DRM_MODE_PAGE_FLIP_ASYNC 0x02 +#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 +#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8 +#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \ + DRM_MODE_PAGE_FLIP_TARGET_RELATIVE) +#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \ + DRM_MODE_PAGE_FLIP_ASYNC | \ + DRM_MODE_PAGE_FLIP_TARGET) + +/* + * Request a page flip on the specified crtc. + * + * This ioctl will ask KMS to schedule a page flip for the specified + * crtc. Once any pending rendering targeting the specified fb (as of + * ioctl time) has completed, the crtc will be reprogrammed to display + * that fb after the next vertical refresh. The ioctl returns + * immediately, but subsequent rendering to the current fb will block + * in the execbuffer ioctl until the page flip happens. If a page + * flip is already pending as the ioctl is called, EBUSY will be + * returned. + * + * Flag DRM_MODE_PAGE_FLIP_EVENT requests that drm sends back a vblank + * event (see drm.h: struct drm_event_vblank) when the page flip is + * done. The user_data field passed in with this ioctl will be + * returned as the user_data field in the vblank event struct. + * + * Flag DRM_MODE_PAGE_FLIP_ASYNC requests that the flip happen + * 'as soon as possible', meaning that it not delay waiting for vblank. + * This may cause tearing on the screen. + * + * The reserved field must be zero. + */ + +struct drm_mode_crtc_page_flip { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 reserved; + __u64 user_data; +}; + +/* + * Request a page flip on the specified crtc. + * + * Same as struct drm_mode_crtc_page_flip, but supports new flags and + * re-purposes the reserved field: + * + * The sequence field must be zero unless either of the + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When + * the ABSOLUTE flag is specified, the sequence field denotes the absolute + * vblank sequence when the flip should take effect. When the RELATIVE + * flag is specified, the sequence field denotes the relative (to the + * current one when the ioctl is called) vblank sequence when the flip + * should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to + * make sure the vblank sequence before the target one has passed before + * calling this ioctl. The purpose of the + * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify + * the target for when code dealing with a page flip runs during a + * vertical blank period. + */ + +struct drm_mode_crtc_page_flip_target { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 sequence; + __u64 user_data; +}; + +/* create a dumb scanout buffer */ +struct drm_mode_create_dumb { + __u32 height; + __u32 width; + __u32 bpp; + __u32 flags; + /* handle, pitch, size will be returned */ + __u32 handle; + __u32 pitch; + __u64 size; +}; + +/* set up for mmap of a dumb scanout buffer */ +struct drm_mode_map_dumb { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_mode_destroy_dumb { + __u32 handle; +}; + +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + +struct drm_format_modifier_blob { +#define FORMAT_BLOB_CURRENT 1 + /* Version of this blob format */ + __u32 version; + + /* Flags */ + __u32 flags; + + /* Number of fourcc formats supported */ + __u32 count_formats; + + /* Where in this blob the formats exist (in bytes) */ + __u32 formats_offset; + + /* Number of drm_format_modifiers */ + __u32 count_modifiers; + + /* Where in this blob the modifiers exist (in bytes) */ + __u32 modifiers_offset; + + /* __u32 formats[] */ + /* struct drm_format_modifier modifiers[] */ +}; + +struct drm_format_modifier { + /* Bitmask of formats in get_plane format list this info applies to. The + * offset allows a sliding window of which 64 formats (bits). + * + * Some examples: + * In today's world with < 65 formats, and formats 0, and 2 are + * supported + * 0x0000000000000005 + * ^-offset = 0, formats = 5 + * + * If the number formats grew to 128, and formats 98-102 are + * supported with the modifier: + * + * 0x0000007c00000000 0000000000000000 + * ^ + * |__offset = 64, formats = 0x7c00000000 + * + */ + __u64 formats; + __u32 offset; + __u32 pad; + + /* The modifier that applies to the >get_plane format list bitmask. */ + __u64 modifier; +}; + +/** + * Create a new 'blob' data property, copying length bytes from data pointer, + * and returning new blob ID. + */ +struct drm_mode_create_blob { + /** Pointer to data to copy. */ + __u64 data; + /** Length of data to copy. */ + __u32 length; + /** Return: new property ID. */ + __u32 blob_id; +}; + +/** + * Destroy a user-created blob property. + */ +struct drm_mode_destroy_blob { + __u32 blob_id; +}; + +/** + * Lease mode resources, creating another drm_master. + */ +struct drm_mode_create_lease { + /** Pointer to array of object ids (__u32) */ + __u64 object_ids; + /** Number of object ids */ + __u32 object_count; + /** flags for new FD (O_CLOEXEC, etc) */ + __u32 flags; + + /** Return: unique identifier for lessee. */ + __u32 lessee_id; + /** Return: file descriptor to new drm_master file */ + __u32 fd; +}; + +/** + * List lesses from a drm_master + */ +struct drm_mode_list_lessees { + /** Number of lessees. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_lessees; + __u32 pad; + + /** Pointer to lessees. + * pointer to __u64 array of lessee ids + */ + __u64 lessees_ptr; +}; + +/** + * Get leased objects + */ +struct drm_mode_get_lease { + /** Number of leased objects. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_objects; + __u32 pad; + + /** Pointer to objects. + * pointer to __u32 array of object ids + */ + __u64 objects_ptr; +}; + +/** + * Revoke lease + */ +struct drm_mode_revoke_lease { + /** Unique ID of lessee + */ + __u32 lessee_id; +}; + +/** + * struct drm_mode_rect - Two dimensional rectangle. + * @x1: Horizontal starting coordinate (inclusive). + * @y1: Vertical starting coordinate (inclusive). + * @x2: Horizontal ending coordinate (exclusive). + * @y2: Vertical ending coordinate (exclusive). + * + * With drm subsystem using struct drm_rect to manage rectangular area this + * export it to user-space. + * + * Currently used by drm_mode_atomic blob property FB_DAMAGE_CLIPS. + */ +struct drm_mode_rect { + __s32 x1; + __s32 y1; + __s32 x2; + __s32 y2; +}; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_sarea.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_sarea.h new file mode 100644 index 0000000..93025be --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/drm_sarea.h @@ -0,0 +1,92 @@ +/** + * \file drm_sarea.h + * \brief SAREA definitions + * + * \author Michel Dänzer + */ + +/* + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* SAREA area needs to be at least a page */ +#if defined(__alpha__) +#define SAREA_MAX 0x2000U +#elif defined(__mips__) +#define SAREA_MAX 0x4000U +#elif defined(__ia64__) +#define SAREA_MAX 0x10000U /* 64kB */ +#else +/* Intel 830M driver needs at least 8k SAREA */ +#define SAREA_MAX 0x2000U +#endif + +/** Maximum number of drawables in the SAREA */ +#define SAREA_MAX_DRAWABLES 256 + +#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000 + +/** SAREA drawable */ +struct drm_sarea_drawable { + unsigned int stamp; + unsigned int flags; +}; + +/** SAREA frame */ +struct drm_sarea_frame { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +}; + +/** SAREA */ +struct drm_sarea { + /** first thing is always the DRM locking structure */ + struct drm_hw_lock lock; + /** \todo Use readers/writer lock for drm_sarea::drawable_lock */ + struct drm_hw_lock drawable_lock; + struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */ + struct drm_sarea_frame frame; /**< frame */ + drm_context_t dummy_context; +}; + +typedef struct drm_sarea_drawable drm_sarea_drawable_t; +typedef struct drm_sarea_frame drm_sarea_frame_t; +typedef struct drm_sarea drm_sarea_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* _DRM_SAREA_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/i915_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/i915_drm.h new file mode 100644 index 0000000..72afd94 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/i915_drm.h @@ -0,0 +1,1915 @@ +/* + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _I915_DRM_H_ +#define _I915_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +/** + * DOC: uevents generated by i915 on it's device node + * + * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch + * event from the gpu l3 cache. Additional information supplied is ROW, + * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep + * track of these events and if a specific cache-line seems to have a + * persistent error remap it with the l3 remapping tool supplied in + * intel-gpu-tools. The value supplied with the event is always 1. + * + * I915_ERROR_UEVENT - Generated upon error detection, currently only via + * hangcheck. The error detection event is a good indicator of when things + * began to go badly. The value supplied with the event is a 1 upon error + * detection, and a 0 upon reset completion, signifying no more error + * exists. NOTE: Disabling hangcheck or reset via module parameter will + * cause the related events to not be seen. + * + * I915_RESET_UEVENT - Event is generated just before an attempt to reset the + * the GPU. The value supplied with the event is always 1. NOTE: Disable + * reset via module parameter will cause this event to not be seen. + */ +#define I915_L3_PARITY_UEVENT "L3_PARITY_ERROR" +#define I915_ERROR_UEVENT "ERROR" +#define I915_RESET_UEVENT "RESET" + +/* + * i915_user_extension: Base class for defining a chain of extensions + * + * Many interfaces need to grow over time. In most cases we can simply + * extend the struct and have userspace pass in more data. Another option, + * as demonstrated by Vulkan's approach to providing extensions for forward + * and backward compatibility, is to use a list of optional structs to + * provide those extra details. + * + * The key advantage to using an extension chain is that it allows us to + * redefine the interface more easily than an ever growing struct of + * increasing complexity, and for large parts of that interface to be + * entirely optional. The downside is more pointer chasing; chasing across + * the boundary with pointers encapsulated inside u64. + */ +struct i915_user_extension { + __u64 next_extension; + __u32 name; + __u32 flags; /* All undefined bits must be zero. */ + __u32 rsvd[4]; /* Reserved for future use; must be zero. */ +}; + +/* + * MOCS indexes used for GPU surfaces, defining the cacheability of the + * surface data and the coherency for this data wrt. CPU vs. GPU accesses. + */ +enum i915_mocs_table_index { + /* + * Not cached anywhere, coherency between CPU and GPU accesses is + * guaranteed. + */ + I915_MOCS_UNCACHED, + /* + * Cacheability and coherency controlled by the kernel automatically + * based on the DRM_I915_GEM_SET_CACHING IOCTL setting and the current + * usage of the surface (used for display scanout or not). + */ + I915_MOCS_PTE, + /* + * Cached in all GPU caches available on the platform. + * Coherency between CPU and GPU accesses to the surface is not + * guaranteed without extra synchronization. + */ + I915_MOCS_CACHED, +}; + +/* + * Different engines serve different roles, and there may be more than one + * engine serving each role. enum drm_i915_gem_engine_class provides a + * classification of the role of the engine, which may be used when requesting + * operations to be performed on a certain subset of engines, or for providing + * information about that group. + */ +enum drm_i915_gem_engine_class { + I915_ENGINE_CLASS_RENDER = 0, + I915_ENGINE_CLASS_COPY = 1, + I915_ENGINE_CLASS_VIDEO = 2, + I915_ENGINE_CLASS_VIDEO_ENHANCE = 3, + + /* should be kept compact */ + + I915_ENGINE_CLASS_INVALID = -1 +}; + +/** + * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915 + * + */ + +enum drm_i915_pmu_engine_sample { + I915_SAMPLE_BUSY = 0, + I915_SAMPLE_WAIT = 1, + I915_SAMPLE_SEMA = 2 +}; + +#define I915_PMU_SAMPLE_BITS (4) +#define I915_PMU_SAMPLE_MASK (0xf) +#define I915_PMU_SAMPLE_INSTANCE_BITS (8) +#define I915_PMU_CLASS_SHIFT \ + (I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS) + +#define __I915_PMU_ENGINE(class, instance, sample) \ + ((class) << I915_PMU_CLASS_SHIFT | \ + (instance) << I915_PMU_SAMPLE_BITS | \ + (sample)) + +#define I915_PMU_ENGINE_BUSY(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY) + +#define I915_PMU_ENGINE_WAIT(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT) + +#define I915_PMU_ENGINE_SEMA(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA) + +#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x)) + +#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0) +#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1) +#define I915_PMU_INTERRUPTS __I915_PMU_OTHER(2) +#define I915_PMU_RC6_RESIDENCY __I915_PMU_OTHER(3) + +#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY + +/* Each region is a minimum of 16k, and there are at most 255 of them. + */ +#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use + * of chars for next/prev indices */ +#define I915_LOG_MIN_TEX_REGION_SIZE 14 + +typedef struct _drm_i915_init { + enum { + I915_INIT_DMA = 0x01, + I915_CLEANUP_DMA = 0x02, + I915_RESUME_DMA = 0x03 + } func; + unsigned int mmio_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; + unsigned int chipset; +} drm_i915_init_t; + +typedef struct _drm_i915_sarea { + struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; + + int pipeA_x; + int pipeA_y; + int pipeA_w; + int pipeA_h; + int pipeB_x; + int pipeB_y; + int pipeB_w; + int pipeB_h; + + /* fill out some space for old userspace triple buffer */ + drm_handle_t unused_handle; + __u32 unused1, unused2, unused3; + + /* buffer object handles for static buffers. May change + * over the lifetime of the client. + */ + __u32 front_bo_handle; + __u32 back_bo_handle; + __u32 unused_bo_handle; + __u32 depth_bo_handle; + +} drm_i915_sarea_t; + +/* due to userspace building against these headers we need some compat here */ +#define planeA_x pipeA_x +#define planeA_y pipeA_y +#define planeA_w pipeA_w +#define planeA_h pipeA_h +#define planeB_x pipeB_x +#define planeB_y pipeB_y +#define planeB_w pipeB_w +#define planeB_h pipeB_h + +/* Flags for perf_boxes + */ +#define I915_BOX_RING_EMPTY 0x1 +#define I915_BOX_FLIP 0x2 +#define I915_BOX_WAIT 0x4 +#define I915_BOX_TEXTURE_LOAD 0x8 +#define I915_BOX_LOST_CONTEXT 0x10 + +/* + * i915 specific ioctls. + * + * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie + * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset + * against DRM_COMMAND_BASE and should be between [0x0, 0x60). + */ +#define DRM_I915_INIT 0x00 +#define DRM_I915_FLUSH 0x01 +#define DRM_I915_FLIP 0x02 +#define DRM_I915_BATCHBUFFER 0x03 +#define DRM_I915_IRQ_EMIT 0x04 +#define DRM_I915_IRQ_WAIT 0x05 +#define DRM_I915_GETPARAM 0x06 +#define DRM_I915_SETPARAM 0x07 +#define DRM_I915_ALLOC 0x08 +#define DRM_I915_FREE 0x09 +#define DRM_I915_INIT_HEAP 0x0a +#define DRM_I915_CMDBUFFER 0x0b +#define DRM_I915_DESTROY_HEAP 0x0c +#define DRM_I915_SET_VBLANK_PIPE 0x0d +#define DRM_I915_GET_VBLANK_PIPE 0x0e +#define DRM_I915_VBLANK_SWAP 0x0f +#define DRM_I915_HWS_ADDR 0x11 +#define DRM_I915_GEM_INIT 0x13 +#define DRM_I915_GEM_EXECBUFFER 0x14 +#define DRM_I915_GEM_PIN 0x15 +#define DRM_I915_GEM_UNPIN 0x16 +#define DRM_I915_GEM_BUSY 0x17 +#define DRM_I915_GEM_THROTTLE 0x18 +#define DRM_I915_GEM_ENTERVT 0x19 +#define DRM_I915_GEM_LEAVEVT 0x1a +#define DRM_I915_GEM_CREATE 0x1b +#define DRM_I915_GEM_PREAD 0x1c +#define DRM_I915_GEM_PWRITE 0x1d +#define DRM_I915_GEM_MMAP 0x1e +#define DRM_I915_GEM_SET_DOMAIN 0x1f +#define DRM_I915_GEM_SW_FINISH 0x20 +#define DRM_I915_GEM_SET_TILING 0x21 +#define DRM_I915_GEM_GET_TILING 0x22 +#define DRM_I915_GEM_GET_APERTURE 0x23 +#define DRM_I915_GEM_MMAP_GTT 0x24 +#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25 +#define DRM_I915_GEM_MADVISE 0x26 +#define DRM_I915_OVERLAY_PUT_IMAGE 0x27 +#define DRM_I915_OVERLAY_ATTRS 0x28 +#define DRM_I915_GEM_EXECBUFFER2 0x29 +#define DRM_I915_GEM_EXECBUFFER2_WR DRM_I915_GEM_EXECBUFFER2 +#define DRM_I915_GET_SPRITE_COLORKEY 0x2a +#define DRM_I915_SET_SPRITE_COLORKEY 0x2b +#define DRM_I915_GEM_WAIT 0x2c +#define DRM_I915_GEM_CONTEXT_CREATE 0x2d +#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e +#define DRM_I915_GEM_SET_CACHING 0x2f +#define DRM_I915_GEM_GET_CACHING 0x30 +#define DRM_I915_REG_READ 0x31 +#define DRM_I915_GET_RESET_STATS 0x32 +#define DRM_I915_GEM_USERPTR 0x33 +#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 +#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 +#define DRM_I915_PERF_OPEN 0x36 +#define DRM_I915_PERF_ADD_CONFIG 0x37 +#define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_QUERY 0x39 +/* Must be kept compact -- no holes */ + +#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) +#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) +#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP) +#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) +#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) +#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) +#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) +#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t) +#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t) +#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) +#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) +#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) +#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) +#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_HWS_ADDR DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init) +#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer) +#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2) +#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2) +#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin) +#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin) +#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy) +#define DRM_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHING, struct drm_i915_gem_caching) +#define DRM_IOCTL_I915_GEM_GET_CACHING DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHING, struct drm_i915_gem_caching) +#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE) +#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) +#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) +#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) +#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) +#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) +#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) +#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) +#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) +#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) +#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) +#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture) +#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id) +#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) +#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image) +#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) +#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) +#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext) +#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) +#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read) +#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats) +#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr) +#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) +#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) +#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) + +/* Allow drivers to submit batchbuffers directly to hardware, relying + * on the security mechanisms provided by hardware. + */ +typedef struct drm_i915_batchbuffer { + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_batchbuffer_t; + +/* As above, but pass a pointer to userspace buffer which can be + * validated by the kernel prior to sending to hardware. + */ +typedef struct _drm_i915_cmdbuffer { + char *buf; /* pointer to userspace command buffer */ + int sz; /* nr bytes in buf */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */ + int num_cliprects; /* mulitpass with multiple cliprects? */ + struct drm_clip_rect *cliprects; /* pointer to userspace cliprects */ +} drm_i915_cmdbuffer_t; + +/* Userspace can request & wait on irq's: + */ +typedef struct drm_i915_irq_emit { + int *irq_seq; +} drm_i915_irq_emit_t; + +typedef struct drm_i915_irq_wait { + int irq_seq; +} drm_i915_irq_wait_t; + +/* + * Different modes of per-process Graphics Translation Table, + * see I915_PARAM_HAS_ALIASING_PPGTT + */ +#define I915_GEM_PPGTT_NONE 0 +#define I915_GEM_PPGTT_ALIASING 1 +#define I915_GEM_PPGTT_FULL 2 + +/* Ioctl to query kernel params: + */ +#define I915_PARAM_IRQ_ACTIVE 1 +#define I915_PARAM_ALLOW_BATCHBUFFER 2 +#define I915_PARAM_LAST_DISPATCH 3 +#define I915_PARAM_CHIPSET_ID 4 +#define I915_PARAM_HAS_GEM 5 +#define I915_PARAM_NUM_FENCES_AVAIL 6 +#define I915_PARAM_HAS_OVERLAY 7 +#define I915_PARAM_HAS_PAGEFLIPPING 8 +#define I915_PARAM_HAS_EXECBUF2 9 +#define I915_PARAM_HAS_BSD 10 +#define I915_PARAM_HAS_BLT 11 +#define I915_PARAM_HAS_RELAXED_FENCING 12 +#define I915_PARAM_HAS_COHERENT_RINGS 13 +#define I915_PARAM_HAS_EXEC_CONSTANTS 14 +#define I915_PARAM_HAS_RELAXED_DELTA 15 +#define I915_PARAM_HAS_GEN7_SOL_RESET 16 +#define I915_PARAM_HAS_LLC 17 +#define I915_PARAM_HAS_ALIASING_PPGTT 18 +#define I915_PARAM_HAS_WAIT_TIMEOUT 19 +#define I915_PARAM_HAS_SEMAPHORES 20 +#define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21 +#define I915_PARAM_HAS_VEBOX 22 +#define I915_PARAM_HAS_SECURE_BATCHES 23 +#define I915_PARAM_HAS_PINNED_BATCHES 24 +#define I915_PARAM_HAS_EXEC_NO_RELOC 25 +#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26 +#define I915_PARAM_HAS_WT 27 +#define I915_PARAM_CMD_PARSER_VERSION 28 +#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29 +#define I915_PARAM_MMAP_VERSION 30 +#define I915_PARAM_HAS_BSD2 31 +#define I915_PARAM_REVISION 32 +#define I915_PARAM_SUBSLICE_TOTAL 33 +#define I915_PARAM_EU_TOTAL 34 +#define I915_PARAM_HAS_GPU_RESET 35 +#define I915_PARAM_HAS_RESOURCE_STREAMER 36 +#define I915_PARAM_HAS_EXEC_SOFTPIN 37 +#define I915_PARAM_HAS_POOLED_EU 38 +#define I915_PARAM_MIN_EU_IN_POOL 39 +#define I915_PARAM_MMAP_GTT_VERSION 40 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution + * priorities and the driver will attempt to execute batches in priority order. + * The param returns a capability bitmask, nonzero implies that the scheduler + * is enabled, with different features present according to the mask. + * + * The initial priority for each batch is supplied by the context and is + * controlled via I915_CONTEXT_PARAM_PRIORITY. + */ +#define I915_PARAM_HAS_SCHEDULER 41 +#define I915_SCHEDULER_CAP_ENABLED (1ul << 0) +#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1) +#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2) +#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3) + +#define I915_PARAM_HUC_STATUS 42 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of + * synchronisation with implicit fencing on individual objects. + * See EXEC_OBJECT_ASYNC. + */ +#define I915_PARAM_HAS_EXEC_ASYNC 43 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support - + * both being able to pass in a sync_file fd to wait upon before executing, + * and being able to return a new sync_file fd that is signaled when the + * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT. + */ +#define I915_PARAM_HAS_EXEC_FENCE 44 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture + * user specified buffers for post-mortem debugging of GPU hangs. See + * EXEC_OBJECT_CAPTURE. + */ +#define I915_PARAM_HAS_EXEC_CAPTURE 45 + +#define I915_PARAM_SLICE_MASK 46 + +/* Assuming it's uniform for each slice, this queries the mask of subslices + * per-slice for this system. + */ +#define I915_PARAM_SUBSLICE_MASK 47 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer + * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST. + */ +#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of + * drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY. + */ +#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49 + +/* + * Query whether every context (both per-file default and user created) is + * isolated (insofar as HW supports). If this parameter is not true, then + * freshly created contexts may inherit values from an existing context, + * rather than default HW values. If true, it also ensures (insofar as HW + * supports) that all state set by this context will not leak to any other + * context. + * + * As not every engine across every gen support contexts, the returned + * value reports the support of context isolation for individual engines by + * returning a bitmask of each engine class set to true if that class supports + * isolation. + */ +#define I915_PARAM_HAS_CONTEXT_ISOLATION 50 + +/* Frequency of the command streamer timestamps given by the *_TIMESTAMP + * registers. This used to be fixed per platform but from CNL onwards, this + * might vary depending on the parts. + */ +#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51 + +/* + * Once upon a time we supposed that writes through the GGTT would be + * immediately in physical memory (once flushed out of the CPU path). However, + * on a few different processors and chipsets, this is not necessarily the case + * as the writes appear to be buffered internally. Thus a read of the backing + * storage (physical memory) via a different path (with different physical tags + * to the indirect write via the GGTT) will see stale values from before + * the GGTT write. Inside the kernel, we can for the most part keep track of + * the different read/write domains in use (e.g. set-domain), but the assumption + * of coherency is baked into the ABI, hence reporting its true state in this + * parameter. + * + * Reports true when writes via mmap_gtt are immediately visible following an + * lfence to flush the WCB. + * + * Reports false when writes via mmap_gtt are indeterminately delayed in an in + * internal buffer and are _not_ immediately visible to third parties accessing + * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC + * communications channel when reporting false is strongly disadvised. + */ +#define I915_PARAM_MMAP_GTT_COHERENT 52 + +/* Must be kept compact -- no holes and well documented */ + +typedef struct drm_i915_getparam { + __s32 param; + /* + * WARNING: Using pointers instead of fixed-size u64 means we need to write + * compat32 code. Don't repeat this mistake. + */ + int *value; +} drm_i915_getparam_t; + +/* Ioctl to set kernel params: + */ +#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 +#define I915_SETPARAM_ALLOW_BATCHBUFFER 3 +#define I915_SETPARAM_NUM_USED_FENCES 4 +/* Must be kept compact -- no holes */ + +typedef struct drm_i915_setparam { + int param; + int value; +} drm_i915_setparam_t; + +/* A memory manager for regions of shared memory: + */ +#define I915_MEM_REGION_AGP 1 + +typedef struct drm_i915_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drm_i915_mem_alloc_t; + +typedef struct drm_i915_mem_free { + int region; + int region_offset; +} drm_i915_mem_free_t; + +typedef struct drm_i915_mem_init_heap { + int region; + int size; + int start; +} drm_i915_mem_init_heap_t; + +/* Allow memory manager to be torn down and re-initialized (eg on + * rotate): + */ +typedef struct drm_i915_mem_destroy_heap { + int region; +} drm_i915_mem_destroy_heap_t; + +/* Allow X server to configure which pipes to monitor for vblank signals + */ +#define DRM_I915_VBLANK_PIPE_A 1 +#define DRM_I915_VBLANK_PIPE_B 2 + +typedef struct drm_i915_vblank_pipe { + int pipe; +} drm_i915_vblank_pipe_t; + +/* Schedule buffer swap at given vertical blank: + */ +typedef struct drm_i915_vblank_swap { + drm_drawable_t drawable; + enum drm_vblank_seq_type seqtype; + unsigned int sequence; +} drm_i915_vblank_swap_t; + +typedef struct drm_i915_hws_addr { + __u64 addr; +} drm_i915_hws_addr_t; + +struct drm_i915_gem_init { + /** + * Beginning offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_start; + /** + * Ending offset in the GTT to be managed by the DRM memory + * manager. + */ + __u64 gtt_end; +}; + +struct drm_i915_gem_create { + /** + * Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + */ + __u64 size; + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** + * Pointer to write the data into. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** + * Pointer to read the data from. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 data_ptr; +}; + +struct drm_i915_gem_mmap { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** Offset in the object to map. */ + __u64 offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + __u64 size; + /** + * Returned pointer the data was mapped at. + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 addr_ptr; + + /** + * Flags for extended behaviour. + * + * Added in version 2. + */ + __u64 flags; +#define I915_MMAP_WC 0x1 +}; + +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_i915_gem_set_domain { + /** Handle for the object */ + __u32 handle; + + /** New read domains */ + __u32 read_domains; + + /** New write domain */ + __u32 write_domain; +}; + +struct drm_i915_gem_sw_finish { + /** Handle for the object */ + __u32 handle; +}; + +struct drm_i915_gem_relocation_entry { + /** + * Handle of the buffer being pointed to by this relocation entry. + * + * It's appealing to make this be an index into the mm_validate_entry + * list to refer to the buffer, but this allows the driver to create + * a relocation list for state buffers and not re-write it per + * exec using the buffer. + */ + __u32 target_handle; + + /** + * Value to be added to the offset of the target buffer to make up + * the relocation entry. + */ + __u32 delta; + + /** Offset in the buffer the relocation entry will be written into */ + __u64 offset; + + /** + * Offset value of the target buffer that the relocation entry was last + * written as. + * + * If the buffer has the same offset as last time, we can skip syncing + * and writing the relocation. This value is written back out by + * the execbuffer ioctl when the relocation is written. + */ + __u64 presumed_offset; + + /** + * Target memory domains read by this operation. + */ + __u32 read_domains; + + /** + * Target memory domains written by this operation. + * + * Note that only one domain may be written by the whole + * execbuffer operation, so that where there are conflicts, + * the application will get -EINVAL back. + */ + __u32 write_domain; +}; + +/** @{ + * Intel memory domains + * + * Most of these just align with the various caches in + * the system and are used to flush and invalidate as + * objects end up cached in different domains. + */ +/** CPU cache */ +#define I915_GEM_DOMAIN_CPU 0x00000001 +/** Render cache, used by 2D and 3D drawing */ +#define I915_GEM_DOMAIN_RENDER 0x00000002 +/** Sampler cache, used by texture engine */ +#define I915_GEM_DOMAIN_SAMPLER 0x00000004 +/** Command queue, used to load batch buffers */ +#define I915_GEM_DOMAIN_COMMAND 0x00000008 +/** Instruction cache, used by shader programs */ +#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010 +/** Vertex address cache */ +#define I915_GEM_DOMAIN_VERTEX 0x00000020 +/** GTT domain - aperture and scanout */ +#define I915_GEM_DOMAIN_GTT 0x00000040 +/** WC domain - uncached access */ +#define I915_GEM_DOMAIN_WC 0x00000080 +/** @} */ + +struct drm_i915_gem_exec_object { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * Returned value of the updated offset of the object, for future + * presumed_offset writes. + */ + __u64 offset; +}; + +struct drm_i915_gem_execbuffer { + /** + * List of buffers to be validated with their relocations to be + * performend on them. + * + * This is a pointer to an array of struct drm_i915_gem_validate_entry. + * + * These buffers must be listed in an order such that all relocations + * a buffer is performing refer to buffers that have already appeared + * in the validate list. + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** This is a struct drm_clip_rect *cliprects */ + __u64 cliprects_ptr; +}; + +struct drm_i915_gem_exec_object2 { + /** + * User's handle for a buffer to be bound into the GTT for this + * operation. + */ + __u32 handle; + + /** Number of relocations to be performed on this buffer */ + __u32 relocation_count; + /** + * Pointer to array of struct drm_i915_gem_relocation_entry containing + * the relocations to be performed in this buffer. + */ + __u64 relocs_ptr; + + /** Required alignment in graphics aperture */ + __u64 alignment; + + /** + * When the EXEC_OBJECT_PINNED flag is specified this is populated by + * the user with the GTT offset at which this object will be pinned. + * When the I915_EXEC_NO_RELOC flag is specified this must contain the + * presumed_offset of the object. + * During execbuffer2 the kernel populates it with the value of the + * current GTT offset of the object, for future presumed_offset writes. + */ + __u64 offset; + +#define EXEC_OBJECT_NEEDS_FENCE (1<<0) +#define EXEC_OBJECT_NEEDS_GTT (1<<1) +#define EXEC_OBJECT_WRITE (1<<2) +#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3) +#define EXEC_OBJECT_PINNED (1<<4) +#define EXEC_OBJECT_PAD_TO_SIZE (1<<5) +/* The kernel implicitly tracks GPU activity on all GEM objects, and + * synchronises operations with outstanding rendering. This includes + * rendering on other devices if exported via dma-buf. However, sometimes + * this tracking is too coarse and the user knows better. For example, + * if the object is split into non-overlapping ranges shared between different + * clients or engines (i.e. suballocating objects), the implicit tracking + * by kernel assumes that each operation affects the whole object rather + * than an individual range, causing needless synchronisation between clients. + * The kernel will also forgo any CPU cache flushes prior to rendering from + * the object as the client is expected to be also handling such domain + * tracking. + * + * The kernel maintains the implicit tracking in order to manage resources + * used by the GPU - this flag only disables the synchronisation prior to + * rendering with this object in this execbuf. + * + * Opting out of implicit synhronisation requires the user to do its own + * explicit tracking to avoid rendering corruption. See, for example, + * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously. + */ +#define EXEC_OBJECT_ASYNC (1<<6) +/* Request that the contents of this execobject be copied into the error + * state upon a GPU hang involving this batch for post-mortem debugging. + * These buffers are recorded in no particular order as "user" in + * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see + * if the kernel supports this flag. + */ +#define EXEC_OBJECT_CAPTURE (1<<7) +/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */ +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1) + __u64 flags; + + union { + __u64 rsvd1; + __u64 pad_to_size; + }; + __u64 rsvd2; +}; + +struct drm_i915_gem_exec_fence { + /** + * User's handle for a drm_syncobj to wait on or signal. + */ + __u32 handle; + +#define I915_EXEC_FENCE_WAIT (1<<0) +#define I915_EXEC_FENCE_SIGNAL (1<<1) +#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1)) + __u32 flags; +}; + +struct drm_i915_gem_execbuffer2 { + /** + * List of gem_exec_object2 structs + */ + __u64 buffers_ptr; + __u32 buffer_count; + + /** Offset in the batchbuffer to start execution from. */ + __u32 batch_start_offset; + /** Bytes used in batchbuffer from batch_start_offset */ + __u32 batch_len; + __u32 DR1; + __u32 DR4; + __u32 num_cliprects; + /** + * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY + * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a + * struct drm_i915_gem_exec_fence *fences. + */ + __u64 cliprects_ptr; +#define I915_EXEC_RING_MASK (0x3f) +#define I915_EXEC_DEFAULT (0<<0) +#define I915_EXEC_RENDER (1<<0) +#define I915_EXEC_BSD (2<<0) +#define I915_EXEC_BLT (3<<0) +#define I915_EXEC_VEBOX (4<<0) + +/* Used for switching the constants addressing mode on gen4+ RENDER ring. + * Gen6+ only supports relative addressing to dynamic state (default) and + * absolute addressing. + * + * These flags are ignored for the BSD and BLT rings. + */ +#define I915_EXEC_CONSTANTS_MASK (3<<6) +#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */ +#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) +#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ + __u64 flags; + __u64 rsvd1; /* now used for context info */ + __u64 rsvd2; +}; + +/** Resets the SO write offset registers for transform feedback on gen7. */ +#define I915_EXEC_GEN7_SOL_RESET (1<<8) + +/** Request a privileged ("secure") batch buffer. Note only available for + * DRM_ROOT_ONLY | DRM_MASTER processes. + */ +#define I915_EXEC_SECURE (1<<9) + +/** Inform the kernel that the batch is and will always be pinned. This + * negates the requirement for a workaround to be performed to avoid + * an incoherent CS (such as can be found on 830/845). If this flag is + * not passed, the kernel will endeavour to make sure the batch is + * coherent with the CS before execution. If this flag is passed, + * userspace assumes the responsibility for ensuring the same. + */ +#define I915_EXEC_IS_PINNED (1<<10) + +/** Provide a hint to the kernel that the command stream and auxiliary + * state buffers already holds the correct presumed addresses and so the + * relocation process may be skipped if no buffers need to be moved in + * preparation for the execbuffer. + */ +#define I915_EXEC_NO_RELOC (1<<11) + +/** Use the reloc.handle as an index into the exec object array rather + * than as the per-file handle. + */ +#define I915_EXEC_HANDLE_LUT (1<<12) + +/** Used for switching BSD rings on the platforms with two BSD rings */ +#define I915_EXEC_BSD_SHIFT (13) +#define I915_EXEC_BSD_MASK (3 << I915_EXEC_BSD_SHIFT) +/* default ping-pong mode */ +#define I915_EXEC_BSD_DEFAULT (0 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING1 (1 << I915_EXEC_BSD_SHIFT) +#define I915_EXEC_BSD_RING2 (2 << I915_EXEC_BSD_SHIFT) + +/** Tell the kernel that the batchbuffer is processed by + * the resource streamer. + */ +#define I915_EXEC_RESOURCE_STREAMER (1<<15) + +/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent + * a sync_file fd to wait upon (in a nonblocking manner) prior to executing + * the batch. + * + * Returns -EINVAL if the sync_file fd cannot be found. + */ +#define I915_EXEC_FENCE_IN (1<<16) + +/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd + * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given + * to the caller, and it should be close() after use. (The fd is a regular + * file descriptor and will be cleaned up on process termination. It holds + * a reference to the request, but nothing else.) + * + * The sync_file fd can be combined with other sync_file and passed either + * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip + * will only occur after this request completes), or to other devices. + * + * Using I915_EXEC_FENCE_OUT requires use of + * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written + * back to userspace. Failure to do so will cause the out-fence to always + * be reported as zero, and the real fence fd to be leaked. + */ +#define I915_EXEC_FENCE_OUT (1<<17) + +/* + * Traditionally the execbuf ioctl has only considered the final element in + * the execobject[] to be the executable batch. Often though, the client + * will known the batch object prior to construction and being able to place + * it into the execobject[] array first can simplify the relocation tracking. + * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the + * execobject[] as the * batch instead (the default is to use the last + * element). + */ +#define I915_EXEC_BATCH_FIRST (1<<18) + +/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr + * define an array of i915_gem_exec_fence structures which specify a set of + * dma fences to wait upon or signal. + */ +#define I915_EXEC_FENCE_ARRAY (1<<19) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1)) + +#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) +#define i915_execbuffer2_set_context_id(eb2, context) \ + (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK +#define i915_execbuffer2_get_context_id(eb2) \ + ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) + +struct drm_i915_gem_pin { + /** Handle of the buffer to be pinned. */ + __u32 handle; + __u32 pad; + + /** alignment required within the aperture */ + __u64 alignment; + + /** Returned GTT offset of the buffer. */ + __u64 offset; +}; + +struct drm_i915_gem_unpin { + /** Handle of the buffer to be unpinned. */ + __u32 handle; + __u32 pad; +}; + +struct drm_i915_gem_busy { + /** Handle of the buffer to check for busy */ + __u32 handle; + + /** Return busy status + * + * A return of 0 implies that the object is idle (after + * having flushed any pending activity), and a non-zero return that + * the object is still in-flight on the GPU. (The GPU has not yet + * signaled completion for all pending requests that reference the + * object.) An object is guaranteed to become idle eventually (so + * long as no new GPU commands are executed upon it). Due to the + * asynchronous nature of the hardware, an object reported + * as busy may become idle before the ioctl is completed. + * + * Furthermore, if the object is busy, which engine is busy is only + * provided as a guide and only indirectly by reporting its class + * (there may be more than one engine in each class). There are race + * conditions which prevent the report of which engines are busy from + * being always accurate. However, the converse is not true. If the + * object is idle, the result of the ioctl, that all engines are idle, + * is accurate. + * + * The returned dword is split into two fields to indicate both + * the engine classess on which the object is being read, and the + * engine class on which it is currently being written (if any). + * + * The low word (bits 0:15) indicate if the object is being written + * to by any engine (there can only be one, as the GEM implicit + * synchronisation rules force writes to be serialised). Only the + * engine class (offset by 1, I915_ENGINE_CLASS_RENDER is reported as + * 1 not 0 etc) for the last write is reported. + * + * The high word (bits 16:31) are a bitmask of which engines classes + * are currently reading from the object. Multiple engines may be + * reading from the object simultaneously. + * + * The value of each engine class is the same as specified in the + * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e. + * I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc. + * reported as active itself. Some hardware may have parallel + * execution engines, e.g. multiple media engines, which are + * mapped to the same class identifier and so are not separately + * reported for busyness. + * + * Caveat emptor: + * Only the boolean result of this query is reliable; that is whether + * the object is idle or busy. The report of which engines are busy + * should be only used as a heuristic. + */ + __u32 busy; +}; + +/** + * I915_CACHING_NONE + * + * GPU access is not coherent with cpu caches. Default for machines without an + * LLC. + */ +#define I915_CACHING_NONE 0 +/** + * I915_CACHING_CACHED + * + * GPU access is coherent with cpu caches and furthermore the data is cached in + * last-level caches shared between cpu cores and the gpu GT. Default on + * machines with HAS_LLC. + */ +#define I915_CACHING_CACHED 1 +/** + * I915_CACHING_DISPLAY + * + * Special GPU caching mode which is coherent with the scanout engines. + * Transparently falls back to I915_CACHING_NONE on platforms where no special + * cache mode (like write-through or gfdt flushing) is available. The kernel + * automatically sets this mode when using a buffer as a scanout target. + * Userspace can manually set this mode to avoid a costly stall and clflush in + * the hotpath of drawing the first frame. + */ +#define I915_CACHING_DISPLAY 2 + +struct drm_i915_gem_caching { + /** + * Handle of the buffer to set/get the caching level of. */ + __u32 handle; + + /** + * Caching level to apply or return value + * + * bits0-15 are for generic caching control (i.e. the above defined + * values). bits16-31 are reserved for platform-specific variations + * (e.g. l3$ caching on gen7). */ + __u32 caching; +}; + +#define I915_TILING_NONE 0 +#define I915_TILING_X 1 +#define I915_TILING_Y 2 +#define I915_TILING_LAST I915_TILING_Y + +#define I915_BIT_6_SWIZZLE_NONE 0 +#define I915_BIT_6_SWIZZLE_9 1 +#define I915_BIT_6_SWIZZLE_9_10 2 +#define I915_BIT_6_SWIZZLE_9_11 3 +#define I915_BIT_6_SWIZZLE_9_10_11 4 +/* Not seen by userland */ +#define I915_BIT_6_SWIZZLE_UNKNOWN 5 +/* Seen by userland. */ +#define I915_BIT_6_SWIZZLE_9_17 6 +#define I915_BIT_6_SWIZZLE_9_10_17 7 + +struct drm_i915_gem_set_tiling { + /** Handle of the buffer to have its tiling state updated */ + __u32 handle; + + /** + * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + * + * This value is to be set on request, and will be updated by the + * kernel on successful return with the actual chosen tiling layout. + * + * The tiling mode may be demoted to I915_TILING_NONE when the system + * has bit 6 swizzling that can't be managed correctly by GEM. + * + * Buffer contents become undefined when changing tiling_mode. + */ + __u32 tiling_mode; + + /** + * Stride in bytes for the object when in I915_TILING_X or + * I915_TILING_Y. + */ + __u32 stride; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; +}; + +struct drm_i915_gem_get_tiling { + /** Handle of the buffer to get tiling state for. */ + __u32 handle; + + /** + * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X, + * I915_TILING_Y). + */ + __u32 tiling_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping. + */ + __u32 swizzle_mode; + + /** + * Returned address bit 6 swizzling required for CPU access through + * mmap mapping whilst bound. + */ + __u32 phys_swizzle_mode; +}; + +struct drm_i915_gem_get_aperture { + /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ + __u64 aper_size; + + /** + * Available space in the aperture used by i915_gem_execbuffer, in + * bytes + */ + __u64 aper_available_size; +}; + +struct drm_i915_get_pipe_from_crtc_id { + /** ID of CRTC being requested **/ + __u32 crtc_id; + + /** pipe of requested CRTC **/ + __u32 pipe; +}; + +#define I915_MADV_WILLNEED 0 +#define I915_MADV_DONTNEED 1 +#define __I915_MADV_PURGED 2 /* internal state */ + +struct drm_i915_gem_madvise { + /** Handle of the buffer to change the backing store advice */ + __u32 handle; + + /* Advice: either the buffer will be needed again in the near future, + * or wont be and could be discarded under memory pressure. + */ + __u32 madv; + + /** Whether the backing store still exists. */ + __u32 retained; +}; + +/* flags */ +#define I915_OVERLAY_TYPE_MASK 0xff +#define I915_OVERLAY_YUV_PLANAR 0x01 +#define I915_OVERLAY_YUV_PACKED 0x02 +#define I915_OVERLAY_RGB 0x03 + +#define I915_OVERLAY_DEPTH_MASK 0xff00 +#define I915_OVERLAY_RGB24 0x1000 +#define I915_OVERLAY_RGB16 0x2000 +#define I915_OVERLAY_RGB15 0x3000 +#define I915_OVERLAY_YUV422 0x0100 +#define I915_OVERLAY_YUV411 0x0200 +#define I915_OVERLAY_YUV420 0x0300 +#define I915_OVERLAY_YUV410 0x0400 + +#define I915_OVERLAY_SWAP_MASK 0xff0000 +#define I915_OVERLAY_NO_SWAP 0x000000 +#define I915_OVERLAY_UV_SWAP 0x010000 +#define I915_OVERLAY_Y_SWAP 0x020000 +#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000 + +#define I915_OVERLAY_FLAGS_MASK 0xff000000 +#define I915_OVERLAY_ENABLE 0x01000000 + +struct drm_intel_overlay_put_image { + /* various flags and src format description */ + __u32 flags; + /* source picture description */ + __u32 bo_handle; + /* stride values and offsets are in bytes, buffer relative */ + __u16 stride_Y; /* stride for packed formats */ + __u16 stride_UV; + __u32 offset_Y; /* offset for packet formats */ + __u32 offset_U; + __u32 offset_V; + /* in pixels */ + __u16 src_width; + __u16 src_height; + /* to compensate the scaling factors for partially covered surfaces */ + __u16 src_scan_width; + __u16 src_scan_height; + /* output crtc description */ + __u32 crtc_id; + __u16 dst_x; + __u16 dst_y; + __u16 dst_width; + __u16 dst_height; +}; + +/* flags */ +#define I915_OVERLAY_UPDATE_ATTRS (1<<0) +#define I915_OVERLAY_UPDATE_GAMMA (1<<1) +#define I915_OVERLAY_DISABLE_DEST_COLORKEY (1<<2) +struct drm_intel_overlay_attrs { + __u32 flags; + __u32 color_key; + __s32 brightness; + __u32 contrast; + __u32 saturation; + __u32 gamma0; + __u32 gamma1; + __u32 gamma2; + __u32 gamma3; + __u32 gamma4; + __u32 gamma5; +}; + +/* + * Intel sprite handling + * + * Color keying works with a min/mask/max tuple. Both source and destination + * color keying is allowed. + * + * Source keying: + * Sprite pixels within the min & max values, masked against the color channels + * specified in the mask field, will be transparent. All other pixels will + * be displayed on top of the primary plane. For RGB surfaces, only the min + * and mask fields will be used; ranged compares are not allowed. + * + * Destination keying: + * Primary plane pixels that match the min value, masked against the color + * channels specified in the mask field, will be replaced by corresponding + * pixels from the sprite plane. + * + * Note that source & destination keying are exclusive; only one can be + * active on a given plane. + */ + +#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set + * flags==0 to disable colorkeying. + */ +#define I915_SET_COLORKEY_DESTINATION (1<<1) +#define I915_SET_COLORKEY_SOURCE (1<<2) +struct drm_intel_sprite_colorkey { + __u32 plane_id; + __u32 min_value; + __u32 channel_mask; + __u32 max_value; + __u32 flags; +}; + +struct drm_i915_gem_wait { + /** Handle of BO we shall wait on */ + __u32 bo_handle; + __u32 flags; + /** Number of nanoseconds to wait, Returns time remaining. */ + __s64 timeout_ns; +}; + +struct drm_i915_gem_context_create { + __u32 ctx_id; /* output: id of new context*/ + __u32 pad; +}; + +struct drm_i915_gem_context_create_ext { + __u32 ctx_id; /* output: id of new context*/ + __u32 flags; +#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0) +#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \ + (-(I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS << 1)) + __u64 extensions; +}; + +struct drm_i915_gem_context_param { + __u32 ctx_id; + __u32 size; + __u64 param; +#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1 +#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2 +#define I915_CONTEXT_PARAM_GTT_SIZE 0x3 +#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4 +#define I915_CONTEXT_PARAM_BANNABLE 0x5 +#define I915_CONTEXT_PARAM_PRIORITY 0x6 +#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */ +#define I915_CONTEXT_DEFAULT_PRIORITY 0 +#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */ + /* + * When using the following param, value should be a pointer to + * drm_i915_gem_context_param_sseu. + */ +#define I915_CONTEXT_PARAM_SSEU 0x7 + +/* + * Not all clients may want to attempt automatic recover of a context after + * a hang (for example, some clients may only submit very small incremental + * batches relying on known logical state of previous batches which will never + * recover correctly and each attempt will hang), and so would prefer that + * the context is forever banned instead. + * + * If set to false (0), after a reset, subsequent (and in flight) rendering + * from this context is discarded, and the client will need to create a new + * context to use instead. + * + * If set to true (1), the kernel will automatically attempt to recover the + * context by skipping the hanging batch and executing the next batch starting + * from the default context state (discarding the incomplete logical context + * state lost due to the reset). + * + * On creation, all new contexts are marked as recoverable. + */ +#define I915_CONTEXT_PARAM_RECOVERABLE 0x8 +/* Must be kept compact -- no holes and well documented */ + + __u64 value; +}; + +/** + * Context SSEU programming + * + * It may be necessary for either functional or performance reason to configure + * a context to run with a reduced number of SSEU (where SSEU stands for Slice/ + * Sub-slice/EU). + * + * This is done by configuring SSEU configuration using the below + * @struct drm_i915_gem_context_param_sseu for every supported engine which + * userspace intends to use. + * + * Not all GPUs or engines support this functionality in which case an error + * code -ENODEV will be returned. + * + * Also, flexibility of possible SSEU configuration permutations varies between + * GPU generations and software imposed limitations. Requesting such a + * combination will return an error code of -EINVAL. + * + * NOTE: When perf/OA is active the context's SSEU configuration is ignored in + * favour of a single global setting. + */ +struct drm_i915_gem_context_param_sseu { + /* + * Engine class & instance to be configured or queried. + */ + __u16 engine_class; + __u16 engine_instance; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Mask of slices to enable for the context. Valid values are a subset + * of the bitmask value returned for I915_PARAM_SLICE_MASK. + */ + __u64 slice_mask; + + /* + * Mask of subslices to enable for the context. Valid values are a + * subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK. + */ + __u64 subslice_mask; + + /* + * Minimum/Maximum number of EUs to enable per subslice for the + * context. min_eus_per_subslice must be inferior or equal to + * max_eus_per_subslice. + */ + __u16 min_eus_per_subslice; + __u16 max_eus_per_subslice; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 rsvd; +}; + +struct drm_i915_gem_context_create_ext_setparam { +#define I915_CONTEXT_CREATE_EXT_SETPARAM 0 + struct i915_user_extension base; + struct drm_i915_gem_context_param param; +}; + +struct drm_i915_gem_context_destroy { + __u32 ctx_id; + __u32 pad; +}; + +/* + * DRM_I915_GEM_VM_CREATE - + * + * Create a new virtual memory address space (ppGTT) for use within a context + * on the same file. Extensions can be provided to configure exactly how the + * address space is setup upon creation. + * + * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is + * returned in the outparam @id. + * + * No flags are defined, with all bits reserved and must be zero. + * + * An extension chain maybe provided, starting with @extensions, and terminated + * by the @next_extension being 0. Currently, no extensions are defined. + * + * DRM_I915_GEM_VM_DESTROY - + * + * Destroys a previously created VM id, specified in @id. + * + * No extensions or flags are allowed currently, and so must be zero. + */ +struct drm_i915_gem_vm_control { + __u64 extensions; + __u32 flags; + __u32 vm_id; +}; + +struct drm_i915_reg_read { + /* + * Register offset. + * For 64bit wide registers where the upper 32bits don't immediately + * follow the lower 32bits, the offset of the lower 32bits must + * be specified + */ + __u64 offset; +#define I915_REG_READ_8B_WA (1ul << 0) + + __u64 val; /* Return value */ +}; + +/* Known registers: + * + * Render engine timestamp - 0x2358 + 64bit - gen7+ + * - Note this register returns an invalid value if using the default + * single instruction 8byte read, in order to workaround that pass + * flag I915_REG_READ_8B_WA in offset field. + * + */ + +struct drm_i915_reset_stats { + __u32 ctx_id; + __u32 flags; + + /* All resets since boot/module reload, for all contexts */ + __u32 reset_count; + + /* Number of batches lost when active in GPU, for this context */ + __u32 batch_active; + + /* Number of batches lost pending for execution, for this context */ + __u32 batch_pending; + + __u32 pad; +}; + +struct drm_i915_gem_userptr { + __u64 user_ptr; + __u64 user_size; + __u32 flags; +#define I915_USERPTR_READ_ONLY 0x1 +#define I915_USERPTR_UNSYNCHRONIZED 0x80000000 + /** + * Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; +}; + +enum drm_i915_oa_format { + I915_OA_FORMAT_A13 = 1, /* HSW only */ + I915_OA_FORMAT_A29, /* HSW only */ + I915_OA_FORMAT_A13_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8, /* HSW only */ + I915_OA_FORMAT_A45_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8_A16, /* HSW only */ + I915_OA_FORMAT_C4_B8, /* HSW+ */ + + /* Gen8+ */ + I915_OA_FORMAT_A12, + I915_OA_FORMAT_A12_B8_C8, + I915_OA_FORMAT_A32u40_A4u32_B8_C8, + + I915_OA_FORMAT_MAX /* non-ABI */ +}; + +enum drm_i915_perf_property_id { + /** + * Open the stream for a specific context handle (as used with + * execbuffer2). A stream opened for a specific context this way + * won't typically require root privileges. + */ + DRM_I915_PERF_PROP_CTX_HANDLE = 1, + + /** + * A value of 1 requests the inclusion of raw OA unit reports as + * part of stream samples. + */ + DRM_I915_PERF_PROP_SAMPLE_OA, + + /** + * The value specifies which set of OA unit metrics should be + * be configured, defining the contents of any OA unit reports. + */ + DRM_I915_PERF_PROP_OA_METRICS_SET, + + /** + * The value specifies the size and layout of OA unit reports. + */ + DRM_I915_PERF_PROP_OA_FORMAT, + + /** + * Specifying this property implicitly requests periodic OA unit + * sampling and (at least on Haswell) the sampling frequency is derived + * from this exponent as follows: + * + * 80ns * 2^(period_exponent + 1) + */ + DRM_I915_PERF_PROP_OA_EXPONENT, + + DRM_I915_PERF_PROP_MAX /* non-ABI */ +}; + +struct drm_i915_perf_open_param { + __u32 flags; +#define I915_PERF_FLAG_FD_CLOEXEC (1<<0) +#define I915_PERF_FLAG_FD_NONBLOCK (1<<1) +#define I915_PERF_FLAG_DISABLED (1<<2) + + /** The number of u64 (id, value) pairs */ + __u32 num_properties; + + /** + * Pointer to array of u64 (id, value) pairs configuring the stream + * to open. + */ + __u64 properties_ptr; +}; + +/** + * Enable data capture for a stream that was either opened in a disabled state + * via I915_PERF_FLAG_DISABLED or was later disabled via + * I915_PERF_IOCTL_DISABLE. + * + * It is intended to be cheaper to disable and enable a stream than it may be + * to close and re-open a stream with the same configuration. + * + * It's undefined whether any pending data for the stream will be lost. + */ +#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0) + +/** + * Disable data capture for a stream. + * + * It is an error to try and read a stream that is disabled. + */ +#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1) + +/** + * Common to all i915 perf records + */ +struct drm_i915_perf_record_header { + __u32 type; + __u16 pad; + __u16 size; +}; + +enum drm_i915_perf_record_type { + + /** + * Samples are the work horse record type whose contents are extensible + * and defined when opening an i915 perf stream based on the given + * properties. + * + * Boolean properties following the naming convention + * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in + * every sample. + * + * The order of these sample properties given by userspace has no + * affect on the ordering of data within a sample. The order is + * documented here. + * + * struct { + * struct drm_i915_perf_record_header header; + * + * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA + * }; + */ + DRM_I915_PERF_RECORD_SAMPLE = 1, + + /* + * Indicates that one or more OA reports were not written by the + * hardware. This can happen for example if an MI_REPORT_PERF_COUNT + * command collides with periodic sampling - which would be more likely + * at higher sampling frequencies. + */ + DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2, + + /** + * An error occurred that resulted in all pending OA reports being lost. + */ + DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3, + + DRM_I915_PERF_RECORD_MAX /* non-ABI */ +}; + +/** + * Structure to upload perf dynamic configuration into the kernel. + */ +struct drm_i915_perf_oa_config { + /** String formatted like "%08x-%04x-%04x-%04x-%012x" */ + char uuid[36]; + + __u32 n_mux_regs; + __u32 n_boolean_regs; + __u32 n_flex_regs; + + /* + * These fields are pointers to tuples of u32 values (register address, + * value). For example the expected length of the buffer pointed by + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). + */ + __u64 mux_regs_ptr; + __u64 boolean_regs_ptr; + __u64 flex_regs_ptr; +}; + +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_TOPOLOGY_INFO 1 +/* Must be kept compact -- no holes and well documented */ + + /* + * When set to zero by userspace, this is filled with the size of the + * data to be written at the data_ptr pointer. The kernel sets this + * value to a negative value to signal an error on a particular query + * item. + */ + __s32 length; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Data will be written at the location pointed by data_ptr when the + * value of length matches the length of the data to be written by the + * kernel. + */ + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * This points to an array of num_items drm_i915_query_item structures. + */ + __u64 items_ptr; +}; + +/* + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : + * + * data: contains the 3 pieces of information : + * + * - the slice mask with one bit per slice telling whether a slice is + * available. The availability of slice X can be queried with the following + * formula : + * + * (data[X / 8] >> (X % 8)) & 1 + * + * - the subslice mask for each slice with one bit per subslice telling + * whether a subslice is available. The availability of subslice Y in slice + * X can be queried with the following formula : + * + * (data[subslice_offset + + * X * subslice_stride + + * Y / 8] >> (Y % 8)) & 1 + * + * - the EU mask for each subslice in each slice with one bit per EU telling + * whether an EU is available. The availability of EU Z in subslice Y in + * slice X can be queried with the following formula : + * + * (data[eu_offset + + * (X * max_subslices + Y) * eu_stride + + * Z / 8] >> (Z % 8)) & 1 + */ +struct drm_i915_query_topology_info { + /* + * Unused for now. Must be cleared to zero. + */ + __u16 flags; + + __u16 max_slices; + __u16 max_subslices; + __u16 max_eus_per_subslice; + + /* + * Offset in data[] at which the subslice masks are stored. + */ + __u16 subslice_offset; + + /* + * Stride at which each of the subslice masks for each slice are + * stored. + */ + __u16 subslice_stride; + + /* + * Offset in data[] at which the EU masks are stored. + */ + __u16 eu_offset; + + /* + * Stride at which each of the EU masks for each subslice are stored. + */ + __u16 eu_stride; + + __u8 data[]; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _I915_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mach64_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mach64_drm.h new file mode 100644 index 0000000..1f5fd84 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mach64_drm.h @@ -0,0 +1,256 @@ +/* mach64_drm.h -- Public header for the mach64 driver -*- linux-c -*- + * Created: Thu Nov 30 20:04:32 2000 by gareth@valinux.com + */ +/* + * Copyright 2000 Gareth Hughes + * Copyright 2002 Frank C. Earl + * Copyright 2002-2003 Leif Delgass + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Frank C. Earl + * Leif Delgass + */ + +#ifndef __MACH64_DRM_H__ +#define __MACH64_DRM_H__ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mach64_sarea.h) + */ +#ifndef __MACH64_SAREA_DEFINES__ +#define __MACH64_SAREA_DEFINES__ + +/* What needs to be changed for the current vertex buffer? + * GH: We're going to be pedantic about this. We want the card to do as + * little as possible, so let's avoid having it fetch a whole bunch of + * register values that don't change all that often, if at all. + */ +#define MACH64_UPLOAD_DST_OFF_PITCH 0x0001 +#define MACH64_UPLOAD_Z_OFF_PITCH 0x0002 +#define MACH64_UPLOAD_Z_ALPHA_CNTL 0x0004 +#define MACH64_UPLOAD_SCALE_3D_CNTL 0x0008 +#define MACH64_UPLOAD_DP_FOG_CLR 0x0010 +#define MACH64_UPLOAD_DP_WRITE_MASK 0x0020 +#define MACH64_UPLOAD_DP_PIX_WIDTH 0x0040 +#define MACH64_UPLOAD_SETUP_CNTL 0x0080 +#define MACH64_UPLOAD_MISC 0x0100 +#define MACH64_UPLOAD_TEXTURE 0x0200 +#define MACH64_UPLOAD_TEX0IMAGE 0x0400 +#define MACH64_UPLOAD_TEX1IMAGE 0x0800 +#define MACH64_UPLOAD_CLIPRECTS 0x1000 /* handled client-side */ +#define MACH64_UPLOAD_CONTEXT 0x00ff +#define MACH64_UPLOAD_ALL 0x1fff + +/* DMA buffer size + */ +#define MACH64_BUFFER_SIZE 16384 + +/* Max number of swaps allowed on the ring + * before the client must wait + */ +#define MACH64_MAX_QUEUED_FRAMES 3U + +/* Byte offsets for host blit buffer data + */ +#define MACH64_HOSTDATA_BLIT_OFFSET 104 + +/* Keep these small for testing. + */ +#define MACH64_NR_SAREA_CLIPRECTS 8 + +#define MACH64_CARD_HEAP 0 +#define MACH64_AGP_HEAP 1 +#define MACH64_NR_TEX_HEAPS 2 +#define MACH64_NR_TEX_REGIONS 64 +#define MACH64_LOG_TEX_GRANULARITY 16 + +#define MACH64_TEX_MAXLEVELS 1 + +#define MACH64_NR_CONTEXT_REGS 15 +#define MACH64_NR_TEXTURE_REGS 4 + +#endif /* __MACH64_SAREA_DEFINES__ */ + +typedef struct { + unsigned int dst_off_pitch; + + unsigned int z_off_pitch; + unsigned int z_cntl; + unsigned int alpha_tst_cntl; + + unsigned int scale_3d_cntl; + + unsigned int sc_left_right; + unsigned int sc_top_bottom; + + unsigned int dp_fog_clr; + unsigned int dp_write_mask; + unsigned int dp_pix_width; + unsigned int dp_mix; + unsigned int dp_src; + + unsigned int clr_cmp_cntl; + unsigned int gui_traj_cntl; + + unsigned int setup_cntl; + + unsigned int tex_size_pitch; + unsigned int tex_cntl; + unsigned int secondary_tex_off; + unsigned int tex_offset; +} drm_mach64_context_regs_t; + +typedef struct drm_mach64_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + drm_mach64_context_regs_t context_state; + unsigned int dirty; + unsigned int vertsize; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[MACH64_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int frames_queued; + + /* Texture memory LRU. + */ + struct drm_tex_region tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[MACH64_NR_TEX_HEAPS]; + int ctx_owner; +} drm_mach64_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mach64_common.h) + */ + +/* Mach64 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ + +#define DRM_MACH64_INIT 0x00 +#define DRM_MACH64_IDLE 0x01 +#define DRM_MACH64_RESET 0x02 +#define DRM_MACH64_SWAP 0x03 +#define DRM_MACH64_CLEAR 0x04 +#define DRM_MACH64_VERTEX 0x05 +#define DRM_MACH64_BLIT 0x06 +#define DRM_MACH64_FLUSH 0x07 +#define DRM_MACH64_GETPARAM 0x08 + +#define DRM_IOCTL_MACH64_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_INIT, drm_mach64_init_t) +#define DRM_IOCTL_MACH64_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_IDLE ) +#define DRM_IOCTL_MACH64_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_RESET ) +#define DRM_IOCTL_MACH64_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_SWAP ) +#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_CLEAR, drm_mach64_clear_t) +#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_VERTEX, drm_mach64_vertex_t) +#define DRM_IOCTL_MACH64_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_BLIT, drm_mach64_blit_t) +#define DRM_IOCTL_MACH64_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_FLUSH ) +#define DRM_IOCTL_MACH64_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_MACH64_GETPARAM, drm_mach64_getparam_t) + +/* Buffer flags for clears + */ +#define MACH64_FRONT 0x1 +#define MACH64_BACK 0x2 +#define MACH64_DEPTH 0x4 + +/* Primitive types for vertex buffers + */ +#define MACH64_PRIM_POINTS 0x00000000 +#define MACH64_PRIM_LINES 0x00000001 +#define MACH64_PRIM_LINE_LOOP 0x00000002 +#define MACH64_PRIM_LINE_STRIP 0x00000003 +#define MACH64_PRIM_TRIANGLES 0x00000004 +#define MACH64_PRIM_TRIANGLE_STRIP 0x00000005 +#define MACH64_PRIM_TRIANGLE_FAN 0x00000006 +#define MACH64_PRIM_QUADS 0x00000007 +#define MACH64_PRIM_QUAD_STRIP 0x00000008 +#define MACH64_PRIM_POLYGON 0x00000009 + +typedef enum _drm_mach64_dma_mode_t { + MACH64_MODE_DMA_ASYNC, + MACH64_MODE_DMA_SYNC, + MACH64_MODE_MMIO +} drm_mach64_dma_mode_t; + +typedef struct drm_mach64_init { + enum { + DRM_MACH64_INIT_DMA = 0x01, + DRM_MACH64_CLEANUP_DMA = 0x02 + } func; + + unsigned long sarea_priv_offset; + int is_pci; + drm_mach64_dma_mode_t dma_mode; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drm_mach64_init_t; + +typedef struct drm_mach64_clear { + unsigned int flags; + int x, y, w, h; + unsigned int clear_color; + unsigned int clear_depth; +} drm_mach64_clear_t; + +typedef struct drm_mach64_vertex { + int prim; + void *buf; /* Address of vertex buffer */ + unsigned long used; /* Number of bytes in buffer */ + int discard; /* Client finished with buffer? */ +} drm_mach64_vertex_t; + +typedef struct drm_mach64_blit { + void *buf; + int pitch; + int offset; + int format; + unsigned short x, y; + unsigned short width, height; +} drm_mach64_blit_t; + +typedef struct drm_mach64_getparam { + enum { + MACH64_PARAM_FRAMES_QUEUED = 0x01, + MACH64_PARAM_IRQ_NR = 0x02 + } param; + void *value; +} drm_mach64_getparam_t; + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mga_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mga_drm.h new file mode 100644 index 0000000..7930011 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/mga_drm.h @@ -0,0 +1,427 @@ +/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- + * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jeff Hartmann + * Keith Whitwell + * + * Rewritten by: + * Gareth Hughes + */ + +#ifndef __MGA_DRM_H__ +#define __MGA_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (mga_sarea.h) + */ + +#ifndef __MGA_SAREA_DEFINES__ +#define __MGA_SAREA_DEFINES__ + +/* WARP pipe flags + */ +#define MGA_F 0x1 /* fog */ +#define MGA_A 0x2 /* alpha */ +#define MGA_S 0x4 /* specular */ +#define MGA_T2 0x8 /* multitexture */ + +#define MGA_WARP_TGZ 0 +#define MGA_WARP_TGZF (MGA_F) +#define MGA_WARP_TGZA (MGA_A) +#define MGA_WARP_TGZAF (MGA_F|MGA_A) +#define MGA_WARP_TGZS (MGA_S) +#define MGA_WARP_TGZSF (MGA_S|MGA_F) +#define MGA_WARP_TGZSA (MGA_S|MGA_A) +#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) +#define MGA_WARP_T2GZ (MGA_T2) +#define MGA_WARP_T2GZF (MGA_T2|MGA_F) +#define MGA_WARP_T2GZA (MGA_T2|MGA_A) +#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) +#define MGA_WARP_T2GZS (MGA_T2|MGA_S) +#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) +#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) +#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) + +#define MGA_MAX_G200_PIPES 8 /* no multitex */ +#define MGA_MAX_G400_PIPES 16 +#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES +#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ + +#define MGA_CARD_TYPE_G200 1 +#define MGA_CARD_TYPE_G400 2 +#define MGA_CARD_TYPE_G450 3 /* not currently used */ +#define MGA_CARD_TYPE_G550 4 + +#define MGA_FRONT 0x1 +#define MGA_BACK 0x2 +#define MGA_DEPTH 0x4 + +/* What needs to be changed for the current vertex dma buffer? + */ +#define MGA_UPLOAD_CONTEXT 0x1 +#define MGA_UPLOAD_TEX0 0x2 +#define MGA_UPLOAD_TEX1 0x4 +#define MGA_UPLOAD_PIPE 0x8 +#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ +#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ +#define MGA_UPLOAD_2D 0x40 +#define MGA_WAIT_AGE 0x80 /* handled client-side */ +#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ +#if 0 +#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock + quiescent */ +#endif + +/* 32 buffers of 64k each, total 2 meg. + */ +#define MGA_BUFFER_SIZE (1 << 16) +#define MGA_NUM_BUFFERS 128 + +/* Keep these small for testing. + */ +#define MGA_NR_SAREA_CLIPRECTS 8 + +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define MGA_CARD_HEAP 0 +#define MGA_AGP_HEAP 1 +#define MGA_NR_TEX_HEAPS 2 +#define MGA_NR_TEX_REGIONS 16 +#define MGA_LOG_MIN_TEX_REGION_SIZE 16 + +#define DRM_MGA_IDLE_RETRY 2048 + +#endif /* __MGA_SAREA_DEFINES__ */ + +/* Setup registers for 3D context + */ +typedef struct { + unsigned int dstorg; + unsigned int maccess; + unsigned int plnwt; + unsigned int dwgctl; + unsigned int alphactrl; + unsigned int fogcolor; + unsigned int wflag; + unsigned int tdualstage0; + unsigned int tdualstage1; + unsigned int fcol; + unsigned int stencil; + unsigned int stencilctl; +} drm_mga_context_regs_t; + +/* Setup registers for 2D, X server + */ +typedef struct { + unsigned int pitch; +} drm_mga_server_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int texctl; + unsigned int texctl2; + unsigned int texfilter; + unsigned int texbordercol; + unsigned int texorg; + unsigned int texwidth; + unsigned int texheight; + unsigned int texorg1; + unsigned int texorg2; + unsigned int texorg3; + unsigned int texorg4; +} drm_mga_texture_regs_t; + +/* General aging mechanism + */ +typedef struct { + unsigned int head; /* Position of head pointer */ + unsigned int wrap; /* Primary DMA wrap count */ +} drm_mga_age_t; + +typedef struct _drm_mga_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex dma buffer. + */ + drm_mga_context_regs_t context_state; + drm_mga_server_regs_t server_state; + drm_mga_texture_regs_t tex_state[2]; + unsigned int warp_pipe; + unsigned int dirty; + unsigned int vertsize; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Information about the most recently used 3d drawable. The + * client fills in the req_* fields, the server fills in the + * exported_ fields and puts the cliprects into boxes, above. + * + * The client clears the exported_drawable field before + * clobbering the boxes data. + */ + unsigned int req_drawable; /* the X drawable id */ + unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ + + unsigned int exported_drawable; + unsigned int exported_index; + unsigned int exported_stamp; + unsigned int exported_buffers; + unsigned int exported_nfront; + unsigned int exported_nback; + int exported_back_x, exported_front_x, exported_w; + int exported_back_y, exported_front_y, exported_h; + struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS]; + + /* Counters for aging textures and for client-side throttling. + */ + unsigned int status[4]; + unsigned int last_wrap; + + drm_mga_age_t last_frame; + unsigned int last_enqueue; /* last time a buffer was enqueued */ + unsigned int last_dispatch; /* age of the most recently dispatched buffer */ + unsigned int last_quiescent; /* */ + + /* LRU lists for texture memory in agp space and on the card. + */ + struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; + unsigned int texAge[MGA_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_mga_sarea_t; + +/* MGA specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_MGA_INIT 0x00 +#define DRM_MGA_FLUSH 0x01 +#define DRM_MGA_RESET 0x02 +#define DRM_MGA_SWAP 0x03 +#define DRM_MGA_CLEAR 0x04 +#define DRM_MGA_VERTEX 0x05 +#define DRM_MGA_INDICES 0x06 +#define DRM_MGA_ILOAD 0x07 +#define DRM_MGA_BLIT 0x08 +#define DRM_MGA_GETPARAM 0x09 + +/* 3.2: + * ioctls for operating on fences. + */ +#define DRM_MGA_SET_FENCE 0x0a +#define DRM_MGA_WAIT_FENCE 0x0b +#define DRM_MGA_DMA_BOOTSTRAP 0x0c + +#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) +#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) +#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) +#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) +#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) +#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) +#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) + +typedef struct _drm_mga_warp_index { + int installed; + unsigned long phys_addr; + int size; +} drm_mga_warp_index_t; + +typedef struct drm_mga_init { + enum { + MGA_INIT_DMA = 0x01, + MGA_CLEANUP_DMA = 0x02 + } func; + + unsigned long sarea_priv_offset; + + int chipset; + int sgram; + + unsigned int maccess; + + unsigned int fb_cpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + + unsigned int depth_cpp; + unsigned int depth_offset, depth_pitch; + + unsigned int texture_offset[MGA_NR_TEX_HEAPS]; + unsigned int texture_size[MGA_NR_TEX_HEAPS]; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long status_offset; + unsigned long warp_offset; + unsigned long primary_offset; + unsigned long buffers_offset; +} drm_mga_init_t; + +typedef struct drm_mga_dma_bootstrap { + /** + * \name AGP texture region + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will + * be filled in with the actual AGP texture settings. + * + * \warning + * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode + * is zero, it means that PCI memory (most likely through the use of + * an IOMMU) is being used for "AGP" textures. + */ + /*@{ */ + unsigned long texture_handle; /**< Handle used to map AGP textures. */ + __u32 texture_size; /**< Size of the AGP texture region. */ + /*@} */ + + /** + * Requested size of the primary DMA region. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + */ + __u32 primary_size; + + /** + * Requested number of secondary DMA buffers. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual number of secondary DMA buffers + * allocated. Particularly when PCI DMA is used, this may be + * (subtantially) less than the number requested. + */ + __u32 secondary_bin_count; + + /** + * Requested size of each secondary DMA buffer. + * + * While the kernel \b is free to reduce + * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed + * to reduce dma_mga_dma_bootstrap::secondary_bin_size. + */ + __u32 secondary_bin_size; + + /** + * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, + * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is + * zero, it means that PCI DMA should be used, even if AGP is + * possible. + * + * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be + * filled in with the actual AGP mode. If AGP was not available + * (i.e., PCI DMA was used), this value will be zero. + */ + __u32 agp_mode; + + /** + * Desired AGP GART size, measured in megabytes. + */ + __u8 agp_size; +} drm_mga_dma_bootstrap_t; + +typedef struct drm_mga_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_mga_clear_t; + +typedef struct drm_mga_vertex { + int idx; /* buffer to queue */ + int used; /* bytes in use */ + int discard; /* client finished with buffer? */ +} drm_mga_vertex_t; + +typedef struct drm_mga_indices { + int idx; /* buffer to queue */ + unsigned int start; + unsigned int end; + int discard; /* client finished with buffer? */ +} drm_mga_indices_t; + +typedef struct drm_mga_iload { + int idx; + unsigned int dstorg; + unsigned int length; +} drm_mga_iload_t; + +typedef struct _drm_mga_blit { + unsigned int planemask; + unsigned int srcorg; + unsigned int dstorg; + int src_pitch, dst_pitch; + int delta_sx, delta_sy; + int delta_dx, delta_dy; + int height, ydir; /* flip image vertically */ + int source_pitch, dest_pitch; +} drm_mga_blit_t; + +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +/* 3.2: Query the actual card type. The DDX only distinguishes between + * G200 chips and non-G200 chips, which it calls G400. It turns out that + * there are some very sublte differences between the G4x0 chips and the G550 + * chips. Using this parameter query, a client-side driver can detect the + * difference between a G4x0 and a G550. + */ +#define MGA_PARAM_CARD_TYPE 2 + +typedef struct drm_mga_getparam { + int param; + void *value; +} drm_mga_getparam_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/nouveau_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/nouveau_drm.h new file mode 100644 index 0000000..d42105c --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/nouveau_drm.h @@ -0,0 +1,221 @@ +/* + * Copyright 2005 Stephane Marchesin. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NOUVEAU_DRM_H__ +#define __NOUVEAU_DRM_H__ + +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16 + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +struct drm_nouveau_channel_alloc { + uint32_t fb_ctxdma_handle; + uint32_t tt_ctxdma_handle; + + int channel; + uint32_t pushbuf_domains; + + /* Notifier memory */ + uint32_t notifier_handle; + + /* DRM-enforced subchannel assignments */ + struct { + uint32_t handle; + uint32_t grclass; + } subchan[8]; + uint32_t nr_subchan; +}; + +struct drm_nouveau_channel_free { + int channel; +}; + +struct drm_nouveau_grobj_alloc { + int channel; + uint32_t handle; + int class; +}; + +struct drm_nouveau_notifierobj_alloc { + uint32_t channel; + uint32_t handle; + uint32_t size; + uint32_t offset; +}; + +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + +/* FIXME : maybe unify {GET,SET}PARAMs */ +#define NOUVEAU_GETPARAM_PCI_VENDOR 3 +#define NOUVEAU_GETPARAM_PCI_DEVICE 4 +#define NOUVEAU_GETPARAM_BUS_TYPE 5 +#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 +#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 +#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 +#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 +#define NOUVEAU_GETPARAM_GRAPH_UNITS 13 +#define NOUVEAU_GETPARAM_PTIMER_TIME 14 +#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 +#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 +struct drm_nouveau_getparam { + uint64_t param; + uint64_t value; +}; + +struct drm_nouveau_setparam { + uint64_t param; + uint64_t value; +}; + +#define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) +#define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) +#define NOUVEAU_GEM_DOMAIN_GART (1 << 2) +#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) +#define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4) + +#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ +#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 +#define NOUVEAU_GEM_TILE_16BPP 0x00000001 +#define NOUVEAU_GEM_TILE_32BPP 0x00000002 +#define NOUVEAU_GEM_TILE_ZETA 0x00000004 +#define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 + +struct drm_nouveau_gem_info { + __u32 handle; + __u32 domain; + __u64 size; + __u64 offset; + __u64 map_handle; + __u32 tile_mode; + __u32 tile_flags; +}; + +struct drm_nouveau_gem_new { + struct drm_nouveau_gem_info info; + __u32 channel_hint; + __u32 align; +}; + +#define NOUVEAU_GEM_MAX_BUFFERS 1024 +struct drm_nouveau_gem_pushbuf_bo_presumed { + __u32 valid; + __u32 domain; + __u64 offset; +}; + +struct drm_nouveau_gem_pushbuf_bo { + __u64 user_priv; + __u32 handle; + __u32 read_domains; + __u32 write_domains; + __u32 valid_domains; + struct drm_nouveau_gem_pushbuf_bo_presumed presumed; +}; + +#define NOUVEAU_GEM_RELOC_LOW (1 << 0) +#define NOUVEAU_GEM_RELOC_HIGH (1 << 1) +#define NOUVEAU_GEM_RELOC_OR (1 << 2) +#define NOUVEAU_GEM_MAX_RELOCS 1024 +struct drm_nouveau_gem_pushbuf_reloc { + __u32 reloc_bo_index; + __u32 reloc_bo_offset; + __u32 bo_index; + __u32 flags; + __u32 data; + __u32 vor; + __u32 tor; +}; + +#define NOUVEAU_GEM_MAX_PUSH 512 +struct drm_nouveau_gem_pushbuf_push { + __u32 bo_index; + __u32 pad; + __u64 offset; + __u64 length; +}; + +struct drm_nouveau_gem_pushbuf { + __u32 channel; + __u32 nr_buffers; + __u64 buffers; + __u32 nr_relocs; + __u32 nr_push; + __u64 relocs; + __u64 push; + __u32 suffix0; + __u32 suffix1; + __u64 vram_available; + __u64 gart_available; +}; + +#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 +#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 +#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 +struct drm_nouveau_gem_cpu_prep { + __u32 handle; + __u32 flags; +}; + +struct drm_nouveau_gem_cpu_fini { + __u32 handle; +}; + +enum nouveau_bus_type { + NV_AGP = 0, + NV_PCI = 1, + NV_PCIE = 2, +}; + +struct drm_nouveau_sarea { +}; + +#define DRM_NOUVEAU_GETPARAM 0x00 +#define DRM_NOUVEAU_SETPARAM 0x01 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 +#define DRM_NOUVEAU_CHANNEL_FREE 0x03 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x04 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x06 +#define DRM_NOUVEAU_NVIF 0x07 +#define DRM_NOUVEAU_GEM_NEW 0x40 +#define DRM_NOUVEAU_GEM_PUSHBUF 0x41 +#define DRM_NOUVEAU_GEM_CPU_PREP 0x42 +#define DRM_NOUVEAU_GEM_CPU_FINI 0x43 +#define DRM_NOUVEAU_GEM_INFO 0x44 + +#if defined(__cplusplus) +} +#endif + +#endif /* __NOUVEAU_DRM_H__ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/qxl_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/qxl_drm.h new file mode 100644 index 0000000..880999d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/qxl_drm.h @@ -0,0 +1,158 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef QXL_DRM_H +#define QXL_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define QXL_GEM_DOMAIN_CPU 0 +#define QXL_GEM_DOMAIN_VRAM 1 +#define QXL_GEM_DOMAIN_SURFACE 2 + +#define DRM_QXL_ALLOC 0x00 +#define DRM_QXL_MAP 0x01 +#define DRM_QXL_EXECBUFFER 0x02 +#define DRM_QXL_UPDATE_AREA 0x03 +#define DRM_QXL_GETPARAM 0x04 +#define DRM_QXL_CLIENTCAP 0x05 + +#define DRM_QXL_ALLOC_SURF 0x06 + +struct drm_qxl_alloc { + __u32 size; + __u32 handle; /* 0 is an invalid handle */ +}; + +struct drm_qxl_map { + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; +}; + +/* + * dest is the bo we are writing the relocation into + * src is bo we are relocating. + * *(dest_handle.base_addr + dest_offset) = physical_address(src_handle.addr + + * src_offset) + */ +#define QXL_RELOC_TYPE_BO 1 +#define QXL_RELOC_TYPE_SURF 2 + +struct drm_qxl_reloc { + __u64 src_offset; /* offset into src_handle or src buffer */ + __u64 dst_offset; /* offset in dest handle */ + __u32 src_handle; /* dest handle to compute address from */ + __u32 dst_handle; /* 0 if to command buffer */ + __u32 reloc_type; + __u32 pad; +}; + +struct drm_qxl_command { + __u64 command; /* void* */ + __u64 relocs; /* struct drm_qxl_reloc* */ + __u32 type; + __u32 command_size; + __u32 relocs_num; + __u32 pad; +}; + +struct drm_qxl_execbuffer { + __u32 flags; /* for future use */ + __u32 commands_num; + __u64 commands; /* struct drm_qxl_command* */ +}; + +struct drm_qxl_update_area { + __u32 handle; + __u32 top; + __u32 left; + __u32 bottom; + __u32 right; + __u32 pad; +}; + +#define QXL_PARAM_NUM_SURFACES 1 /* rom->n_surfaces */ +#define QXL_PARAM_MAX_RELOCS 2 +struct drm_qxl_getparam { + __u64 param; + __u64 value; +}; + +/* these are one bit values */ +struct drm_qxl_clientcap { + __u32 index; + __u32 pad; +}; + +struct drm_qxl_alloc_surf { + __u32 format; + __u32 width; + __u32 height; + __s32 stride; + __u32 handle; + __u32 pad; +}; + +#define DRM_IOCTL_QXL_ALLOC \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC, struct drm_qxl_alloc) + +#define DRM_IOCTL_QXL_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_MAP, struct drm_qxl_map) + +#define DRM_IOCTL_QXL_EXECBUFFER \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_EXECBUFFER,\ + struct drm_qxl_execbuffer) + +#define DRM_IOCTL_QXL_UPDATE_AREA \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_UPDATE_AREA,\ + struct drm_qxl_update_area) + +#define DRM_IOCTL_QXL_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_GETPARAM,\ + struct drm_qxl_getparam) + +#define DRM_IOCTL_QXL_CLIENTCAP \ + DRM_IOW(DRM_COMMAND_BASE + DRM_QXL_CLIENTCAP,\ + struct drm_qxl_clientcap) + +#define DRM_IOCTL_QXL_ALLOC_SURF \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC_SURF,\ + struct drm_qxl_alloc_surf) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/r128_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/r128_drm.h new file mode 100644 index 0000000..bf431a0 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/r128_drm.h @@ -0,0 +1,336 @@ +/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + */ +/* + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + * Kevin E. Martin + */ + +#ifndef __R128_DRM_H__ +#define __R128_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (r128_sarea.h) + */ +#ifndef __R128_SAREA_DEFINES__ +#define __R128_SAREA_DEFINES__ + +/* What needs to be changed for the current vertex buffer? + */ +#define R128_UPLOAD_CONTEXT 0x001 +#define R128_UPLOAD_SETUP 0x002 +#define R128_UPLOAD_TEX0 0x004 +#define R128_UPLOAD_TEX1 0x008 +#define R128_UPLOAD_TEX0IMAGES 0x010 +#define R128_UPLOAD_TEX1IMAGES 0x020 +#define R128_UPLOAD_CORE 0x040 +#define R128_UPLOAD_MASKS 0x080 +#define R128_UPLOAD_WINDOW 0x100 +#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */ +#define R128_REQUIRE_QUIESCENCE 0x400 +#define R128_UPLOAD_ALL 0x7ff + +#define R128_FRONT 0x1 +#define R128_BACK 0x2 +#define R128_DEPTH 0x4 + +/* Primitive types + */ +#define R128_POINTS 0x1 +#define R128_LINES 0x2 +#define R128_LINE_STRIP 0x3 +#define R128_TRIANGLES 0x4 +#define R128_TRIANGLE_FAN 0x5 +#define R128_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define R128_BUFFER_SIZE 16384 + +/* Byte offsets for indirect buffer data + */ +#define R128_INDEX_PRIM_OFFSET 20 +#define R128_HOSTDATA_BLIT_OFFSET 32 + +/* Keep these small for testing. + */ +#define R128_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/AGP). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define R128_LOCAL_TEX_HEAP 0 +#define R128_AGP_TEX_HEAP 1 +#define R128_NR_TEX_HEAPS 2 +#define R128_NR_TEX_REGIONS 64 +#define R128_LOG_TEX_GRANULARITY 16 + +#define R128_NR_CONTEXT_REGS 12 + +#define R128_MAX_TEXTURE_LEVELS 11 +#define R128_MAX_TEXTURE_UNITS 2 + +#endif /* __R128_SAREA_DEFINES__ */ + +typedef struct { + /* Context state - can be written in one large chunk */ + unsigned int dst_pitch_offset_c; + unsigned int dp_gui_master_cntl_c; + unsigned int sc_top_left_c; + unsigned int sc_bottom_right_c; + unsigned int z_offset_c; + unsigned int z_pitch_c; + unsigned int z_sten_cntl_c; + unsigned int tex_cntl_c; + unsigned int misc_3d_state_cntl_reg; + unsigned int texture_clr_cmp_clr_c; + unsigned int texture_clr_cmp_msk_c; + unsigned int fog_color_c; + + /* Texture state */ + unsigned int tex_size_pitch_c; + unsigned int constant_color_c; + + /* Setup state */ + unsigned int pm4_vc_fpu_setup; + unsigned int setup_cntl; + + /* Mask state */ + unsigned int dp_write_mask; + unsigned int sten_ref_mask_c; + unsigned int plane_3d_mask_c; + + /* Window state */ + unsigned int window_xy_offset; + + /* Core state */ + unsigned int scale_3d_cntl; +} drm_r128_context_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int tex_cntl; + unsigned int tex_combine_cntl; + unsigned int tex_size_pitch; + unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS]; + unsigned int tex_border_color; +} drm_r128_texture_regs_t; + +typedef struct drm_r128_sarea { + /* The channel for communication of state information to the kernel + * on firing a vertex buffer. + */ + drm_r128_context_regs_t context_state; + drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + + struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1]; + unsigned int tex_age[R128_NR_TEX_HEAPS]; + int ctx_owner; + int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */ + int pfCurrentPage; /* which buffer is being displayed? */ +} drm_r128_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmR128.h) + */ + +/* Rage 128 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_R128_INIT 0x00 +#define DRM_R128_CCE_START 0x01 +#define DRM_R128_CCE_STOP 0x02 +#define DRM_R128_CCE_RESET 0x03 +#define DRM_R128_CCE_IDLE 0x04 +/* 0x05 not used */ +#define DRM_R128_RESET 0x06 +#define DRM_R128_SWAP 0x07 +#define DRM_R128_CLEAR 0x08 +#define DRM_R128_VERTEX 0x09 +#define DRM_R128_INDICES 0x0a +#define DRM_R128_BLIT 0x0b +#define DRM_R128_DEPTH 0x0c +#define DRM_R128_STIPPLE 0x0d +/* 0x0e not used */ +#define DRM_R128_INDIRECT 0x0f +#define DRM_R128_FULLSCREEN 0x10 +#define DRM_R128_CLEAR2 0x11 +#define DRM_R128_GETPARAM 0x12 +#define DRM_R128_FLIP 0x13 + +#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START) +#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE) +/* 0x05 not used */ +#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET) +#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t) +/* 0x0e not used */ +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) +#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP) + +typedef struct drm_r128_init { + enum { + R128_INIT_CCE = 0x01, + R128_CLEANUP_CCE = 0x02 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_secure; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + unsigned int span_offset; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; +} drm_r128_init_t; + +typedef struct drm_r128_cce_stop { + int flush; + int idle; +} drm_r128_cce_stop_t; + +typedef struct drm_r128_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; +} drm_r128_clear_t; + +typedef struct drm_r128_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_r128_vertex_t; + +typedef struct drm_r128_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_r128_indices_t; + +typedef struct drm_r128_blit { + int idx; + int pitch; + int offset; + int format; + unsigned short x, y; + unsigned short width, height; +} drm_r128_blit_t; + +typedef struct drm_r128_depth { + enum { + R128_WRITE_SPAN = 0x01, + R128_WRITE_PIXELS = 0x02, + R128_READ_SPAN = 0x03, + R128_READ_PIXELS = 0x04 + } func; + int n; + int *x; + int *y; + unsigned int *buffer; + unsigned char *mask; +} drm_r128_depth_t; + +typedef struct drm_r128_stipple { + unsigned int *mask; +} drm_r128_stipple_t; + +typedef struct drm_r128_indirect { + int idx; + int start; + int end; + int discard; +} drm_r128_indirect_t; + +typedef struct drm_r128_fullscreen { + enum { + R128_INIT_FULLSCREEN = 0x01, + R128_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_r128_fullscreen_t; + +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + void *value; +} drm_r128_getparam_t; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/radeon_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/radeon_drm.h new file mode 100644 index 0000000..a1e385d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/radeon_drm.h @@ -0,0 +1,1079 @@ +/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + * Keith Whitwell + */ + +#ifndef __RADEON_DRM_H__ +#define __RADEON_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the X server file (radeon_sarea.h) + */ +#ifndef __RADEON_SAREA_DEFINES__ +#define __RADEON_SAREA_DEFINES__ + +/* Old style state flags, required for sarea interface (1.1 and 1.2 + * clears) and 1.2 drm_vertex2 ioctl. + */ +#define RADEON_UPLOAD_CONTEXT 0x00000001 +#define RADEON_UPLOAD_VERTFMT 0x00000002 +#define RADEON_UPLOAD_LINE 0x00000004 +#define RADEON_UPLOAD_BUMPMAP 0x00000008 +#define RADEON_UPLOAD_MASKS 0x00000010 +#define RADEON_UPLOAD_VIEWPORT 0x00000020 +#define RADEON_UPLOAD_SETUP 0x00000040 +#define RADEON_UPLOAD_TCL 0x00000080 +#define RADEON_UPLOAD_MISC 0x00000100 +#define RADEON_UPLOAD_TEX0 0x00000200 +#define RADEON_UPLOAD_TEX1 0x00000400 +#define RADEON_UPLOAD_TEX2 0x00000800 +#define RADEON_UPLOAD_TEX0IMAGES 0x00001000 +#define RADEON_UPLOAD_TEX1IMAGES 0x00002000 +#define RADEON_UPLOAD_TEX2IMAGES 0x00004000 +#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */ +#define RADEON_REQUIRE_QUIESCENCE 0x00010000 +#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ +#define RADEON_UPLOAD_ALL 0x003effff +#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff + +/* New style per-packet identifiers for use in cmd_buffer ioctl with + * the RADEON_EMIT_PACKET command. Comments relate new packets to old + * state bits and the packet size: + */ +#define RADEON_EMIT_PP_MISC 0 /* context/7 */ +#define RADEON_EMIT_PP_CNTL 1 /* context/3 */ +#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ +#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ +#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ +#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ +#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ +#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ +#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ +#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ +#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ +#define RADEON_EMIT_RE_MISC 11 /* misc/1 */ +#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ +#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ +#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ +#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ +#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ +#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ +#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ +#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ +#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ +#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ +#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ +#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ +#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ +#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ +#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ +#define R200_EMIT_TFACTOR_0 30 /* tf/7 */ +#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ +#define R200_EMIT_VAP_CTL 32 /* vap/1 */ +#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ +#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ +#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ +#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ +#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ +#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ +#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ +#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ +#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ +#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ +#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ +#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ +#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ +#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ +#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ +#define R200_EMIT_VTE_CNTL 48 /* vte/1 */ +#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ +#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ +#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ +#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ +#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ +#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ +#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ +#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ +#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ +#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_EMIT_PP_TEX_SIZE_0 73 +#define RADEON_EMIT_PP_TEX_SIZE_1 74 +#define RADEON_EMIT_PP_TEX_SIZE_2 75 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77 +#define RADEON_EMIT_PP_CUBIC_FACES_0 78 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79 +#define RADEON_EMIT_PP_CUBIC_FACES_1 80 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81 +#define RADEON_EMIT_PP_CUBIC_FACES_2 82 +#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83 +#define R200_EMIT_PP_TRI_PERF_CNTL 84 +#define R200_EMIT_PP_AFS_0 85 +#define R200_EMIT_PP_AFS_1 86 +#define R200_EMIT_ATF_TFACTOR 87 +#define R200_EMIT_PP_TXCTLALL_0 88 +#define R200_EMIT_PP_TXCTLALL_1 89 +#define R200_EMIT_PP_TXCTLALL_2 90 +#define R200_EMIT_PP_TXCTLALL_3 91 +#define R200_EMIT_PP_TXCTLALL_4 92 +#define R200_EMIT_PP_TXCTLALL_5 93 +#define R200_EMIT_VAP_PVS_CNTL 94 +#define RADEON_MAX_STATE_PACKETS 95 + +/* Commands understood by cmd_buffer ioctl. More can be added but + * obviously these can't be removed or changed: + */ +#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ +#define RADEON_CMD_SCALARS 2 /* emit scalar data */ +#define RADEON_CMD_VECTORS 3 /* emit vector data */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ +#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ +#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: + * doesn't make the cpu wait, just + * the graphics hardware */ +#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */ + +typedef union { + int i; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, packet_id, pad0, pad1; + } packet; + struct { + unsigned char cmd_type, offset, stride, count; + } scalars; + struct { + unsigned char cmd_type, offset, stride, count; + } vectors; + struct { + unsigned char cmd_type, addr_lo, addr_hi, count; + } veclinear; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; +} drm_radeon_cmd_header_t; + +#define RADEON_WAIT_2D 0x1 +#define RADEON_WAIT_3D 0x2 + +/* Allowed parameters for R300_CMD_PACKET3 + */ +#define R300_CMD_PACKET3_CLEAR 0 +#define R300_CMD_PACKET3_RAW 1 + +/* Commands understood by cmd_buffer ioctl for R300. + * The interface has not been stabilized, so some of these may be removed + * and eventually reordered before stabilization. + */ +#define R300_CMD_PACKET0 1 +#define R300_CMD_VPU 2 /* emit vertex program upload */ +#define R300_CMD_PACKET3 3 /* emit a packet3 */ +#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */ +#define R300_CMD_CP_DELAY 5 +#define R300_CMD_DMA_DISCARD 6 +#define R300_CMD_WAIT 7 +# define R300_WAIT_2D 0x1 +# define R300_WAIT_3D 0x2 +/* these two defines are DOING IT WRONG - however + * we have userspace which relies on using these. + * The wait interface is backwards compat new + * code should use the NEW_WAIT defines below + * THESE ARE NOT BIT FIELDS + */ +# define R300_WAIT_2D_CLEAN 0x3 +# define R300_WAIT_3D_CLEAN 0x4 + +# define R300_NEW_WAIT_2D_3D 0x3 +# define R300_NEW_WAIT_2D_2D_CLEAN 0x4 +# define R300_NEW_WAIT_3D_3D_CLEAN 0x6 +# define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN 0x8 + +#define R300_CMD_SCRATCH 8 +#define R300_CMD_R500FP 9 + +typedef union { + unsigned int u; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, count, reglo, reghi; + } packet0; + struct { + unsigned char cmd_type, count, adrlo, adrhi; + } vpu; + struct { + unsigned char cmd_type, packet, pad0, pad1; + } packet3; + struct { + unsigned char cmd_type, packet; + unsigned short count; /* amount of packet2 to emit */ + } delay; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; + struct { + unsigned char cmd_type, count, adrlo, adrhi_flags; + } r500fp; +} drm_r300_cmd_header_t; + +#define RADEON_FRONT 0x1 +#define RADEON_BACK 0x2 +#define RADEON_DEPTH 0x4 +#define RADEON_STENCIL 0x8 +#define RADEON_CLEAR_FASTZ 0x80000000 +#define RADEON_USE_HIERZ 0x40000000 +#define RADEON_USE_COMP_ZBUF 0x20000000 + +#define R500FP_CONSTANT_TYPE (1 << 1) +#define R500FP_CONSTANT_CLAMP (1 << 2) + +/* Primitive types + */ +#define RADEON_POINTS 0x1 +#define RADEON_LINES 0x2 +#define RADEON_LINE_STRIP 0x3 +#define RADEON_TRIANGLES 0x4 +#define RADEON_TRIANGLE_FAN 0x5 +#define RADEON_TRIANGLE_STRIP 0x6 + +/* Vertex/indirect buffer size + */ +#define RADEON_BUFFER_SIZE 65536 + +/* Byte offsets for indirect buffer data + */ +#define RADEON_INDEX_PRIM_OFFSET 20 + +#define RADEON_SCRATCH_REG_OFFSET 32 + +#define R600_SCRATCH_REG_OFFSET 256 + +#define RADEON_NR_SAREA_CLIPRECTS 12 + +/* There are 2 heaps (local/GART). Each region within a heap is a + * minimum of 64k, and there are at most 64 of them per heap. + */ +#define RADEON_LOCAL_TEX_HEAP 0 +#define RADEON_GART_TEX_HEAP 1 +#define RADEON_NR_TEX_HEAPS 2 +#define RADEON_NR_TEX_REGIONS 64 +#define RADEON_LOG_TEX_GRANULARITY 16 + +#define RADEON_MAX_TEXTURE_LEVELS 12 +#define RADEON_MAX_TEXTURE_UNITS 3 + +#define RADEON_MAX_SURFACES 8 + +/* Blits have strict offset rules. All blit offset must be aligned on + * a 1K-byte boundary. + */ +#define RADEON_OFFSET_SHIFT 10 +#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT) +#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1) + +#endif /* __RADEON_SAREA_DEFINES__ */ + +typedef struct { + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int alpha; +} radeon_color_regs_t; + +typedef struct { + /* Context state */ + unsigned int pp_misc; /* 0x1c14 */ + unsigned int pp_fog_color; + unsigned int re_solid_color; + unsigned int rb3d_blendcntl; + unsigned int rb3d_depthoffset; + unsigned int rb3d_depthpitch; + unsigned int rb3d_zstencilcntl; + + unsigned int pp_cntl; /* 0x1c38 */ + unsigned int rb3d_cntl; + unsigned int rb3d_coloroffset; + unsigned int re_width_height; + unsigned int rb3d_colorpitch; + unsigned int se_cntl; + + /* Vertex format state */ + unsigned int se_coord_fmt; /* 0x1c50 */ + + /* Line state */ + unsigned int re_line_pattern; /* 0x1cd0 */ + unsigned int re_line_state; + + unsigned int se_line_width; /* 0x1db8 */ + + /* Bumpmap state */ + unsigned int pp_lum_matrix; /* 0x1d00 */ + + unsigned int pp_rot_matrix_0; /* 0x1d58 */ + unsigned int pp_rot_matrix_1; + + /* Mask state */ + unsigned int rb3d_stencilrefmask; /* 0x1d7c */ + unsigned int rb3d_ropcntl; + unsigned int rb3d_planemask; + + /* Viewport state */ + unsigned int se_vport_xscale; /* 0x1d98 */ + unsigned int se_vport_xoffset; + unsigned int se_vport_yscale; + unsigned int se_vport_yoffset; + unsigned int se_vport_zscale; + unsigned int se_vport_zoffset; + + /* Setup state */ + unsigned int se_cntl_status; /* 0x2140 */ + + /* Misc state */ + unsigned int re_top_left; /* 0x26c0 */ + unsigned int re_misc; +} drm_radeon_context_regs_t; + +typedef struct { + /* Zbias state */ + unsigned int se_zbias_factor; /* 0x1dac */ + unsigned int se_zbias_constant; +} drm_radeon_context2_regs_t; + +/* Setup registers for each texture unit + */ +typedef struct { + unsigned int pp_txfilter; + unsigned int pp_txformat; + unsigned int pp_txoffset; + unsigned int pp_txcblend; + unsigned int pp_txablend; + unsigned int pp_tfactor; + unsigned int pp_border_color; +} drm_radeon_texture_regs_t; + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim:8; + unsigned int stateidx:8; + unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ + unsigned int vc_format; /* vertex format */ +} drm_radeon_prim_t; + +typedef struct { + drm_radeon_context_regs_t context; + drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; + drm_radeon_context2_regs_t context2; + unsigned int dirty; +} drm_radeon_state_t; + +typedef struct { + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. + */ + drm_radeon_context_regs_t context_state; + drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; + unsigned int dirty; + unsigned int vertsize; + unsigned int vc_format; + + /* The current cliprects, or a subset thereof. + */ + struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS]; + unsigned int nbox; + + /* Counters for client-side throttling of rendering clients. + */ + unsigned int last_frame; + unsigned int last_dispatch; + unsigned int last_clear; + + struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS + + 1]; + unsigned int tex_age[RADEON_NR_TEX_HEAPS]; + int ctx_owner; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ + int tiling_enabled; /* set by drm, read by 2d + 3d clients */ +} drm_radeon_sarea_t; + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmRadeon.h) + * + * KW: actually it's illegal to change any of this (backwards compatibility). + */ + +/* Radeon specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_RADEON_CP_INIT 0x00 +#define DRM_RADEON_CP_START 0x01 +#define DRM_RADEON_CP_STOP 0x02 +#define DRM_RADEON_CP_RESET 0x03 +#define DRM_RADEON_CP_IDLE 0x04 +#define DRM_RADEON_RESET 0x05 +#define DRM_RADEON_FULLSCREEN 0x06 +#define DRM_RADEON_SWAP 0x07 +#define DRM_RADEON_CLEAR 0x08 +#define DRM_RADEON_VERTEX 0x09 +#define DRM_RADEON_INDICES 0x0A +#define DRM_RADEON_NOT_USED +#define DRM_RADEON_STIPPLE 0x0C +#define DRM_RADEON_INDIRECT 0x0D +#define DRM_RADEON_TEXTURE 0x0E +#define DRM_RADEON_VERTEX2 0x0F +#define DRM_RADEON_CMDBUF 0x10 +#define DRM_RADEON_GETPARAM 0x11 +#define DRM_RADEON_FLIP 0x12 +#define DRM_RADEON_ALLOC 0x13 +#define DRM_RADEON_FREE 0x14 +#define DRM_RADEON_INIT_HEAP 0x15 +#define DRM_RADEON_IRQ_EMIT 0x16 +#define DRM_RADEON_IRQ_WAIT 0x17 +#define DRM_RADEON_CP_RESUME 0x18 +#define DRM_RADEON_SETPARAM 0x19 +#define DRM_RADEON_SURF_ALLOC 0x1a +#define DRM_RADEON_SURF_FREE 0x1b +/* KMS ioctl */ +#define DRM_RADEON_GEM_INFO 0x1c +#define DRM_RADEON_GEM_CREATE 0x1d +#define DRM_RADEON_GEM_MMAP 0x1e +#define DRM_RADEON_GEM_PREAD 0x21 +#define DRM_RADEON_GEM_PWRITE 0x22 +#define DRM_RADEON_GEM_SET_DOMAIN 0x23 +#define DRM_RADEON_GEM_WAIT_IDLE 0x24 +#define DRM_RADEON_CS 0x26 +#define DRM_RADEON_INFO 0x27 +#define DRM_RADEON_GEM_SET_TILING 0x28 +#define DRM_RADEON_GEM_GET_TILING 0x29 +#define DRM_RADEON_GEM_BUSY 0x2a +#define DRM_RADEON_GEM_VA 0x2b +#define DRM_RADEON_GEM_OP 0x2c +#define DRM_RADEON_GEM_USERPTR 0x2d + +#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) +#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) +#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) +#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET) +#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE) +#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t) +#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP) +#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t) +#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t) +#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME) +#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) +#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) +#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) +/* KMS */ +#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info) +#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create) +#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap) +#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) +#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) +#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) +#define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) +#define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) +#define DRM_IOCTL_RADEON_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling) +#define DRM_IOCTL_RADEON_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling) +#define DRM_IOCTL_RADEON_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy) +#define DRM_IOCTL_RADEON_GEM_VA DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_VA, struct drm_radeon_gem_va) +#define DRM_IOCTL_RADEON_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_OP, struct drm_radeon_gem_op) +#define DRM_IOCTL_RADEON_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_USERPTR, struct drm_radeon_gem_userptr) + +typedef struct drm_radeon_init { + enum { + RADEON_INIT_CP = 0x01, + RADEON_CLEANUP_CP = 0x02, + RADEON_INIT_R200_CP = 0x03, + RADEON_INIT_R300_CP = 0x04, + RADEON_INIT_R600_CP = 0x05 + } func; + unsigned long sarea_priv_offset; + int is_pci; + int cp_mode; + int gart_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long ring_offset; + unsigned long ring_rptr_offset; + unsigned long buffers_offset; + unsigned long gart_textures_offset; +} drm_radeon_init_t; + +typedef struct drm_radeon_cp_stop { + int flush; + int idle; +} drm_radeon_cp_stop_t; + +typedef struct drm_radeon_fullscreen { + enum { + RADEON_INIT_FULLSCREEN = 0x01, + RADEON_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_radeon_fullscreen_t; + +#define CLEAR_X1 0 +#define CLEAR_Y1 1 +#define CLEAR_X2 2 +#define CLEAR_Y2 3 +#define CLEAR_DEPTH 4 + +typedef union drm_radeon_clear_rect { + float f[5]; + unsigned int ui[5]; +} drm_radeon_clear_rect_t; + +typedef struct drm_radeon_clear { + unsigned int flags; + unsigned int clear_color; + unsigned int clear_depth; + unsigned int color_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ + drm_radeon_clear_rect_t *depth_boxes; +} drm_radeon_clear_t; + +typedef struct drm_radeon_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_radeon_vertex_t; + +typedef struct drm_radeon_indices { + int prim; + int idx; + int start; + int end; + int discard; /* Client finished with buffer? */ +} drm_radeon_indices_t; + +/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices + * - allows multiple primitives and state changes in a single ioctl + * - supports driver change to emit native primitives + */ +typedef struct drm_radeon_vertex2 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t *state; + int nr_prims; + drm_radeon_prim_t *prim; +} drm_radeon_vertex2_t; + +/* v1.3 - obsoletes drm_radeon_vertex2 + * - allows arbitrarily large cliprect list + * - allows updating of tcl packet, vector and scalar state + * - allows memory-efficient description of state updates + * - allows state to be emitted without a primitive + * (for clears, ctx switches) + * - allows more than one dma buffer to be referenced per ioctl + * - supports tcl driver + * - may be extended in future versions with new cmd types, packets + */ +typedef struct drm_radeon_cmd_buffer { + int bufsz; + char *buf; + int nbox; + struct drm_clip_rect *boxes; +} drm_radeon_cmd_buffer_t; + +typedef struct drm_radeon_tex_image { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + const void *data; +} drm_radeon_tex_image_t; + +typedef struct drm_radeon_texture { + unsigned int offset; + int pitch; + int format; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t *image; +} drm_radeon_texture_t; + +typedef struct drm_radeon_stipple { + unsigned int *mask; +} drm_radeon_stipple_t; + +typedef struct drm_radeon_indirect { + int idx; + int start; + int end; + int discard; +} drm_radeon_indirect_t; + +/* enum for card type parameters */ +#define RADEON_CARD_PCI 0 +#define RADEON_CARD_AGP 1 +#define RADEON_CARD_PCIE 2 + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +/* Added with DRM version 1.6. */ +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ +/* Added with DRM version 1.8. */ +#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ +#define RADEON_PARAM_STATUS_HANDLE 8 +#define RADEON_PARAM_SAREA_HANDLE 9 +#define RADEON_PARAM_GART_TEX_HANDLE 10 +#define RADEON_PARAM_SCRATCH_OFFSET 11 +#define RADEON_PARAM_CARD_TYPE 12 +#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ +#define RADEON_PARAM_FB_LOCATION 14 /* FB location */ +#define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ +#define RADEON_PARAM_DEVICE_ID 16 +#define RADEON_PARAM_NUM_Z_PIPES 17 /* num Z pipes */ + +typedef struct drm_radeon_getparam { + int param; + void *value; +} drm_radeon_getparam_t; + +/* 1.6: Set up a memory manager for regions of shared memory: + */ +#define RADEON_MEM_REGION_GART 1 +#define RADEON_MEM_REGION_FB 2 + +typedef struct drm_radeon_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or GART */ +} drm_radeon_mem_alloc_t; + +typedef struct drm_radeon_mem_free { + int region; + int region_offset; +} drm_radeon_mem_free_t; + +typedef struct drm_radeon_mem_init_heap { + int region; + int size; + int start; +} drm_radeon_mem_init_heap_t; + +/* 1.6: Userspace can request & wait on irq's: + */ +typedef struct drm_radeon_irq_emit { + int *irq_seq; +} drm_radeon_irq_emit_t; + +typedef struct drm_radeon_irq_wait { + int irq_seq; +} drm_radeon_irq_wait_t; + +/* 1.10: Clients tell the DRM where they think the framebuffer is located in + * the card's address space, via a new generic ioctl to set parameters + */ + +typedef struct drm_radeon_setparam { + unsigned int param; + __s64 value; +} drm_radeon_setparam_t; + +#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ +#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ +#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ +#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ +/* 1.14: Clients can allocate/free a surface + */ +typedef struct drm_radeon_surface_alloc { + unsigned int address; + unsigned int size; + unsigned int flags; +} drm_radeon_surface_alloc_t; + +typedef struct drm_radeon_surface_free { + unsigned int address; +} drm_radeon_surface_free_t; + +#define DRM_RADEON_VBLANK_CRTC1 1 +#define DRM_RADEON_VBLANK_CRTC2 2 + +/* + * Kernel modesetting world below. + */ +#define RADEON_GEM_DOMAIN_CPU 0x1 +#define RADEON_GEM_DOMAIN_GTT 0x2 +#define RADEON_GEM_DOMAIN_VRAM 0x4 + +struct drm_radeon_gem_info { + __u64 gart_size; + __u64 vram_size; + __u64 vram_visible; +}; + +#define RADEON_GEM_NO_BACKING_STORE (1 << 0) +#define RADEON_GEM_GTT_UC (1 << 1) +#define RADEON_GEM_GTT_WC (1 << 2) +/* BO is expected to be accessed by the CPU */ +#define RADEON_GEM_CPU_ACCESS (1 << 3) +/* CPU access is not expected to work for this BO */ +#define RADEON_GEM_NO_CPU_ACCESS (1 << 4) + +struct drm_radeon_gem_create { + __u64 size; + __u64 alignment; + __u32 handle; + __u32 initial_domain; + __u32 flags; +}; + +/* + * This is not a reliable API and you should expect it to fail for any + * number of reasons and have fallback path that do not use userptr to + * perform any operation. + */ +#define RADEON_GEM_USERPTR_READONLY (1 << 0) +#define RADEON_GEM_USERPTR_ANONONLY (1 << 1) +#define RADEON_GEM_USERPTR_VALIDATE (1 << 2) +#define RADEON_GEM_USERPTR_REGISTER (1 << 3) + +struct drm_radeon_gem_userptr { + __u64 addr; + __u64 size; + __u32 flags; + __u32 handle; +}; + +#define RADEON_TILING_MACRO 0x1 +#define RADEON_TILING_MICRO 0x2 +#define RADEON_TILING_SWAP_16BIT 0x4 +#define RADEON_TILING_R600_NO_SCANOUT RADEON_TILING_SWAP_16BIT +#define RADEON_TILING_SWAP_32BIT 0x8 +/* this object requires a surface when mapped - i.e. front buffer */ +#define RADEON_TILING_SURFACE 0x10 +#define RADEON_TILING_MICRO_SQUARE 0x20 +#define RADEON_TILING_EG_BANKW_SHIFT 8 +#define RADEON_TILING_EG_BANKW_MASK 0xf +#define RADEON_TILING_EG_BANKH_SHIFT 12 +#define RADEON_TILING_EG_BANKH_MASK 0xf +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT 16 +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK 0xf +#define RADEON_TILING_EG_TILE_SPLIT_SHIFT 24 +#define RADEON_TILING_EG_TILE_SPLIT_MASK 0xf +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT 28 +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf + +struct drm_radeon_gem_set_tiling { + __u32 handle; + __u32 tiling_flags; + __u32 pitch; +}; + +struct drm_radeon_gem_get_tiling { + __u32 handle; + __u32 tiling_flags; + __u32 pitch; +}; + +struct drm_radeon_gem_mmap { + __u32 handle; + __u32 pad; + __u64 offset; + __u64 size; + __u64 addr_ptr; +}; + +struct drm_radeon_gem_set_domain { + __u32 handle; + __u32 read_domains; + __u32 write_domain; +}; + +struct drm_radeon_gem_wait_idle { + __u32 handle; + __u32 pad; +}; + +struct drm_radeon_gem_busy { + __u32 handle; + __u32 domain; +}; + +struct drm_radeon_gem_pread { + /** Handle for the object being read. */ + __u32 handle; + __u32 pad; + /** Offset into the object to read from */ + __u64 offset; + /** Length of data to read */ + __u64 size; + /** Pointer to write the data into. */ + /* void *, but pointers are not 32/64 compatible */ + __u64 data_ptr; +}; + +struct drm_radeon_gem_pwrite { + /** Handle for the object being written to. */ + __u32 handle; + __u32 pad; + /** Offset into the object to write to */ + __u64 offset; + /** Length of data to write */ + __u64 size; + /** Pointer to read the data from. */ + /* void *, but pointers are not 32/64 compatible */ + __u64 data_ptr; +}; + +/* Sets or returns a value associated with a buffer. */ +struct drm_radeon_gem_op { + __u32 handle; /* buffer */ + __u32 op; /* RADEON_GEM_OP_* */ + __u64 value; /* input or return value */ +}; + +#define RADEON_GEM_OP_GET_INITIAL_DOMAIN 0 +#define RADEON_GEM_OP_SET_INITIAL_DOMAIN 1 + +#define RADEON_VA_MAP 1 +#define RADEON_VA_UNMAP 2 + +#define RADEON_VA_RESULT_OK 0 +#define RADEON_VA_RESULT_ERROR 1 +#define RADEON_VA_RESULT_VA_EXIST 2 + +#define RADEON_VM_PAGE_VALID (1 << 0) +#define RADEON_VM_PAGE_READABLE (1 << 1) +#define RADEON_VM_PAGE_WRITEABLE (1 << 2) +#define RADEON_VM_PAGE_SYSTEM (1 << 3) +#define RADEON_VM_PAGE_SNOOPED (1 << 4) + +struct drm_radeon_gem_va { + __u32 handle; + __u32 operation; + __u32 vm_id; + __u32 flags; + __u64 offset; +}; + +#define RADEON_CHUNK_ID_RELOCS 0x01 +#define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_FLAGS 0x03 +#define RADEON_CHUNK_ID_CONST_IB 0x04 + +/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ +#define RADEON_CS_KEEP_TILING_FLAGS 0x01 +#define RADEON_CS_USE_VM 0x02 +#define RADEON_CS_END_OF_FRAME 0x04 /* a hint from userspace which CS is the last one */ +/* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */ +#define RADEON_CS_RING_GFX 0 +#define RADEON_CS_RING_COMPUTE 1 +#define RADEON_CS_RING_DMA 2 +#define RADEON_CS_RING_UVD 3 +#define RADEON_CS_RING_VCE 4 +/* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ +/* 0 = normal, + = higher priority, - = lower priority */ + +struct drm_radeon_cs_chunk { + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; +}; + +/* drm_radeon_cs_reloc.flags */ +#define RADEON_RELOC_PRIO_MASK (0xf << 0) + +struct drm_radeon_cs_reloc { + __u32 handle; + __u32 read_domains; + __u32 write_domain; + __u32 flags; +}; + +struct drm_radeon_cs { + __u32 num_chunks; + __u32 cs_id; + /* this points to __u64 * which point to cs chunks */ + __u64 chunks; + /* updates to the limits after this CS ioctl */ + __u64 gart_limit; + __u64 vram_limit; +}; + +#define RADEON_INFO_DEVICE_ID 0x00 +#define RADEON_INFO_NUM_GB_PIPES 0x01 +#define RADEON_INFO_NUM_Z_PIPES 0x02 +#define RADEON_INFO_ACCEL_WORKING 0x03 +#define RADEON_INFO_CRTC_FROM_ID 0x04 +#define RADEON_INFO_ACCEL_WORKING2 0x05 +#define RADEON_INFO_TILING_CONFIG 0x06 +#define RADEON_INFO_WANT_HYPERZ 0x07 +#define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ +#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ +#define RADEON_INFO_NUM_BACKENDS 0x0a /* DB/backends for r600+ - need for OQ */ +#define RADEON_INFO_NUM_TILE_PIPES 0x0b /* tile pipes for r600+ */ +#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ +#define RADEON_INFO_BACKEND_MAP 0x0d /* pipe to backend map, needed by mesa */ +/* virtual address start, va < start are reserved by the kernel */ +#define RADEON_INFO_VA_START 0x0e +/* maximum size of ib using the virtual memory cs */ +#define RADEON_INFO_IB_VM_MAX_SIZE 0x0f +/* max pipes - needed for compute shaders */ +#define RADEON_INFO_MAX_PIPES 0x10 +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ +#define RADEON_INFO_TIMESTAMP 0x11 +/* max shader engines (SE) - needed for geometry shaders, etc. */ +#define RADEON_INFO_MAX_SE 0x12 +/* max SH per SE */ +#define RADEON_INFO_MAX_SH_PER_SE 0x13 +/* fast fb access is enabled */ +#define RADEON_INFO_FASTFB_WORKING 0x14 +/* query if a RADEON_CS_RING_* submission is supported */ +#define RADEON_INFO_RING_WORKING 0x15 +/* SI tile mode array */ +#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16 +/* query if CP DMA is supported on the compute ring */ +#define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17 +/* CIK macrotile mode array */ +#define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY 0x18 +/* query the number of render backends */ +#define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19 +/* max engine clock - needed for OpenCL */ +#define RADEON_INFO_MAX_SCLK 0x1a +/* version of VCE firmware */ +#define RADEON_INFO_VCE_FW_VERSION 0x1b +/* version of VCE feedback */ +#define RADEON_INFO_VCE_FB_VERSION 0x1c +#define RADEON_INFO_NUM_BYTES_MOVED 0x1d +#define RADEON_INFO_VRAM_USAGE 0x1e +#define RADEON_INFO_GTT_USAGE 0x1f +#define RADEON_INFO_ACTIVE_CU_COUNT 0x20 +#define RADEON_INFO_CURRENT_GPU_TEMP 0x21 +#define RADEON_INFO_CURRENT_GPU_SCLK 0x22 +#define RADEON_INFO_CURRENT_GPU_MCLK 0x23 +#define RADEON_INFO_READ_REG 0x24 +#define RADEON_INFO_VA_UNMAP_WORKING 0x25 +#define RADEON_INFO_GPU_RESET_COUNTER 0x26 + +struct drm_radeon_info { + __u32 request; + __u32 pad; + __u64 value; +}; + +/* Those correspond to the tile index to use, this is to explicitly state + * the API that is implicitly defined by the tile mode array. + */ +#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8 +#define SI_TILE_MODE_COLOR_1D 13 +#define SI_TILE_MODE_COLOR_1D_SCANOUT 9 +#define SI_TILE_MODE_COLOR_2D_8BPP 14 +#define SI_TILE_MODE_COLOR_2D_16BPP 15 +#define SI_TILE_MODE_COLOR_2D_32BPP 16 +#define SI_TILE_MODE_COLOR_2D_64BPP 17 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12 +#define SI_TILE_MODE_DEPTH_STENCIL_1D 4 +#define SI_TILE_MODE_DEPTH_STENCIL_2D 0 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2 + +#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5 + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/savage_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/savage_drm.h new file mode 100644 index 0000000..1a91234 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/savage_drm.h @@ -0,0 +1,220 @@ +/* savage_drm.h -- Public header for the savage driver + * + * Copyright 2004 Felix Kuehling + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SAVAGE_DRM_H__ +#define __SAVAGE_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef __SAVAGE_SAREA_DEFINES__ +#define __SAVAGE_SAREA_DEFINES__ + +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 + * regions, subject to a minimum region size of (1<<16) == 64k. + * + * Clients may subdivide regions internally, but when sharing between + * clients, the region size is the minimum granularity. + */ + +#define SAVAGE_CARD_HEAP 0 +#define SAVAGE_AGP_HEAP 1 +#define SAVAGE_NR_TEX_HEAPS 2 +#define SAVAGE_NR_TEX_REGIONS 16 +#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16 + +#endif /* __SAVAGE_SAREA_DEFINES__ */ + +typedef struct _drm_savage_sarea { + /* LRU lists for texture memory in agp space and on the card. + */ + struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS + + 1]; + unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; + + /* Mechanism to validate card state. + */ + int ctxOwner; +} drm_savage_sarea_t, *drm_savage_sarea_ptr; + +/* Savage-specific ioctls + */ +#define DRM_SAVAGE_BCI_INIT 0x00 +#define DRM_SAVAGE_BCI_CMDBUF 0x01 +#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 +#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 + +#define DRM_IOCTL_SAVAGE_BCI_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) +#define DRM_IOCTL_SAVAGE_BCI_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) + +#define SAVAGE_DMA_PCI 1 +#define SAVAGE_DMA_AGP 3 +typedef struct drm_savage_init { + enum { + SAVAGE_INIT_BCI = 1, + SAVAGE_CLEANUP_BCI = 2 + } func; + unsigned int sarea_priv_offset; + + /* some parameters */ + unsigned int cob_size; + unsigned int bci_threshold_lo, bci_threshold_hi; + unsigned int dma_type; + + /* frame buffer layout */ + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + /* local textures */ + unsigned int texture_offset; + unsigned int texture_size; + + /* physical locations of non-permanent maps */ + unsigned long status_offset; + unsigned long buffers_offset; + unsigned long agp_textures_offset; + unsigned long cmd_dma_offset; +} drm_savage_init_t; + +typedef union drm_savage_cmd_header drm_savage_cmd_header_t; +typedef struct drm_savage_cmdbuf { + /* command buffer in client's address space */ + drm_savage_cmd_header_t *cmd_addr; + unsigned int size; /* size of the command buffer in 64bit units */ + + unsigned int dma_idx; /* DMA buffer index to use */ + int discard; /* discard DMA buffer when done */ + /* vertex buffer in client's address space */ + unsigned int *vb_addr; + unsigned int vb_size; /* size of client vertex buffer in bytes */ + unsigned int vb_stride; /* stride of vertices in 32bit words */ + /* boxes in client's address space */ + struct drm_clip_rect *box_addr; + unsigned int nbox; /* number of clipping boxes */ +} drm_savage_cmdbuf_t; + +#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */ +#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */ +#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */ +typedef struct drm_savage_event { + unsigned int count; + unsigned int flags; +} drm_savage_event_emit_t, drm_savage_event_wait_t; + +/* Commands for the cmdbuf ioctl + */ +#define SAVAGE_CMD_STATE 0 /* a range of state registers */ +#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */ +#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */ +#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */ +#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */ +#define SAVAGE_CMD_CLEAR 5 /* clear buffers */ +#define SAVAGE_CMD_SWAP 6 /* swap buffers */ + +/* Primitive types +*/ +#define SAVAGE_PRIM_TRILIST 0 /* triangle list */ +#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */ +#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */ +#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat + * shading on s3d */ + +/* Skip flags (vertex format) + */ +#define SAVAGE_SKIP_Z 0x01 +#define SAVAGE_SKIP_W 0x02 +#define SAVAGE_SKIP_C0 0x04 +#define SAVAGE_SKIP_C1 0x08 +#define SAVAGE_SKIP_S0 0x10 +#define SAVAGE_SKIP_T0 0x20 +#define SAVAGE_SKIP_ST0 0x30 +#define SAVAGE_SKIP_S1 0x40 +#define SAVAGE_SKIP_T1 0x80 +#define SAVAGE_SKIP_ST1 0xc0 +#define SAVAGE_SKIP_ALL_S3D 0x3f +#define SAVAGE_SKIP_ALL_S4 0xff + +/* Buffer names for clear command + */ +#define SAVAGE_FRONT 0x1 +#define SAVAGE_BACK 0x2 +#define SAVAGE_DEPTH 0x4 + +/* 64-bit command header + */ +union drm_savage_cmd_header { + struct { + unsigned char cmd; /* command */ + unsigned char pad0; + unsigned short pad1; + unsigned short pad2; + unsigned short pad3; + } cmd; /* generic */ + struct { + unsigned char cmd; + unsigned char global; /* need idle engine? */ + unsigned short count; /* number of consecutive registers */ + unsigned short start; /* first register */ + unsigned short pad3; + } state; /* SAVAGE_CMD_STATE */ + struct { + unsigned char cmd; + unsigned char prim; /* primitive type */ + unsigned short skip; /* vertex format (skip flags) */ + unsigned short count; /* number of vertices */ + unsigned short start; /* first vertex in DMA/vertex buffer */ + } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */ + struct { + unsigned char cmd; + unsigned char prim; + unsigned short skip; + unsigned short count; /* number of indices that follow */ + unsigned short pad3; + } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */ + struct { + unsigned char cmd; + unsigned char pad0; + unsigned short pad1; + unsigned int flags; + } clear0; /* SAVAGE_CMD_CLEAR */ + struct { + unsigned int mask; + unsigned int value; + } clear1; /* SAVAGE_CMD_CLEAR data */ +}; + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/sis_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/sis_drm.h new file mode 100644 index 0000000..8e51bb9 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/sis_drm.h @@ -0,0 +1,77 @@ +/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ +/* + * Copyright 2005 Eric Anholt + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __SIS_DRM_H__ +#define __SIS_DRM_H__ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* SiS specific ioctls */ +#define NOT_USED_0_3 +#define DRM_SIS_FB_ALLOC 0x04 +#define DRM_SIS_FB_FREE 0x05 +#define NOT_USED_6_12 +#define DRM_SIS_AGP_INIT 0x13 +#define DRM_SIS_AGP_ALLOC 0x14 +#define DRM_SIS_AGP_FREE 0x15 +#define DRM_SIS_FB_INIT 0x16 + +#define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t) +#define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t) +#define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t) +#define DRM_IOCTL_SIS_FB_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t) +/* +#define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t) +#define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49) +#define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50) +*/ + +typedef struct { + int context; + unsigned int offset; + unsigned int size; + unsigned long free; +} drm_sis_mem_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_agp_t; + +typedef struct { + unsigned int offset, size; +} drm_sis_fb_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* __SIS_DRM_H__ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/tegra_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/tegra_drm.h new file mode 100644 index 0000000..6c07919 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/tegra_drm.h @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) +#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) + +/** + * struct drm_tegra_gem_create - parameters for the GEM object creation IOCTL + */ +struct drm_tegra_gem_create { + /** + * @size: + * + * The size, in bytes, of the buffer object to be created. + */ + __u64 size; + + /** + * @flags: + * + * A bitmask of flags that influence the creation of GEM objects: + * + * DRM_TEGRA_GEM_CREATE_TILED + * Use the 16x16 tiling format for this buffer. + * + * DRM_TEGRA_GEM_CREATE_BOTTOM_UP + * The buffer has a bottom-up layout. + */ + __u32 flags; + + /** + * @handle: + * + * The handle of the created GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u32 handle; +}; + +/** + * struct drm_tegra_gem_mmap - parameters for the GEM mmap IOCTL + */ +struct drm_tegra_gem_mmap { + /** + * @handle: + * + * Handle of the GEM object to obtain an mmap offset for. + */ + __u32 handle; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; + + /** + * @offset: + * + * The mmap offset for the given GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u64 offset; +}; + +/** + * struct drm_tegra_syncpt_read - parameters for the read syncpoint IOCTL + */ +struct drm_tegra_syncpt_read { + /** + * @id: + * + * ID of the syncpoint to read the current value from. + */ + __u32 id; + + /** + * @value: + * + * The current syncpoint value. Set by the kernel upon successful + * completion of the IOCTL. + */ + __u32 value; +}; + +/** + * struct drm_tegra_syncpt_incr - parameters for the increment syncpoint IOCTL + */ +struct drm_tegra_syncpt_incr { + /** + * @id: + * + * ID of the syncpoint to increment. + */ + __u32 id; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_syncpt_wait - parameters for the wait syncpoint IOCTL + */ +struct drm_tegra_syncpt_wait { + /** + * @id: + * + * ID of the syncpoint to wait on. + */ + __u32 id; + + /** + * @thresh: + * + * Threshold value for which to wait. + */ + __u32 thresh; + + /** + * @timeout: + * + * Timeout, in milliseconds, to wait. + */ + __u32 timeout; + + /** + * @value: + * + * The new syncpoint value after the wait. Set by the kernel upon + * successful completion of the IOCTL. + */ + __u32 value; +}; + +#define DRM_TEGRA_NO_TIMEOUT (0xffffffff) + +/** + * struct drm_tegra_open_channel - parameters for the open channel IOCTL + */ +struct drm_tegra_open_channel { + /** + * @client: + * + * The client ID for this channel. + */ + __u32 client; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; + + /** + * @context: + * + * The application context of this channel. Set by the kernel upon + * successful completion of the IOCTL. This context needs to be passed + * to the DRM_TEGRA_CHANNEL_CLOSE or the DRM_TEGRA_SUBMIT IOCTLs. + */ + __u64 context; +}; + +/** + * struct drm_tegra_close_channel - parameters for the close channel IOCTL + */ +struct drm_tegra_close_channel { + /** + * @context: + * + * The application context of this channel. This is obtained from the + * DRM_TEGRA_OPEN_CHANNEL IOCTL. + */ + __u64 context; +}; + +/** + * struct drm_tegra_get_syncpt - parameters for the get syncpoint IOCTL + */ +struct drm_tegra_get_syncpt { + /** + * @context: + * + * The application context identifying the channel for which to obtain + * the syncpoint ID. + */ + __u64 context; + + /** + * @index: + * + * Index of the client syncpoint for which to obtain the ID. + */ + __u32 index; + + /** + * @id: + * + * The ID of the given syncpoint. Set by the kernel upon successful + * completion of the IOCTL. + */ + __u32 id; +}; + +/** + * struct drm_tegra_get_syncpt_base - parameters for the get wait base IOCTL + */ +struct drm_tegra_get_syncpt_base { + /** + * @context: + * + * The application context identifying for which channel to obtain the + * wait base. + */ + __u64 context; + + /** + * @syncpt: + * + * ID of the syncpoint for which to obtain the wait base. + */ + __u32 syncpt; + + /** + * @id: + * + * The ID of the wait base corresponding to the client syncpoint. Set + * by the kernel upon successful completion of the IOCTL. + */ + __u32 id; +}; + +/** + * struct drm_tegra_syncpt - syncpoint increment operation + */ +struct drm_tegra_syncpt { + /** + * @id: + * + * ID of the syncpoint to operate on. + */ + __u32 id; + + /** + * @incrs: + * + * Number of increments to perform for the syncpoint. + */ + __u32 incrs; +}; + +/** + * struct drm_tegra_cmdbuf - structure describing a command buffer + */ +struct drm_tegra_cmdbuf { + /** + * @handle: + * + * Handle to a GEM object containing the command buffer. + */ + __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, into the GEM object identified by @handle at + * which the command buffer starts. + */ + __u32 offset; + + /** + * @words: + * + * Number of 32-bit words in this command buffer. + */ + __u32 words; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_reloc - GEM object relocation structure + */ +struct drm_tegra_reloc { + struct { + /** + * @cmdbuf.handle: + * + * Handle to the GEM object containing the command buffer for + * which to perform this GEM object relocation. + */ + __u32 handle; + + /** + * @cmdbuf.offset: + * + * Offset, in bytes, into the command buffer at which to + * insert the relocated address. + */ + __u32 offset; + } cmdbuf; + struct { + /** + * @target.handle: + * + * Handle to the GEM object to be relocated. + */ + __u32 handle; + + /** + * @target.offset: + * + * Offset, in bytes, into the target GEM object at which the + * relocated data starts. + */ + __u32 offset; + } target; + + /** + * @shift: + * + * The number of bits by which to shift relocated addresses. + */ + __u32 shift; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_waitchk - wait check structure + */ +struct drm_tegra_waitchk { + /** + * @handle: + * + * Handle to the GEM object containing a command stream on which to + * perform the wait check. + */ + __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, of the location in the command stream to perform + * the wait check on. + */ + __u32 offset; + + /** + * @syncpt: + * + * ID of the syncpoint to wait check. + */ + __u32 syncpt; + + /** + * @thresh: + * + * Threshold value for which to check. + */ + __u32 thresh; +}; + +/** + * struct drm_tegra_submit - job submission structure + */ +struct drm_tegra_submit { + /** + * @context: + * + * The application context identifying the channel to use for the + * execution of this job. + */ + __u64 context; + + /** + * @num_syncpts: + * + * The number of syncpoints operated on by this job. This defines the + * length of the array pointed to by @syncpts. + */ + __u32 num_syncpts; + + /** + * @num_cmdbufs: + * + * The number of command buffers to execute as part of this job. This + * defines the length of the array pointed to by @cmdbufs. + */ + __u32 num_cmdbufs; + + /** + * @num_relocs: + * + * The number of relocations to perform before executing this job. + * This defines the length of the array pointed to by @relocs. + */ + __u32 num_relocs; + + /** + * @num_waitchks: + * + * The number of wait checks to perform as part of this job. This + * defines the length of the array pointed to by @waitchks. + */ + __u32 num_waitchks; + + /** + * @waitchk_mask: + * + * Bitmask of valid wait checks. + */ + __u32 waitchk_mask; + + /** + * @timeout: + * + * Timeout, in milliseconds, before this job is cancelled. + */ + __u32 timeout; + + /** + * @syncpts: + * + * A pointer to an array of &struct drm_tegra_syncpt structures that + * specify the syncpoint operations performed as part of this job. + * The number of elements in the array must be equal to the value + * given by @num_syncpts. + */ + __u64 syncpts; + + /** + * @cmdbufs: + * + * A pointer to an array of &struct drm_tegra_cmdbuf structures that + * define the command buffers to execute as part of this job. The + * number of elements in the array must be equal to the value given + * by @num_syncpts. + */ + __u64 cmdbufs; + + /** + * @relocs: + * + * A pointer to an array of &struct drm_tegra_reloc structures that + * specify the relocations that need to be performed before executing + * this job. The number of elements in the array must be equal to the + * value given by @num_relocs. + */ + __u64 relocs; + + /** + * @waitchks: + * + * A pointer to an array of &struct drm_tegra_waitchk structures that + * specify the wait checks to be performed while executing this job. + * The number of elements in the array must be equal to the value + * given by @num_waitchks. + */ + __u64 waitchks; + + /** + * @fence: + * + * The threshold of the syncpoint associated with this job after it + * has been completed. Set by the kernel upon successful completion of + * the IOCTL. This can be used with the DRM_TEGRA_SYNCPT_WAIT IOCTL to + * wait for this job to be finished. + */ + __u32 fence; + + /** + * @reserved: + * + * This field is reserved for future use. Must be 0. + */ + __u32 reserved[5]; +}; + +#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 +#define DRM_TEGRA_GEM_TILING_MODE_TILED 1 +#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 + +/** + * struct drm_tegra_gem_set_tiling - parameters for the set tiling IOCTL + */ +struct drm_tegra_gem_set_tiling { + /** + * @handle: + * + * Handle to the GEM object for which to set the tiling parameters. + */ + __u32 handle; + + /** + * @mode: + * + * The tiling mode to set. Must be one of: + * + * DRM_TEGRA_GEM_TILING_MODE_PITCH + * pitch linear format + * + * DRM_TEGRA_GEM_TILING_MODE_TILED + * 16x16 tiling format + * + * DRM_TEGRA_GEM_TILING_MODE_BLOCK + * 16Bx2 tiling format + */ + __u32 mode; + + /** + * @value: + * + * The value to set for the tiling mode parameter. + */ + __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +/** + * struct drm_tegra_gem_get_tiling - parameters for the get tiling IOCTL + */ +struct drm_tegra_gem_get_tiling { + /** + * @handle: + * + * Handle to the GEM object for which to query the tiling parameters. + */ + __u32 handle; + + /** + * @mode: + * + * The tiling mode currently associated with the GEM object. Set by + * the kernel upon successful completion of the IOCTL. + */ + __u32 mode; + + /** + * @value: + * + * The tiling mode parameter currently associated with the GEM object. + * Set by the kernel upon successful completion of the IOCTL. + */ + __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ + __u32 pad; +}; + +#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) +#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) + +/** + * struct drm_tegra_gem_set_flags - parameters for the set flags IOCTL + */ +struct drm_tegra_gem_set_flags { + /** + * @handle: + * + * Handle to the GEM object for which to set the flags. + */ + __u32 handle; + + /** + * @flags: + * + * The flags to set for the GEM object. + */ + __u32 flags; +}; + +/** + * struct drm_tegra_gem_get_flags - parameters for the get flags IOCTL + */ +struct drm_tegra_gem_get_flags { + /** + * @handle: + * + * Handle to the GEM object for which to query the flags. + */ + __u32 handle; + + /** + * @flags: + * + * The flags currently associated with the GEM object. Set by the + * kernel upon successful completion of the IOCTL. + */ + __u32 flags; +}; + +#define DRM_TEGRA_GEM_CREATE 0x00 +#define DRM_TEGRA_GEM_MMAP 0x01 +#define DRM_TEGRA_SYNCPT_READ 0x02 +#define DRM_TEGRA_SYNCPT_INCR 0x03 +#define DRM_TEGRA_SYNCPT_WAIT 0x04 +#define DRM_TEGRA_OPEN_CHANNEL 0x05 +#define DRM_TEGRA_CLOSE_CHANNEL 0x06 +#define DRM_TEGRA_GET_SYNCPT 0x07 +#define DRM_TEGRA_SUBMIT 0x08 +#define DRM_TEGRA_GET_SYNCPT_BASE 0x09 +#define DRM_TEGRA_GEM_SET_TILING 0x0a +#define DRM_TEGRA_GEM_GET_TILING 0x0b +#define DRM_TEGRA_GEM_SET_FLAGS 0x0c +#define DRM_TEGRA_GEM_GET_FLAGS 0x0d + +#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) +#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) +#define DRM_IOCTL_TEGRA_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_READ, struct drm_tegra_syncpt_read) +#define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr) +#define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait) +#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel) +#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) +#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) +#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) +#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) +#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) +#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) +#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/vc4_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/vc4_drm.h new file mode 100644 index 0000000..31f50de --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/vc4_drm.h @@ -0,0 +1,442 @@ +/* + * Copyright © 2014-2015 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _VC4_DRM_H_ +#define _VC4_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_VC4_SUBMIT_CL 0x00 +#define DRM_VC4_WAIT_SEQNO 0x01 +#define DRM_VC4_WAIT_BO 0x02 +#define DRM_VC4_CREATE_BO 0x03 +#define DRM_VC4_MMAP_BO 0x04 +#define DRM_VC4_CREATE_SHADER_BO 0x05 +#define DRM_VC4_GET_HANG_STATE 0x06 +#define DRM_VC4_GET_PARAM 0x07 +#define DRM_VC4_SET_TILING 0x08 +#define DRM_VC4_GET_TILING 0x09 +#define DRM_VC4_LABEL_BO 0x0a +#define DRM_VC4_GEM_MADVISE 0x0b +#define DRM_VC4_PERFMON_CREATE 0x0c +#define DRM_VC4_PERFMON_DESTROY 0x0d +#define DRM_VC4_PERFMON_GET_VALUES 0x0e + +#define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) +#define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) +#define DRM_IOCTL_VC4_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_BO, struct drm_vc4_wait_bo) +#define DRM_IOCTL_VC4_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_BO, struct drm_vc4_create_bo) +#define DRM_IOCTL_VC4_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_MMAP_BO, struct drm_vc4_mmap_bo) +#define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo) +#define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state) +#define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param) +#define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling) +#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling) +#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo) +#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise) +#define DRM_IOCTL_VC4_PERFMON_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_CREATE, struct drm_vc4_perfmon_create) +#define DRM_IOCTL_VC4_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_DESTROY, struct drm_vc4_perfmon_destroy) +#define DRM_IOCTL_VC4_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_GET_VALUES, struct drm_vc4_perfmon_get_values) + +struct drm_vc4_submit_rcl_surface { + __u32 hindex; /* Handle index, or ~0 if not present. */ + __u32 offset; /* Offset to start of buffer. */ + /* + * Bits for either render config (color_write) or load/store packet. + * Bits should all be 0 for MSAA load/stores. + */ + __u16 bits; + +#define VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES (1 << 0) + __u16 flags; +}; + +/** + * struct drm_vc4_submit_cl - ioctl argument for submitting commands to the 3D + * engine. + * + * Drivers typically use GPU BOs to store batchbuffers / command lists and + * their associated state. However, because the VC4 lacks an MMU, we have to + * do validation of memory accesses by the GPU commands. If we were to store + * our commands in BOs, we'd need to do uncached readback from them to do the + * validation process, which is too expensive. Instead, userspace accumulates + * commands and associated state in plain memory, then the kernel copies the + * data to its own address space, and then validates and stores it in a GPU + * BO. + */ +struct drm_vc4_submit_cl { + /* Pointer to the binner command list. + * + * This is the first set of commands executed, which runs the + * coordinate shader to determine where primitives land on the screen, + * then writes out the state updates and draw calls necessary per tile + * to the tile allocation BO. + */ + __u64 bin_cl; + + /* Pointer to the shader records. + * + * Shader records are the structures read by the hardware that contain + * pointers to uniforms, shaders, and vertex attributes. The + * reference to the shader record has enough information to determine + * how many pointers are necessary (fixed number for shaders/uniforms, + * and an attribute count), so those BO indices into bo_handles are + * just stored as __u32s before each shader record passed in. + */ + __u64 shader_rec; + + /* Pointer to uniform data and texture handles for the textures + * referenced by the shader. + * + * For each shader state record, there is a set of uniform data in the + * order referenced by the record (FS, VS, then CS). Each set of + * uniform data has a __u32 index into bo_handles per texture + * sample operation, in the order the QPU_W_TMUn_S writes appear in + * the program. Following the texture BO handle indices is the actual + * uniform data. + * + * The individual uniform state blocks don't have sizes passed in, + * because the kernel has to determine the sizes anyway during shader + * code validation. + */ + __u64 uniforms; + __u64 bo_handles; + + /* Size in bytes of the binner command list. */ + __u32 bin_cl_size; + /* Size in bytes of the set of shader records. */ + __u32 shader_rec_size; + /* Number of shader records. + * + * This could just be computed from the contents of shader_records and + * the address bits of references to them from the bin CL, but it + * keeps the kernel from having to resize some allocations it makes. + */ + __u32 shader_rec_count; + /* Size in bytes of the uniform state. */ + __u32 uniforms_size; + + /* Number of BO handles passed in (size is that times 4). */ + __u32 bo_handle_count; + + /* RCL setup: */ + __u16 width; + __u16 height; + __u8 min_x_tile; + __u8 min_y_tile; + __u8 max_x_tile; + __u8 max_y_tile; + struct drm_vc4_submit_rcl_surface color_read; + struct drm_vc4_submit_rcl_surface color_write; + struct drm_vc4_submit_rcl_surface zs_read; + struct drm_vc4_submit_rcl_surface zs_write; + struct drm_vc4_submit_rcl_surface msaa_color_write; + struct drm_vc4_submit_rcl_surface msaa_zs_write; + __u32 clear_color[2]; + __u32 clear_z; + __u8 clear_s; + + __u32 pad:24; + +#define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0) +/* By default, the kernel gets to choose the order that the tiles are + * rendered in. If this is set, then the tiles will be rendered in a + * raster order, with the right-to-left vs left-to-right and + * top-to-bottom vs bottom-to-top dictated by + * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*. This allows overlapping + * blits to be implemented using the 3D engine. + */ +#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3) + __u32 flags; + + /* Returned value of the seqno of this render job (for the + * wait ioctl). + */ + __u64 seqno; + + /* ID of the perfmon to attach to this job. 0 means no perfmon. */ + __u32 perfmonid; + + /* Syncobj handle to wait on. If set, processing of this render job + * will not start until the syncobj is signaled. 0 means ignore. + */ + __u32 in_sync; + + /* Syncobj handle to export fence to. If set, the fence in the syncobj + * will be replaced with a fence that signals upon completion of this + * render job. 0 means ignore. + */ + __u32 out_sync; + + __u32 pad2; +}; + +/** + * struct drm_vc4_wait_seqno - ioctl argument for waiting for + * DRM_VC4_SUBMIT_CL completion using its returned seqno. + * + * timeout_ns is the timeout in nanoseconds, where "0" means "don't + * block, just return the status." + */ +struct drm_vc4_wait_seqno { + __u64 seqno; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_wait_bo - ioctl argument for waiting for + * completion of the last DRM_VC4_SUBMIT_CL on a BO. + * + * This is useful for cases where multiple processes might be + * rendering to a BO and you want to wait for all rendering to be + * completed. + */ +struct drm_vc4_wait_bo { + __u32 handle; + __u32 pad; + __u64 timeout_ns; +}; + +/** + * struct drm_vc4_create_bo - ioctl argument for creating VC4 BOs. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_create_bo { + __u32 size; + __u32 flags; + /** Returned GEM handle for the BO. */ + __u32 handle; + __u32 pad; +}; + +/** + * struct drm_vc4_mmap_bo - ioctl argument for mapping VC4 BOs. + * + * This doesn't actually perform an mmap. Instead, it returns the + * offset you need to use in an mmap on the DRM device node. This + * means that tools like valgrind end up knowing about the mapped + * memory. + * + * There are currently no values for the flags argument, but it may be + * used in a future extension. + */ +struct drm_vc4_mmap_bo { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 flags; + /** offset into the drm node to use for subsequent mmap call. */ + __u64 offset; +}; + +/** + * struct drm_vc4_create_shader_bo - ioctl argument for creating VC4 + * shader BOs. + * + * Since allowing a shader to be overwritten while it's also being + * executed from would allow privlege escalation, shaders must be + * created using this ioctl, and they can't be mmapped later. + */ +struct drm_vc4_create_shader_bo { + /* Size of the data argument. */ + __u32 size; + /* Flags, currently must be 0. */ + __u32 flags; + + /* Pointer to the data. */ + __u64 data; + + /** Returned GEM handle for the BO. */ + __u32 handle; + /* Pad, must be 0. */ + __u32 pad; +}; + +struct drm_vc4_get_hang_state_bo { + __u32 handle; + __u32 paddr; + __u32 size; + __u32 pad; +}; + +/** + * struct drm_vc4_hang_state - ioctl argument for collecting state + * from a GPU hang for analysis. +*/ +struct drm_vc4_get_hang_state { + /** Pointer to array of struct drm_vc4_get_hang_state_bo. */ + __u64 bo; + /** + * On input, the size of the bo array. Output is the number + * of bos to be returned. + */ + __u32 bo_count; + + __u32 start_bin, start_render; + + __u32 ct0ca, ct0ea; + __u32 ct1ca, ct1ea; + __u32 ct0cs, ct1cs; + __u32 ct0ra0, ct1ra0; + + __u32 bpca, bpcs; + __u32 bpoa, bpos; + + __u32 vpmbase; + + __u32 dbge; + __u32 fdbgo; + __u32 fdbgb; + __u32 fdbgr; + __u32 fdbgs; + __u32 errstat; + + /* Pad that we may save more registers into in the future. */ + __u32 pad[16]; +}; + +#define DRM_VC4_PARAM_V3D_IDENT0 0 +#define DRM_VC4_PARAM_V3D_IDENT1 1 +#define DRM_VC4_PARAM_V3D_IDENT2 2 +#define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 +#define DRM_VC4_PARAM_SUPPORTS_ETC1 4 +#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 +#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6 +#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7 +#define DRM_VC4_PARAM_SUPPORTS_PERFMON 8 + +struct drm_vc4_get_param { + __u32 param; + __u32 pad; + __u64 value; +}; + +struct drm_vc4_get_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +struct drm_vc4_set_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +/** + * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes. + */ +struct drm_vc4_label_bo { + __u32 handle; + __u32 len; + __u64 name; +}; + +/* + * States prefixed with '__' are internal states and cannot be passed to the + * DRM_IOCTL_VC4_GEM_MADVISE ioctl. + */ +#define VC4_MADV_WILLNEED 0 +#define VC4_MADV_DONTNEED 1 +#define __VC4_MADV_PURGED 2 +#define __VC4_MADV_NOTSUPP 3 + +struct drm_vc4_gem_madvise { + __u32 handle; + __u32 madv; + __u32 retained; + __u32 pad; +}; + +enum { + VC4_PERFCNT_FEP_VALID_PRIMS_NO_RENDER, + VC4_PERFCNT_FEP_VALID_PRIMS_RENDER, + VC4_PERFCNT_FEP_CLIPPED_QUADS, + VC4_PERFCNT_FEP_VALID_QUADS, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_STENCIL, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_NON_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_WRITTEN_TO_COLOR_BUF, + VC4_PERFCNT_PLB_PRIMS_OUTSIDE_VIEWPORT, + VC4_PERFCNT_PLB_PRIMS_NEED_CLIPPING, + VC4_PERFCNT_PSE_PRIMS_REVERSED, + VC4_PERFCNT_QPU_TOTAL_IDLE_CYCLES, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_VERTEX_COORD_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_FRAGMENT_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_EXEC_VALID_INST, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_TMUS, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_SCOREBOARD, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_VARYINGS, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_MISS, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_MISS, + VC4_PERFCNT_TMU_TOTAL_TEXT_QUADS_PROCESSED, + VC4_PERFCNT_TMU_TOTAL_TEXT_CACHE_MISS, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VDW_STALLED, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VCD_STALLED, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_HIT, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_MISS, + VC4_PERFCNT_NUM_EVENTS, +}; + +#define DRM_VC4_MAX_PERF_COUNTERS 16 + +struct drm_vc4_perfmon_create { + __u32 id; + __u32 ncounters; + __u8 events[DRM_VC4_MAX_PERF_COUNTERS]; +}; + +struct drm_vc4_perfmon_destroy { + __u32 id; +}; + +/* + * Returns the values of the performance counters tracked by this + * perfmon (as an array of ncounters u64 values). + * + * No implicit synchronization is performed, so the user has to + * guarantee that any jobs using this perfmon have already been + * completed (probably by blocking on the seqno returned by the + * last exec that used the perfmon). + */ +struct drm_vc4_perfmon_get_values { + __u32 id; + __u64 values_ptr; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _VC4_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/via_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/via_drm.h new file mode 100644 index 0000000..8b69e81 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/via_drm.h @@ -0,0 +1,283 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _VIA_DRM_H_ +#define _VIA_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _VIA_DEFINES_ +#define _VIA_DEFINES_ + +#include "via_drmclient.h" + +#define VIA_NR_SAREA_CLIPRECTS 8 +#define VIA_NR_XVMC_PORTS 10 +#define VIA_NR_XVMC_LOCKS 5 +#define VIA_MAX_CACHELINE_SIZE 64 +#define XVMCLOCKPTR(saPriv,lockNo) \ + ((__volatile__ struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ + (VIA_MAX_CACHELINE_SIZE - 1)) & \ + ~(VIA_MAX_CACHELINE_SIZE - 1)) + \ + VIA_MAX_CACHELINE_SIZE*(lockNo))) + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define VIA_NR_TEX_REGIONS 64 +#define VIA_LOG_MIN_TEX_REGION_SIZE 16 +#endif + +#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define VIA_UPLOAD_CTX 0x4 +#define VIA_UPLOAD_BUFFERS 0x8 +#define VIA_UPLOAD_TEX0 0x10 +#define VIA_UPLOAD_TEX1 0x20 +#define VIA_UPLOAD_CLIPRECTS 0x40 +#define VIA_UPLOAD_ALL 0xff + +/* VIA specific ioctls */ +#define DRM_VIA_ALLOCMEM 0x00 +#define DRM_VIA_FREEMEM 0x01 +#define DRM_VIA_AGP_INIT 0x02 +#define DRM_VIA_FB_INIT 0x03 +#define DRM_VIA_MAP_INIT 0x04 +#define DRM_VIA_DEC_FUTEX 0x05 +#define NOT_USED +#define DRM_VIA_DMA_INIT 0x07 +#define DRM_VIA_CMDBUFFER 0x08 +#define DRM_VIA_FLUSH 0x09 +#define DRM_VIA_PCICMD 0x0a +#define DRM_VIA_CMDBUF_SIZE 0x0b +#define NOT_USED +#define DRM_VIA_WAIT_IRQ 0x0d +#define DRM_VIA_DMA_BLIT 0x0e +#define DRM_VIA_BLIT_SYNC 0x0f + +#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t) +#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t) +#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t) +#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t) +#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t) +#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t) +#define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t) +#define DRM_IOCTL_VIA_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t) +#define DRM_IOCTL_VIA_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_VIA_FLUSH) +#define DRM_IOCTL_VIA_PCICMD DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t) +#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \ + drm_via_cmdbuf_size_t) +#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t) +#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t) +#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t) + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +#define VIA_TEX_SETUP_SIZE 8 + +/* Flags for clear ioctl + */ +#define VIA_FRONT 0x1 +#define VIA_BACK 0x2 +#define VIA_DEPTH 0x4 +#define VIA_STENCIL 0x8 +#define VIA_MEM_VIDEO 0 /* matches drm constant */ +#define VIA_MEM_AGP 1 /* matches drm constant */ +#define VIA_MEM_SYSTEM 2 +#define VIA_MEM_MIXED 3 +#define VIA_MEM_UNKNOWN 4 + +typedef struct { + __u32 offset; + __u32 size; +} drm_via_agp_t; + +typedef struct { + __u32 offset; + __u32 size; +} drm_via_fb_t; + +typedef struct { + __u32 context; + __u32 type; + __u32 size; + unsigned long index; + unsigned long offset; +} drm_via_mem_t; + +typedef struct _drm_via_init { + enum { + VIA_INIT_MAP = 0x01, + VIA_CLEANUP_MAP = 0x02 + } func; + + unsigned long sarea_priv_offset; + unsigned long fb_offset; + unsigned long mmio_offset; + unsigned long agpAddr; +} drm_via_init_t; + +typedef struct _drm_via_futex { + enum { + VIA_FUTEX_WAIT = 0x00, + VIA_FUTEX_WAKE = 0X01 + } func; + __u32 ms; + __u32 lock; + __u32 val; +} drm_via_futex_t; + +typedef struct _drm_via_dma_init { + enum { + VIA_INIT_DMA = 0x01, + VIA_CLEANUP_DMA = 0x02, + VIA_DMA_INITIALIZED = 0x03 + } func; + + unsigned long offset; + unsigned long size; + unsigned long reg_pause_addr; +} drm_via_dma_init_t; + +typedef struct _drm_via_cmdbuffer { + char *buf; + unsigned long size; +} drm_via_cmdbuffer_t; + +/* Warning: If you change the SAREA structure you must change the Xserver + * structure as well */ + +typedef struct _drm_via_tex_region { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char inUse; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} drm_via_tex_region_t; + +typedef struct _drm_via_sarea { + unsigned int dirty; + unsigned int nbox; + struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS]; + drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1]; + int texAge; /* last time texture was uploaded */ + int ctxOwner; /* last context to upload state */ + int vertexPrim; + + /* + * Below is for XvMC. + * We want the lock integers alone on, and aligned to, a cache line. + * Therefore this somewhat strange construct. + */ + + char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)]; + + unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS]; + unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS]; + unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ + + /* Used by the 3d driver only at this point, for pageflipping: + */ + unsigned int pfCurrentOffset; +} drm_via_sarea_t; + +typedef struct _drm_via_cmdbuf_size { + enum { + VIA_CMDBUF_SPACE = 0x01, + VIA_CMDBUF_LAG = 0x02 + } func; + int wait; + __u32 size; +} drm_via_cmdbuf_size_t; + +typedef enum { + VIA_IRQ_ABSOLUTE = 0x0, + VIA_IRQ_RELATIVE = 0x1, + VIA_IRQ_SIGNAL = 0x10000000, + VIA_IRQ_FORCE_SEQUENCE = 0x20000000 +} via_irq_seq_type_t; + +#define VIA_IRQ_FLAGS_MASK 0xF0000000 + +enum drm_via_irqs { + drm_via_irq_hqv0 = 0, + drm_via_irq_hqv1, + drm_via_irq_dma0_dd, + drm_via_irq_dma0_td, + drm_via_irq_dma1_dd, + drm_via_irq_dma1_td, + drm_via_irq_num +}; + +struct drm_via_wait_irq_request { + unsigned irq; + via_irq_seq_type_t type; + __u32 sequence; + __u32 signal; +}; + +typedef union drm_via_irqwait { + struct drm_via_wait_irq_request request; + struct drm_wait_vblank_reply reply; +} drm_via_irqwait_t; + +typedef struct drm_via_blitsync { + __u32 sync_handle; + unsigned engine; +} drm_via_blitsync_t; + +/* - * Below,"flags" is currently unused but will be used for possible future + * extensions like kernel space bounce buffers for bad alignments and + * blit engine busy-wait polling for better latency in the absence of + * interrupts. + */ + +typedef struct drm_via_dmablit { + __u32 num_lines; + __u32 line_length; + + __u32 fb_addr; + __u32 fb_stride; + + unsigned char *mem_addr; + __u32 mem_stride; + + __u32 flags; + int to_fb; + + drm_via_blitsync_t sync; +} drm_via_dmablit_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* _VIA_DRM_H_ */ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/virtgpu_drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/virtgpu_drm.h new file mode 100644 index 0000000..f06a789 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/libdrm/virtgpu_drm.h @@ -0,0 +1,182 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRTGPU_DRM_H +#define VIRTGPU_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define DRM_VIRTGPU_MAP 0x01 +#define DRM_VIRTGPU_EXECBUFFER 0x02 +#define DRM_VIRTGPU_GETPARAM 0x03 +#define DRM_VIRTGPU_RESOURCE_CREATE 0x04 +#define DRM_VIRTGPU_RESOURCE_INFO 0x05 +#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06 +#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07 +#define DRM_VIRTGPU_WAIT 0x08 +#define DRM_VIRTGPU_GET_CAPS 0x09 + +#define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01 +#define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02 +#define VIRTGPU_EXECBUF_FLAGS (\ + VIRTGPU_EXECBUF_FENCE_FD_IN |\ + VIRTGPU_EXECBUF_FENCE_FD_OUT |\ + 0) + +struct drm_virtgpu_map { + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; +}; + +struct drm_virtgpu_execbuffer { + __u32 flags; + __u32 size; + __u64 command; /* void* */ + __u64 bo_handles; + __u32 num_bo_handles; + __s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */ +}; + +#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ +#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */ + +struct drm_virtgpu_getparam { + __u64 param; + __u64 value; +}; + +/* NO_BO flags? NO resource flag? */ +/* resource flag for y_0_top */ +struct drm_virtgpu_resource_create { + __u32 target; + __u32 format; + __u32 bind; + __u32 width; + __u32 height; + __u32 depth; + __u32 array_size; + __u32 last_level; + __u32 nr_samples; + __u32 flags; + __u32 bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ + __u32 res_handle; /* returned by kernel */ + __u32 size; /* validate transfer in the host */ + __u32 stride; /* validate transfer in the host */ +}; + +struct drm_virtgpu_resource_info { + __u32 bo_handle; + __u32 res_handle; + __u32 size; + __u32 stride; +}; + +struct drm_virtgpu_3d_box { + __u32 x; + __u32 y; + __u32 z; + __u32 w; + __u32 h; + __u32 d; +}; + +struct drm_virtgpu_3d_transfer_to_host { + __u32 bo_handle; + struct drm_virtgpu_3d_box box; + __u32 level; + __u32 offset; +}; + +struct drm_virtgpu_3d_transfer_from_host { + __u32 bo_handle; + struct drm_virtgpu_3d_box box; + __u32 level; + __u32 offset; +}; + +#define VIRTGPU_WAIT_NOWAIT 1 /* like it */ +struct drm_virtgpu_3d_wait { + __u32 handle; /* 0 is an invalid handle */ + __u32 flags; +}; + +struct drm_virtgpu_get_caps { + __u32 cap_set_id; + __u32 cap_set_ver; + __u64 addr; + __u32 size; + __u32 pad; +}; + +#define DRM_IOCTL_VIRTGPU_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) + +#define DRM_IOCTL_VIRTGPU_EXECBUFFER \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\ + struct drm_virtgpu_execbuffer) + +#define DRM_IOCTL_VIRTGPU_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\ + struct drm_virtgpu_getparam) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, \ + struct drm_virtgpu_resource_create) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \ + struct drm_virtgpu_resource_info) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST, \ + struct drm_virtgpu_3d_transfer_from_host) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST, \ + struct drm_virtgpu_3d_transfer_to_host) + +#define DRM_IOCTL_VIRTGPU_WAIT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT, \ + struct drm_virtgpu_3d_wait) + +#define DRM_IOCTL_VIRTGPU_GET_CAPS \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ + struct drm_virtgpu_get_caps) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/tool.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/tool.h new file mode 100644 index 0000000..c7b334d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/tool.h @@ -0,0 +1,145 @@ +/* + + */ + +#ifndef TOOL_H_ +#define TOOL_H_ +//ڴ˴ͷļ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define YUV420 0 +#define YUV422 YUV420 + 1 +#define YUV444 YUV422 + 1 +/************************************************************* +Function: ReadBmpFile +Description: ȡbmpͼڴ +Input: pFilePathbmp· + pDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgrrgbֵΪ8bit + widthͼ + heightͼ +Output: +*************************************************************/ +extern void ReadBmpFile(char *pFilePath, unsigned char *pData, int & width, int & height); +/************************************************************* +Function: SaveBmpFile +Description: rgbͼݱΪbmp +Input: pFilePathbmp· + pDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgrrgbֵΪ8bit + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveBmpFile(char *pFilePath, unsigned char *pData, int width, int height); +/************************************************************* +Function: SaveRaw +Description: rawͼ +Input: pSavePathraw· + pDataraw + widthrawͼ + heightrawͼ +Output: +*************************************************************/ +extern void SaveRaw(char *pSavePath, short *pRawData, int width, int height); + +extern void SaveRaw32bit(char *pSavePath, long *pRawData, int width, int height); + +/************************************************************* +Function: SaveBmpFile2 +Description: λ8bitbmpͼ +Input: pFilePathbmp· + widthͼ + heightͼ + bitValueͼλ + pRGBDatargbͼڴָ룬rgbͼ˳Ϊbgrbgr...bgr +Output: +*************************************************************/ +extern void SaveBmpFile2(char *pFilePath, int width, int height, int bitValue, short *pRGBData); + +/************************************************************* +Function: SaveYUVData +Description: 8bit YUVͼ +Input: pSavePath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData(char *pSavePath, unsigned char *pData, int width, int height); + + + +/************************************************************* +Function: SaveYUVData2 +Description: λ8bitYUVͼ +Input: pSavePath· + pDatayuvݣλ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData2(char *pSavePath, short *pData, int width, int height, int bitValue); +/************************************************************* +Function: SaveYUVData1 +Description: 8bit YUV420ͼ +Input: pSavePath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void SaveYUVData1(char *pSavePath, unsigned char *pData, int width, int height, int fmt); +/************************************************************* +Function: ReadYUVData1 +Description: ȡ8bit YUV420ͼ +Input: pReadPath· + pDatayuvݣ8bit˳yyy...yyyuuu...uuuvvv...vvv + widthͼ + heightͼ +Output: +*************************************************************/ +extern void ReadYUVData1(char *pReadPath, unsigned char *pData, int width, int height, int fmt); +/************************************************************* +Function: Yuvfmtconv +Description: yuv fmt conversion.444 420 422 to 444 420 422 +Input: pDatain 뻺 + pDataout + width + height + fmt_in ʽ + fmt_out ʽ +Output: +*************************************************************/ +extern void Yuvfmtconv(void *pDatain, void *pDataout, int width, int height, int fmt_in, int fmt_out, int size); +/************************************************************* +Function: Yuvbitstochar +Description: save yuv to 8 bitdepth +Input: pDatain 뻺 + pDataout + size yuv + height λ +Output: +*************************************************************/ +extern void Yuvbitstochar(short *pDatain, unsigned char *pDataout, int size, int bitdepth); + +/************************************************************* +Function: SaveCfaBmp +Description: rawcfaͼ +Input: pRawDatarawͼ + widthrawͼ + heightrawͼߣ + bayerPatternbayer patternʽȡֵΧ[03] + bitValuerawλ +Output: +*************************************************************/ +extern void SaveCfaBmp(char *pFilePath, short *pRawData, int width, int height, int bayerPattern, int bitValue); + +#ifdef __cplusplus +} +#endif + +#endif // TOOL_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/xf86drm.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/xf86drm.h new file mode 100644 index 0000000..d86428a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/xf86drm.h @@ -0,0 +1,930 @@ +/** + * \file xf86drm.h + * OS-independent header for DRM user-level library interface. + * + * \author Rickard E. (Rik) Faith + */ + +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _XF86DRM_H_ +#define _XF86DRM_H_ + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef DRM_MAX_MINOR +#define DRM_MAX_MINOR 16 +#endif + +#if defined(__linux__) + +#define DRM_IOCTL_NR(n) _IOC_NR(n) +#define DRM_IOC_VOID _IOC_NONE +#define DRM_IOC_READ _IOC_READ +#define DRM_IOC_WRITE _IOC_WRITE +#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) + +#else /* One of the *BSDs */ + +#include +#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define DRM_IOC_VOID IOC_VOID +#define DRM_IOC_READ IOC_OUT +#define DRM_IOC_WRITE IOC_IN +#define DRM_IOC_READWRITE IOC_INOUT +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) + +#endif + + /* Defaults, if nothing set in xf86config */ +#define DRM_DEV_UID 0 +#define DRM_DEV_GID 0 +/* Default /dev/dri directory permissions 0755 */ +#define DRM_DEV_DIRMODE \ + (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) +#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + +#ifdef __OpenBSD__ +#define DRM_DIR_NAME "/dev" +#define DRM_PRIMARY_MINOR_NAME "drm" +#define DRM_CONTROL_MINOR_NAME "drmC" +#define DRM_RENDER_MINOR_NAME "drmR" +#else +#define DRM_DIR_NAME "/dev/dri" +#define DRM_PRIMARY_MINOR_NAME "card" +#define DRM_CONTROL_MINOR_NAME "controlD" +#define DRM_RENDER_MINOR_NAME "renderD" +#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ +#endif + +#define DRM_DEV_NAME "%s/" DRM_PRIMARY_MINOR_NAME "%d" +#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d" +#define DRM_RENDER_DEV_NAME "%s/" DRM_RENDER_MINOR_NAME "%d" + +#define DRM_NODE_NAME_MAX \ + (sizeof(DRM_DIR_NAME) + 1 /* slash */ \ + + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \ + sizeof(DRM_CONTROL_MINOR_NAME), \ + sizeof(DRM_RENDER_MINOR_NAME)) \ + + sizeof("144") /* highest possible node number */ \ + + 1) /* NULL-terminator */ + +#define DRM_ERR_NO_DEVICE (-1001) +#define DRM_ERR_NO_ACCESS (-1002) +#define DRM_ERR_NOT_ROOT (-1003) +#define DRM_ERR_INVALID (-1004) +#define DRM_ERR_NO_FD (-1005) + +#define DRM_AGP_NO_HANDLE 0 + +typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ +typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ + +#if (__GNUC__ >= 3) +#define DRM_PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) +#else +#define DRM_PRINTFLIKE(f, a) +#endif + +typedef struct _drmServerInfo { + int (*debug_print)(const char *format, va_list ap) DRM_PRINTFLIKE(1,0); + int (*load_module)(const char *name); + void (*get_perms)(gid_t *, mode_t *); +} drmServerInfo, *drmServerInfoPtr; + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +extern int drmIoctl(int fd, unsigned long request, void *arg); +extern void *drmGetHashTable(void); +extern drmHashEntry *drmGetEntry(int fd); + +/** + * Driver version information. + * + * \sa drmGetVersion() and drmSetVersion(). + */ +typedef struct _drmVersion { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + int name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + int date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + int desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +} drmVersion, *drmVersionPtr; + +typedef struct _drmStats { + unsigned long count; /**< Number of data */ + struct { + unsigned long value; /**< Value from kernel */ + const char *long_format; /**< Suggested format for long_name */ + const char *long_name; /**< Long name for value */ + const char *rate_format; /**< Suggested format for rate_name */ + const char *rate_name; /**< Short name for value per second */ + int isvalue; /**< True if value (vs. counter) */ + const char *mult_names; /**< Multiplier names (e.g., "KGM") */ + int mult; /**< Multiplier value (e.g., 1024) */ + int verbose; /**< Suggest only in verbose output */ + } data[15]; +} drmStatsT; + + + /* All of these enums *MUST* match with the + kernel implementation -- so do *NOT* + change them! (The drmlib implementation + will just copy the flags instead of + translating them.) */ +typedef enum { + DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */ + DRM_REGISTERS = 1, /**< no caching, no core dump */ + DRM_SHM = 2, /**< shared, cached */ + DRM_AGP = 3, /**< AGP/GART */ + DRM_SCATTER_GATHER = 4, /**< PCI scatter/gather */ + DRM_CONSISTENT = 5 /**< PCI consistent */ +} drmMapType; + +typedef enum { + DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */ + DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */ + DRM_LOCKED = 0x0004, /**< Physical pages locked */ + DRM_KERNEL = 0x0008, /**< Kernel requires access */ + DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */ + DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */ + DRM_REMOVABLE = 0x0040 /**< Removable mapping */ +} drmMapFlags; + +/** + * \warning These values *MUST* match drm.h + */ +typedef enum { + /** \name Flags for DMA buffer dispatch */ + /*@{*/ + DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note the buffer may not yet have been + * processed by the hardware -- getting a + * hardware lock with the hardware quiescent + * will ensure that the buffer has been + * processed. + */ + DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + /*@}*/ + + /** \name Flags for DMA buffer request */ + /*@{*/ + DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ + /*@}*/ +} drmDMAFlags; + +typedef enum { + DRM_PAGE_ALIGN = 0x01, + DRM_AGP_BUFFER = 0x02, + DRM_SG_BUFFER = 0x04, + DRM_FB_BUFFER = 0x08, + DRM_PCI_BUFFER_RO = 0x10 +} drmBufDescFlags; + +typedef enum { + DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +} drmLockFlags; + +typedef enum { + DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and + never swapped. */ + DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */ +} drm_context_tFlags, *drm_context_tFlagsPtr; + +typedef struct _drmBufDesc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ +} drmBufDesc, *drmBufDescPtr; + +typedef struct _drmBufInfo { + int count; /**< Number of buffers described in list */ + drmBufDescPtr list; /**< List of buffer descriptions */ +} drmBufInfo, *drmBufInfoPtr; + +typedef struct _drmBuf { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + drmAddress address; /**< Address */ +} drmBuf, *drmBufPtr; + +/** + * Buffer mapping information. + * + * Used by drmMapBufs() and drmUnmapBufs() to store information about the + * mapped buffers. + */ +typedef struct _drmBufMap { + int count; /**< Number of buffers mapped */ + drmBufPtr list; /**< Buffers */ +} drmBufMap, *drmBufMapPtr; + +typedef struct _drmLock { + volatile unsigned int lock; + char padding[60]; + /* This is big enough for most current (and future?) architectures: + DEC Alpha: 32 bytes + Intel Merced: ? + Intel P5/PPro/PII/PIII: 32 bytes + Intel StrongARM: 32 bytes + Intel i386/i486: 16 bytes + MIPS: 32 bytes (?) + Motorola 68k: 16 bytes + Motorola PowerPC: 32 bytes + Sun SPARC: 32 bytes + */ +} drmLock, *drmLockPtr; + +/** + * Indices here refer to the offset into + * list in drmBufInfo + */ +typedef struct _drmDMAReq { + drm_context_t context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_list; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send, in bytes */ + drmDMAFlags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size of buffers requested */ + int *request_list; /**< Buffer information */ + int *request_sizes; /**< Minimum acceptable sizes */ + int granted_count; /**< Number of buffers granted at this size */ +} drmDMAReq, *drmDMAReqPtr; + +typedef struct _drmRegion { + drm_handle_t handle; + unsigned int offset; + drmSize size; + drmAddress map; +} drmRegion, *drmRegionPtr; + +typedef struct _drmTextureRegion { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; /**< Explicitly pad this out */ + unsigned int age; +} drmTextureRegion, *drmTextureRegionPtr; + + +typedef enum { + DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drmVBlankSeqType; +#define DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +typedef struct _drmVBlankReq { + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq, *drmVBlankReqPtr; + +typedef struct _drmVBlankReply { + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec; + long tval_usec; +} drmVBlankReply, *drmVBlankReplyPtr; + +typedef union _drmVBlank { + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank, *drmVBlankPtr; + +typedef struct _drmSetVersion { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drmSetVersion, *drmSetVersionPtr; + +#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) + +#define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ + +#if defined(__GNUC__) && (__GNUC__ >= 2) +# if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__) + /* Reflect changes here to drmP.h */ +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + int __dummy; /* Can't mark eax as clobbered */ \ + __asm__ __volatile__( \ + "lock ; cmpxchg %4,%1\n\t" \ + "setnz %0" \ + : "=d" (__ret), \ + "=m" (__drm_dummy_lock(lock)), \ + "=a" (__dummy) \ + : "2" (old), \ + "r" (new)); \ + } while (0) + +#elif defined(__alpha__) + +#define DRM_CAS(lock, old, new, ret) \ + do { \ + int tmp, old32; \ + __asm__ __volatile__( \ + " addl $31, %5, %3\n" \ + "1: ldl_l %0, %2\n" \ + " cmpeq %0, %3, %1\n" \ + " beq %1, 2f\n" \ + " mov %4, %0\n" \ + " stl_c %0, %2\n" \ + " beq %0, 3f\n" \ + " mb\n" \ + "2: cmpeq %1, 0, %1\n" \ + ".subsection 2\n" \ + "3: br 1b\n" \ + ".previous" \ + : "=&r"(tmp), "=&r"(ret), \ + "=m"(__drm_dummy_lock(lock)), \ + "=&r"(old32) \ + : "r"(new), "r"(old) \ + : "memory"); \ + } while (0) + +#elif defined(__sparc__) + +#define DRM_CAS(lock,old,new,__ret) \ +do { register unsigned int __old __asm("o0"); \ + register unsigned int __new __asm("o1"); \ + register volatile unsigned int *__lock __asm("o2"); \ + __old = old; \ + __new = new; \ + __lock = (volatile unsigned int *)lock; \ + __asm__ __volatile__( \ + /*"cas [%2], %3, %0"*/ \ + ".word 0xd3e29008\n\t" \ + /*"membar #StoreStore | #StoreLoad"*/ \ + ".word 0x8143e00a" \ + : "=&r" (__new) \ + : "0" (__new), \ + "r" (__lock), \ + "r" (__old) \ + : "memory"); \ + __ret = (__new != __old); \ +} while(0) + +#elif defined(__ia64__) + +#ifdef __INTEL_COMPILER +/* this currently generates bad code (missing stop bits)... */ +#include + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned long __result, __old = (old) & 0xffffffff; \ + __mf(); \ + __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\ + __ret = (__result) != (__old); \ +/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ + (old), (new)) \ + != (old)); */\ + } while (0) + +#else +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned int __result, __old = (old); \ + __asm__ __volatile__( \ + "mf\n" \ + "mov ar.ccv=%2\n" \ + ";;\n" \ + "cmpxchg4.acq %0=%1,%3,ar.ccv" \ + : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ + : "r" ((unsigned long)__old), "r" (new) \ + : "memory"); \ + __ret = (__result) != (__old); \ + } while (0) + +#endif + +#elif defined(__powerpc__) + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__( \ + "sync;" \ + "0: lwarx %0,0,%1;" \ + " xor. %0,%3,%0;" \ + " bne 1f;" \ + " stwcx. %2,0,%1;" \ + " bne- 0b;" \ + "1: " \ + "sync;" \ + : "=&r"(__ret) \ + : "r"(lock), "r"(new), "r"(old) \ + : "cr0", "memory"); \ + } while (0) + +# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \ + || defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) + #undef DRM_DEV_MODE + #define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + + #define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__ ( \ + "1: ldrex %0, [%1]\n" \ + " teq %0, %2\n" \ + " ite eq\n" \ + " strexeq %0, %3, [%1]\n" \ + " movne %0, #1\n" \ + : "=&r" (__ret) \ + : "r" (lock), "r" (old), "r" (new) \ + : "cc","memory"); \ + } while (0) + +#endif /* architecture */ +#endif /* __GNUC__ >= 2 */ + +#ifndef DRM_CAS +#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ +#endif + +#if defined(__alpha__) +#define DRM_CAS_RESULT(_result) long _result +#elif defined(__powerpc__) +#define DRM_CAS_RESULT(_result) int _result +#else +#define DRM_CAS_RESULT(_result) char _result +#endif + +#define DRM_LIGHT_LOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + } while(0) + + /* This one counts fast locks -- for + benchmarking only. */ +#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + else ++count; \ + } while(0) + +#define DRM_LOCK(fd,lock,context,flags) \ + do { \ + if (flags) drmGetLock(fd,context,flags); \ + else DRM_LIGHT_LOCK(fd,lock,context); \ + } while(0) + +#define DRM_UNLOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \ + if (__ret) drmUnlock(fd,context); \ + } while(0) + + /* Simple spin locks */ +#define DRM_SPINLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + do { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) while ((spin)->lock); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_TAKE(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + int cur; \ + do { \ + cur = (*spin).lock; \ + DRM_CAS(spin,cur,val,__ret); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ + do { \ + int __i; \ + __ret = 1; \ + for (__i = 0; __ret && __i < count; __i++) { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) for (;__i < count && (spin)->lock; __i++); \ + } \ + } while(0) + +#define DRM_SPINUNLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + if ((*spin).lock == val) { /* else server stole lock */ \ + do { \ + DRM_CAS(spin,val,0,__ret); \ + } while (__ret); \ + } \ + } while(0) + + + +/* General user-level programmer's API: unprivileged */ +extern int drmAvailable(void); +extern int drmOpen(const char *name, const char *busid); + +#define DRM_NODE_PRIMARY 0 +#define DRM_NODE_CONTROL 1 +#define DRM_NODE_RENDER 2 +#define DRM_NODE_MAX 3 + +extern int drmOpenWithType(const char *name, const char *busid, + int type); + +extern int drmOpenControl(int minor); +extern int drmOpenRender(int minor); +extern int drmClose(int fd); +extern drmVersionPtr drmGetVersion(int fd); +extern drmVersionPtr drmGetLibVersion(int fd); +extern int drmGetCap(int fd, uint64_t capability, uint64_t *value); +extern void drmFreeVersion(drmVersionPtr); +extern int drmGetMagic(int fd, drm_magic_t * magic); +extern char *drmGetBusid(int fd); +extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum, + int funcnum); +extern int drmGetMap(int fd, int idx, drm_handle_t *offset, + drmSize *size, drmMapType *type, + drmMapFlags *flags, drm_handle_t *handle, + int *mtrr); +extern int drmGetClient(int fd, int idx, int *auth, int *pid, + int *uid, unsigned long *magic, + unsigned long *iocs); +extern int drmGetStats(int fd, drmStatsT *stats); +extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); +extern int drmCommandNone(int fd, unsigned long drmCommandIndex); +extern int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); + +/* General user-level programmer's API: X server (root) only */ +extern void drmFreeBusid(const char *busid); +extern int drmSetBusid(int fd, const char *busid); +extern int drmAuthMagic(int fd, drm_magic_t magic); +extern int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle); +extern int drmRmMap(int fd, drm_handle_t handle); +extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t handle); + +extern int drmAddBufs(int fd, int count, int size, + drmBufDescFlags flags, + int agp_offset); +extern int drmMarkBufs(int fd, double low, double high); +extern int drmCreateContext(int fd, drm_context_t * handle); +extern int drmSetContextFlags(int fd, drm_context_t context, + drm_context_tFlags flags); +extern int drmGetContextFlags(int fd, drm_context_t context, + drm_context_tFlagsPtr flags); +extern int drmAddContextTag(int fd, drm_context_t context, void *tag); +extern int drmDelContextTag(int fd, drm_context_t context); +extern void *drmGetContextTag(int fd, drm_context_t context); +extern drm_context_t * drmGetReservedContextList(int fd, int *count); +extern void drmFreeReservedContextList(drm_context_t *); +extern int drmSwitchToContext(int fd, drm_context_t context); +extern int drmDestroyContext(int fd, drm_context_t handle); +extern int drmCreateDrawable(int fd, drm_drawable_t * handle); +extern int drmDestroyDrawable(int fd, drm_drawable_t handle); +extern int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, + drm_drawable_info_type_t type, + unsigned int num, void *data); +extern int drmCtlInstHandler(int fd, int irq); +extern int drmCtlUninstHandler(int fd); +extern int drmSetClientCap(int fd, uint64_t capability, + uint64_t value); + +extern int drmCrtcGetSequence(int fd, uint32_t crtcId, + uint64_t *sequence, uint64_t *ns); +extern int drmCrtcQueueSequence(int fd, uint32_t crtcId, + uint32_t flags, uint64_t sequence, + uint64_t *sequence_queued, + uint64_t user_data); +/* General user-level programmer's API: authenticated client and/or X */ +extern int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address); +extern int drmUnmap(drmAddress address, drmSize size); +extern drmBufInfoPtr drmGetBufInfo(int fd); +extern drmBufMapPtr drmMapBufs(int fd); +extern int drmUnmapBufs(drmBufMapPtr bufs); +extern int drmDMA(int fd, drmDMAReqPtr request); +extern int drmFreeBufs(int fd, int count, int *list); +extern int drmGetLock(int fd, + drm_context_t context, + drmLockFlags flags); +extern int drmUnlock(int fd, drm_context_t context); +extern int drmFinish(int fd, int context, drmLockFlags flags); +extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t * handle); + +/* AGP/GART support: X server (root) only */ +extern int drmAgpAcquire(int fd); +extern int drmAgpRelease(int fd); +extern int drmAgpEnable(int fd, unsigned long mode); +extern int drmAgpAlloc(int fd, unsigned long size, + unsigned long type, unsigned long *address, + drm_handle_t *handle); +extern int drmAgpFree(int fd, drm_handle_t handle); +extern int drmAgpBind(int fd, drm_handle_t handle, + unsigned long offset); +extern int drmAgpUnbind(int fd, drm_handle_t handle); + +/* AGP/GART info: authenticated client and/or X */ +extern int drmAgpVersionMajor(int fd); +extern int drmAgpVersionMinor(int fd); +extern unsigned long drmAgpGetMode(int fd); +extern unsigned long drmAgpBase(int fd); /* Physical location */ +extern unsigned long drmAgpSize(int fd); /* Bytes */ +extern unsigned long drmAgpMemoryUsed(int fd); +extern unsigned long drmAgpMemoryAvail(int fd); +extern unsigned int drmAgpVendorId(int fd); +extern unsigned int drmAgpDeviceId(int fd); + +/* PCI scatter/gather support: X server (root) only */ +extern int drmScatterGatherAlloc(int fd, unsigned long size, + drm_handle_t *handle); +extern int drmScatterGatherFree(int fd, drm_handle_t handle); + +extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); + +/* Support routines */ +extern void drmSetServerInfo(drmServerInfoPtr info); +extern int drmError(int err, const char *label); +extern void *drmMalloc(int size); +extern void drmFree(void *pt); + +/* Hash table routines */ +extern void *drmHashCreate(void); +extern int drmHashDestroy(void *t); +extern int drmHashLookup(void *t, unsigned long key, void **value); +extern int drmHashInsert(void *t, unsigned long key, void *value); +extern int drmHashDelete(void *t, unsigned long key); +extern int drmHashFirst(void *t, unsigned long *key, void **value); +extern int drmHashNext(void *t, unsigned long *key, void **value); + +/* PRNG routines */ +extern void *drmRandomCreate(unsigned long seed); +extern int drmRandomDestroy(void *state); +extern unsigned long drmRandom(void *state); +extern double drmRandomDouble(void *state); + +/* Skip list routines */ + +extern void *drmSLCreate(void); +extern int drmSLDestroy(void *l); +extern int drmSLLookup(void *l, unsigned long key, void **value); +extern int drmSLInsert(void *l, unsigned long key, void *value); +extern int drmSLDelete(void *l, unsigned long key); +extern int drmSLNext(void *l, unsigned long *key, void **value); +extern int drmSLFirst(void *l, unsigned long *key, void **value); +extern void drmSLDump(void *l); +extern int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); + +extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened); +extern int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type); +extern void drmCloseOnce(int fd); +extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2); + +extern int drmSetMaster(int fd); +extern int drmDropMaster(int fd); +extern int drmIsMaster(int fd); + +#define DRM_EVENT_CONTEXT_VERSION 4 + +typedef struct _drmEventContext { + + /* This struct is versioned so we can add more pointers if we + * add more events. */ + int version; + + void (*vblank_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + + void (*page_flip_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + + void (*page_flip_handler2)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + unsigned int crtc_id, + void *user_data); + + void (*sequence_handler)(int fd, + uint64_t sequence, + uint64_t ns, + uint64_t user_data); +} drmEventContext, *drmEventContextPtr; + +extern int drmHandleEvent(int fd, drmEventContextPtr evctx); + +extern char *drmGetDeviceNameFromFd(int fd); + +/* Improved version of drmGetDeviceNameFromFd which attributes for any type of + * device/node - card, control or renderD. + */ +extern char *drmGetDeviceNameFromFd2(int fd); +extern int drmGetNodeTypeFromFd(int fd); + +extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd); +extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle); + +extern char *drmGetPrimaryDeviceNameFromFd(int fd); +extern char *drmGetRenderDeviceNameFromFd(int fd); + +#define DRM_BUS_PCI 0 +#define DRM_BUS_USB 1 +#define DRM_BUS_PLATFORM 2 +#define DRM_BUS_HOST1X 3 + +typedef struct _drmPciBusInfo { + uint16_t domain; + uint8_t bus; + uint8_t dev; + uint8_t func; +} drmPciBusInfo, *drmPciBusInfoPtr; + +typedef struct _drmPciDeviceInfo { + uint16_t vendor_id; + uint16_t device_id; + uint16_t subvendor_id; + uint16_t subdevice_id; + uint8_t revision_id; +} drmPciDeviceInfo, *drmPciDeviceInfoPtr; + +typedef struct _drmUsbBusInfo { + uint8_t bus; + uint8_t dev; +} drmUsbBusInfo, *drmUsbBusInfoPtr; + +typedef struct _drmUsbDeviceInfo { + uint16_t vendor; + uint16_t product; +} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr; + +#define DRM_PLATFORM_DEVICE_NAME_LEN 512 + +typedef struct _drmPlatformBusInfo { + char fullname[DRM_PLATFORM_DEVICE_NAME_LEN]; +} drmPlatformBusInfo, *drmPlatformBusInfoPtr; + +typedef struct _drmPlatformDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr; + +#define DRM_HOST1X_DEVICE_NAME_LEN 512 + +typedef struct _drmHost1xBusInfo { + char fullname[DRM_HOST1X_DEVICE_NAME_LEN]; +} drmHost1xBusInfo, *drmHost1xBusInfoPtr; + +typedef struct _drmHost1xDeviceInfo { + char **compatible; /* NULL terminated list of compatible strings */ +} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; + +typedef struct _drmDevice { + char **nodes; /* DRM_NODE_MAX sized array */ + int available_nodes; /* DRM_NODE_* bitmask */ + int bustype; + union { + drmPciBusInfoPtr pci; + drmUsbBusInfoPtr usb; + drmPlatformBusInfoPtr platform; + drmHost1xBusInfoPtr host1x; + } businfo; + union { + drmPciDeviceInfoPtr pci; + drmUsbDeviceInfoPtr usb; + drmPlatformDeviceInfoPtr platform; + drmHost1xDeviceInfoPtr host1x; + } deviceinfo; +} drmDevice, *drmDevicePtr; + +extern int drmGetDevice(int fd, drmDevicePtr *device); +extern void drmFreeDevice(drmDevicePtr *device); + +extern int drmGetDevices(drmDevicePtr devices[], int max_devices); +extern void drmFreeDevices(drmDevicePtr devices[], int count); + +#define DRM_DEVICE_GET_PCI_REVISION (1 << 0) +extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device); +extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices); + +extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); + +extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); +extern int drmSyncobjDestroy(int fd, uint32_t handle); +extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd); +extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle); + +extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd); +extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd); +extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, + uint64_t *points, uint32_t handle_count); +extern int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, + unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points, + uint32_t handle_count); +extern int drmSyncobjTransfer(int fd, + uint32_t dst_handle, uint64_t dst_point, + uint32_t src_handle, uint64_t src_point, + uint32_t flags); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/xf86drmMode.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/xf86drmMode.h new file mode 100644 index 0000000..a32902f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/drm/include/xf86drmMode.h @@ -0,0 +1,551 @@ +/* + * \file xf86drmMode.h + * Header for DRM modesetting interface. + * + * \author Jakob Bornecrantz + * + * \par Acknowledgements: + * Feb 2007, Dave Airlie + */ + +/* + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 2007-2008 Dave Airlie + * Copyright (c) 2007-2008 Jakob Bornecrantz + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _XF86DRMMODE_H_ +#define _XF86DRMMODE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include + +/* + * This is the interface for modesetting for drm. + * + * In order to use this interface you must include either or another + * header defining uint32_t, int32_t and uint16_t. + * + * It aims to provide a randr1.2 compatible interface for modesettings in the + * kernel, the interface is also meant to be used by libraries like EGL. + * + * More information can be found in randrproto.txt which can be found here: + * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git + * + * There are some major differences to be noted. Unlike the randr1.2 proto you + * need to create the memory object of the framebuffer yourself with the ttm + * buffer object interface. This object needs to be pinned. + */ + +/* + * If we pickup an old version of drm.h which doesn't include drm_mode.h + * we should redefine defines. This is so that builds doesn't breaks with + * new libdrm on old kernels. + */ +#ifndef _DRM_MODE_H + +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NON_GPU 0 +#define DRM_MODE_SCALE_FULLSCREEN 1 +#define DRM_MODE_SCALE_NO_SCALE 2 +#define DRM_MODE_SCALE_ASPECT 3 + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 + +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 +#define DRM_MODE_SUBCONNECTOR_SCART 9 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) + +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) + +#endif /* _DRM_MODE_H */ + + +/* + * Feature defines + * + * Just because these are defined doesn't mean that the kernel + * can do that feature, its just for new code vs old libdrm. + */ +#define DRM_MODE_FEATURE_KMS 1 +#define DRM_MODE_FEATURE_DIRTYFB 1 + + +typedef struct _drmModeRes { + + int count_fbs; + uint32_t *fbs; + + int count_crtcs; + uint32_t *crtcs; + + int count_connectors; + uint32_t *connectors; + + int count_encoders; + uint32_t *encoders; + + uint32_t min_width, max_width; + uint32_t min_height, max_height; +} drmModeRes, *drmModeResPtr; + +typedef struct _drmModeModeInfo { + uint32_t clock; + uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; + uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; + + uint32_t vrefresh; + + uint32_t flags; + uint32_t type; + char name[DRM_DISPLAY_MODE_LEN]; +} drmModeModeInfo, *drmModeModeInfoPtr; + +typedef struct _drmModeFB { + uint32_t fb_id; + uint32_t width, height; + uint32_t pitch; + uint32_t bpp; + uint32_t depth; + /* driver specific handle */ + uint32_t handle; +} drmModeFB, *drmModeFBPtr; + +typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr; + +typedef struct _drmModePropertyBlob { + uint32_t id; + uint32_t length; + void *data; +} drmModePropertyBlobRes, *drmModePropertyBlobPtr; + +typedef struct _drmModeProperty { + uint32_t prop_id; + uint32_t flags; + char name[DRM_PROP_NAME_LEN]; + int count_values; + uint64_t *values; /* store the blob lengths */ + int count_enums; + struct drm_mode_property_enum *enums; + int count_blobs; + uint32_t *blob_ids; /* store the blob IDs */ +} drmModePropertyRes, *drmModePropertyPtr; + +static __inline int drm_property_type_is(drmModePropertyPtr property, + uint32_t type) +{ + /* instanceof for props.. handles extended type vs original types: */ + if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) + return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type; + return property->flags & type; +} + +typedef struct _drmModeCrtc { + uint32_t crtc_id; + uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */ + + uint32_t x, y; /**< Position on the framebuffer */ + uint32_t width, height; + int mode_valid; + drmModeModeInfo mode; + + int gamma_size; /**< Number of gamma stops */ + +} drmModeCrtc, *drmModeCrtcPtr; + +typedef struct _drmModeEncoder { + uint32_t encoder_id; + uint32_t encoder_type; + uint32_t crtc_id; + uint32_t possible_crtcs; + uint32_t possible_clones; +} drmModeEncoder, *drmModeEncoderPtr; + +typedef enum { + DRM_MODE_CONNECTED = 1, + DRM_MODE_DISCONNECTED = 2, + DRM_MODE_UNKNOWNCONNECTION = 3 +} drmModeConnection; + +typedef enum { + DRM_MODE_SUBPIXEL_UNKNOWN = 1, + DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2, + DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3, + DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4, + DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5, + DRM_MODE_SUBPIXEL_NONE = 6 +} drmModeSubPixel; + +typedef struct _drmModeConnector { + uint32_t connector_id; + uint32_t encoder_id; /**< Encoder currently connected to */ + uint32_t connector_type; + uint32_t connector_type_id; + drmModeConnection connection; + uint32_t mmWidth, mmHeight; /**< HxW in millimeters */ + drmModeSubPixel subpixel; + + int count_modes; + drmModeModeInfoPtr modes; + + int count_props; + uint32_t *props; /**< List of property ids */ + uint64_t *prop_values; /**< List of property values */ + + int count_encoders; + uint32_t *encoders; /**< List of encoder ids */ +} drmModeConnector, *drmModeConnectorPtr; + +#define DRM_PLANE_TYPE_OVERLAY 0 +#define DRM_PLANE_TYPE_PRIMARY 1 +#define DRM_PLANE_TYPE_CURSOR 2 + +typedef struct _drmModeObjectProperties { + uint32_t count_props; + uint32_t *props; + uint64_t *prop_values; +} drmModeObjectProperties, *drmModeObjectPropertiesPtr; + +typedef struct _drmModePlane { + uint32_t count_formats; + uint32_t *formats; + uint32_t plane_id; + + uint32_t crtc_id; + uint32_t fb_id; + + uint32_t crtc_x, crtc_y; + uint32_t x, y; + + uint32_t possible_crtcs; + uint32_t gamma_size; +} drmModePlane, *drmModePlanePtr; + +typedef struct _drmModePlaneRes { + uint32_t count_planes; + uint32_t *planes; +} drmModePlaneRes, *drmModePlaneResPtr; + +extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr ); +extern void drmModeFreeResources( drmModeResPtr ptr ); +extern void drmModeFreeFB( drmModeFBPtr ptr ); +extern void drmModeFreeCrtc( drmModeCrtcPtr ptr ); +extern void drmModeFreeConnector( drmModeConnectorPtr ptr ); +extern void drmModeFreeEncoder( drmModeEncoderPtr ptr ); +extern void drmModeFreePlane( drmModePlanePtr ptr ); +extern void drmModeFreePlaneResources(drmModePlaneResPtr ptr); + +/** + * Retrieves all of the resources associated with a card. + */ +extern drmModeResPtr drmModeGetResources(int fd); + +/* + * FrameBuffer manipulation. + */ + +/** + * Retrieve information about framebuffer bufferId + */ +extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId); + +/** + * Creates a new framebuffer with an buffer object as its scanout buffer. + */ +extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint32_t *buf_id); +/* ...with a specific pixel format */ +extern int drmModeAddFB2(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + uint32_t *buf_id, uint32_t flags); + +/* ...with format modifiers */ +int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + const uint64_t modifier[4], uint32_t *buf_id, + uint32_t flags); + +/** + * Destroies the given framebuffer. + */ +extern int drmModeRmFB(int fd, uint32_t bufferId); + +/** + * Mark a region of a framebuffer as dirty. + */ +extern int drmModeDirtyFB(int fd, uint32_t bufferId, + drmModeClipPtr clips, uint32_t num_clips); + + +/* + * Crtc functions + */ + +/** + * Retrieve information about the ctrt crtcId + */ +extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId); + +/** + * Set the mode on a crtc crtcId with the given mode modeId. + */ +int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, + uint32_t x, uint32_t y, uint32_t *connectors, int count, + drmModeModeInfoPtr mode); + +/* + * Cursor functions + */ + +/** + * Set the cursor on crtc + */ +int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height); + +int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y); +/** + * Move the cursor on crtc + */ +int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y); + +/** + * Encoder functions + */ +drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id); + +/* + * Connector manipulation + */ + +/** + * Retrieve all information about the connector connectorId. This will do a + * forced probe on the connector to retrieve remote information such as EDIDs + * from the display device. + */ +extern drmModeConnectorPtr drmModeGetConnector(int fd, + uint32_t connectorId); + +/** + * Retrieve current information, i.e the currently active mode and encoder, + * about the connector connectorId. This will not do any probing on the + * connector or remote device, and only reports what is currently known. + * For the complete set of modes and encoders associated with the connector + * use drmModeGetConnector() which will do a probe to determine any display + * link changes first. + */ +extern drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, + uint32_t connector_id); + +/** + * Attaches the given mode to an connector. + */ +extern int drmModeAttachMode(int fd, uint32_t connectorId, drmModeModeInfoPtr mode_info); + +/** + * Detaches a mode from the connector + * must be unused, by the given mode. + */ +extern int drmModeDetachMode(int fd, uint32_t connectorId, drmModeModeInfoPtr mode_info); + +extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId); +extern void drmModeFreeProperty(drmModePropertyPtr ptr); + +extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id); +extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); +extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, + uint64_t value); +extern int drmCheckModesettingSupported(const char *busid); + +extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data); +extern int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data, + uint32_t target_vblank); + +extern drmModePlaneResPtr drmModeGetPlaneResources(int fd); +extern drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id); +extern int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, + uint32_t fb_id, uint32_t flags, + int32_t crtc_x, int32_t crtc_y, + uint32_t crtc_w, uint32_t crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); + +extern drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, + uint32_t object_id, + uint32_t object_type); +extern void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr); +extern int drmModeObjectSetProperty(int fd, uint32_t object_id, + uint32_t object_type, uint32_t property_id, + uint64_t value); + + +typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr; + +extern drmModeAtomicReqPtr drmModeAtomicAlloc(void); +extern drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr req); +extern int drmModeAtomicMerge(drmModeAtomicReqPtr base, + drmModeAtomicReqPtr augment); +extern void drmModeAtomicFree(drmModeAtomicReqPtr req); +extern int drmModeAtomicGetCursor(drmModeAtomicReqPtr req); +extern void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor); +extern int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, + uint32_t object_id, + uint32_t property_id, + uint64_t value); +extern int drmModeAtomicCommit(int fd, + drmModeAtomicReqPtr req, + uint32_t flags, + void *user_data); + +extern int drmModeCreatePropertyBlob(int fd, const void *data, size_t size, + uint32_t *id); +extern int drmModeDestroyPropertyBlob(int fd, uint32_t id); + +/* + * DRM mode lease APIs. These create and manage new drm_masters with + * access to a subset of the available DRM resources + */ + +extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id); + +typedef struct drmModeLesseeList { + uint32_t count; + uint32_t lessees[0]; +} drmModeLesseeListRes, *drmModeLesseeListPtr; + +extern drmModeLesseeListPtr drmModeListLessees(int fd); + +typedef struct drmModeObjectList { + uint32_t count; + uint32_t objects[0]; +} drmModeObjectListRes, *drmModeObjectListPtr; + +extern drmModeObjectListPtr drmModeGetLease(int fd); + +extern int drmModeRevokeLease(int fd, uint32_t lessee_id); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h new file mode 100644 index 0000000..c484f4d --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RgaApi.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "drmrga.h" + +#include "RockchipRgaMacro.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +int c_RkRgaInit(); +void c_RkRgaDeInit(); +int c_RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp); +int c_RkRgaGetMmap(bo_t *bo_info); +int c_RkRgaUnmap(bo_t *bo_info); +int c_RkRgaGetBufferFd(bo_t *bo_info, int *fd); +int c_RkRgaBlit(rga_info_t *src, rga_info_t *dst, rga_info_t *src1); +int c_RkRgaColorFill(rga_info_t *dst); +#ifdef __cplusplus +} +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipFileOps.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipFileOps.h new file mode 100644 index 0000000..6d123ec --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipFileOps.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _rk_file_ops_h_ +#define _rk_file_ops_h_ + +// ------------------------------------------------------------------------------- +int get_buf_from_file(void *buf, int f, int sw, int sh, int index); +int output_buf_data_to_file(void *buf, int f, int sw, int sh, int index); +#endif + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRga.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRga.h new file mode 100644 index 0000000..c49c467 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRga.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +//#include +#include + +////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "stdio.h" + +////////////////////////////////////////////////////////////////////////////////// + +// ------------------------------------------------------------------------------- + +class RockchipRga +{ +/************************************public**************************************/ + +public: + + RockchipRga(); + ~RockchipRga(); + + int RkRgaInit(); + void RkRgaDeInit(); + int RkRgaAllocBuffer(int drm_fd /* input */, bo_t *bo_info, + int width, int height, int bpp); + int RkRgaFreeBuffer(int drm_fd /* input */, bo_t *bo_info); + int RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp); + int RkRgaGetMmap(bo_t *bo_info); + int RkRgaUnmap(bo_t *bo_info); + int RkRgaFree(bo_t *bo_info); + int RkRgaGetBufferFd(bo_t *bo_info, int *fd); + int RkRgaBlit(rga_info *src, rga_info *dst, rga_info *src1); + int RkRgaCollorFill(rga_info *dst); + + + void RkRgaSetLogOnceFlag(int log) {mLogOnce = log;} + void RkRgaSetAlwaysLogFlag(bool log) {mLogAlways = log;} + void RkRgaLogOutRgaReq(struct rga_req rgaReg); + int RkRgaLogOutUserPara(rga_info *rgaInfo); + inline bool RkRgaIsReady() { return mSupportRga; } + +/************************************private***********************************/ +private: + bool mSupportRga; + int mLogOnce; + int mLogAlways; + void * mContext; +}; + +// --------------------------------------------------------------------------- + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h new file mode 100644 index 0000000..3c1fff0 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/RockchipRgaMacro.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __ROCKCHIP_RGA_MACRO_H__ +#define __ROCKCHIP_RGA_MACRO_H__ + +/* flip source image horizontally (around the vertical axis) */ +#define HAL_TRANSFORM_FLIP_H 0x01 +/* flip source image vertically (around the horizontal axis)*/ +#define HAL_TRANSFORM_FLIP_V 0x02 +/* rotate source image 90 degrees clockwise */ +#define HAL_TRANSFORM_ROT_90 0x04 +/* rotate source image 180 degrees */ +#define HAL_TRANSFORM_ROT_180 0x03 +/* rotate source image 270 degrees clockwise */ +#define HAL_TRANSFORM_ROT_270 0x07 + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h new file mode 100644 index 0000000..abd8b97 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/drmrga.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co.Ltd + * Authors: + * Zhiqin Wei + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _rk_drm_rga_ +#define _rk_drm_rga_ + +#include +#include +#include "rga.h" +#include "RockchipRgaMacro.h" + +/*****************************************************************************/ + +/* for compatibility */ +#define DRM_RGA_MODULE_API_VERSION HWC_MODULE_API_VERSION_0_1 +#define DRM_RGA_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_1 +#define DRM_RGA_API_VERSION HWC_DEVICE_API_VERSION + +#define DRM_RGA_TRANSFORM_ROT_MASK 0x0000000F +#define DRM_RGA_TRANSFORM_ROT_0 0x00000000 +#define DRM_RGA_TRANSFORM_ROT_90 HAL_TRANSFORM_ROT_90 +#define DRM_RGA_TRANSFORM_ROT_180 HAL_TRANSFORM_ROT_180 +#define DRM_RGA_TRANSFORM_ROT_270 HAL_TRANSFORM_ROT_270 + +#define DRM_RGA_TRANSFORM_FLIP_MASK 0x00000003 +#define DRM_RGA_TRANSFORM_FLIP_H HAL_TRANSFORM_FLIP_H +#define DRM_RGA_TRANSFORM_FLIP_V HAL_TRANSFORM_FLIP_V + +enum { + AWIDTH = 0, + AHEIGHT, + ASTRIDE, + AFORMAT, + ASIZE, + ATYPE, +}; +/*****************************************************************************/ + + +typedef struct bo { + int fd; + void *ptr; + size_t size; + size_t offset; + size_t pitch; + unsigned handle; + }bo_t; + +/* + @value size: user not need care about.For avoid read/write out of memory + */ +typedef struct rga_rect { + int xoffset; + int yoffset; + int width; + int height; + int wstride; + int hstride; + int format; + int size; +} rga_rect_t; + +typedef struct rga_nn { + int nn_flag; + int scale_r; + int scale_g; + int scale_b; + int offset_r; + int offset_g; + int offset_b; +} rga_nn_t; + +typedef struct rga_dither { + int enable; + int mode; + int lut0_l; + int lut0_h; + int lut1_l; + int lut1_h; +} rga_dither_t; +/* + @value fd: use fd to share memory, it can be ion shard fd,and dma fd. + @value virAddr:userspace address + @value phyAddr:use phy address + @value hnd: use buffer_handle_t + */ +typedef struct rga_info { + int fd; + void *virAddr; + void *phyAddr; + unsigned hnd; + int format; + rga_rect_t rect; + unsigned int blend; + int bufferSize; + int rotation; + int color; + int testLog; + int mmuFlag; + int scale_mode; + rga_nn_t nn; + rga_dither_t dither; + int reserve[124]; +} rga_info_t; + + +typedef struct drm_rga { + rga_rect_t src; + rga_rect_t dst; +} drm_rga_t; + +/* + @fun rga_set_rect:For use to set the rects esayly + + @param rect:The rect user want to set,like setting the src rect: + drm_rga_t rects; + rga_set_rect(rects.src,0,0,1920,1080,1920,NV12); + mean to set the src rect to the value. + */ +static inline int rga_set_rect(rga_rect_t *rect, + int x, int y, int w, int h, int sw, int sh, int f) +{ + if (!rect) + return -EINVAL; + + rect->xoffset = x; + rect->yoffset = y; + rect->width = w; + rect->height = h; + rect->wstride = sw; + rect->hstride = sh; + rect->format = f; + + return 0; +} + +static inline void rga_set_rotation(rga_info_t *info, int angle) +{ + if (angle == 90) + info->rotation = HAL_TRANSFORM_ROT_90; + else if (angle == 180) + info->rotation = HAL_TRANSFORM_ROT_180; + else if (angle == 270) + info->rotation = HAL_TRANSFORM_ROT_270; +} +/*****************************************************************************/ + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h new file mode 100644 index 0000000..7737e7a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/rga/include/rga.h @@ -0,0 +1,752 @@ +#ifndef _RGA_DRIVER_H_ +#define _RGA_DRIVER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +#define RGA_BLIT_SYNC 0x5017 +#define RGA_BLIT_ASYNC 0x5018 +#define RGA_FLUSH 0x5019 +#define RGA_GET_RESULT 0x501a +#define RGA_GET_VERSION 0x501b + + +#define RGA_REG_CTRL_LEN 0x8 /* 8 */ +#define RGA_REG_CMD_LEN 0x1c /* 28 */ +#define RGA_CMD_BUF_SIZE 0x700 /* 16*28*4 */ + + + +#ifndef ENABLE +#define ENABLE 1 +#endif + + +#ifndef DISABLE +#define DISABLE 0 +#endif + + + +/* RGA process mode enum */ +enum +{ + bitblt_mode = 0x0, + color_palette_mode = 0x1, + color_fill_mode = 0x2, + line_point_drawing_mode = 0x3, + blur_sharp_filter_mode = 0x4, + pre_scaling_mode = 0x5, + update_palette_table_mode = 0x6, + update_patten_buff_mode = 0x7, +}; + + +enum +{ + rop_enable_mask = 0x2, + dither_enable_mask = 0x8, + fading_enable_mask = 0x10, + PD_enbale_mask = 0x20, +}; + +enum +{ + yuv2rgb_mode0 = 0x0, /* BT.601 MPEG */ + yuv2rgb_mode1 = 0x1, /* BT.601 JPEG */ + yuv2rgb_mode2 = 0x2, /* BT.709 */ +}; + + +/* RGA rotate mode */ +enum +{ + rotate_mode0 = 0x0, /* no rotate */ + rotate_mode1 = 0x1, /* rotate */ + rotate_mode2 = 0x2, /* x_mirror */ + rotate_mode3 = 0x3, /* y_mirror */ +}; + +enum +{ + color_palette_mode0 = 0x0, /* 1K */ + color_palette_mode1 = 0x1, /* 2K */ + color_palette_mode2 = 0x2, /* 4K */ + color_palette_mode3 = 0x3, /* 8K */ +}; + +enum +{ + BB_BYPASS = 0x0, /* no rotate */ + BB_ROTATE = 0x1, /* rotate */ + BB_X_MIRROR = 0x2, /* x_mirror */ + BB_Y_MIRROR = 0x3 /* y_mirror */ +}; + +enum +{ + nearby = 0x0, /* no rotate */ + bilinear = 0x1, /* rotate */ + bicubic = 0x2, /* x_mirror */ +}; + + + + + +/* +// Alpha Red Green Blue +{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // RK_FORMAT_RGBA_8888 +{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGBX_8888 +{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGB_888 +{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_BGRA }, // RK_FORMAT_BGRA_8888 +{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // RK_FORMAT_RGB_565 +{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // RK_FORMAT_RGBA_5551 +{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // RK_FORMAT_RGBA_4444 +{ 3, 24, {{ 0, 0, 24,16, 16, 8, 8, 0 }}, GGL_BGR }, // RK_FORMAT_BGB_888 + +*/ + +typedef enum _Rga_SURF_FORMAT +{ + RK_FORMAT_RGBA_8888 = 0x0, + RK_FORMAT_RGBX_8888 = 0x1, + RK_FORMAT_RGB_888 = 0x2, + RK_FORMAT_BGRA_8888 = 0x3, + RK_FORMAT_BGRX_8888 = 0x4, + RK_FORMAT_BGR_888 = 0x5, + RK_FORMAT_RGB_565 = 0x6, + RK_FORMAT_RGBA_5551 = 0x7, + RK_FORMAT_RGBA_4444 = 0x8, + RK_FORMAT_BGR_565 = 0x9, + RK_FORMAT_BGRA_5551 = 0xa, + RK_FORMAT_BGRA_4444 = 0xb, + + RK_FORMAT_Y4 = 0xe, + RK_FORMAT_YCbCr_400 = 0xf, + RK_FORMAT_YCbCr_422_SP = 0x10, + RK_FORMAT_YCbCr_422_P = 0x11, + RK_FORMAT_YCbCr_420_SP = 0x12, + RK_FORMAT_YCbCr_420_P = 0x13, + RK_FORMAT_YCrCb_422_SP = 0x14, + RK_FORMAT_YCrCb_422_P = 0x15, + RK_FORMAT_YCrCb_420_SP = 0x16, + RK_FORMAT_YCrCb_420_P = 0x17, + + RK_FORMAT_YVYU_422 = 0x18, + RK_FORMAT_YVYU_420 = 0x19, + RK_FORMAT_VYUY_422 = 0x1a, + RK_FORMAT_VYUY_420 = 0x1b, + RK_FORMAT_YUYV_422 = 0x1c, + RK_FORMAT_YUYV_420 = 0x1d, + RK_FORMAT_UYVY_422 = 0x1e, + RK_FORMAT_UYVY_420 = 0x1f, + + RK_FORMAT_YCbCr_422_10b_SP = 0x20, + RK_FORMAT_YCbCr_420_10b_SP = 0x21, + RK_FORMAT_YCrCb_422_10b_SP = 0x22, + RK_FORMAT_YCrCb_420_10b_SP = 0x23, + + RK_FORMAT_UNKNOWN = 0x100, +} RgaSURF_FORMAT; + +typedef struct rga_img_info_t +{ +#if defined(__arm64__) || defined(__aarch64__) + unsigned long yrgb_addr; /* yrgb mem addr */ + unsigned long uv_addr; /* cb/cr mem addr */ + unsigned long v_addr; /* cr mem addr */ +#else + unsigned int yrgb_addr; /* yrgb mem addr */ + unsigned int uv_addr; /* cb/cr mem addr */ + unsigned int v_addr; /* cr mem addr */ +#endif + unsigned int format; //definition by RK_FORMAT + unsigned short act_w; + unsigned short act_h; + unsigned short x_offset; + unsigned short y_offset; + + unsigned short vir_w; + unsigned short vir_h; + + unsigned short endian_mode; //for BPP + unsigned short alpha_swap; +} +rga_img_info_t; + + +typedef struct mdp_img_act +{ + unsigned short w; // width + unsigned short h; // height + short x_off; // x offset for the vir + short y_off; // y offset for the vir +} +mdp_img_act; + + + +typedef struct RANGE +{ + unsigned short min; + unsigned short max; +} +RANGE; + +typedef struct POINT_t +{ + unsigned short x; + unsigned short y; +} +POINT_t; + +typedef struct RECT_t +{ + unsigned short xmin; + unsigned short xmax; // width - 1 + unsigned short ymin; + unsigned short ymax; // height - 1 +} RECT_t; + +typedef struct RGT_t +{ + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char res; +}RGB_t; + + +typedef struct MMU +{ + unsigned char mmu_en; +#if defined(__arm64__) || defined(__aarch64__) + unsigned long base_addr; +#else + unsigned int base_addr; +#endif + unsigned int mmu_flag; /* [0] mmu enable [1] src_flush [2] dst_flush [3] CMD_flush [4~5] page size*/ +} MMU; + + + + +typedef struct COLOR_FILL +{ + short gr_x_a; + short gr_y_a; + short gr_x_b; + short gr_y_b; + short gr_x_g; + short gr_y_g; + short gr_x_r; + short gr_y_r; + + //u8 cp_gr_saturation; +} +COLOR_FILL; + +typedef struct FADING +{ + unsigned char b; + unsigned char g; + unsigned char r; + unsigned char res; +} +FADING; + + +typedef struct line_draw_t +{ + POINT_t start_point; /* LineDraw_start_point */ + POINT_t end_point; /* LineDraw_end_point */ + unsigned int color; /* LineDraw_color */ + unsigned int flag; /* (enum) LineDrawing mode sel */ + unsigned int line_width; /* range 1~16 */ +} +line_draw_t; + + + + struct rga_req { + unsigned char render_mode; /* (enum) process mode sel */ + + rga_img_info_t src; /* src image info */ + rga_img_info_t dst; /* dst image info */ + rga_img_info_t pat; /* patten image info */ + +#if defined(__arm64__) || defined(__aarch64__) + unsigned long rop_mask_addr; /* rop4 mask addr */ + unsigned long LUT_addr; /* LUT addr */ +#else + unsigned int rop_mask_addr; /* rop4 mask addr */ + unsigned int LUT_addr; /* LUT addr */ +#endif + + RECT_t clip; /* dst clip window default value is dst_vir */ + /* value from [0, w-1] / [0, h-1]*/ + + int sina; /* dst angle default value 0 16.16 scan from table */ + int cosa; /* dst angle default value 0 16.16 scan from table */ + + unsigned short alpha_rop_flag; /* alpha rop process flag */ + /* ([0] = 1 alpha_rop_enable) */ + /* ([1] = 1 rop enable) */ + /* ([2] = 1 fading_enable) */ + /* ([3] = 1 PD_enable) */ + /* ([4] = 1 alpha cal_mode_sel) */ + /* ([5] = 1 dither_enable) */ + /* ([6] = 1 gradient fill mode sel) */ + /* ([7] = 1 AA_enable) */ + + unsigned char scale_mode; /* 0 nearst / 1 bilnear / 2 bicubic */ + + unsigned int color_key_max; /* color key max */ + unsigned int color_key_min; /* color key min */ + + unsigned int fg_color; /* foreground color */ + unsigned int bg_color; /* background color */ + + COLOR_FILL gr_color; /* color fill use gradient */ + + line_draw_t line_draw_info; + + FADING fading; + + unsigned char PD_mode; /* porter duff alpha mode sel */ + + unsigned char alpha_global_value; /* global alpha value */ + + unsigned short rop_code; /* rop2/3/4 code scan from rop code table*/ + + unsigned char bsfilter_flag; /* [2] 0 blur 1 sharp / [1:0] filter_type*/ + + unsigned char palette_mode; /* (enum) color palatte 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/ + + unsigned char yuv2rgb_mode; /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */ + + unsigned char endian_mode; /* 0/big endian 1/little endian*/ + + unsigned char rotate_mode; /* (enum) rotate mode */ + /* 0x0, no rotate */ + /* 0x1, rotate */ + /* 0x2, x_mirror */ + /* 0x3, y_mirror */ + + unsigned char color_fill_mode; /* 0 solid color / 1 patten color */ + + MMU mmu_info; /* mmu information */ + + unsigned char alpha_rop_mode; /* ([0~1] alpha mode) */ + /* ([2~3] rop mode) */ + /* ([4] zero mode en) */ + /* ([5] dst alpha mode) */ + + unsigned char src_trans_mode; + + unsigned char dither_mode; + + unsigned char CMD_fin_int_enable; + + /* completion is reported through a callback */ + void (*complete)(int retval); +}; + +#if 0 +typedef struct TILE_INFO +{ + int64_t matrix[4]; + + uint16_t tile_x_num; /* x axis tile num / tile size is 8x8 pixel */ + uint16_t tile_y_num; /* y axis tile num */ + + int16_t dst_x_tmp; /* dst pos x = (xstart - xoff) default value 0 */ + int16_t dst_y_tmp; /* dst pos y = (ystart - yoff) default value 0 */ + + uint16_t tile_w; + uint16_t tile_h; + int16_t tile_start_x_coor; + int16_t tile_start_y_coor; + int32_t tile_xoff; + int32_t tile_yoff; + + int32_t tile_temp_xstart; + int32_t tile_temp_ystart; + + /* src tile incr */ + int32_t x_dx; + int32_t x_dy; + int32_t y_dx; + int32_t y_dy; + + mdp_img_act dst_ctrl; + +} +TILE_INFO; +#endif + +#if 0 + +#define RGA_BASE 0x10114000 + +//General Registers +#define RGA_SYS_CTRL 0x000 +#define RGA_CMD_CTRL 0x004 +#define RGA_CMD_ADDR 0x008 +#define RGA_STATUS 0x00c +#define RGA_INT 0x010 +#define RGA_AXI_ID 0x014 +#define RGA_MMU_STA_CTRL 0x018 +#define RGA_MMU_STA 0x01c + +//Command code start +#define RGA_MODE_CTRL 0x100 + +//Source Image Registers +#define RGA_SRC_Y_MST 0x104 +#define RGA_SRC_CB_MST 0x108 +#define RGA_MASK_READ_MST 0x108 //repeat +#define RGA_SRC_CR_MST 0x10c +#define RGA_SRC_VIR_INFO 0x110 +#define RGA_SRC_ACT_INFO 0x114 +#define RGA_SRC_X_PARA 0x118 +#define RGA_SRC_Y_PARA 0x11c +#define RGA_SRC_TILE_XINFO 0x120 +#define RGA_SRC_TILE_YINFO 0x124 +#define RGA_SRC_TILE_H_INCR 0x128 +#define RGA_SRC_TILE_V_INCR 0x12c +#define RGA_SRC_TILE_OFFSETX 0x130 +#define RGA_SRC_TILE_OFFSETY 0x134 +#define RGA_SRC_BG_COLOR 0x138 +#define RGA_SRC_FG_COLOR 0x13c +#define RGA_LINE_DRAWING_COLOR 0x13c //repeat +#define RGA_SRC_TR_COLOR0 0x140 +#define RGA_CP_GR_A 0x140 //repeat +#define RGA_SRC_TR_COLOR1 0x144 +#define RGA_CP_GR_B 0x144 //repeat + +#define RGA_LINE_DRAW 0x148 +#define RGA_PAT_START_POINT 0x148 //repeat + +//Destination Image Registers +#define RGA_DST_MST 0x14c +#define RGA_LUT_MST 0x14c //repeat +#define RGA_PAT_MST 0x14c //repeat +#define RGA_LINE_DRAWING_MST 0x14c //repeat + +#define RGA_DST_VIR_INFO 0x150 + +#define RGA_DST_CTR_INFO 0x154 +#define RGA_LINE_DRAW_XY_INFO 0x154 //repeat + +//Alpha/ROP Registers +#define RGA_ALPHA_CON 0x158 + +#define RGA_PAT_CON 0x15c +#define RGA_DST_VIR_WIDTH_PIX 0x15c //repeat + +#define RGA_ROP_CON0 0x160 +#define RGA_CP_GR_G 0x160 //repeat +#define RGA_PRESCL_CB_MST 0x160 //repeat + +#define RGA_ROP_CON1 0x164 +#define RGA_CP_GR_R 0x164 //repeat +#define RGA_PRESCL_CR_MST 0x164 //repeat + +//MMU Register +#define RGA_FADING_CON 0x168 +#define RGA_MMU_CTRL 0x168 //repeat + +#define RGA_MMU_TBL 0x16c //repeat + + +#define RGA_BLIT_COMPLETE_EVENT 1 + +#endif + +int +RGA_set_src_act_info( + struct rga_req *req, + unsigned int width, /* act width */ + unsigned int height, /* act height */ + unsigned int x_off, /* x_off */ + unsigned int y_off /* y_off */ + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_src_vir_info( + struct rga_req *req, + unsigned long yrgb_addr, /* yrgb_addr */ + unsigned long uv_addr, /* uv_addr */ + unsigned long v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + unsigned char format, /* format */ + unsigned char a_swap_en /* only for 32bit RGB888 format */ + ); +#else +int +RGA_set_src_vir_info( + struct rga_req *req, + unsigned int yrgb_addr, /* yrgb_addr */ + unsigned int uv_addr, /* uv_addr */ + unsigned int v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + unsigned char format, /* format */ + unsigned char a_swap_en /* only for 32bit RGB888 format */ + ); +#endif + +int +RGA_set_dst_act_info( + struct rga_req *req, + unsigned int width, /* act width */ + unsigned int height, /* act height */ + unsigned int x_off, /* x_off */ + unsigned int y_off /* y_off */ + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_dst_vir_info( + struct rga_req *msg, + unsigned long yrgb_addr, /* yrgb_addr */ + unsigned long uv_addr, /* uv_addr */ + unsigned long v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + RECT_t *clip, /* clip window */ + unsigned char format, /* format */ + unsigned char a_swap_en + ); +#else +int +RGA_set_dst_vir_info( + struct rga_req *msg, + unsigned int yrgb_addr, /* yrgb_addr */ + unsigned int uv_addr, /* uv_addr */ + unsigned int v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + RECT_t *clip, /* clip window */ + unsigned char format, /* format */ + unsigned char a_swap_en + ); +#endif + +int +RGA_set_pat_info( + struct rga_req *msg, + unsigned int width, + unsigned int height, + unsigned int x_off, + unsigned int y_off, + unsigned int pat_format + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_rop_mask_info( + struct rga_req *msg, + unsigned long rop_mask_addr, + unsigned int rop_mask_endian_mode + ); +#else +int +RGA_set_rop_mask_info( + struct rga_req *msg, + unsigned int rop_mask_addr, + unsigned int rop_mask_endian_mode + ); +#endif + +int RGA_set_alpha_en_info( + struct rga_req *msg, + unsigned int alpha_cal_mode, /* 0:alpha' = alpha + (alpha>>7) | alpha' = alpha */ + unsigned int alpha_mode, /* 0 global alpha / 1 per pixel alpha / 2 mix mode */ + unsigned int global_a_value, + unsigned int PD_en, /* porter duff alpha mode en */ + unsigned int PD_mode, + unsigned int dst_alpha_en ); /* use dst alpha */ + +int +RGA_set_rop_en_info( + struct rga_req *msg, + unsigned int ROP_mode, + unsigned int ROP_code, + unsigned int color_mode, + unsigned int solid_color + ); + + +int +RGA_set_fading_en_info( + struct rga_req *msg, + unsigned char r, + unsigned char g, + unsigned char b + ); + +int +RGA_set_src_trans_mode_info( + struct rga_req *msg, + unsigned char trans_mode, + unsigned char a_en, + unsigned char b_en, + unsigned char g_en, + unsigned char r_en, + unsigned char color_key_min, + unsigned char color_key_max, + unsigned char zero_mode_en + ); + + +int +RGA_set_bitblt_mode( + struct rga_req *msg, + unsigned char scale_mode, // 0/near 1/bilnear 2/bicubic + unsigned char rotate_mode, // 0/copy 1/rotate_scale 2/x_mirror 3/y_mirror + unsigned int angle, // rotate angle + unsigned int dither_en, // dither en flag + unsigned int AA_en, // AA flag + unsigned int yuv2rgb_mode + ); + + +int +RGA_set_color_palette_mode( + struct rga_req *msg, + unsigned char palette_mode, /* 1bpp/2bpp/4bpp/8bpp */ + unsigned char endian_mode, /* src endian mode sel */ + unsigned int bpp1_0_color, /* BPP1 = 0 */ + unsigned int bpp1_1_color /* BPP1 = 1 */ + ); + + +int +RGA_set_color_fill_mode( + struct rga_req *msg, + COLOR_FILL *gr_color, /* gradient color part */ + unsigned char gr_satur_mode, /* saturation mode */ + unsigned char cf_mode, /* patten fill or solid fill */ + unsigned int color, /* solid color */ + unsigned short pat_width, /* pattern width */ + unsigned short pat_height, /* pattern height */ + unsigned char pat_x_off, /* pattern x offset */ + unsigned char pat_y_off, /* pattern y offset */ + unsigned char aa_en /* alpha en */ + ); + + +int +RGA_set_line_point_drawing_mode( + struct rga_req *msg, + POINT_t sp, /* start point */ + POINT_t ep, /* end point */ + unsigned int color, /* line point drawing color */ + unsigned int line_width, /* line width */ + unsigned char AA_en, /* AA en */ + unsigned char last_point_en /* last point en */ + ); + + +int +RGA_set_blur_sharp_filter_mode( + struct rga_req *msg, + unsigned char filter_mode, /* blur/sharpness */ + unsigned char filter_type, /* filter intensity */ + unsigned char dither_en /* dither_en flag */ + ); + +int +RGA_set_pre_scaling_mode( + struct rga_req *msg, + unsigned char dither_en + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_update_palette_table_mode( + struct rga_req *msg, + unsigned long LUT_addr, /* LUT table addr */ + unsigned int palette_mode /* 1bpp/2bpp/4bpp/8bpp */ + ); +#else +int +RGA_update_palette_table_mode( + struct rga_req *msg, + unsigned int LUT_addr, /* LUT table addr */ + unsigned int palette_mode /* 1bpp/2bpp/4bpp/8bpp */ + ); +#endif + +int +RGA_set_update_patten_buff_mode( + struct rga_req *msg, + unsigned int pat_addr, /* patten addr */ + unsigned int w, /* patten width */ + unsigned int h, /* patten height */ + unsigned int format /* patten format */ + ); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_mmu_info( + struct rga_req *msg, + unsigned char mmu_en, + unsigned char src_flush, + unsigned char dst_flush, + unsigned char cmd_flush, + unsigned long base_addr, + unsigned char page_size + ); +#else +int +RGA_set_mmu_info( + struct rga_req *msg, + unsigned char mmu_en, + unsigned char src_flush, + unsigned char dst_flush, + unsigned char cmd_flush, + unsigned int base_addr, + unsigned char page_size + ); +#endif + +void rga_set_fds_offsets( + struct rga_req *rga_request, + unsigned short src_fd, + unsigned short dst_fd, + unsigned int src_offset, + unsigned int dst_offset); + +int +RGA_set_src_fence_flag( + struct rga_req *msg, + int acq_fence, + int src_flag +); + + +int +RGA_set_dst_fence_flag( + struct rga_req *msg, + int dst_flag +); + +int +RGA_get_dst_fence( + struct rga_req *msg +); +#ifdef __cplusplus +} +#endif + +#endif /*_RK29_IPP_DRIVER_H_*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image.h new file mode 100644 index 0000000..196dfd5 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image.h @@ -0,0 +1,7559 @@ +/* stb_image - v2.23 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt JR Smith github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image_resize.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image_resize.h new file mode 100644 index 0000000..4f6ad35 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image_resize.h @@ -0,0 +1,2630 @@ +/* stb_image_resize - v0.96 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image_write.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image_write.h new file mode 100644 index 0000000..c117344 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/3rdparty/stb/stb_image_write.h @@ -0,0 +1,1619 @@ +/* stb_image_write - v1.13 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. + +USAGE: + + There are five functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +extern int stbi_write_tga_with_rle; +extern int stbi_write_png_compression_level; +extern int stbi_write_force_png_filter; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBI_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi__flip_vertically_on_write=0; +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi__flip_vertically_on_write=0; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + +typedef struct +{ + stbi_write_func *func; + void *context; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a; arr[1] = b; arr[2] = c; + s->func(s->context, arr, 3); +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + s->func(s->context, &d[comp - 1], 1); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + s->func(s->context, d, 1); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + s->func(s->context, &d[comp - 1], 1); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + s->func(s->context, &header, 1); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + s->func(s->context, &header, 1); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +#ifdef __STDC_WANT_SECURE_LIB__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else + len = snprintf(buffer, 128, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +#endif +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + const unsigned char *imageData = (const unsigned char *)data; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + int x, y, pos; + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float YDU[64], UDU[64], VDU[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + float r, g, b; + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + + r = imageData[p+0]; + g = imageData[p+ofsG]; + b = imageData[p+ofsB]; + YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128; + UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b; + VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/CMakeLists.txt new file mode 100644 index 0000000..b3b9339 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_batch_inference_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +# utils +include_directories(${CMAKE_SOURCE_DIR}/src/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_batch_inference_demo + src/main.cc +) + +target_link_libraries(rknn_batch_inference_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_batch_inference_demo) +install(TARGETS rknn_batch_inference_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/README.md new file mode 100644 index 0000000..4a4f668 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_batch_inference_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_batch_inference_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_batch_inference_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/build.sh new file mode 100644 index 0000000..70781f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_batch_inference_demo/ +cp run_rv1109_rv1126.sh install/rknn_batch_inference_demo/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rk180x/mobilenet_v1_rk1808_batch_4.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rk180x/mobilenet_v1_rk1808_batch_4.rknn new file mode 100644 index 0000000..a0f9b4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rk180x/mobilenet_v1_rk1808_batch_4.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rv1109_rv1126/mobilenet_v1_rv1109_rv1126_batch_4.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rv1109_rv1126/mobilenet_v1_rv1109_rv1126_batch_4.rknn new file mode 100644 index 0000000..8103d58 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/model/rv1109_rv1126/mobilenet_v1_rv1109_rv1126_batch_4.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rk180x.sh new file mode 100644 index 0000000..2ff2d2a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rk180x.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rk180x" +./rknn_batch_inference_demo model/${chip_dir}/mobilenet_v1_rk1808_batch_4.rknn model/dog_224x224.jpg \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..efac954 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/run_rv1109_rv1126.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +./rknn_batch_inference_demo model/${chip_dir}/mobilenet_v1_rv1109_rv1126_batch_4.rknn model/dog_224x224.jpg \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/src/main.cc new file mode 100644 index 0000000..6cd5a6b --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_batch_inference_demo/src/main.cc @@ -0,0 +1,330 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "rknn_api.h" + +using namespace std; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static int rknn_GetTop( + float *pfProb, + float *pfMaxProb, + uint32_t *pMaxClass, + uint32_t outputCount, + uint32_t topNum) +{ + uint32_t i, j; + +#define MAX_TOP_NUM 20 + if (topNum > MAX_TOP_NUM) + return 0; + + memset(pfMaxProb, 0, sizeof(float) * topNum); + memset(pMaxClass, 0xff, sizeof(float) * topNum); + + for (j = 0; j < topNum; j++) + { + for (i = 0; i < outputCount; i++) + { + if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || + (i == *(pMaxClass + 3)) || (i == *(pMaxClass + 4))) + { + continue; + } + + if (pfProb[i] > *(pfMaxProb + j)) + { + *(pfMaxProb + j) = pfProb[i]; + *(pMaxClass + j) = i; + } + } + } + + return 1; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + const int MODEL_IN_WIDTH = 224; + const int MODEL_IN_HEIGHT = 224; + const int MODEL_IN_CHANNELS = 3; + const int MODEL_IN_BATCHSIZE = 4; + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + + // Load RKNN Model + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image + unsigned char *input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) + { + return -1; + } + + //concat img to batch + int img_size = input_attrs[0].dims[0] * input_attrs[0].dims[1] * input_attrs[0].dims[2] * sizeof(uint8_t); + unsigned char *in_data_batch = NULL; + in_data_batch = (unsigned char *)malloc(MODEL_IN_BATCHSIZE * img_size); + if (!in_data_batch) + { + return -1; + } + for (int i = 0; i < MODEL_IN_BATCHSIZE; ++i) + { + unsigned char *in_data_ptr = in_data_batch + img_size * i; + memcpy(in_data_ptr, input_data, img_size); + } + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = in_data_batch; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + for (int n = 0; n < MODEL_IN_BATCHSIZE; ++n) + { + for (int i = 0; i < io_num.n_output; i++) + { + uint32_t MaxClass[5]; + float fMaxProb[5]; + float *buffer_f32 = (float *)outputs[i].buf; + float *cur_batch_buf = buffer_f32 + 1001 * n; + uint32_t cur_batch_sz = outputs[i].size / (4 * MODEL_IN_BATCHSIZE); + rknn_GetTop(cur_batch_buf, fMaxProb, MaxClass, cur_batch_sz, 5); + + printf(" --- Top5 ---\n"); + for (int i = 0; i < 5; i++) + { + printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); + } + } + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + if (input_data) + { + free(input_data); + } + if (in_data_batch) + { + stbi_image_free(in_data_batch); + } + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/CMakeLists.txt new file mode 100644 index 0000000..c2d48ec --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_mobilenet_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_mobilenet_demo + src/main.cc +) + +target_link_libraries(rknn_mobilenet_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_mobilenet_demo) +install(TARGETS rknn_mobilenet_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/README.md new file mode 100644 index 0000000..7a302a2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_mobilenet_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_mobilenet_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_mobilenet_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/build.sh new file mode 100644 index 0000000..c869f2a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/build.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +# GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/cat_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/cat_224x224.jpg new file mode 100644 index 0000000..11c5ba4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/cat_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rk180x.rknn new file mode 100644 index 0000000..b02f728 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rv1109_rv1126.rknn new file mode 100644 index 0000000..b0f6735 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/model/mobilenet_v1_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/src/main.cc new file mode 100644 index 0000000..b0f7de2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_mobilenet_demo/src/main.cc @@ -0,0 +1,327 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "rknn_api.h" + +using namespace std; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static inline int64_t getCurrentTimeUs() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static int rknn_GetTop( + float *pfProb, + float *pfMaxProb, + uint32_t *pMaxClass, + uint32_t outputCount, + uint32_t topNum) +{ + uint32_t i, j; + +#define MAX_TOP_NUM 20 + if (topNum > MAX_TOP_NUM) + return 0; + + memset(pfMaxProb, 0, sizeof(float) * topNum); + memset(pMaxClass, 0xff, sizeof(float) * topNum); + + for (j = 0; j < topNum; j++) + { + for (i = 0; i < outputCount; i++) + { + if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || + (i == *(pMaxClass + 3)) || (i == *(pMaxClass + 4))) + { + continue; + } + + if (pfProb[i] > *(pfMaxProb + j)) + { + *(pfMaxProb + j) = pfProb[i]; + *(pMaxClass + j) = i; + } + } + } + + return 1; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + int loop_count = 1; + if (argc > 3) + { + loop_count = atoi(argv[3]); + } + + // Load RKNN Model + model = load_model(model_path, &model_len); + + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image + unsigned char *input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) + { + return -1; + } + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = input_data; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + for (int n = 0; n < loop_count; ++n) + { + int64_t start_us = getCurrentTimeUs(); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + int64_t elapse_us = getCurrentTimeUs() - start_us; + printf("%4d: Elapse Time = %.2fms, FPS = %.2f\n", n, elapse_us / 1000.f, 1000.f * 1000.f / elapse_us); + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + for (int i = 0; i < io_num.n_output; i++) + { + uint32_t MaxClass[5]; + float fMaxProb[5]; + float *buffer = (float *)outputs[i].buf; + uint32_t sz = outputs[i].size / 4; + + rknn_GetTop(buffer, fMaxProb, MaxClass, sz, 5); + + printf(" --- Top5 ---\n"); + for (int i = 0; i < 5; i++) + { + printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); + } + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + + if (input_data) + { + stbi_image_free(input_data); + } + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/CMakeLists.txt new file mode 100644 index 0000000..3326955 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_multi_input_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +# utils +include_directories(${CMAKE_SOURCE_DIR}/src/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_multi_input_demo + src/main.cc +) + +target_link_libraries(rknn_multi_input_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_multi_input_demo) +install(TARGETS rknn_multi_input_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/README.md new file mode 100644 index 0000000..6782968 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_multi_input_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_multi_input_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_multi_input_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/build.sh new file mode 100644 index 0000000..cbcd900 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_multi_input_demo/ +cp run_rv1109_rv1126.sh install/rknn_multi_input_demo/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/dog_128x128_gray.png b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/dog_128x128_gray.png new file mode 100644 index 0000000..3b3c325 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/dog_128x128_gray.png differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/rk180x/multi_input_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/rk180x/multi_input_rk180x.rknn new file mode 100644 index 0000000..c3c5921 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/rk180x/multi_input_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/rv1109_rv1126/multi_input_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/rv1109_rv1126/multi_input_rv1109_rv1126.rknn new file mode 100644 index 0000000..4232100 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/model/rv1109_rv1126/multi_input_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/run_rk180x.sh new file mode 100644 index 0000000..1f61582 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/run_rk180x.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rk180x" +./rknn_multi_input_demo model/${chip_dir}/multi_input_rk180x.rknn model/dog_128x128_gray.png \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..4b364fd --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/run_rv1109_rv1126.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +./rknn_multi_input_demo model/${chip_dir}/multi_input_rv1109_rv1126.rknn model/dog_128x128_gray.png \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/src/main.cc new file mode 100644 index 0000000..1c26d20 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_multi_input_demo/src/main.cc @@ -0,0 +1,284 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "rknn_api.h" + +using namespace std; + +#define DEMO_INPUT_NUM 4 + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + const int MODEL_IN_WIDTH = 128; + const int MODEL_IN_HEIGHT = 128; + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + + // Load RKNN Model + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + assert(DEMO_INPUT_NUM == io_num.n_input); + // Set Input struct + rknn_input inputs[DEMO_INPUT_NUM]; + memset(inputs, 0, DEMO_INPUT_NUM * sizeof(rknn_input)); + std::vector imgs; + for (int i = 0; i < io_num.n_input; ++i) + { + int channel = 0; + if (input_attrs[i].fmt == RKNN_TENSOR_NCHW) + { + channel = input_attrs[i].dims[2]; + } + else + { + channel = input_attrs[i].dims[0]; + } + //convert single channel to multi channels + // Load image + unsigned char *input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) + { + return -1; + } + imgs.push_back(input_data); + int img_size = input_attrs[0].size; + inputs[i].index = i; + inputs[i].type = RKNN_TENSOR_UINT8; + inputs[i].size = img_size; + inputs[i].fmt = RKNN_TENSOR_NHWC; + } + for (int i = 0; i < io_num.n_input; ++i) + { + inputs[i].buf = imgs[i]; + } + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + float ref_data[5] = {24.482, 20.453, 20.453, 20.453, 20.453}; + float *buffer = (float *)outputs[0].buf; + printf("first 5 result:\n"); + for (int i = 0; i < 5; ++i) + { + printf("[%d]:%.3f vs %.3f\n", i, buffer[i], ref_data[i]); + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + for (auto d : imgs) + { + stbi_image_free(d); + } + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/CMakeLists.txt new file mode 100644 index 0000000..1cf20d4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_pass_through_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "64bit") + set(LIB_ARCH lib64) +else() + message(STATUS "32bit") + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +# utils +include_directories(${CMAKE_SOURCE_DIR}/src/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_pass_through_demo + src/main.cc + src/quant_utils.cc +) + +target_link_libraries(rknn_pass_through_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_pass_through_demo) +install(TARGETS rknn_pass_through_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/README.md new file mode 100644 index 0000000..80d9556 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/README.md @@ -0,0 +1,38 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_pass_through_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_pass_through_demo /userdata/ +``` + +If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +``` +adb shell +cd /userdata/rknn_pass_through_demo/ +``` + +- RK1808/RK1806 +``` +./run_rk180x.sh int8 +``` + +- RV1109/RV1126 +``` +./run_rv1109_rv1126.sh int8 +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/build.sh new file mode 100644 index 0000000..b39e372 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_pass_through_demo/ +cp run_rv1109_rv1126.sh install/rknn_pass_through_demo/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/cat_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/cat_224x224.jpg new file mode 100644 index 0000000..11c5ba4 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/cat_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/dog_224x224.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/dog_224x224.jpg new file mode 100644 index 0000000..4f46457 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/dog_224x224.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_FP_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_FP_rk180x.rknn new file mode 100644 index 0000000..a6c328a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_FP_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT16_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT16_rk180x.rknn new file mode 100644 index 0000000..61dc82d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT16_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT8_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT8_rk180x.rknn new file mode 100644 index 0000000..b622a8e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_INT8_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_UINT8_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_UINT8_rk180x.rknn new file mode 100644 index 0000000..c86d218 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rk180x/mobilenet_v2_UINT8_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_FP_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_FP_rv1109_rv1126.rknn new file mode 100644 index 0000000..651fcac Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_FP_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT16_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT16_rv1109_rv1126.rknn new file mode 100644 index 0000000..46b5aaf Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT16_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT8_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT8_rv1109_rv1126.rknn new file mode 100644 index 0000000..eed99da Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_INT8_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_UINT8_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_UINT8_rv1109_rv1126.rknn new file mode 100644 index 0000000..3308572 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/model/rv1109_rv1126/mobilenet_v2_UINT8_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/run_rk180x.sh new file mode 100644 index 0000000..ffb9880 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/run_rk180x.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +chip_dir="rk180x" +case $1 in + uint8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_UINT8_rk180x.rknn model/dog_224x224.jpg + ;; + int8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT8_rk180x.rknn model/dog_224x224.jpg + ;; + int16) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT16_rk180x.rknn model/dog_224x224.jpg + ;; + fp) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_FP_rk180x.rknn model/dog_224x224.jpg + ;; + *) + echo './run.sh uint8 int8 int16 fp' + ;; +esac + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..4f7166e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/run_rv1109_rv1126.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +case $1 in + uint8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_UINT8_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + int8) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT8_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + int16) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_INT16_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + fp) + ./rknn_pass_through_demo model/${chip_dir}/mobilenet_v2_FP_rv1109_rv1126.rknn model/dog_224x224.jpg + ;; + *) + echo './run.sh uint8 int8 int16 fp' + ;; +esac + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/main.cc new file mode 100644 index 0000000..59108c4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/main.cc @@ -0,0 +1,484 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#include "quant_utils.h" +#include "rknn_api.h" + +using namespace std; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d " + "fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], + attr->dims[1], attr->dims[0], attr->n_elems, attr->size, 0, attr->type, + attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + FILE *fp = fopen(filename, "rb"); + if (fp == nullptr) + { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char *model = (unsigned char *)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) + { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) + { + fclose(fp); + } + return model; +} + +static int GetElementByte(rknn_tensor_attr *in_attr) +{ + int byte = 0; + switch (in_attr->type) + { + case RKNN_TENSOR_FLOAT32: + byte = 4; + break; + case RKNN_TENSOR_FLOAT16: + case RKNN_TENSOR_INT16: + byte = 2; + break; + case RKNN_TENSOR_INT8: + case RKNN_TENSOR_UINT8: + byte = 1; + break; + default: + break; + } + return byte; +} + +static unsigned char *load_image(const char *image_path, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) + { + unsigned char *image_resized = (unsigned char *)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) + { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) + { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +static int ProcessInput(unsigned char *src_buf, void **dst_buf, rknn_tensor_attr *in_attr, + std::vector mean, std::vector scale, + bool isReorder210, bool isNCHW) +{ + // check + if (3 != mean.size() || src_buf == NULL) + { + return -1; + } + int img_height, img_width, img_channels = 0; + if (isNCHW) + { + img_width = in_attr->dims[0]; + img_height = in_attr->dims[1]; + img_channels = in_attr->dims[2]; + } + else + { + img_channels = in_attr->dims[0]; + img_width = in_attr->dims[1]; + img_height = in_attr->dims[2]; + } + int HW = img_height * img_width; + int ele_count = HW * img_channels; + int ele_bytes = GetElementByte(in_attr); + printf("total element count = %d, bytes per element = %d\n", ele_count, + ele_bytes); + float *pixel_f = (float *)malloc(ele_count * sizeof(float)); + + // RGB2BGR + if (isReorder210 == true) + { + printf("perform RGB2BGR\n"); + float *f_ptr = pixel_f; + unsigned char *u_ptr = src_buf; + for (int i = 0; i < HW; ++i) + { + f_ptr[2] = u_ptr[0]; + f_ptr[1] = u_ptr[1]; + f_ptr[0] = u_ptr[2]; + u_ptr += img_channels; + f_ptr += img_channels; + } + } + else + { + float *f_ptr = pixel_f; + unsigned char *u_ptr = src_buf; + for (int i = 0; i < ele_count; ++i) + { + f_ptr[i] = u_ptr[i]; + } + } + + // normalize + printf("perform normalize\n"); + float *f_ptr = pixel_f; + for (int i = 0; i < HW; ++i) + { + for (int j = 0; j < img_channels; ++j) + { + f_ptr[j] -= mean[j]; + f_ptr[j] /= scale[j]; + } + f_ptr += img_channels; + } + + // quantize + printf("perform quantize\n"); + uint8_t *qnt_buf = (uint8_t *)malloc(ele_count * ele_bytes); + switch (in_attr->type) + { + case RKNN_TENSOR_FLOAT32: + memcpy(qnt_buf, pixel_f, ele_count * ele_bytes); + break; + case RKNN_TENSOR_FLOAT16: + f32_to_f16((uint16_t *)(qnt_buf), pixel_f, ele_count); + break; + case RKNN_TENSOR_INT16: + case RKNN_TENSOR_INT8: + case RKNN_TENSOR_UINT8: + switch (in_attr->qnt_type) + { + case RKNN_TENSOR_QNT_DFP: + qnt_f32_to_dfp(qnt_buf, in_attr->type, in_attr->fl, pixel_f, ele_count); + break; + case RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + qnt_f32_to_affine(qnt_buf, in_attr->type, in_attr->zp, in_attr->scale, pixel_f, ele_count); + break; + case RKNN_TENSOR_QNT_NONE: + qnt_f32_to_none(qnt_buf, in_attr->type, pixel_f, ele_count); + default: + break; + } + break; + default: + break; + } + + // NHWC ==> NCHW + if (isNCHW) + { + printf("perform NHWC to NCHW\n"); + uint8_t *nchw_buf = (uint8_t *)malloc(ele_count * ele_bytes); + uint8_t *dst_ptr = nchw_buf; + uint8_t *src_ptr = qnt_buf; + for (int i = 0; i < img_channels; ++i) + { + src_ptr = qnt_buf + i * ele_bytes; + dst_ptr = nchw_buf + i * HW * ele_bytes; + for (int j = 0; j < HW; ++j) + { + // dst_ptr[i*HW+j] = src_ptr[j*C+i]; + memcpy(dst_ptr, src_ptr, ele_bytes); + src_ptr += img_channels * ele_bytes; + dst_ptr += ele_bytes; + } + } + *dst_buf = nchw_buf; + free(qnt_buf); + } + else + { + *dst_buf = qnt_buf; + } + + free(pixel_f); + + return 0; +} + +static int rknn_GetTop( + float *pfProb, + float *pfMaxProb, + uint32_t *pMaxClass, + uint32_t outputCount, + uint32_t topNum) +{ + uint32_t i, j; + +#define MAX_TOP_NUM 20 + if (topNum > MAX_TOP_NUM) + return 0; + + memset(pfMaxProb, 0, sizeof(float) * topNum); + memset(pMaxClass, 0xff, sizeof(float) * topNum); + + for (j = 0; j < topNum; j++) + { + for (i = 0; i < outputCount; i++) + { + if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || + (i == *(pMaxClass + 3)) || (i == *(pMaxClass + 4))) + { + continue; + } + + if (pfProb[i] > *(pfMaxProb + j)) + { + *(pfMaxProb + j) = pfProb[i]; + *(pMaxClass + j) = i; + } + } + } + + return 1; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char **argv) +{ + const int MODEL_IN_WIDTH = 224; + const int MODEL_IN_HEIGHT = 224; + const int MODEL_IN_CHANNELS = 3; + bool isNCHW = false; + // mobilenet v2 mean/scale in rknn.config() + bool isReorder210 = true; /* reorder= '2 1 0' */ + std::vector mean({103.94, 116.78, 123.68}); + std::vector scale({58.82, 58.82, 58.82}); + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char *model; + + const char *model_path = argv[1]; + const char *img_path = argv[2]; + + // Load RKNN Model + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) + { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, + io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) + { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image + unsigned char *img_data = NULL; + img_data = load_image(img_path, &input_attrs[0]); + if (!img_data) + { + return -1; + } + + // rknn model need nchw layout input + if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) + { + isNCHW = true; + } + + // process input when pass_through = 1 + void *in_data = NULL; + ProcessInput(img_data, &in_data, &(input_attrs[0]), mean, scale, isReorder210, + isNCHW); + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NCHW; + inputs[0].buf = in_data; + inputs[0].pass_through = 1; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) + { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) + { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[1]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + ret = rknn_outputs_get(ctx, 1, outputs, NULL); + if (ret < 0) + { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + for (int i = 0; i < io_num.n_output; i++) + { + uint32_t MaxClass[5]; + float fMaxProb[5]; + float *buffer = (float *)outputs[i].buf; + uint32_t sz = outputs[i].size / 4; + + rknn_GetTop(buffer, fMaxProb, MaxClass, sz, 5); + + printf(" --- Top5 ---\n"); + for (int i = 0; i < 5; i++) + { + printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); + } + } + + // Release rknn_outputs + rknn_outputs_release(ctx, 1, outputs); + + // Release + if (ctx >= 0) + { + rknn_destroy(ctx); + } + if (model) + { + free(model); + } + stbi_image_free(img_data); + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.cc new file mode 100644 index 0000000..d59e11c --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.cc @@ -0,0 +1,181 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "quant_utils.h" +#include "rknn_api.h" + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + // return (int32_t)((f > 0.0) ? (f + 0.5) : (f - 0.5)); //四舍五入 + return f; +} + +void f32_to_f16(uint16_t *f16, float *f32, int num) +{ + float *src = f32; + uint16_t *dst = f16; + int i = 0; + + for (; i < num; i++) + { + float in = *src; + + uint32_t fp32 = *((uint32_t *)&in); + uint32_t t1 = (fp32 & 0x80000000u) >> 16; /* sign bit. */ + uint32_t t2 = (fp32 & 0x7F800000u) >> 13; /* Exponent bits */ + uint32_t t3 = (fp32 & 0x007FE000u) >> 13; /* Mantissa bits, no rounding */ + uint32_t fp16 = 0u; + + if (t2 >= 0x023c00u) + { + fp16 = t1 | 0x7BFF; /* Don't round to infinity. */ + } + else if (t2 <= 0x01c000u) + { + fp16 = t1; + } + else + { + t2 -= 0x01c000u; + fp16 = t1 | t2 | t3; + } + + *dst = (uint16_t)fp16; + + src++; + dst++; + } +} + +void qnt_f32_to_dfp(uint8_t *qnt, uint8_t type, int8_t fl, float *f32, + int num) +{ + float *src_ptr = f32; + int i = 0; + float dst_val = 0.0; + + switch (type) + { + case RKNN_TENSOR_INT8: + for (; i < num; i++) + { + dst_val = (fl > 0) ? ((*src_ptr) * ((float)(1 << fl))) + : ((*src_ptr) / (float)(1 << -fl)); + *((int8_t *)qnt) = (int8_t)__clip(dst_val, -128, 127); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_UINT8: + for (; i < num; i++) + { + dst_val = (fl > 0) ? ((*src_ptr) * ((float)(1 << fl))) + : ((*src_ptr) / (float)(1 << -fl)); + *qnt = (uint8_t)__clip(dst_val, 0, 255); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_INT16: + for (; i < num; i++) + { + dst_val = (fl > 0) ? ((*src_ptr) * ((float)(1 << fl))) + : ((*src_ptr) / (float)(1 << -fl)); + *((int16_t *)qnt) = (int16_t)__clip(dst_val, -32768, 32767); + src_ptr++; + qnt += 2; + } + break; + default: + break; + } +} + +void qnt_f32_to_affine(uint8_t *qnt, uint8_t type, uint8_t zp, float scale, + float *f32, int num) +{ + float *src_ptr = f32; + int i = 0; + float dst_val = 0.0; + + switch (type) + { + case RKNN_TENSOR_INT8: + for (; i < num; i++) + { + dst_val = ((*src_ptr) / scale) + zp; + *((int8_t *)qnt) = (int8_t)__clip(dst_val, -128, 127); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_UINT8: + for (; i < num; i++) + { + dst_val = ((*src_ptr) / scale) + zp; + *qnt = (uint8_t)__clip(dst_val, 0, 255); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_INT16: + for (; i < num; i++) + { + dst_val = ((*src_ptr) / scale) + zp; + *((int16_t *)qnt) = (int16_t)__clip(dst_val, -32768, 32767); + src_ptr++; + qnt += 2; + } + break; + default: + break; + } +} + +void qnt_f32_to_none(uint8_t *qnt, uint8_t type, float *f32, int num) +{ + float *src_ptr = f32; + int i = 0; + + switch (type) + { + case RKNN_TENSOR_INT8: + for (; i < num; i++) + { + *((int8_t *)qnt) = (int8_t)__clip(*src_ptr, -128, 127); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_UINT8: + for (; i < num; i++) + { + *qnt = (uint8_t)__clip(*src_ptr, 0, 255); + src_ptr++; + qnt++; + } + break; + case RKNN_TENSOR_INT16: + for (; i < num; i++) + { + *((int16_t *)qnt) = (int16_t)__clip(*src_ptr, -32768, 32767); + src_ptr++; + qnt += 2; + } + break; + default: + break; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.h new file mode 100644 index 0000000..f6fa12e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_pass_through_demo/src/quant_utils.h @@ -0,0 +1,28 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _RKNN_DEMO_QUANT_UTILS_H_ +#define _RKNN_DEMO_QUANT_UTILS_H_ + +#include + +void f32_to_f16(uint16_t *f16, float *f32, int num); + +void qnt_f32_to_dfp(uint8_t *qnt, uint8_t type, int8_t fl, float *f32, int num); + +void qnt_f32_to_affine(uint8_t *qnt, uint8_t type, uint8_t zp, float scale, float *f32, int num); + +void qnt_f32_to_none(uint8_t *qnt, uint8_t type, float *f32, int num); + +#endif /*_RKNN_DEMO_QUANT_UTILS_H_ */ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/CMakeLists.txt new file mode 100644 index 0000000..0fb7f63 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_ssd_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_ssd_demo + src/main.cc + src/ssd.cc + ) + +target_link_libraries(rknn_ssd_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_ssd_demo) +install(TARGETS rknn_ssd_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/README.md new file mode 100644 index 0000000..bae5217 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/README.md @@ -0,0 +1,39 @@ +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## Install + +Copy install/rknn_ssd_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +``` +adb push install/rknn_ssd_demo /userdata/ +``` + +- If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + + +## Run + +``` +adb shell +cd /userdata/rknn_ssd_demo/ +``` + +- RK1808/RK1806 +``` +./rknn_ssd_demo model/ssd_inception_v2_rk180x.rknn model/road.bmp +``` + +- RV1109/RV1126 +``` +./rknn_ssd_demo model/ssd_inception_v2_rv1109_rv1126.rknn model/road.bmp +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/build.sh new file mode 100644 index 0000000..6ddeae5 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/build.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=/work/projects/rv1109/git/rv1109/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=~/opts/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/box_priors.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/box_priors.txt new file mode 100644 index 0000000..efc3be4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/box_priors.txt @@ -0,0 +1,4 @@ + 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.02631579 0.02631579 0.026315793 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.078947365 0.07894737 0.078947365 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.13157895 0.13157895 0.13157894 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.18421052 0.18421051 0.18421052 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.23684211 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.28947368 0.28947368 0.28947365 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.34210524 0.34210524 0.3421052 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.92105263 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.97368425 0.9736843 0.97368425 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.049999997 0.049999997 0.049999997 0.05 0.050000012 0.049999997 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.25 0.25 0.25 0.25 0.25000003 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000005 0.35000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.45 0.45000002 0.45000002 0.45000002 0.45000002 0.45000002 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.55 0.55 0.55 0.55 0.54999995 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.099999994 0.1 0.099999994 0.1 0.099999994 0.099999994 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.30000004 0.3 0.3 0.3 0.3 0.30000004 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.49999997 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.90000004 0.16666667 0.16666667 0.16666666 0.16666667 0.16666669 0.16666667 0.16666667 0.16666667 0.16666666 0.16666667 0.16666669 0.16666667 0.16666667 0.16666667 0.16666666 0.16666667 0.16666669 0.16666667 0.5 0.5 0.49999997 0.5 0.5 0.5 0.5 0.5 0.49999997 0.5 0.5 0.5 0.5 0.5 0.49999997 0.5 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.8333334 0.25 0.25 0.25 0.24999999 0.25 0.25 0.25 0.25 0.25 0.24999999 0.25 0.25 0.75 0.75 0.75 0.75 0.74999994 0.75 0.75 0.75 0.75 0.75 0.74999994 0.75 0.5 0.5 0.5 0.5 0.5 0.5 + 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.02631579 0.026315793 0.02631579 0.078947365 0.078947365 0.07894737 0.13157895 0.13157894 0.13157895 0.18421052 0.18421052 0.18421051 0.23684211 0.23684211 0.23684211 0.28947368 0.28947365 0.28947368 0.34210524 0.3421052 0.34210524 0.39473683 0.39473683 0.39473683 0.4473684 0.4473684 0.4473684 0.5 0.5 0.5 0.5526316 0.5526316 0.5526316 0.6052632 0.6052632 0.6052632 0.65789473 0.65789473 0.65789473 0.71052635 0.71052635 0.71052635 0.7631579 0.7631579 0.7631579 0.8157895 0.8157895 0.8157895 0.8684211 0.8684211 0.8684211 0.92105263 0.92105263 0.92105263 0.97368425 0.97368425 0.9736843 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.049999997 0.049999997 0.050000004 0.050000012 0.05 0.049999997 0.15 0.14999999 0.15 0.15 0.15 0.15 0.25 0.25 0.25 0.25 0.25 0.25 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.35000002 0.45000002 0.45 0.45000002 0.45000002 0.45 0.45000002 0.55 0.55 0.55 0.55 0.55 0.55 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.65000004 0.75 0.75 0.75 0.75 0.75 0.75 0.85 0.85 0.85 0.85 0.85 0.85 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.95000005 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.10000001 0.099999994 0.1 0.099999994 0.1 0.099999994 0.3 0.3 0.3 0.29999998 0.3 0.30000004 0.5 0.5 0.5 0.5 0.5 0.49999997 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.70000005 0.9 0.90000004 0.90000004 0.9 0.90000004 0.90000004 0.16666667 0.16666669 0.16666667 0.16666669 0.16666667 0.16666667 0.49999997 0.5 0.5 0.50000006 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333333 0.8333334 0.8333334 0.16666667 0.16666669 0.16666667 0.16666669 0.16666667 0.16666667 0.49999997 0.5 0.5 0.50000006 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333333 0.8333334 0.8333334 0.16666667 0.16666669 0.16666667 0.16666669 0.16666667 0.16666667 0.49999997 0.5 0.5 0.50000006 0.5 0.5 0.8333334 0.8333334 0.8333334 0.8333333 0.8333334 0.8333334 0.25 0.25 0.25 0.25 0.25 0.25 0.75 0.75 0.75 0.75 0.75 0.75 0.25 0.25 0.25 0.25 0.25 0.25 0.75 0.75 0.75 0.75 0.75 0.75 0.5 0.5 0.5 0.5 0.5 0.5 + 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.1 0.14142136 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.28284273 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142138 0.2828427 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.099999994 0.14142135 0.28284273 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.10000001 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142138 0.2828427 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142135 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.2828427 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142132 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.100000024 0.14142138 0.28284276 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.2474874 0.4949748 0.20207259 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748738 0.4949748 0.20207258 0.6062481 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.4949748 0.2020726 0.60624814 0.41833 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35000002 0.24748741 0.49497482 0.2020726 0.60624814 0.41832998 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35 0.24748737 0.4949748 0.20207256 0.6062481 0.41833 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497476 0.20207262 0.606248 0.41833004 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000002 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.35000008 0.24748743 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.34999996 0.24748737 0.49497485 0.20207262 0.60624814 0.41832995 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.50000006 0.3535534 0.7071068 0.28867513 0.8660687 0.57008773 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5000001 0.3535534 0.7071068 0.28867513 0.8660687 0.5700878 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.2886751 0.8660687 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5 0.3535534 0.7071068 0.28867507 0.8660688 0.5700877 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.5000001 0.3535534 0.70710677 0.2886752 0.8660687 0.5700878 0.65000004 0.45961943 0.91923887 0.37527767 1.1258893 0.7211102 0.65000004 0.45961943 0.91923887 0.37527767 1.1258893 0.7211102 0.65000004 0.45961943 0.91923887 0.37527767 1.1258893 0.7211102 0.6500001 0.4596194 0.9192388 0.37527764 1.1258893 0.7211102 0.6500001 0.4596194 0.9192388 0.37527764 1.1258893 0.7211102 0.6500001 0.4596194 0.9192388 0.37527764 1.1258893 0.7211102 0.6500001 0.45961946 0.9192388 0.3752777 1.1258893 0.72111017 0.6500001 0.45961946 0.9192388 0.3752777 1.1258893 0.72111017 0.6500001 0.45961946 0.9192388 0.3752777 1.1258893 0.72111017 0.8000001 0.5656855 1.131371 0.4618802 1.3857099 0.8717798 0.8000001 0.5656855 1.131371 0.4618802 1.3857099 0.8717798 0.80000013 0.5656855 1.131371 0.4618802 1.3857098 0.87177986 0.80000013 0.5656855 1.131371 0.4618802 1.3857098 0.87177986 0.95000005 0.6717515 1.343503 0.5484828 1.6455305 0.97467947 + 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.1 0.28284273 0.14142136 0.099999994 0.28284273 0.14142138 0.099999994 0.2828427 0.14142138 0.099999994 0.28284273 0.14142135 0.099999994 0.28284273 0.14142135 0.10000001 0.2828427 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142138 0.100000024 0.2828427 0.14142138 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142135 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.2828427 0.14142132 0.100000024 0.28284276 0.14142132 0.100000024 0.28284276 0.14142138 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.34999996 0.4949747 0.24748735 0.60621774 0.20206249 0.41833 0.34999996 0.49497467 0.24748737 0.60621774 0.20206249 0.41833 0.34999996 0.49497473 0.24748737 0.60621774 0.20206249 0.41833 0.34999993 0.49497473 0.24748737 0.60621774 0.20206249 0.41832998 0.34999996 0.49497467 0.24748737 0.60621774 0.20206246 0.41833 0.35 0.49497473 0.24748734 0.60621774 0.20206249 0.41833004 0.35 0.49497473 0.2474873 0.60621774 0.20206249 0.41833004 0.3499999 0.49497473 0.2474873 0.6062178 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062177 0.20206249 0.41832995 0.3499999 0.49497467 0.2474873 0.6062178 0.20206255 0.41832995 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.49999997 0.7071067 0.35355335 0.8660254 0.2886607 0.57008773 0.5 0.7071067 0.35355335 0.8660253 0.2886607 0.5700878 0.5 0.7071067 0.35355332 0.86602545 0.28866073 0.5700877 0.5 0.70710665 0.3535533 0.86602545 0.28866076 0.5700877 0.49999994 0.7071067 0.3535534 0.8660253 0.28866065 0.5700878 0.6499999 0.9192387 0.45961934 1.1258329 0.3752589 0.7211102 0.64999986 0.9192387 0.4596193 1.125833 0.37525892 0.7211102 0.64999986 0.91923875 0.45961928 1.1258328 0.37525892 0.72111017 0.6499999 0.9192387 0.45961934 1.1258329 0.3752589 0.7211102 0.64999986 0.9192387 0.4596193 1.125833 0.37525892 0.7211102 0.64999986 0.91923875 0.45961928 1.1258328 0.37525892 0.72111017 0.6499999 0.9192387 0.45961934 1.1258329 0.3752589 0.7211102 0.64999986 0.9192387 0.4596193 1.125833 0.37525892 0.7211102 0.64999986 0.91923875 0.45961928 1.1258328 0.37525892 0.72111017 0.79999995 1.1313708 0.5656854 1.3856406 0.46185714 0.8717798 0.79999995 1.1313708 0.56568533 1.3856406 0.46185708 0.87177986 0.79999995 1.1313708 0.5656854 1.3856406 0.46185714 0.8717798 0.79999995 1.1313708 0.56568533 1.3856406 0.46185708 0.87177986 0.9499999 1.3435028 0.6717514 1.6454482 0.54845536 0.97467947 \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/coco_labels_list.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/coco_labels_list.txt new file mode 100644 index 0000000..c634db4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/coco_labels_list.txt @@ -0,0 +1,91 @@ +??? +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +??? +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +??? +backpack +umbrella +??? +??? +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +??? +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +??? +dining table +??? +??? +toilet +??? +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +??? +book +clock +vase +scissors +teddy bear +hair drier +toothbrush \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/road.bmp b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/road.bmp new file mode 100644 index 0000000..1254b96 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/road.bmp differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rk180x.rknn new file mode 100644 index 0000000..712b791 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rv1109_rv1126.rknn new file mode 100644 index 0000000..a65660e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/model/ssd_inception_v2_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/main.cc new file mode 100644 index 0000000..b4e9559 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/main.cc @@ -0,0 +1,277 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include + +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb/stb_image_write.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#undef cimg_display +#define cimg_display 0 +#include "CImg/CImg.h" +#include "rknn_api.h" +#include "ssd.h" + +using namespace std; +using namespace cimg_library; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +static void printRKNNTensor(rknn_tensor_attr* attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d fmt=%d type=%d qnt_type=%d fl=%d zp=%d " + "scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, 0, attr->type, attr->qnt_type, attr->fl, attr->zp, attr->scale); +} + +static unsigned char* load_model(const char* filename, int* model_size) +{ + FILE* fp = fopen(filename, "rb"); + if (fp == nullptr) { + printf("fopen %s fail!\n", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + int model_len = ftell(fp); + unsigned char* model = (unsigned char*)malloc(model_len); + fseek(fp, 0, SEEK_SET); + if (model_len != fread(model, 1, model_len, fp)) { + printf("fread %s fail!\n", filename); + free(model); + return NULL; + } + *model_size = model_len; + if (fp) { + fclose(fp); + } + return model; +} +static unsigned char* load_image(const char* image_path, rknn_tensor_attr* input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char* image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) { + printf("load image failed!\n"); + return NULL; + } + + if (width != req_width || height != req_height) { + unsigned char* image_resized = (unsigned char*)STBI_MALLOC(req_width * req_height * req_channel); + if (!image_resized) { + printf("malloc image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + if (stbir_resize_uint8(image_data, width, height, 0, image_resized, req_width, req_height, 0, channel) != 1) { + printf("resize image failed!\n"); + STBI_FREE(image_data); + return NULL; + } + STBI_FREE(image_data); + image_data = image_resized; + } + + return image_data; +} + +/*------------------------------------------- + Main Function +-------------------------------------------*/ +int main(int argc, char** argv) +{ + const int img_width = 300; + const int img_height = 300; + const int img_channels = 3; + + rknn_context ctx; + int ret; + int model_len = 0; + unsigned char* model; + + const char* model_path = argv[1]; + const char* img_path = argv[2]; + + if (argc != 3) { + printf("Usage:%s model image\n", argv[0]); + return -1; + } + if (strstr(img_path, ".jpg") != NULL || strstr(img_path, ".png") != NULL) { + printf("Error: read %s failed! only support .bmp format image\n", img_path); + return -1; + } + + // Load RKNN Model + printf("Loading model ...\n"); + model = load_model(model_path, &model_len); + ret = rknn_init(&ctx, model, model_len, 0); + if (ret < 0) { + printf("rknn_init fail! ret=%d\n", ret); + return -1; + } + + // Get Model Input Output Info + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret != RKNN_SUCC) { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + printf("input tensors:\n"); + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(input_attrs[i])); + } + + printf("output tensors:\n"); + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret != RKNN_SUCC) { + printf("rknn_query fail! ret=%d\n", ret); + return -1; + } + printRKNNTensor(&(output_attrs[i])); + } + + // Load image, only support .bmp format + CImg img(img_path); + if (img.height() != img_height || img.width() != img_width) { + img = img.resize(img_width, img_height); + } + unsigned char* input_data = NULL; + input_data = load_image(img_path, &input_attrs[0]); + if (!input_data) { + return -1; + } + + // Set Input Data + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = input_attrs[0].size; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = input_data; + + ret = rknn_inputs_set(ctx, io_num.n_input, inputs); + if (ret < 0) { + printf("rknn_input_set fail! ret=%d\n", ret); + return -1; + } + + // Run + printf("rknn_run\n"); + ret = rknn_run(ctx, nullptr); + if (ret < 0) { + printf("rknn_run fail! ret=%d\n", ret); + return -1; + } + + // Get Output + rknn_output outputs[2]; + memset(outputs, 0, sizeof(outputs)); + outputs[0].want_float = 1; + outputs[1].want_float = 1; + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + if (ret < 0) { + printf("rknn_outputs_get fail! ret=%d\n", ret); + return -1; + } + + // Post Process + detect_result_group_t detect_result_group; + postProcessSSD((float*)(outputs[0].buf), (float*)(outputs[1].buf), img_height, img_width, &detect_result_group); + // Release rknn_outputs + rknn_outputs_release(ctx, 2, outputs); + + // Draw Objects + const unsigned char blue[] = {0, 0, 255}; + for (int i = 0; i < detect_result_group.count; i++) { + detect_result_t* det_result = &(detect_result_group.results[i]); + printf("%s @ (%d %d %d %d) %f\n", det_result->name, det_result->box.left, det_result->box.top, + det_result->box.right, det_result->box.bottom, det_result->prop); + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + // draw box + img.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U); + img.draw_text(x1, y1 - 12, det_result->name, blue); + } + img.save("./out.bmp"); + + // Release + if (ctx >= 0) { + rknn_destroy(ctx); + } + if (model) { + free(model); + } + if (input_data) { + stbi_image_free(input_data); + } + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.cc new file mode 100644 index 0000000..2dccac7 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.cc @@ -0,0 +1,323 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "ssd.h" + +#define BOX_PRIORS_TXT_PATH "./model/box_priors.txt" +#define LABEL_NALE_TXT_PATH "./model/coco_labels_list.txt" + +float MIN_SCORE = 0.4f; +float NMS_THRESHOLD = 0.45f; + +static char* labels[NUM_CLASS]; +static float box_priors[4][NUM_RESULTS]; + +int64_t getCurrentTimeUs() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +char* readLine(FILE* fp, char* buffer, int* len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char*)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) { + buff_len++; + void* tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) { + free(buffer); + return NULL; // Out of memory + } + buffer = (char*)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char* fileName, char* lines[], int max_line) +{ + FILE* file = fopen(fileName, "r"); + char* s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + +int loadLabelName(const char* locationFilename, char* label[]) +{ + printf("ssd - loadLabelName %s\n", locationFilename); + readLines(locationFilename, label, NUM_CLASS); + return 0; +} + +int loadBoxPriors(const char* locationFilename, float (*boxPriors)[NUM_RESULTS]) +{ + const char* d = " "; + char* lines[4]; + int count = readLines(locationFilename, lines, 4); + // printf("line count %d\n", count); + // for (int i = 0; i < count; i++) { + // printf("%s\n", lines[i]); + // } + for (int i = 0; i < 4; i++) { + char* line_str = lines[i]; + char* p; + p = strtok(line_str, d); + int priorIndex = 0; + while (p) { + float number = (float)(atof(p)); + boxPriors[i][priorIndex++] = number; + p = strtok(NULL, d); + } + if (priorIndex != NUM_RESULTS) { + printf("error\n"); + return -1; + } + } + return 0; +} + +float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, + float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1)); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1)); + float i = w * h; + float u = (xmax0 - xmin0) * (ymax0 - ymin0) + (xmax1 - xmin1) * (ymax1 - ymin1) - i; + return u <= 0.f ? 0.f : (i / u); +} + +float unexpit(float y) { return -1.0 * logf((1.0 / y) - 1.0); } + +float expit(float x) { return (float)(1.0 / (1.0 + expf(-x))); } + +void decodeCenterSizeBoxes(float* predictions, float (*boxPriors)[NUM_RESULTS]) +{ + for (int i = 0; i < NUM_RESULTS; ++i) { + float ycenter = predictions[i * 4 + 0] / Y_SCALE * boxPriors[2][i] + boxPriors[0][i]; + float xcenter = predictions[i * 4 + 1] / X_SCALE * boxPriors[3][i] + boxPriors[1][i]; + float h = (float)expf(predictions[i * 4 + 2] / H_SCALE) * boxPriors[2][i]; + float w = (float)expf(predictions[i * 4 + 3] / W_SCALE) * boxPriors[3][i]; + + float ymin = ycenter - h / 2.0f; + float xmin = xcenter - w / 2.0f; + float ymax = ycenter + h / 2.0f; + float xmax = xcenter + w / 2.0f; + + predictions[i * 4 + 0] = ymin; + predictions[i * 4 + 1] = xmin; + predictions[i * 4 + 2] = ymax; + predictions[i * 4 + 3] = xmax; + } +} + +int filterValidResult(float* outputClasses, int (*output)[NUM_RESULTS], int numClasses, float* props) +{ + int validCount = 0; + float min_score = unexpit(MIN_SCORE); + + // Scale them back to the input size. + for (int i = 0; i < NUM_RESULTS; ++i) { + float topClassScore = (float)(-1000.0); + int topClassScoreIndex = -1; + + // Skip the first catch-all class. + for (int j = 1; j < numClasses; ++j) { + // x and expit(x) has same monotonicity + // so compare x and comare expit(x) is same + // float score = expit(outputClasses[i*numClasses+j]); + float score = outputClasses[i * numClasses + j]; + + if (score > topClassScore) { + topClassScoreIndex = j; + topClassScore = score; + } + } + + if (topClassScore >= min_score) { + output[0][validCount] = i; + output[1][validCount] = topClassScoreIndex; + props[validCount] = expit(outputClasses[i * numClasses + topClassScoreIndex]); + ++validCount; + } + } + + return validCount; +} + +int nms(int validCount, float* outputLocations, int (*output)[NUM_RESULTS]) +{ + for (int i = 0; i < validCount; ++i) { + if (output[0][i] == -1) { + continue; + } + int n = output[0][i]; + for (int j = i + 1; j < validCount; ++j) { + int m = output[0][j]; + if (m == -1) { + continue; + } + float xmin0 = outputLocations[n * 4 + 1]; + float ymin0 = outputLocations[n * 4 + 0]; + float xmax0 = outputLocations[n * 4 + 3]; + float ymax0 = outputLocations[n * 4 + 2]; + + float xmin1 = outputLocations[m * 4 + 1]; + float ymin1 = outputLocations[m * 4 + 0]; + float xmax1 = outputLocations[m * 4 + 3]; + float ymax1 = outputLocations[m * 4 + 2]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou >= NMS_THRESHOLD) { + output[0][j] = -1; + } + } + } + return 0; +} + +void sort(int output[][1917], float* props, int sz) +{ + int i = 0; + int j = 0; + + if (sz < 2) { + return; + } + + for (i = 0; i < sz - 1; i++) { + int top = i; + for (j = i + 1; j < sz; j++) { + if (props[top] < props[j]) { + top = j; + } + } + + if (i != top) { + int tmp1 = output[0][i]; + int tmp2 = output[1][i]; + float prop = props[i]; + output[0][i] = output[0][top]; + output[1][i] = output[1][top]; + props[i] = props[top]; + output[0][top] = tmp1; + output[1][top] = tmp2; + props[top] = prop; + } + } +} + +int postProcessSSD(float* predictions, float* output_classes, int width, int heigh, detect_result_group_t* group) +{ + static int init = -1; + if (init == -1) { + int ret = 0; + printf("loadLabelName\n"); + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) { + return -1; + } + + printf("loadBoxPriors\n"); + ret = loadBoxPriors(BOX_PRIORS_TXT_PATH, box_priors); + if (ret < 0) { + return -1; + } + + init = 0; + } + + int output[2][NUM_RESULTS]; + float props[NUM_RESULTS]; + memset(output, 0, 2 * NUM_RESULTS); + memset(props, 0, sizeof(float) * NUM_RESULTS); + + decodeCenterSizeBoxes(predictions, box_priors); + + int validCount = filterValidResult(output_classes, output, NUM_CLASS, props); + + if (validCount > OBJ_NUMB_MAX_SIZE) { + printf("validCount too much !!\n"); + return -1; + } + + sort(output, props, validCount); + + /* detect nest box */ + nms(validCount, predictions, output); + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) { + if (output[0][i] == -1) { + continue; + } + int n = output[0][i]; + int topClassScoreIndex = output[1][i]; + + int x1 = (int)(predictions[n * 4 + 1] * width); + int y1 = (int)(predictions[n * 4 + 0] * heigh); + int x2 = (int)(predictions[n * 4 + 3] * width); + int y2 = (int)(predictions[n * 4 + 2] * heigh); + // There are a bug show toothbrush always + if (x1 == 0 && x2 == 0 && y1 == 0 && y2 == 0) + continue; + char* label = labels[topClassScoreIndex]; + + group->results[last_count].box.left = x1; + group->results[last_count].box.top = y1; + group->results[last_count].box.right = x2; + group->results[last_count].box.bottom = y2; + group->results[last_count].prop = props[i]; + memcpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("ssd result %2d: (%4d, %4d, %4d, %4d), %4.2f, %s\n", i, x1, y1, x2, y2, props[i], label); + last_count++; + } + + group->count = last_count; + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.h new file mode 100644 index 0000000..ff910a0 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_ssd_demo/src/ssd.h @@ -0,0 +1,58 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SSD_H_ +#define _SSD_H_ + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 64 + +typedef struct _BOX_RECT { + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t { + char name[OBJ_NAME_MAX_SIZE]; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t { + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + +#define IMG_CHANNEL 3 +#define MODEL_INPUT_SIZE 300 +#define NUM_RESULTS 1917 +#define NUM_CLASS 91 + +#define Y_SCALE 10.0f +#define X_SCALE 10.0f +#define H_SCALE 5.0f +#define W_SCALE 5.0f + +int loadLabelName(const char* locationFilename, char* labels[]); + +int loadBoxPriors(const char* locationFilename, float (*boxPriors)[NUM_RESULTS]); + +int postProcessSSD(float * predictions, float *output_classes, int width, int heigh, detect_result_group_t *group); + +int64_t getCurrentTimeUs(); + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/CMakeLists.txt new file mode 100644 index 0000000..d7ea9d6 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_yolov5_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s -O3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s -O3") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rga +set(RGA_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/rga) +include_directories(${RGA_DIR}/include) + +# drm +set(DRM_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/drm) +include_directories(${DRM_DIR}/include) +include_directories(${DRM_DIR}/include/libdrm) + +include_directories(${CMAKE_SOURCE_DIR}/include) + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_yolov5_demo + src/drm_func.c + src/rga_func.c + src/postprocess.cc + src/main.cc + ) + +target_link_libraries(rknn_yolov5_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_yolov5_demo) +install(TARGETS rknn_yolov5_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/README.md new file mode 100644 index 0000000..e8086cc --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/README.md @@ -0,0 +1,64 @@ +# Yolo-v5 demo + +## 导出rknn模型 + +请参考 https://github.com/airockchip/rknn_model_zoo/tree/main/models/vision/object_detection/yolov5-pytorch + + + +## 注意事项: + +1. 使用rknn-toolkit版本大于等于1.7.0。 +2. 本Demo只支持8比特非对称量化的rknn模型推理。 +3. 切换成自己训练的模型时,请注意对齐anchor等后处理参数,否则会导致后处理解析出错。 +4. 官网和rk预训练模型都是检测80类的目标,如果自己训练的模型,自行更改include/postprocess.h中的OBJ_CLASS_NUM以及NMS_THRESH,BOX_THRESH后处理参数后再编译。 +5. 由于硬件限制,该demo的模型默认把 yolov5 模型的后处理部分,移至cpu实现。本demo附带的模型均使用relu为激活函数,相比silu激活函数精度略微下降,推理速度更快。 +6. 关于加载时间:model目录下均是预编译rknn模型,加载速度比非预编译rknn模型快。convert_rknn_demo目录下的转换脚本生成非预编译rknn模型,如需重新生成预编译rknn模型,请参考rknn-toolkit的User Guide. + + +## Aarch64 Linux Demo + +### 编译 + +根据指定平台修改`build.sh`中的交叉编译器所在目录的路径`GCC_COMPILER`,例如修改成 + +```sh +GCC_COMPILER=~/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf +``` + +然后执行: + +```sh +./build.sh +``` + +### 推送执行文件到板子 + +将 install/rknn_yolov5_demo 拷贝到板子的/userdata/目录. + +- 如果使用rockchip的EVB板子,可以使用adb将文件推到板子上: + +```sh +adb push install/rknn_yolov5_demo /userdata/ +``` + +如果使用其他板子,可以使用scp等方式将install/rknn_yolov5_demo拷贝到板子的/userdata/目录 + +## 运行 + +```sh +adb shell +cd /userdata/rknn_yolov5_demo/ +``` + +- rk180x + +```sh +./run_rk180x.sh +``` + +- rv1109/rv1126 + +```sh +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/build.sh new file mode 100644 index 0000000..334bf73 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/build.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_yolov5_demo/ +cp run_rv1109_rv1126.sh install/rknn_yolov5_demo/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/bus.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/bus.jpg new file mode 100644 index 0000000..d8ef30b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/bus.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/dataset.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/dataset.txt new file mode 100644 index 0000000..a81b1f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/dataset.txt @@ -0,0 +1 @@ +bus.jpg diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py new file mode 100644 index 0000000..9f4ec6e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py @@ -0,0 +1,40 @@ +from rknn.api import RKNN + +ONNX_MODEL = './onnx_models/yolov5s_rm_transpose.onnx' +# platform="rk1808" +platform = "rv1109" +RKNN_MODEL = 'yolov5s_relu_{}_out_opt.rknn'.format(platform) + + +if __name__ == '__main__': + + add_perm = False # 如果设置成True,则将模型输入layout修改成NHWC + # Create RKNN object + rknn = RKNN(verbose=True) + + # pre-process config + print('--> config model') + rknn.config(batch_size=1, mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], reorder_channel='0 1 2', target_platform=[platform], + force_builtin_perm=add_perm, output_optimize=1) + print('done') + + # Load tensorflow model + print('--> Loading model') + ret = rknn.load_onnx(model=ONNX_MODEL) + if ret != 0: + print('Load resnet50v2 failed!') + exit(ret) + print('done') + + # Build model + print('--> Building model') + ret = rknn.build(do_quantization=True, dataset='./dataset.txt') + if ret != 0: + print('Build resnet50 failed!') + exit(ret) + print('done') + + # rknn.export_rknn_precompile_model(RKNN_MODEL) + rknn.export_rknn(RKNN_MODEL) + + rknn.release() diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/bus.jpg b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/bus.jpg new file mode 100644 index 0000000..d8ef30b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/bus.jpg differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/dataset.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/dataset.txt new file mode 100644 index 0000000..a81b1f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/dataset.txt @@ -0,0 +1 @@ +bus.jpg diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/yolov5s_rm_transpose.onnx b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/yolov5s_rm_transpose.onnx new file mode 100644 index 0000000..0a340ed Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx_models/yolov5s_rm_transpose.onnx differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/drm_func.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/drm_func.h new file mode 100644 index 0000000..0a9e3b3 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/drm_func.h @@ -0,0 +1,53 @@ +#ifndef __DRM_FUNC_H__ +#define __DRM_FUNC_H__ +#include +#include +#include +#include +#include // open function +#include // close function +#include +#include + + +#include +#include "libdrm/drm_fourcc.h" +#include "xf86drm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (* FUNC_DRM_IOCTL)(int fd, unsigned long request, void *arg); + +typedef struct _drm_context{ + void *drm_handle; + FUNC_DRM_IOCTL io_func; +} drm_context; + +/* memory type definitions. */ +enum drm_rockchip_gem_mem_type +{ + /* Physically Continuous memory and used as default. */ + ROCKCHIP_BO_CONTIG = 1 << 0, + /* cachable mapping. */ + ROCKCHIP_BO_CACHABLE = 1 << 1, + /* write-combine mapping. */ + ROCKCHIP_BO_WC = 1 << 2, + ROCKCHIP_BO_SECURE = 1 << 3, + ROCKCHIP_BO_MASK = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_CACHABLE | + ROCKCHIP_BO_WC | ROCKCHIP_BO_SECURE +}; + +int drm_init(drm_context *drm_ctx); + +void* drm_buf_alloc(drm_context *drm_ctx,int drm_fd, int TexWidth, int TexHeight,int bpp,int *fd,unsigned int *handle,size_t *actual_size); + +int drm_buf_destroy(drm_context *drm_ctx,int drm_fd,int buf_fd, int handle,void *drm_buf,size_t size); + +void drm_deinit(drm_context *drm_ctx, int drm_fd); + +#ifdef __cplusplus +} +#endif +#endif /*__DRM_FUNC_H__*/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/postprocess.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/postprocess.h new file mode 100644 index 0000000..e474505 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/postprocess.h @@ -0,0 +1,40 @@ +#ifndef _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ +#define _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ + +#include + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 64 +#define OBJ_CLASS_NUM 80 +#define NMS_THRESH 0.6 +#define BOX_THRESH 0.5 +#define PROP_BOX_SIZE (5+OBJ_CLASS_NUM) + +typedef struct _BOX_RECT +{ + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t +{ + char name[OBJ_NAME_MAX_SIZE]; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t +{ + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + +int post_process(uint8_t *input0, uint8_t *input1, uint8_t *input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector &qnt_zps, std::vector &qnt_scales, + detect_result_group_t *group); + +#endif //_RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/rga_func.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/rga_func.h new file mode 100644 index 0000000..beeb441 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/include/rga_func.h @@ -0,0 +1,33 @@ +#ifndef __RGA_FUNC_H__ +#define __RGA_FUNC_H__ + +#include +#include "RgaApi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(* FUNC_RGA_INIT)(); +typedef void(* FUNC_RGA_DEINIT)(); +typedef int(* FUNC_RGA_BLIT)(rga_info_t *, rga_info_t *, rga_info_t *); + +typedef struct _rga_context{ + void *rga_handle; + FUNC_RGA_INIT init_func; + FUNC_RGA_DEINIT deinit_func; + FUNC_RGA_BLIT blit_func; +} rga_context; + +int RGA_init(rga_context* rga_ctx); + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h); + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h); + +int RGA_deinit(rga_context* rga_ctx); + +#ifdef __cplusplus +} +#endif +#endif/*__RGA_FUNC_H__*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/bus.bmp b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/bus.bmp new file mode 100644 index 0000000..82df079 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/bus.bmp differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt new file mode 100644 index 0000000..941cb4e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/coco_80_labels_list.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +dining table +toilet +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/rk180x/yolov5s_relu_rk180x_out_opt.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/rk180x/yolov5s_relu_rk180x_out_opt.rknn new file mode 100644 index 0000000..b240c62 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/rk180x/yolov5s_relu_rk180x_out_opt.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_out_opt.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_out_opt.rknn new file mode 100644 index 0000000..0692c1c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_out_opt.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/run_rk180x.sh new file mode 100644 index 0000000..f8492f8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/run_rk180x.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +chip_dir="rk180x" +./rknn_yolov5_demo model/${chip_dir}/yolov5s_relu_rk180x_out_opt.rknn model/bus.bmp + + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..54d81fe --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/run_rv1109_rv1126.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +./rknn_yolov5_demo model/${chip_dir}/yolov5s_relu_rv1109_rv1126_out_opt.rknn model/bus.bmp + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/drm_func.c b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/drm_func.c new file mode 100644 index 0000000..2992326 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/drm_func.c @@ -0,0 +1,163 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "drm_func.h" + +#include + +int drm_init(drm_context* drm_ctx) +{ + static const char* card = "/dev/dri/card0"; + int flag = O_RDWR; + int drm_fd = -1; + + drm_fd = open(card, flag); + if (drm_fd < 0) { + printf("failed to open %s\n", card); + return -1; + } + + drm_ctx->drm_handle = dlopen("/usr/lib/libdrm.so", RTLD_LAZY); + if (!drm_ctx->drm_handle) { + printf("failed to dlopen /usr/lib/libdrm.so\n"); + drm_deinit(drm_ctx, drm_fd); + return -1; + } + + drm_ctx->io_func = (FUNC_DRM_IOCTL)dlsym(drm_ctx->drm_handle, "drmIoctl"); + if (drm_ctx->io_func == NULL) { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + drm_deinit(drm_ctx, drm_fd); + printf("failed to dlsym drmIoctl\n"); + return -1; + } + return drm_fd; +} + +void drm_deinit(drm_context* drm_ctx, int drm_fd) +{ + if (drm_ctx->drm_handle) { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + } + if (drm_fd > 0) { + close(drm_fd); + } +} + +void* drm_buf_alloc(drm_context* drm_ctx, int drm_fd, int TexWidth, int TexHeight, int bpp, int* fd, + unsigned int* handle, size_t* actual_size) +{ + int ret; + if (drm_ctx == NULL) { + printf("drm context is unvalid\n"); + return NULL; + } + char* map = NULL; + + void* vir_addr = NULL; + struct drm_prime_handle fd_args; + struct drm_mode_map_dumb mmap_arg; + struct drm_mode_destroy_dumb destory_arg; + + struct drm_mode_create_dumb alloc_arg; + + memset(&alloc_arg, 0, sizeof(alloc_arg)); + alloc_arg.bpp = bpp; + alloc_arg.width = TexWidth; + alloc_arg.height = TexHeight; + // alloc_arg.flags = ROCKCHIP_BO_CONTIG; + + //获取handle和size + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg); + if (ret) { + printf("failed to create dumb buffer: %s\n", strerror(errno)); + return NULL; + } + if (handle != NULL) { + *handle = alloc_arg.handle; + } + if (actual_size != NULL) { + *actual_size = alloc_arg.size; + } + // printf("create width=%u, height=%u, bpp=%u, size=%lu dumb + // buffer\n",alloc_arg.width,alloc_arg.height,alloc_arg.bpp,alloc_arg.size); printf("out handle= + // %d\n",alloc_arg.handle); + + //获取fd + memset(&fd_args, 0, sizeof(fd_args)); + fd_args.fd = -1; + fd_args.handle = alloc_arg.handle; + ; + fd_args.flags = 0; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args); + if (ret) { + printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle); + return NULL; + } + // printf("out fd = %d, drm fd: %d\n",fd_args.fd,drm_fd); + if (fd != NULL) { + *fd = fd_args.fd; + } + + //获取虚拟地址 + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = alloc_arg.handle; + + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg); + if (ret) { + printf("failed to create map dumb: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + vir_addr = map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset); + if (map == MAP_FAILED) { + printf("failed to mmap buffer: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + // printf("alloc map=%x \n",map); + return vir_addr; +destory_dumb: + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = alloc_arg.handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d\n", ret); + return vir_addr; +} + +int drm_buf_destroy(drm_context* drm_ctx, int drm_fd, int buf_fd, int handle, void* drm_buf, size_t size) +{ + int ret = -1; + if (drm_buf == NULL) { + printf("drm buffer is NULL\n"); + return -1; + } + + munmap(drm_buf, size); + + struct drm_mode_destroy_dumb destory_arg; + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno)); + if (buf_fd > 0) { + close(buf_fd); + } + + return ret; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/main.cc new file mode 100644 index 0000000..db229bc --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/main.cc @@ -0,0 +1,417 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include + +#include + +#define _BASETSD_H + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#undef cimg_display +#define cimg_display 0 +#include "CImg/CImg.h" +#include "drm_func.h" +#include "postprocess.h" +#include "rga_func.h" +#include "rknn_api.h" + +#define PERF_WITH_POST 1 + +using namespace cimg_library; +/*------------------------------------------- + Functions +-------------------------------------------*/ + +inline const char* get_type_string(rknn_tensor_type type) +{ + switch (type) { + case RKNN_TENSOR_FLOAT32: + return "FP32"; + case RKNN_TENSOR_FLOAT16: + return "FP16"; + case RKNN_TENSOR_INT8: + return "INT8"; + case RKNN_TENSOR_UINT8: + return "UINT8"; + case RKNN_TENSOR_INT16: + return "INT16"; + default: + return "UNKNOW"; + } +} + +inline const char* get_qnt_type_string(rknn_tensor_qnt_type type) +{ + switch (type) { + case RKNN_TENSOR_QNT_NONE: + return "NONE"; + case RKNN_TENSOR_QNT_DFP: + return "DFP"; + case RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + return "AFFINE"; + default: + return "UNKNOW"; + } +} + +inline const char* get_format_string(rknn_tensor_format fmt) +{ + switch (fmt) { + case RKNN_TENSOR_NCHW: + return "NCHW"; + case RKNN_TENSOR_NHWC: + return "NHWC"; + default: + return "UNKNOW"; + } +} + +static void dump_tensor_attr(rknn_tensor_attr* attr) +{ + printf(" index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, " + "zp=%d, scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, get_format_string(attr->fmt), get_type_string(attr->type), + get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale); +} + +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static unsigned char* load_data(FILE* fp, size_t ofst, size_t sz) +{ + unsigned char* data; + int ret; + + data = NULL; + + if (NULL == fp) { + return NULL; + } + + ret = fseek(fp, ofst, SEEK_SET); + if (ret != 0) { + printf("blob seek failure.\n"); + return NULL; + } + + data = (unsigned char*)malloc(sz); + if (data == NULL) { + printf("buffer malloc failure.\n"); + return NULL; + } + ret = fread(data, 1, sz, fp); + return data; +} + +static unsigned char* load_model(const char* filename, int* model_size) +{ + FILE* fp; + unsigned char* data; + + fp = fopen(filename, "rb"); + if (NULL == fp) { + printf("Open file %s failed.\n", filename); + return NULL; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + + data = load_data(fp, 0, size); + + fclose(fp); + + *model_size = size; + return data; +} + +static int saveFloat(const char* file_name, float* output, int element_size) +{ + FILE* fp; + fp = fopen(file_name, "w"); + for (int i = 0; i < element_size; i++) { + fprintf(fp, "%.6f\n", output[i]); + } + fclose(fp); + return 0; +} + +static unsigned char* load_image(const char* image_path, int* org_height, int* org_width, int* org_ch, + rknn_tensor_attr* input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char* image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) { + printf("load image failed!\n"); + return NULL; + } + *org_width = width; + *org_height = height; + *org_ch = channel; + + return image_data; +} + +/*------------------------------------------- + Main Functions +-------------------------------------------*/ +int main(int argc, char** argv) +{ + int status = 0; + char* model_name = NULL; + rknn_context ctx; + void* drm_buf = NULL; + int drm_fd = -1; + int buf_fd = -1; // converted from buffer handle + unsigned int handle; + size_t actual_size = 0; + int img_width = 0; + int img_height = 0; + int img_channel = 0; + rga_context rga_ctx; + drm_context drm_ctx; + const float nms_threshold = NMS_THRESH; + const float box_conf_threshold = BOX_THRESH; + struct timeval start_time, stop_time; + int ret; + memset(&rga_ctx, 0, sizeof(rga_context)); + memset(&drm_ctx, 0, sizeof(drm_context)); + + if (argc != 3) { + printf("Usage: %s \n", argv[0]); + return -1; + } + + printf("post process config: box_conf_threshold = %.2f, nms_threshold = %.2f\n", box_conf_threshold, nms_threshold); + + model_name = (char*)argv[1]; + char* image_name = argv[2]; + + if (strstr(image_name, ".jpg") != NULL || strstr(image_name, ".png") != NULL) { + printf("Error: read %s failed! only support .bmp format image\n", image_name); + return -1; + } + + /* Create the neural network */ + printf("Loading mode...\n"); + int model_data_size = 0; + unsigned char* model_data = load_model(model_name, &model_data_size); + ret = rknn_init(&ctx, model_data, model_data_size, 0); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, sizeof(rknn_sdk_version)); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("sdk version: %s driver version: %s\n", version.api_version, version.drv_version); + + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); + + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr)); + if (ret < 0) { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + dump_tensor_attr(&(input_attrs[i])); + } + + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr)); + dump_tensor_attr(&(output_attrs[i])); + if (output_attrs[i].qnt_type != RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC || output_attrs[i].type != RKNN_TENSOR_UINT8) { + fprintf(stderr, + "The Demo required for a Affine asymmetric u8 quantized rknn model, but output quant type is %s, output " + "data type is %s\n", + get_qnt_type_string(output_attrs[i].qnt_type), get_type_string(output_attrs[i].type)); + return -1; + } + } + + int channel = 3; + int width = 0; + int height = 0; + if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) { + printf("model is NCHW input fmt\n"); + width = input_attrs[0].dims[0]; + height = input_attrs[0].dims[1]; + } else { + printf("model is NHWC input fmt\n"); + width = input_attrs[0].dims[1]; + height = input_attrs[0].dims[2]; + } + + printf("model input height=%d, width=%d, channel=%d\n", height, width, channel); + + // Load image + CImg img(image_name); + unsigned char* input_data = NULL; + input_data = load_image(image_name, &img_height, &img_width, &img_channel, &input_attrs[0]); + if (!input_data) { + return -1; + } + + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = width * height * channel; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].pass_through = 0; + + // DRM alloc buffer + drm_fd = drm_init(&drm_ctx); + drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, img_width, img_height, channel * 8, &buf_fd, &handle, &actual_size); + memcpy(drm_buf, input_data, img_width * img_height * channel); + void* resize_buf = malloc(height * width * channel); + + // init rga context + RGA_init(&rga_ctx); + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + inputs[0].buf = resize_buf; + gettimeofday(&start_time, NULL); + rknn_inputs_set(ctx, io_num.n_input, inputs); + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) { + outputs[i].want_float = 0; + } + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + gettimeofday(&stop_time, NULL); + printf("once run use %f ms\n", (__get_us(stop_time) - __get_us(start_time)) / 1000); + + // post process + float scale_w = (float)width / img_width; + float scale_h = (float)height / img_height; + + detect_result_group_t detect_result_group; + std::vector out_scales; + std::vector out_zps; + for (int i = 0; i < io_num.n_output; ++i) { + out_scales.push_back(output_attrs[i].scale); + out_zps.push_back(output_attrs[i].zp); + } + post_process((uint8_t*)outputs[0].buf, (uint8_t*)outputs[1].buf, (uint8_t*)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); + + // Draw Objects + char text[256]; + const unsigned char blue[] = {0, 0, 255}; + const unsigned char white[] = {255, 255, 255}; + for (int i = 0; i < detect_result_group.count; i++) { + detect_result_t* det_result = &(detect_result_group.results[i]); + sprintf(text, "%s %.2f", det_result->name, det_result->prop); + printf("%s @ (%d %d %d %d) %f\n", det_result->name, det_result->box.left, det_result->box.top, + det_result->box.right, det_result->box.bottom, det_result->prop); + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + // draw box + img.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U); + img.draw_text(x1, y1 - 12, text, white); + } + img.save("./out.bmp"); + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + + // loop test + int test_count = 10; + gettimeofday(&start_time, NULL); + for (int i = 0; i < test_count; ++i) { + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + rknn_inputs_set(ctx, io_num.n_input, inputs); + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); +#if PERF_WITH_POST + post_process((uint8_t*)outputs[0].buf, (uint8_t*)outputs[1].buf, (uint8_t*)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); +#endif + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + } + gettimeofday(&stop_time, NULL); + printf("loop count = %d , average run %f ms\n", test_count, + (__get_us(stop_time) - __get_us(start_time)) / 1000.0 / test_count); + + // release + ret = rknn_destroy(ctx); + drm_buf_destroy(&drm_ctx, drm_fd, buf_fd, handle, drm_buf, actual_size); + + drm_deinit(&drm_ctx, drm_fd); + RGA_deinit(&rga_ctx); + if (model_data) { + free(model_data); + } + + if (resize_buf) { + free(resize_buf); + } + stbi_image_free(input_data); + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/postprocess.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/postprocess.cc new file mode 100644 index 0000000..793efd4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/postprocess.cc @@ -0,0 +1,328 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "postprocess.h" + + +#define LABEL_NALE_TXT_PATH "./model/coco_80_labels_list.txt" + +static char* labels[OBJ_CLASS_NUM]; + +const int anchor0[6] = {10, 13, 16, 30, 33, 23}; +const int anchor1[6] = {30, 61, 62, 45, 59, 119}; +const int anchor2[6] = {116, 90, 156, 198, 373, 326}; + +inline static int clamp(float val, int min, int max) { return val > min ? (val < max ? val : max) : min; } + +char* readLine(FILE* fp, char* buffer, int* len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char*)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) { + buff_len++; + void* tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) { + free(buffer); + return NULL; // Out of memory + } + buffer = (char*)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char* fileName, char* lines[], int max_line) +{ + FILE* file = fopen(fileName, "r"); + char* s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + +int loadLabelName(const char* locationFilename, char* label[]) +{ + printf("loadLabelName %s\n", locationFilename); + readLines(locationFilename, label, OBJ_CLASS_NUM); + return 0; +} + +static float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, + float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1) + 1.0); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1) + 1.0); + float i = w * h; + float u = (xmax0 - xmin0 + 1.0) * (ymax0 - ymin0 + 1.0) + (xmax1 - xmin1 + 1.0) * (ymax1 - ymin1 + 1.0) - i; + return u <= 0.f ? 0.f : (i / u); +} + +static int nms(int validCount, std::vector& outputLocations, std::vector classIds, std::vector& order, + int filterId, float threshold) +{ + for (int i = 0; i < validCount; ++i) { + if (order[i] == -1 || classIds[i] != filterId) { + continue; + } + int n = order[i]; + for (int j = i + 1; j < validCount; ++j) { + int m = order[j]; + if (m == -1 || classIds[i] != filterId) { + continue; + } + float xmin0 = outputLocations[n * 4 + 0]; + float ymin0 = outputLocations[n * 4 + 1]; + float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2]; + float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3]; + + float xmin1 = outputLocations[m * 4 + 0]; + float ymin1 = outputLocations[m * 4 + 1]; + float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2]; + float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou > threshold) { + order[j] = -1; + } + } + } + return 0; +} + +static int quick_sort_indice_inverse(std::vector& input, int left, int right, std::vector& indices) +{ + float key; + int key_index; + int low = left; + int high = right; + if (left < right) { + key_index = indices[left]; + key = input[left]; + while (low < high) { + while (low < high && input[high] <= key) { + high--; + } + input[low] = input[high]; + indices[low] = indices[high]; + while (low < high && input[low] >= key) { + low++; + } + input[high] = input[low]; + indices[high] = indices[low]; + } + input[low] = key; + indices[low] = key_index; + quick_sort_indice_inverse(input, left, low - 1, indices); + quick_sort_indice_inverse(input, low + 1, right, indices); + } + return low; +} + +static float sigmoid(float x) { return 1.0 / (1.0 + expf(-x)); } + +static float unsigmoid(float y) { return -1.0 * logf((1.0 / y) - 1.0); } + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + return f; +} + +static uint8_t qnt_f32_to_affine(float f32, uint32_t zp, float scale) +{ + float dst_val = (f32 / scale) + zp; + uint8_t res = (uint8_t)__clip(dst_val, 0, 255); + return res; +} + +static float deqnt_affine_to_f32(uint8_t qnt, uint32_t zp, float scale) { return ((float)qnt - (float)zp) * scale; } + +static int process(uint8_t* input, int* anchor, int grid_h, int grid_w, int height, int width, int stride, + std::vector& boxes, std::vector& objProbs, std::vector& classId, float threshold, + uint32_t zp, float scale) +{ + int validCount = 0; + int grid_len = grid_h * grid_w; + float thres = unsigmoid(threshold); + uint8_t thres_u8 = qnt_f32_to_affine(thres, zp, scale); + for (int a = 0; a < 3; a++) { + for (int i = 0; i < grid_h; i++) { + for (int j = 0; j < grid_w; j++) { + uint8_t box_confidence = input[(PROP_BOX_SIZE * a + 4) * grid_len + i * grid_w + j]; + if (box_confidence >= thres_u8) { + int offset = (PROP_BOX_SIZE * a) * grid_len + i * grid_w + j; + uint8_t* in_ptr = input + offset; + float box_x = sigmoid(deqnt_affine_to_f32(*in_ptr, zp, scale)) * 2.0 - 0.5; + float box_y = sigmoid(deqnt_affine_to_f32(in_ptr[grid_len], zp, scale)) * 2.0 - 0.5; + float box_w = sigmoid(deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale)) * 2.0; + float box_h = sigmoid(deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale)) * 2.0; + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w = box_w * box_w * (float)anchor[a * 2]; + box_h = box_h * box_h * (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + + uint8_t maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < OBJ_CLASS_NUM; ++k) { + uint8_t prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) { + maxClassId = k; + maxClassProbs = prob; + } + } + objProbs.push_back(sigmoid(deqnt_affine_to_f32(maxClassProbs, zp, scale))); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + return validCount; +} + +int post_process(uint8_t* input0, uint8_t* input1, uint8_t* input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector& qnt_zps, std::vector& qnt_scales, detect_result_group_t* group) +{ + static int init = -1; + if (init == -1) { + int ret = 0; + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) { + return -1; + } + + init = 0; + } + memset(group, 0, sizeof(detect_result_group_t)); + + std::vector filterBoxes; + std::vector objProbs; + std::vector classId; + + // stride 8 + int stride0 = 8; + int grid_h0 = model_in_h / stride0; + int grid_w0 = model_in_w / stride0; + int validCount0 = 0; + validCount0 = process(input0, (int*)anchor0, grid_h0, grid_w0, model_in_h, model_in_w, stride0, filterBoxes, objProbs, + classId, conf_threshold, qnt_zps[0], qnt_scales[0]); + + // stride 16 + int stride1 = 16; + int grid_h1 = model_in_h / stride1; + int grid_w1 = model_in_w / stride1; + int validCount1 = 0; + validCount1 = process(input1, (int*)anchor1, grid_h1, grid_w1, model_in_h, model_in_w, stride1, filterBoxes, objProbs, + classId, conf_threshold, qnt_zps[1], qnt_scales[1]); + + // stride 32 + int stride2 = 32; + int grid_h2 = model_in_h / stride2; + int grid_w2 = model_in_w / stride2; + int validCount2 = 0; + validCount2 = process(input2, (int*)anchor2, grid_h2, grid_w2, model_in_h, model_in_w, stride2, filterBoxes, objProbs, + classId, conf_threshold, qnt_zps[2], qnt_scales[2]); + + int validCount = validCount0 + validCount1 + validCount2; + // no object detect + if (validCount <= 0) { + return 0; + } + + std::vector indexArray; + for (int i = 0; i < validCount; ++i) { + indexArray.push_back(i); + } + + quick_sort_indice_inverse(objProbs, 0, validCount - 1, indexArray); + + std::set class_set(std::begin(classId), std::end(classId)); + + for (auto c : class_set) { + nms(validCount, filterBoxes, classId, indexArray, c, nms_threshold); + } + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) { + if (indexArray[i] == -1 || last_count >= OBJ_NUMB_MAX_SIZE) { + continue; + } + int n = indexArray[i]; + + float x1 = filterBoxes[n * 4 + 0]; + float y1 = filterBoxes[n * 4 + 1]; + float x2 = x1 + filterBoxes[n * 4 + 2]; + float y2 = y1 + filterBoxes[n * 4 + 3]; + int id = classId[n]; + float obj_conf = objProbs[i]; + + group->results[last_count].box.left = (int)(clamp(x1, 0, model_in_w) / scale_w); + group->results[last_count].box.top = (int)(clamp(y1, 0, model_in_h) / scale_h); + group->results[last_count].box.right = (int)(clamp(x2, 0, model_in_w) / scale_w); + group->results[last_count].box.bottom = (int)(clamp(y2, 0, model_in_h) / scale_h); + group->results[last_count].prop = obj_conf; + char* label = labels[id]; + strncpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("result %2d: (%4d, %4d, %4d, %4d), %s\n", i, group->results[last_count].box.left, + // group->results[last_count].box.top, + // group->results[last_count].box.right, group->results[last_count].box.bottom, label); + last_count++; + } + group->count = last_count; + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/rga_func.c b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/rga_func.c new file mode 100644 index 0000000..c9e8a90 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_yolov5_demo/src/rga_func.c @@ -0,0 +1,108 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rga_func.h" + +int RGA_init(rga_context* rga_ctx) +{ + rga_ctx->rga_handle = dlopen("/usr/lib/librga.so", RTLD_LAZY); + if (!rga_ctx->rga_handle) { + printf("dlopen /usr/lib/librga.so failed\n"); + return -1; + } + rga_ctx->init_func = (FUNC_RGA_INIT)dlsym(rga_ctx->rga_handle, "c_RkRgaInit"); + rga_ctx->deinit_func = (FUNC_RGA_DEINIT)dlsym(rga_ctx->rga_handle, "c_RkRgaDeInit"); + rga_ctx->blit_func = (FUNC_RGA_BLIT)dlsym(rga_ctx->rga_handle, "c_RkRgaBlit"); + rga_ctx->init_func(); + return 0; +} + +void img_resize_fast(rga_context* rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h) +{ + // printf("rga use fd, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = src_fd; + src.mmuFlag = 1; + // src.virAddr = (void *)psrc; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 0; + +#if defined(__arm__) + dst.phyAddr = (void*)((uint32_t)dst_phys); +#else + dst.phyAddr = (void*)dst_phys; +#endif + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +void img_resize_slow(rga_context* rga_ctx, void* src_virt, int src_w, int src_h, void* dst_virt, int dst_w, int dst_h) +{ + // printf("rga use virtual, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = -1; + src.mmuFlag = 1; + src.virAddr = (void*)src_virt; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 1; + dst.virAddr = dst_virt; + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +int RGA_deinit(rga_context* rga_ctx) +{ + if (rga_ctx->rga_handle) { + dlclose(rga_ctx->rga_handle); + rga_ctx->rga_handle = NULL; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/CMakeLists.txt new file mode 100644 index 0000000..cdcfc38 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_zero_copy_demo_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s -O3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s -O3") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rga +set(RGA_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/rga) +include_directories(${RGA_DIR}/include) + +# drm +set(DRM_DIR ${CMAKE_SOURCE_DIR}/../3rdparty/drm) +include_directories(${DRM_DIR}/include) +include_directories(${DRM_DIR}/include/libdrm) + +include_directories(${CMAKE_SOURCE_DIR}/include) + +# rknn api +set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../librknn_api) +include_directories(${RKNN_API_PATH}/include) +set(RKNN_API_LIB ${RKNN_API_PATH}/${LIB_ARCH}/librknn_api.so) + +#stb +include_directories(${CMAKE_SOURCE_DIR}/../3rdparty/) + +set(CMAKE_INSTALL_RPATH "lib") + +add_executable(rknn_zero_copy_demo + src/drm_func.c + src/rga_func.c + src/postprocess.cc + src/main.cc + ) + +target_link_libraries(rknn_zero_copy_demo + ${RKNN_API_LIB} + dl +) + +# install target and libraries +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_zero_copy_demo) +install(TARGETS rknn_zero_copy_demo DESTINATION ./) +install(DIRECTORY model DESTINATION ./) +install(PROGRAMS ${RKNN_API_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/README.md b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/README.md new file mode 100644 index 0000000..500cb9b --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/README.md @@ -0,0 +1,88 @@ +# Zero copy demo + +In specific case, the number of input data copies can be reduced to 0, that is, zero copy. For example, when the RKNN model is asymmetric quantization, the quantization data type is uint8, the mean value of the 3 channels is the same integer and the scaling factor is the same, the normalization and quantization can be omitted. + +This demo compares the performance difference between zero-copy and normal process inference. + +```txt +a. zero-copy inference uses the "rknn_inputs_map" interface + +b. normal inference uses the "rknn_inputs_set" interface. +``` + +In the "model" directory, models without NHWC suffix have input in NCHW format, and models with NHWC suffix have input in NHWC format. The model with NHWC suffix is ​​exported using rknn-toolkit by adding the following parameters + +```python +rknn.config(force_builtin_perm=True) +``` + +Note: if it shows "**get unvalid input physical address, please extend in/out memory space**", you may need to modify the size of **CMA** in the **kernel's dts**, such as: + +``` +diff --git a/arch/arm/boot/dts/rv1126.dtsi b/arch/arm/boot/dts/rv1126.dtsi +index f5f0a07..1d0487c 100644 +--- a/arch/arm/boot/dts/rv1126.dtsi ++++ b/arch/arm/boot/dts/rv1126.dtsi +@@ -362,11 +362,17 @@ + #size-cells = <1>; + ranges; + ++ nouse@0 { ++ reg = <0x00000000 0x4000>; ++ no-map; ++ }; ++ ++ + linux,cma { + compatible = "shared-dma-pool"; + inactive; + reusable; +- size = <0x800000>; ++ size = <0x8000000>; + linux,cma-default; + }; + +``` + +This patch is only for RV1109/RV1126,if you use RK1808,you need to select the appropriate dts file to modify. + +## Build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +```sh +./build.sh +``` + +## Install + +Copy install/rknn_zero_copy_demo to the devices under /userdata/. + +- If you use rockchip's evb board, you can use the following way: + +Connect device and push the program and rknn model to `/userdata` + +```sh +adb push install/rknn_zero_copy_demo /userdata/ +``` + +- If your board has sshd service, you can use scp or other methods to copy the program and rknn model to the board. + +## Run + +```sh +adb shell +cd /userdata/rknn_zero_copy_demo/ +``` + +- RK1808/RK1806 + +```sh +./run_rk180x.sh +``` + +- RV1109/RV1126 + +```sh +./run_rv1109_rv1126.sh +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/build.sh new file mode 100644 index 0000000..01da901 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/build.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +# GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - + +cp run_rk180x.sh install/rknn_zero_copy_demo/ +cp run_rv1109_rv1126.sh install/rknn_zero_copy_demo/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/drm_func.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/drm_func.h new file mode 100644 index 0000000..0a9e3b3 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/drm_func.h @@ -0,0 +1,53 @@ +#ifndef __DRM_FUNC_H__ +#define __DRM_FUNC_H__ +#include +#include +#include +#include +#include // open function +#include // close function +#include +#include + + +#include +#include "libdrm/drm_fourcc.h" +#include "xf86drm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (* FUNC_DRM_IOCTL)(int fd, unsigned long request, void *arg); + +typedef struct _drm_context{ + void *drm_handle; + FUNC_DRM_IOCTL io_func; +} drm_context; + +/* memory type definitions. */ +enum drm_rockchip_gem_mem_type +{ + /* Physically Continuous memory and used as default. */ + ROCKCHIP_BO_CONTIG = 1 << 0, + /* cachable mapping. */ + ROCKCHIP_BO_CACHABLE = 1 << 1, + /* write-combine mapping. */ + ROCKCHIP_BO_WC = 1 << 2, + ROCKCHIP_BO_SECURE = 1 << 3, + ROCKCHIP_BO_MASK = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_CACHABLE | + ROCKCHIP_BO_WC | ROCKCHIP_BO_SECURE +}; + +int drm_init(drm_context *drm_ctx); + +void* drm_buf_alloc(drm_context *drm_ctx,int drm_fd, int TexWidth, int TexHeight,int bpp,int *fd,unsigned int *handle,size_t *actual_size); + +int drm_buf_destroy(drm_context *drm_ctx,int drm_fd,int buf_fd, int handle,void *drm_buf,size_t size); + +void drm_deinit(drm_context *drm_ctx, int drm_fd); + +#ifdef __cplusplus +} +#endif +#endif /*__DRM_FUNC_H__*/ \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/postprocess.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/postprocess.h new file mode 100644 index 0000000..e474505 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/postprocess.h @@ -0,0 +1,40 @@ +#ifndef _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ +#define _RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ + +#include + +#define OBJ_NAME_MAX_SIZE 16 +#define OBJ_NUMB_MAX_SIZE 64 +#define OBJ_CLASS_NUM 80 +#define NMS_THRESH 0.6 +#define BOX_THRESH 0.5 +#define PROP_BOX_SIZE (5+OBJ_CLASS_NUM) + +typedef struct _BOX_RECT +{ + int left; + int right; + int top; + int bottom; +} BOX_RECT; + +typedef struct __detect_result_t +{ + char name[OBJ_NAME_MAX_SIZE]; + BOX_RECT box; + float prop; +} detect_result_t; + +typedef struct _detect_result_group_t +{ + int id; + int count; + detect_result_t results[OBJ_NUMB_MAX_SIZE]; +} detect_result_group_t; + +int post_process(uint8_t *input0, uint8_t *input1, uint8_t *input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector &qnt_zps, std::vector &qnt_scales, + detect_result_group_t *group); + +#endif //_RKNN_ZERO_COPY_DEMO_POSTPROCESS_H_ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/rga_func.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/rga_func.h new file mode 100644 index 0000000..beeb441 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/include/rga_func.h @@ -0,0 +1,33 @@ +#ifndef __RGA_FUNC_H__ +#define __RGA_FUNC_H__ + +#include +#include "RgaApi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(* FUNC_RGA_INIT)(); +typedef void(* FUNC_RGA_DEINIT)(); +typedef int(* FUNC_RGA_BLIT)(rga_info_t *, rga_info_t *, rga_info_t *); + +typedef struct _rga_context{ + void *rga_handle; + FUNC_RGA_INIT init_func; + FUNC_RGA_DEINIT deinit_func; + FUNC_RGA_BLIT blit_func; +} rga_context; + +int RGA_init(rga_context* rga_ctx); + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h); + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h); + +int RGA_deinit(rga_context* rga_ctx); + +#ifdef __cplusplus +} +#endif +#endif/*__RGA_FUNC_H__*/ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/bus.bmp b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/bus.bmp new file mode 100644 index 0000000..82df079 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/bus.bmp differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/coco_80_labels_list.txt b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/coco_80_labels_list.txt new file mode 100644 index 0000000..941cb4e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/coco_80_labels_list.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +dining table +toilet +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x.rknn new file mode 100644 index 0000000..f8170d3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x_NHWC.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x_NHWC.rknn new file mode 100644 index 0000000..0b8c68c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rk180x/yolov5s_relu_rk180x_NHWC.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126.rknn new file mode 100644 index 0000000..eba83c6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_NHWC.rknn b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_NHWC.rknn new file mode 100644 index 0000000..80f2a2e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/model/rv1109_rv1126/yolov5s_relu_rv1109_rv1126_NHWC.rknn differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rk180x.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rk180x.sh new file mode 100644 index 0000000..d74398a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rk180x.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +chip_dir="rk180x" +echo '********************* run zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rk180x_NHWC.rknn model/bus.bmp 1 +echo '********************* run non-zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rk180x.rknn model/bus.bmp 0 + + + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rv1109_rv1126.sh b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rv1109_rv1126.sh new file mode 100644 index 0000000..0701370 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/run_rv1109_rv1126.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +chip_dir="rv1109_rv1126" +echo '********************* run zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rv1109_rv1126_NHWC.rknn model/bus.bmp 1 + +echo '********************* run non-zero-copy model *********************' +./rknn_zero_copy_demo model/${chip_dir}/yolov5s_relu_rv1109_rv1126.rknn model/bus.bmp 0 + + + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/drm_func.c b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/drm_func.c new file mode 100644 index 0000000..5811922 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/drm_func.c @@ -0,0 +1,175 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "drm_func.h" +#include + +int drm_init(drm_context *drm_ctx) +{ + static const char *card = "/dev/dri/card0"; + int flag = O_RDWR; + int drm_fd = -1; + + drm_fd = open(card, flag); + if (drm_fd < 0) + { + printf("failed to open %s\n", card); + return -1; + } + + drm_ctx->drm_handle = dlopen("/usr/lib/libdrm.so", RTLD_LAZY); + if (!drm_ctx->drm_handle) + { + printf("failed to dlopen /usr/lib/libdrm.so\n"); + drm_deinit(drm_ctx, drm_fd); + return -1; + } + + drm_ctx->io_func = (FUNC_DRM_IOCTL)dlsym(drm_ctx->drm_handle, "drmIoctl"); + if (drm_ctx->io_func == NULL) + { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + drm_deinit(drm_ctx, drm_fd); + printf("failed to dlsym drmIoctl\n"); + return -1; + } + return drm_fd; +} + +void drm_deinit(drm_context *drm_ctx, int drm_fd) +{ + if (drm_ctx->drm_handle) + { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + } + if (drm_fd > 0) + { + close(drm_fd); + } +} + +void *drm_buf_alloc(drm_context *drm_ctx, int drm_fd, int TexWidth, int TexHeight, int bpp, int *fd, unsigned int *handle, size_t *actual_size) +{ + int ret; + if (drm_ctx == NULL) + { + printf("drm context is unvalid\n"); + return NULL; + } + char *map = NULL; + + void *vir_addr = NULL; + struct drm_prime_handle fd_args; + struct drm_mode_map_dumb mmap_arg; + struct drm_mode_destroy_dumb destory_arg; + + struct drm_mode_create_dumb alloc_arg; + + memset(&alloc_arg, 0, sizeof(alloc_arg)); + alloc_arg.bpp = bpp; + alloc_arg.width = TexWidth; + alloc_arg.height = TexHeight; + // alloc_arg.flags = ROCKCHIP_BO_CONTIG; + + //获取handle和size + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg); + if (ret) + { + printf("failed to create dumb buffer: %s\n", strerror(errno)); + return NULL; + } + if (handle != NULL) + { + *handle = alloc_arg.handle; + } + if (actual_size != NULL) + { + *actual_size = alloc_arg.size; + } + // printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n",alloc_arg.width,alloc_arg.height,alloc_arg.bpp,alloc_arg.size); + // printf("out handle= %d\n",alloc_arg.handle); + + //获取fd + memset(&fd_args, 0, sizeof(fd_args)); + fd_args.fd = -1; + fd_args.handle = alloc_arg.handle; + ; + fd_args.flags = 0; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args); + if (ret) + { + printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle); + return NULL; + } + // printf("out fd = %d, drm fd: %d\n",fd_args.fd,drm_fd); + if (fd != NULL) + { + *fd = fd_args.fd; + } + + //获取虚拟地址 + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = alloc_arg.handle; + + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg); + if (ret) + { + printf("failed to create map dumb: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + vir_addr = map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset); + if (map == MAP_FAILED) + { + printf("failed to mmap buffer: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + // printf("alloc map=%x \n",map); + return vir_addr; +destory_dumb: + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = alloc_arg.handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d\n", ret); + return vir_addr; +} + +int drm_buf_destroy(drm_context *drm_ctx, int drm_fd, int buf_fd, int handle, void *drm_buf, size_t size) +{ + int ret = -1; + if (drm_buf == NULL) + { + printf("drm buffer is NULL\n"); + return -1; + } + + munmap(drm_buf, size); + + struct drm_mode_destroy_dumb destory_arg; + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno)); + if (buf_fd > 0) + { + close(buf_fd); + } + + return ret; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/main.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/main.cc new file mode 100644 index 0000000..60ce6c8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/main.cc @@ -0,0 +1,500 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#define _BASETSD_H + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include + +#undef cimg_display +#define cimg_display 0 +#include "CImg/CImg.h" + +#include "drm_func.h" +#include "rga_func.h" +#include "rknn_api.h" +#include "postprocess.h" + +#define PERF_WITH_POST 1 + +using namespace cimg_library; + +/*------------------------------------------- + Functions +-------------------------------------------*/ + +inline const char *get_type_string(rknn_tensor_type type) +{ + switch (type) + { + case RKNN_TENSOR_FLOAT32: + return "FP32"; + case RKNN_TENSOR_FLOAT16: + return "FP16"; + case RKNN_TENSOR_INT8: + return "INT8"; + case RKNN_TENSOR_UINT8: + return "UINT8"; + case RKNN_TENSOR_INT16: + return "INT16"; + default: + return "UNKNOW"; + } +} + +inline const char *get_qnt_type_string(rknn_tensor_qnt_type type) +{ + switch (type) + { + case RKNN_TENSOR_QNT_NONE: + return "NONE"; + case RKNN_TENSOR_QNT_DFP: + return "DFP"; + case RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + return "AFFINE"; + default: + return "UNKNOW"; + } +} + +inline const char *get_format_string(rknn_tensor_format fmt) +{ + switch (fmt) + { + case RKNN_TENSOR_NCHW: + return "NCHW"; + case RKNN_TENSOR_NHWC: + return "NHWC"; + default: + return "UNKNOW"; + } +} + +static void dump_tensor_attr(rknn_tensor_attr *attr) +{ + printf(" index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, " + "zp=%d, scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], attr->dims[1], attr->dims[0], + attr->n_elems, attr->size, get_format_string(attr->fmt), get_type_string(attr->type), + get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale); +} + +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static unsigned char *load_data(FILE *fp, size_t ofst, size_t sz) +{ + unsigned char *data; + int ret; + + data = NULL; + + if (NULL == fp) + { + return NULL; + } + + ret = fseek(fp, ofst, SEEK_SET); + if (ret != 0) + { + printf("blob seek failure.\n"); + return NULL; + } + + data = (unsigned char *)malloc(sz); + if (data == NULL) + { + printf("buffer malloc failure.\n"); + return NULL; + } + ret = fread(data, 1, sz, fp); + return data; +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + + FILE *fp; + unsigned char *data; + + fp = fopen(filename, "rb"); + if (NULL == fp) + { + printf("Open file %s failed.\n", filename); + return NULL; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + + data = load_data(fp, 0, size); + + fclose(fp); + + *model_size = size; + return data; +} + +static int saveFloat(const char *file_name, float *output, int element_size) +{ + FILE *fp; + fp = fopen(file_name, "w"); + for (int i = 0; i < element_size; i++) + { + fprintf(fp, "%.6f\n", output[i]); + } + fclose(fp); + return 0; +} + +static unsigned char *load_image(const char *image_path, int *org_height, int *org_width, int *org_ch, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image failed!\n"); + return NULL; + } + *org_width = width; + *org_height = height; + *org_ch = channel; + + return image_data; +} + +/*------------------------------------------- + Main Functions +-------------------------------------------*/ +int main(int argc, char **argv) +{ + int status = 0; + char *model_name = NULL; + rknn_context ctx; + int is_map = 0; + rknn_tensor_mem in_mem[1]; + void *drm_buf = NULL; + int drm_fd = -1; + int buf_fd = -1; // converted from buffer handle + unsigned int handle; + size_t actual_size = 0; + int img_width = 0; + int img_height = 0; + int img_channel = 0; + rga_context rga_ctx; + drm_context drm_ctx; + const float nms_threshold = NMS_THRESH; + const float box_conf_threshold = BOX_THRESH; + struct timeval start_time, stop_time; + int ret; + memset(&rga_ctx, 0, sizeof(rga_context)); + memset(&drm_ctx, 0, sizeof(drm_context)); + + if (argc != 4) + { + printf("Note: rknn model need meet zero-copy condition: 3-channel with same integer means and same scales\n"); + printf("Usage: %s \n", argv[0]); + printf("flag:\n"); + printf("\t 0: run builtin_permute=False rknn model, perform rknn_inputs_set\n"); + printf("\t 1: run builtin_permute=True rknn model, perform rknn_inputs_map\n"); + return -1; + } + + printf("post process config: box_conf_threshold = %.2f, nms_threshold = %.2f\n", + box_conf_threshold, nms_threshold); + model_name = (char *)argv[1]; + char *image_name = argv[2]; + is_map = atoi(argv[3]); + + if (strstr(image_name, ".jpg") != NULL || strstr(image_name, ".png") != NULL) + { + printf("Error: read %s failed! only support .bmp format image\n", image_name); + return -1; + } + + /* Create the neural network */ + printf("Loading mode...\n"); + int model_data_size = 0; + unsigned char *model_data = load_model(model_name, &model_data_size); + ret = rknn_init(&ctx, model_data, model_data_size, 0); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + sizeof(rknn_sdk_version)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("sdk version: %s driver version: %s\n", version.api_version, + version.drv_version); + + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, + io_num.n_output); + + rknn_tensor_attr input_attrs[io_num.n_input]; + memset(input_attrs, 0, sizeof(input_attrs)); + for (int i = 0; i < io_num.n_input; i++) + { + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + sizeof(rknn_tensor_attr)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + dump_tensor_attr(&(input_attrs[i])); + } + + rknn_tensor_attr output_attrs[io_num.n_output]; + memset(output_attrs, 0, sizeof(output_attrs)); + for (int i = 0; i < io_num.n_output; i++) + { + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + sizeof(rknn_tensor_attr)); + dump_tensor_attr(&(output_attrs[i])); + } + + int channel = 3; + int width = 0; + int height = 0; + if (input_attrs[0].fmt == RKNN_TENSOR_NCHW) + { + printf("model is NCHW input fmt\n"); + width = input_attrs[0].dims[0]; + height = input_attrs[0].dims[1]; + } + else + { + printf("model is NHWC input fmt\n"); + width = input_attrs[0].dims[1]; + height = input_attrs[0].dims[2]; + } + + printf("model input height=%d, width=%d, channel=%d\n", height, width, + channel); + + // Load image + CImg img(image_name); + unsigned char *input_data = NULL; + input_data = load_image(image_name, &img_height, &img_width, &img_channel, &input_attrs[0]); + if (!input_data) + { + return -1; + } + + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = width * height * channel; + inputs[0].fmt = RKNN_TENSOR_NHWC; + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) + { + outputs[i].want_float = 0; + } + + // DRM alloc buffer + drm_fd = drm_init(&drm_ctx); + drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, img_width, img_height, channel * 8, + &buf_fd, &handle, &actual_size); + memcpy(drm_buf, input_data, img_width * img_height * channel); + void *resize_buf = malloc(height * width * channel); + + // init rga context + RGA_init(&rga_ctx); + if (is_map == 0) + { + inputs[0].pass_through = 0; + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + inputs[0].buf = resize_buf; + gettimeofday(&start_time, NULL); + rknn_inputs_set(ctx, io_num.n_input, inputs); + } + else + { + gettimeofday(&start_time, NULL); + ret = rknn_inputs_map(ctx, io_num.n_input, in_mem); + printf("input virt_addr = %p, phys_addr = 0x%llx, fd = %d, size = %d\n", + in_mem[0].logical_addr, in_mem[0].physical_addr, in_mem[0].fd, + in_mem[0].size); + if (in_mem[0].physical_addr == 0xffffffffffffffff) + { + printf("get unvalid input physical address, please extend in/out memory space\n"); + exit(-1); + } + else + { + // rga process by physical addr + img_resize_fast(&rga_ctx, buf_fd, img_width, img_height, in_mem[0].physical_addr, width, height); + } + rknn_inputs_sync(ctx, io_num.n_input, in_mem); + } + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + gettimeofday(&stop_time, NULL); + printf("once run use %f ms\n", + (__get_us(stop_time) - __get_us(start_time)) / 1000); + + //post process + float scale_w = (float)width / img_width; + float scale_h = (float)height / img_height; + + detect_result_group_t detect_result_group; + std::vector out_scales; + std::vector out_zps; + for (int i = 0; i < io_num.n_output; ++i) + { + out_scales.push_back(output_attrs[i].scale); + out_zps.push_back(output_attrs[i].zp); + } + post_process((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); + + // Draw Objects + char text[256]; + const unsigned char blue[] = {0, 0, 255}; + const unsigned char white[] = {255, 255, 255}; + for (int i = 0; i < detect_result_group.count; i++) + { + detect_result_t *det_result = &(detect_result_group.results[i]); + sprintf(text, "%s %.2f", det_result->name, det_result->prop); + printf("%s @ (%d %d %d %d) %f\n", + det_result->name, + det_result->box.left, det_result->box.top, det_result->box.right, det_result->box.bottom, + det_result->prop); + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + //draw box + img.draw_rectangle(x1, y1, x2, y2, blue, 1, ~0U); + img.draw_text(x1, y1 - 12, text, white); + } + img.save("./out.bmp"); + + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + + // loop test + int test_count = 10; + gettimeofday(&start_time, NULL); + if (is_map == 0) + { + for (int i = 0; i < test_count; ++i) + { + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, width, height); + rknn_inputs_set(ctx, io_num.n_input, inputs); + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); +#if PERF_WITH_POST + post_process((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); +#endif + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + } + } + else + { + for (int i = 0; i < test_count; ++i) + { + img_resize_fast(&rga_ctx, buf_fd, img_width, img_height, in_mem[0].physical_addr, width, height); + rknn_inputs_sync(ctx, io_num.n_input, in_mem); + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); +#if PERF_WITH_POST + post_process((uint8_t *)outputs[0].buf, (uint8_t *)outputs[1].buf, (uint8_t *)outputs[2].buf, height, width, + box_conf_threshold, nms_threshold, scale_w, scale_h, out_zps, out_scales, &detect_result_group); +#endif + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + } + } + gettimeofday(&stop_time, NULL); + printf("run loop count = %d , average time: %f ms\n", test_count, + (__get_us(stop_time) - __get_us(start_time)) / 1000.0 / test_count); + + // release + if (is_map) + { + ret = rknn_inputs_unmap(ctx, io_num.n_input, in_mem); + } + ret = rknn_destroy(ctx); + drm_buf_destroy(&drm_ctx, drm_fd, buf_fd, handle, drm_buf, actual_size); + + drm_deinit(&drm_ctx, drm_fd); + RGA_deinit(&rga_ctx); + if (model_data) + { + free(model_data); + } + + if (resize_buf) + { + free(resize_buf); + } + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/postprocess.cc b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/postprocess.cc new file mode 100644 index 0000000..adf6ea8 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/postprocess.cc @@ -0,0 +1,366 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include "postprocess.h" +#include +#define LABEL_NALE_TXT_PATH "./model/coco_80_labels_list.txt" + +static char *labels[OBJ_CLASS_NUM]; + +const int anchor0[6] = {10, 13, 16, 30, 33, 23}; +const int anchor1[6] = {30, 61, 62, 45, 59, 119}; +const int anchor2[6] = {116, 90, 156, 198, 373, 326}; + +inline static int clamp(float val, int min, int max) +{ + return val > min ? (val < max ? val : max) : min; +} + +char *readLine(FILE *fp, char *buffer, int *len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char *)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) + { + buff_len++; + void *tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) + { + free(buffer); + return NULL; // Out of memory + } + buffer = (char *)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) + { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char *fileName, char *lines[], int max_line) +{ + FILE *file = fopen(fileName, "r"); + char *s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) + { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + +int loadLabelName(const char *locationFilename, char *label[]) +{ + printf("loadLabelName %s\n", locationFilename); + readLines(locationFilename, label, OBJ_CLASS_NUM); + return 0; +} + +static float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, float ymax1) +{ + float w = fmax(0.f, fmin(xmax0, xmax1) - fmax(xmin0, xmin1) + 1.0); + float h = fmax(0.f, fmin(ymax0, ymax1) - fmax(ymin0, ymin1) + 1.0); + float i = w * h; + float u = (xmax0 - xmin0 + 1.0) * (ymax0 - ymin0 + 1.0) + (xmax1 - xmin1 + 1.0) * (ymax1 - ymin1 + 1.0) - i; + return u <= 0.f ? 0.f : (i / u); +} + +static int nms(int validCount, std::vector &outputLocations, std::vector classIds, std::vector &order, int filterId, float threshold) +{ + for (int i = 0; i < validCount; ++i) + { + if (order[i] == -1 || classIds[i] != filterId) + { + continue; + } + int n = order[i]; + for (int j = i + 1; j < validCount; ++j) + { + int m = order[j]; + if (m == -1 || classIds[i] != filterId) + { + continue; + } + float xmin0 = outputLocations[n * 4 + 0]; + float ymin0 = outputLocations[n * 4 + 1]; + float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2]; + float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3]; + + float xmin1 = outputLocations[m * 4 + 0]; + float ymin1 = outputLocations[m * 4 + 1]; + float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2]; + float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou > threshold) + { + order[j] = -1; + } + } + } + return 0; +} + +static int quick_sort_indice_inverse( + std::vector &input, + int left, + int right, + std::vector &indices) +{ + float key; + int key_index; + int low = left; + int high = right; + if (left < right) + { + key_index = indices[left]; + key = input[left]; + while (low < high) + { + while (low < high && input[high] <= key) + { + high--; + } + input[low] = input[high]; + indices[low] = indices[high]; + while (low < high && input[low] >= key) + { + low++; + } + input[high] = input[low]; + indices[high] = indices[low]; + } + input[low] = key; + indices[low] = key_index; + quick_sort_indice_inverse(input, left, low - 1, indices); + quick_sort_indice_inverse(input, low + 1, right, indices); + } + return low; +} + +static float sigmoid(float x) +{ + return 1.0 / (1.0 + expf(-x)); +} + +static float unsigmoid(float y) +{ + return -1.0 * logf((1.0 / y) - 1.0); +} + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + return f; +} + +static uint8_t qnt_f32_to_affine(float f32, uint32_t zp, float scale) +{ + float dst_val = (f32 / scale) + zp; + uint8_t res = (uint8_t)__clip(dst_val, 0, 255); + return res; +} + +static float deqnt_affine_to_f32(uint8_t qnt, uint32_t zp, float scale) +{ + return ((float)qnt - (float)zp) * scale; +} + +static int process(uint8_t *input, int *anchor, int grid_h, int grid_w, int height, int width, int stride, + std::vector &boxes, std::vector &objProbs, std::vector &classId, + float threshold, uint32_t zp, float scale) +{ + + int validCount = 0; + int grid_len = grid_h * grid_w; + float thres = unsigmoid(threshold); + uint8_t thres_u8 = qnt_f32_to_affine(thres, zp, scale); + for (int a = 0; a < 3; a++) + { + for (int i = 0; i < grid_h; i++) + { + for (int j = 0; j < grid_w; j++) + { + uint8_t box_confidence = input[(PROP_BOX_SIZE * a + 4) * grid_len + i * grid_w + j]; + if (box_confidence >= thres_u8) + { + int offset = (PROP_BOX_SIZE * a) * grid_len + i * grid_w + j; + uint8_t *in_ptr = input + offset; + float box_x = sigmoid(deqnt_affine_to_f32(*in_ptr, zp, scale)) * 2.0 - 0.5; + float box_y = sigmoid(deqnt_affine_to_f32(in_ptr[grid_len], zp, scale)) * 2.0 - 0.5; + float box_w = sigmoid(deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale)) * 2.0; + float box_h = sigmoid(deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale)) * 2.0; + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w = box_w * box_w * (float)anchor[a * 2]; + box_h = box_h * box_h * (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + + uint8_t maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < OBJ_CLASS_NUM; ++k) + { + uint8_t prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) + { + maxClassId = k; + maxClassProbs = prob; + } + } + objProbs.push_back(sigmoid(deqnt_affine_to_f32(maxClassProbs, zp, scale))); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + return validCount; +} + +int post_process(uint8_t *input0, uint8_t *input1, uint8_t *input2, int model_in_h, int model_in_w, + float conf_threshold, float nms_threshold, float scale_w, float scale_h, + std::vector &qnt_zps, std::vector &qnt_scales, + detect_result_group_t *group) +{ + static int init = -1; + if (init == -1) + { + int ret = 0; + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) + { + return -1; + } + + init = 0; + } + memset(group, 0, sizeof(detect_result_group_t)); + + std::vector filterBoxes; + std::vector objProbs; + std::vector classId; + + // stride 8 + int stride0 = 8; + int grid_h0 = model_in_h / stride0; + int grid_w0 = model_in_w / stride0; + int validCount0 = 0; + validCount0 = process(input0, (int *)anchor0, grid_h0, grid_w0, model_in_h, model_in_w, + stride0, filterBoxes, objProbs, classId, conf_threshold, qnt_zps[0], qnt_scales[0]); + + // stride 16 + int stride1 = 16; + int grid_h1 = model_in_h / stride1; + int grid_w1 = model_in_w / stride1; + int validCount1 = 0; + validCount1 = process(input1, (int *)anchor1, grid_h1, grid_w1, model_in_h, model_in_w, + stride1, filterBoxes, objProbs, classId, conf_threshold, qnt_zps[1], qnt_scales[1]); + + // stride 32 + int stride2 = 32; + int grid_h2 = model_in_h / stride2; + int grid_w2 = model_in_w / stride2; + int validCount2 = 0; + validCount2 = process(input2, (int *)anchor2, grid_h2, grid_w2, model_in_h, model_in_w, + stride2, filterBoxes, objProbs, classId, conf_threshold, qnt_zps[2], qnt_scales[2]); + + int validCount = validCount0 + validCount1 + validCount2; + // no object detect + if (validCount <= 0) + { + return 0; + } + + std::vector indexArray; + for (int i = 0; i < validCount; ++i) + { + indexArray.push_back(i); + } + + quick_sort_indice_inverse(objProbs, 0, validCount - 1, indexArray); + + std::set class_set(std::begin(classId), std::end(classId)); + + for (auto c : class_set) + { + nms(validCount, filterBoxes, classId, indexArray, c, nms_threshold); + } + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) + { + + if (indexArray[i] == -1 || last_count >= OBJ_NUMB_MAX_SIZE) + { + continue; + } + int n = indexArray[i]; + + float x1 = filterBoxes[n * 4 + 0]; + float y1 = filterBoxes[n * 4 + 1]; + float x2 = x1 + filterBoxes[n * 4 + 2]; + float y2 = y1 + filterBoxes[n * 4 + 3]; + int id = classId[n]; + float obj_conf = objProbs[i]; + + group->results[last_count].box.left = (int)(clamp(x1, 0, model_in_w) / scale_w); + group->results[last_count].box.top = (int)(clamp(y1, 0, model_in_h) / scale_h); + group->results[last_count].box.right = (int)(clamp(x2, 0, model_in_w) / scale_w); + group->results[last_count].box.bottom = (int)(clamp(y2, 0, model_in_h) / scale_h); + group->results[last_count].prop = obj_conf; + char *label = labels[id]; + strncpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("result %2d: (%4d, %4d, %4d, %4d), %s\n", i, group->results[last_count].box.left, group->results[last_count].box.top, + // group->results[last_count].box.right, group->results[last_count].box.bottom, label); + last_count++; + } + group->count = last_count; + + return 0; +} diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/rga_func.c b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/rga_func.c new file mode 100644 index 0000000..69caada --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/examples/rknn_zero_copy_demo/src/rga_func.c @@ -0,0 +1,114 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rga_func.h" + +int RGA_init(rga_context *rga_ctx) +{ + rga_ctx->rga_handle = dlopen("/usr/lib/librga.so", RTLD_LAZY); + if (!rga_ctx->rga_handle) + { + printf("dlopen /usr/lib/librga.so failed\n"); + return -1; + } + rga_ctx->init_func = (FUNC_RGA_INIT)dlsym(rga_ctx->rga_handle, "c_RkRgaInit"); + rga_ctx->deinit_func = (FUNC_RGA_DEINIT)dlsym(rga_ctx->rga_handle, "c_RkRgaDeInit"); + rga_ctx->blit_func = (FUNC_RGA_BLIT)dlsym(rga_ctx->rga_handle, "c_RkRgaBlit"); + rga_ctx->init_func(); + return 0; +} + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h) +{ + // printf("rga use fd, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) + { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = src_fd; + src.mmuFlag = 1; + // src.virAddr = (void *)psrc; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 0; + +#if defined(__arm__) + dst.phyAddr = (void *)((uint32_t)dst_phys); +#else + dst.phyAddr = (void *)dst_phys; +#endif + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) + { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h) +{ + // printf("rga use virtual, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) + { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = -1; + src.mmuFlag = 1; + src.virAddr = (void *)src_virt; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 1; + dst.virAddr = dst_virt; + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) + { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +int RGA_deinit(rga_context *rga_ctx) +{ + if(rga_ctx->rga_handle) + { + dlclose(rga_ctx->rga_handle); + rga_ctx->rga_handle = NULL; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h new file mode 100644 index 0000000..a114c1f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/include/rknn_api.h @@ -0,0 +1,504 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + + +#ifndef _RKNN_RUNTIME_H +#define _RKNN_RUNTIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + Definition of extended flag for rknn_init. +*/ +/* set high priority context. */ +#define RKNN_FLAG_PRIOR_HIGH 0x00000000 + +/* set medium priority context */ +#define RKNN_FLAG_PRIOR_MEDIUM 0x00000001 + +/* set low priority context. */ +#define RKNN_FLAG_PRIOR_LOW 0x00000002 + +/* asynchronous mode. + when enable, rknn_outputs_get will not block for too long because it directly retrieves the result of + the previous frame which can increase the frame rate on single-threaded mode, but at the cost of + rknn_outputs_get not retrieves the result of the current frame. + in multi-threaded mode you do not need to turn this mode on. */ +#define RKNN_FLAG_ASYNC_MASK 0x00000004 + +/* collect performance mode. + when enable, you can get detailed performance reports via rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, ...), + but it will reduce the frame rate. */ +#define RKNN_FLAG_COLLECT_PERF_MASK 0x00000008 + +/* + save pre-compile model. +*/ +#define RKNN_FLAG_PRECOMPILE_MASK 0x00000020 + +/* + Error code returned by the RKNN API. +*/ +#define RKNN_SUCC 0 /* execute succeed. */ +#define RKNN_ERR_FAIL -1 /* execute failed. */ +#define RKNN_ERR_TIMEOUT -2 /* execute timeout. */ +#define RKNN_ERR_DEVICE_UNAVAILABLE -3 /* device is unavailable. */ +#define RKNN_ERR_MALLOC_FAIL -4 /* memory malloc fail. */ +#define RKNN_ERR_PARAM_INVALID -5 /* parameter is invalid. */ +#define RKNN_ERR_MODEL_INVALID -6 /* model is invalid. */ +#define RKNN_ERR_CTX_INVALID -7 /* context is invalid. */ +#define RKNN_ERR_INPUT_INVALID -8 /* input is invalid. */ +#define RKNN_ERR_OUTPUT_INVALID -9 /* output is invalid. */ +#define RKNN_ERR_DEVICE_UNMATCH -10 /* the device is unmatch, please update rknn sdk + and npu driver/firmware. */ +#define RKNN_ERR_INCOMPATILE_PRE_COMPILE_MODEL -11 /* This RKNN model use pre_compile mode, but not compatible with current driver. */ +//add by chifred: for reporting optimization version bug info +#define RKNN_ERR_INCOMPATILE_OPTIMIZATION_LEVEL_VERSION -12 /* This RKNN model set optimization level, but not compatible with current driver. */ +#define RKNN_ERR_TARGET_PLATFORM_UNMATCH -13 /* This RKNN model set target platform, but not compatible with current platform. */ +//chifred add end +#define RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER -14 /* This RKNN model is not a pre-compiled model, but the npu driver is mini driver. */ + +/* + Definition for tensor +*/ +#define RKNN_MAX_DIMS 16 /* maximum dimension of tensor. */ +#define RKNN_MAX_NAME_LEN 256 /* maximum name lenth of tensor. */ + + + +#ifdef __arm__ +typedef uint32_t rknn_context; +#else +typedef uint64_t rknn_context; +#endif + +/* + The query command for rknn_query +*/ +typedef enum _rknn_query_cmd { + RKNN_QUERY_IN_OUT_NUM = 0, /* query the number of input & output tensor. */ + RKNN_QUERY_INPUT_ATTR, /* query the attribute of input tensor. */ + RKNN_QUERY_OUTPUT_ATTR, /* query the attribute of output tensor. */ + RKNN_QUERY_PERF_DETAIL, /* query the detail performance, need set + RKNN_FLAG_COLLECT_PERF_MASK when call rknn_init. */ + RKNN_QUERY_PERF_RUN, /* query the time of run. */ + RKNN_QUERY_SDK_VERSION, /* query the sdk & driver version */ + RKNN_QUERY_PRE_COMPILE, /* query the pre compile model */ + + RKNN_QUERY_CMD_MAX +} rknn_query_cmd; + +/* + the tensor data type. +*/ +typedef enum _rknn_tensor_type { + RKNN_TENSOR_FLOAT32 = 0, /* data type is float32. */ + RKNN_TENSOR_FLOAT16, /* data type is float16. */ + RKNN_TENSOR_INT8, /* data type is int8. */ + RKNN_TENSOR_UINT8, /* data type is uint8. */ + RKNN_TENSOR_INT16, /* data type is int16. */ + + RKNN_TENSOR_TYPE_MAX +} rknn_tensor_type; + +/* + the quantitative type. +*/ +typedef enum _rknn_tensor_qnt_type { + RKNN_TENSOR_QNT_NONE = 0, /* none. */ + RKNN_TENSOR_QNT_DFP, /* dynamic fixed point. */ + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC, /* asymmetric affine. */ + + RKNN_TENSOR_QNT_MAX +} rknn_tensor_qnt_type; + +/* + the tensor data format. +*/ +typedef enum _rknn_tensor_format { + RKNN_TENSOR_NCHW = 0, /* data format is NCHW. */ + RKNN_TENSOR_NHWC, /* data format is NHWC. */ + + RKNN_TENSOR_FORMAT_MAX +} rknn_tensor_format; + +/* + the information for RKNN_QUERY_IN_OUT_NUM. +*/ +typedef struct _rknn_input_output_num { + uint32_t n_input; /* the number of input. */ + uint32_t n_output; /* the number of output. */ +} rknn_input_output_num; + +/* + the information for RKNN_QUERY_INPUT_ATTR / RKNN_QUERY_OUTPUT_ATTR. +*/ +typedef struct _rknn_tensor_attr { + uint32_t index; /* input parameter, the index of input/output tensor, + need set before call rknn_query. */ + + uint32_t n_dims; /* the number of dimensions. */ + uint32_t dims[RKNN_MAX_DIMS]; /* the dimensions array. */ + char name[RKNN_MAX_NAME_LEN]; /* the name of tensor. */ + + uint32_t n_elems; /* the number of elements. */ + uint32_t size; /* the bytes size of tensor. */ + + rknn_tensor_format fmt; /* the data format of tensor. */ + rknn_tensor_type type; /* the data type of tensor. */ + rknn_tensor_qnt_type qnt_type; /* the quantitative type of tensor. */ + int8_t fl; /* fractional length for RKNN_TENSOR_QNT_DFP. */ + uint32_t zp; /* zero point for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ + float scale; /* scale for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ +} rknn_tensor_attr; + +/* + the information for RKNN_QUERY_PERF_DETAIL. +*/ +typedef struct _rknn_perf_detail { + char* perf_data; /* the string pointer of perf detail. don't need free it by user. */ + uint64_t data_len; /* the string length. */ +} rknn_perf_detail; + +/* + the information for RKNN_QUERY_PERF_RUN. +*/ +typedef struct _rknn_perf_run { + int64_t run_duration; /* real inference time (us) */ +} rknn_perf_run; + +/* + the information for RKNN_QUERY_SDK_VERSION. +*/ +typedef struct _rknn_sdk_version { + char api_version[256]; /* the version of rknn api. */ + char drv_version[256]; /* the version of rknn driver. */ +} rknn_sdk_version; + +/* + The flags of rknn_tensor_mem. +*/ +typedef enum _rknn_tensor_mem_flags { + RKNN_TENSOR_MEMORY_FLAGS_UNKNOWN = 0, + RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE = 1, /*Used to mark in rknn_destroy_mem() whether it is necessary to release the "mem" pointer itself. + If the flag RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE is set, rknn_destroy_mem() will call free(mem).*/ + +} rknn_tensor_mem_flags; + + +/* + the memory information of tensor. +*/ +typedef struct _rknn_tensor_memory { + void* logical_addr; /* the virtual address of tensor buffer. */ + uint64_t physical_addr; /* the physical address of tensor buffer. */ + int32_t fd; /* the fd of tensor buffer. */ + uint32_t size; /* the size of tensor buffer. */ + uint32_t handle; /* the handle tensor buffer. */ + void * priv_data; /* the data which is reserved. */ + uint64_t reserved_flag; /* the flag which is reserved. */ +} rknn_tensor_mem; + +/* + the input information for rknn_input_set. +*/ +typedef struct _rknn_input { + uint32_t index; /* the input index. */ + void* buf; /* the input buf for index. */ + uint32_t size; /* the size of input buf. */ + uint8_t pass_through; /* pass through mode. + if TRUE, the buf data is passed directly to the input node of the rknn model + without any conversion. the following variables do not need to be set. + if FALSE, the buf data is converted into an input consistent with the model + according to the following type and fmt. so the following variables + need to be set.*/ + rknn_tensor_type type; /* the data type of input buf. */ + rknn_tensor_format fmt; /* the data format of input buf. + currently the internal input format of NPU is NCHW by default. + so entering NCHW data can avoid the format conversion in the driver. */ +} rknn_input; + +/* + the output information for rknn_outputs_get. +*/ +typedef struct _rknn_output { + uint8_t want_float; /* want transfer output data to float */ + uint8_t is_prealloc; /* whether buf is pre-allocated. + if true, the following variables need to be set. + if false, The following variables do not need to be set. */ + uint32_t index; /* the output index. */ + void* buf; /* the output buf for index. + when is_prealloc = FALSE and rknn_outputs_release called, + this buf pointer will be free and don't use it anymore. */ + uint32_t size; /* the size of output buf. */ +} rknn_output; + +/* + the extend information for rknn_run. +*/ +typedef struct _rknn_run_extend { + uint64_t frame_id; /* output parameter, indicate current frame id of run. */ +} rknn_run_extend; + +/* + the extend information for rknn_outputs_get. +*/ +typedef struct _rknn_output_extend { + uint64_t frame_id; /* output parameter, indicate the frame id of outputs, corresponds to + struct rknn_run_extend.frame_id.*/ +} rknn_output_extend; + +/* + the information for RKNN_QUERY_RKNN_PRECOMPILE. +*/ +typedef struct _rknn_precompile { + void* model_data; /* the pointer of precompile model. don't need free it by user. */ + uint32_t data_len; /* the model length. */ +} rknn_precompile; + + +/* rknn_init + + initial the context and load the rknn model. + + input: + rknn_context* context the pointer of context handle. + void* model pointer to the rknn model. + uint32_t size the size of rknn model. + uint32_t flag extend flag, see the define of RKNN_FLAG_XXX_XXX. + return: + int error code. +*/ +int rknn_init(rknn_context* context, void* model, uint32_t size, uint32_t flag); + + +/* rknn_destroy + + unload the rknn model and destroy the context. + + input: + rknn_context context the handle of context. + return: + int error code. +*/ +int rknn_destroy(rknn_context context); + + +/* rknn_query + + query the information about model or others. see rknn_query_cmd. + + input: + rknn_context context the handle of context. + rknn_query_cmd cmd the command of query. + void* info the buffer point of information. + uint32_t size the size of information. + return: + int error code. +*/ +int rknn_query(rknn_context context, rknn_query_cmd cmd, void* info, uint32_t size); + + +/* rknn_inputs_set + + set inputs information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_input inputs[] the arrays of inputs information, see rknn_input. + return: + int error code +*/ +int rknn_inputs_set(rknn_context context, uint32_t n_inputs, rknn_input inputs[]); + + +/* rknn_inputs_map + + map inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_map(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_sync + + synchronize inputs tensor buffer by input index of rknn model. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_sync(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_unmap + + unmap inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_unmap(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_run + + run the model to execute inference. + + input: + rknn_context context the handle of context. + rknn_run_extend* extend the extend information of run. + return: + int error code. +*/ +int rknn_run(rknn_context context, rknn_run_extend* extend); + + +/* rknn_outputs_get + + wait the inference to finish and get the outputs. + this function will block until inference finish. + the results will set to outputs[]. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_output outputs[] the arrays of output, see rknn_output. + rknn_output_extend* the extend information of output. + return: + int error code. +*/ +int rknn_outputs_get(rknn_context context, uint32_t n_outputs, rknn_output outputs[], rknn_output_extend* extend); + + +/* rknn_outputs_release + + release the outputs that get by rknn_outputs_get. + after called, the rknn_output[x].buf get from rknn_outputs_get will + also be free when rknn_output[x].is_prealloc = FALSE. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_output outputs[] the arrays of output. + return: + int error code +*/ +int rknn_outputs_release(rknn_context context, uint32_t n_ouputs, rknn_output outputs[]); + + +/* rknn_outputs_map + + map the model output tensors memory information. + The difference between this function and "rknn_outputs_get" is + that it directly maps the model output tensor memory location to the user. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_map(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_sync + + synchronize the output tensors buffer to ensure cache cohenrency, wait the inference to finish. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_sync(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_unmap + + unmap the outputs memory information that get by rknn_outputs_map. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_outputs_unmap(rknn_context context, uint32_t n_ouputs, rknn_tensor_mem mem[]); + +/* rknn_create_mem (memory allocated inside) + + Create tensor memory. This API require libdrm support! + + input: + rknn_context ctx the handle of context. + uint64_t size the size of tensor buffer. + return: + rknn_tensor_mem the pointer of tensor memory information. +*/ +rknn_tensor_mem* rknn_create_mem(rknn_context ctx, uint64_t size); + +/* rknn_destroy_mem (support allocate inside and outside) + + destroy tensor memory. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the pointer of tensor memory information. + return: + int error code +*/ +int rknn_destroy_mem(rknn_context ctx, rknn_tensor_mem *mem); + + + +/* rknn_set_io_mem + + set the input and output tensors buffer. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the array of tensor memory information. + rknn_tensor_attr *attr the attribute of input or output tensor buffer. + return: + int error code. +*/ +int rknn_set_io_mem(rknn_context ctx, rknn_tensor_mem *mem, rknn_tensor_attr *attr); + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //_RKNN_RUNTIME_H diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib/librknn_api.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib/librknn_api.so new file mode 100644 index 0000000..ae3b0d1 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib/librknn_api.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib64/librknn_api.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib64/librknn_api.so new file mode 100644 index 0000000..950bc6e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_api/librknn_api/lib64/librknn_api.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/include/rknn_matmul_api.h b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/include/rknn_matmul_api.h new file mode 100644 index 0000000..74752d1 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/include/rknn_matmul_api.h @@ -0,0 +1,110 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2021 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + + +#ifndef _RKNN_MATMUL_H +#define _RKNN_MATMUL_H + + +/** + * Perform specific Matrix Multiply like AxB = C, where, + * Matrix A : [input] shape is [K,M], K is the high rank dimension in memory, M is the low rank dimension in memory and must be 1 now! + * Matrix B : [input] shape is [K,N], N is the low rank dimension in memory. + * Matrix C : [output] shape is [M,N] + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + the tensor data type. +*/ + +typedef enum _rknn_tensor_type { + RKNN_TENSOR_FLOAT32 = 0, /* data type is float32. */ + RKNN_TENSOR_FLOAT16, /* data type is float16. */ + RKNN_TENSOR_INT8, /* data type is int8. */ + RKNN_TENSOR_UINT8, /* data type is uint8. */ + RKNN_TENSOR_INT16, /* data type is int16. */ + + RKNN_TENSOR_TYPE_MAX +} rknn_tensor_type; + +#ifdef __arm__ +typedef uint32_t rknn_context; +#else +typedef uint64_t rknn_context; +#endif + + +/* + Definition of handle for rknn_matmul_run. +*/ +typedef struct _rknn_matmul_t{ + void* A; + void* B; + int32_t M; /* the low rank dimension of A */ + int32_t K; /* the high rank dimension of A and B*/ + int32_t N; /* the low rank dimension of B */ + rknn_tensor_type in_dtype; /* the input buffer type */ + rknn_context rknn_ctx; /* rknn context handle */ +} rknn_matmul_t; + +typedef rknn_matmul_t* rknn_matmul_handle_t; + +/* rknn_matmul_load + + load input buffer and initial the context. + + [input]: + void* a the pointer of A Matrix buffer, number of element is K*M, alloced by user. + void* b the pointer to B Matrix buffer, number of element is K*N, alloced by user. + int32_t M the low rank dimension of A + int32_t K the high rank dimension of A + int32_t N the low rank dimension of B + rknn_tensor_type dtype; the input buffer type, now only support RKNN_TENSOR_UINT8 and RKNN_TENSOR_INT8. + [output]: + rknn_matmul_handle_t the handle of mamul. it will return NULL if failed. +*/ +rknn_matmul_handle_t rknn_matmul_load(void *a, void *b, int M, int K, int N, rknn_tensor_type dtype); + +/* rknn_matmul_run + + run Matmul with fixed shape. + + [input]: + rknn_matmul_handle_t matmul_handle the handle of mamul, get by rknn_matmul_load. + float *c the pointer of C Matrix buffer, number of element is 256x4096, alloced by user. + [output]: + int error code. +*/ +int rknn_matmul_run(rknn_matmul_handle_t matmul_handle, float *c); + +/* rknn_matmul_unload + + destroy the context. + + [input]: + rknn_matmul_handle_t matmul_handle the handle of mamul, get by rknn_matmul_load. + [output]: + int error code. +*/ +int rknn_matmul_unload(rknn_matmul_handle_t matmul_handle); + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //_RKNN_MATMUL_H \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/lib/librknn_utils.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/lib/librknn_utils.so new file mode 100644 index 0000000..a35f60e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/lib/librknn_utils.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/lib64/librknn_utils.so b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/lib64/librknn_utils.so new file mode 100644 index 0000000..2ca9bf6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu-1.7.3/rknn/rknn_utils/librknn_utils/lib64/librknn_utils.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/.gitignore b/rknn_yolo_demo/libs/rklibs/rknpu/.gitignore new file mode 100644 index 0000000..70b84df --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/.gitignore @@ -0,0 +1 @@ +.gitreview diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/LICENSE b/rknn_yolo_demo/libs/rklibs/rknpu/LICENSE new file mode 100644 index 0000000..0fbe7ec --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/LICENSE @@ -0,0 +1,28 @@ +// Copyright 2020 Rockchip Electronics Co.,Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/README.md b/rknn_yolo_demo/libs/rklibs/rknpu/README.md new file mode 100644 index 0000000..08efd61 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/README.md @@ -0,0 +1,140 @@ +# RKNPU + +本工程主要为Rockchip NPU提供驱动、示例等。 + + + +## 适用平台 + +- RK1808/RK1806 + +- RV1109/RV1126 + + + +**注意:** + +- **RK3399Pro用户态的库及驱动不在本工程**,请参考:https://github.com/airockchip/RK3399Pro_npu +- RK3566/RK3568/RK3588/RV1103/RV1106请参考:https://github.com/rockchip-linux/rknpu2 + + + +## RKNN Toolkit + +​ 在使用RKNN API进行部署之前,需要使用RKNN Toolkit将原始的模型转化成rknn模型。 + +- RK1808/RK1806/RV1109/RV1126/RK3399Pro 使用: https://github.com/rockchip-linux/rknn-toolkit +- RK3566/RK3568/RK3588/RV1103/RV1106使用:https://github.com/rockchip-linux/rknn-toolkit2 + +​ 具体的使用说明请参考相应的网址。 + + + +## NPU驱动说明 + +### NPU驱动目录说明 + +NPU的驱动在$SDK/external/rknpu/drivers/目录下或者https://github.com/rockchip-linux/rknpu/tree/master/drivers + +其中的编译、安装规则参考$SDK/buildroot/package/rockchip/rknpu/rknpu.mk + +主要目录包括: + +``` +drivers/ +├── common +├── linux-aarch64 +├── linux-aarch64-mini +├── linux-armhf +├── linux-armhf-mini +├── linux-armhf-puma +├── linux-armhf-puma-mini +├── npu_ko +``` + +- linux-aarch64:RK1808 full driver + +- linux-aarch64-mini: RK1808 mini driver + +- linux-armhf: RK1806 full driver + +- linux-armhf-mini: RK1806 mini driver + +- linux-armhf-puma: RV1109/RV1126 full driver + +- linux-armhf-puma-mini: RV1109/RV1126 mini driver + +- npu_ko:NPU内核驱动KO + + 在更新驱动时,需要同时更新用户态驱动及内核驱动,不然会产生类似错误: + + ``` + [ 1] HAL user version 6.4.6.5.351518 + [ 2] HAL kernel version 6.4.6.5.351518 + ``` + + 另外,npu ko与内核配置强相关,有可能会加载不成功,运行程序时,会产生类似错误: + + ``` + [ 1] Failed to open device: No such file or directory, Try again... + [ 2] Failed to open device: No such file or directory, Try again... + ``` + + 遇到这种情况需要联系开发团队解决。 + + + +### NPU full driver与mini driver的区别 + +主要包含以下几点: + +- Mini driver只支持预编译的rknn模型,如果跑非预编译模型,会出现 RKNN_ERR_MODEL_INVALID的错误,从1.6.0开始,会返回RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER的错误; + +- Full driver支持RKNN Toolkit的联机调试功能,mini driver不支持; + +- Mini driver 库大小比full driver小很多,以RV1109/RV1126 1.6.0驱动为例,full driver大小为87MB,mini driver大小为7.1MB,可以有效的节省flash大小。 + +- Mini driver库运行时占用的内存比full driver小。 + + + +### 手动更新NPU驱动 + +有时需要手动更新NPU驱动,只要将相关的驱动拷贝到对应的目录就可以。 + +- 更新RK1808的驱动: + +``` +adb push drivers/linux-aarch64/ / +adb push drivers/npu_ko/galcore.ko /lib/modules/galcore.ko +``` + +- 更新RK1808 mini driver: + +``` +adb push drivers/linux-aarch64-mini/ / +adb push drivers/npu_ko/galcore.ko /lib/modules/galcore.ko +``` +- 更新RV1109/RV1126的驱动: + +``` +adb push drivers/linux-armhf-puma/ / +adb push drivers/npu_ko/galcore_puma.ko /lib/modules/galcore.ko +``` + +- 更新RV1109/RV1126 mini driver: + +``` +adb push drivers/linux-armhf-puma-mini/ / +adb push drivers/npu_ko/galcore_puma.ko /lib/modules/galcore.ko +``` + +注意:adb不同版本的默认行为不一样,有些是直接push目录的,有些是push目录下的文件。因此替换完后,需要检查一下相关的库是否已经替换成功。比如通过md5sum检查对应文件的md5值是否相同。部分板子不支持adb命令,请通过ssh等其他方式拷贝文件到对应目录即可。 + +**另外,toybrick可能对文件路径进行了调整,因此最好通过toybrick自带的方式进行更新。** + + + +## librknn_api与librknn_runtime的区别 + +librknn_api是对librknn_runtime的封装,主要是为了减少对其他so的编译依赖,功能上并没有区别。检查驱动版本时,一般以librknn_runtime.so为准。 diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/README b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/README new file mode 100644 index 0000000..221dc00 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/README @@ -0,0 +1,5 @@ +Mini driver (folder name contains mini) only support rknn models with precompiled mode. + +linux-aarch64: RK1808 +linux-arm: RK1806 +linux-armhf-puma: RV1109/RV1126 diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/etc/init.d/S05NPU_init b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/etc/init.d/S05NPU_init new file mode 100644 index 0000000..b9e97ab --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/etc/init.d/S05NPU_init @@ -0,0 +1,43 @@ +#!/bin/sh + +GetDDRBitWidth() +{ + bit=1 + a=1 + while [ 1 ];do + a=$((1<<$bit)) + if [ $a -ge $1 ];then + break + fi + let bit++ + done + return $(($bit<16?16:$bit)) +} + + + +case "$1" in + start) + printf "insmod NPU modules: " + cp /usr/lib/cl_*.h /tmp/ + DDR_SIZE=`cat /proc/meminfo|grep MemTotal|awk '{print $2}'` + GetDDRBitWidth $DDR_SIZE + bitWidth=$(($?+10)) + insmod /lib/modules/galcore.ko contiguousSize=0x400000 DDRBitWidth=$bitWidth + unset MAX_FREQ + read MAX_FREQ < /sys/class/devfreq/ffbc0000.npu/max_freq + echo $MAX_FREQ > /sys/class/devfreq/ffbc0000.npu/userspace/set_freq + [ $? = 0 ] && echo "OK" || echo "FAIL" +#start_rknn.sh & + ;; + stop) + ;; + restart|reload) + $0 stop + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/etc/init.d/S60NPU_init b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/etc/init.d/S60NPU_init new file mode 100644 index 0000000..2b3e454 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/etc/init.d/S60NPU_init @@ -0,0 +1,43 @@ +#!/bin/sh -x + +GetDDRBitWidth() +{ + bit=1 + a=1 + while [ 1 ];do + a=$((1<<$bit)) + if [ $a -ge $1 ];then + break + fi + let bit++ + done + return $(($bit<16?16:$bit)) +} + + + +case "$1" in + start) + printf "insmod NPU modules: " + cp /usr/lib/cl_*.h /tmp/ + DDR_SIZE=`cat /proc/meminfo|grep MemTotal|awk '{print $2}'` + GetDDRBitWidth $DDR_SIZE + bitWidth=$(($?+10)) + insmod /lib/modules/galcore.ko contiguousSize=0x400000 DDRBitWidth=$bitWidth + unset MAX_FREQ + read MAX_FREQ < /sys/class/devfreq/ffbc0000.npu/max_freq + echo $MAX_FREQ > /sys/class/devfreq/ffbc0000.npu/userspace/set_freq + [ $? = 0 ] && echo "OK" || echo "FAIL" + start_rknn.sh & + ;; + stop) + ;; + restart|reload) + $0 stop + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac +exit 0 diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/restart_rknn.sh b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/restart_rknn.sh new file mode 100644 index 0000000..a38bee3 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/restart_rknn.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +killall start_rknn.sh > /dev/null 2>&1 +killall rknn_server > /dev/null 2>&1 +start_rknn.sh & diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/start_rknn.sh b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/start_rknn.sh new file mode 100644 index 0000000..4de64ac --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/start_rknn.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +export RKNN_SERVER_PLUGINS='/usr/lib/npu/rknn/plugins/' + +while true +do + sleep 1 + rknn_server #>/dev/null 2>&1 +done diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/start_usb.sh b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/start_usb.sh new file mode 100644 index 0000000..0dc8ab4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/bin/start_usb.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +configfs_init() +{ + PID=$1 + CONFIG_STRING=$2 + mkdir -p /dev/usb-ffs -m 0770 + mkdir -p /dev/usb-ffs/$CONFIG_STRING -m 0770 + mount -t configfs none /sys/kernel/config + mkdir -p /sys/kernel/config/usb_gadget/rockchip -m 0770 + echo 0x2207 > /sys/kernel/config/usb_gadget/rockchip/idVendor + echo $PID > /sys/kernel/config/usb_gadget/rockchip/idProduct + mkdir -p /sys/kernel/config/usb_gadget/rockchip/strings/0x409 -m 0770 + echo "0123456789ABCDEF" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/serialnumber + echo "rockchip" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/manufacturer + echo "rk3xxx" > /sys/kernel/config/usb_gadget/rockchip/strings/0x409/product + mkdir -p /sys/kernel/config/usb_gadget/rockchip/configs/b.1 -m 0770 + mkdir -p /sys/kernel/config/usb_gadget/rockchip/configs/b.1/strings/0x409 -m 0770 + echo 500 > /sys/kernel/config/usb_gadget/rockchip/configs/b.1/MaxPower + echo \"$CONFIG_STRING\" > /sys/kernel/config/usb_gadget/rockchip/configs/b.1/strings/0x409/configuration +} + +function_init() +{ + CONFIG_STRING=$1 + mkdir -p /sys/kernel/config/usb_gadget/rockchip/functions/ffs.$CONFIG_STRING + rm -f /sys/kernel/config/usb_gadget/rockchip/configs/b.1/ffs.* + ln -s /sys/kernel/config/usb_gadget/rockchip/functions/ffs.$CONFIG_STRING /sys/kernel/config/usb_gadget/rockchip/configs/b.1/ffs.$CONFIG_STRING +} + +case "$1" in +adb) + killall adbd start_rknn.sh rknn_server > /dev/null 2>&1 + + echo "none" > /sys/kernel/config/usb_gadget/rockchip/UDC + + umount /sys/kernel/config + umount /dev/usb-ffs/ntb > /dev/null 2>&1 + rm -rf /dev/usb-ffs/ntb + + configfs_init 0x0006 adb + function_init adb + + # START_APP_BEFORE_UDC + mkdir -p /dev/usb-ffs/adb + mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb + export service_adb_tcp_port=5555 + adbd& + sleep 1 + + UDC=`ls /sys/class/udc/| awk '{print $1}'` + echo $UDC > /sys/kernel/config/usb_gadget/rockchip/UDC + # START_APP_AFTER_UDC + + start_rknn.sh & + + ;; +ntb) + killall adbd start_rknn.sh rknn_server > /dev/null 2>&1 + + echo "none" > /sys/kernel/config/usb_gadget/rockchip/UDC + + umount /sys/kernel/config + umount /dev/usb-ffs/adb > /dev/null 2>&1 + rm -rf /dev/usb-ffs/adb + + configfs_init 0x1808 ntb + function_init ntb + + # START_APP_BEFORE_UDC + mkdir -p /dev/usb-ffs/ntb + mount -o uid=2000,gid=2000 -t functionfs ntb /dev/usb-ffs/ntb + + start_rknn.sh & + + ;; +*) + echo "Usage: $0 {adb|ntb}" + exit 1 +esac + +exit 0 diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/lib/cl_viv_vx_ext.h b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/lib/cl_viv_vx_ext.h new file mode 100644 index 0000000..a6ecd50 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/common/usr/lib/cl_viv_vx_ext.h @@ -0,0 +1,1456 @@ + + + +#ifndef _GC_VX_H +#define _GC_VX_H 1 + +#ifdef _VIV_VX_EXTENSION + +#pragma OPENCL EXTENSION CL_VIV_asm : enable + +#ifndef VX_VERSION +#define VX_VERSION 1 +#endif + +typedef enum _VXC_FilterMode +{ + VXC_FM_BOX = 0, + VXC_FM_Guassian = 1, + VXC_FM_SobelX = 2, + VXC_FM_SobelY = 3, + VXC_FM_ScharrX = 4, + VXC_FM_ScharrY = 5, + VXC_FM_Max = 8, + VXC_FM_Min = 9, + VXC_FM_Median = 10 +} vxc_filter_mode; + +typedef enum _VXC_RoundMode +{ + VXC_RM_Truncate = 0, + VXC_RM_TowardZero = 0, + VXC_RM_TowardInf = 1, + VXC_RM_ToNearestEven = 2 +} vxc_round_mode; + +typedef enum _VXC_ScatteredOffsetType +{ + VXC_OFFSET_UNSIGNED32 = 0, + VXC_OFFSET_SIGNED32 = 1, + VXC_OFFSET_UNSIGNED16 = 2, + VXC_OFFSET_SIGNED16 = 3, + VXC_OFFSET_UNSIGNED8 = 4, + VXC_OFFSET_SIGNED8 = 5, +} VXC_ScatteredOffsetType; + +typedef enum _VXC_AtomicOp +{ + VXC_ATOMIC_OP_ADD = 0, + VXC_ATOMIC_OP_MIN = 1, + VXC_ATOMIC_OP_MAX = 2, + VXC_ATOMIC_OP_OR = 3, + VXC_ATOMIC_OP_AND = 4, + VXC_ATOMIC_OP_XOR = 5, + VXC_ATOMIC_OP_XCHG = 6, +}VXC_AtomicOpType; + +#define VXC_CLAMP_BITMASK 0x00400000 +#define VXC_PREADJ_BITMASK 0x00200000 +#define VXC_RANGEPI_BITMASK 0x00100000 +#define VXC_FILTER_BITMASK 0x000F0000 +#define VXC_START_BIN_BITMASK 0x0000F000 +#define VXC_END_BIN_BITMASK 0x00000F00 +#define VXC_SOURCE_BIN_BITMASK 0x000000F0 +#define VXC_ROUNDING_MODE_BITMASK 0x0000000C +#define VXC_ENABLEBOOL_BITMASK 0x00000002 +#define VXC_SIGNEXT_BITMASK 0x00000001 + + +#define VXC_OFFSET_TYPE_BITMASK 0x00070000 +#define VXC_OFFSET_TYPE_SHIFT 16 + + +#define VXC_ATOM_OP_BITMASK 0x00380000 +#define VXC_ATOM_OP_SHIFT 19 + +#define VXC_MODIFIER(StartBin, EndBin, SourceBin, RoundingMode, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) | \ + ((RoundingMode << 2)&VXC_ROUNDING_MODE_BITMASK) \ + ) + +#define VXC_MODIFIER_SIGNEXT(StartBin, EndBin, SourceBin, SignExt, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + ((SignExt)&VXC_SIGNEXT_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_MAGPHASE(StartBin, EndBin, SourceBin, NoPreAdjust, RangePi) \ + ( \ + (VXC_CLAMP_BITMASK) | \ + (((RangePi) << 20)&VXC_RANGEPI_BITMASK) | \ + (((NoPreAdjust) << 21)&VXC_PREADJ_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_CLAMP(StartBin, EndBin, SourceBin, EnableBool) \ + ( \ + (((EnableBool) << 1)&VXC_ENABLEBOOL_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_FILTER(StartBin, EndBin, SourceBin, Filter, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + (((Filter) << 16)&VXC_FILTER_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_BIN(StartBin, EndBin, Clamp) \ + ( \ + (((Clamp) << 22)&VXC_CLAMP_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_GATHER(StartBin, EndBin, SourceBin, OffsetType) \ + ( \ + (((OffsetType) << VXC_OFFSET_TYPE_SHIFT)&VXC_OFFSET_TYPE_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_SCATTER(StartBin, EndBin, SourceBin, OffsetType) \ + ( \ + (((OffsetType) << VXC_OFFSET_TYPE_SHIFT)&VXC_OFFSET_TYPE_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + +#define VXC_MODIFIER_ATOMIC_S(StartBin, EndBin, SourceBin, OffsetType, AtomOp) \ + ( \ + (((OffsetType) << VXC_OFFSET_TYPE_SHIFT)&VXC_OFFSET_TYPE_BITMASK) | \ + (((AtomOp) << VXC_ATOM_OP_SHIFT)&VXC_ATOM_OP_BITMASK) | \ + (((StartBin) << 12)&VXC_START_BIN_BITMASK) | \ + (((EndBin) << 8)&VXC_END_BIN_BITMASK) | \ + (((SourceBin) << 4)&VXC_SOURCE_BIN_BITMASK) \ + ) + + +#define VXC_MODIFIER_SetDestClamp(VxModifier, Clamp) ((VxModifier) | (((Clamp) << 22)&VXC_CLAMP_BITMASK)) + +#define VXC_DEFAULT_MODIFIER (-1) + +typedef unsigned int vxc_modifier; + + +typedef _viv_char2_packed vxc_char2; +typedef _viv_char4_packed vxc_char4; +typedef _viv_char8_packed vxc_char8; +typedef _viv_char16_packed vxc_char16; +typedef struct _vxc_char32 +{ + vxc_char16 hi; + vxc_char16 lo; +} vxc_char32; + + +typedef _viv_uchar2_packed vxc_uchar2; +typedef _viv_uchar4_packed vxc_uchar4; +typedef _viv_uchar8_packed vxc_uchar8; +typedef _viv_uchar16_packed vxc_uchar16; +typedef struct _vxc_uchar32 +{ + vxc_uchar16 hi; + vxc_uchar16 lo; +} vxc_uchar32; + + +typedef _viv_short2_packed vxc_short2; +typedef _viv_short4_packed vxc_short4; +typedef _viv_short8_packed vxc_short8; +typedef struct _vxc_short16 +{ + vxc_short8 hi; + vxc_short8 lo; +} vxc_short16; + + +typedef _viv_ushort2_packed vxc_ushort2; +typedef _viv_ushort4_packed vxc_ushort4; +typedef _viv_ushort8_packed vxc_ushort8; +typedef struct _vxc_ushort16 +{ + vxc_ushort8 hi; + vxc_ushort8 lo; +} vxc_ushort16; + + +typedef int vxc_int; +typedef int2 vxc_int2; +typedef int4 vxc_int4; +typedef int8 vxc_int8; +typedef int16 vxc_int16; + + +typedef uint vxc_uint; +typedef uint2 vxc_uint2; +typedef uint4 vxc_uint4; +typedef uint8 vxc_uint8; +typedef uint16 vxc_uint16; + + +typedef float vxc_float; +typedef float2 vxc_float2; +typedef float4 vxc_float4; +typedef float8 vxc_float8; +typedef float16 vxc_float16; + + +typedef half vxc_half; +typedef _viv_half2_packed vxc_half2; +typedef _viv_half4_packed vxc_half4; +typedef _viv_half8_packed vxc_half8; +typedef struct _vxc_half16 +{ + vxc_half8 hi; + vxc_half8 lo; +} vxc_half16; + +typedef uint16 vxc_512bits; +typedef uint4 vxc_128bits; + +typedef vxc_512bits VXC_512Bits; +typedef vxc_128bits VXC_128Bits; +typedef vxc_modifier VXC_Modifier_t ; +typedef vxc_round_mode VXC_RoundMode; +typedef vxc_filter_mode VXC_FilterMode; + +#ifndef VX_USE_INTRINSIC +#define VX_USE_INTRINSIC 0 +#endif + +enum VXC_OP { + VXC_OP_abs_diff = 3, + VXC_OP_iadd, + VXC_OP_iacc_sq, + VXC_OP_lerp, + VXC_OP_filter, + VXC_OP_mag_phase, + VXC_OP_mul_shift, + VXC_OP_dp16x1, + VXC_OP_dp8x2, + VXC_OP_dp4x4, + VXC_OP_dp2x8, + VXC_OP_clamp, + VXC_OP_bi_linear, + VXC_OP_select_add, + VXC_OP_atomic_add, + VXC_OP_bit_extract, + VXC_OP_bit_replace, + VXC_OP_dp32x1, + VXC_OP_dp16x2, + VXC_OP_dp8x4, + VXC_OP_dp4x8, + VXC_OP_dp2x16, + VXC_OP_dp32x1_b, + VXC_OP_dp16x2_b, + VXC_OP_dp8x4_b, + VXC_OP_dp4x8_b, + VXC_OP_dp2x16_b, + VXC_OP_img_load, + VXC_OP_img_load_3d, + VXC_OP_img_store, + VXC_OP_img_store_3d, + VXC_OP_vload2, + VXC_OP_vload3, + VXC_OP_vload4, + VXC_OP_vload8, + VXC_OP_vload16, + VXC_OP_vstore2, + VXC_OP_vstore3, + VXC_OP_vstore4, + VXC_OP_vstore8, + VXC_OP_vstore16, + VXC_OP_index_add, + VXC_OP_vert_min3, + VXC_OP_vert_max3, + VXC_OP_vert_med3, + VXC_OP_horz_min3, + VXC_OP_horz_max3, + VXC_OP_horz_med3, + VXC_OP_error, + OP_bit_extract, + VXC_OP_dp16x1_b, + VXC_OP_dp8x2_b, + VXC_OP_dp4x4_b, + VXC_OP_dp2x8_b, + VXC_OP_gather, + VXC_OP_gather_b, + VXC_OP_scatter, + VXC_OP_scatter_b, + VXC_OP_atomic_s, + VXC_OP_atomic_s_b, +}; + +enum eVXC_ERROR +{ + ERROR_DP2x16_NOT_SUPPORTED, + ERROR_IADD_NOT_SUPPORTED, + ERROR_SELECTADD_NOT_SUPPORTED, + ERROR_BITREPLACE_NOT_SUPPORTED +}; + +#define VXC_OP1(Op, Dest, Src0) _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, Src0) + +#define VXC_OP2(Op, Dest, Src0, Src1) \ + do { \ + int _t1; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t1); \ + } while(0) + +#define VXC_OP3(Op, Dest, Src0, Src1, Src2) \ + do { \ + int _t1, _t2; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t2); \ + } while(0) + +#define VXC_OP3_NoDest(Op, Src0, Src1, Src2) \ + do { \ + int _t1, _t2, _t3; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(INTRINSIC_ST, _t3, VXC_OP_##Op, _t2); \ + } while(0) + + +#define VXC_OP4(Op, Dest, Src0, Src1, Src2, Src3) \ + do { \ + int _t1, _t2, _t3; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t3); \ + } while(0) + +#define VXC_OP4_NoDest(Op, Src0, Src1, Src2, Src3) \ + do { \ + int _t1, _t2, _t3, _t4; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(INTRINSIC_ST, _t4, VXC_OP_##Op, _t3); \ + } while(0) + +#define VXC_OP4_ST(Op, Dest, Src0, Src1, Src2, Src3) \ + do { \ + int _t1, _t2, _t3; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(INTRINSIC_ST, Dest, VXC_OP_##Op, _t3);\ + } while(0) + +#define VXC_OP5(Op, Dest, Src0, Src1, Src2, Src3, Src4) \ + do { \ + int _t1, _t2, _t3, _t4; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(PARAM_CHAIN, _t4, _t3, Src4); \ + _viv_asm(INTRINSIC, Dest, VXC_OP_##Op, _t4); \ + } while(0) + +#define VXC_OP5_NoDest(Op, Src0, Src1, Src2, Src3, Src4) \ + do { \ + int _t1, _t2, _t3, _t4, _t5; \ + _viv_asm(PARAM_CHAIN, _t1, Src0, Src1); \ + _viv_asm(PARAM_CHAIN, _t2, _t1, Src2); \ + _viv_asm(PARAM_CHAIN, _t3, _t2, Src3); \ + _viv_asm(PARAM_CHAIN, _t4, _t3, Src4); \ + _viv_asm(INTRINSIC_ST, _t5, VXC_OP_##Op, _t4); \ + } while(0) + + +#define VXC_5BITOFFSET_XY(offsetX, offsetY) ((((offsetY) & 0x1F) << 5) | ((offsetX) & 0x1F)) + + + +#if !VX_USE_INTRINSIC +#define VXC_AbsDiff(Dest, Src0, Src1, Info) VXC_OP3(abs_diff, Dest, Src0, Src1, Info) +#define VXC_IAccSq(Dest, Src0, Src1, Imm, Info) VXC_OP4(iacc_sq, Dest, Src0, Src1, Imm, Info) +#define VXC_Lerp(Dest, Src0, Src1, Src2, Info) VXC_OP4(lerp, Dest, Src0, Src1, Src2, Info) + +#define VXC_MulShift(Dest, Src0, Src1, Imm, Info) VXC_OP4(mul_shift, Dest, Src0, Src1, Imm, Info) +#define VXC_Clamp(Dest, Src0, Src1, Src2, Info) VXC_OP4(clamp, Dest, Src0, Src1, Src2, Info) +#define VXC_AtomicAdd(Dest, Base, Offset, Data, Info) VXC_OP4_ST(atomic_add, Dest, Base, Offset, Data, Info) +#define VXC_BitExtract(Dest, Src0, Src1, Src2, Info) VXC_OP4(bit_extract, Dest, Src0, Src1, Src2, Info) + +#define VXC_DP16x1(Dest, Src0, Src1, Info, U512) VXC_OP4(dp16x1, Dest, Src0, Src1, Info, U512) +#define VXC_DP8x2(Dest, Src0, Src1, Info, U512) VXC_OP4(dp8x2, Dest, Src0, Src1, Info, U512) +#define VXC_DP4x4(Dest, Src0, Src1, Info, U512) VXC_OP4(dp4x4, Dest, Src0, Src1, Info, U512) +#define VXC_DP2x8(Dest, Src0, Src1, Info, U512) VXC_OP4(dp2x8, Dest, Src0, Src1, Info, U512) + +#define VXC_DP32x1(Dest, Src0, Src1, Info, U512) VXC_OP4(dp32x1, Dest, Src0, Src1, Info, U512) +#define VXC_DP16x2(Dest, Src0, Src1, Info, U512) VXC_OP4(dp16x2, Dest, Src0, Src1, Info, U512) +#define VXC_DP8x4(Dest, Src0, Src1, Info, U512) VXC_OP4(dp8x4, Dest, Src0, Src1, Info, U512) +#define VXC_DP4x8(Dest, Src0, Src1, Info, U512) VXC_OP4(dp4x8, Dest, Src0, Src1, Info, U512) +#if (VX_VERSION >= 2) +#define VXC_DP2x16(Dest, Src0, Src1, Info, U512) VXC_OP1(error, ERROR_DP2x16_NOT_SUPPORTED) +#else +#define VXC_DP2x16(Dest, Src0, Src1, Info, U512) VXC_OP4(dp2x16, Dest, Src0, Src1, Info, U512) +#endif + +#if (VX_VERSION >= 2) + +#define VXC_DP16x1_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp16x1_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP8x2_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp8x2_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP4x4_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp4x4_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP2x8_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp2x8_b, Dest, Src0, Src1, Src2, Info, U512) +#endif + + +#define VXC_DP32x1_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp32x1_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP16x2_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp16x2_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP8x4_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp8x4_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP4x8_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp4x8_b, Dest, Src0, Src1, Src2, Info, U512) +#define VXC_DP2x16_b(Dest, Src0, Src1, Src2, Info, U512) VXC_OP5(dp2x16_b, Dest, Src0, Src1, Src2, Info, U512) + +#define VXC_Gather(Dest, BaseAddr, Offsets, GatherInfo) VXC_OP3(gather, Dest, BaseAddr, Offsets, GatherInfo) +#define VXC_Gather_b(Dest, BaseAddr, Offsets, Offsets_b, GatherInfo) VXC_OP4(gather_b, Dest, BaseAddr, Offsets, Offsets_b, GatherInfo) + +#define VXC_Scatter(BaseAddr, Offsets, Data, ScatterInfo) VXC_OP4_NoDest(scatter, BaseAddr, Offsets, Data, ScatterInfo) +#define VXC_Scatter_b(BaseAddr, Offsets, Offsets_b, Data, ScatterInfo) VXC_OP5_NoDest(scatter_b, BaseAddr, Offsets, Offsets_b, Data, ScatterInfo) + +#define VXC_AtomicS(Dest, BaseAddr, Offsets, Data, AtomicSInfo) VXC_OP4(atomic_s, Dest, BaseAddr, Offsets, Data, AtomicSInfo) +#define VXC_AtomicS_b(Dest, BaseAddr, Offsets, Offsets_b, Data, AtomicSInfo) VXC_OP5(atomic_s_b, Dest, BaseAddr, Offsets, Offsets_b, Data, AtomicSInfo) + + + +#define VXC_ReadImage(Dest, Image, Coord, Offset, Info) VXC_OP4(img_load, Dest, Image, Coord, Offset, Info) +#define VXC_WriteImage(Image, Coord, Color, Info) VXC_OP4_NoDest(img_store, Image, Coord, Color, Info) + + +#define VXC_ReadImage2DArray(Dest, Image, Coord, Offset, Info) \ + do { \ + int8 desc; \ + _viv_asm(COPY, desc, Image, sizeof(desc)); \ + _viv_asm(CLAMP0MAX, (Coord).w, (Coord).z, desc.s5 - 1); \ + int baseAddr = (int)(Coord).w *desc.s4 + desc.s0; \ + _viv_asm(MOV, (Coord).w, baseAddr); \ + VXC_OP4(img_load_3d, Dest, Image, (Coord).xyww, Offset, Info); \ + } while (0) +#define VXC_WriteImage2DArray(Image, Coord, Color, Info) \ + do { \ + int8 desc; \ + _viv_asm(COPY, desc, Image, sizeof(desc)); \ + _viv_asm(CLAMP0MAX, (Coord).w, (Coord).z, desc.s5 - 1); \ + int baseAddr = (int)(Coord).w *(desc).s4 + desc.s0; \ + _viv_asm(MOV, (Coord).w, baseAddr); \ + VXC_OP4_NoDest(img_store_3d, Image, (Coord).xyww, Color, Info); \ + } while (0) + + +#define VXC_ReadImage3D(Dest, Image, Coord, Offset, Info) VXC_OP4(img_load_3d, Dest, Image, Coord, Offset, Info) +#define VXC_WriteImage3D(Image, Coord, Color, Info) VXC_OP4_NoDest(img_store_3d, Image, Coord, Color, Info) + +#define VXC_Vload2(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload2, Dest, Pointer, byteOffset); } while(0) +#define VXC_Vload4(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload4, Dest, Pointer, byteOffset); } while(0) +#define VXC_Vload8(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload8, Dest, Pointer, byteOffset); } while(0) +#define VXC_Vload16(Dest, Pointer, Offset) do { int byteOffset = ((int)sizeof((Dest)))*(Offset); VXC_OP2(vload16, Dest, Pointer, byteOffset); } while(0) + +#define VXC_Vstore2(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore2, Pointer, byteOffset, Data); } while(0) +#define VXC_Vstore4(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore4, Pointer, byteOffset, Data); } while(0) +#define VXC_Vstore8(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore8, Pointer, byteOffset, Data); } while(0) +#define VXC_Vstore16(Pointer, Offset, Data) do { int byteOffset = ((int)sizeof((Data)))*(Offset); VXC_OP3_NoDest(vstore16, Pointer, byteOffset, Data); } while(0) + + +#define VXC_IndexAdd(Dest, Src0, Src1, Src2, Info) VXC_OP4(index_add, Dest, Src0, Src1, Src2, Info) +#define VXC_VertMin3(Dest, Src0, Src1, Src2, Info) VXC_OP4(vert_min3, Dest, Src0, Src1, Src2, Info) +#define VXC_VertMax3(Dest, Src0, Src1, Src2, Info) VXC_OP4(vert_max3, Dest, Src0, Src1, Src2, Info) +#define VXC_VertMed3(Dest, Src0, Src1, Src2, Info) VXC_OP4(vert_med3, Dest, Src0, Src1, Src2, Info) +#define VXC_HorzMin3(Dest, Src0, Info) VXC_OP2(horz_min3, Dest, Src0, Info) +#define VXC_HorzMax3(Dest, Src0, Info) VXC_OP2(horz_max3, Dest, Src0, Info) +#define VXC_HorzMed3(Dest, Src0, Info) VXC_OP2(horz_med3, Dest, Src0, Info) + +#if (VX_VERSION == 2) +#define VXC_BiLinear(Dest, Src0, Src1, Src2, Info) \ + do { \ + int endBin = ((Info) & VXC_END_BIN_BITMASK) >> 8; \ + int roundMode = ((Info) & VXC_ROUNDING_MODE_BITMASK) >> 2; \ + int clamp = ((Info) & VXC_CLAMP_BITMASK) >> 22; \ + int mod1 = VXC_MODIFIER(0, endBin + 1, 0, roundMode, clamp); \ + int4 bitMask = { 0x00000000, 0x00000008, 0x00000010, 0x00000018}; \ + typeof (Dest) bi1; \ + uint4 bi2; \ + int bi3, bi4; \ + VXC_Lerp(bi1, Src0, Src1, (Src2).y, mod1); \ + _viv_asm(PARAM_CHAIN, bi3, bi1.x!, bitMask); \ + _viv_asm(PARAM_CHAIN, bi4, bi3, 8); \ + _viv_asm(INTRINSIC, bi2, OP_bit_extract, bi4); \ + VXC_Lerp(Dest, bi2!, bi2.y!, (Src2).x, Info); \ + } while (0) + +#define VXC_BitReplace(Dest, Src0, Src1, Src2, Info) +#define VXC_IAdd(Dest, Src0, Src1, Src2, Info) +#define VXC_MagPhase(Dest, Src0, Src1, Info) +#define VXC_SelectAdd(Dest, Src0, Src1, U512, Info) VXC_OP1(error, ERROR_SELECTADD_NOT_SUPPORTED) + +#define VXC_Filter_Box(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Guassian(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_SobelX(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_SobelY(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_ScharrX(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_ScharrY(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Max(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Min(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter_Median(Dest, Src0, Src1, Src2, Info) +#define VXC_Filter(Dest, Src0, Src1, Src2, Info) do { \ + int filter = (((Info) >> 16)&0x0F); \ + if (filter == VXC_FM_BOX) { VXC_Filter_Box(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Guassian) { VXC_Filter_Guassian(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_SobelX) { VXC_Filter_SobelX(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_SobelY) { VXC_Filter_SobelY(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_ScharrX) { VXC_Filter_ScharrX(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_ScharrY) { VXC_Filter_ScharrY(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Max) { VXC_Filter_Max(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Min) { VXC_Filter_Min(Dest, Src0, Src1, Src2, Info); } \ + if (filter == VXC_FM_Median) { VXC_Filter_Median(Dest, Src0, Src1, Src2, Info); } \ + } while (0) + +#else + +#define VXC_BiLinear(Dest, Src0, Src1, Src2, Info) VXC_OP4(bi_linear, Dest, Src0, Src1, Src2, Info) +#define VXC_BitReplace(Dest, Src0, Src1, Src2, Info) VXC_OP4(bit_replace, Dest, Src0, Src1, Src2, Info) +#define VXC_IAdd(Dest, Src0, Src1, Src2, Info) VXC_OP4(iadd, Dest, Src0, Src1, Src2, Info) +#define VXC_MagPhase(Dest, Src0, Src1, Info) VXC_OP3(mag_phase, Dest, Src0, Src1, Info) +#define VXC_SelectAdd(Dest, Src0, Src1, U512, Info) VXC_OP4(select_add, Dest, Src0, Src1, U512, Info) +#define VXC_Filter(Dest, Src0, Src1, Src2, Info) VXC_OP4(filter, Dest, Src0, Src1, Src2, Info) +#endif + +#else + +#ifdef __cplusplus +extern "c" { +#endif + +#define viv_vx_api_only 0 + +#if viv_vx_api_only +#define _RET0_ ; +#define _RET_ ; +#define _EXT_ extern +#else +#define _RET0_ { return (0); } +#define _RET_ { return ; } +#define _EXT_ +#endif + + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_char16 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_char8 a) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_short8 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_short4 a) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_ushort8 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastP_uc(vxc_half8 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastP_uc(vxc_half4 a) _RET0_ + + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_uchar16 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_short8 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_short4 a) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_ushort8 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_icastP_c(vxc_half8 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastP_c(vxc_half4 a) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_uchar16 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_char16 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_char8 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_short8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_short4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastP_us(vxc_half8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastP_us(vxc_half4 a) _RET0_ + + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_uchar16 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_char16 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_char8 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_ushort8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastP_s(vxc_half8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastP_s(vxc_half4 a) _RET0_ + + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_uchar16 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_char16 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_char8 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_ushort8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastP_h(vxc_short8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastP_h(vxc_short4 a) _RET0_ + + + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_icastD_uc(vxc_char16 a) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_char8 a) _RET0_ + +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_short8 a) _RET0_ +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_short4 a) _RET0_ + +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_ushort8 a) _RET0_ +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_uchar8 viv_intrinsic_vx_icastD_uc(vxc_half8 a) _RET0_ +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_half4 a) _RET0_ + +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_int4 a) _RET0_ +_EXT_ vxc_uchar2 viv_intrinsic_vx_icastD_uc(vxc_int2 a) _RET0_ + +_EXT_ vxc_uchar4 viv_intrinsic_vx_icastD_uc(vxc_uint4 a) _RET0_ +_EXT_ vxc_uchar2 viv_intrinsic_vx_icastD_uc(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_char16 viv_intrinsic_vx_icastD_c(vxc_uchar16 a) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_uchar8 a) _RET0_ + +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_short8 a) _RET0_ +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_short4 a) _RET0_ + +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_ushort8 a) _RET0_ +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_char8 viv_intrinsic_vx_icastD_c(vxc_half8 a) _RET0_ +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_half4 a) _RET0_ + +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_int4 a) _RET0_ +_EXT_ vxc_char2 viv_intrinsic_vx_icastD_c(vxc_int2 a) _RET0_ + +_EXT_ vxc_char4 viv_intrinsic_vx_icastD_c(vxc_uint4 a) _RET0_ +_EXT_ vxc_char2 viv_intrinsic_vx_icastD_c(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_uchar8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_uchar4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_char8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_char4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_short8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_short4 a) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vx_icastD_us(vxc_half8 a) _RET0_ +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_half4 a) _RET0_ + +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_int4 a) _RET0_ +_EXT_ vxc_ushort2 viv_intrinsic_vx_icastD_us(vxc_int2 a) _RET0_ + +_EXT_ vxc_ushort4 viv_intrinsic_vx_icastD_us(vxc_uint4 a) _RET0_ +_EXT_ vxc_ushort2 viv_intrinsic_vx_icastD_us(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_uchar8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_uchar4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_char8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_char4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_ushort8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_short8 viv_intrinsic_vx_icastD_s(vxc_half8 a) _RET0_ +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_half4 a) _RET0_ + +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_int4 a) _RET0_ +_EXT_ vxc_short2 viv_intrinsic_vx_icastD_s(vxc_int2 a) _RET0_ + +_EXT_ vxc_short4 viv_intrinsic_vx_icastD_s(vxc_uint4 a) _RET0_ +_EXT_ vxc_short2 viv_intrinsic_vx_icastD_s(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_uchar8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_uchar4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_char8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_char4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_ushort8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_ushort4 a) _RET0_ + +_EXT_ vxc_half8 viv_intrinsic_vx_icastD_h(vxc_short8 a) _RET0_ +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_short4 a) _RET0_ + +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_int4 a) _RET0_ +_EXT_ vxc_half2 viv_intrinsic_vx_icastD_h(vxc_int2 a) _RET0_ + +_EXT_ vxc_half4 viv_intrinsic_vx_icastD_h(vxc_uint4 a) _RET0_ +_EXT_ vxc_half2 viv_intrinsic_vx_icastD_h(vxc_uint2 a) _RET0_ + + +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_char4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_uchar4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_short4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_ushort4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_half4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_uint4 a) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vx_icastD_i(vxc_float4 a) _RET0_ + +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_char2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_uchar2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_short2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_ushort2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_half2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_uint2 a) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vx_icastD_i(vxc_float2 a) _RET0_ + + +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_char4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_uchar4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_short4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_ushort4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_half4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_int4 a) _RET0_ +_EXT_ vxc_uint4 viv_intrinsic_vx_icastD_ui(vxc_float4 a) _RET0_ + +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_char2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_uchar2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_short2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_ushort2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_half2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_int2 a) _RET0_ +_EXT_ vxc_uint2 viv_intrinsic_vx_icastD_ui(vxc_float2 a) _RET0_ + + +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_char4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_uchar4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_short4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_ushort4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_half4 a) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vx_icastD_f(vxc_int4 a) _RET0_ + +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_char2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_uchar2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_short2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_ushort2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_half2 a) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vx_icastD_f(vxc_int2 a) _RET0_ + + + +#define VXC_SWIZZLE_MASK8_ALL() 0xFFFF +#define VXC_SWIZZLE_MASK8(E0, E1, E2, E3, E4, E5, E6, E7) \ + (((E0) * 0x3) | ((E1) * (0x3 << 2)) | ((E2) * (0x3 << 4)) | \ + ((E3) * (0x3 << 6)) | ((E4) * (0x3 << 8)) | ((E5) * (0x3 << 10)) | \ + ((E6) * (0x3 << 12)) | ((E7) * (0x3 << 14)) ) + +#define VXC_SWIZZLE_MASK16_ALL() 0xFFFF +#define VXC_SWIZZLE_MASK16(E0, E1, E2, E3, E4, E5, E6, E7, E9, E10, E11, E12, E13, E14, E15) \ + (((E0) * 0x1) | ((E1) * (0x1 << 1)) | ((E2) * (0x1 << 2)) | \ + ((E3) * (0x1 << 1)) | ((E4) * (0x1 << 4)) | ((E5) * (0x1 << 5)) | \ + ((E6) * (0x1 << 6)) | ((E7) * (0x1 << 7)) | ((E8) * (0x1 << 8)) | \ + ((E9) * (0x1 << 9)) | ((E10) * (0x1 << 10)) | ((E11) * (0x1 << 11)) | \ + ((E12) * (0x1 << 12)) | ((E13) * (0x1 << 13)) | ((E14) * (0x1 << 14)) | \ + ((E15) * (0x1 << 15)) ) + +#define VXC_SWIZZLE8(S0, S1, S2, S3, S4, S5, S6, S7) \ + (uint)((S0) << 0 | (S1) << 4 | (S2) << 8 | (S3) << 12 | \ + (S4) << 16 | (S5) << 20 | (S6) << 24 | (S7) << 28 ) + + +_EXT_ vxc_char16 viv_intrinsic_vx_read_imagec (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_read_imageuc (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_read_images (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_read_imageus (image2d_t image, int2 coord) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vx_read_imageh (image2d_t image, int2 coord) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_read_imagec (image1d_t image, int coord) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_read_imageuc (image1d_t image, int coord) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_read_images (image1d_t image, int coord) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_read_imageus (image1d_t image, int coord) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vx_read_imageh (image1d_t image, int coord) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vx_read_imagec (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_read_imageuc (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_read_images (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_read_imageus (image1d_array_t image, int2 coord) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vx_read_imageh (image1d_array_t image, int2 coord) _RET0_ + + +_EXT_ void viv_intrinsic_vx_write_imagec (image2d_t image, int2 coord, vxc_char16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageuc (image2d_t image, int2 coord, vxc_uchar16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_images (image2d_t image, int2 coord, vxc_short8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageus (image2d_t image, int2 coord, vxc_ushort8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageh (image2d_t image, int2 coord, vxc_half8 color) _RET_ + +_EXT_ void viv_intrinsic_vx_write_imagec (image1d_t image, int coord, vxc_char16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageuc (image1d_t image, int coord, vxc_uchar16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_images (image1d_t image, int coord, vxc_short8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageus (image1d_t image, int coord, vxc_ushort8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageh (image1d_t image, int coord, vxc_half8 color) _RET_ + +_EXT_ void viv_intrinsic_vx_write_imagec (image1d_array_t image, int2 coord, vxc_char16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageuc (image1d_array_t image, int2 coord, vxc_uchar16 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_images (image1d_array_t image, int2 coord, vxc_short8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageus (image1d_array_t image, int2 coord, vxc_ushort8 color) _RET_ +_EXT_ void viv_intrinsic_vx_write_imageh (image1d_array_t image, int2 coord, vxc_half8 color) _RET_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_AbsDiff_uc(vxc_uchar16 a, vxc_uchar16 b) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_AbsDiff_c(vxc_char16 a, vxc_char16 b) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_AbsDiff_s(vxc_short8 a, vxc_short8 b) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_AbsDiff_us(vxc_ushort8 a, vxc_ushort8 b) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_IAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_IAdd_c(vxc_char16 a, vxc_char16 b, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_IAdd_s(vxc_short8 a, vxc_short8 b, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_IAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_IAccSq_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_IAccSq_c(vxc_char16 a, vxc_char16 b, uint Imm) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_IAccSq_s(vxc_short8 a, vxc_short8 b, uint Imm) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_IAccSq_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_Lerp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_float c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_Lerp_c(vxc_char16 a, vxc_char16 b, vxc_float c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_Lerp_s(vxc_short8 a, vxc_short8 b, vxc_float c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_Lerp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_float c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_Filter_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_filter_mode f) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_Filter_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_filter_mode f) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_Filter_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_filter_mode f) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_Filter_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_filter_mode f) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_MagPhase_uc(vxc_uchar16 a, vxc_uchar16 b) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_MagPhase_c(vxc_char16 a, vxc_char16 b) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_MagPhase_s(vxc_short8 a, vxc_short8 b) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_MagPhase_us(vxc_ushort8 a, vxc_ushort8 b) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_MulShift_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_MulShift_c(vxc_char16 a, vxc_char16 b, uint Imm) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_MulShift_s(vxc_short8 a, vxc_short8 b, uint Imm) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_MulShift_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm) _RET0_ + +/* Clamp: clamps up to 16 values to a min and.or max value + * + * Syntax: + * r = Clamp(a, b, c) ; + * r = ClampBoolean(a, b, c) ; // boolean mode + * Semantics: + * r[i] = clamp(a[i], b[i], c[i]) ; i E [0, elem(r) ) + * + * In boolean mode it will write a 0 in the result if the value + * is inside the specified min/max range, otherwise all 1s will + * be written to the result. + */ +_EXT_ vxc_uchar16 viv_intrinsic_vx_Clamp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_Clamp_c(vxc_char16 a, vxc_char16 b, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_Clamp_s(vxc_short8 a, vxc_short8 b, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_Clamp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vx_ClampBoolean_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_ClampBoolean_c(vxc_char16 a, vxc_char16 b, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_ClampBoolean_s(vxc_short8 a, vxc_short8 b, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_ClampBoolean_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_BiLinear_uc(vxc_uchar16 a, vxc_uchar16 b, float2 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_BiLinear_c(vxc_char16 a, vxc_char16 b, float2 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_BiLinear_s(vxc_short8 a, vxc_short8 b, float2 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_BiLinear_us(vxc_ushort8 a, vxc_ushort8 b, float2 c) _RET0_ + + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_SelectAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_512bits c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_SelectAdd_c(vxc_char16 a, vxc_char16 b, vxc_512bits c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_SelectAdd_s(vxc_short8 a, vxc_short8 b, vxc_512bits c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_SelectAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_512bits c) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vx_AtomicAdd_uc(vxc_uchar16 * a, vxc_int offset, vxc_uchar16 c) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vx_AtomicAdd_c(vxc_char16 * a, vxc_int offset, vxc_char16 c) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vx_AtomicAdd_s(vxc_short8 * a, vxc_int offset, vxc_short8 c) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vx_AtomicAdd_us(vxc_ushort8 * a, vxc_int offset, vxc_ushort8 c) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_BitExtract_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vx_BitExtract_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vx_BitReplace_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vx_BitReplace_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c) _RET0_ + + + + + + +_EXT_ vxc_char16 viv_intrinsic_vxmc_read_imagec (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_read_imageuc (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_read_images (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_read_imageus (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_read_imageh (image2d_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vxmc_read_imagec (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_read_imageuc (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_read_images (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_read_imageus (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_read_imageh (image1d_t image, int coord, int offsetX, vxc_modifier modifier) _RET0_ + +_EXT_ vxc_char16 viv_intrinsic_vxmc_read_imagec (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_read_imageuc (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_read_images (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_read_imageus (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_read_imageh (image1d_array_t image, int2 coord, int offsetXY, vxc_modifier modifier) _RET0_ + + +_EXT_ void viv_intrinsic_vxmc_write_imagec (image2d_t image, int2 coord, vxc_char16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageuc (image2d_t image, int2 coord, vxc_uchar16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_images (image2d_t image, int2 coord, vxc_short8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageus (image2d_t image, int2 coord, vxc_ushort8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageh (image2d_t image, int2 coord, vxc_half8 color, vxc_modifier modifier) _RET_ + +_EXT_ void viv_intrinsic_vxmc_write_imagec (image1d_t image, int coord, vxc_char16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageuc (image1d_t image, int coord, vxc_uchar16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_images (image1d_t image, int coord, vxc_short8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageus (image1d_t image, int coord, vxc_ushort8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageh (image1d_t image, int coord, vxc_half8 color, vxc_modifier modifier) _RET_ + +_EXT_ void viv_intrinsic_vxmc_write_imagec (image1d_array_t image, int2 coord, vxc_char16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageuc (image1d_array_t image, int2 coord, vxc_uchar16 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_images (image1d_array_t image, int2 coord, vxc_short8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageus (image1d_array_t image, int2 coord, vxc_ushort8 color, vxc_modifier modifier) _RET_ +_EXT_ void viv_intrinsic_vxmc_write_imageh (image1d_array_t image, int2 coord, vxc_half8 color, vxc_modifier modifier) _RET_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_AbsDiff_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_AbsDiff_c(vxc_char16 a, vxc_char16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_AbsDiff_s(vxc_short8 a, vxc_short8 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_AbsDiff_us(vxc_ushort8 a, vxc_ushort8 b, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_IAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_IAdd_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_IAdd_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_IAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_IAccSq_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_IAccSq_c(vxc_char16 a, vxc_char16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_IAccSq_s(vxc_short8 a, vxc_short8 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_IAccSq_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_Lerp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_float c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_Lerp_c(vxc_char16 a, vxc_char16 b, vxc_float c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_Lerp_s(vxc_short8 a, vxc_short8 b, vxc_float c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_Lerp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_float c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_Filter_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_Filter_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_Filter_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_Filter_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_MagPhase_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_MagPhase_c(vxc_char16 a, vxc_char16 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_MagPhase_s(vxc_short8 a, vxc_short8 b, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_MagPhase_us(vxc_ushort8 a, vxc_ushort8 b, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_MulShift_uc(vxc_uchar16 a, vxc_uchar16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_MulShift_c(vxc_char16 a, vxc_char16 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_MulShift_s(vxc_short8 a, vxc_short8 b, uint Imm, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_MulShift_us(vxc_ushort8 a, vxc_ushort8 b, uint Imm, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uint viv_intrinsic_vxmc_DP16x1(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int viv_intrinsic_vxmc_DP16x1(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_float viv_intrinsic_vxmc_DP16x1(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint2 viv_intrinsic_vxmc_DP8x2(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vxmc_DP8x2(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_float2 viv_intrinsic_vxmc_DP8x2(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint4 viv_intrinsic_vxmc_DP4x4(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vxmc_DP4x4(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_float4 viv_intrinsic_vxmc_DP4x4(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uchar8 viv_intrinsic_vxmc_DP2x8(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_char8 viv_intrinsic_vxmc_DP2x8(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_half8 viv_intrinsic_vxmc_DP2x8(vxc_half8 a, vxc_half8 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint viv_intrinsic_vxmc_DP32x1(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int viv_intrinsic_vxmc_DP32x1(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint2 viv_intrinsic_vxmc_DP16x2(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vxmc_DP16x2(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint4 viv_intrinsic_vxmc_DP8x4(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vxmc_DP8x4(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_DP4x8(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_DP4x8(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_DP2x16(vxc_uchar16 a, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_DP2x16(vxc_char16 a, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uint viv_intrinsic_vxmc_DP32x1_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int viv_intrinsic_vxmc_DP32x1_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint2 viv_intrinsic_vxmc_DP16x2_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int2 viv_intrinsic_vxmc_DP16x2_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uint4 viv_intrinsic_vxmc_DP8x4_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_int4 viv_intrinsic_vxmc_DP8x4_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_DP4x8_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_DP4x8_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_DP2x16_b(vxc_uchar16 a_hi, vxc_uchar16 a_lo, vxc_uchar16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_DP2x16_b(vxc_char16 a_hi, vxc_char16 a_lo, vxc_char16 b, vxc_modifier modifier, vxc_512bits u) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_Clamp_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_Clamp_c(vxc_char16 a, vxc_char16 b, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_Clamp_s(vxc_short8 a, vxc_short8 b, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_Clamp_us(vxc_ushort8 a, vxc_ushort8 b, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_BiLinear_uc(vxc_uchar16 a, vxc_uchar16 b, float2 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_BiLinear_c(vxc_char16 a, vxc_char16 b, float2 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_BiLinear_s(vxc_short8 a, vxc_short8 b, float2 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_BiLinear_us(vxc_ushort8 a, vxc_ushort8 b, float2 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_SelectAdd_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_512bits c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_SelectAdd_c(vxc_char16 a, vxc_char16 b, vxc_512bits c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_SelectAdd_s(vxc_short8 a, vxc_short8 b, vxc_512bits c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_SelectAdd_us(vxc_ushort8 a, vxc_ushort8 b, vxc_512bits c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_AtomicAdd_uc(vxc_uchar16 * a, vxc_int offset, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_char16 viv_intrinsic_vxmc_AtomicAdd_c(vxc_char16 * a, vxc_int offset, vxc_char16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_short8 viv_intrinsic_vxmc_AtomicAdd_s(vxc_short8 * a, vxc_int offset, vxc_short8 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_AtomicAdd_us(vxc_ushort8 * a, vxc_int offset, vxc_ushort8 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_BitExtract_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar8 viv_intrinsic_vxmc_BitExtract_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ + + +_EXT_ vxc_ushort8 viv_intrinsic_vxmc_BitReplace_us(vxc_ushort8 a, vxc_ushort8 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ +_EXT_ vxc_uchar16 viv_intrinsic_vxmc_BitReplace_uc(vxc_uchar16 a, vxc_uchar16 b, vxc_uchar16 c, vxc_modifier modifier) _RET0_ + + +vxc_char2 viv_intrinsic_vx_vload2(size_t Offset, char *Pointer) { + vxc_char2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_char2)); + return dest; +} + +vxc_char4 viv_intrinsic_vx_vload4(size_t Offset, char *Pointer) { + vxc_char4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_char4)); + return dest; +} + +vxc_char8 viv_intrinsic_vx_vload8(size_t Offset, char *Pointer) { + vxc_char8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_char8)); + return dest; +} + +vxc_char16 viv_intrinsic_vx_vload16(size_t Offset, char *Pointer) { + vxc_char16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_char16)); + return dest; +} + +vxc_uchar2 viv_intrinsic_vx_vload2(size_t Offset, uchar *Pointer) { + vxc_uchar2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_uchar2)); + return dest; +} + +vxc_uchar4 viv_intrinsic_vx_vload4(size_t Offset, uchar *Pointer) { + vxc_uchar4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_uchar4)); + return dest; +} + +vxc_uchar8 viv_intrinsic_vx_vload8(size_t Offset, uchar *Pointer) { + vxc_uchar8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_uchar8)); + return dest; +} + +vxc_uchar16 viv_intrinsic_vx_vload16(size_t Offset, uchar *Pointer) { + vxc_uchar16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_uchar16)); + return dest; +} + +vxc_short2 viv_intrinsic_vx_vload2(size_t Offset, short *Pointer) { + vxc_short2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_short2)); + return dest; +} + +vxc_short4 viv_intrinsic_vx_vload4(size_t Offset, short *Pointer) { + vxc_short4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_short4)); + return dest; +} + +vxc_short8 viv_intrinsic_vx_vload8(size_t Offset, short *Pointer) { + vxc_short8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_short8)); + return dest; +} + +vxc_short16 viv_intrinsic_vx_vload16(size_t Offset, short *Pointer) { + vxc_short16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_short16)); + return dest; +} + +vxc_ushort2 viv_intrinsic_vx_vload2(size_t Offset, ushort *Pointer) { + vxc_ushort2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_ushort2)); + return dest; +} + +vxc_ushort4 viv_intrinsic_vx_vload4(size_t Offset, ushort *Pointer) { + vxc_ushort4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_ushort4)); + return dest; +} + +vxc_ushort8 viv_intrinsic_vx_vload8(size_t Offset, ushort *Pointer) { + vxc_ushort8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_ushort8)); + return dest; +} + +vxc_ushort16 viv_intrinsic_vx_vload16(size_t Offset, ushort *Pointer) { + vxc_ushort16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_ushort16)); + return dest; +} + +vxc_half2 viv_intrinsic_vx_vload2(size_t Offset, half *Pointer) { + vxc_half2 dest; + VXC_OP2(vload2, dest, Pointer, Offset * sizeof(vxc_half2)); + return dest; +} + +vxc_half4 viv_intrinsic_vx_vload4(size_t Offset, half *Pointer) { + vxc_half4 dest; + VXC_OP2(vload4, dest, Pointer, Offset * sizeof(vxc_half4)); + return dest; +} + +vxc_half8 viv_intrinsic_vx_vload8(size_t Offset, half *Pointer) { + vxc_half8 dest; + VXC_OP2(vload8, dest, Pointer, Offset * sizeof(vxc_half8)); + return dest; +} + +vxc_half16 viv_intrinsic_vx_vload16(size_t Offset, half *Pointer) { + vxc_half16 dest; + VXC_OP2(vload16, dest, Pointer, Offset * sizeof(vxc_half16)); + return dest; +} + + +void viv_intrinsic_vx_vstore2(vxc_char2 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_char2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_char4 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_char4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_char8 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_char8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_char16 Data, size_t Offset, char * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_char16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_uchar2 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_uchar2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_uchar4 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_uchar4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_uchar8 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_uchar8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_uchar16 Data, size_t Offset, uchar * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_uchar16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_short2 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_short2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_short4 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_short4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_short8 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_short8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_short16 Data, size_t Offset, short * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_short16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_ushort2 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_ushort2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_ushort4 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_ushort4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_ushort8 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_ushort8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_ushort16 Data, size_t Offset, ushort * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_ushort16), Data); +} + +void viv_intrinsic_vx_vstore2(vxc_half2 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore2, Pointer, Offset * sizeof(vxc_half2), Data); +} + +void viv_intrinsic_vx_vstore4(vxc_half4 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore4, Pointer, Offset * sizeof(vxc_half4), Data); +} + +void viv_intrinsic_vx_vstore8(vxc_half8 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore8, Pointer, Offset * sizeof(vxc_half8), Data); +} + +void viv_intrinsic_vx_vstore16(vxc_half16 Data, size_t Offset, half * Pointer) { + VXC_OP3_NoDest(vstore16, Pointer, Offset * sizeof(vxc_half16), Data); +} + +#undef _RET0_ +#undef _RET_ +#undef _EXT_ + +#ifdef __cplusplus +} +#endif + +#endif +typedef struct +{ + size_t size; + global char* item; +} vx_array_char; + +typedef struct +{ + size_t size; + global unsigned char* item; +} vx_array_uchar; + +typedef struct +{ + size_t size; + global short* item; +} vx_array_short; + +typedef struct +{ + size_t size; + global unsigned short* item; +} vx_array_ushort; + +typedef struct +{ + size_t size; + global int* item; +} vx_array_int; + +typedef struct +{ + size_t size; + global unsigned int* item; +} vx_array_uint; + + +typedef struct +{ + size_t size; + global float * item; +} vx_array_float; + +typedef struct +{ + size_t size; + global unsigned char* item; +} vx_lut_uchar; + +typedef struct +{ + size_t size; + global unsigned short* item; +} vx_lut_ushort; + +typedef struct +{ + size_t columns; + size_t rows; + global short* matrix; + uint scale; +} vx_convolution; + +typedef struct +{ + size_t columns; + size_t rows; + global char* matrix; +} vx_matrix_char; + +typedef struct +{ + size_t columns; + size_t rows; + global unsigned char* matrix; +} vx_matrix_uchar; + +typedef struct +{ + size_t columns; + size_t rows; + global short* matrix; +} vx_matrix_short; + +typedef struct +{ + size_t columns; + size_t rows; + global unsigned short* matrix; +} vx_matrix_ushort; + +typedef struct +{ + size_t columns; + size_t rows; + global int* matrix; +} vx_matrix_int; + +typedef struct +{ + size_t columns; + size_t rows; + global unsigned int* matrix; +} vx_matrix_uint; + +typedef struct +{ + size_t columns; + size_t rows; + global float* matrix; +} vx_matrix_float; + +typedef struct +{ + int type; + uint value; + uint lower; + uint upper; + uint trueValue; + uint falseValue; +} vx_threshold; + +typedef struct { + int dst_width; + int dst_height; + global float* ptr; +} vx_remap; + +typedef struct +{ + int bins; + int rang; + int offset; + float window_r; + global int* ptr; +} vx_distribution; + +typedef struct _vxc_pyramid +{ + float scale; + uint width; + uint height; + uint format; + uint levelCount; + _viv_image2d_array_t imageArray; +} vxc_pyramid; + +#endif + +#endif diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..c26c2bc Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libGAL.so new file mode 100644 index 0000000..4c5fdaa Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..816a76e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..687ebe9 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..8a1185c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libVSC_Lite.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libVSC_Lite.so new file mode 100644 index 0000000..22d0cc3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/libVSC_Lite.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..1264ce3 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64-mini/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/bin/rknn_server b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/bin/rknn_server new file mode 100644 index 0000000..fb5ab85 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/bin/rknn_server differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..c26c2bc Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libCLC.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libCLC.so new file mode 100644 index 0000000..100c901 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libCLC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libGAL.so new file mode 100644 index 0000000..87da367 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..816a76e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNGPUBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNGPUBinary.so new file mode 100644 index 0000000..8987d4d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNGPUBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNVXCBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNVXCBinary.so new file mode 100644 index 0000000..0793f10 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libNNVXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenCL.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenCL.so.1.2 new file mode 100644 index 0000000..94ce057 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenCL.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..23f5ae6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..8a1185c Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOvx12VXCBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOvx12VXCBinary.so new file mode 100644 index 0000000..fbdc57d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libOvx12VXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libVSC.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libVSC.so new file mode 100644 index 0000000..ed6e52a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libVSC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libneuralnetworks.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libneuralnetworks.so new file mode 100644 index 0000000..ea9768d Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/libneuralnetworks.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/librknn_runtime.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/librknn_runtime.so new file mode 100644 index 0000000..a207e3f Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-aarch64/usr/lib/librknn_runtime.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/bin/rknn_server b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/bin/rknn_server new file mode 100644 index 0000000..3731a46 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/bin/rknn_server differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libArchModelSw.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libArchModelSw.so new file mode 100644 index 0000000..267dfbb Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libArchModelSw.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libCLC.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libCLC.so new file mode 100644 index 0000000..642b34b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libCLC.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libGAL.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libGAL.so new file mode 100644 index 0000000..109e22a Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libGAL.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNArchPerf.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNArchPerf.so new file mode 100644 index 0000000..e75cf4b Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNArchPerf.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNGPUBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNGPUBinary.so new file mode 100644 index 0000000..609e6a2 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNGPUBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNVXCBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNVXCBinary.so new file mode 100644 index 0000000..f7c1460 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libNNVXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenCL.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenCL.so.1.2 new file mode 100644 index 0000000..73e5bfe Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenCL.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenVX.so.1.2 b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenVX.so.1.2 new file mode 100644 index 0000000..e896ca1 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenVX.so.1.2 differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenVXU.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenVXU.so new file mode 100644 index 0000000..ccae677 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOpenVXU.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOvx12VXCBinary.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOvx12VXCBinary.so new file mode 100644 index 0000000..ac8f547 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libOvx12VXCBinary.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libneuralnetworks.so b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libneuralnetworks.so new file mode 100644 index 0000000..2266108 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/linux-armhf/usr/lib/libneuralnetworks.so differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore.ko new file mode 100644 index 0000000..8ebbbaa Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_fedora.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_fedora.ko new file mode 100644 index 0000000..1a51915 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_fedora.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_puma.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_puma.ko new file mode 100644 index 0000000..4644e82 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_puma.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_puma_tb.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_puma_tb.ko new file mode 100644 index 0000000..1bebce6 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_puma_tb.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk1806.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk1806.ko new file mode 100644 index 0000000..f69273f Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk1806.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk3399pro-npu-pcie.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk3399pro-npu-pcie.ko new file mode 100644 index 0000000..3c69e5e Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk3399pro-npu-pcie.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk3399pro-npu.ko b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk3399pro-npu.ko new file mode 100644 index 0000000..f694c17 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/drivers/npu_ko/galcore_rk3399pro-npu.ko differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/README.md b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/README.md new file mode 100644 index 0000000..4846874 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/README.md @@ -0,0 +1,47 @@ +# Introduction +RKNN-Toolkit is a software development kit that provides users with model conversion, inference and performance evaluation on PC and Rockchip NPU platforms(RK1808/RK1806/RK3399Pro/RV1109/RV1126). +RKNN-Toolkit-Lite provides Python programming interfaces for Rockchip NPU platform to help users deploy RKNN models and accelerate the implementation of AI applications. +Note: +- For the deployment of the RKNN model, please refer to: + - RK1808/RK1806/RV1109/RV1126: https://github.com/rockchip-linux/rknpu + - RK3399Pro: https://github.com/airockchip/RK3399Pro_npu +- For RK3566/RK3568/RK3588/RK3588S/RV1103/RV1106, please refer to: + - https://github.com/rockchip-linux/rknn-toolkit2 + - https://github.com/rockchip-linux/rknpu2 +# Download +From version 1.3.0, some wheel packages are larger than 100MB, can not be uploaded directly. So, you need to go to the releases page to download. +You can download from releases page: https://github.com/rockchip-linux/rknn-toolkit/releases +- All wheel packages are in compressed file: [rknn-toolkit-v1.7.3-packages.tar.gz](https://github.com/rockchip-linux/rknn-toolkit/releases/download/v1.7.3/rknn-toolkit-v1.7.3-packages.tar.gz "rknn-toolkit-v1.7.3-packages.tar.gz") or [rknn-toolkit-v1.7.3-packages.zip](https://github.com/rockchip-linux/rknn-toolkit/releases/download/v1.7.3/rknn-toolkit-v1.7.3-packages.zip "rknn-toolkit-v1.7.3-packages.zip ") +- All examples, docs and platform-tools are in compressed file: [Source code(zip)](https://github.com/rockchip-linux/rknn-toolkit/archive/v1.7.3.zip "Source code(zip)") or [Source code(tar.gz)](https://github.com/rockchip-linux/rknn-toolkit/archive/v1.7.3.tar.gz "Source code(tar.gz)") +- You can also download all packages, docker image, examples, docs and platform-tools from baidu cloud: [rknn-toolkit](https://eyun.baidu.com/s/3bqgIr0N "RKNN-Toolkit"), fetch code: rknn +- You can download RKNN Toolkit Lite packages and examples from [rknn-toolkit-lite](rknn-toolkit-lite) +# Checksums +## MD5 +``` +7d672e911c26af34112bbfcfed86aef7 rknn_toolkit-1.7.3-cp35-cp35m-linux_aarch64.whl +e751a1c2782879dedbe3904448e07105 rknn_toolkit-1.7.3-cp36-cp36m-linux_x86_64.whl +20db420731b4976b15b0fbddef9984e3 rknn_toolkit-1.7.3-cp36-cp36m-macosx_10_15_x86_64.whl +1ebba11b78766cd320a470bb397578cb rknn_toolkit-1.7.3-cp36-cp36m-win_amd64.whl +0cdd9c288a748bcef84848fd5dc12d80 rknn_toolkit-1.7.3-cp37-cp37m-linux_aarch64.whl +f06e1f88864c5a4759e4258cb536c38d rknn_toolkit-1.7.3-cp37-cp37m-macosx_10_15_x86_64.whl +8e5c63a241b809b78ca65d226344d0eb rknn_toolkit-1.7.3-cp38-cp38-linux_x86_64.whl + +a24f157407e16bc255fc387404eb2030 rknn-toolkit-v1.7.3-packages.tar.gz +8dbeeecb06b9201b9f464909ad8d9544 rknn-toolkit-v1.7.3-packages.zip + +4b50d8966908e80567843c3623e33d46 rknn_toolkit_lite-1.7.3-cp36-cp36m-linux_aarch64.whl +dc669361506646104e823d569055b849 rknn_toolkit_lite-1.7.3-cp36-cp36m-linux_x86_64.whl +15a26aad303769f8f2f38f5888529a57 rknn_toolkit_lite-1.7.3-cp36-cp36m-macosx_10_15_x86_64.whl +cd490d13dc1e40e24ab76100a9b82ced rknn_toolkit_lite-1.7.3-cp36-cp36m-win_amd64.whl +17f10789ec42fdc687c3c02ef6dc1141 rknn_toolkit_lite-1.7.3-cp37-cp37m-linux_aarch64.whl +030a09ed522620aa6dfb4ccac578518b rknn_toolkit_lite-1.7.3-cp37-cp37m-linux_armv7l.whl +079aaf9c2c39b2c2a6858688ed733973 rknn_toolkit_lite-1.7.3-cp37-cp37m-macosx_10_15_x86_64.whl +b1b32a4e8803dd9303ab1a72ae8deccf rknn_toolkit_lite-1.7.3-cp38-cp38-linux_x86_64.whl +``` +# Feedback and Community Support +- QQ Group Chat: 1025468710 (full, please join group 2) +- QQ Group Chat2: 547021958 +

+ + +
diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_CN.pdf b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_CN.pdf new file mode 100644 index 0000000..9e80b4b --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_CN.pdf @@ -0,0 +1,1290 @@ + 瑞芯微电子股份有限公司 + +密级状态:绝密( ) 秘密( ) 内部( ) 公开(√ ) + +Rockchip User Guide RKNN API + + (技术部,图形计算平台中心) + +文件状态: 当前版本: 1.7.3 + HPC +[ ] 正在修改 作 者: 2022-8-13 + 熊伟 +[√] 正式发布 完成日期: 2022-8-13 + + 审 核: + + 完成日期: + + 瑞芯微电子股份有限公司 + Rockchips Semiconductor Co . , Ltd + + (版本所有,翻版必究) + 瑞芯微电子股份有限公司 + + 更新记录 + + 版本 修改人 修改日期 修改说明 核定人 +v0.9.6 杨华聪 +V0.9.7 杨华聪 2018-12-20 初始版本 熊伟 +V0.9.8 杨华聪 熊伟 + 2019-01-16 1) 添加 RKNN SDK 开发流程说明 卓鸿添 +V1.3.3 卓鸿添 2019-06-05 2) 添加 RKNN Python API 说明 卓鸿添 +V1.4.0 卓鸿添 2020-06-02 1) 添加 RKNN API 库的说明 卓鸿添 + 2) 更新 rknn example 和 rknn-toolkit 路 +v1.6.0 洪启飞 卓鸿添 + 径 +v1.6.1 洪启飞 3) 修正文档中错误 卓鸿添 +v1.7.0 洪启飞 1)支持 RV1126/RV1109 +v1.7.1 洪启飞 2)删除 python 支持说明,关于 python +v1.7.3 洪启飞 支持见 RKNN Toolkit Lite 相关文档。 + + 2020-09-10 1)增加错误码 + + 2021-1-15 1)增加 Matmul 高级 API 说明 + 2)增加一组设置输入和一组获取输出 + 的接口 + 3)增加做量化和反量化的算法说明 + 4)增加 NPU 驱动说明 + 5)增加 FAQ + + 2021-4-26 1)更新 Matmul 高级 API 说明 + + 2021-8-5 1)更新版本号 卓鸿添 + 2021-12-2 1)rknn_inputs_set 接口单通道输入性能 卓鸿添 + 2022-8-13 优化 卓鸿添 + 2)已知 Bug 修复 + 1)更新版本号 + + 1 + 瑞芯微电子股份有限公司 + +1 主要功能说明 ................................................................................................................................................... 5 +2 硬件平台 ........................................................................................................................................................... 5 +3 使用说明 ........................................................................................................................................................... 5 + + 3.1 RKNN SDK 开发流程 ............................................................................................................................... 5 + 3.2 RKNN C API ...............................................................................................................................................6 + + 3.2.1 RKNN API 库 ...................................................................................................................................... 6 + 3.2.2 EXAMPLE 使用说明 ..........................................................................................................................6 + 3.2.3 API 流程说明 ...................................................................................................................................... 7 + + 3.2.3.1 API 内部处理流程 ..........................................................................................................................................9 + 3.2.3.2 量化和反量化 ..............................................................................................................................................10 + 3.2.3.3 零拷贝 .......................................................................................................................................................... 11 + 3.2.4 API 详细说明 .................................................................................................................................... 12 + 3.2.4.1 rknn_init ........................................................................................................................................................ 12 + 3.2.4.2 rknn_destroy ..................................................................................................................................................13 + 3.2.4.3 rknn_query .................................................................................................................................................... 13 + 3.2.4.4 rknn_inputs_set ............................................................................................................................................. 16 + 3.2.4.5 rknn_inputs_map ...........................................................................................................................................16 + 3.2.4.6 rknn_inputs_sync ...........................................................................................................................................18 + 3.2.4.7 rknn_inputs_unmap .......................................................................................................................................18 + 3.2.4.8 rknn_run ........................................................................................................................................................ 19 + 3.2.4.9 rknn_outputs_get ...........................................................................................................................................19 + 3.2.4.10 rknn_outputs_release .................................................................................................................................. 20 + 3.2.4.11 rknn_outputs_map ....................................................................................................................................... 21 + 3.2.4.12 rknn_outputs_sync .......................................................................................................................................21 + + 2 + 瑞芯微电子股份有限公司 + 3.2.4.13 rknn_outputs_unmap ...................................................................................................................................22 + 3.2.5 RKNN 数据结构定义 ....................................................................................................................... 22 + 3.2.5.1 rknn_input_output_num ................................................................................................................................ 22 + 3.2.5.2 rknn_tensor_attr ............................................................................................................................................23 + 3.2.5.3 rknn_input ..................................................................................................................................................... 24 + 3.2.5.4 rknn_tensor_mem ..........................................................................................................................................24 + 3.2.5.5 rknn_output ................................................................................................................................................... 25 + 3.2.5.6 rknn_perf_detail ............................................................................................................................................ 25 + 3.2.5.7 rknn_sdk_version .......................................................................................................................................... 25 + 3.2.6 RKNN 返回值错误码 ....................................................................................................................... 26 +4 高级 API 使用说明 ........................................................................................................................................ 27 + 4.1 MATMUL 算子库 ........................................................................................................................................27 + 4.1.1 简介 ...................................................................................................................................................27 + 4.1.2 数据结构定义 ...................................................................................................................................27 + 4.1.3 详细 API 说明 .................................................................................................................................. 28 + 4.1.3.1 rknn_matmul_load ........................................................................................................................................ 28 + 4.1.3.2 rknn_matmul_run ..........................................................................................................................................28 + 4.1.3.3 rknn_matmul_unload .................................................................................................................................... 29 + 4.1.4 实现限制 ...........................................................................................................................................29 + 4.1.4.1 维度限制 ......................................................................................................................................................29 + 4.1.4.2 输入数据类型限制 ......................................................................................................................................30 + 4.1.5 基准测试 ...........................................................................................................................................30 +5 NPU 驱动说明 .................................................................................................................................................31 + 5.1.1 NPU 驱动目录说明 ...........................................................................................................................31 + 5.1.2 NPU full driver 与 mini driver 的区别 ..............................................................................................31 + + 3 + 瑞芯微电子股份有限公司 +6 FAQ ..................................................................................................................................................................32 + + 6.1.1 输入输出数据格式问题 ...................................................................................................................32 + 6.1.2 输入输出接口使用问题 ...................................................................................................................33 + 6.1.3 API 调用流程问题 ............................................................................................................................ 33 + 6.1.4 性能问题 ...........................................................................................................................................34 + + 4 + 瑞芯微电子股份有限公司 + +1 主要功能说明 + + RKNN SDK 为 RK1808 等 带 有 NPU 的 平 台 提 供 编 程 接 口 , 能 够 帮 助 用 户 部 署 使 用 +RKNN-Toolkit 导出的 RKNN 模型,加速 AI 应用的落地。 + +2 硬件平台 + +本文档适用如下硬件平台: + 1) RK1808、RK1806 + 2) RV1126、RV1109 + +注意:本文档不适用 RK3399Pro +下面的说明以 RK1808 为例,也同时适用上述其他平台。 + +3 使用说明 + +3.1 RKNN SDK 开发流程 + + 在使用 RKNN SDK 之前,用户首先需要使用 RKNN-Toolkit 工具将用户的模型转换为 RKNN + +模型,用户可以在 https://github.com/rockchip-linux/rknn-toolkit 获取工具的完整 + +安装包及使用文档。 + 成功转换生成 RKNN 模型之后,用户可以先通过 RKNN-Toolkit 连接 RK1808 等开发板进行联 + +机调试,确保模型的精度性能符合要求。 + 得到 RKNN 模型文件之后,用户可以选择使用 C 或 Python 接口在 RK1808 等平台开发应用, + +后续章节将说明如何在 RK1808 等平台上基于 RKNN SDK 进行开发。 + + 5 + 瑞芯微电子股份有限公司 + +3.2 RKNN C API + +3.2.1 RKNN API 库 + + RKNN SDK 所提供的库和头文件位于/external/rknpu/rknn/ +rknn_api/librknn_api 目录下,开发者可以在自己应用中引用即可开发应用。 + + 需要注意的是,RK1808 和 RK3399Pro 平台的 RKNN API 是兼容的,两者开发的应用程序 +可以很方便地移植。但是使用过程中需要注意要区分两个平台的 librknn_api.so,如果开发者使 +用 RK3399Pro 的 librknn_api.so 将无法在 RK1808 平台上运行。开发者可以使用以下方法来区分 +librknn_api.so 的平台: + + $ strings librknn_api.so |grep version + librknn_api version 1.7.3 (cf7f05f build: 2022-08-13 10:59:33) + +3.2.2 EXAMPLE 使用说明 + + SDK 提供了 Linux 平台的 MobileNet 图像分类、MobileNet SSD 目标检测以及 YoloV3 Tiny + 目标检测 Demo。这些 Demo 能够为客户基于 RKNN SDK 开发自己的 AI 应用提供参考。Demo + 代码位于/external/rknpu/rknn/rknn_api/examples 目录。下面以 rknn_mobilenet_demo 为例 + 来讲解如何快速上手运行。 + + 1) 编译 Demo + + cd examples/rknn_mobilenet_demo + # 修改 build.sh 中的 GCC_COMPILER,指向目标平台的编译器 + ./build.sh + 2) 部署到 RK1808 设备 + + adb push install/rknn_mobilenet_demo /userdata/ + + 3) 运行 Demo + + 6 + 瑞芯微电子股份有限公司 + + adb shell + cd /userdata/rknn_mobilenet_demo/ + ./rknn_mobilenet_demo model/mobilenet_v1_rk180x.rknn + model/dog_224x224.jpg #for RK1808 + ./rknn_mobilenet_demo model/mobilenet_v1_rv1109_rv1126.rknn + model/dog_224x224.jpg #for RV1109/RV1126 + +3.2.3 API 流程说明 + + 从 RKNN API V1.6.0 版本开始,新增加了一组设置输入的函数: +  rknn_inputs_map +  rknn_inputs_sync +  rknn_inputs_unmap + 以及一组获取输出的函数: +  rknn_outputs_map +  rknn_outputs_sync +  rknn_outputs_unmap + 在设置输入时,用户可以使用 rknn_inputs_set 或者 rknn_inputs_map 系列函数。获取推理 + 的输出时,使用 rknn_outputs_get 或者 rknn_outputs_map 系列函数。特定场景下,使用 map 系 + 列接口可以减少内存拷贝的次数,提高完整推理的速度。 + rknn_inputs_map 系列接口和 rknn_inputs_set 接口的调用流程不同,rknn_outputs_map 系 + 列接口和 rknn_outputs_get 接口的调用流程也不同。两个系列 API 调用流程差异如图 3-1 所示, + 其中(a)为 set/get 系列接口调用流程,(b)为 map 系列接口调用流程。 + + 7 + 瑞芯微电子股份有限公司 + + 图 3-1 使用 set/get 系列(a)和 map 系列(b)接口流程差异 + 设置输入和获取输出接口没有绑定关系,因此可以混合使用 set/get 系列接口和 map 系列 +接口。如图 3-2(c),用户可以使用 rknn_inputs_map 系列接口设置输入,再通过 rknn_outputs_get +接 口 获 取 输 出 , 或 者 如 图 3-2 ( d ) 通 过 rknn_inputs_set 系 列 接 口 设 置 输 入 , 再 使 用 +rknn_outputs_map 接口获取输出。 + + 8 + 瑞芯微电子股份有限公司 + + 图 3-2 混合使用 set/get 系列和 map 系列接口的调用流程 +3.2.3.1 API 内部处理流程 + + 在推理 RKNN 模型时,原始数据要经过输入处理、NPU 运行模型、输出处理三大流程。 + 在典型的图片推理场景中,假设输入数据 data 是 3 通道的图片且为 NHWC 排布格式,运行时 + (Runtime)对数据处 理的流程如图 3-3 所示。在 API 层面上,rknn_inputs_set 接口(当 + pass_through=0 时,详见 rknn_input 结构体)包含了颜色通道交换、归一化、量化、NHWC 转 + 换成 NCHW 的过程,rknn_outputs_get 接口(当 want_float=1 时,详见 rknn_output 结构体) + + 9 + 瑞芯微电子股份有限公司 + +包含了反量化的过程。 + + 图 3-3 完整的图片数据处理流程 + 实际上,对于某些 RKNN 模型,输入处理的流程没有全部执行,例如,当输入数据不是 + 3 通道图像时或者用 rknn-toolkit 导出模型的 config 函数配置为 reorder=”0 1 2”时,没有颜色通 + 道转换流程。当 RKNN 模型输入 tensor 的属性是 NHWC 布局时,没有 NHWC 转换成 NCHW + 的流程。rknn_inputs_se(t 当 pass_through=1 时)和 rknn_inputs_map 不包含任何输入处理流程, + rknn_outputs_get(当 want_float=0 时)和 rknn_outputs_map 不包含任何输出处理流程。此时, + 虽然两组 API 都不包含对应的处理流程,不过,使用 set/get 系列接口会比 map 系列接口多出 + 数据拷贝过程。 + +3.2.3.2 量化和反量化 + + 当使用 rknn_inputs_set(pass_through=1)和 rknn_inputs_map 时,表明在 NPU 推理之前 + 的流程要用户处理。rknn_outputs_map 获取输出后,用户也要做反量化得到 32 位浮点结果。 + + 量化和反量化用到的量化方式、量化数据类型以及量化参数,可以通过 rknn_query 接口 + 查询。目前,RK1808/RK3399Pro/RV1109/RV1126 的 NPU 有非对称量化和动态定点量化两种 + 量化方式,每种量化方式指定相应的量化数据类型。总共有以下四种数据类型和量化方式组 + 合: + +  uint8(非对称量化) +  int8(动态定点) +  int16(动态定点) +  float16(无) + 通常,归一化后的数据用 32 位浮点数保存,32 位浮点转换成 16 位浮点数请参考 IEEE-754 + 标准。假设归一化后的 32 位浮点数据是 D ,下面介绍量化流程: + + 10 + 瑞芯微电子股份有限公司 + +1)float32 转 uint8 +假设输入 tensor 的非对称量化参数是 Sq , ZP ,数据 D 量化过程表示为下式: + + Dq  round (clamp(D / Sq  ZP,0,255)) (3-1) + +上式中,clamp 表示将数值限制在某个范围。round 表示做舍入处理。 +2)float32 转 int8 +假设输入 tensor 的动态定点量化参数是 fl,数据 D 量化过程表示为下式: + + Dq  round (clamp(D * 2 fl ,-128,127)) (3-2) + +3)float32 转 int16 +假设输入 tensor 的动态定点量化参数是 fl,数据 D 量化过程表示为下式: + + Dq  round (clamp(D * 2 fl ,-32768,32767)) (3-3) + +反量化流程是量化的逆过程,可以根据上述量化公式反推出反量化公式,这里不做赘述。 + +3.2.3.3 零拷贝 + + 在特定的条件下,可以把输入数据拷贝次数减少到零,即零拷贝。比如,当 RKNN 模型 +是非对称量化,量化数据类型是 uint8,3 通道的均值是相同的整数同时缩放因子相同的情况 +下,归一化和量化可以省略。证明如下: + +假设输入图像数据是 D f ,量化参数是 Sq , ZP 。 M i 表示第 i 通道的均值, Si 表示第 i + +通道的归一化因子。则第 i 通道归一化后的数据 Di 如下式子: + + Di  (D f  M i ) / Si (3-4) + +数据 Di 量化过程表示为下式: (3-5) + Dq  clamp(Di / Sq  ZP,0,255) + +上述两个式子合并后,可以得出 + + Dq  clamp((D f  Mi ) /(Si * Sq)  ZP) (3-6) +假设量化图片矫正集数据范围包含 0 到 255 的整数值,当 M1  M 2  M 3 ,S1  S2  S3 时, + + 11 + 瑞芯微电子股份有限公司 + +归一化数值范围表示如下: (3-7) + Dmin  (0 - M i ) / Si  M i / Si (3-8) + Dmax  (255 - M i ) / Si + + 因此,量化参数计算如下: + + Sq  (Dmax  Dmin ) / 255  1/Si (3-9) + + ZP  (0  Dmin ) / Sq  M i (3-10) + +把式(3-9)和式(3-10)代入式(3-6),可以得出 D f  Dq ,即符合零拷贝的条件下:3 + +通道的均值是相同的整数同时归一化的缩放因子相同,输入 uint8 数据等于量化后的 uint8 数 +据。 + + 输入零拷贝能降低 CPU 负载,提高整体的推理速度。针对 RGB 或 BGR 输入数据,实现 +输入零拷贝的步骤如下: + + 1)三个通道的均值是相同的整数同时归一化的缩放因子相同。 + 2)在 rknn-toolkit 的 config 函数中,设置 force_builtin_perm=True,导出 NHWC 输入的 +RKNN 模型。 + 3)使用 rknn_inputs_map 接口,获取输入 tensor 内存地址信息。 + 4)往内存地址填充输入数据,比如调用 RGA 缩放函数,目标地址使用 rknn_inputs_map +获取的物理地址。 + 5)调用 rknn_inputs_sync 接口。 + 6)调用 rknn_run 接口。 + 7)调用获取输出接口。 + +3.2.4 API 详细说明 + +3.2.4.1 rknn_init + + rknn_init 初始化函数将创建 rknn_context 对象、加载 RKNN 模型以及根据 flag 执行特定 +的初始化行为。 + + 12 + 瑞芯微电子股份有限公司 + +API rknn_init +功能 初始化 rknn +参数 rknn_context *context:rknn_context 指针。函数调用之后,context 将会被赋值。 + void *model:RKNN 模型的二进制数据。 + uint32_t size:模型大小。 + uint32_t flag:特定的初始化标志。目前 RK1808 平台仅支持以下标志: + + RKNN_FLAG_COLLECT_PERF_MASK:打开性能收集调试开关,打开之后能够通过 + rknn_query 接口查询网络每层运行时间。需要注意,该标志被设置后 rknn_run 的 + 运行时间将会变长。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + rknn_context ctx; + int ret = rknn_init(&ctx, model_data, model_data_size, 0); + +3.2.4.2 rknn_destroy + + rknn_destroy 函数将释放传入的 rknn_context 及其相关资源。 + +API rknn_destroy + +功能 销毁 rknn_context 对象及其相关资源。 + +参数 rknn_context context:要销毁的 rknn_context 对象。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + int ret = rknn_destroy (ctx); + +3.2.4.3 rknn_query + rknn_query 函数能够查询获取到模型输入输出、运行时间以及 SDK 版本等信息。 + + 13 + 瑞芯微电子股份有限公司 + +API rknn_query + +功能 查询模型与 SDK 的相关信息。 + +参数 rknn_context context:rknn_context 对象。 + + rknn_query_cmd cmd:查询命令。 + + void* info:存放返回结果的结构体变量。 + + uint32_t size:info 对应的结构体变量的大小。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 当前 SDK 支持的查询命令如下表所示: + + 查询命令 返回结果结构体 功能 + +RKNN_QUERY_IN_OUT_NUM rknn_input_output_num 查询输入输出 Tensor 个数 + +RKNN_QUERY_INPUT_ATTR rknn_tensor_attr 查询输入 Tensor 属性 + +RKNN_QUERY_OUTPUT_ATTR rknn_tensor_attr 查询输出 Tensor 属性 + +RKNN_QUERY_PERF_DETAIL rknn_perf_detail 查询网络各层运行时间 + +RKNN_QUERY_SDK_VERSION rknn_sdk_version 查询 SDK 版本 + + 接下来的将依次详解各个查询命令如何使用。 + +1) 查询输入输出 Tensor 个数 + 传入 RKNN_QUERY_IN_OUT_NUM 命令可以查询模型输入输出 Tensor 的个数。其中需 + +要先创建 rknn_input_output_num 结构体对象。 + 示例代码如下: + + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, + + sizeof(io_num)); + printf("model input num: %d, output num: %d\n", io_num.n_input, + + io_num.n_output); + +2) 查询输入 Tensor 属性 + 传入 RKNN_QUERY_INPUT_ATTR 命令可以查询模型输入 Tensor 的属性。其中需要先创 + +建 rknn_tensor_attr 结构体对象。 + + 14 + 瑞芯微电子股份有限公司 + +示例代码如下: + +rknn_tensor_attr input_attrs[io_num.n_input]; +memset(input_attrs, 0, sizeof(input_attrs)); +for (int i = 0; i < io_num.n_input; i++) { + + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +3) 查询输出 Tensor 属性 + 传入 RKNN_QUERY_OUTPUT_ATTR 命令可以查询模型输出 Tensor 的属性。其中需要先 + +创建 rknn_tensor_attr 结构体对象。 + 示例代码如下: + +rknn_tensor_attr output_attrs[io_num.n_output]; +memset(output_attrs, 0, sizeof(output_attrs)); +for (int i = 0; i < io_num.n_output; i++) { + + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +4) 查询网络各层运行时间 + 如果在 rknn_init 函数调用时有设置 RKNN_FLAG_COLLECT_PERF_MASK 标志,那么 + +在执行 rknn_run 完成之后,可以传入 RKNN_QUERY_PERF_DETAIL 命令来查询网络每层运 +行时间。其中需要先创建 rknn_perf_detail 结构体对象。 + + 示例代码如下: + +rknn_perf_detail perf_detail; +ret = rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, &perf_detail, + + sizeof(rknn_perf_detail)); +printf("%s", perf_detail.perf_data); + + 注意,用户不需要释放 rknn_perf_detail 中的 perf_data,SDK 会自动管理该 Buffer 内存。 +5) 查询 SDK 版本 + + 传入 RKNN_QUERY_SDK_VERSION 命令可以查询 RKNN SDK 的版本信息。其中需要 +先创建 rknn_sdk_version 结构体对象。 + + 15 + 瑞芯微电子股份有限公司 + + 示例代码如下: + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + + sizeof(rknn_sdk_version)); + printf("sdk api version: %s\n", version.api_version); + printf("driver version: %s\n", version.drv_version); + +3.2.4.4 rknn_inputs_set + + 通过 rknn_inputs_set 函数可以设置模型的输入数据。该函数能够支持多个输入,其中每 + + 个输入是 rknn_input 结构体对象,在传入之前用户需要设置该对象。 + +API rknn_inputs_set + +功能 设置模型输入数据。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + rknn_input inputs[]:输入数据数组,数组每个元素是 rknn_input 结构体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = img_width*img_height*img_channels; + inputs[0].fmt = RKNN_TENSOR_NHWC; + inputs[0].buf = in_data; + + ret = rknn_inputs_set(ctx, 1, inputs); + +3.2.4.5 rknn_inputs_map + rknn_inputs_map 函数用于获取模型输入 tensor 初始化后的存储状态,存储状态包括虚拟 + + 16 + 瑞芯微电子股份有限公司 + + 地址,物理地址,fd,存储空间大小。它需要和 rknn_inputs_sync 接口(见 rknn_inputs_sync + 函数)配合使用,在模型初始化后,用户通过返回的的内存位置设置输入数据,并且在推理 + + 前调用 rknn_inputs_sync 函数。存储状态使用 rknn_tensor_mem 结构体表示。输入参数 mem 是 + + rknn_tensor_mem 结构体数组。 + 目前 ,在 RK1808/RV1109/RV1126 芯片 上,返回 的 fd 是 -1。当 返回的物 理地址 值是 + + 0xffffffffffffffff(2 的 64 次幂-1),表示无法获取正确的物理地址,而虚拟地址仍然有效。如 + 果有多个模型输入 tensor 的存储空间较大,用户可以在挂载驱动时,适当增加模型输入和输 + 出存储空间或者扩增固件中的 CMA 内存空间。以 RV1109_RV1126 为例,配置驱动存储空间, + 可以参考如下修改: + + 把/etc/init.d/S60NPU_init 文件这一行: + insmod /lib/modules/galcore.ko contiguousSize=0x400000 gpuProfiler=1 + 改成 + insmod /lib/modules/galcore.ko contiguousSize=0x600000 gpuProfiler=1 + 然后重启生效。此配置应该大于用户模型输入和输出总大小,但不超过固件中可用的 + + CMA 空间大小。 + +API rknn_inputs_map + +功能 读取输入存储状态信息。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结 + 构体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + 17 + 瑞芯微电子股份有限公司 + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + +3.2.4.6 rknn_inputs_sync + + rknn_inputs_sync 函数将 CPU 缓存写回内存,让设备能获取正确的数据。 + +API rknn_inputs_sync + +功能 同步输入数据。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + + ret = rknn_inputs_sync(ctx, 1, mem); + +3.2.4.7 rknn_inputs_unmap + + rknn_inputs_unmap 函数将清除 rknn_inputs_map 函数获取的输入 tensor 的存储位置信息和 + + 标志。 + +API rknn_inputs_unmap + +功能 清除 rknn_inputs_map 函数获取的输入 tensor 的存储位置信息和标志。 + +参数 rknn_context context:rknn_contex 对象。 + + uint32_t n_inputs:输入数据个数。 + + 18 + 瑞芯微电子股份有限公司 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + ret = rknn_inputs_sync(ctx, 1, mem); + ret = rknn_run(ctx, NULL); + + ret = rknn_inputs_unmap(ctx, 1, mem); + +3.2.4.8 rknn_run + + rknn_run 函数将执行一次模型推理,调用之前需要先通过 rknn_inputs_set 函数设置输入数 + + 据。 + +API rknn_run + +功能 执行一次模型推理。 + +参数 rknn_context context:rknn_context 对象。 + + rknn_run_extend* extend:保留扩展,当前没有使用,传入 NULL 即可。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + ret = rknn_run(ctx, NULL); + +3.2.4.9 rknn_outputs_get + + rknn_outputs_get 函数可以获取模型推理的输出数据。该函数能够一次获取多个输出数据。 + 其 中 每 个 输 出 是 rknn_output 结 构 体 对 象 , 在 函 数 调 用 之 前 需 要 依 次 创 建 并 设 置 每 个 + rknn_output 对象。 + + 对于输出数据的 buffer 存放可以采用两种方式:一种是用户自行申请和释放,此时 + + 19 + 瑞芯微电子股份有限公司 + + rknn_output 对象的 is_prealloc 需要设置为 1,并且将 buf 指针指向用户申请的 buffer;另一种 + 是由 rknn 来进行分配,此时 rknn_output 对象的 is_prealloc 设置为 0 即可,函数执行之后 buf + 将指向输出数据。 + +API rknn_outputs_get + +功能 获取模型推理输出。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + rknn_output outputs[]:输出数据的数组,其中数组每个元素为 rknn_output 结构体对 + 象,代表模型的一个输出。 + + rknn_output_extend* extend:保留扩展,当前没有使用,传入 NULL 即可 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下: + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) { + + outputs[i].want_float = 1; + } + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + +3.2.4.10 rknn_outputs_release + + rknn_outputs_release 函数将释放 rknn_outputs_get 函数得到的输出的相关资源。 + +API rknn_outputs_release + +功能 释放 rknn_output 对象。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + rknn_output outputs[]:要销毁的 rknn_output 数组。 + +返回值 int 错误码(见 rknn 返回值错误码) + + 示例代码如下 + + 20 + 瑞芯微电子股份有限公司 + + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + +3.2.4.11 rknn_outputs_map + + rknn_outputs_map 函 数 获 取 模 型 初 始 化 后 输 出 tensor 的 存 储 状 态 。 需 要 和 + + rknn_outputs_sync 函 数 ( 见 rknn_outputs_sync 函 数 ) 配 合 使 用 , 在 模 型 初 始 化 后 调 用 + rknn_outputs_map 接口,接着每次推理完调用 rknn_outputs_sync 接口。如果用户需要 32 位浮 + 点类型的数据,需要根据量化方式和量化的数据类型做反量化。 + +API rknn_outputs_map + +功能 读取输出存储状态信息。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_map(ctx, 1, mem); + +3.2.4.12 rknn_outputs_sync + + 当使用 rknn_outputs_map 接口映射完模型运行时模型输出 tensor 存储状态信息后,为确 + + 保缓存一致性,使用 rknn_outputs_sync 函数让 CPU 获取推理完最新的数据。 + +API rknn_outputs_sync + +功能 推理完,同步最新的输出数据。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + + 21 + 瑞芯微电子股份有限公司 + + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_sync(ctx, io_num.n_output, mem); + +3.2.4.13 rknn_outputs_unmap + + rknn_outputs_unmap 函数将清除 rknn_outputs_map 函数获取的输出 tensor 的存储状态。 + +API rknn_outputs_unmap + +功能 清除 rknn_outputs_map 函数获取的输出 tensor 的存储状态。 + +参数 rknn_context context:rknn_context 对象。 + + uint32_t n_outputs:输出数据个数。 + rknn_tensor_mem mem[]:存储状态信息数组,数组每个元素是 rknn_tensor_mem 结构 + + 体对象。 + +返回值 int 错误码(见 rknn 返回值错误码) + +示例代码如下: + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_unmap(ctx, io_num.n_output,mem); + +3.2.5 RKNN 数据结构定义 + +3.2.5.1 rknn_input_output_num + 结构体 rknn_input_output_num 表示输入输出 Tensor 个数,其结构体成员变量如下表所示: + + 22 + 成员变量 数据类型 瑞芯微电子股份有限公司 + n_input uint32_t +n_output uint32_t 含义 + + 输入 Tensor 个数 + 输出 Tensor 个数 + +3.2.5.2 rknn_tensor_attr + +结构体 rknn_tensor_attr 表示模型的 Tensor 的属性,结构体的定义如下表所示: + +成员变量 数据类型 含义 + +index uint32_t 表示输入输出 Tensor 的索引位置。 + +n_dims uint32_t Tensor 维度个数。 + + dims uint32_t[] Tensor 各维度值。 + name char[] Tensor 名称。 +n_elems Tensor 数据元素个数。 + uint32_t + +size uint32_t Tensor 数据所占内存大小。 + +fmt rknn_tensor_format Tensor 维度的格式,有以下格式: + + RKNN_TENSOR_NCHW + RKNN_TENSOR_NHWC + +type rknn_tensor_type Tensor 数据类型,有以下数据类型: + + RKNN_TENSOR_FLOAT32 + RKNN_TENSOR_FLOAT16 + RKNN_TENSOR_INT8 + RKNN_TENSOR_UINT8 + +qnt_type RKNN_TENSOR_INT16 + rknn_tensor_qnt_type Tensor 量化类型,有以下的量化类型: + + RKNN_TENSOR_QNT_NONE:未量化; + RKNN_TENSOR_QNT_DFP:动态定点量化; + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC : 非 + + 23 + fl int8_t 瑞芯微电子股份有限公司 + zp uint32_t + 对称量化。 +scale float RKNN_TENSOR_QNT_DFP 量化类型的参数。 + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 量 化 + 类型的参数。 + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 量 化 + 类型的参数。 + +3.2.5.3 rknn_input + + 结构体 rknn_input 表示模型的一个数据输入,用来作为参数传入给 rknn_inputs_set 函数。 +结构体的定义如下表所示: + +成员变量 数据类型 含义 + +index uint32_t 该输入的索引位置。 + +buf void* 输入数据 Buffer 的指针。 + +size uint32_t 输入数据 Buffer 所占内存大小。 + +pass_through uint8_t 设置为 1 时会将 buf 存放的输入数据直接设置给 + 模型的输入节点,不做任何预处理。 + +type rknn_tensor_type 输入数据的类型。 + +fmt rknn_tensor_format 输入数据的格式。 + +3.2.5.4 rknn_tensor_mem + +结构体 rknn_tensor_mem 表示 tensor 初始化后的存储状态信息,用来作为参数传入给 + +rknn_inputs_map 系列和 rknn_outputs_map 系列函数。结构体的定义如下表所示: + +成员变量 数据类型 含义 + +logical_addr void* 该输入的虚拟地址。 + +physical_addr uint64_t 该输入的物理地址。 + +fd int32_t 该输入的 fd。 + + 24 + size uint32_t 瑞芯微电子股份有限公司 + handle uint32_t + priv_data 该输入 tensor 占用的内存大小。 +reserved_flag void* 该输入的 handle。 + uint64_t 保留的数据。 + 保留的标志位。 + +3.2.5.5 rknn_output + +结构体 rknn_output 表示模型的一个数据输出,用来作为参数传入给 rknn_outputs_get 函 + +数,在函数执行后,结构体对象将会被赋值。结构体的定义如下表所示: + +成员变量 数据类型 含义 + +want_float uint8_t 标识是否需要将输出数据转为 float 类型输出。 + +is_prealloc uint8_t 标识存放输出数据的 Buffer 是否是预分配。 + +index uint32_t 该输出的索引位置。 + +buf void* 输出数据 Buffer 的指针。 + +size uint32_t 输出数据 Buffer 所占内存大小。 + +3.2.5.6 rknn_perf_detail + +结构体 rknn_perf_detail 表示模型的性能详情,结构体的定义如下表所示: + +成员变量 数据类型 含义 + +perf_data char* 性能详情包含网络每层运行时间,能够直接打印 + + 出来查看。 + +data_len uint64_t 存放性能详情的字符串数组的长度。 + +3.2.5.7 rknn_sdk_version + +结构体 rknn_sdk_version 用来表示 RKNN SDK 的版本信息,结构体的定义如下: + + 25 + 成员变量 数据类型 瑞芯微电子股份有限公司 + api_version char[] + drv_version char[] 含义 + SDK 的版本信息。 + SDK 所基于的驱动版本信息。 + +3.2.6 RKNN 返回值错误码 + +RKNN API 函数的返回值错误码定义如下表所示 + + 错误码 错误详情 + +RKNN_SUCC(0) 执行成功 + +RKNN_ERR_FAIL(-1) 执行出错 + +RKNN_ERR_TIMEOUT(-2) 执行超时 + +RKNN_ERR_DEVICE_UNAVAILABLE(-3) NPU 设备不可用 + +RKNN_ERR_MALLOC_FAIL(-4) 内存分配失败 + +RKNN_ERR_PARAM_INVALID(-5) 传入参数错误 + +RKNN_ERR_MODEL_INVALID(-6) 传入的 RKNN 模型无效 + +RKNN_ERR_CTX_INVALID(-7) 传入的 rknn_context 无效 +RKNN_ERR_INPUT_INVALID(-8) 传入的 rknn_input 对象无效 +RKNN_ERR_OUTPUT_INVALID(-9) 传入的 rknn_output 对象无效 + +RKNN_ERR_DEVICE_UNMATCH(-10) 版本不匹配 + +RKNN_ERR_INCOMPATILE_PRE_COMPILE_M RKNN 模型使用 pre_compile 模式,但是和当前驱动不 + +ODEL(-11) 兼容 + +RKNN_ERR_INCOMPATILE_OPTIMIZATION_L RKNN 模型设置了优化等级的选项,但是和当前驱动 + +EVEL_VERSION(-12) 不兼容 + +RKNN_ERR_TARGET_PLATFORM_UNMATCH RKNN 模型和当前平台不兼容,一般是将 RK1808 的平 + +(-13) 台的 RKNN 模型放到了 RV1109/RV1126 上。 + +RKNN_ERR_NON_PRE_COMPILED_MODEL_ RKNN 模型不是 pre_compile 模式,在 mini-driver 上无 + +ON_MINI_DRIVER(-14) 法执行 + + 26 + 瑞芯微电子股份有限公司 + +4 高级 API 使用说明 + +4.1 Matmul 算子库 + +4.1.1 简介 + + 高级 API 旨在利用 NPU 高算力特性,执行特定的数学运算,提供简洁的接口调用,达到 +计算加速的效果。其中,Matmul 算子库是一个定点数矩阵乘法的加速库。该操作定义如下: + + C  AT * B + 这里: + A,B 和 C 是 2 维矩阵 + A 是一个 K*M 的矩阵, + B 是一个 K*N 的矩阵 + C 是一个 M*N 的矩阵 + +4.1.2 数据结构定义 + + rknn_matmul_handle_t 表示用于执行 Matmul 算子操作的句柄,它包含了运行时环境的上 +下文和输入 buffer 的信息。结构体的定义如下表所示: + +成员变量 数据类型 含义 + + A void* 运算时第一个矩阵 buffer 的指针。 + + B void* 运算时第二个矩阵 buffer 的指针。 + +M int32_t A 矩阵的低维度元素个数。 + + K int32_t A 和 B 矩阵的高维度元素个数。 + + N int32_t B 矩阵的低维度元素个数。 + +in_dtype rknn_tensor_type 输入数据的类型。 + +rknn_ctx rknn_context 运行时的上下文对象。 + + 27 + 瑞芯微电子股份有限公司 + +4.1.3 详细 API 说明 + +4.1.3.1 rknn_matmul_load + + rknn_matmul_load 加载函数将加载用户创建的输入 buffer,返回 rknn_matmul_handle_t 类 + 型对象。Matmul 算子 API 不负责管理输入 buffer 的生命周期,用户要确保输入 buffer 在 Matmul + + 算子 API 调用内有效。 + +API rknn_matmul_load + +功能 初始化和设置输入 buffer 指针。 + +参数 void *a:用户创建的第一个矩阵 buffer 的指针,只支持输入是 8-bit 无符号整型或 8-bit + 有符号整型的一维数组指针。 + + void *b:用户创建的第二个矩阵 buffer 的指针,只支持输入是 8-bit 无符号整型或 8-bit + 有符号整型的一维数组指针。 + + int32_t M:A 矩阵的低维度元素个数。 + + int32_t K:A 和 B 矩阵的高维度元素个数。 + int32_t N:B 矩阵的低维度元素个数。 + + rknn_tensor_type dtype:用户指定的输入数据类型,只支持 RKNN_TENSOR_INT8 或 + RKNN_TENSOR_UINT8 类型 + +返回值 rknn_matmul_handle_t 对象。 + + 示例代码如下: + + rknn_tensor_type dtype = RKNN_TENSOR_INT8; + int8_t x[256*1] = {0}; + int8_t y[256*4096] = {0}; + rknn_matmul_handle_t handle= rknn_matmul_load(x,y,1,256,4096,dtype); + +4.1.3.2 rknn_matmul_run + + 在 rknn_matmul_load 被调用后和执行 rknn_matmul_run 前,输入 buffer 的数据由外部更新, + 不用重新调用 rknn_matmul_load。 + + 28 + 瑞芯微电子股份有限公司 + +API rknn_matmul_run + +功能 执行 Matmul 操作。 + +参数 rknn_matmul_handle_t matmul_handle:由 rknn_matmul_load 接口返回的句柄。 + + float *c:用户创建的矩阵浮点 buffer 的指针,用于获取输出。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + ... + float out_fp32_buf[4096] = {0}; + rknn_matmul_run(handle,out_fp32_buf); + +4.1.3.3 rknn_matmul_unload + +API rknn_matmul_unload + +功能 销毁 Matmul 算子运行时上下文。 + +参数 rknn_matmul_handle_t matmul_handle:由 rknn_matmul_load 接口返回的句柄。 + +返回值 int 错误码(见 rknn 返回值错误码)。 + + 示例代码如下: + + rknn_matmul_unload(handle); + +4.1.4 实现限制 + + Matmul 算子库是基于 NPU 的硬件架构实现,为了达到精度和速度的平衡,有一些限制如下。 + +4.1.4.1 维度限制 + + 按照上述操作描述,该库实现了 M=1 的矩阵乘法。具体而言,Matmul 算子输入 A 必须是 Kx1 +形状的 buffer,即用户必须创建一块包含 K 个 8-bit 无符号整型或者 8-bit 有符号整型元素的数据。 +当算子库运行在 Mini driver 上,K 的值只能设置为 128 或 256 或 512,N 固定为 4096,而在 Full driver +上运行,没有此限制,但建议 K 的值为 128,256,512,1024,2048,N 取 2 的偶数次幂,建议 N + + 29 + 瑞芯微电子股份有限公司 + +不大于 4096。 + +4.1.4.2 输入数据类型限制 + + 只支持 8-bit 无符号整型和 8-bit 有符号整型两种输入。 + +4.1.5 基准测试 + + 输入的两个矩阵使用随机数情况下,在 RV1109-EVB 板子上实测结果如表-1 所示。速度是 + +rknn_matmul_run 接口调用循环 100 次后的平均时间,平均相对误差是 NPU 和 CPU 上执行相同算 + +法的结果的误差值,具体公式是: + + (abs(R1  R2 ) / R2 ) / N + + k + + 其中, + + R1 是 Matmul 算子库输出向量,包含 N 个元素。 + R2 是 CPU 输出向量,包含 N 个元素。 + + 表-1 Matmul 算子库速度/精度结果(RV1109,int8) + +K N 速度(ms) 平均相对误差 + +128 1024 1.0 0.00034 + +256 1024 1.6 0.00032 + +512 2024 3.0 -0.00015 + +1024 1024 5.4 0.00047 + +128 4096 3.0 0.00051 + +256 4096 5.6 0.00024 + +512 4096 10.7 0.00024 + +1024 4096 20.9 0.00051 + +注意,速度可能因为 NPU 驱动版本不同而有些许差异。误差值则根据每次测试的随机数不同也可 +能有些许差异。 + + 30 + 瑞芯微电子股份有限公司 + +5 NPU 驱动说明 + +5.1.1 NPU 驱动目录说明 + + NPU 的驱动在$SDK/external/rknpu/drivers/目录下或者 + +https://github.com/rockchip-linux/rknpu/tree/master/drivers + +其中的编译、安装规则参考$SDK/buildroot/package/rockchip/rknpu/rknpu.mk +drivers/ +├── common +├── linux-aarch64 (for RK1808 npu full driver) +├── linux-aarch64-mini (for RK1808 npu mini driver) +├── linux-armhf (for RK1806 npu full driver) +├── linux-armhf-mini(for RK1806 npu mini driver) +├── linux-armhf-puma (for RV1126/RV1109 npu full driver) +├── linux-armhf-puma-mini(for RV1126/RV1109 npu mini driver) +├── npu_ko (NPU kernel driver) + +5.1.2 NPU full driver 与 mini driver 的区别 + + 主要包含以下几点: + 1)Mini driver 只支持预编译的 rknn 模型,如果跑非预编译模型,会出现 +RKNN_ERR_MODEL_INVALID 的错误,从 1.6.0 开始,会返回 +RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER 的错误; + 2)Full driver 支持 RKNN Toolkit 的联机调试功能,mini driver 不支持; + 3)Mini driver 库大小比 full driver 小很多,以 RV1109/RV1126 1.6.0 驱动为例,full driver 大 +小为 87MB,mini driver 大小为 7.1MB,可以有效的节省 flash 大小。 + 4)Mini driver 库运行时占用的内存比 full driver 小。 + + 31 + 瑞芯微电子股份有限公司 + +6 FAQ + +6.1.1 输入输出数据格式问题 + +6.1.1.1 三通道图片数据输入,采用 RGB 还是 BGR 排布? + + 建议用户输入数据统一使用 RGB 排布。在导出 RKNN 模型时,config 函数的 reorder_channel +参数,有以下两种可能: + + 1)如果原始模型使用 BGR 图片训练,reorder_channel='2 1 0'。 + 2)如果原始模型使用 RGB 图片训练,reorder_channel='0 1 2'。 + +6.1.1.2 rknn_input 结构体该设置的 RKNN_TENSOR_NHWC 还是 RKNN_TENSOR_NCHW? + 两种设置耗时为何不同? + + rknn_input 结构体根据用户自己的数据格式而定,C API 内部会自动转换成 NPU 需要的格式。 +耗时不同的原因是不同输入格式计算量不同,优化方式也不同。 + +6.1.1.3 没量化的 RKNN 模型,输出 rknn_tensor_attr 里面 size 和 rknn_outputs_get 接口返 + 回的 rknn_output 的 size 为何不同? + + 没量化 RKNN 模型,NPU 内部输出数据类型是 float16,大小是元素数量*2 字节。当用户设 +置 want_float=1 时,想要的是 float32 数据,float16 会转换成 float32,大小是元素数量*4 字节。 + +6.1.1.4 rknn_output.index 是用户输入还是驱动返回? + +驱动返回。 + +6.1.1.5 rknn_tensor_attr 中的 dims 数组为何会出现 0? + +0 表示该维度无效。rknn_tensor_attr 中的 n_dims 表示 dims 数组的有效维度数量。 + + 32 + 瑞芯微电子股份有限公司 + +6.1.1.6 rknn_tensor_attr 中的 dims 数组顺序与 rknn_toolkit 的获取的 numpy 的顺序相反? + 是。C API 中的数组排布跟 python 相反,比如 rknn-toolkit 的 run()接口获得 numpy 输出形 + +状是[1,255,20,20],C API 中 dims 数组是{20,20,255,1}。 + +6.1.2 输入输出接口使用问题 + +6.1.2.1 pass_through 用法以及使用 rknn_inputs_map 接口时,如何预处理数据? + 请参考 https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples 下的 + +rknn_pass_through_demo 示例。 +6.1.2.2 使用 rknn_inputs_map 或者 rknn_outputs_map 获取的物理地址为什么会无效?如何 + + 获取有效的物理地址? + + 输入/输出无法分配到物理连续的内存,可能的原因有: + 1)输入/输出的占用空间过大,超过了总的物理连续的内存大小(默认是 4MB)。 + 2)系统中没有足够的物理连续的内存可用。 + 3)导出 RKNN 模型时,config 函数添加如下参数:output_optimize=1。 + 用户可以尝试重启系统,或者让 NPU 驱动挂载时配置更大的连续地址空间,配置方法参考 +rknn_inputs_map 接口说明。 + +6.1.3 API 调用流程问题 + +6.1.3.1 rknn_init 成功后,模型文件占用内存是否可以释放? + 可以。 + +6.1.3.2 rknn_output.is_prealloc=1 时,rknn_outputs_release 是否需要调用? + 需要。 + + 33 + 瑞芯微电子股份有限公司 + +6.1.4 性能问题 + +6.1.4.1 rknn_init 耗时过长? + + 使用预编译模型。使用方法参考 https://github.com/rockchip-linux/rknn-toolkit/tree/master/doc 下 +User Guide 文档的相关章节。 + +6.1.4.2 rknn_inputs_set 接口耗时过长? + + 可能原因是数据量大或格式转换耗时长。如果是格式转换耗时长,用户可以尝试 pass_through +用法自己做转换。转换方式请参考 +https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples 下的 +rknn_pass_through_demo 示例。或者尝试在导出 RKNN 模型时,config 函数添加如下参数: +output_optimize=1。 + +6.1.4.3 rknn_outputs_get 接口耗时过长? + + 可能原因是数据量大或转换格式耗时长。如果是转换格式耗时长,用户可以尝试设置 +want_float=0, 再 自 己 做 转 换 。 或 者 尝 试 在 导 出 RKNN 模 型 时 , config 函 数 添 加 如 下 参 数 : +output_optimize=1。 + + 34 + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_EN.pdf b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_EN.pdf new file mode 100644 index 0000000..1fe93f2 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/doc/Rockchip_User_Guide_RKNN_API_V1.7.3_EN.pdf @@ -0,0 +1,1473 @@ + www.rock-chips.com + +Classification Level: Top Secret( ) Secret( ) Internal( ) Public(√) + +Rockchip User Guide RKNN API + +(Technology Department, Graphic Compute Platform Center) + +Mark: Version: 1.7.3 + +[ ] Changing Author: HPC + +[√] Released Completed Date: 13/Aug/2022 + + Reviewer: Vincent + + Reviewed Date: 213/Aug/2022 + + 瑞芯微电子股份有限公司 + Rockchip Electronics Co., Ltd. + + (Copyright Reserved) + www.rock-chips.com + + Revision History + +Version Modifier Date Modify Description Reviewer +v0.9.7 Yang Huacong +V0.9.8 Yang Huacong 25/Jan/2019 Initial version Zhuo + 5/Jun/2019 Hongtian +V1.3.3 Randall 2/June/2020 1. Add RKNN API Library description +V1.4.0 Randall 2. Update rknn example and rknn-toolkit Zhuo + Hongtian +v1.6.0 Chifred Hong path + 3. Fix some mistake Randall +v1.6.1 Chifred Hong 1. Support RV1109/RV1126 +v1.7.0 Chifred Hong 2. Remove the python support +v1.7.1 Chifred Hong instructions, see the RKNN Toolkit Lite +v1.7.3 Chifred Hong related documentation for python support. + + 10/Sep/2020 1. Add some error code Randall + + 15/Jan/2021 1. Add Matmul advanced API Randall + 2. Add a set of API for setting inputs and + a set of API for obtaining outputs + 3. Add quantization and dequantization + algorithm description + 4. Add NPU driver description + 5. Add FAQ + + 26/Apr/2021 1. Update Matmul advanced API Randall + + 5/Aug/2021 1. Update Version number Randall + Randall + 2/Dec/2021 1. Single-channel input performance Randall + optimization + 2. Fix bug + + 13/Aug/2022 1. Update Version number + + 1 + www.rock-chips.com + +1 OVERVIEW ..................................................................................................................................................... 5 +2 SUPPORTED HARDWARE PLATFORMS ................................................................................................. 5 +3 INSTRUCTIONS ..............................................................................................................................................5 + + 3.1 RKNN SDK DEVELOPMENT PROCESS ........................................................................................................ 5 + 3.2 RKNN C API ...............................................................................................................................................6 + + 3.2.1 RKNN API Library .............................................................................................................................. 6 + 3.2.2 EXAMPLES .........................................................................................................................................6 + 3.2.3 API process description ........................................................................................................................7 + + 3.2.3.1 API internal processing flow ........................................................................................................................... 9 + 3.2.3.2 Quantification and dequantization ................................................................................................................10 + 3.2.3.3 Zero copy .......................................................................................................................................................12 + 3.2.4 API Reference .................................................................................................................................... 13 + 3.2.4.1 rknn_init ........................................................................................................................................................ 13 + 3.2.4.2 rknn_destroy ..................................................................................................................................................14 + 3.2.4.3 rknn_query .................................................................................................................................................... 15 + 3.2.4.4 rknn_inputs_set ............................................................................................................................................. 17 + 3.2.4.5 rknn_inputs_map ...........................................................................................................................................18 + 3.2.4.6 rknn_inputs_sync ...........................................................................................................................................19 + 3.2.4.7 rknn_inputs_unmap .......................................................................................................................................20 + 3.2.4.8 rknn_run ........................................................................................................................................................ 21 + 3.2.4.9 rknn_outputs_get ...........................................................................................................................................21 + 3.2.4.10 rknn_outputs_release .................................................................................................................................. 22 + 3.2.4.11 rknn_outputs_map ....................................................................................................................................... 23 + 3.2.4.12 rknn_outputs_sync .......................................................................................................................................23 + + 2 + www.rock-chips.com + 3.2.4.13 rknn_outputs_unmap ...................................................................................................................................24 + 3.2.5 RKNN DataStruct Define .................................................................................................................. 25 + 3.2.5.1 rknn_input_output_num ................................................................................................................................ 25 + 3.2.5.2 rknn_tensor_attr ............................................................................................................................................25 + 3.2.5.3 rknn_input ..................................................................................................................................................... 26 + 3.2.5.4 rknn_tensor_mem ..........................................................................................................................................27 + 3.2.5.5 rknn_output ................................................................................................................................................... 27 + 3.2.5.6 rknn_perf_detail ............................................................................................................................................ 28 + 3.2.5.7 rknn_sdk_version .......................................................................................................................................... 28 + 3.2.6 RKNN Error Code ............................................................................................................................. 28 +4 ADVANCED API INSTRUCTIONS .............................................................................................................29 + 4.1 MATMUL OPERATOR LIBRARY ....................................................................................................................29 + 4.1.1 Introduction ........................................................................................................................................29 + 4.1.2 Data structure definition .....................................................................................................................30 + 4.1.3 Detailed API description .................................................................................................................... 31 + 4.1.3.1 rknn_matmul_load ........................................................................................................................................ 31 + 4.1.3.2 rknn_matmul_run ..........................................................................................................................................31 + 4.1.3.3 rknn_matmul_unload .................................................................................................................................... 32 + 4.1.4 Implementation restrictions ................................................................................................................32 + 4.1.4.1 Dimensional restrictions ............................................................................................................................... 33 + 4.1.4.2 Input data type restriction ............................................................................................................................. 33 + 4.1.5 Benchmark ......................................................................................................................................... 33 +5 NPU DRIVER DESCRIPTION .................................................................................................................... 35 + 5.1.1 Directory structure description ...........................................................................................................35 + 5.1.2 The difference between NPU full driver and mini driver .................................................................. 35 + + 3 + www.rock-chips.com +6 FAQ ..................................................................................................................................................................36 + + 6.1.1 Input and output data format issues ................................................................................................... 36 + 6.1.2 Input and output interface usage problems ........................................................................................ 37 + 6.1.3 API call process issues ....................................................................................................................... 38 + 6.1.4 Performance issues .............................................................................................................................38 + + 4 + www.rock-chips.com + +1 Overview + + RKNN SDK provides a programming interface for platforms with NPU such as RK1808, which can +help users deploy RKNN models exported using RKNN-Toolkit. + +2 Supported hardware platforms + +This document applies to the following hardware platforms: + 1) RK1808, RK1806 + 2) RV1126, RV1109 + +The following description takes RK1808 as an example and also applies to other platforms mentioned +above. + +3 Instructions +3.1 RKNN SDK Development Process + + Before using the RKNN SDK, users first need to use the RKNN-Toolkit tool to convert the + user's model to the RKNN model. The user can obtain the tool's complete installation package and + documentation at https://github.com/rockchip-linux/rknn-toolkit . + + After successful conversion to the RKNN model, users can first connect to the RK1808 device + via RKNN-Toolkit for online debugging to ensure that the accuracy and performance of the model + meet the requirements. + + After getting the RKNN model file, users can choose using C or Python interface to develop + the application. The following chapters will explain how to develop application based on the RKNN + SDK on RK1808 platform. + + 5 + www.rock-chips.com + +3.2 RKNN C API + +3.2.1 RKNN API Library + + The libraries and header files provided by the RKNN SDK are located at +/external/rknpu/rknn/rknn_api/librknn_api directory, developers can use to develop +applications. + + It should be noted that the RKNN API of the RK1808 and RK3399Pro platforms is compatible, +and applications developed by both can be easily ported. However, you need to pay attention to +distinguish between the two platforms librknn_api.so, if the developer uses RK3399Pro's +librknn_api.so will not be able to run on the RK1808 platform. Developers can use the following +methods to distinguish the platform of librknn_api.so. + + $ strings librknn_api.so |grep version + librknn_api version 1.7.3 (cf7f05f build: 2022-08-13 10:59:33) + +3.2.2 EXAMPLES + + The SDK provides MobileNet image classification, MobileNet SSD object detection, and Yolo + v3 object detection demos. These demos provide reference for developer to develop applications + based on the RKNN SDK. The emo code is located in the + /external/rknpu/rknn/rknn_api/examples directory. Let's take rknn_mobilenet_demo as an + example to explain how to get started quickly. + + 1) Compile Demo Source Code + + cd examples/rknn_mobilenet_demo + # modify `GCC_COMPILER` on `build.sh` for target platform, then execute + ./build.sh + 2) Deploy to the RK1808 device + + adb push install/rknn_mobilenet_demo /userdata/ + + 3) Run Demo + + 6 + www.rock-chips.com + + adb shell + cd /userdata/rknn_mobilenet_demo/ + ./rknn_mobilenet_demo model/mobilenet_v1_rk180x.rknn + model/dog_224x224.jpg # RK180x + ./rknn_mobilenet_demo model/mobilenet_v1_rv1109_rv1126.rknn + model/dog_224x224.jpg # RV1109/RV1126 + +3.2.3 API process description + + From RKNN API V1.6.0, a new set of functions for setting input have been added: +  rknn_inputs_map +  rknn_inputs_sync +  rknn_inputs_unmap + And a set of functions to get the output: +  rknn_outputs_map +  rknn_outputs_sync +  rknn_outputs_unmap + When setting input, users can use rknn_inputs_set or rknn_inputs_map series of functions. + When obtaining the output of inference, use the rknn_outputs_get or rknn_outputs_map series of + functions. In certain scenarios, using the map series of API can reduce the number of memory copies + and improve the speed of complete inference. + The calling process of the rknn_inputs_map series interface and the rknn_inputs_set interface is + different, and the calling process of the rknn_outputs_map series interface and the rknn_outputs_get + interface are also different. The difference between the two series of API call flow is shown in Figure + 3-1, where (a) is the set/get series interface call flow, (b) is the map series interface call flow. + + 7 + www.rock-chips.com + + Figure 3-1 callling process difference between set/get series (a) and map series (b) + There is no binding relationship between the set input and get output API, so set/get series +interfaces and map series interfaces can be mixed. As shown in Figure 3-2(c), the user can use the +rknn_inputs_map series interface to set the input, and then get the output through the +rknn_outputs_get interface, or as Figure 3-2(d) set the input through the rknn_inputs_set series +interface, and then use the rknn_outputs_map interface to get the output. + + 8 + www.rock-chips.com + + Figure 3-2 The calling process of mixed use of set/get series and map series interfaces +3.2.3.1 API internal processing flow + + During inference of RKNN model, the original data has to go through three processes: input + processing, NPU running model, and output processing. In a typical picture inference scenario, + assuming that the input data is a 3-channel picture and is in the NHWC layout format, the data + processing flow at runtime is shown in Figure 3-3. At the API level, the rknn_inputs_set interface + (when pass_through=0, see the rknn_input structure for details) includes the process of swapping + + 9 + www.rock-chips.com + + color channel, normalization, quantization, and conversion of NHWC to NCHW. The + rknn_outputs_get interface (when want_float=1, see rknn_output structure) contains the process of + dequantization. + + Figure 3-3 Normal mode image data processing flow + In fact, for some RKNN models, the Runtime input processing flow is not all executed. For + example, when the input data is not a 3-channel image or the config function of the rknn-toolkit is + configured as reorder=”0 1 2” when exporting model, there is no color channel swapping process. + When the attribute of RKNN model input tensor is NHWC layout, there is no process for converting + NHWC to NCHW. rknn_inputs_set (when pass_through=1) and rknn_inputs_map do not contain any + input processing flow, rknn_outputs_get (when want_float=0) and rknn_outputs_map do not contain + any output processing flow. At this time, although the two sets of APIs do not include the + corresponding processing flow, using the set/get series interface will have more data copying process + than the map series interface. + +3.2.3.2 Quantification and dequantization + + When using rknn_inputs_set (pass_through=1) and rknn_inputs_map, it indicates that the + process before NPU inference needs to be processed by the user. After rknn_outputs_map gets the + output, the user also needs to dequantize output to get the 32-bit floating point result. + + The quantization method, quantization data type and quantization parameters used in + quantization and dequantization can be queried through the rknn_query interface. Currently, the NPU + of RK1808/RK3399Pro/RV1109/RV1126 has two quantization methods: asymmetric quantization + and dynamic fixed-point quantization. Each quantization method specifies the corresponding + quantized data type. There are a total of four combinations of data types and quantification methods: + + 10 + www.rock-chips.com + +  uint8 (asymmetric quantization) +  int8 (dynamic fixed-point) +  int16 (dynamic fixed-point) +  float16 (none) + Normally, the normalized data is stored in 32-bit floating point data. For conversion of 32-bit +floating point data to 16-bit floating point data, please refer to the IEEE-754 standard. Assuming that +the normalized 32-bit floating point data is D , the following describes the quantization process: + 1) float32 to uint8 + +Assuming that the asymmetric quantization parameter of the input tensor is Sq , ZP , the data + +quantization process is expressed as the following formula: + + Dq  round (clamp(D / Sq  ZP,0,255)) (3-1) + +In the above formula, clamp means to limit the value to a certain range. round means rounding + +processing. + +2) float32 to int8 + +Assuming that the dynamic fixed-point quantization parameter of the input tensor is fl, the data + +quantization process is expressed as the following formula: + + Dq  round (clamp(D * 2 fl ,-128,127)) (3-2) + + 3) float32 to int16 + Assuming that the dynamic fixed-point quantization parameter of the input tensor is fl, the data +quantization process is expressed as the following formula: + + Dq  round (clamp(D * 2 fl ,-32768,32767)) (3-3) + + The dequantization process is the inverse process of quantization, and the inverse quantization +formula can be deduced according to the above quantization formula, which will not be repeated +here. + + 11 + www.rock-chips.com + +3.2.3.3 Zero copy + + In specific case, the number of input data copies can be reduced to 0, that is, zero copy. For +example, when the RKNN model is asymmetric quantization, the quantization data type is uint8, the +mean value of the 3 channels is the same integer and the scaling factor is the same, the normalization +and quantization can be omitted. The proof is as follows: + +Assume that the input image data is D f , and the quantization parameter is Sq , ZP . M i + +Represents the mean value of the i-th channel, and Si represents the normalization factor of the i-th +channel. Then the normalized data of the i-th channel is as follows: + + Di  (D f  M i ) / Si (3-4) + +The data quantification process is expressed as the following formula: + + Dq  clamp(Di / Sq  ZP,0,255) (3-5) + +After combining the above two formulas, we can get (3-6) + Dq  clamp((D f  Mi ) /(Si * Sq)  ZP) + +Assuming that the data range of the calibration data set contains integer values from 0 to 255, + +when M1  M 2  M3 , S1  S2  S3 , the normalized value range is expressed as follows: + + Dmin  (0 - M i ) / Si  M i / Si (3-7) + + Dmax  (255 - M i ) / Si (3-8) + +So, the quantization parameter is calculated as follows: + + Sq  (Dmax  Dmin ) / 255  1/Si (3-9) + + ZP  (0  Dmin ) / Sq  M i (3-10) + + Substituting formula (3-9) and formula (3-10) into formula (3-6), it can be concluded that under +the condition of zero-copy: the mean value of the 3 channels is the same integer and the normalized +scaling factor is the same , The input uint8 data is equal to the quantized uint8 data. + + Input zero copy can reduce the CPU load and improve the speed of complete inference. For + + 12 + www.rock-chips.com + + RGB or BGR input data, the steps to achieve input zero-copy are as follows: + 1) The mean value of the three channels is the same integer and the normalized scaling factor is + + the same. + 2) In the config function of rknn-toolkit, set force_builtin_perm=True to export the RKNN + + model input by NHWC. + 3) Use the rknn_inputs_map interface to obtain the input tensor memory address information. + 4) Fill the memory address with input data, such as calling the RGA resize function, the target + + address uses the physical address obtained by rknn_inputs_map. + 5) Call the rknn_inputs_sync interface. + 6) Call the rknn_run interface. + 7) Call the get output interface. + +3.2.4 API Reference + +3.2.4.1 rknn_init + The rknn_init function will create a rknn_context object, load the RKNN model, and perform + + specific initialization behavior based on the flag. + + 13 + www.rock-chips.com + +API rknn_init + +Description Initialize rknn + +Parameters rknn_context *context:Pointer to rknn_context object. After the function is called, the + + context object will be assigned. + + void *model:Binary data for the RKNN model. + + uint32_t size:Model size + + uint32_t flag:A specific initialization flag. Currently supports following flags: + + RKNN_FLAG_COLLECT_PERF_MASK : Open the performance collection debugging + + switch. After opening, you can query the running time of each layer of the network + + through the rknn_query interface. Note that the running time of rknn_run will be + + longer after this flag is set. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_context ctx; + int ret = rknn_init(&ctx, model_data, model_data_size, 0); + +3.2.4.2 rknn_destroy + + The rknn_destroy function will release the rknn_context object and its associated resources. + +API rknn_destroy + +Description Destroy the rknn_context object and its related resources. + +Parameters rknn_context context: The rknn_context object to be destroyed. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + 14 + www.rock-chips.com + + int ret = rknn_destroy (ctx); + +3.2.4.3 rknn_query + + The rknn_query function can query the information of model input and output tensor attribute, + + performance information and SDK version etc. + +API rknn_query + +Description Query the information about the model and the SDK. + +Parameters rknn_context context: The object of rknn_contex. + + rknn_query_cmd cmd: Query command. + + void* info: Structure object that stores the result of the query. + + uint32_t size: the size of the info Structure object. + +Return int: Error code (See RKNN Error Code). + + Currently, the SDK supports the following query commands: + + Query command Return result structure Function + +RKNN_QUERY_IN_OUT_NUM rknn_input_output_num Query the number of input and output + + Tensor. + +RKNN_QUERY_INPUT_ATTR rknn_tensor_attr Query input Tensor attribute. + +RKNN_QUERY_OUTPUT_ATTR rknn_tensor_attr Query output Tensor attribute. + +RKNN_QUERY_PERF_DETAIL rknn_perf_detail Query the running time of each layer + + of the network. + +RKNN_QUERY_SDK_VERSION rknn_sdk_version Query the SDK version. + + Next we will explain each query command in detail. + + 1) Query the number of input and output Tensor + + The RKNN_QUERY_IN_OUT_NUM command can be used to query the number of model + + input and output Tensor. You need to create the rknn_input_output_num structure object first. + + 15 + www.rock-chips.com + +Sample Code: + +rknn_input_output_num io_num; +ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, + + sizeof(io_num)); +printf("model input num: %d, output num: %d\n", io_num.n_input, + + io_num.n_output); + +2) Query input Tensor attribute + The RKNN_QUERY_INPUT_ATTR command can be used to query the attribute of the model + +input Tensor. You need to create the rknn_tensor_attr structure object first. +Sample Code: + +rknn_tensor_attr input_attrs[io_num.n_input]; +memset(input_attrs, 0, sizeof(input_attrs)); +for (int i = 0; i < io_num.n_input; i++) { + + input_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +3) Query output Tensor attribute + The RKNN_QUERY_OUTPUT_ATTR command can be used to query the attribute of the model + +output Tensor. You need to create the rknn_tensor_attr structure object first. + Sample Code: + +rknn_tensor_attr output_attrs[io_num.n_output]; +memset(output_attrs, 0, sizeof(output_attrs)); +for (int i = 0; i < io_num.n_output; i++) { + + output_attrs[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), + + sizeof(rknn_tensor_attr)); +} + +4) Query the running time of each layer of the network + If the RKNN_FLAG_COLLECT_PERF_MASK flag has been set on the rknn_init function, the + +RKNN_QUERY_PERF_DETAIL command can be passed to query the runtime of each layer of the +network after rknn_run function execution completed. You need to create the rknn_perf_detail + + 16 + www.rock-chips.com + + structure object first. + Sample Code: + + rknn_perf_detail perf_detail; + ret = rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, &perf_detail, + + sizeof(rknn_perf_detail)); + printf("%s", perf_detail.perf_data); + + It should be noted that rknn_perf_detail.perf_data does not need to be released. The SDK will + automatically manage this buffer memory. + 5) Query the SDK version + + The RKNN_QUERY_SDK_VERSION command can be used to query the version information + of the RKNN SDK. You need to create the rknn_sdk_version structure object first. + Sample Code: + + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + + sizeof(rknn_sdk_version)); + printf("sdk api version: %s\n", version.api_version); + printf("driver version: %s\n", version.drv_version); + +3.2.4.4 rknn_inputs_set + + The input data of the model can be set by the rknn_inputs_set function. This function can + + support multiple inputs, each one is a rknn_input structure object. Developers needs to set these + + object field before passing in. + +API rknn_inputs_set + +Description Set the model input data. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs. + + rknn_input inputs[]: Array of rknn_input. + +Return int: Error code (See RKNN Error Code). + + 17 + www.rock-chips.com + +Sample Code: + +rknn_input inputs[1]; +memset(inputs, 0, sizeof(inputs)); +inputs[0].index = 0; +inputs[0].type = RKNN_TENSOR_UINT8; +inputs[0].size = img_width*img_height*img_channels; +inputs[0].fmt = RKNN_TENSOR_NHWC; +inputs[0].buf = in_data; + +ret = rknn_inputs_set(ctx, 1, inputs); + +3.2.4.5 rknn_inputs_map + + The rknn_inputs_map function is used to obtain the storage state of the model input tensor after + initialization. The storage state includes virtual address, physical address, fd, and storage space size. + It needs to be used in conjunction with the rknn_inputs_sync interface (see the rknn_inputs_sync + function). After the model is initialized, the user sets the input data through the returned memory + location, and calls the rknn_inputs_sync function before inference. The storage state is represented + by the rknn_tensor_mem structure. The input parameter mem is an array of rknn_tensor_mem + structure. + + Currently, on the RK1808/RV1109/RV1126 chip, the returned fd is -1. When the returned + physical address value is 0xffffffffffffffff (2 to the 64th power-1), it means that the correct physical + address cannot be obtained, and the virtual address is still valid. If there are multiple model input + tensors with large storage space, users can appropriately increase the model input and output storage + space when mounting the driver or increase the CMA memory space in the firmware. Take + RV1109_RV1126 as an example to configure drive storage space, you can refer to the following + modifications: + + Find this line in the /etc/init.d/S60NPU_init file: + insmod /lib/modules/galcore.ko contiguousSize=0x400000 gpuProfiler=1 + Change to + + 18 + www.rock-chips.com + + insmod /lib/modules/galcore.ko contiguousSize=0x600000 gpuProfiler=1 + Then restart to take effect. This configuration should be larger than the total size of user model + + input and output, but not more than the available CMA space in the firmware. + +API rknn_inputs_map + +Description Read input storage status information. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_input inputs[1]; + rknn_tensor_mem mem[1]; + memset(inputs, 0, sizeof(inputs)); + + //set input info returned by rknn_query + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; + inputs[0].size = img_width*img_height*img_channels; + inputs[0].fmt = RKNN_TENSOR_NHWC; + + ret = rknn_inputs_map(ctx, 1, inputs, mem); + +3.2.4.6 rknn_inputs_sync + + The rknn_inputs_sync function writes the CPU cache back to the memory so that the device + + can obtain the correct data. + +API rknn_inputs_sync + +Description Synchronize input data. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs. + + 19 + www.rock-chips.com + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + + ret = rknn_inputs_sync(ctx, 1, mem); + +3.2.4.7 rknn_inputs_unmap + + The rknn_inputs_unmap function will clear the storage location information and flags of the + + input tensor obtained by the rknn_inputs_map function. + +API rknn_inputs_unmap + +Description Clear the storage location information and flags of the input tensor obtained by the + + rknn_inputs_map function. + +Parameter rknn_context context: The object of rknn_contex. + + uint32_t n_inputs: Number of inputs + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + 20 + www.rock-chips.com + + rknn_tensor_mem mem[1]; + ret = rknn_inputs_map(ctx, 1, mem); + ret = rknn_inputs_sync(ctx, 1, mem); + ret = rknn_run(ctx, NULL); + + ret = rknn_inputs_unmap(ctx, 1, inputs, mem); + +3.2.4.8 rknn_run + + The rknn_run function will perform a model reasoning. The input data need to be set by the + + rknn_inputs_set function before rknn_run is called. + +API rknn_run + +Description Perform a model reasoning. + +Parameter rknn_context context: The object of rknn_contex. + + rknn_run_extend* extend: Reserved for extension, currently not used, you can pass + + NULL. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + ret = rknn_run(ctx, NULL); + +3.2.4.9 rknn_outputs_get + + The rknn_outputs_get function can get the output data of the model reasoning. This function + can get multiple output data. Each of these outputs is a rknn_output structure object, which needs to + be created and set in turn before the function is called. + + There are two ways to store buffers for output data: + 1) Developer allocate and release buffers themselves. At this time, the + + rknn_output.is_prealloc needs to be set to 1, and the rknn_output.buf points to users’ + allocated buffer; + + 21 + www.rock-chips.com + + 2) The other is allocated by SDK. At this time, the rknn_output .is_prealloc needs to be set to + + 0. After the function is executed, rknn_output.buf will be created and store the output data. + +API rknn_outputs_get + +Description Get model inference output data. + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_output outputs[]: Array of rknn_output. + + rknn_run_extend* extend: Reserved for extension, currently not used, you can pass + + NULL. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_output outputs[io_num.n_output]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < io_num.n_output; i++) { + + outputs[i].want_float = 1; + } + ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); + +3.2.4.10 rknn_outputs_release + + The rknn_outputs_release function will release the relevant resources of the rknn_output object. + +API rknn_outputs_release + +Description Release the rknn_output object + +Parameter rknn_context context: rknn_context object + + uint32_t n_outputs: Number of output. + + rknn_output outputs[]: rknn_output array to be release. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + 22 + www.rock-chips.com + + ret = rknn_outputs_release(ctx, io_num.n_output, outputs); + +3.2.4.11 rknn_outputs_map + + The rknn_outputs_map function obtains the storage state of the output tensor after the model is + + initialized. It needs to be used in conjunction with the rknn_outputs_sync function (see + + rknn_outputs_sync function). After the model is initialized, the rknn_outputs_map interface is called, + + and then the rknn_outputs_sync interface is called after each inference. If users need 32-bit floating + + point data, they need to perform dequantization according to the quantization method and quantized + + data type. + +API rknn_outputs_map + +Description Read output storage status information. + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + + Sample Code: + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_map(ctx, 1, mem); + +3.2.4.12 rknn_outputs_sync + + After the rknn_outputs_map interface is used to map the model output tensor storage state + information when the model is running, in order to ensure cache consistency, the rknn_outputs_sync + function is used to let the CPU obtain the latest data after the inference. + + 23 + www.rock-chips.com + +API rknn_outputs_sync + +Description After inference, synchronize the latest output data + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + +Sample Code: + + rknn_tensor_mem mem[1]; + + ret = rknn_run(ctx, NULL); + ret = rknn_outputs_sync(ctx, io_num.n_output, mem); + +3.2.4.13 rknn_outputs_unmap + + The rknn_outputs_unmap function will clear the storage status of the output tensor obtained by + + the rknn_outputs_map function. + +API rknn_outputs_unmap + +Description Clear the storage state of the output tensor obtained by the rknn_outputs_map + + function. + +Parameter rknn_context context: The object of rknn_context. + + uint32_t n_outputs: Number of output. + + rknn_tensor_mem mem[]: Array of storage status information. Each element of the + + array is an rknn_tensor_mem structure object. + +Return int: Error code (See RKNN Error Code). + +Sample Code: + + 24 + www.rock-chips.com + + rknn_tensor_mem mem[1]; + ret = rknn_outputs_unmap(ctx, io_num.n_output,mem); + +3.2.5 RKNN DataStruct Define + +3.2.5.1 rknn_input_output_num + + The structure rknn_input_output_num represents the number of input and output Tensor , The + following table shows the definition: + + Field Type Meaning +n_input uint32_t The number of input tensor +n_output uint32_t The number of output tensor + +3.2.5.2 rknn_tensor_attr + +The structure rknn_tensor_attr represents the attribute of the model's Tensor. The following table + +shows the definition: + +Field Type Meaning + +index uint32_t Indicates the index position of the input and output + + Tensor. + +n_dims uint32_t The number of Tensor dimensions. + +dims uint32_t[] Values for each dimension. + +name char[] Tensor name. + +n_elems uint32_t The number of Tensor data elements. + +size uint32_t The memory size of Tensor data. + +fmt rknn_tensor_format The format of Tensor dimension, has the following + + format: + + 25 + www.rock-chips.com + + RKNN_TENSOR_NCHW + + RKNN_TENSOR_NHWC + + type rknn_tensor_type Tensor data type, has the following data types: + +qnt_type RKNN_TENSOR_FLOAT32 + + fl RKNN_TENSOR_FLOAT16 + zp + scale RKNN_TENSOR_INT8 + + RKNN_TENSOR_UINT8 + + RKNN_TENSOR_INT16 + + rknn_tensor_qnt_type Tensor Quantization Type, has the following types + + of quantization: + + RKNN_TENSOR_QNT_NONE: Not quantified; + + RKNN_TENSOR_QNT_DFP: Dynamic fixed point + + quantization; + + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC: + + Asymmetric quantification. + + int8_t RKNN_TENSOR_QNT_DFP quantization parameter + + uint32_t RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC + + quantization parameter. + + float RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC + + quantization parameter. + +3.2.5.3 rknn_input + + The structure rknn_input represents a data input to the model, used as a parameter to the +rknn_inputs_set function. The following table shows the definition: + + 26 + www.rock-chips.com + + Field Type Meaning + index + buf uint32_t The index position of this input. + size +pass_through void* Point to the input data Buffer. + + type uint32_t The memory size of the input data Buffer. + fmt + uint8_t When set to 1, buf will be directly set to the input + + node of the model without any pre-processing. + + rknn_tensor_type The type of input data. + + rknn_tensor_format The format of input data. + +3.2.5.4 rknn_tensor_mem + +The structure rknn_tensor_mem represents the storage state information after tensor + +initialization, which is used as a parameter to pass in to the rknn_inputs_map series and + +rknn_outputs_map series functions. The definition of the structure is shown in the following table: + +Field Type Meaning + +logical_addr void* The virtual address of this input. + +physical_addr uint64_t The physical address of this input. + +fd int32_t The fd of this input. + +size uint32_t The memory size of the input tensor. + +handle uint32_t The handle of this input. + +priv_data void* Reserved data. + +reserved_flag int32_t Reserved flag. + +3.2.5.5 rknn_output + + The structure rknn_output represents a data output of the model, used as a parameter to the +rknn_outputs_get function. The following table shows the definition: + + 27 + Field Type www.rock-chips.com +want_float uint8_t + Meaning +is_prealloc uint8_t Indicates if the output data needs to be converted + to float type. + index uint32_t Indicates whether the Buffer that stores the output + buf void* data is pre-allocated. + size The index position of this output. + uint32_t Pointer which point to the output data Buffer. + Output data Buffer memory size. + +3.2.5.6 rknn_perf_detail + +The structure rknn_perf_detail represents the performance details of the model. The following + +table shows the definition: + +Field Type Meaning + +perf_data char* Performance details include the run time of each + + layer of the network. + +data_len uint64_t The Length of perf_data. + +3.2.5.7 rknn_sdk_version + +The structure rknn_sdk_version is used to indicate the version information of the RKNN SDK. + +The following table shows the definition: + +Field Type Meaning + +api_version char[] SDK API Version information. + +drv_version char[] Driver version information. + +3.2.6 RKNN Error Code + +The return code of the RKNN API function is defined as shown in the following table. + + 28 + www.rock-chips.com + + Error Code Message + +RKNN_SUCC(0) Execution is successful + +RKNN_ERR_FAIL (-1) Execution error + +RKNN_ERR_TIMEOUT (-2) Execution timeout + +RKNN_ERR_DEVICE_UNAVAILABLE (-3) NPU device is unavailable + +RKNN_ERR_MALLOC_FAIL (-4) Memory allocation is failed + +RKNN_ERR_PARAM_INVALID (-5) Parameter error + +RKNN_ERR_MODEL_INVALID (-6) RKNN model is invalid + +RKNN_ERR_CTX_INVALID (-7) rknn_context is invalid + +RKNN_ERR_INPUT_INVALID (-8) rknn_input object is invalid + +RKNN_ERR_OUTPUT_INVALID (-9) rknn_output object is invalid + +RKNN_ERR_DEVICE_UNMATCH (-10) Version does not match + +RKNN_ERR_INCOMPATILE_PRE_COMPILE_ This RKNN model use pre_compile mode, but not + +MODEL (-11) compatible with current driver. + +RKNN_ERR_INCOMPATILE_OPTIMIZATION_ This RKNN model use optimization level mode, but not + +LEVEL_VERSION (-12) compatible with current driver. + +RKNN_ERR_TARGET_PLATFORM_UNMATC This RKNN model don’t compatible with current + +H (-13) platform. + +RKNN_ERR_NON_PRE_COMPILED_MODEL The RKNN model is not in pre_compile mode and cannot + +_ON_MINI_DRIVER(-14) be executed on mini-driver. + +4 Advanced API instructions +4.1 Matmul Operator library + +4.1.1 Introduction + + The high-level API is designed to use the high computing power of the NPU to perform specific + + 29 + www.rock-chips.com + +mathematical operations, provide a simple interface call, and achieve the effect of computing acceleration. +Among them, the Matmul operator library is an acceleration library for fixed-point matrix multiplication. +The operation is defined as follows: + + C  AT * B + Here: + A, B and C are 2-dimensional matrices + A is an K*M matrix + B is a K*N matrix + C is an M*N matrix + +4.1.2 Data structure definition + +rknn_matmul_handle_t represents the handle used to perform the operation of the Matmul + +operator, which contains the context of the runtime environment and the information of the input + +buffer. The definition of the structure is shown in the following table: + +Field Type Meaning + +A void* The pointer of the first matrix buffer during + + operation. + +B void* The pointer of the second matrix buffer during + + operation. + +M int32_t The low rank dimension of A matrix. + +K int32_t The high rank dimension of A and B matrix. + +N int32_t The low rank dimension of B matrix. + +in_dtype rknn_tensor_type The type of input data. + +rknn_ctx rknn_context The context object at runtime. + + 30 + www.rock-chips.com + +4.1.3 Detailed API description + +4.1.3.1 rknn_matmul_load + + The rknn_matmul_load loading function will load the input buffer created by the user and + + return an object of type rknn_matmul_handle_t.The Matmul operator API is not responsible for + + managing the life cycle of the input buffer, and the user must ensure that the input buffer is valid + + within the Matmul operator API call. + +API rknn_matmul_load + +Description Initialize and set the input buffer pointer. + +Parameter void *a:The pointer of the first matrix buffer created by the user can only support the + + input of 8-bit unsigned integer or 8-bit signed integer one-dimensional array pointer. + + void *b:The pointer of the second matrix buffer created by the user only supports the + + input of 8-bit unsigned integer or 8-bit signed integer one-dimensional array pointer. + + int32_t M: The low rank dimension of A matrix. + + int32_t K: The high rank dimension of A and B matrix. + + int32_t N: The low rank dimension of B matrix. + + rknn_tensor_type dtype : The input data type specified by the user, only supports + + RKNN_TENSOR_INT8 or RKNN_TENSOR_UINT8 type + +Return rknn_matmul_handle_t object。 + + The sample code is as follows: + + rknn_tensor_type dtype = RKNN_TENSOR_INT8; + int8_t x[256*1] = {0}; + int8_t y[256*4096] = {0}; + rknn_matmul_handle_t handle= rknn_matmul_load(x,y,1,256,4096,dtype); + +4.1.3.2 rknn_matmul_run + After rknn_matmul_load is called and before rknn_matmul_run is executed, the data in the + + 31 + www.rock-chips.com + + input buffer is updated externally, without calling rknn_matmul_load again. + +API rknn_matmul_run + +Description Perform Matmul operations. + +Parameter rknn_matmul_handle_t matmul_handle: The handle returned by the + + rknn_matmul_load interface. + + float *c: The pointer to the matrix floating-point buffer created by the user, used to + + obtain the output. + +Return int: Error code (See RKNN Error Code). + + The sample code is as follows: + + ... + float out_fp32_buf[4096] = {0}; + rknn_matmul_run(handle,out_fp32_buf); + +4.1.3.3 rknn_matmul_unload + +API rknn_matmul_unload + +Description Destroy the Matmul operator runtime context. + +Parameter rknn_matmul_handle_t matmul_handle: The handle returned by the + + rknn_matmul_load interface. + +Return int: Error code (See RKNN Error Code). + + The sample code is as follows: + + ... + rknn_matmul_unload(handle); + +4.1.4 Implementation restrictions + + The Matmul operator library is implemented based on the hardware architecture of the NPU. In +order to achieve a balance between accuracy and speed, there are some restrictions as follows. + + 32 + www.rock-chips.com + +4.1.4.1 Dimensional restrictions + + According to the above operation description, the library realizes the matrix multiplication of M=1. +Specifically, the input A of the Matmul operator must be a Kx1 buffer(row-major), that is, the user must +create a piece of data that contains K 8-bit unsigned integers or 8-bit signed integers. When the operator +library is running on the Mini driver, the value of K can only be set to 128 or 256 or 512, and N is fixed +at 4096. When running on the Full driver, there is no such limit, but the recommended number of K is +128, 256, 512, 1024, 2048, N is an even power of 2. It is recommended that N should not be greater than +4096. + +4.1.4.2 Input data type restriction + + Only supports 8-bit unsigned integer and 8-bit signed integer input. + +4.1.5 Benchmark + + When the two input matrices use random numbers, the measured results on the RV1109-EVB board +are shown in Table-1. The speed is the average time after the rknn_matmul_run interface is called 100 +times. The average relative error is the error value of the result of executing the same algorithm on the +NPU and CPU. The specific formula is: + + (abs(R1  R2 ) / R2 ) / N + + k + + among them, + R1 is the output vector of the Matmul operator library, containing N elements. + R2 is the CPU output vector, containing N elements. + + 33 + www.rock-chips.com + + Table-1 Speed/accuracy results of Matmul operator library (RV1109, int8) + +K N Speed(ms) Average relative error + +128 1024 1.0 0.00034 + +256 1024 1.6 0.00032 + +512 2024 3.0 -0.00015 + +1024 1024 5.4 0.00047 + +128 4096 3.0 0.00051 + +256 4096 5.6 0.00024 + +512 4096 10.7 0.00024 + +1024 4096 20.9 0.00051 + +Note: the speed may vary slightly due to different NPU driver versions. The error value may varies + +slightly according to the random number of each test. + + 34 + www.rock-chips.com + +5 NPU driver description + +5.1.1 Directory structure description + + The NPU driver is in the $SDK/external/rknpu/drivers/ directory or +https://github.com/rockchip-linux/rknpu/tree/master/drivers +The compilation and installation rules refer to $SDK/buildroot/package/rockchip/rknpu/rknpu.mk +drivers/ +├── common +├── linux-aarch64 (for RK1808 npu full driver) +├── linux-aarch64-mini (for RK1808 npu mini driver) +├── linux-armhf (for RK1806 npu full driver) +├── linux-armhf-mini(for RK1806 npu mini driver) +├── linux-armhf-puma (for RV1126/RV1109 npu full driver) +├── linux-armhf-puma-mini(for RV1126/RV1109 npu mini driver) +├── npu_ko (NPU kernel driver) + +5.1.2 The difference between NPU full driver and mini driver + + Include the following points: + 1) Mini driver only supports pre-compiled rknn model. If you run non-pre-compiled model, +RKNN_ERR_MODEL_INVALID error will appear. Starting from 1.6.0, it will return +RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER error; + 2) The full driver supports the online debugging function of RKNN Toolkit, but the mini driver does +not; + 3) Mini driver library size is much smaller than full driver. Taking RV1109/RV1126 1.6.0 driver as +an example, full driver size is 87MB, mini driver size is 7.1MB, which can effectively save flash size. + 4) Mini driver library occupies less memory than full driver when running. + + 35 + www.rock-chips.com + +6 FAQ + +6.1.1 Input and output data format issues + +6.1.1.1 How to choose from RGB or BGR format when given three-channel image data + input? + + It is recommended that using RGB format input data uniformly. When exporting the RKNN model, +there are two possibilities for the reorder_channel parameter of the config function: + + 1) If the original model is trained using BGR images, reorder_channel = '2 1 0'. + 2) If the original model is trained using RGB images, reorder_channel = '0 1 2'. + +6.1.1.2 Which RKNN_TENSOR_NHWC or RKNN_TENSOR_NCHW should be set in the + rknn_input structure? Why are the two settings time-consuming different? + + The rknn_input structure is determined according to the user's own data format, and the C API will +automatically convert it into the format required by the NPU. + + The reason for the different time-consuming is that different input formats have different calculation +amounts and different optimization methods. + +6.1.1.3 For the non-quantized RKNN model, why is the size in the output + rknn_tensor_attr different from the size of the rknn_output returned by the + rknn_outputs_get interface? + + The non-quantized RKNN model, the internal output data type of the NPU is float16, and the size is +the number of elements * 2 bytes. When the user sets want_float = 1, what they want is float32 data, +float16 will be converted to float32, and the size is the number of elements * 4 bytes. + + 36 + www.rock-chips.com + +6.1.1.4 Is rknn_output.index set by user or return by driver? + +Return by driver. + +6.1.1.5 Why does the dims array of the rknn_tensor_attr have 0? + +0 means the size is invalid. n_dims in rknn_tensor_attr represents the number of valid size in dims. + +6.1.1.6 The order of dims in rknn_tensor_attr is opposite to the order of numpy obtained + by rknn_toolkit? + + The layout of arrays in C API is the opposite of python. For example, the numpy output shape +obtained by the run() interface of rknn-toolkit is [1,255,20,20], and the dims array in C API is +{20,20,255,1}. + +6.1.2 Input and output interface usage problems + +6.1.2.1 How to preprocess the data when using pass_through and using + rknn_inputs_map interface? + + Please refer to the rknn_pass_through_demo example under +https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples. + +6.1.2.2 Why is the physical address obtained using rknn_inputs_map or + rknn_outputs_map invalid? How to obtain a valid physical address? + + Input/output cannot be allocated to physically contiguous memory. The possible reasons are: + 1) The input/output size is too large, exceeding the total physically contiguous memory size (the +default is 4MB). + 2) There is not enough physically contiguous memory available in the system. + 3) When exporting the RKNN model, add the following parameter to the config function: + + 37 + www.rock-chips.com + +output_optimize=1. + Users can try to restart the system, or configure a larger physically continuous memory space when + +the NPU driver is mounted. For the configuration method, refer to the rknn_inputs_map interface +description. + +6.1.3 API call process issues + +6.1.3.1 After rknn_init succeeds, can the memory occupied by the model file be + released? + + Yes,you can. + +6.1.3.2 When rknn_output.is_prealloc=1, does rknn_outputs_release need to be called? + + Yes, it needs. + +6.1.4 Performance issues + +6.1.4.1 rknn_init takes too long? + + Use pre-compiled models. Refer to the relevant chapters of the User Guide document under +https://github.com/rockchip-linux/rknn-toolkit/tree/master/doc for usage. + +6.1.4.2 rknn_inputs_set takes too long? + + The possible reason is the large amount of data or the time-consuming format conversion. If it takes +a long time to convert the format, users can try the pass_through usage to do the conversion themselves. +For conversion method, please refer to rknn_pass_through_demo example under +https://github.com/rockchip-linux/rknpu/tree/master/rknn/rknn_api/examples, or try to export the RKNN +model by adding the following parameter to the config function: output_optimize=1. + + 38 + www.rock-chips.com + +6.1.4.3 rknn_outputs_get takes too long? + + The possible reason is the large amount of data or the time-consuming format conversion. If it takes +a long time to convert the format, users can try to set want_float=0 and do the conversion themselves, or +try to export the RKNN model by adding the following parameter to the config function: +output_optimize=1. + + 39 + diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/include/rknn_runtime.h b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/include/rknn_runtime.h new file mode 100644 index 0000000..a114c1f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/include/rknn_runtime.h @@ -0,0 +1,504 @@ +/**************************************************************************** +* +* Copyright (c) 2017 - 2018 by Rockchip Corp. All rights reserved. +* +* The material in this file is confidential and contains trade secrets +* of Rockchip Corporation. This is proprietary information owned by +* Rockchip Corporation. No part of this work may be disclosed, +* reproduced, copied, transmitted, or used in any way for any purpose, +* without the express written permission of Rockchip Corporation. +* +*****************************************************************************/ + + +#ifndef _RKNN_RUNTIME_H +#define _RKNN_RUNTIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + Definition of extended flag for rknn_init. +*/ +/* set high priority context. */ +#define RKNN_FLAG_PRIOR_HIGH 0x00000000 + +/* set medium priority context */ +#define RKNN_FLAG_PRIOR_MEDIUM 0x00000001 + +/* set low priority context. */ +#define RKNN_FLAG_PRIOR_LOW 0x00000002 + +/* asynchronous mode. + when enable, rknn_outputs_get will not block for too long because it directly retrieves the result of + the previous frame which can increase the frame rate on single-threaded mode, but at the cost of + rknn_outputs_get not retrieves the result of the current frame. + in multi-threaded mode you do not need to turn this mode on. */ +#define RKNN_FLAG_ASYNC_MASK 0x00000004 + +/* collect performance mode. + when enable, you can get detailed performance reports via rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, ...), + but it will reduce the frame rate. */ +#define RKNN_FLAG_COLLECT_PERF_MASK 0x00000008 + +/* + save pre-compile model. +*/ +#define RKNN_FLAG_PRECOMPILE_MASK 0x00000020 + +/* + Error code returned by the RKNN API. +*/ +#define RKNN_SUCC 0 /* execute succeed. */ +#define RKNN_ERR_FAIL -1 /* execute failed. */ +#define RKNN_ERR_TIMEOUT -2 /* execute timeout. */ +#define RKNN_ERR_DEVICE_UNAVAILABLE -3 /* device is unavailable. */ +#define RKNN_ERR_MALLOC_FAIL -4 /* memory malloc fail. */ +#define RKNN_ERR_PARAM_INVALID -5 /* parameter is invalid. */ +#define RKNN_ERR_MODEL_INVALID -6 /* model is invalid. */ +#define RKNN_ERR_CTX_INVALID -7 /* context is invalid. */ +#define RKNN_ERR_INPUT_INVALID -8 /* input is invalid. */ +#define RKNN_ERR_OUTPUT_INVALID -9 /* output is invalid. */ +#define RKNN_ERR_DEVICE_UNMATCH -10 /* the device is unmatch, please update rknn sdk + and npu driver/firmware. */ +#define RKNN_ERR_INCOMPATILE_PRE_COMPILE_MODEL -11 /* This RKNN model use pre_compile mode, but not compatible with current driver. */ +//add by chifred: for reporting optimization version bug info +#define RKNN_ERR_INCOMPATILE_OPTIMIZATION_LEVEL_VERSION -12 /* This RKNN model set optimization level, but not compatible with current driver. */ +#define RKNN_ERR_TARGET_PLATFORM_UNMATCH -13 /* This RKNN model set target platform, but not compatible with current platform. */ +//chifred add end +#define RKNN_ERR_NON_PRE_COMPILED_MODEL_ON_MINI_DRIVER -14 /* This RKNN model is not a pre-compiled model, but the npu driver is mini driver. */ + +/* + Definition for tensor +*/ +#define RKNN_MAX_DIMS 16 /* maximum dimension of tensor. */ +#define RKNN_MAX_NAME_LEN 256 /* maximum name lenth of tensor. */ + + + +#ifdef __arm__ +typedef uint32_t rknn_context; +#else +typedef uint64_t rknn_context; +#endif + +/* + The query command for rknn_query +*/ +typedef enum _rknn_query_cmd { + RKNN_QUERY_IN_OUT_NUM = 0, /* query the number of input & output tensor. */ + RKNN_QUERY_INPUT_ATTR, /* query the attribute of input tensor. */ + RKNN_QUERY_OUTPUT_ATTR, /* query the attribute of output tensor. */ + RKNN_QUERY_PERF_DETAIL, /* query the detail performance, need set + RKNN_FLAG_COLLECT_PERF_MASK when call rknn_init. */ + RKNN_QUERY_PERF_RUN, /* query the time of run. */ + RKNN_QUERY_SDK_VERSION, /* query the sdk & driver version */ + RKNN_QUERY_PRE_COMPILE, /* query the pre compile model */ + + RKNN_QUERY_CMD_MAX +} rknn_query_cmd; + +/* + the tensor data type. +*/ +typedef enum _rknn_tensor_type { + RKNN_TENSOR_FLOAT32 = 0, /* data type is float32. */ + RKNN_TENSOR_FLOAT16, /* data type is float16. */ + RKNN_TENSOR_INT8, /* data type is int8. */ + RKNN_TENSOR_UINT8, /* data type is uint8. */ + RKNN_TENSOR_INT16, /* data type is int16. */ + + RKNN_TENSOR_TYPE_MAX +} rknn_tensor_type; + +/* + the quantitative type. +*/ +typedef enum _rknn_tensor_qnt_type { + RKNN_TENSOR_QNT_NONE = 0, /* none. */ + RKNN_TENSOR_QNT_DFP, /* dynamic fixed point. */ + RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC, /* asymmetric affine. */ + + RKNN_TENSOR_QNT_MAX +} rknn_tensor_qnt_type; + +/* + the tensor data format. +*/ +typedef enum _rknn_tensor_format { + RKNN_TENSOR_NCHW = 0, /* data format is NCHW. */ + RKNN_TENSOR_NHWC, /* data format is NHWC. */ + + RKNN_TENSOR_FORMAT_MAX +} rknn_tensor_format; + +/* + the information for RKNN_QUERY_IN_OUT_NUM. +*/ +typedef struct _rknn_input_output_num { + uint32_t n_input; /* the number of input. */ + uint32_t n_output; /* the number of output. */ +} rknn_input_output_num; + +/* + the information for RKNN_QUERY_INPUT_ATTR / RKNN_QUERY_OUTPUT_ATTR. +*/ +typedef struct _rknn_tensor_attr { + uint32_t index; /* input parameter, the index of input/output tensor, + need set before call rknn_query. */ + + uint32_t n_dims; /* the number of dimensions. */ + uint32_t dims[RKNN_MAX_DIMS]; /* the dimensions array. */ + char name[RKNN_MAX_NAME_LEN]; /* the name of tensor. */ + + uint32_t n_elems; /* the number of elements. */ + uint32_t size; /* the bytes size of tensor. */ + + rknn_tensor_format fmt; /* the data format of tensor. */ + rknn_tensor_type type; /* the data type of tensor. */ + rknn_tensor_qnt_type qnt_type; /* the quantitative type of tensor. */ + int8_t fl; /* fractional length for RKNN_TENSOR_QNT_DFP. */ + uint32_t zp; /* zero point for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ + float scale; /* scale for RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC. */ +} rknn_tensor_attr; + +/* + the information for RKNN_QUERY_PERF_DETAIL. +*/ +typedef struct _rknn_perf_detail { + char* perf_data; /* the string pointer of perf detail. don't need free it by user. */ + uint64_t data_len; /* the string length. */ +} rknn_perf_detail; + +/* + the information for RKNN_QUERY_PERF_RUN. +*/ +typedef struct _rknn_perf_run { + int64_t run_duration; /* real inference time (us) */ +} rknn_perf_run; + +/* + the information for RKNN_QUERY_SDK_VERSION. +*/ +typedef struct _rknn_sdk_version { + char api_version[256]; /* the version of rknn api. */ + char drv_version[256]; /* the version of rknn driver. */ +} rknn_sdk_version; + +/* + The flags of rknn_tensor_mem. +*/ +typedef enum _rknn_tensor_mem_flags { + RKNN_TENSOR_MEMORY_FLAGS_UNKNOWN = 0, + RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE = 1, /*Used to mark in rknn_destroy_mem() whether it is necessary to release the "mem" pointer itself. + If the flag RKNN_TENSOR_MEMORY_FLAGS_ALLOC_INSIDE is set, rknn_destroy_mem() will call free(mem).*/ + +} rknn_tensor_mem_flags; + + +/* + the memory information of tensor. +*/ +typedef struct _rknn_tensor_memory { + void* logical_addr; /* the virtual address of tensor buffer. */ + uint64_t physical_addr; /* the physical address of tensor buffer. */ + int32_t fd; /* the fd of tensor buffer. */ + uint32_t size; /* the size of tensor buffer. */ + uint32_t handle; /* the handle tensor buffer. */ + void * priv_data; /* the data which is reserved. */ + uint64_t reserved_flag; /* the flag which is reserved. */ +} rknn_tensor_mem; + +/* + the input information for rknn_input_set. +*/ +typedef struct _rknn_input { + uint32_t index; /* the input index. */ + void* buf; /* the input buf for index. */ + uint32_t size; /* the size of input buf. */ + uint8_t pass_through; /* pass through mode. + if TRUE, the buf data is passed directly to the input node of the rknn model + without any conversion. the following variables do not need to be set. + if FALSE, the buf data is converted into an input consistent with the model + according to the following type and fmt. so the following variables + need to be set.*/ + rknn_tensor_type type; /* the data type of input buf. */ + rknn_tensor_format fmt; /* the data format of input buf. + currently the internal input format of NPU is NCHW by default. + so entering NCHW data can avoid the format conversion in the driver. */ +} rknn_input; + +/* + the output information for rknn_outputs_get. +*/ +typedef struct _rknn_output { + uint8_t want_float; /* want transfer output data to float */ + uint8_t is_prealloc; /* whether buf is pre-allocated. + if true, the following variables need to be set. + if false, The following variables do not need to be set. */ + uint32_t index; /* the output index. */ + void* buf; /* the output buf for index. + when is_prealloc = FALSE and rknn_outputs_release called, + this buf pointer will be free and don't use it anymore. */ + uint32_t size; /* the size of output buf. */ +} rknn_output; + +/* + the extend information for rknn_run. +*/ +typedef struct _rknn_run_extend { + uint64_t frame_id; /* output parameter, indicate current frame id of run. */ +} rknn_run_extend; + +/* + the extend information for rknn_outputs_get. +*/ +typedef struct _rknn_output_extend { + uint64_t frame_id; /* output parameter, indicate the frame id of outputs, corresponds to + struct rknn_run_extend.frame_id.*/ +} rknn_output_extend; + +/* + the information for RKNN_QUERY_RKNN_PRECOMPILE. +*/ +typedef struct _rknn_precompile { + void* model_data; /* the pointer of precompile model. don't need free it by user. */ + uint32_t data_len; /* the model length. */ +} rknn_precompile; + + +/* rknn_init + + initial the context and load the rknn model. + + input: + rknn_context* context the pointer of context handle. + void* model pointer to the rknn model. + uint32_t size the size of rknn model. + uint32_t flag extend flag, see the define of RKNN_FLAG_XXX_XXX. + return: + int error code. +*/ +int rknn_init(rknn_context* context, void* model, uint32_t size, uint32_t flag); + + +/* rknn_destroy + + unload the rknn model and destroy the context. + + input: + rknn_context context the handle of context. + return: + int error code. +*/ +int rknn_destroy(rknn_context context); + + +/* rknn_query + + query the information about model or others. see rknn_query_cmd. + + input: + rknn_context context the handle of context. + rknn_query_cmd cmd the command of query. + void* info the buffer point of information. + uint32_t size the size of information. + return: + int error code. +*/ +int rknn_query(rknn_context context, rknn_query_cmd cmd, void* info, uint32_t size); + + +/* rknn_inputs_set + + set inputs information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_input inputs[] the arrays of inputs information, see rknn_input. + return: + int error code +*/ +int rknn_inputs_set(rknn_context context, uint32_t n_inputs, rknn_input inputs[]); + + +/* rknn_inputs_map + + map inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_map(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_sync + + synchronize inputs tensor buffer by input index of rknn model. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_sync(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_inputs_unmap + + unmap inputs tensor memory information by input index of rknn model. + inputs information see rknn_input. + + input: + rknn_context context the handle of context. + uint32_t n_inputs the number of inputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_inputs_unmap(rknn_context context, uint32_t n_inputs, rknn_tensor_mem mem[]); + + +/* rknn_run + + run the model to execute inference. + + input: + rknn_context context the handle of context. + rknn_run_extend* extend the extend information of run. + return: + int error code. +*/ +int rknn_run(rknn_context context, rknn_run_extend* extend); + + +/* rknn_outputs_get + + wait the inference to finish and get the outputs. + this function will block until inference finish. + the results will set to outputs[]. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_output outputs[] the arrays of output, see rknn_output. + rknn_output_extend* the extend information of output. + return: + int error code. +*/ +int rknn_outputs_get(rknn_context context, uint32_t n_outputs, rknn_output outputs[], rknn_output_extend* extend); + + +/* rknn_outputs_release + + release the outputs that get by rknn_outputs_get. + after called, the rknn_output[x].buf get from rknn_outputs_get will + also be free when rknn_output[x].is_prealloc = FALSE. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_output outputs[] the arrays of output. + return: + int error code +*/ +int rknn_outputs_release(rknn_context context, uint32_t n_ouputs, rknn_output outputs[]); + + +/* rknn_outputs_map + + map the model output tensors memory information. + The difference between this function and "rknn_outputs_get" is + that it directly maps the model output tensor memory location to the user. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_map(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_sync + + synchronize the output tensors buffer to ensure cache cohenrency, wait the inference to finish. + + input: + rknn_context context the handle of context. + uint32_t n_outputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code. +*/ +int rknn_outputs_sync(rknn_context context, uint32_t n_outputs, rknn_tensor_mem mem[]); + +/* rknn_outputs_unmap + + unmap the outputs memory information that get by rknn_outputs_map. + + input: + rknn_context context the handle of context. + uint32_t n_ouputs the number of outputs. + rknn_tensor_mem mem[] the array of tensor memory information + return: + int error code +*/ +int rknn_outputs_unmap(rknn_context context, uint32_t n_ouputs, rknn_tensor_mem mem[]); + +/* rknn_create_mem (memory allocated inside) + + Create tensor memory. This API require libdrm support! + + input: + rknn_context ctx the handle of context. + uint64_t size the size of tensor buffer. + return: + rknn_tensor_mem the pointer of tensor memory information. +*/ +rknn_tensor_mem* rknn_create_mem(rknn_context ctx, uint64_t size); + +/* rknn_destroy_mem (support allocate inside and outside) + + destroy tensor memory. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the pointer of tensor memory information. + return: + int error code +*/ +int rknn_destroy_mem(rknn_context ctx, rknn_tensor_mem *mem); + + + +/* rknn_set_io_mem + + set the input and output tensors buffer. + + input: + rknn_context ctx the handle of context. + rknn_tensor_mem *mem the array of tensor memory information. + rknn_tensor_attr *attr the attribute of input or output tensor buffer. + return: + int error code. +*/ +int rknn_set_io_mem(rknn_context ctx, rknn_tensor_mem *mem, rknn_tensor_attr *attr); + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //_RKNN_RUNTIME_H diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/README b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/README new file mode 100644 index 0000000..7beab1a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/README @@ -0,0 +1 @@ +# RKNN \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/VERSION b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/VERSION new file mode 100644 index 0000000..d612b7f --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/VERSION @@ -0,0 +1 @@ +0.9.7.1 diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/__init__.py b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/__init__.py new file mode 100644 index 0000000..cfc82a4 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn/__init__.py @@ -0,0 +1 @@ +from rknn import api diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn1808-1.2.0-cp36-cp36m-linux_aarch64.whl b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn1808-1.2.0-cp36-cp36m-linux_aarch64.whl new file mode 100644 index 0000000..0b99684 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn1808-1.2.0-cp36-cp36m-linux_aarch64.whl differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn1808-1.2.0-cp37-cp37m-linux_aarch64.whl b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn1808-1.2.0-cp37-cp37m-linux_aarch64.whl new file mode 100644 index 0000000..08ca084 Binary files /dev/null and b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/python/rknn1808-1.2.0-cp37-cp37m-linux_aarch64.whl differ diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/CMakeLists.txt b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/CMakeLists.txt new file mode 100644 index 0000000..ab0d1f6 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(rknn_matmul_sample_linux) + +set(CMAKE_SYSTEM_NAME Linux) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +if (CMAKE_C_COMPILER MATCHES "aarch64") + set(LIB_ARCH lib64) +else() + set(LIB_ARCH lib) +endif() + +# rknn_utils +include_directories(${CMAKE_SOURCE_DIR}/librknn_utils/include) +set(RKNN_UTILS_LIB ${CMAKE_CURRENT_SOURCE_DIR}/librknn_utils/${LIB_ARCH}/librknn_utils.so) + +add_executable(rknn_matmul_sample + example/matmul_sample.c +) + +target_link_libraries(rknn_matmul_sample + "-Wl,--allow-shlib-undefined" ${RKNN_UTILS_LIB} +) + +# install target +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/rknn_matmul_sample) +install(TARGETS rknn_matmul_sample DESTINATION bin) +install(PROGRAMS ${RKNN_UTILS_LIB} DESTINATION lib) diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/README.md b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/README.md new file mode 100644 index 0000000..bdac65e --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/README.md @@ -0,0 +1,28 @@ +## build + +modify `GCC_COMPILER` on `build.sh` for target platform, then execute + +``` +./build.sh +``` + +## install + +connect device and push build output into `/userdata` + +``` +adb push install/rknn_matmul_sample/lib/librknn_utils.so /usr/lib +adb push install/rknn_matmul_sample /userdata/ +``` + +## run + +``` +adb shell +cd /userdata/rknn_matmul_sample/ +``` + +- /rk180x/rv1109/rv1126 +``` +./bin/rknn_matmul_sample 256 4096 +``` diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/build.sh b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/build.sh new file mode 100644 index 0000000..75a9a87 --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/build.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# for rk1808 aarch64 +# GCC_COMPILER=${RK1808_TOOL_CHAIN}/bin/aarch64-linux-gnu + + +# for rk1806 armhf +# GCC_COMPILER=~/opts/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf + +# for rv1109/rv1126 armhf +GCC_COMPILER=${RV1109_TOOL_CHAIN}/bin/arm-linux-gnueabihf + +ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd ) + +# build rockx +BUILD_DIR=${ROOT_PWD}/build + +if [[ ! -d "${BUILD_DIR}" ]]; then + mkdir -p ${BUILD_DIR} +fi + +cd ${BUILD_DIR} +cmake .. \ + -DCMAKE_C_COMPILER=${GCC_COMPILER}-gcc \ + -DCMAKE_CXX_COMPILER=${GCC_COMPILER}-g++ +make -j4 +make install +cd - \ No newline at end of file diff --git a/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/example/matmul_sample.c b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/example/matmul_sample.c new file mode 100644 index 0000000..7fec91a --- /dev/null +++ b/rknn_yolo_demo/libs/rklibs/rknpu/rknn/rknn_utils/example/matmul_sample.c @@ -0,0 +1,182 @@ +/** + * Example: Calculate (x-y)^2 using Matmul API + */ + + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#include +#include "rknn_matmul_api.h" + +/*------------------------------------------- + Macros and Variables +-------------------------------------------*/ + +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static int gen_random_data(int8_t *x,int len,int min_value,int max_value) { + srand((unsigned int)time(NULL)); + int range = max_value-min_value+1; + for (int i = 0;i \n",argv[0]); + return -1; + } + int DIM = atoi(argv[1]); + int BATCH_SIZE = atoi(argv[2]); + rknn_tensor_type dtype = RKNN_TENSOR_INT8; + int8_t *x = (int8_t *)malloc(DIM*sizeof(int8_t)); + int8_t *y = (int8_t *)malloc(DIM*BATCH_SIZE*sizeof(int8_t)); + float out_fp32_buf[BATCH_SIZE]; + float res_cpu[BATCH_SIZE]; + int x_size = DIM; + int y_size = DIM*BATCH_SIZE; + int test_count = 100; + float err; + struct timeval start_time, stop_time; + + int *square_y = (int *)malloc(BATCH_SIZE*sizeof(int)); + + //generate random test data + gen_random_data(x,x_size,-128,127); + gen_random_data(y,y_size,-128,127); + pre_process_y(y,DIM,BATCH_SIZE,square_y); + + rknn_matmul_handle_t handle= rknn_matmul_load(x,y, 1, DIM, BATCH_SIZE, dtype); + if (handle == NULL) + { + fprintf(stderr, "rknn_matmul_load failed.\n"); + return -1; + } + + //loop for matmul + gettimeofday(&start_time, NULL); + for(int i = 0;i + +int drm_init(drm_context *drm_ctx) +{ + static const char *card = "/dev/dri/card0"; + int flag = O_RDWR; + int drm_fd = -1; + + drm_fd = open(card, flag); + if (drm_fd < 0) + { + printf("failed to open %s\n", card); + return -1; + } + + drm_ctx->drm_handle = dlopen("libdrm.so", RTLD_LAZY); + + if (!drm_ctx->drm_handle) + { + printf("failed to dlopen libdrm.so\n"); + printf("dlopen error: %s\n", dlerror()); + drm_deinit(drm_ctx, drm_fd); + return -1; + } + + drm_ctx->io_func = (FUNC_DRM_IOCTL)dlsym(drm_ctx->drm_handle, "drmIoctl"); + if (drm_ctx->io_func == NULL) + { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + drm_deinit(drm_ctx, drm_fd); + printf("failed to dlsym drmIoctl\n"); + return -1; + } + return drm_fd; +} + +void drm_deinit(drm_context *drm_ctx, int drm_fd) +{ + if (drm_ctx->drm_handle) + { + dlclose(drm_ctx->drm_handle); + drm_ctx->drm_handle = NULL; + } + if (drm_fd > 0) + { + close(drm_fd); + } +} + +void *drm_buf_alloc(drm_context *drm_ctx, int drm_fd, int TexWidth, int TexHeight, int bpp, int *fd, unsigned int *handle, size_t *actual_size) +{ + // printf("0: Width %d, Heigh %d, bpp %d\n", TexWidth, TexHeight, bpp); + // printf("fd: %d, handle: %d, size: %d\n", fd, handle, actual_size); + int ret; + if (drm_ctx == NULL) + { + printf("drm context is unvalid\n"); + return NULL; + } + char *map = NULL; + + // printf("Width %d, Heigh %d\n", TexWidth, TexHeight); + + void *vir_addr = NULL; + struct drm_prime_handle fd_args; + struct drm_mode_map_dumb mmap_arg; + struct drm_mode_destroy_dumb destory_arg; + + struct drm_mode_create_dumb alloc_arg; + + memset(&alloc_arg, 0, sizeof(alloc_arg)); + alloc_arg.bpp = bpp; + alloc_arg.width = TexWidth; + alloc_arg.height = TexHeight; + // alloc_arg.flags = ROCKCHIP_BO_CONTIG; + + // printf("2: Width %d, Heigh %d\n", TexWidth, TexHeight); + + //获取handle和size + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg); + // printf("3: Width %d, Heigh %d\n", TexWidth, TexHeight); + if (ret) + { + printf("failed to create dumb buffer: %s\n", strerror(errno)); + return NULL; + } + // printf("4: Width %d, Heigh %d\n", TexWidth, TexHeight); + if (handle != NULL) + { + *handle = alloc_arg.handle; + } + // printf("5: Width %d, Heigh %d\n", TexWidth, TexHeight); + if (actual_size != NULL) + { + *actual_size = alloc_arg.size; + } + // printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n",alloc_arg.width,alloc_arg.height,alloc_arg.bpp,alloc_arg.size); + // printf("out handle= %d\n",alloc_arg.handle); + + //获取fd + memset(&fd_args, 0, sizeof(fd_args)); + fd_args.fd = -1; + fd_args.handle = alloc_arg.handle; + ; + fd_args.flags = 0; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args); + if (ret) + { + printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle); + return NULL; + } + // printf("out fd = %d, drm fd: %d\n",fd_args.fd,drm_fd); + if (fd != NULL) + { + *fd = fd_args.fd; + } + + //获取虚拟地址 + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = alloc_arg.handle; + + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg); + if (ret) + { + printf("failed to create map dumb: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + vir_addr = map = mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset); + if (map == MAP_FAILED) + { + printf("failed to mmap buffer: %s\n", strerror(errno)); + vir_addr = NULL; + goto destory_dumb; + } + // printf("alloc map=%x \n",map); + return vir_addr; +destory_dumb: + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = alloc_arg.handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d\n", ret); + return vir_addr; +} + +int drm_buf_destroy(drm_context *drm_ctx, int drm_fd, int buf_fd, int handle, void *drm_buf, size_t size) +{ + int ret = -1; + if (drm_buf == NULL) + { + printf("drm buffer is NULL\n"); + return -1; + } + + munmap(drm_buf, size); + + struct drm_mode_destroy_dumb destory_arg; + memset(&destory_arg, 0, sizeof(destory_arg)); + destory_arg.handle = handle; + ret = drm_ctx->io_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg); + if (ret) + printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno)); + if (buf_fd > 0) + { + close(buf_fd); + } + + return ret; +} diff --git a/rknn_yolo_demo/src/main.cpp b/rknn_yolo_demo/src/main.cpp new file mode 100644 index 0000000..76ac8a8 --- /dev/null +++ b/rknn_yolo_demo/src/main.cpp @@ -0,0 +1,1297 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*------------------------------------------- + Includes +-------------------------------------------*/ +#include "main.h" +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _BASETSD_H + +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb/stb_image_write.h" + +#undef cimg_display +#define cimg_display 0 +#undef cimg_use_jpeg +#define cimg_use_jpeg 1 +#undef cimg_use_png +#define cimg_use_png 1 +#include "CImg/CImg.h" + +#include "drm_func.h" +#include "rga_func.h" +#include "rknn_api.h" +#include "yolo.h" + +#define PERF_WITH_POST 1 +#define COCO_IMG_NUMBER 5000 +#define DUMP_INPUT 0 + +using namespace cimg_library; + +std::string DeviceID; +#define modelpath "/demo/bin/elevator7_RV1109_1126_u8.rknn" +#define FILE_PWD "/etc/DeviceID" + +#define IF_RUN_RKNN 1 +/*------------------------------------------- + Functions +-------------------------------------------*/ +using namespace std; +std::string Charge_Chinese(char* charge){ + std::string result; + if(strcmp(charge, "fire")==0) result = "火"; + if(strcmp(charge, "head")==0) result = "头"; + if(strcmp(charge, "person")==0) result = "人"; + if(strcmp(charge, "smoke")==0) result = "抽烟"; + if(strcmp(charge, "fog")==0) result = "烟雾"; + if(strcmp(charge, "fall")==0) result = "跌倒"; + if(strcmp(charge, "ebike")==0) result = "电瓶车"; + return result; +} + +struct Alarm { + int ifalarm; + std::string alarmCode; + std::string alarmRemark; + float alarmprop; +}; + +void initializeAlarm(Alarm* Alarm) { + // 初始化结构体成员 + Alarm->ifalarm = 0; + Alarm->alarmCode = "无"; + Alarm->alarmRemark = "无"; + Alarm->alarmprop = 0.0; +} + +size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response){ + size_t totalSize = size * nmemb; + response->append(static_cast(contents), totalSize); + return totalSize; +} + +// 提取 "path" 字段的值 +std::string extractSrcValue(const std::string& jsonString) { + // std::size_t srcPos = jsonString.find("\"src\":\""); + std::size_t srcPos = jsonString.find("\"path\":\""); + if (srcPos == std::string::npos) + return ""; // 未找到 "src" 字段 + + // std::size_t valueStartPos = srcPos + 7; //"src":" 7字节 + std::size_t valueStartPos = srcPos + 8; //"path":" 8字节 + std::size_t valueEndPos = jsonString.find("\"", valueStartPos); + if (valueEndPos == std::string::npos) + return ""; // 未找到值的结束位置 + + return jsonString.substr(valueStartPos, valueEndPos - valueStartPos); +} + +// 函数用于读取文件并将其内容保存在全局字符串变量中 +void readFileAndStoreInGlobal(const std::string& filename) { + std::ifstream file(filename); + + if (file.is_open()) { + std::getline(file, DeviceID); // 读取一行并存储在全局字符串中 + file.close(); + } else { + std::cerr << "无法打开文件: " << filename << std::endl; + } +} + +static void printRKNNTensor(rknn_tensor_attr *attr) +{ + printf("index=%d name=%s n_dims=%d dims=[%d %d %d %d] n_elems=%d size=%d " + "fmt=%d type=%d qnt_type=%d fl=%d zp=%d scale=%f\n", + attr->index, attr->name, attr->n_dims, attr->dims[3], attr->dims[2], + attr->dims[1], attr->dims[0], attr->n_elems, attr->size, 0, attr->type, + attr->qnt_type, attr->fl, attr->zp, attr->scale); +} +double __get_us(struct timeval t) { return (t.tv_sec * 1000000 + t.tv_usec); } + +static unsigned char *load_data(FILE *fp, size_t ofst, size_t sz) +{ + unsigned char *data; + int ret; + + data = NULL; + + if (NULL == fp) + { + return NULL; + } + + ret = fseek(fp, ofst, SEEK_SET); + if (ret != 0) + { + printf("blob seek failure.\n"); + return NULL; + } + + data = (unsigned char *)malloc(sz); + if (data == NULL) + { + printf("buffer malloc failure.\n"); + return NULL; + } + ret = fread(data, 1, sz, fp); + return data; +} + +static unsigned char *load_model(const char *filename, int *model_size) +{ + + FILE *fp; + unsigned char *data; + + fp = fopen(filename, "rb"); + if (NULL == fp) + { + printf("Open file %s failed.\n", filename); + return NULL; + } + + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + + data = load_data(fp, 0, size); + + fclose(fp); + + *model_size = size; + return data; +} + +static int saveFloat(const char *file_name, float *output, int element_size) +{ + FILE *fp; + fp = fopen(file_name, "w"); + for (int i = 0; i < element_size; i++) + { + fprintf(fp, "%.6f\n", output[i]); + } + fclose(fp); + return 0; +} + +static unsigned char *load_image(const char *image_path, int *org_height, int *org_width, int *org_ch, rknn_tensor_attr *input_attr) +{ + int req_height = 0; + int req_width = 0; + int req_channel = 0; + + switch (input_attr->fmt) + { + case RKNN_TENSOR_NHWC: + req_height = input_attr->dims[2]; + req_width = input_attr->dims[1]; + req_channel = input_attr->dims[0]; + break; + case RKNN_TENSOR_NCHW: + req_height = input_attr->dims[1]; + req_width = input_attr->dims[0]; + req_channel = input_attr->dims[2]; + break; + default: + printf("meet unsupported layout\n"); + return NULL; + } + + // printf("w=%d,h=%d,c=%d, fmt=%d\n", req_width, req_height, req_channel, input_attr->fmt); + + int height = 0; + int width = 0; + int channel = 0; + + unsigned char *image_data = stbi_load(image_path, &width, &height, &channel, req_channel); + if (image_data == NULL) + { + printf("load image-%s failed!\n", image_path); + return NULL; + } + + if (channel == 1){ + printf("image is grey, convert to RGB"); + void* rgb_data = malloc(width* height* 3); + for(int i=0; im_path = (char *)modelpath; + // m->in_path = (char *)"/demo/pic/test1_save.jpg"; + m->in_path = (char *)"/demo/pic/test.jpg"; + + + //写死argv[1] + m->m_type = YOLOV5; + m->color_expect = RK_FORMAT_RGB_888; + m->anchor_per_branch = 3; + printf("Runing with yolov5 model\n"); + + + // load anchors + int n = 2* m->out_nodes* m->anchor_per_branch; + printf("anchors: "); + int result[18]={10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90, 156, 198, 373, 326}; + for (int i=0; i<18; i++){ + m->anchors[i] = result[i]; + printf("%d ", m->anchors[i]); + } + printf("\n"); + + //写死 argv[2] + m->post_type = U8; + printf("Post process with u8\n"); + + + //写死argv[3] + m->in_source = SINGLE_IMG; + printf("Test with single img\n"); + + return 0; +} + + +int query_model_info(MODEL_INFO *m, rknn_context ctx){ + int ret; + /* Query sdk version */ + rknn_sdk_version version; + ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, + sizeof(rknn_sdk_version)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("sdk version: %s driver version: %s\n", version.api_version, + version.drv_version); + + /* Get input,output attr */ + rknn_input_output_num io_num; + ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printf("model input num: %d, output num: %d\n", io_num.n_input, + io_num.n_output); + m->in_nodes = io_num.n_input; + m->out_nodes = io_num.n_output; + m->in_attr = (rknn_tensor_attr*)malloc(sizeof(rknn_tensor_attr)* io_num.n_input); + m->out_attr = (rknn_tensor_attr*)malloc(sizeof(rknn_tensor_attr)* io_num.n_output); + if (m->in_attr == NULL || m->out_attr == NULL){ + printf("alloc memery failed\n"); + return -1; + } + + for (int i = 0; i < io_num.n_input; i++) + { + m->in_attr[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &m->in_attr[i], + sizeof(rknn_tensor_attr)); + if (ret < 0) + { + printf("rknn_init error ret=%d\n", ret); + return -1; + } + printRKNNTensor(&m->in_attr[i]); + } + + for (int i = 0; i < io_num.n_output; i++) + { + m->out_attr[i].index = i; + ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(m->out_attr[i]), + sizeof(rknn_tensor_attr)); + printRKNNTensor(&(m->out_attr[i])); + } + + /* get input shape */ + if (io_num.n_input > 1){ + printf("expect model have 1 input, but got %d\n", io_num.n_input); + return -1; + } + + if (m->in_attr[0].fmt == RKNN_TENSOR_NCHW) + { + printf("model is NCHW input fmt\n"); + m->width = m->in_attr[0].dims[0]; + m->height = m->in_attr[0].dims[1]; + m->channel = m->in_attr[0].dims[2]; + } + else + { + printf("model is NHWC input fmt\n"); + m->width = m->in_attr[0].dims[1]; + m->height = m->in_attr[0].dims[2]; + m->channel = m->in_attr[0].dims[0]; + } + printf("model input height=%d, width=%d, channel=%d\n", m->height, m->width, + m->channel); + + return 0; +} + + +/*------------------------------------------- + Main Functions +-------------------------------------------*/ +int main(int argc, char **argv) +{ + RK_CHAR *pDeviceName_01 = "rkispp_scale0"; + RK_CHAR *pDeviceName_02 = "rkispp_scale1"; + RK_CHAR *pcDevNode = "/dev/dri/card0"; + char *iq_file_dir = "/etc/iqfiles"; + + RK_S32 s32CamId = 0; + RK_U32 u32BufCnt = 3; + RK_U32 fps = 20; + int ret; + + CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H264; + + printf("\n###############################################\n"); + printf("VI CameraIdx: %d\npDeviceName: %s\nResolution: %dx%d\n\n", + s32CamId,pDeviceName_01,video_width,video_height); + + printf("VO pcDevNode: %s\nResolution: %dx%d\n", + pcDevNode,disp_width,disp_height); + printf("###############################################\n\n"); + + if (iq_file_dir) + { + #ifdef RKAIQ + printf("#Rkaiq XML DirPath: %s\n", iq_file_dir); + rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; + const char* sns_ent_name = "m01_f_imx307 1-001a"; + const char *iq_file_dir = "/etc/iqfiles"; + // 调用rk_aiq_uapi_sysctl_init函数初始化AIQ上下文 + rk_aiq_sys_ctx_t* aiq_context = rk_aiq_uapi_sysctl_init(sns_ent_name, iq_file_dir, NULL, NULL); + // 检查AIQ上下文是否成功初始化 + if (aiq_context != NULL) { + printf("AIQ上下文初始化成功,可以进行后续操作\n"); + } else { + printf("AIQ上下文初始化失败\n"); + } + // int res_stop = rk_aiq_uapi_sysctl_stop(aiq_context); + // if (res_stop == 0) { + // printf("关闭aiq成功\n"); + // } else { + // printf("关闭aiq失败\n"); + // } + + + bool en = 1; + XCamReturn res_aiq = rk_aiq_uapi_setFecEn(aiq_context, en); + if (res_aiq == 0) { + printf("鱼眼畸变校正功能开启成功\n"); + } else { + printf("鱼眼畸变校正功能开启失败\n"); + } + + fec_correct_direction_t direction = FEC_CORRECT_DIRECTION_XY; + int res_Direction = rk_aiq_uapi_setFecCorrectDirection(aiq_context, direction); + if (res_Direction == 0) { + printf("设置鱼眼畸变校正方向成功\n"); + } else { + printf("设置鱼眼畸变校正方向失败\n"); + } + + int res_setLevel = rk_aiq_uapi_setFecCorrectLevel(aiq_context, 255); + if (res_setLevel == 0) { + printf("设置鱼眼畸变校正等级成功\n"); + } else { + printf("设置鱼眼畸变校正等级失败\n"); + } + + // int res_prepare = rk_aiq_uapi_sysctl_prepare(aiq_context, video_width, video_height, hdr_mode); + // if (res_prepare == 0) { + // printf("准备AIQ运行环境成功\n"); + // } else { + // printf("准备AIQ运行环境失败\n"); + // } + + // int res_start = rk_aiq_uapi_sysctl_start(aiq_context); + // if (res_start == 0) { + // printf("启动AIQ控制系统成功\n"); + // } else { + // printf("启动AIQ控制系统失败\n"); + // } + + SAMPLE_COMM_ISP_Init(s32CamId,hdr_mode, RK_FALSE,iq_file_dir); + SAMPLE_COMM_ISP_Run(s32CamId); + // SAMPLE_COMM_ISP_SetFrameRate(s32CamId,25); + SAMPLE_COMM_ISP_SetFrameRate(s32CamId, fps); + + #endif + } + + // init rtsp + g_rtsplive = create_rtsp_demo(554); + g_rtsp_session = rtsp_new_session(g_rtsplive, "/live/main_stream"); + if (enCodecType == RK_CODEC_TYPE_H264) + { + rtsp_set_video(g_rtsp_session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0); + } + else if (enCodecType == RK_CODEC_TYPE_H265) + { + rtsp_set_video(g_rtsp_session, RTSP_CODEC_ID_VIDEO_H265, NULL, 0); + } + else + { + printf("not support other type\n"); + return -1; + } + rtsp_sync_video_ts(g_rtsp_session, rtsp_get_reltime(), rtsp_get_ntptime()); + + RK_MPI_SYS_Init(); + VI_CHN_ATTR_S vi_chn_attr_01; + memset(&vi_chn_attr_01, 0, sizeof(vi_chn_attr_01)); + vi_chn_attr_01.pcVideoNode = pDeviceName_01; + vi_chn_attr_01.u32BufCnt = u32BufCnt; + vi_chn_attr_01.u32Width = video_width; + vi_chn_attr_01.u32Height = video_height; + vi_chn_attr_01.enPixFmt = IMAGE_TYPE_NV12; + vi_chn_attr_01.enBufType = VI_CHN_BUF_TYPE_MMAP; + vi_chn_attr_01.enWorkMode = VI_WORK_MODE_NORMAL; + ret = RK_MPI_VI_SetChnAttr(s32CamId, 0, &vi_chn_attr_01); + ret |= RK_MPI_VI_EnableChn(s32CamId, 0); + if (ret) + { + printf("ERROR: create VI[0:0] error! ret=%d\n", ret); + return 0; + } + + RGA_ATTR_S stRgaAttr_01; + memset(&stRgaAttr_01, 0, sizeof(stRgaAttr_01)); + stRgaAttr_01.bEnBufPool = RK_TRUE; + stRgaAttr_01.u16BufPoolCnt = 3; + stRgaAttr_01.u16Rotaion = 0; + stRgaAttr_01.stImgIn.u32X = 0; + stRgaAttr_01.stImgIn.u32Y = 0; + stRgaAttr_01.stImgIn.imgType = IMAGE_TYPE_NV12; + stRgaAttr_01.stImgIn.u32Width = video_width; + stRgaAttr_01.stImgIn.u32Height = video_height; + stRgaAttr_01.stImgIn.u32HorStride = video_width; + stRgaAttr_01.stImgIn.u32VirStride = video_height; + stRgaAttr_01.stImgOut.u32X = 0; + stRgaAttr_01.stImgOut.u32Y = 0; + // stRgaAttr_01.stImgOut.imgType = IMAGE_TYPE_RGB888; + stRgaAttr_01.stImgOut.imgType = IMAGE_TYPE_BGR888; + stRgaAttr_01.stImgOut.u32Width = video_width; + stRgaAttr_01.stImgOut.u32Height = video_height; + stRgaAttr_01.stImgOut.u32HorStride = video_width; + stRgaAttr_01.stImgOut.u32VirStride = video_height; + ret = RK_MPI_RGA_CreateChn(0, &stRgaAttr_01); + if (ret) + { + printf("ERROR: create RGA[0:0] falied! ret=%d\n", ret); + return -1; + } + + VENC_CHN_ATTR_S venc_chn_attr; + memset(&venc_chn_attr, 0, sizeof(venc_chn_attr)); + switch (enCodecType) + { + case RK_CODEC_TYPE_H265: + venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H265; + venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR; + venc_chn_attr.stRcAttr.stH265Cbr.u32Gop = 30; + venc_chn_attr.stRcAttr.stH265Cbr.u32BitRate = video_width * video_height; + // frame rate: in 30/1, out 30/1. + venc_chn_attr.stRcAttr.stH265Cbr.fr32DstFrameRateDen = 1; + venc_chn_attr.stRcAttr.stH265Cbr.fr32DstFrameRateNum = 30; + venc_chn_attr.stRcAttr.stH265Cbr.u32SrcFrameRateDen = 1; + venc_chn_attr.stRcAttr.stH265Cbr.u32SrcFrameRateNum = 30; + break; + case RK_CODEC_TYPE_H264: + default: + venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264; + venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; + venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30; + venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = video_width * video_height * 3; + // frame rate: in 30/1, out 30/1. + venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1; + venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 30; + venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1; + venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 30; + break; + } + + venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_RGB888; + venc_chn_attr.stVencAttr.u32PicWidth = video_width; + venc_chn_attr.stVencAttr.u32PicHeight = video_height; + venc_chn_attr.stVencAttr.u32VirWidth = video_width; + venc_chn_attr.stVencAttr.u32VirHeight = video_height; + venc_chn_attr.stVencAttr.u32Profile = 66; + ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr); + if (ret) + { + printf("ERROR: create VENC[0:0] error! ret=%d\n", ret); + return -1; + } + + MPP_CHN_S stSrcChn; + MPP_CHN_S stDestChn; + printf("Bind VI[0:0] to RGA[0:0]....\n"); + stSrcChn.enModId = RK_ID_VI; + stSrcChn.s32DevId = s32CamId; + stSrcChn.s32ChnId = 0; + stDestChn.enModId = RK_ID_RGA; + stSrcChn.s32DevId = s32CamId; + stDestChn.s32ChnId = 0; + ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn); + if (ret) + { + printf("ERROR: bind VI[0:0] to RGA[0:0] failed! ret=%d\n", ret); + return -1; + } + + pthread_t rtsp_tidp; + pthread_t rkmedia_rknn_tidp; + pthread_create(&rkmedia_rknn_tidp, NULL, rkmedia_rknn_thread, NULL); + pthread_create(&rtsp_tidp, NULL, venc_rtsp_tidp, NULL); + + printf("%s initial finish\n", __func__); + + + while (!quit) + { + usleep(500000); + } + + printf("UnBind VI[0:0] to RGA[0:0]....\n"); + stSrcChn.enModId = RK_ID_VI; + stSrcChn.s32DevId = s32CamId; + stSrcChn.s32ChnId = 0; + stDestChn.enModId = RK_ID_RGA; + stSrcChn.s32DevId = s32CamId; + stDestChn.s32ChnId = 0; + ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn); + if (ret) + { + printf("ERROR: unbind VI[0:0] to RGA[0:0] failed! ret=%d\n", ret); + return -1; + } + + RK_MPI_VENC_DestroyChn(0); + RK_MPI_RGA_DestroyChn(0); + RK_MPI_VI_DisableChn(s32CamId, 0); + + if (iq_file_dir) + { +#if RKAIQ + SAMPLE_COMM_ISP_Stop(s32CamId); +#endif + } + return 0; +} + +void *rkmedia_rknn_thread(void *args) +{ + pthread_detach(pthread_self()); + auto last_time = std::chrono::high_resolution_clock::now();// 记录开始时间 + int numperson = 0; + int time2run_count = 0; + // 创建一个 Alarm 结构体对象 + Alarm Alarm; + // 调用初始化函数来初始化结构体成员 + initializeAlarm(&Alarm); + + readFileAndStoreInGlobal((char *)FILE_PWD); + // 打印全局字符串变量 + std::cout << "文件内容:" << DeviceID < ft; + ft = cv::freetype::createFreeType2(); + ft->loadFontData( "/demo/bin/simfang.ttf", 0 ); + + while (!quit) + { + Alarm.ifalarm = 0; + int time2run = 0; + int time2capture = 0; + int time2overlay = 0; + auto current_time = std::chrono::high_resolution_clock::now(); + auto elapsed_time = std::chrono::duration_cast(current_time - last_time);// 计算距离开始时间的时间差 + + if (elapsed_time.count() - 1000 > 0) { + last_time = current_time; + time2capture = 1; + time2run_count++; + if(time2run_count>2){ + time2run_count = 0; + time2overlay = 1; + time2run = 1; + } + } + + //获取摄像头buffer + MEDIA_BUFFER src_mb = NULL; + src_mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA, 0, -1); + if (!src_mb) + { + printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n"); + // break; + } + + /* Init input tensor */ + rknn_input inputs[1]; + memset(inputs, 0, sizeof(inputs)); + inputs[0].index = 0; + inputs[0].type = RKNN_TENSOR_UINT8; /* SAME AS INPUT IMAGE */ + inputs[0].size = m_info.width * m_info.height * m_info.channel; + inputs[0].fmt = RKNN_TENSOR_NHWC; /* SAME AS INPUT IMAGE */ + inputs[0].pass_through = 0; + + /* Init output tensor */ + rknn_output outputs[m_info.out_nodes]; + memset(outputs, 0, sizeof(outputs)); + for (int i = 0; i < m_info.out_nodes; i++) + { + outputs[i].want_float = m_info.post_type; + } + + void *resize_buf = malloc(inputs[0].size); + if (resize_buf == NULL){ + printf("resize buf alloc failed\n"); + return NULL; + } + unsigned char *input_data = NULL; + /* Single img input */ + /* Due to different input img size, multi img method has to calculate letterbox param each time*/ + if (m_info.in_source == SINGLE_IMG) + { + /* Input preprocess */ + // Load image + // CImg img(m_info.in_path); + + // if(time2overlay){ + // Mat orig_img = Mat(video_height, video_width, CV_8UC3, RK_MPI_MB_GetPtr(src_mb)); + // // 在图像上指定的位置绘制 overlay_img + // int x = 0; // x 坐标 + // int y = 0; // y 坐标 + // // 创建一个感兴趣区域 (ROI) 来指定绘制的位置 + // cv::Rect roi(x, y, overlay_img.cols, overlay_img.rows); + // // 将 overlay_img 复制到 orig_img 的指定位置 + // overlay_img.copyTo(orig_img(roi)); + // } + + + + + // Mat overlay_img = imread("/demo/pic/test.jpg"); + // cv::cvtColor(overlay_img, overlay_img, cv::COLOR_BGR2RGB); + + + // if (!overlay_img.empty()) { + // // 图像加载成功 + // cout << "Image loaded successfully." << endl; + // // 进行图像处理等操作 + // } else { + // // 图像加载失败 + // cout << "Image failed to load." << endl; + // } + + // int overlay_img_channels = overlay_img.channels(); + // int orig_img_channels = orig_img.channels(); + + // cout << "Overlay Image Channels: " << overlay_img_channels << endl; + // cout << "Original Image Channels: " << orig_img_channels << endl; + // Mat orig_img = Mat(video_height, video_width, CV_8UC3, RK_MPI_MB_GetPtr(src_mb)); + // // 在图像上指定的位置绘制 overlay_img + // int x = 900; // x 坐标 + // int y = 450; // y 坐标 + // // 创建一个感兴趣区域 (ROI) 来指定绘制的位置 + // cv::Rect roi(x, y, overlay_img.cols, overlay_img.rows); + // // 将 overlay_img 复制到 orig_img 的指定位置 + // overlay_img.copyTo(orig_img(roi)); + + + // input_data = load_image(m_info.in_path, &img_height, &img_width, &img_channel, &m_info.in_attr[0]); + // if (!input_data){ + // fprintf(stderr, "Error in loading input image\n"); + // return NULL; + // } + + // printf("img_width: %d\nimg_height: %d\nimg_channel: %d\n", img_width, img_height, img_channel); + + // DRM alloc buffer + drm_fd = drm_init(&drm_ctx); + drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, video_width, video_height, channel * 8, + &buf_fd, &handle, &actual_size); + // printf("create drm buffer finish\n"); + // memcpy(drm_buf, orig_img.data , video_width * video_height * channel); + memcpy(drm_buf, (uint8_t *)RK_MPI_MB_GetPtr(src_mb) , video_width * video_height * channel); + memset(resize_buf, 0, inputs[0].size); + // printf("set resize buf finish\n"); + + // drm_fd = drm_init(&drm_ctx); + // drm_buf = drm_buf_alloc(&drm_ctx, drm_fd, img_width, img_height, img_channel * 8, + // &buf_fd, &handle, &actual_size); + // printf("create drm buffer finish\n"); + // memcpy(drm_buf, input_data, img_width * img_height * img_channel); + // memset(resize_buf, 0, inputs[0].size); + // printf("set resize buf finish\n"); + + // Letter box resize + letter_box.target_height = m_info.height; + letter_box.target_width = m_info.width; + letter_box.in_height = img_height; + letter_box.in_width = img_width; + compute_letter_box(&letter_box); + + if ((m_info.height!= img_height) || (m_info.width!= img_width)){ + // Init rga context + + // gettimeofday(&start_time_resize, NULL); + // printf("WARNING: img_size(w:%d h:%d) not match model input_size(w:%d h:%d)\n", img_width, img_height, m_info.width, m_info.height); + // printf("Try resize img with rga. If any error occur, please using image with size(w:%d h:%d) or using newer firmware to update rga driver version\n", m_info.width, m_info.height); + RGA_init(&rga_ctx); + img_resize_slow(&rga_ctx, drm_buf, img_width, img_height, resize_buf, letter_box.resize_width, letter_box.resize_height, + letter_box.w_pad, letter_box.h_pad, m_info.color_expect, + letter_box.add_extra_sz_w_pad, letter_box.add_extra_sz_h_pad); + inputs[0].buf = resize_buf; + // gettimeofday(&stop_time_resize, NULL); + // printf("once img_resize_slow use %f ms\n", + // (__get_us(stop_time_resize) - __get_us(start_time_resize)) / 1000); + } + else{ + inputs[0].buf = drm_buf; + } + +#if (DUMP_INPUT == 1) + FILE* dump_file; + if ((dump_file = fopen("./demo_c_input_hwc_rgb.txt", "wb")) == NULL){ + printf("Dump input Failed !\n"); + } + else{ + fwrite(resize_buf, sizeof(uint8_t), inputs[0].size, dump_file); + printf("Dump input Successed. Path: ./demo_c_input_hwc_rgb.txt !\n"); + } + fclose(dump_file); +#endif + gettimeofday(&start_time, NULL); + rknn_inputs_set(ctx, m_info.in_nodes, inputs); + if (time2run && IF_RUN_RKNN) { + readFileAndStoreInGlobal((char *)FILE_PWD); + // 打印全局字符串变量 + std::cout << "文件内容:" << DeviceID <name, + det_result->box.left, det_result->box.top, det_result->box.right, det_result->box.bottom, + det_result->prop); + } + int x1 = det_result->box.left; + int y1 = det_result->box.top; + int x2 = det_result->box.right; + int y2 = det_result->box.bottom; + int ret = snprintf(score_result, sizeof score_result, "%f", det_result->prop); + //draw box + Mat orig_img = Mat(video_height, video_width, CV_8UC3, RK_MPI_MB_GetPtr(src_mb));//黑白灰图案 + cv::rectangle(orig_img,cv::Point(x1, y1),cv::Point(x2, y2),cv::Scalar(0,255,0),3,8,0); + // putText(orig_img, name_prop,Point(x1, y1-16), FONT_HERSHEY_TRIPLEX, 2, Scalar(0,225,0),4,8,0); + std::stringstream stream; + stream << std::fixed << std::setprecision(2) << detect_result_group.results[i].prop; + std::string name_prop = Charge_Chinese(detect_result_group.results[i].name) + ":" + stream.str(); + ft->putText(orig_img, name_prop, cv::Point(x1, y1-16), 30, cv::Scalar(0,255,0), -1, 8, true); + if(time2run){ + // 打印信息 + // printf("border=(%d %d %d %d)\n", left, top, w, h); + // printf("%s\n", det_result->name); + if (det_result->name != NULL && strcmp(det_result->name, "smoke") == 0 && det_result->prop >0.60) + { + Alarm.ifalarm = 1; + Alarm.alarmCode = "03"; + Alarm.alarmRemark = "抽烟报警"; + Alarm.alarmprop = det_result->prop; + } + if (det_result->name != NULL && strcmp(det_result->name, "ebike") == 0 && det_result->prop >0.75) + { + Alarm.ifalarm = 1; + Alarm.alarmCode = "01"; + Alarm.alarmRemark = "电瓶车报警"; + Alarm.alarmprop = det_result->prop; + } + if (det_result->name != NULL && strcmp(det_result->name, "fog") == 0 && det_result->prop >0.60) + { + Alarm.ifalarm = 1; + Alarm.alarmCode = "05"; + Alarm.alarmRemark = "烟雾报警"; + Alarm.alarmprop = det_result->prop; + } + if (det_result->name != NULL && strcmp(det_result->name, "head") == 0 && det_result->prop >0.60) + { + numperson++; + } + if (det_result->name != NULL && strcmp(det_result->name, "fall") == 0 && det_result->prop >0.60) + { + Alarm.ifalarm = 1; + Alarm.alarmCode = "06"; + Alarm.alarmRemark = "人员跌倒报警"; + Alarm.alarmprop = det_result->prop; + } + if (det_result->name != NULL && strcmp(det_result->name, "fire") == 0 && det_result->prop >0.60) + { + Alarm.ifalarm = 1; + Alarm.alarmCode = "04"; + Alarm.alarmRemark = "火焰报警"; + Alarm.alarmprop = det_result->prop; + } + } + + } + if(numperson > 10){ + Alarm.ifalarm = 1; + Alarm.alarmCode = "02"; + Alarm.alarmRemark = "人数超载报警"; + } + // 设置压缩质量 + std::vector compression_params; + compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); + compression_params.push_back(30); // 设置压缩质量,范围为 0-100 + + if((time2run && Alarm.ifalarm == 1)) + { + // printf("ifalarm=%d upload_message_tidp\n",Alarm.ifalarm); + // printf("alarmCode=%s\n",Alarm.alarmCode.c_str()); + // printf("alarmRemark=%s\n",Alarm.alarmRemark.c_str()); + // printf("prop=%f\n",Alarm.alarmprop); + printf("警报图片保存并上传"); + Mat orig_img = Mat(video_height, video_width, CV_8UC3, RK_MPI_MB_GetPtr(src_mb)); + Mat save_img = orig_img.clone(); + cv::cvtColor(save_img, save_img, cv::COLOR_BGR2RGB); + cv::imwrite("/demo/pic/Alarm.jpg", save_img, compression_params); + pthread_t upload_message_tidp; + pthread_create(&upload_message_tidp, NULL, upload_message, static_cast(&Alarm)); + } + + if((time2capture && (!IF_RUN_RKNN))) + { + // printf("ifalarm=%d upload_message_tidp\n",Alarm.ifalarm); + // printf("alarmCode=%s\n",Alarm.alarmCode.c_str()); + // printf("alarmRemark=%s\n",Alarm.alarmRemark.c_str()); + // printf("prop=%f\n",Alarm.alarmprop); + printf("不检测,采集图片保存并上传\n"); + Mat orig_img = Mat(video_height, video_width, CV_8UC3, RK_MPI_MB_GetPtr(src_mb)); + Mat save_img = orig_img.clone(); + cv::cvtColor(save_img, save_img, cv::COLOR_BGR2RGB); + cv::imwrite("/demo/pic/Alarm.jpg", save_img, compression_params); + pthread_t upload_message_tidp; + pthread_create(&upload_message_tidp, NULL, upload_message, static_cast(&Alarm)); + } + + + + + + numperson = 0; //人数计数归零 + ret = rknn_outputs_release(ctx, m_info.out_nodes, outputs); + + + RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC, 0, src_mb); + RK_MPI_MB_ReleaseBuffer(src_mb); + src_mb = NULL; + drm_buf_destroy(&drm_ctx, drm_fd, buf_fd, handle, drm_buf, actual_size); + drm_deinit(&drm_ctx, drm_fd); + RGA_deinit(&rga_ctx); + free(input_data); + free(resize_buf); + } + } + + + + // release + ret = rknn_destroy(ctx); + + RGA_deinit(&rga_ctx); + if (model_data) + { + free(model_data); + } + + + if (m_info.in_attr){ + free(m_info.in_attr); + } + + if (m_info.out_attr){ + free(m_info.out_attr); + } + + return NULL; +} + +void *venc_rtsp_tidp(void *args) +{ + pthread_detach(pthread_self());//将线程状态改为unjoinable状态,确保资源的释放 + auto last_time = std::chrono::high_resolution_clock::now(); + MEDIA_BUFFER mb = NULL; + while (!quit) + { + int time2run_rtsp = 0; + auto current_time = std::chrono::high_resolution_clock::now(); + auto elapsed_time = std::chrono::duration_cast(current_time - last_time);// 计算距离开始时间的时间差 + if (elapsed_time.count() - 33 > 0) { + last_time = current_time; + time2run_rtsp = 1; + } + // if(time2run_rtsp){ + mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 0, -1); + if (!mb) + { + printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n"); + break; + } + // // 获取当前时间的时间戳 + // auto now = std::chrono::high_resolution_clock::now(); + + // // 将时间戳转换为 uint64_t 类型 + // uint64_t timestamp_chrono = std::chrono::duration_cast(now.time_since_epoch()).count(); + + // std::cout << "chrono Timestamp: " << timestamp_chrono << std::endl; + rtsp_tx_video(g_rtsp_session, (unsigned char *)RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), RK_MPI_MB_GetTimestamp(mb)); + // rtsp_tx_video(g_rtsp_session, (unsigned char *)RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), timestamp_chrono); + // uint64_t timestamp = RK_MPI_MB_GetTimestamp(mb); + // std::cout << "RK_MPI_MB_GetTimestamp Timestamp: " << timestamp << std::endl; + + + RK_MPI_MB_ReleaseBuffer(mb); + rtsp_do_event(g_rtsplive); + // } + + } + return NULL; +} + + +void *upload_message(void *args) +{ + printf("upload_message_run\n"); + Alarm* alarm = static_cast(args); // 将传入的参数转换回结构体类型 + pthread_detach(pthread_self());//将线程状态改为unjoinable状态,确保资源的释放 + // 获取当前系统时间 + std::time_t alarmTime_std = std::time(nullptr); + + // 将时间转换为本地时间 + std::tm* localTime = std::localtime(&alarmTime_std); + + // 从本地时间结构中获取时间信息 + int year = localTime->tm_year + 1900; + int month = localTime->tm_mon + 1; + int day = localTime->tm_mday; + int hour = localTime->tm_hour; + int minute = localTime->tm_min; + int second = localTime->tm_sec; + + // 拼接成字符串 + std::ostringstream oss_alarmTime; + oss_alarmTime << std::setfill('0') + << std::setw(4) << year << "-" + << std::setw(2) << month << "-" + << std::setw(2) << day << " " + << std::setw(2) << hour << ":" + << std::setw(2) << minute << ":" + << std::setw(2) << second; + + // 获取拼接后的字符串 + std::string formattedTime = oss_alarmTime.str(); + + // 打印结果 + std::cout << "当前系统时间:" << formattedTime << std::endl; + + + // det_result->name 不为空且和 "no_helmet" 相等 + // 监测到不戴安全帽时执行的程序 + // //上传信息 + // CURL *curl; + // CURLcode res; + // curl_global_init(CURL_GLOBAL_ALL); + // curl = curl_easy_init(); + // if(curl) + // { + // curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.106:5000/receive_string"); + // /* Now specify the POST data */ + // struct curl_slist *plist = nullptr; + // plist = curl_slist_append(plist, "Content-Type:application/json;charset=UTF-8"); + // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, plist); + // curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "no_helmet from owl"); + // // std::cout << szJsonData << std::endl; + + // /* Perform the request, res will get the return code */ + // res = curl_easy_perform(curl); + // /* Check for errors */ + // if(res != CURLE_OK) + // fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res)); + // // /* always cleanup */ + // curl_easy_cleanup(curl); + // } + // curl_global_cleanup(); + + + //上传图片到服务器并接受返回的路径 + CURL *curl; + CURLcode res; + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + std::string src_pic ; + if(curl) + { + // 设置请求的 URL + curl_easy_setopt(curl, CURLOPT_URL, "36.108.213.190:10004/system/alarmUpload"); + + // 添加文件参数 + curl_httppost* formpost = nullptr; + curl_httppost* lastptr = nullptr; + curl_formadd(&formpost, &lastptr, + CURLFORM_COPYNAME, "file", + CURLFORM_FILE, "/demo/pic/Alarm.jpg", + CURLFORM_END); + + // 添加其他参数 + curl_formadd(&formpost, &lastptr, + CURLFORM_COPYNAME, "folderName", + CURLFORM_COPYCONTENTS, "myFolder", + CURLFORM_END); + + // 设置请求的内容类型为 multipart/form-data + struct curl_slist* headers = nullptr; + headers = curl_slist_append(headers, "Content-Type: multipart/form-data"); + headers = curl_slist_append(headers, "Expect:"); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + // 设置请求体 + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + + + // 设置响应回调函数和缓冲区 + std::string response; + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + // 执行请求 + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + std::cerr << "Failed to perform cURL request: " << curl_easy_strerror(res) << std::endl; + } else { + std::cout << "Request successful!" << std::endl; + std::cout << "Response: " << response << std::endl; + src_pic = extractSrcValue(response);//从返回信息里截取src的信息 + // std::cout << "src: " << src_pic << std::endl; + } + + + // 释放资源 + curl_easy_cleanup(curl); + curl_formfree(formpost); + curl_slist_free_all(headers); + } + curl_global_cleanup(); + + std::cout << "src_pic.c_str(): " << src_pic.c_str() << std::endl; + //上传图片 + // 读取原始图片文件 + // char* imgfilename = (char*)args; + // std::string filepath = "/demo/pic/" + std::string(imgfilename); + // std::ifstream file(filepath, std::ios::in | std::ios::binary); + // std::ifstream file("/demo/pic/Alarm.jpg", std::ios::in | std::ios::binary); + // std::ostringstream oss; + // oss << file.rdbuf(); + // std::string orig_data = oss.str(); + + + + // 编码图片数据为base64格式 + // std::string encoded_data = base64_encode(reinterpret_cast(orig_data.c_str()), orig_data.length()); + //上传base64 + // CURL *curl; + // CURLcode res_image; + + + // std::string alarmCode = "01"; + std::string alarmCode = (alarm->alarmCode).c_str(); + // std::string alarmTime = "2021-12-03 12:22:22"; + std::string alarmTime = formattedTime; + // std::string alarmRemark = "电瓶车报警"; + std::string alarmRemark = (alarm->alarmRemark).c_str(); + // std::string alarmImg = encoded_data.c_str(); + std::string alarmImg = src_pic.c_str(); + std::string alarmVideo = DeviceID; + + std::cout << "alarmCode: " << alarmCode << " alarmRemark: " << alarmRemark << "alarmVideo: " << alarmVideo < +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _BASETSD_H + +#include "im2d.h" +#include "rga.h" +#include "drm_func.h" +#include "rga_func.h" +#include "rknn_api.h" +#include "rkmedia_api.h" +#include "rkmedia_venc.h" +#include "sample_common.h" +#include "opencv2/opencv.hpp" + +#include "librtsp/rtsp_demo.h" +#include "rk_aiq_user_api_sysctl.h" +#include "rk_aiq_user_api_afec.h" +// #include "rk_aiq_uapi_afec_int.h" + +#include +#include +#include "opencv2/imgcodecs.hpp" +#include + +using namespace cv; + + + +RK_U32 video_width = 1920; +RK_U32 video_height = 1072; +// RK_U32 video_height = 720; +int disp_width = 720; +int disp_height = 1280; + +static bool quit = false; +rtsp_demo_handle g_rtsplive = NULL; +static rtsp_session_handle g_rtsp_session; + +int rgb24_resize(unsigned char *input_rgb, unsigned char *output_rgb, int width,int height, int outwidth, int outheight); + +static unsigned char *load_model(const char *filename, int *model_size); + +static void printRKNNTensor(rknn_tensor_attr *attr); + +void *rkmedia_rknn_thread(void *args); +void *venc_rtsp_tidp(void *args); +void *upload_message(void *args); //上传检测信息与截取的图片 +void *upload_heart_beat(void *args); //上传心跳检测 +void *distortion(void *args); //矫正 + +#endif \ No newline at end of file diff --git a/rknn_yolo_demo/src/rga_func.c b/rknn_yolo_demo/src/rga_func.c new file mode 100644 index 0000000..aaea364 --- /dev/null +++ b/rknn_yolo_demo/src/rga_func.c @@ -0,0 +1,129 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "rga_func.h" + +int RGA_init(rga_context *rga_ctx) +{ + rga_ctx->rga_handle = dlopen("librga.so", RTLD_LAZY); + if (!rga_ctx->rga_handle) + { + printf("dlopen librga.so failed\n"); + printf("dlopen error: %s\n", dlerror()); + return -1; + } + rga_ctx->init_func = (FUNC_RGA_INIT)dlsym(rga_ctx->rga_handle, "c_RkRgaInit"); + rga_ctx->deinit_func = (FUNC_RGA_DEINIT)dlsym(rga_ctx->rga_handle, "c_RkRgaDeInit"); + rga_ctx->blit_func = (FUNC_RGA_BLIT)dlsym(rga_ctx->rga_handle, "c_RkRgaBlit"); + rga_ctx->init_func(); + return 0; +} + +void img_resize_fast(rga_context *rga_ctx, int src_fd, int src_w, int src_h, uint64_t dst_phys, int dst_w, int dst_h) +{ + // printf("rga use fd, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + + if (rga_ctx->rga_handle) + { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = src_fd; + src.mmuFlag = 1; + // src.virAddr = (void *)psrc; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 0; + +#if defined(__arm__) + dst.phyAddr = (void *)((uint32_t)dst_phys); +#else + dst.phyAddr = (void *)dst_phys; +#endif + + dst.nn.nn_flag = 0; + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + rga_set_rect(&dst.rect, 0, 0, dst_w, dst_h, dst_w, dst_h, RK_FORMAT_RGB_888); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret) + { + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +void img_resize_slow(rga_context *rga_ctx, void *src_virt, int src_w, int src_h, void *dst_virt, int dst_w, int dst_h, + int w_offset, int h_offset, RgaSURF_FORMAT color, bool add_extra_sz_w, bool add_extra_sz_h) +{ + // printf("rga use virtual, src(%dx%d) -> dst(%dx%d)\n", src_w, src_h, dst_w, dst_h); + if (rga_ctx->rga_handle) + { + int ret = 0; + rga_info_t src, dst; + + memset(&src, 0, sizeof(rga_info_t)); + src.fd = -1; + src.mmuFlag = 1; + src.virAddr = (void *)src_virt; + + memset(&dst, 0, sizeof(rga_info_t)); + dst.fd = -1; + dst.mmuFlag = 1; + dst.virAddr = dst_virt; + + dst.nn.nn_flag = 0; + // printf("input to rga para, w_offset: %d, h_offset: %d, dst_w: %d, dst_h: %d\n", + // w_offset, h_offset, dst_w, dst_h); + + rga_set_rect(&src.rect, 0, 0, src_w, src_h, src_w, src_h, RK_FORMAT_RGB_888); + int src_w = dst_w + 2*w_offset; + int src_h = dst_h + 2*h_offset; + if (add_extra_sz_w){ + src_w += 1; + // printf("Adding extra sz w: %d\n", src_w); + } + else if (add_extra_sz_h){ + src_h += 1; + // printf("Adding extra sz h: %d\n", src_h); + } + + //rga_set_rect(&dst.rect, w_offset, h_offset, dst_w, dst_h, src_w, dst_h + 2*h_offset, color); + rga_set_rect(&dst.rect, w_offset, h_offset, dst_w, dst_h, src_w, src_h, color); + + ret = rga_ctx->blit_func(&src, &dst, NULL); + if (ret){ + printf("c_RkRgaBlit error : %s\n", strerror(errno)); + } + + return; + } + return; +} + +int RGA_deinit(rga_context *rga_ctx) +{ + if(rga_ctx->rga_handle) + { + dlclose(rga_ctx->rga_handle); + rga_ctx->rga_handle = NULL; + } +} \ No newline at end of file diff --git a/rknn_yolo_demo/src/yolo.cc b/rknn_yolo_demo/src/yolo.cc new file mode 100644 index 0000000..586fbbf --- /dev/null +++ b/rknn_yolo_demo/src/yolo.cc @@ -0,0 +1,525 @@ +// Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on annpu "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include "yolo.h" +#include +#define LABEL_NALE_TXT_PATH "/demo/bin/elevator-2_list.txt" + +static char *labels[OBJ_CLASS_NUM]; + +const int anchor0[6] = {10, 13, 16, 30, 33, 23}; +const int anchor1[6] = {30, 61, 62, 45, 59, 119}; +const int anchor2[6] = {116, 90, 156, 198, 373, 326}; + +inline static int clamp(float val, int min, int max) +{ + return val > min ? (val < max ? val : max) : min; +} + +char *readLine(FILE *fp, char *buffer, int *len) +{ + int ch; + int i = 0; + size_t buff_len = 0; + + buffer = (char *)malloc(buff_len + 1); + if (!buffer) + return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) + { + buff_len++; + void *tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) + { + free(buffer); + return NULL; // Out of memory + } + buffer = (char *)tmp; + + buffer[i] = (char)ch; + i++; + } + buffer[i] = '\0'; + + *len = buff_len; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) + { + free(buffer); + return NULL; + } + return buffer; +} + +int readLines(const char *fileName, char *lines[], int max_line) +{ + FILE *file = fopen(fileName, "r"); + char *s; + int i = 0; + int n = 0; + while ((s = readLine(file, s, &n)) != NULL) + { + lines[i++] = s; + if (i >= max_line) + break; + } + return i; +} + + +int readFloats(const char *fileName, float* result, int max_line, int* valid_number) +{ + FILE *file = fopen(fileName, "r"); + if (file == NULL) { + printf("failed to open file\n"); + return 1; + } + + int n = 0; + while ((n<=max_line) &&(fscanf(file, "%f", &result[n++]) != EOF)) + ; + + /* n-1 float values were successfully read */ + // for (int i=0; i &outputLocations, std::vector &class_id, std::vector &order, float threshold, bool class_agnostic) +{ + // printf("class_agnostic: %d\n", class_agnostic); + for (int i = 0; i < validCount; ++i) + { + if (order[i] == -1) + { + continue; + } + int n = order[i]; + for (int j = i + 1; j < validCount; ++j) + { + int m = order[j]; + if (m == -1) + { + continue; + } + + if (class_agnostic == false && class_id[n] != class_id[m]){ + continue; + } + + float xmin0 = outputLocations[n * 4 + 0]; + float ymin0 = outputLocations[n * 4 + 1]; + float xmax0 = outputLocations[n * 4 + 0] + outputLocations[n * 4 + 2]; + float ymax0 = outputLocations[n * 4 + 1] + outputLocations[n * 4 + 3]; + + float xmin1 = outputLocations[m * 4 + 0]; + float ymin1 = outputLocations[m * 4 + 1]; + float xmax1 = outputLocations[m * 4 + 0] + outputLocations[m * 4 + 2]; + float ymax1 = outputLocations[m * 4 + 1] + outputLocations[m * 4 + 3]; + + float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1); + + if (iou > threshold) + { + order[j] = -1; + } + } + } + return 0; +} + +static int quick_sort_indice_inverse( + std::vector &input, + int left, + int right, + std::vector &indices) +{ + float key; + int key_index; + int low = left; + int high = right; + if (left < right) + { + key_index = indices[left]; + key = input[left]; + while (low < high) + { + while (low < high && input[high] <= key) + { + high--; + } + input[low] = input[high]; + indices[low] = indices[high]; + while (low < high && input[low] >= key) + { + low++; + } + input[high] = input[low]; + indices[high] = indices[low]; + } + input[low] = key; + indices[low] = key_index; + quick_sort_indice_inverse(input, left, low - 1, indices); + quick_sort_indice_inverse(input, low + 1, right, indices); + } + return low; +} + +static float sigmoid(float x) +{ + return 1.0 / (1.0 + expf(-x)); +} + +static float unsigmoid(float y) +{ + return -1.0 * logf((1.0 / y) - 1.0); +} + +inline static int32_t __clip(float val, float min, float max) +{ + float f = val <= min ? min : (val >= max ? max : val); + return f; +} + +static uint8_t qnt_f32_to_affine(float f32, uint8_t zp, float scale) +{ + float dst_val = (f32 / scale) + zp; + uint8_t res = (uint8_t)__clip(dst_val, 0, 255); + return res; +} + +static float deqnt_affine_to_f32(uint8_t qnt, uint8_t zp, float scale) +{ + return ((float)qnt - (float)zp) * scale; +} + +static int process_u8(uint8_t *input, int *anchor, int anchor_per_branch, int grid_h, int grid_w, int height, int width, int stride, + std::vector &boxes, std::vector &boxScores, std::vector &classId, + float threshold, uint8_t zp, float scale, MODEL_TYPE yolo) +{ + int validCount = 0; + int grid_len = grid_h * grid_w; + float thres = threshold; + uint8_t thres_u8 = qnt_f32_to_affine(thres, zp, scale); + // printf("threash %f\n", thres); + // printf("thres_u8 %u\n", thres_u8); + // printf("scale %f\n", scale); + // printf("zp %u\n", zp); + + for (int a = 0; a < anchor_per_branch; a++) + { + for (int i = 0; i < grid_h; i++) + { + for (int j = 0; j < grid_w; j++) + { + uint8_t box_confidence = input[(PROP_BOX_SIZE * a + 4) * grid_len + i * grid_w + j]; + if (box_confidence >= thres_u8) + { + // printf("box_conf %u, thres_u8 %u\n", box_confidence, thres_u8); + int offset = (PROP_BOX_SIZE * a) * grid_len + i * grid_w + j; + uint8_t *in_ptr = input + offset; + + uint8_t maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < OBJ_CLASS_NUM; ++k) + { + uint8_t prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) + { + maxClassId = k; + maxClassProbs = prob; + } + } + + float box_conf_f32 = deqnt_affine_to_f32(box_confidence, zp, scale); + float class_prob_f32 = deqnt_affine_to_f32(maxClassProbs, zp, scale); + float limit_score = 0; + limit_score = box_conf_f32* class_prob_f32; + + // printf("limit score: %f\n", limit_score); + if (limit_score > threshold){ + float box_x, box_y, box_w, box_h; + if(yolo == YOLOX){ + box_x = deqnt_affine_to_f32(*in_ptr, zp, scale); + box_y = deqnt_affine_to_f32(in_ptr[grid_len], zp, scale); + box_w = deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale); + box_h = deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale); + box_w = exp(box_w)* stride; + box_h = exp(box_h)* stride; + } + else{ + box_x = deqnt_affine_to_f32(*in_ptr, zp, scale) * 2.0 - 0.5; + box_y = deqnt_affine_to_f32(in_ptr[grid_len], zp, scale) * 2.0 - 0.5; + box_w = deqnt_affine_to_f32(in_ptr[2 * grid_len], zp, scale) * 2.0; + box_h = deqnt_affine_to_f32(in_ptr[3 * grid_len], zp, scale) * 2.0; + box_w = box_w * box_w; + box_h = box_h * box_h; + } + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w *= (float)anchor[a * 2]; + box_h *= (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + boxScores.push_back(box_conf_f32* class_prob_f32); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + } + return validCount; +} + + + +static int process_fp(float *input, int *anchor, int anchor_per_branch,int grid_h, int grid_w, int height, int width, int stride, + std::vector &boxes, std::vector &boxScores, std::vector &classId, + float threshold, MODEL_TYPE yolo) +{ + // printf("anchor :"); + // for (int i=0; i= threshold) + { + int offset = (PROP_BOX_SIZE * a) * grid_len + i * grid_w + j; + float *in_ptr = input + offset; + + float maxClassProbs = in_ptr[5 * grid_len]; + int maxClassId = 0; + for (int k = 1; k < OBJ_CLASS_NUM; ++k) + { + float prob = in_ptr[(5 + k) * grid_len]; + if (prob > maxClassProbs) + { + maxClassId = k; + maxClassProbs = prob; + } + } + float box_conf_f32 = (box_confidence); + float class_prob_f32 = (maxClassProbs); + float limit_score = 0; + if (yolo == YOLOX){ + limit_score = class_prob_f32; + } + else{ + limit_score = box_conf_f32* class_prob_f32; + } + // printf("limit score: %f", limit_score); + if (limit_score > CONF_THRESHOLD){ + float box_x, box_y, box_w, box_h; + if (yolo == YOLOX){ + box_x = *in_ptr; + box_y = (in_ptr[grid_len]); + box_w = exp(in_ptr[2* grid_len])* stride; + box_h = exp(in_ptr[3* grid_len])* stride; + } + else{ + box_x = *in_ptr * 2.0 - 0.5; + box_y = (in_ptr[grid_len]) * 2.0 - 0.5; + box_w = (in_ptr[2 * grid_len]) * 2.0; + box_h = (in_ptr[3 * grid_len]) * 2.0; + box_w *= box_w; + box_h *= box_h; + } + box_x = (box_x + j) * (float)stride; + box_y = (box_y + i) * (float)stride; + box_w *= (float)anchor[a * 2]; + box_h *= (float)anchor[a * 2 + 1]; + box_x -= (box_w / 2.0); + box_y -= (box_h / 2.0); + + boxes.push_back(box_x); + boxes.push_back(box_y); + boxes.push_back(box_w); + boxes.push_back(box_h); + boxScores.push_back(box_conf_f32* class_prob_f32); + classId.push_back(maxClassId); + validCount++; + } + } + } + } + } + return validCount; +} + + +int post_process(rknn_output* rk_outputs, MODEL_INFO* m, LETTER_BOX* lb, detect_result_group_t* group){ + // printf("post process\n"); + static int init = -1; + if (init == -1) + { + int ret = 0; + ret = loadLabelName(LABEL_NALE_TXT_PATH, labels); + if (ret < 0) + { + return -1; + } + + init = 0; + } + memset(group, 0, sizeof(detect_result_group_t)); + + std::vector filterBoxes; + std::vector boxesScore; + std::vector classId; + int validCount = 0; + int stride = 0; + int grid_h = 0; + int grid_w = 0; + int* anchors; + for (int i=0; iout_nodes; i++){ + stride = m->strides[i]; + grid_h = m->height/ stride; + grid_w = m->width/ stride; + anchors = &(m->anchors[i*2*m->anchor_per_branch]); + // printf("post process parse\n"); + if (m->post_type == U8){ + validCount = validCount + process_u8((uint8_t*)rk_outputs[i].buf, anchors, m->anchor_per_branch, grid_h, grid_w, m->height, m->width, stride, + filterBoxes, boxesScore, classId, CONF_THRESHOLD, m->out_attr[i].zp, m->out_attr[i].scale, m->m_type); + } + else { + validCount = validCount + process_fp((float*)rk_outputs[i].buf, anchors, m->anchor_per_branch, grid_h, grid_w, m->height, m->width, stride, + filterBoxes, boxesScore, classId, CONF_THRESHOLD, m->m_type); + } + } + + // no object detect + if (validCount <= 0) + { + return 0; + } + + std::vector indexArray; + for (int i = 0; i < validCount; ++i) + { + indexArray.push_back(i); + } + + quick_sort_indice_inverse(boxesScore, 0, validCount - 1, indexArray); + + if (m->m_type == YOLOV5 || m->m_type == YOLOV7){ + nms(validCount, filterBoxes, classId, indexArray, NMS_THRESHOLD, false); + } + else if (m->m_type == YOLOX) + { + nms(validCount, filterBoxes, classId, indexArray, NMS_THRESHOLD, true); + } + + + int last_count = 0; + group->count = 0; + /* box valid detect target */ + for (int i = 0; i < validCount; ++i) + { + + if (indexArray[i] == -1 || boxesScore[i] < CONF_THRESHOLD || last_count >= OBJ_NUMB_MAX_SIZE) + { + continue; + } + int n = indexArray[i]; + + float x1 = filterBoxes[n * 4 + 0]; + float y1 = filterBoxes[n * 4 + 1]; + float x2 = x1 + filterBoxes[n * 4 + 2]; + float y2 = y1 + filterBoxes[n * 4 + 3]; + int id = classId[n]; + + group->results[last_count].box.left = (int)((clamp(x1, 0, lb->target_width) - lb->w_pad) / lb->resize_scale); + group->results[last_count].box.top = (int)((clamp(y1, 0, lb->target_height) - lb->h_pad) / lb->resize_scale); + group->results[last_count].box.right = (int)((clamp(x2, 0, lb->target_width) - lb->w_pad) / lb->resize_scale); + group->results[last_count].box.bottom = (int)((clamp(y2, 0, lb->target_height) - lb->h_pad) / lb->resize_scale); + group->results[last_count].prop = boxesScore[i]; + group->results[last_count].class_index = id; + char *label = labels[id]; + strncpy(group->results[last_count].name, label, OBJ_NAME_MAX_SIZE); + + // printf("result %2d: (%4d, %4d, %4d, %4d), %s\n", i, group->results[last_count].box.left, group->results[last_count].box.top, + // group->results[last_count].box.right, group->results[last_count].box.bottom, label); + last_count++; + } + group->count = last_count; + + return 0; +} + + +int compute_letter_box(LETTER_BOX* lb){ + lb->img_wh_ratio = (float)lb->in_width/ (float)lb->in_height; + lb->target_wh_ratio = (float)lb->target_width/ (float)lb->target_height; + + if (lb->img_wh_ratio >= lb->target_wh_ratio){ + //pad height dim + lb->resize_scale = (float)lb->target_width / (float)lb->in_width; + lb->resize_width = lb->target_width; + lb->resize_height = (int)((float)lb->in_height * lb->resize_scale); + lb->w_pad = 0; + lb->h_pad = (lb->target_height - lb->resize_height) / 2; + } + else{ + //pad width dim + lb->resize_scale = (float)lb->target_height / (float)lb->in_height; + lb->resize_width = (int)((float)lb->in_width * lb->resize_scale); + lb->resize_height = lb->target_height; + lb->w_pad = (lb->target_width - lb->resize_width) / 2; + lb->h_pad = 0; + } + return 0; +} \ No newline at end of file diff --git a/time_sync/readme.md b/time_sync/readme.md new file mode 100644 index 0000000..f454d40 --- /dev/null +++ b/time_sync/readme.md @@ -0,0 +1,2 @@ +用于开机后的时间同步 +编译:/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -o time_sync time_sync.cpp -lpthread \ No newline at end of file diff --git a/time_sync/time_sync b/time_sync/time_sync new file mode 100644 index 0000000..45f3bda Binary files /dev/null and b/time_sync/time_sync differ diff --git a/time_sync/time_sync.cpp b/time_sync/time_sync.cpp new file mode 100644 index 0000000..cde8c16 --- /dev/null +++ b/time_sync/time_sync.cpp @@ -0,0 +1,217 @@ +/* +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ -o time_sync time_sync.cpp -lpthread +*/ + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// int main() { +// // 创建套接字 +// int socketId = socket(AF_INET, SOCK_STREAM, 0); +// if (socketId == -1) { +// std::cerr << "无法创建套接字" << std::endl; +// return 1; +// } + +// // 获取时间服务器的IP地址 +// struct hostent* server = gethostbyname("edu.ntp.org.cn"); +// if (server == nullptr) { +// std::cerr << "无法解析时间服务器" << std::endl; +// return 1; +// } + +// // 配置服务器地址 +// struct sockaddr_in serverAddress{}; +// serverAddress.sin_family = AF_INET; +// serverAddress.sin_port = htons(13); +// std::memcpy(&serverAddress.sin_addr.s_addr, server->h_addr, server->h_length); + +// // 连接到时间服务器 +// if (connect(socketId, (struct sockaddr*) &serverAddress, sizeof(serverAddress)) == -1) { +// std::cerr << "无法连接到时间服务器" << std::endl; +// return 1; +// } + +// // 从服务器接收时间 +// char buffer[128]; +// ssize_t bytesRead = recv(socketId, buffer, sizeof(buffer) - 1, 0); +// if (bytesRead == -1) { +// std::cerr << "无法接收数据" << std::endl; +// return 1; +// } +// buffer[bytesRead] = '\0'; + +// // 输出接收到的时间字符串 +// std::cout << "接收到的时间字符串:" << buffer << std::endl; + +// // // 解析时间字符串 +// // std::tm timeInfo{}; +// // std::istringstream iss(buffer); +// // int skipFields; +// // if (!(iss >> skipFields >> std::get_time(&timeInfo, "%d-%m-%y %H:%M:%S"))) { +// // std::cerr << "无法解析时间" << std::endl; +// // return 1; +// // } +// // 解析时间字符串 +// int year, month, day, hour, minute, second; +// if (sscanf(buffer, "%*d %d-%d-%d %d:%d:%d", +// &year, &month, &day, &hour, &minute, &second) != 6) { +// std::cerr << "无法解析时间" << std::endl; +// return 1; +// } + +// // // 从timeInfo结构中获取时间值 +// // int year = timeInfo.tm_year + 1900; +// // int month = timeInfo.tm_mon + 1; +// // int day = timeInfo.tm_mday; +// // int hour = timeInfo.tm_hour; +// // int minute = timeInfo.tm_min; +// // int second = timeInfo.tm_sec; + + +// // 构建设置系统时间的命令 +// char dateCmd[128]; +// snprintf(dateCmd, sizeof(dateCmd), "date -s \"%04d-%d-%d %02d:%02d\"", +// year+2000, month, day, hour, minute); +// std::cout << "dateCmd: " << dateCmd << std::endl; +// // 设置系统时间 +// if (system(dateCmd) == -1) { +// std::cerr << "无法设置系统时间" << std::endl; +// return 1; +// } + +// std::cout << "系统时间已更新" << std::endl; + +// // 关闭套接字 +// close(socketId); + +// return 0; +// } + +#include +#include +#include +#include +#include +#include +#include +#include + +int main() { + while(true) { + std::cerr << "开始时间矫正!" << std::endl; + // 创建套接字 + int socketId = socket(AF_INET, SOCK_STREAM, 0); + if (socketId == -1) { + std::cerr << "无法创建套接字" << std::endl; + sleep(5); + continue; + } + + // 获取时间服务器的IP地址 + struct hostent* server = gethostbyname("time.nist.gov"); //微软 + // struct hostent* server = gethostbyname("time1.cloud.tencent.com"); + if (server == nullptr) { + std::cerr << "无法解析时间服务器" << std::endl; + sleep(5); + continue; + } + + // 配置服务器地址 + struct sockaddr_in serverAddress{}; + serverAddress.sin_family = AF_INET; + serverAddress.sin_port = htons(13); + // serverAddress.sin_port = htons(123); + std::memcpy(&serverAddress.sin_addr.s_addr, server->h_addr, server->h_length); + + // 连接到时间服务器 + if (connect(socketId, (struct sockaddr*) &serverAddress, sizeof(serverAddress)) == -1) { + std::cerr << "无法连接到时间服务器" << std::endl; + perror("连接时间服务器失败"); + sleep(5); + continue; + } + + // 从服务器接收时间 + char buffer[128]; + ssize_t bytesRead = recv(socketId, buffer, sizeof(buffer) - 1, 0); + if (bytesRead == -1) { + std::cerr << "无法接收数据" << std::endl; + sleep(5); + continue; + } + buffer[bytesRead] = '\0'; + + // 输出接收到的时间字符串 + std::cout << "接收到的时间字符串:" << buffer << std::endl; + + // 解析时间字符串 + int year, month, day, hour, minute, second; + if (sscanf(buffer, "%*d %d-%d-%d %d:%d:%d", + &year, &month, &day, &hour, &minute, &second) != 6) { + std::cerr << "无法解析时间" << std::endl; + sleep(5); + continue; + } + std::cout << "解析后的时间信息:" << std::endl; + std::cout << "年份:" << year << std::endl; + std::cout << "月份:" << month << std::endl; + std::cout << "日期:" << day << std::endl; + std::cout << "小时:" << hour << std::endl; + std::cout << "分钟:" << minute << std::endl; + std::cout << "秒钟:" << second << std::endl; + + // 关闭套接字 + close(socketId); + + // 将时间转换为中国时区 + std::tm timeInfo{}; + timeInfo.tm_year = year +100; + timeInfo.tm_mon = month - 1; + timeInfo.tm_mday = day; + timeInfo.tm_hour = hour; + timeInfo.tm_min = minute; + timeInfo.tm_sec = second; + + // std::time_t utcTime = std::mktime(&timeInfo); + + // // 转换为中国时区 + // std::tm* localTime = std::gmtime(&utcTime); + // localTime->tm_hour += 8; // 添加8小时,表示中国时区偏移 + + // 转换为time_t类型 + std::time_t utcTime = std::mktime(&timeInfo); + + // 转换为中国时区 + const std::time_t chinaTime = utcTime + 8 * 3600; // 添加8小时的偏移量,表示中国时区偏移 + + // 转换为本地时间 + std::tm* localTime = std::localtime(&chinaTime); + + // 构建设置系统时间的命令 + char dateCmd[128]; + snprintf(dateCmd, sizeof(dateCmd), "date -s \"%04d-%02d-%02d %02d:%02d:%02d\"", + localTime->tm_year +1900, localTime->tm_mon + 1, localTime->tm_mday, + localTime->tm_hour, localTime->tm_min, localTime->tm_sec); + + std::cout << "dateCmd: " << dateCmd << std::endl; + + // 设置系统时间 + if (system(dateCmd) == -1) { + std::cerr << "无法设置系统时间" << std::endl; + sleep(5); + continue; + } + + std::cout << "系统时间已更新" << std::endl; + break; + } + + return 0; +} \ No newline at end of file diff --git a/update_engine/recovery/update_engine/CMakeLists.txt b/update_engine/recovery/update_engine/CMakeLists.txt new file mode 100644 index 0000000..1d7155b --- /dev/null +++ b/update_engine/recovery/update_engine/CMakeLists.txt @@ -0,0 +1,71 @@ +# @author Liang Huanyan +# @email lianghuanyan@alientek.com +# http://www.openedv.com/forum.php + +cmake_minimum_required(VERSION 3.8) +message(STATUS "cmake version ${CMAKE_VERSION}") + +set(TOOLCHAIN_DIR /opt/atk-dlrv1126-toolchain) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-g++) +set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-gcc) +set(SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot/usr/include) +set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot) + +set(CMAKE_CXX_STANDARD 11) +add_definitions(-g -O0 -ggdb -gdwarf -funwind-tables -rdynamic) +add_definitions(-Wno-write-strings -Wno-return-type) + + + + +link_directories(include lib) + + +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIR}) +message("CURL_LIBRARIES: ${CURL_LIBRARIES}") +message("CURL_INCLUDE_DIR: ${CURL_INCLUDE_DIR}") +find_package(OpenSSL REQUIRED) +find_library(JSONC_LIBRARY NAMES json-c) +message("JSONC_LIBRARY: ${JSONC_LIBRARY}") + +include_directories(${SYSROOT}) +include_directories(../) +include_directories(.) + + + +add_executable(update + crc.cpp + download.cpp + flash_image.cpp + log.cpp + main.cpp + md5sum.cpp + rkboot.cpp + rkbootloader.cpp + rkimage.cpp + rktools.cpp + update.cpp + ../mtdutils/mounts.c + ../mtdutils/mtdutils.c + ../mtdutils/rk29.c + + # ../default_recovery_ui.c + # ../rktools.c + # ../roots.c + # ../bootloader.c + # ../safe_iop.c + # ../strlcpy.c + # ../strlcat.c + # ../rkupdate.c + # ../sdboot.c + # ../mtdutils/mounts.c + # ../mtdutils/mtdutils.c + # ../mtdutils/rk29.c + # ../minzip/DirUtil.c + + # ../noui.c + + ) +target_link_libraries(update pthread OpenSSL::Crypto OpenSSL::SSL ${CURL_LIBRARIES} ${JSONC_LIBRARY}) diff --git a/update_engine/recovery/update_engine/README.md b/update_engine/recovery/update_engine/README.md new file mode 100644 index 0000000..8650652 --- /dev/null +++ b/update_engine/recovery/update_engine/README.md @@ -0,0 +1,5 @@ +本工程项目用于1126开发板demo分区的ota升级,由官方的external/recovery/update_engine代码修改而来 +(自定义了升级分区与ota方法,可自行对比) + +修改后使用命令请参考 开机脚本receives.sh +原始update_engined的使用命令 请参考瑞芯微官方资料:Rockchip_Developer_Guide_Linux_Upgrade_CN.pdf \ No newline at end of file diff --git a/update_engine/recovery/update_engine/S99_bootcontrol b/update_engine/recovery/update_engine/S99_bootcontrol new file mode 100644 index 0000000..51fd3a3 --- /dev/null +++ b/update_engine/recovery/update_engine/S99_bootcontrol @@ -0,0 +1,13 @@ +case "$1" in + start) + /usr/bin/updateEngine --misc=now + ;; + stop) + printf "stop finished\n" + ;; + *) + echo "Usage: $0 {start|stop}" + exit 1 + ;; +esac +exit 0 diff --git a/update_engine/recovery/update_engine/build/CMakeCache.txt b/update_engine/recovery/update_engine/build/CMakeCache.txt new file mode 100644 index 0000000..4b6104b --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeCache.txt @@ -0,0 +1,528 @@ +# This is the CMakeCache file. +# For build in directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build +# It was generated by CMake: /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/pkgRedirects + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//The directory containing a CMake configuration file for CURL. +CURL_DIR:PATH=CURL_DIR-NOTFOUND + +//Path to a file. +CURL_INCLUDE_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +//Path to a library. +CURL_LIBRARY_DEBUG:FILEPATH=CURL_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +CURL_LIBRARY_RELEASE:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so + +//The directory containing a CMake configuration file for JSONCPP. +JSONCPP_DIR:PATH=JSONCPP_DIR-NOTFOUND + +//The directory containing a CMake configuration file for JSONC. +JSONC_DIR:PATH=JSONC_DIR-NOTFOUND + +//Path to a library. +JSONC_LIBRARY:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libjson-c.so + +//Path to a library. +OPENSSL_CRYPTO_LIBRARY:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcrypto.so + +//Path to a file. +OPENSSL_INCLUDE_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +//Path to a library. +OPENSSL_SSL_LIBRARY:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libssl.so + +//Arguments to supply to pkg-config +PKG_CONFIG_ARGN:STRING= + +//pkg-config executable +PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build + +//Value Computed by CMake +Project_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine + +//The directory containing a CMake configuration file for json-c. +json-c_DIR:PATH=json-c_DIR-NOTFOUND + +//The directory containing a CMake configuration file for jsoncpp. +jsoncpp_DIR:PATH=jsoncpp_DIR-NOTFOUND + +//Path to a library. +pkgcfg_lib_PC_CURL_curl:FILEPATH=/usr/lib/x86_64-linux-gnu/libcurl.so + +//Path to a library. +pkgcfg_lib__OPENSSL_crypto:FILEPATH=/usr/lib/x86_64-linux-gnu/libcrypto.so + +//Path to a library. +pkgcfg_lib__OPENSSL_ssl:FILEPATH=/usr/lib/x86_64-linux-gnu/libssl.so + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=26 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=0 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_DIR +CURL_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_INCLUDE_DIR +CURL_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_DEBUG +CURL_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_RELEASE +CURL_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//Details about finding CURL +FIND_PACKAGE_MESSAGE_DETAILS_CURL:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so][/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include][c ][v7.75.0()] +//Details about finding OpenSSL +FIND_PACKAGE_MESSAGE_DETAILS_OpenSSL:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcrypto.so][/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include][c ][v1.1.1h()] +//ADVANCED property for variable: OPENSSL_CRYPTO_LIBRARY +OPENSSL_CRYPTO_LIBRARY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: OPENSSL_INCLUDE_DIR +OPENSSL_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: OPENSSL_SSL_LIBRARY +OPENSSL_SSL_LIBRARY-ADVANCED:INTERNAL=1 +PC_CURL_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_CFLAGS_I:INTERNAL= +PC_CURL_CFLAGS_OTHER:INTERNAL= +PC_CURL_FOUND:INTERNAL=1 +PC_CURL_INCLUDEDIR:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lcurl +PC_CURL_LDFLAGS_OTHER:INTERNAL= +PC_CURL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBRARIES:INTERNAL=curl +PC_CURL_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBS:INTERNAL= +PC_CURL_LIBS_L:INTERNAL= +PC_CURL_LIBS_OTHER:INTERNAL= +PC_CURL_LIBS_PATHS:INTERNAL= +PC_CURL_MODULE_NAME:INTERNAL=libcurl +PC_CURL_PREFIX:INTERNAL=/usr +PC_CURL_STATIC_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_CFLAGS_I:INTERNAL= +PC_CURL_STATIC_CFLAGS_OTHER:INTERNAL= +PC_CURL_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-L/usr/lib/x86_64-linux-gnu/mit-krb5;-lcurl;-lnghttp2;-lidn2;-lrtmp;-lssh;-lpsl;-lssl;-lcrypto;-lssl;-lcrypto;-Wl,-Bsymbolic-functions;-Wl,-z,relro;-lgssapi_krb5;-lkrb5;-lk5crypto;-lcom_err;-llber;-lldap;-llber;-lbrotlidec;-lz +PC_CURL_STATIC_LDFLAGS_OTHER:INTERNAL=-Wl,-Bsymbolic-functions;-Wl,-z,relro +PC_CURL_STATIC_LIBDIR:INTERNAL= +PC_CURL_STATIC_LIBRARIES:INTERNAL=curl;nghttp2;idn2;rtmp;ssh;psl;ssl;crypto;ssl;crypto;gssapi_krb5;krb5;k5crypto;com_err;lber;ldap;lber;brotlidec;z +PC_CURL_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu;/usr/lib/x86_64-linux-gnu/mit-krb5 +PC_CURL_STATIC_LIBS:INTERNAL= +PC_CURL_STATIC_LIBS_L:INTERNAL= +PC_CURL_STATIC_LIBS_OTHER:INTERNAL= +PC_CURL_STATIC_LIBS_PATHS:INTERNAL= +PC_CURL_VERSION:INTERNAL=7.68.0 +PC_CURL_libcurl_INCLUDEDIR:INTERNAL= +PC_CURL_libcurl_LIBDIR:INTERNAL= +PC_CURL_libcurl_PREFIX:INTERNAL= +PC_CURL_libcurl_VERSION:INTERNAL= +//ADVANCED property for variable: PKG_CONFIG_ARGN +PKG_CONFIG_ARGN-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE +PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1 +//linker supports push/pop state +_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED:INTERNAL=TRUE +_OPENSSL_CFLAGS:INTERNAL= +_OPENSSL_CFLAGS_I:INTERNAL= +_OPENSSL_CFLAGS_OTHER:INTERNAL= +_OPENSSL_FOUND:INTERNAL=1 +_OPENSSL_INCLUDEDIR:INTERNAL=/usr/include +_OPENSSL_INCLUDE_DIRS:INTERNAL= +_OPENSSL_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lssl;-lcrypto +_OPENSSL_LDFLAGS_OTHER:INTERNAL= +_OPENSSL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu +_OPENSSL_LIBRARIES:INTERNAL=ssl;crypto +_OPENSSL_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu +_OPENSSL_LIBS:INTERNAL= +_OPENSSL_LIBS_L:INTERNAL= +_OPENSSL_LIBS_OTHER:INTERNAL= +_OPENSSL_LIBS_PATHS:INTERNAL= +_OPENSSL_MODULE_NAME:INTERNAL=openssl +_OPENSSL_PREFIX:INTERNAL=/usr +_OPENSSL_STATIC_CFLAGS:INTERNAL= +_OPENSSL_STATIC_CFLAGS_I:INTERNAL= +_OPENSSL_STATIC_CFLAGS_OTHER:INTERNAL= +_OPENSSL_STATIC_INCLUDE_DIRS:INTERNAL= +_OPENSSL_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lssl;-lcrypto;-ldl;-pthread +_OPENSSL_STATIC_LDFLAGS_OTHER:INTERNAL=-pthread +_OPENSSL_STATIC_LIBDIR:INTERNAL= +_OPENSSL_STATIC_LIBRARIES:INTERNAL=ssl;crypto;dl +_OPENSSL_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu +_OPENSSL_STATIC_LIBS:INTERNAL= +_OPENSSL_STATIC_LIBS_L:INTERNAL= +_OPENSSL_STATIC_LIBS_OTHER:INTERNAL= +_OPENSSL_STATIC_LIBS_PATHS:INTERNAL= +_OPENSSL_VERSION:INTERNAL=1.1.1f +_OPENSSL_openssl_INCLUDEDIR:INTERNAL= +_OPENSSL_openssl_LIBDIR:INTERNAL= +_OPENSSL_openssl_PREFIX:INTERNAL= +_OPENSSL_openssl_VERSION:INTERNAL= +__pkg_config_arguments_PC_CURL:INTERNAL=QUIET;libcurl +__pkg_config_arguments__OPENSSL:INTERNAL=QUIET;openssl +__pkg_config_checked_PC_CURL:INTERNAL=1 +__pkg_config_checked__OPENSSL:INTERNAL=1 +//ADVANCED property for variable: pkgcfg_lib_PC_CURL_curl +pkgcfg_lib_PC_CURL_curl-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: pkgcfg_lib__OPENSSL_crypto +pkgcfg_lib__OPENSSL_crypto-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: pkgcfg_lib__OPENSSL_ssl +pkgcfg_lib__OPENSSL_ssl-ADVANCED:INTERNAL=1 +prefix_result:INTERNAL=SSL;IPv6;UnixSockets;libz;brotli;AsynchDNS;IDN;GSS-API;PSL;SPNEGO;Kerberos;NTLM;NTLM_WB;TLS-SRP;HTTP2;HTTPS-proxy + diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake new file mode 100644 index 0000000..db12033 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "9.4.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..9950db3 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "9.4.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000..d10d50b Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin new file mode 100644 index 0000000..61bb758 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeSystem.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeSystem.cmake new file mode 100644 index 0000000..f1cb793 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-5.15.0-84-generic") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "5.15.0-84-generic") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-5.15.0-84-generic") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "5.15.0-84-generic") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..88155ff --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,866 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/a.out b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/a.out new file mode 100644 index 0000000..6dc55f1 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/a.out differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..746b167 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,855 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out new file mode 100644 index 0000000..3198cb5 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/CMakeConfigureLog.yaml b/update_engine/recovery/update_engine/build/CMakeFiles/CMakeConfigureLog.yaml new file mode 100644 index 0000000..f37507c --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/CMakeConfigureLog.yaml @@ -0,0 +1,529 @@ + +--- +events: + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineSystem.cmake:204 (message)" + - "CMakeLists.txt" + message: | + The system is: Linux - 5.15.0-84-generic - x86_64 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCCompiler.cmake:123 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt" + message: | + Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. + Compiler: /usr/bin/cc + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + + The C compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdC/a.out + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt" + message: | + Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. + Compiler: /usr/bin/c++ + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + + The CXX compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + checks: + - "Detecting C compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn" + cmakeVariables: + CMAKE_C_FLAGS: "" + buildResult: + variable: "CMAKE_C_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_3d391/fast && /usr/bin/make -f CMakeFiles/cmTC_3d391.dir/build.make CMakeFiles/cmTC_3d391.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn' + Building C object CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o + /usr/bin/cc -v -o CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c + Using built-in specs. + COLLECT_GCC=/usr/bin/cc + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccY1fJj3.s + GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/lib/gcc/x86_64-linux-gnu/9/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 01da938ff5dc2163489aa33cb3b747a7 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o /tmp/ccY1fJj3.s + GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34 + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + Linking C executable cmTC_3d391 + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_3d391.dir/link.txt --verbose=1 + /usr/bin/cc -v -rdynamic CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -o cmTC_3d391 + Using built-in specs. + COLLECT_GCC=/usr/bin/cc + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_3d391' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccqmDJbx.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_3d391 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_3d391' '-mtune=generic' '-march=x86-64' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed C implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-linux-gnu/9/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed C implicit link information: + link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_3d391/fast && /usr/bin/make -f CMakeFiles/cmTC_3d391.dir/build.make CMakeFiles/cmTC_3d391.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-bhzyHn'] + ignore line: [Building C object CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccY1fJj3.s] + ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 01da938ff5dc2163489aa33cb3b747a7] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o /tmp/ccY1fJj3.s] + ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking C executable cmTC_3d391] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_3d391.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -o cmTC_3d391 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_3d391' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccqmDJbx.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_3d391 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccqmDJbx.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_3d391] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] + arg [CMakeFiles/cmTC_3d391.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + checks: + - "Detecting CXX compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq" + cmakeVariables: + CMAKE_CXX_FLAGS: "" + buildResult: + variable: "CMAKE_CXX_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_f47fc/fast && /usr/bin/make -f CMakeFiles/cmTC_f47fc.dir/build.make CMakeFiles/cmTC_f47fc.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq' + Building CXX object CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o + /usr/bin/c++ -v -o CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/cchhSEKe.s + GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9" + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/include/c++/9 + /usr/include/x86_64-linux-gnu/c++/9 + /usr/include/c++/9/backward + /usr/lib/gcc/x86_64-linux-gnu/9/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 3d1eba838554fa2348dba760e4770469 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o /tmp/cchhSEKe.s + GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34 + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + Linking CXX executable cmTC_f47fc + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_f47fc.dir/link.txt --verbose=1 + /usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_f47fc + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_f47fc' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccUsWXOE.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_f47fc /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_f47fc' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed CXX implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/include/c++/9] + add: [/usr/include/x86_64-linux-gnu/c++/9] + add: [/usr/include/c++/9/backward] + add: [/usr/lib/gcc/x86_64-linux-gnu/9/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/include/c++/9] ==> [/usr/include/c++/9] + collapse include dir [/usr/include/x86_64-linux-gnu/c++/9] ==> [/usr/include/x86_64-linux-gnu/c++/9] + collapse include dir [/usr/include/c++/9/backward] ==> [/usr/include/c++/9/backward] + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt" + message: | + Parsed CXX implicit link information: + link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_f47fc/fast && /usr/bin/make -f CMakeFiles/cmTC_f47fc.dir/build.make CMakeFiles/cmTC_f47fc.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/CMakeScratch/TryCompile-TIUDiq'] + ignore line: [Building CXX object CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/cchhSEKe.s] + ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/include/c++/9] + ignore line: [ /usr/include/x86_64-linux-gnu/c++/9] + ignore line: [ /usr/include/c++/9/backward] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 3d1eba838554fa2348dba760e4770469] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o /tmp/cchhSEKe.s] + ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking CXX executable cmTC_f47fc] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_f47fc.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_f47fc ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_f47fc' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccUsWXOE.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_f47fc /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccUsWXOE.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_f47fc] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] + arg [CMakeFiles/cmTC_f47fc.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + +... diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/CMakeDirectoryInformation.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..0073ba6 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/Makefile.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..692dd36 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,53 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCommonLanguageInclude.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeGenericSystem.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeInitializeConfigs.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeLanguageInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeSystemSpecificInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeSystemSpecificInitialize.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU-C.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU-CXX.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindCURL.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindOpenSSL.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageHandleStandardArgs.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageMessage.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPkgConfig.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU-C.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU-CXX.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/UnixPaths.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/SelectLibraryConfigurations.cmake" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/CMakeLists.txt" + "CMakeFiles/3.26.0/CMakeCCompiler.cmake" + "CMakeFiles/3.26.0/CMakeCXXCompiler.cmake" + "CMakeFiles/3.26.0/CMakeSystem.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/update.dir/DependInfo.cmake" + ) diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/Makefile2 b/update_engine/recovery/update_engine/build/CMakeFiles/Makefile2 new file mode 100644 index 0000000..5e0c990 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/Makefile2 @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/update.dir/all +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/update.dir/clean +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/update.dir + +# All Build rule for target. +CMakeFiles/update.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 "Built target update" +.PHONY : CMakeFiles/update.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/update.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles 15 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/update.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles 0 +.PHONY : CMakeFiles/update.dir/rule + +# Convenience name for target. +update: CMakeFiles/update.dir/rule +.PHONY : update + +# clean rule for target. +CMakeFiles/update.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/clean +.PHONY : CMakeFiles/update.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/TargetDirectories.txt b/update_engine/recovery/update_engine/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..6f48306 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/update.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/edit_cache.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/rebuild_cache.dir diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/cmake.check_cache b/update_engine/recovery/update_engine/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/progress.marks b/update_engine/recovery/update_engine/build/CMakeFiles/progress.marks new file mode 100644 index 0000000..60d3b2f --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/progress.marks @@ -0,0 +1 @@ +15 diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/DependInfo.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/DependInfo.cmake new file mode 100644 index 0000000..74f985d --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/DependInfo.cmake @@ -0,0 +1,32 @@ + +# Consider dependencies only in project. +set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) + +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + ) + +# The set of dependency files which are needed: +set(CMAKE_DEPENDS_DEPENDENCY_FILES + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c" "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o" "gcc" "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c" "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o" "gcc" "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c" "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o" "gcc" "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp" "CMakeFiles/update.dir/crc.cpp.o" "gcc" "CMakeFiles/update.dir/crc.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp" "CMakeFiles/update.dir/download.cpp.o" "gcc" "CMakeFiles/update.dir/download.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp" "CMakeFiles/update.dir/flash_image.cpp.o" "gcc" "CMakeFiles/update.dir/flash_image.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp" "CMakeFiles/update.dir/log.cpp.o" "gcc" "CMakeFiles/update.dir/log.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp" "CMakeFiles/update.dir/main.cpp.o" "gcc" "CMakeFiles/update.dir/main.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp" "CMakeFiles/update.dir/md5sum.cpp.o" "gcc" "CMakeFiles/update.dir/md5sum.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp" "CMakeFiles/update.dir/rkboot.cpp.o" "gcc" "CMakeFiles/update.dir/rkboot.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp" "CMakeFiles/update.dir/rkbootloader.cpp.o" "gcc" "CMakeFiles/update.dir/rkbootloader.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp" "CMakeFiles/update.dir/rkimage.cpp.o" "gcc" "CMakeFiles/update.dir/rkimage.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp" "CMakeFiles/update.dir/rktools.cpp.o" "gcc" "CMakeFiles/update.dir/rktools.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp" "CMakeFiles/update.dir/update.cpp.o" "gcc" "CMakeFiles/update.dir/update.cpp.o.d" + ) + +# Targets to which this target links which contain Fortran sources. +set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/build.make b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/build.make new file mode 100644 index 0000000..ca4a6ed --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/build.make @@ -0,0 +1,323 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build + +# Include any dependencies generated for this target. +include CMakeFiles/update.dir/depend.make +# Include any dependencies generated by the compiler for this target. +include CMakeFiles/update.dir/compiler_depend.make + +# Include the progress variables for this target. +include CMakeFiles/update.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/update.dir/flags.make + +CMakeFiles/update.dir/crc.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/crc.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp +CMakeFiles/update.dir/crc.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/update.dir/crc.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/crc.cpp.o -MF CMakeFiles/update.dir/crc.cpp.o.d -o CMakeFiles/update.dir/crc.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp + +CMakeFiles/update.dir/crc.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/crc.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp > CMakeFiles/update.dir/crc.cpp.i + +CMakeFiles/update.dir/crc.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/crc.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp -o CMakeFiles/update.dir/crc.cpp.s + +CMakeFiles/update.dir/download.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/download.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp +CMakeFiles/update.dir/download.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object CMakeFiles/update.dir/download.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/download.cpp.o -MF CMakeFiles/update.dir/download.cpp.o.d -o CMakeFiles/update.dir/download.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp + +CMakeFiles/update.dir/download.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/download.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp > CMakeFiles/update.dir/download.cpp.i + +CMakeFiles/update.dir/download.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/download.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp -o CMakeFiles/update.dir/download.cpp.s + +CMakeFiles/update.dir/flash_image.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/flash_image.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp +CMakeFiles/update.dir/flash_image.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object CMakeFiles/update.dir/flash_image.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/flash_image.cpp.o -MF CMakeFiles/update.dir/flash_image.cpp.o.d -o CMakeFiles/update.dir/flash_image.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp + +CMakeFiles/update.dir/flash_image.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/flash_image.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp > CMakeFiles/update.dir/flash_image.cpp.i + +CMakeFiles/update.dir/flash_image.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/flash_image.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp -o CMakeFiles/update.dir/flash_image.cpp.s + +CMakeFiles/update.dir/log.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/log.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp +CMakeFiles/update.dir/log.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object CMakeFiles/update.dir/log.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/log.cpp.o -MF CMakeFiles/update.dir/log.cpp.o.d -o CMakeFiles/update.dir/log.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp + +CMakeFiles/update.dir/log.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/log.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp > CMakeFiles/update.dir/log.cpp.i + +CMakeFiles/update.dir/log.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/log.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp -o CMakeFiles/update.dir/log.cpp.s + +CMakeFiles/update.dir/main.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/main.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp +CMakeFiles/update.dir/main.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object CMakeFiles/update.dir/main.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/main.cpp.o -MF CMakeFiles/update.dir/main.cpp.o.d -o CMakeFiles/update.dir/main.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp + +CMakeFiles/update.dir/main.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/main.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp > CMakeFiles/update.dir/main.cpp.i + +CMakeFiles/update.dir/main.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/main.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp -o CMakeFiles/update.dir/main.cpp.s + +CMakeFiles/update.dir/md5sum.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/md5sum.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp +CMakeFiles/update.dir/md5sum.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building CXX object CMakeFiles/update.dir/md5sum.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/md5sum.cpp.o -MF CMakeFiles/update.dir/md5sum.cpp.o.d -o CMakeFiles/update.dir/md5sum.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp + +CMakeFiles/update.dir/md5sum.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/md5sum.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp > CMakeFiles/update.dir/md5sum.cpp.i + +CMakeFiles/update.dir/md5sum.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/md5sum.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp -o CMakeFiles/update.dir/md5sum.cpp.s + +CMakeFiles/update.dir/rkboot.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/rkboot.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp +CMakeFiles/update.dir/rkboot.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Building CXX object CMakeFiles/update.dir/rkboot.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/rkboot.cpp.o -MF CMakeFiles/update.dir/rkboot.cpp.o.d -o CMakeFiles/update.dir/rkboot.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp + +CMakeFiles/update.dir/rkboot.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/rkboot.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp > CMakeFiles/update.dir/rkboot.cpp.i + +CMakeFiles/update.dir/rkboot.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/rkboot.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp -o CMakeFiles/update.dir/rkboot.cpp.s + +CMakeFiles/update.dir/rkbootloader.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/rkbootloader.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp +CMakeFiles/update.dir/rkbootloader.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building CXX object CMakeFiles/update.dir/rkbootloader.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/rkbootloader.cpp.o -MF CMakeFiles/update.dir/rkbootloader.cpp.o.d -o CMakeFiles/update.dir/rkbootloader.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp + +CMakeFiles/update.dir/rkbootloader.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/rkbootloader.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp > CMakeFiles/update.dir/rkbootloader.cpp.i + +CMakeFiles/update.dir/rkbootloader.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/rkbootloader.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp -o CMakeFiles/update.dir/rkbootloader.cpp.s + +CMakeFiles/update.dir/rkimage.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/rkimage.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp +CMakeFiles/update.dir/rkimage.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_9) "Building CXX object CMakeFiles/update.dir/rkimage.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/rkimage.cpp.o -MF CMakeFiles/update.dir/rkimage.cpp.o.d -o CMakeFiles/update.dir/rkimage.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp + +CMakeFiles/update.dir/rkimage.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/rkimage.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp > CMakeFiles/update.dir/rkimage.cpp.i + +CMakeFiles/update.dir/rkimage.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/rkimage.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp -o CMakeFiles/update.dir/rkimage.cpp.s + +CMakeFiles/update.dir/rktools.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/rktools.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp +CMakeFiles/update.dir/rktools.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_10) "Building CXX object CMakeFiles/update.dir/rktools.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/rktools.cpp.o -MF CMakeFiles/update.dir/rktools.cpp.o.d -o CMakeFiles/update.dir/rktools.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp + +CMakeFiles/update.dir/rktools.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/rktools.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp > CMakeFiles/update.dir/rktools.cpp.i + +CMakeFiles/update.dir/rktools.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/rktools.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp -o CMakeFiles/update.dir/rktools.cpp.s + +CMakeFiles/update.dir/update.cpp.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/update.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp +CMakeFiles/update.dir/update.cpp.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_11) "Building CXX object CMakeFiles/update.dir/update.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/update.dir/update.cpp.o -MF CMakeFiles/update.dir/update.cpp.o.d -o CMakeFiles/update.dir/update.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp + +CMakeFiles/update.dir/update.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/update.dir/update.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp > CMakeFiles/update.dir/update.cpp.i + +CMakeFiles/update.dir/update.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/update.dir/update.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp -o CMakeFiles/update.dir/update.cpp.s + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_12) "Building C object CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o -MF CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o.d -o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c > CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c -o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_13) "Building C object CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o -MF CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o.d -o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c > CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c -o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o: CMakeFiles/update.dir/flags.make +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o: CMakeFiles/update.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_14) "Building C object CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o -MF CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o.d -o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c > CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c -o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s + +# Object files for target update +update_OBJECTS = \ +"CMakeFiles/update.dir/crc.cpp.o" \ +"CMakeFiles/update.dir/download.cpp.o" \ +"CMakeFiles/update.dir/flash_image.cpp.o" \ +"CMakeFiles/update.dir/log.cpp.o" \ +"CMakeFiles/update.dir/main.cpp.o" \ +"CMakeFiles/update.dir/md5sum.cpp.o" \ +"CMakeFiles/update.dir/rkboot.cpp.o" \ +"CMakeFiles/update.dir/rkbootloader.cpp.o" \ +"CMakeFiles/update.dir/rkimage.cpp.o" \ +"CMakeFiles/update.dir/rktools.cpp.o" \ +"CMakeFiles/update.dir/update.cpp.o" \ +"CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o" \ +"CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o" \ +"CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o" + +# External object files for target update +update_EXTERNAL_OBJECTS = + +update: CMakeFiles/update.dir/crc.cpp.o +update: CMakeFiles/update.dir/download.cpp.o +update: CMakeFiles/update.dir/flash_image.cpp.o +update: CMakeFiles/update.dir/log.cpp.o +update: CMakeFiles/update.dir/main.cpp.o +update: CMakeFiles/update.dir/md5sum.cpp.o +update: CMakeFiles/update.dir/rkboot.cpp.o +update: CMakeFiles/update.dir/rkbootloader.cpp.o +update: CMakeFiles/update.dir/rkimage.cpp.o +update: CMakeFiles/update.dir/rktools.cpp.o +update: CMakeFiles/update.dir/update.cpp.o +update: CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o +update: CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o +update: CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o +update: CMakeFiles/update.dir/build.make +update: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcrypto.so +update: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libssl.so +update: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so +update: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libjson-c.so +update: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcrypto.so +update: CMakeFiles/update.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_15) "Linking CXX executable update" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/update.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/update.dir/build: update +.PHONY : CMakeFiles/update.dir/build + +CMakeFiles/update.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/update.dir/cmake_clean.cmake +.PHONY : CMakeFiles/update.dir/clean + +CMakeFiles/update.dir/depend: + cd /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/update.dir/depend + diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/cmake_clean.cmake b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/cmake_clean.cmake new file mode 100644 index 0000000..ba446ab --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/cmake_clean.cmake @@ -0,0 +1,37 @@ +file(REMOVE_RECURSE + "CMakeFiles/update.dir/crc.cpp.o" + "CMakeFiles/update.dir/crc.cpp.o.d" + "CMakeFiles/update.dir/download.cpp.o" + "CMakeFiles/update.dir/download.cpp.o.d" + "CMakeFiles/update.dir/flash_image.cpp.o" + "CMakeFiles/update.dir/flash_image.cpp.o.d" + "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o" + "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o.d" + "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o" + "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o.d" + "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o" + "CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o.d" + "CMakeFiles/update.dir/log.cpp.o" + "CMakeFiles/update.dir/log.cpp.o.d" + "CMakeFiles/update.dir/main.cpp.o" + "CMakeFiles/update.dir/main.cpp.o.d" + "CMakeFiles/update.dir/md5sum.cpp.o" + "CMakeFiles/update.dir/md5sum.cpp.o.d" + "CMakeFiles/update.dir/rkboot.cpp.o" + "CMakeFiles/update.dir/rkboot.cpp.o.d" + "CMakeFiles/update.dir/rkbootloader.cpp.o" + "CMakeFiles/update.dir/rkbootloader.cpp.o.d" + "CMakeFiles/update.dir/rkimage.cpp.o" + "CMakeFiles/update.dir/rkimage.cpp.o.d" + "CMakeFiles/update.dir/rktools.cpp.o" + "CMakeFiles/update.dir/rktools.cpp.o.d" + "CMakeFiles/update.dir/update.cpp.o" + "CMakeFiles/update.dir/update.cpp.o.d" + "update" + "update.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C CXX) + include(CMakeFiles/update.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.internal b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.internal new file mode 100644 index 0000000..93abaa2 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.internal @@ -0,0 +1,1192 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/update.dir/crc.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + +CMakeFiles/update.dir/download.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + +CMakeFiles/update.dir/flash_image.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/gpt.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.h + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-user.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-abi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/wait.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.h + +CMakeFiles/update.dir/log.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + +CMakeFiles/update.dir/main.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/bootloader.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/debug.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/linkhash.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_inttypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_config.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/printbuf.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/arraylist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_util.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_pointer.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_tokener.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object_iterator.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_c_version.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h + +CMakeFiles/update.dir/md5sum.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/md5.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslconf.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslv.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/e_os2.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/rkboot.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/rkbootloader.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/bootloader.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h + +CMakeFiles/update.dir/rkimage.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h + +CMakeFiles/update.dir/rktools.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/update.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h + diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.make b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.make new file mode 100644 index 0000000..1333493 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.make @@ -0,0 +1,1782 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/update.dir/crc.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h + +CMakeFiles/update.dir/download.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h + +CMakeFiles/update.dir/flash_image.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/gpt.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.h + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-user.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-abi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/wait.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.h + +CMakeFiles/update.dir/log.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + +CMakeFiles/update.dir/main.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/bootloader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/debug.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/linkhash.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_inttypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_config.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/printbuf.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/arraylist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_util.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_pointer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_tokener.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object_iterator.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_c_version.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h + +CMakeFiles/update.dir/md5sum.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/md5.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslconf.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslv.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/e_os2.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/rkboot.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/rkbootloader.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/bootloader.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h + +CMakeFiles/update.dir/rkimage.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h + +CMakeFiles/update.dir/rktools.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h + +CMakeFiles/update.dir/update.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h + + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslv.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/printbuf.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/gpt.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_inttypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/e_os2.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-abi.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/bootloader.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-user.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslconf.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/wait.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/md5.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/debug.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/linkhash.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/arraylist.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_util.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_tokener.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object_iterator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_c_version.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_pointer.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_config.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h: diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.ts b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.ts new file mode 100644 index 0000000..049ca15 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for update. diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/crc.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/crc.cpp.o new file mode 100644 index 0000000..4c3877f Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/crc.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/crc.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/crc.cpp.o.d new file mode 100644 index 0000000..2681efb --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/crc.cpp.o.d @@ -0,0 +1,4 @@ +CMakeFiles/update.dir/crc.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/depend.make b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/depend.make new file mode 100644 index 0000000..f3ce3d8 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/depend.make @@ -0,0 +1,2 @@ +# Empty dependencies file for update. +# This may be replaced when dependencies are built. diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/download.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/download.cpp.o new file mode 100644 index 0000000..8fef779 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/download.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/download.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/download.cpp.o.d new file mode 100644 index 0000000..235742e --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/download.cpp.o.d @@ -0,0 +1,80 @@ +CMakeFiles/update.dir/download.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flags.make b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flags.make new file mode 100644 index 0000000..0075893 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flags.make @@ -0,0 +1,17 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# compile C with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +# compile CXX with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +C_DEFINES = + +C_INCLUDES = -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/.. -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/. -isystem /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +C_FLAGS = -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + +CXX_DEFINES = + +CXX_INCLUDES = -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/.. -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/. -isystem /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +CXX_FLAGS = -std=gnu++11 -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flash_image.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flash_image.cpp.o new file mode 100644 index 0000000..ce0104f Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flash_image.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flash_image.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flash_image.cpp.o.d new file mode 100644 index 0000000..5c599ea --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/flash_image.cpp.o.d @@ -0,0 +1,93 @@ +CMakeFiles/update.dir/flash_image.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/gpt.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../mtdutils/mtdutils.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o new file mode 100644 index 0000000..11d806d Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o.d new file mode 100644 index 0000000..b2e1731 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o.d @@ -0,0 +1,74 @@ +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o new file mode 100644 index 0000000..a7e740a Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o.d new file mode 100644 index 0000000..26e8c64 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o.d @@ -0,0 +1,93 @@ +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-user.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/mtd/mtd-abi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/int-ll64.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/bitsperlong.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/posix_types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/assert.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o new file mode 100644 index 0000000..f2f57cf Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o.d new file mode 100644 index 0000000..de35f1e --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o.d @@ -0,0 +1,110 @@ +CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/dirent.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/wait.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/mount.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctls.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ioctl-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/link.txt b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/link.txt new file mode 100644 index 0000000..ee78339 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/link.txt @@ -0,0 +1 @@ +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot CMakeFiles/update.dir/crc.cpp.o CMakeFiles/update.dir/download.cpp.o CMakeFiles/update.dir/flash_image.cpp.o CMakeFiles/update.dir/log.cpp.o CMakeFiles/update.dir/main.cpp.o CMakeFiles/update.dir/md5sum.cpp.o CMakeFiles/update.dir/rkboot.cpp.o CMakeFiles/update.dir/rkbootloader.cpp.o CMakeFiles/update.dir/rkimage.cpp.o CMakeFiles/update.dir/rktools.cpp.o CMakeFiles/update.dir/update.cpp.o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o -o update -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/include -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/lib -Wl,-rpath,/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/include:/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/lib:/usr/lib -lpthread /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcrypto.so /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libssl.so /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libjson-c.so /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcrypto.so diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/log.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/log.cpp.o new file mode 100644 index 0000000..3229e6a Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/log.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/log.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/log.cpp.o.d new file mode 100644 index 0000000..470e723 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/log.cpp.o.d @@ -0,0 +1,25 @@ +CMakeFiles/update.dir/log.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/main.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/main.cpp.o new file mode 100644 index 0000000..9a33385 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/main.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/main.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/main.cpp.o.d new file mode 100644 index 0000000..5c3ceda --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/main.cpp.o.d @@ -0,0 +1,224 @@ +CMakeFiles/update.dir/main.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/main.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../bootloader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/debug.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/linkhash.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_inttypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_config.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/inttypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/printbuf.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/arraylist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_util.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_pointer.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_tokener.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_object_iterator.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/json-c/json_c_version.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/md5sum.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/md5sum.cpp.o new file mode 100644 index 0000000..47f4226 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/md5sum.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/md5sum.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/md5sum.cpp.o.d new file mode 100644 index 0000000..a82271e --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/md5sum.cpp.o.d @@ -0,0 +1,85 @@ +CMakeFiles/update.dir/md5sum.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/md5.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslconf.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/opensslv.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/openssl/e_os2.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../mtdutils/mtdutils.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/progress.make b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/progress.make new file mode 100644 index 0000000..1029366 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/progress.make @@ -0,0 +1,16 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 +CMAKE_PROGRESS_4 = 4 +CMAKE_PROGRESS_5 = 5 +CMAKE_PROGRESS_6 = 6 +CMAKE_PROGRESS_7 = 7 +CMAKE_PROGRESS_8 = 8 +CMAKE_PROGRESS_9 = 9 +CMAKE_PROGRESS_10 = 10 +CMAKE_PROGRESS_11 = 11 +CMAKE_PROGRESS_12 = 12 +CMAKE_PROGRESS_13 = 13 +CMAKE_PROGRESS_14 = 14 +CMAKE_PROGRESS_15 = 15 + diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkboot.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkboot.cpp.o new file mode 100644 index 0000000..d059785 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkboot.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkboot.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkboot.cpp.o.d new file mode 100644 index 0000000..18936f1 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkboot.cpp.o.d @@ -0,0 +1,70 @@ +CMakeFiles/update.dir/rkboot.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkboot.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/crc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../mtdutils/mtdutils.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkbootloader.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkbootloader.cpp.o new file mode 100644 index 0000000..3f03b3c Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkbootloader.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkbootloader.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkbootloader.cpp.o.d new file mode 100644 index 0000000..4365eff --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkbootloader.cpp.o.d @@ -0,0 +1,80 @@ +CMakeFiles/update.dir/rkbootloader.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkbootloader.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../bootloader.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../mtdutils/mtdutils.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/reboot.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkimage.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkimage.cpp.o new file mode 100644 index 0000000..8bb69a0 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkimage.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkimage.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkimage.cpp.o.d new file mode 100644 index 0000000..4c61512 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rkimage.cpp.o.d @@ -0,0 +1,74 @@ +CMakeFiles/update.dir/rkimage.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rktools.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rktools.cpp.o new file mode 100644 index 0000000..a981381 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rktools.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rktools.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rktools.cpp.o.d new file mode 100644 index 0000000..9eaaed7 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/rktools.cpp.o.d @@ -0,0 +1,79 @@ +CMakeFiles/update.dir/rktools.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/../mtdutils/mtdutils.h diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/update.cpp.o b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/update.cpp.o new file mode 100644 index 0000000..4d95833 Binary files /dev/null and b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/update.cpp.o differ diff --git a/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/update.cpp.o.d b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/update.cpp.o.d new file mode 100644 index 0000000..9462557 --- /dev/null +++ b/update_engine/recovery/update_engine/build/CMakeFiles/update.dir/update.cpp.o.d @@ -0,0 +1,84 @@ +CMakeFiles/update.dir/update.cpp.o: \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/update.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/log.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/download.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rkimage.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/defineHeader.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/flash_image.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/rktools.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/md5sum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libgen.h diff --git a/update_engine/recovery/update_engine/build/Makefile b/update_engine/recovery/update_engine/build/Makefile new file mode 100644 index 0000000..096e9d4 --- /dev/null +++ b/update_engine/recovery/update_engine/build/Makefile @@ -0,0 +1,532 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named update + +# Build rule for target. +update: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 update +.PHONY : update + +# fast build rule for target. +update/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/build +.PHONY : update/fast + +crc.o: crc.cpp.o +.PHONY : crc.o + +# target to build an object file +crc.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/crc.cpp.o +.PHONY : crc.cpp.o + +crc.i: crc.cpp.i +.PHONY : crc.i + +# target to preprocess a source file +crc.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/crc.cpp.i +.PHONY : crc.cpp.i + +crc.s: crc.cpp.s +.PHONY : crc.s + +# target to generate assembly for a file +crc.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/crc.cpp.s +.PHONY : crc.cpp.s + +download.o: download.cpp.o +.PHONY : download.o + +# target to build an object file +download.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/download.cpp.o +.PHONY : download.cpp.o + +download.i: download.cpp.i +.PHONY : download.i + +# target to preprocess a source file +download.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/download.cpp.i +.PHONY : download.cpp.i + +download.s: download.cpp.s +.PHONY : download.s + +# target to generate assembly for a file +download.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/download.cpp.s +.PHONY : download.cpp.s + +flash_image.o: flash_image.cpp.o +.PHONY : flash_image.o + +# target to build an object file +flash_image.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/flash_image.cpp.o +.PHONY : flash_image.cpp.o + +flash_image.i: flash_image.cpp.i +.PHONY : flash_image.i + +# target to preprocess a source file +flash_image.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/flash_image.cpp.i +.PHONY : flash_image.cpp.i + +flash_image.s: flash_image.cpp.s +.PHONY : flash_image.s + +# target to generate assembly for a file +flash_image.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/flash_image.cpp.s +.PHONY : flash_image.cpp.s + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.o: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.o + +# target to build an object file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.o + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.i: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.i + +# target to preprocess a source file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.i + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.s: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.s + +# target to generate assembly for a file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.c.s + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.o: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.o + +# target to build an object file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.o + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.i: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.i + +# target to preprocess a source file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.i + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.s: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.s + +# target to generate assembly for a file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.c.s + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.o: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.o + +# target to build an object file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.o + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.i: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.i + +# target to preprocess a source file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.i + +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.s: home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.s + +# target to generate assembly for a file +home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s +.PHONY : home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.c.s + +log.o: log.cpp.o +.PHONY : log.o + +# target to build an object file +log.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/log.cpp.o +.PHONY : log.cpp.o + +log.i: log.cpp.i +.PHONY : log.i + +# target to preprocess a source file +log.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/log.cpp.i +.PHONY : log.cpp.i + +log.s: log.cpp.s +.PHONY : log.s + +# target to generate assembly for a file +log.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/log.cpp.s +.PHONY : log.cpp.s + +main.o: main.cpp.o +.PHONY : main.o + +# target to build an object file +main.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/main.cpp.o +.PHONY : main.cpp.o + +main.i: main.cpp.i +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/main.cpp.s +.PHONY : main.cpp.s + +md5sum.o: md5sum.cpp.o +.PHONY : md5sum.o + +# target to build an object file +md5sum.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/md5sum.cpp.o +.PHONY : md5sum.cpp.o + +md5sum.i: md5sum.cpp.i +.PHONY : md5sum.i + +# target to preprocess a source file +md5sum.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/md5sum.cpp.i +.PHONY : md5sum.cpp.i + +md5sum.s: md5sum.cpp.s +.PHONY : md5sum.s + +# target to generate assembly for a file +md5sum.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/md5sum.cpp.s +.PHONY : md5sum.cpp.s + +rkboot.o: rkboot.cpp.o +.PHONY : rkboot.o + +# target to build an object file +rkboot.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkboot.cpp.o +.PHONY : rkboot.cpp.o + +rkboot.i: rkboot.cpp.i +.PHONY : rkboot.i + +# target to preprocess a source file +rkboot.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkboot.cpp.i +.PHONY : rkboot.cpp.i + +rkboot.s: rkboot.cpp.s +.PHONY : rkboot.s + +# target to generate assembly for a file +rkboot.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkboot.cpp.s +.PHONY : rkboot.cpp.s + +rkbootloader.o: rkbootloader.cpp.o +.PHONY : rkbootloader.o + +# target to build an object file +rkbootloader.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkbootloader.cpp.o +.PHONY : rkbootloader.cpp.o + +rkbootloader.i: rkbootloader.cpp.i +.PHONY : rkbootloader.i + +# target to preprocess a source file +rkbootloader.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkbootloader.cpp.i +.PHONY : rkbootloader.cpp.i + +rkbootloader.s: rkbootloader.cpp.s +.PHONY : rkbootloader.s + +# target to generate assembly for a file +rkbootloader.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkbootloader.cpp.s +.PHONY : rkbootloader.cpp.s + +rkimage.o: rkimage.cpp.o +.PHONY : rkimage.o + +# target to build an object file +rkimage.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkimage.cpp.o +.PHONY : rkimage.cpp.o + +rkimage.i: rkimage.cpp.i +.PHONY : rkimage.i + +# target to preprocess a source file +rkimage.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkimage.cpp.i +.PHONY : rkimage.cpp.i + +rkimage.s: rkimage.cpp.s +.PHONY : rkimage.s + +# target to generate assembly for a file +rkimage.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rkimage.cpp.s +.PHONY : rkimage.cpp.s + +rktools.o: rktools.cpp.o +.PHONY : rktools.o + +# target to build an object file +rktools.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rktools.cpp.o +.PHONY : rktools.cpp.o + +rktools.i: rktools.cpp.i +.PHONY : rktools.i + +# target to preprocess a source file +rktools.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rktools.cpp.i +.PHONY : rktools.cpp.i + +rktools.s: rktools.cpp.s +.PHONY : rktools.s + +# target to generate assembly for a file +rktools.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/rktools.cpp.s +.PHONY : rktools.cpp.s + +update.o: update.cpp.o +.PHONY : update.o + +# target to build an object file +update.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/update.cpp.o +.PHONY : update.cpp.o + +update.i: update.cpp.i +.PHONY : update.i + +# target to preprocess a source file +update.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/update.cpp.i +.PHONY : update.cpp.i + +update.s: update.cpp.s +.PHONY : update.s + +# target to generate assembly for a file +update.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/update.dir/build.make CMakeFiles/update.dir/update.cpp.s +.PHONY : update.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... update" + @echo "... crc.o" + @echo "... crc.i" + @echo "... crc.s" + @echo "... download.o" + @echo "... download.i" + @echo "... download.s" + @echo "... flash_image.o" + @echo "... flash_image.i" + @echo "... flash_image.s" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.o" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.i" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mounts.s" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.o" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.i" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/mtdutils.s" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.o" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.i" + @echo "... home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/mtdutils/rk29.s" + @echo "... log.o" + @echo "... log.i" + @echo "... log.s" + @echo "... main.o" + @echo "... main.i" + @echo "... main.s" + @echo "... md5sum.o" + @echo "... md5sum.i" + @echo "... md5sum.s" + @echo "... rkboot.o" + @echo "... rkboot.i" + @echo "... rkboot.s" + @echo "... rkbootloader.o" + @echo "... rkbootloader.i" + @echo "... rkbootloader.s" + @echo "... rkimage.o" + @echo "... rkimage.i" + @echo "... rkimage.s" + @echo "... rktools.o" + @echo "... rktools.i" + @echo "... rktools.s" + @echo "... update.o" + @echo "... update.i" + @echo "... update.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/update_engine/recovery/update_engine/build/cmake_install.cmake b/update_engine/recovery/update_engine/build/cmake_install.cmake new file mode 100644 index 0000000..737f256 --- /dev/null +++ b/update_engine/recovery/update_engine/build/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/update_engine/recovery/update_engine/build/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/update_engine/recovery/update_engine/build/update b/update_engine/recovery/update_engine/build/update new file mode 100644 index 0000000..d017326 Binary files /dev/null and b/update_engine/recovery/update_engine/build/update differ diff --git a/update_engine/recovery/update_engine/crc.cpp b/update_engine/recovery/update_engine/crc.cpp new file mode 100644 index 0000000..8435720 --- /dev/null +++ b/update_engine/recovery/update_engine/crc.cpp @@ -0,0 +1,359 @@ +#include "defineHeader.h" +UINT gTable_Crc32[256] = +{ + 0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, + 0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005, + 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61, + 0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd, + 0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9, + 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75, + 0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011, + 0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd, + 0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039, + 0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5, + 0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81, + 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d, + 0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49, + 0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95, + 0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1, + 0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d, + 0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae, + 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072, + 0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16, + 0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca, + 0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde, + 0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02, + 0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066, + 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba, + 0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e, + 0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692, + 0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6, + 0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a, + 0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e, + 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2, + 0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686, + 0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a, + 0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637, + 0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb, + 0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f, + 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53, + 0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47, + 0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b, + 0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff, + 0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623, + 0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7, + 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b, + 0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f, + 0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3, + 0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7, + 0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b, + 0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f, + 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3, + 0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640, + 0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c, + 0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8, + 0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24, + 0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30, + 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec, + 0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088, + 0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654, + 0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0, + 0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c, + 0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18, + 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4, + 0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0, + 0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c, + 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668, + 0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4, +}; +#define rr_max 104 /* Number of parity checks, rr = deg[g(x)] */ +#define parallel 8 //bit count +#define mm 13//limit count +#define nn 8191//code size +#define kk 4120//info length +#define tt 8//correct count + +#define tt2 2*tt +UINT s[tt2+1]; // Syndrome values + +UINT rr;//redundant length // BCH code parameters + + +UINT p[mm + 1]; +UINT alpha_to[nn+1], index_of[nn+1] ; // Galois field +UINT gg[rr_max+1] ; // Generator polynomial + +UINT ggx1=0; +UINT ggx2=0; +UINT ggx3=0; +UINT ggx4=0; +// get crc32 value +UINT CRC_32(unsigned char* pData, UINT ulSize,UINT uiPreviousValue=0) +{ + UINT i; + UINT nAccum = uiPreviousValue; + + for ( i=0; i>24)^(*pData++)]; + return nAccum; +} +#define CRC16_CCITT 0x1021 //CRC operator +void CRCBuildTable16(unsigned short aPoly , unsigned short *crcTable) +{ + unsigned short i, j; + unsigned short nData; + unsigned short nAccum; + + for (i = 0; i < 256; i++) + { + nData = (unsigned short)(i << 8); + nAccum = 0; + for (j = 0; j < 8; j++) + { + if ((nData ^ nAccum) & 0x8000) + nAccum = (nAccum << 1) ^ aPoly; + else + nAccum <<= 1; + nData <<= 1; + } + crcTable[i] = nAccum; + } +} + +unsigned short CRC_16(unsigned char* aData, UINT aSize) +{ + UINT i; + unsigned short nAccum = 0; + unsigned short crcTable[256]; + + CRCBuildTable16(CRC16_CCITT , crcTable); + for (i = 0; i < aSize; i++) + nAccum = (nAccum << 8) ^ crcTable[(nAccum >> 8) ^ *aData++]; + + return nAccum; +} + +void P_RC4(unsigned char* buf, unsigned short len) +{ + unsigned char S[256],K[256],temp; + unsigned short i,j,t,x; + unsigned char key[16]={124,78,3,4,85,5,9,7,45,44,123,56,23,13,23,17}; + + j = 0; + for(i=0; i<256; i++){ + S[i] = (unsigned char)i; + j&=0x0f; + K[i] = key[j]; + j++; + } + + j = 0; + for(i=0; i<256; i++){ + j = (j + S[i] + K[i]) % 256; + temp = S[i]; + S[i] = S[j]; + S[j] = temp; + } + + i = j = 0; + for(x=0; x>j) & 1); + + bch1=((bch1>>1)|((bch2&1)*0x80000000))^(ggx1*feed_back); + bch2=((bch2>>1)|((bch3&1)*0x80000000))^(ggx2*feed_back); + bch3=((bch3>>1)|((bch4&1)*0x80000000))^(ggx3*feed_back); + bch4=(((bch4>>1)^(ggx4*feed_back))) | (feed_back*0x80); + } + } + + //********Handle FF*********************** + bch1 = ~(bch1 ^ 0xad6273b1); + bch2 = ~(bch2 ^ 0x348393d2); + bch3 = ~(bch3 ^ 0xe6ebed3c); + bch4 = ~(bch4 ^ 0xc8); + //********************************************* + + for (i=0;i<515;i++) + encode_out[i] = encode_in[i]; + encode_out[515] = bch1&0x000000ff; + encode_out[516] = (bch1&0x0000ff00)>>8; + encode_out[517] = (bch1&0x00ff0000)>>16; + encode_out[518] = (bch1&0xff000000)>>24; + encode_out[519] = bch2&0x000000ff; + encode_out[520] = (bch2&0x0000ff00)>>8; + encode_out[521] = (bch2&0x00ff0000)>>16; + encode_out[522] = (bch2&0xff000000)>>24; + encode_out[523] = bch3&0x000000ff; + encode_out[524] = (bch3&0x0000ff00)>>8; + encode_out[525] = (bch3&0x00ff0000)>>16; + encode_out[526] = (bch3&0xff000000)>>24; + encode_out[527] = bch4&0x000000ff; +} + +#define poly16_CCITT 0x1021 /* crc-ccitt mask */ + +unsigned short CRC_Calculate(unsigned short crc, unsigned char ch) +{ + UINT i; + for(i=0x80; i!=0; i>>=1) + { + if((crc & 0x8000) != 0) + { + crc <<= 1; + crc ^= poly16_CCITT; + } + else + crc <<= 1; + + if((ch & i)!=0) + crc ^= poly16_CCITT; + } + return crc; +} +unsigned short CRC_CCITT(unsigned char* p, UINT CalculateNumber) +{ + unsigned short crc = 0xffff; + while(CalculateNumber--) + { + crc = CRC_Calculate(crc, *p); + p++; + } + return crc; +} + +void gen_poly() +{ + UINT gen_roots[nn + 1], gen_roots_true[nn + 1] ; // Roots of generator polynomial + UINT i, j, Temp ; + +// Initialization of gen_roots + for (i = 0; i <= nn; i++) + { gen_roots_true[i] = 0; + gen_roots[i] = 0; + } + +// Cyclotomic cosets of gen_roots + for (i = 1; i <= 2*tt ; i++) + { + for (j = 0; j < mm; j++) + { + Temp = ((1< 0; j--) + if (gg[j] != 0) + gg[j] = gg[j-1]^ alpha_to[(index_of[gg[j]] + index_of[alpha_to[gen_roots[i]]]) % nn] ; + else + gg[j] = gg[j-1] ; + gg[0] = alpha_to[(index_of[gg[0]] + index_of[alpha_to[gen_roots[i]]]) % nn] ; + } + +ggx1 = gg[103] | (gg[102]<<1) | (gg[101]<<2) | (gg[100]<<3) | (gg[99]<<4) |(gg[98]<<5)| (gg[97]<<6)|(gg[96]<<7) + | (gg[95]<<8) | (gg[94]<<9) | (gg[93]<<10) | (gg[92]<<11) |(gg[91]<<12)| (gg[90]<<13)|(gg[89]<<14) |(gg[88]<<15) + | (gg[87]<<16) | (gg[86]<<17) | (gg[85]<<18) | (gg[84]<<19) | (gg[83]<<20) |(gg[82]<<21)| (gg[81]<<22)|(gg[80]<<23) + | (gg[79]<<24) | (gg[78]<<25) | (gg[77]<<26) | (gg[76]<<27) |(gg[75]<<28)| (gg[74]<<29)|(gg[73]<<30) |(gg[72]<<31); +ggx2 = gg[71] | (gg[70]<<1) | (gg[69]<<2) | (gg[68]<<3) | (gg[67]<<4) |(gg[66]<<5)| (gg[65]<<6)|(gg[64]<<7) + | (gg[63]<<8) | (gg[62]<<9) | (gg[61]<<10) | (gg[60]<<11) |(gg[59]<<12)| (gg[58]<<13)|(gg[57]<<14) |(gg[56]<<15) + | (gg[55]<<16) | (gg[54]<<17) | (gg[53]<<18) | (gg[52]<<19) | (gg[51]<<20) |(gg[50]<<21)| (gg[49]<<22)|(gg[48]<<23) + | (gg[47]<<24) | (gg[46]<<25) | (gg[45]<<26) | (gg[44]<<27) |(gg[43]<<28)| (gg[42]<<29)|(gg[41]<<30) |(gg[40]<<31); +ggx3 = gg[39] | (gg[38]<<1) | (gg[37]<<2) | (gg[36]<<3) | (gg[35]<<4) |(gg[34]<<5)| (gg[33]<<6)|(gg[32]<<7) + | (gg[31]<<8) | (gg[30]<<9) | (gg[29]<<10) | (gg[28]<<11) |(gg[27]<<12)| (gg[26]<<13)|(gg[25]<<14) |(gg[24]<<15) + | (gg[23]<<16) | (gg[22]<<17) | (gg[21]<<18) | (gg[20]<<19) | (gg[19]<<20) |(gg[18]<<21)| (gg[17]<<22)|(gg[16]<<23) + | (gg[15]<<24) | (gg[14]<<25) | (gg[13]<<26) | (gg[12]<<27) |(gg[11]<<28)| (gg[10]<<29)|(gg[9]<<30) |(gg[8]<<31); +ggx4 = gg[7] | (gg[6]<<1) | (gg[5]<<2) | (gg[4]<<3) | (gg[3]<<4) |(gg[2]<<5)| (gg[1]<<6); + +} + +void generate_gf() +{ + UINT i; + UINT mask ; // Register states + + // Primitive polynomials + for (i = 1; i < mm; i++) + p[i] = 0; + p[0] = p[mm] = 1; + if (mm == 2) p[1] = 1; + else if (mm == 3) p[1] = 1; + else if (mm == 4) p[1] = 1; + else if (mm == 5) p[2] = 1; + else if (mm == 6) p[1] = 1; + else if (mm == 7) p[1] = 1; + else if (mm == 8) p[4] = p[5] = p[6] = 1; + else if (mm == 9) p[4] = 1; + else if (mm == 10) p[3] = 1; + else if (mm == 11) p[2] = 1; + else if (mm == 12) p[3] = p[4] = p[7] = 1; + else if (mm == 13) p[1] = p[2] = p[3] = p[5] = p[7] = p[8] = p[10] = 1; // 25AF + else if (mm == 14) p[2] = p[4] = p[6] = p[7] = p[8] = 1; // 41D5 + else if (mm == 15) p[1] = 1; + else if (mm == 16) p[2] = p[3] = p[5] = 1; + else if (mm == 17) p[3] = 1; + else if (mm == 18) p[7] = 1; + else if (mm == 19) p[1] = p[5] = p[6] = 1; + else if (mm == 20) p[3] = 1; + // Galois field implementation with shift registers + // Ref: L&C, Chapter 6.7, pp. 217 + mask = 1 ; + alpha_to[mm] = 0 ; + for (i = 0; i < mm; i++) + { + alpha_to[i] = mask ; + index_of[alpha_to[i]] = i ; + if (p[i] != 0) + alpha_to[mm] ^= mask ; + mask <<= 1 ; + } + + index_of[alpha_to[mm]] = mm ; + mask >>= 1 ; + for (i = mm + 1; i < nn; i++) + { + if (alpha_to[i-1] >= mask) + alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1] ^ mask) << 1) ; + else + alpha_to[i] = alpha_to[i-1] << 1 ; + + index_of[alpha_to[i]] = i ; + } + index_of[0] = -1 ; +} diff --git a/update_engine/recovery/update_engine/crc.h b/update_engine/recovery/update_engine/crc.h new file mode 100644 index 0000000..a409656 --- /dev/null +++ b/update_engine/recovery/update_engine/crc.h @@ -0,0 +1,18 @@ +/************************************************************************* + > File Name: crc.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Tue 04 Jun 2019 02:34:40 PM CST + ************************************************************************/ + +#ifndef _CRC_H +#define _CRC_H +#include "defineHeader.h" +extern USHORT CRC_16(BYTE * aData, UINT aSize); +extern UINT CRC_32(PBYTE pData, UINT ulSize, UINT uiPreviousValue=0); +extern void P_RC4(BYTE * buf, USHORT len); +extern void bch_encode(BYTE *encode_in, BYTE *encode_out); +extern USHORT CRC_CCITT(UCHAR *p, UINT CalculateNumber); +extern void generate_gf(); +extern void gen_poly(); +#endif diff --git a/update_engine/recovery/update_engine/defineHeader.h b/update_engine/recovery/update_engine/defineHeader.h new file mode 100644 index 0000000..bd5d382 --- /dev/null +++ b/update_engine/recovery/update_engine/defineHeader.h @@ -0,0 +1,78 @@ +/************************************************************************* + > File Name: defineHeader.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Tue 04 Jun 2019 09:06:31 AM CST + ************************************************************************/ + +#ifndef _DEFINEHEADER_H +#define _DEFINEHEADER_H + +#define DEFAULT_DOWNLOAD_PATH "/tmp/update.img" +#define BLOCK_WRITE_LEN (16 * 1024) +#define MTD_SIZE 2048 +#define SECTOR_SIZE 512 + +#define BYTE2SECTOR(x) ((x>0)?((x-1)/SECTOR_SIZE + 1):(x)) +#define PAGEALIGN(x) ((x>0)?((x-1) / 4 + 1):(x)) + +typedef unsigned char BYTE; +typedef BYTE *PBYTE; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned int DWORD; +typedef unsigned char UCHAR; +typedef unsigned short WCHAR; +typedef signed char CHAR; + +typedef enum +{ + RKNONE_DEVICE=0, + RK27_DEVICE=0x10, + RKCAYMAN_DEVICE, + RK28_DEVICE=0x20, + RK281X_DEVICE, + RKPANDA_DEVICE, + RKNANO_DEVICE=0x30, + RKSMART_DEVICE, + RKCROWN_DEVICE=0x40, + RK29_DEVICE=0x50, + RK292X_DEVICE, + RK30_DEVICE=0x60, + RK30B_DEVICE, + RK31_DEVICE=0x70, + RK32_DEVICE=0x80 +}ENUM_RKDEVICE_TYPE; + +typedef enum +{ + ENTRY471=1, + ENTRY472=2, + ENTRYLOADER=4 +}ENUM_RKBOOTENTRY; + +#define SHA_DIGEST_SIZE 20 +#define PART_NAME 32 +#define RELATIVE_PATH 64 +#define MAX_PARTS 20 +#define MAX_MACHINE_MODEL 64 +#define MAX_MANUFACTURER 60 +#define MAX_PACKAGE_FILES 32 +#define RKIMAGE_TAG 0x46414B52 +#define IMAGE_RESERVED_SIZE 61 +#define BOOT_RESERVED_SIZE 57 +#define IDB_BLOCKS 5 +#define IDBLOCK_TOP 50 +#define CHIPINFO_LEN 16 +#define RKANDROID_SEC2_RESERVED_LEN 473 +#define RKDEVICE_SN_LEN 30 +#define RKANDROID_SEC3_RESERVED_LEN 419 +#define RKDEVICE_IMEI_LEN 15 +#define RKDEVICE_UID_LEN 30 +#define RKDEVICE_BT_LEN 6 +#define RKDEVICE_MAC_LEN 6 +#define SPARE_SIZE 16 + +#define GPT_BACKUP_FILE_NAME "gpt_backup.img" + +#endif diff --git a/update_engine/recovery/update_engine/download.cpp b/update_engine/recovery/update_engine/download.cpp new file mode 100644 index 0000000..132025e --- /dev/null +++ b/update_engine/recovery/update_engine/download.cpp @@ -0,0 +1,74 @@ +/************************************************************************* + > File Name: download.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Thu 07 Mar 2019 10:30:31 AM CST + ************************************************************************/ + +#include +#include +#include +#include "log.h" +size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + return fwrite(ptr, size, nmemb, stream); +} + +extern double processvalue; +static int down_processvalue; + +int my_progress_func(char *progress_data, + double t, /* dltotal */ + double d, /* dlnow */ + double ultotal, + double ulnow) +{ + processvalue = ulnow / ultotal * 100 / 110; + //LOGI("ultotal is %f, ulnow is %f, t is %f, d is %f\n", ultotal, ulnow, t, d); + if (down_processvalue != (int)(d / t * 100)) { + down_processvalue = (int)(d / t * 100); + LOGI("down_processvalue is %d%\n", down_processvalue); + } + + return 0; +} + +int download_file(char *url, char *output_filename) +{ + if (strncmp(url, "http", 4) != 0) { + LOGI("where the file is local.\n"); + return -2; + } + CURL *curl; + CURLcode res; + FILE *outfile; + char *progress_data = "* "; + down_processvalue = -1; + + curl = curl_easy_init(); + if(curl) + { + outfile = fopen(output_filename, "wb"); + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress_data); + + res = curl_easy_perform(curl); + + if(res != CURLE_OK) + LOGE("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + fclose(outfile); + /* always cleanup */ + curl_easy_cleanup(curl); + } + if(res != CURLE_OK){ + LOGE("download Error.\n"); + return -1; + } + return 0; +} + diff --git a/update_engine/recovery/update_engine/download.h b/update_engine/recovery/update_engine/download.h new file mode 100644 index 0000000..6565f08 --- /dev/null +++ b/update_engine/recovery/update_engine/download.h @@ -0,0 +1,11 @@ +/************************************************************************* + > File Name: download.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Thu 07 Mar 2019 10:39:33 AM CST + ************************************************************************/ + +#ifndef _DOWNLOAD_H +#define _DOWNLOAD_H +int download_file(char *url, char *output_filename); +#endif diff --git a/update_engine/recovery/update_engine/flash_image.cpp b/update_engine/recovery/update_engine/flash_image.cpp new file mode 100644 index 0000000..05a49b5 --- /dev/null +++ b/update_engine/recovery/update_engine/flash_image.cpp @@ -0,0 +1,676 @@ +/************************************************************************* + > File Name: flash_image.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Tue 21 May 2019 09:29:30 AM CST + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "flash_image.h" +#include "update.h" +#include "log.h" +#include "rktools.h" +#include "gpt.h" +#include "rkimage.h" +#include "defineHeader.h" +#include "rkboot.h" + +extern "C" { + #include "../mtdutils/mtdutils.h" +} +#define UBI_HEAD_MAGIC "UBI#" + +static PSTRUCT_PARAM_ITEM gp_param_item = NULL; +static long long *gp_backup_gpt_offset = NULL; + +// get greastest common divisor (gcd) +static int get_gcd ( long long x, long long y ) +{ + while (x != y)//用大数减去小数并将结果保存起来 + { + if (x > y) { + x -= y; + } else if(x < y) { + y -= x; + } + } + return x; +} + +static bool is_ubi(char *src_path, long long offset) +{ + char magic[5] = {0}; + bool ret; + + int fd_src = open(src_path, O_RDONLY); + if (fd_src < 0) { + LOGE("error opening %s.\n", src_path); + return 0; + } + if ( lseek64(fd_src, offset, SEEK_SET) == -1) { + close(fd_src); + LOGE("lseek64 failed (%s:%d).\n", __func__, __LINE__); + return 0; + } + read(fd_src, magic, 4); + LOGI("image magic is %s\n", magic); + if(strcmp(magic, UBI_HEAD_MAGIC) == 0) + ret = 1; + else + ret = 0; + close(fd_src); + + return ret; +} + +static void mtd_read() { + +} + +static int mtd_write(char *src_path, long long offset, long long size, long long flash_offset, char *dest_path) { + LOGI("mtd_write %s, offset = %#llx size = %#llx flash_offset = %lld.\n", dest_path, offset, size, flash_offset); + + struct stat sb; + char mtd_write_erase_cmd[256] = {0}; + stat(dest_path, &sb); + long long dd_bs = 1; + long long dd_skip = offset; + long long dd_count = size; + + if ((sb.st_mode & S_IFMT) == S_IFCHR) { + memset(mtd_write_erase_cmd, 0, sizeof(mtd_write_erase_cmd)/sizeof(mtd_write_erase_cmd[0])); + sprintf(mtd_write_erase_cmd, "flash_erase %s 0 0", dest_path); + system(mtd_write_erase_cmd); + + dd_bs = get_gcd(offset, size); + dd_skip = offset / dd_bs; + dd_count = size / dd_bs; + // dd if=/mnt/sdcard/sdupdate.img bs=4 skip=2727533 count=3646464 | nandwrite -p /dev/block/by-name/recovery + memset(mtd_write_erase_cmd, 0, sizeof(mtd_write_erase_cmd)/sizeof(mtd_write_erase_cmd[0])); + sprintf(mtd_write_erase_cmd, "dd if=%s bs=%lld skip=%lld count=%lld | nandwrite -p %s", + src_path, dd_bs, dd_skip, dd_count, dest_path ); + system(mtd_write_erase_cmd); + } else { + LOGE("flash_erase: can't erase MTD \"%s\"\n", dest_path); + return -1; + } + + return 0; +} + +static void block_read() { + +} + +static int block_write(char *src_path, long long offset, long long size, long long flash_offset, char *dest_path) { + LOGI("block_write src %s dest %s.\n", src_path, dest_path); + int fd_dest = 0, fd_src = 0; + long long src_offset = 0, dest_offset = 0; + long long src_remain, dest_remain; + int src_step, dest_step; + long long src_file_offset = 0; + long long read_count, write_count; + char data_buf[BLOCK_WRITE_LEN] = {0}; + + fd_src = open(src_path, O_RDONLY); + if (fd_src < 0) { + LOGE("Can't open %s\n", src_path); + return -2; + } + src_offset = offset; + dest_remain = src_remain = size; + dest_step = src_step = BLOCK_WRITE_LEN; + + if (lseek64(fd_src, src_offset, SEEK_SET) == -1) { + close(fd_src); + LOGE("lseek64 failed (%s:%d).\n", __func__, __LINE__); + return -2; + } + src_file_offset = src_offset; + // dest_offset = flash_offset; + // This step is going to write (src_path: sdupdate.img) to the file which is partition data (e.g. uboot) + // So dest_offset is 0. + dest_offset = 0; + + fd_dest = open(dest_path, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (fd_dest < 0) { + close(fd_src); + LOGE("Can't open %s\n", dest_path); + return -2; + } + if ( lseek64(fd_dest, dest_offset, SEEK_SET) == -1 ) { + LOGE("(%s:%d) lseek64 failed(%s).\n", __func__, __LINE__, strerror(errno)); + close(fd_src); + close(fd_dest); + return -2; + } + while (src_remain > 0 && dest_remain > 0) { + memset(data_buf, 0, BLOCK_WRITE_LEN); + read_count = src_remain>src_step?src_step:src_remain; + + if (read(fd_src, data_buf, read_count) != read_count) { + close(fd_dest); + close(fd_src); + LOGE("Read failed(%s):(%s:%d)\n", strerror(errno), __func__, __LINE__); + return -2; + } + + src_remain -= read_count; + src_file_offset += read_count; + write_count = dest_remain>dest_step?dest_step:dest_remain; + + if (write(fd_dest, data_buf, write_count) != write_count) { + close(fd_dest); + close(fd_src); + LOGE("(%s:%d) write failed(%s).\n", __func__, __LINE__, strerror(errno)); + return -2; + } + dest_remain -= write_count; + } + + fsync(fd_dest); + close(fd_dest); + close(fd_src); + return 0; +} + +extern bool is_sdboot; +int flash_normal(char *src_path, void *pupdate_cmd) { + LOGI("%s:%d start.\n", __func__, __LINE__); + PUPDATE_CMD pcmd = (PUPDATE_CMD)pupdate_cmd; + int ret = 0; + if (is_sdboot || !isMtdDevice()) { + //block + ret = block_write(src_path, pcmd->offset, pcmd->size, pcmd->flash_offset, pcmd->dest_path); + } else { + //mtd + printf("pcmd->flash_offset = %lld.\n", pcmd->flash_offset); + ret = mtd_write(src_path, pcmd->offset, pcmd->size, pcmd->flash_offset, pcmd->dest_path); + } + return ret; +} + +static void string_to_uuid(char* strUUid, char *uuid) +{ + unsigned int i; + char value; + memset(uuid, 0, 16); + for (i =0; i < 256; i++) { + if (strUUid[i] == '\0') { + break; + } + value = 0; + if ((strUUid[i] >= '0')&&(strUUid[i] <= '9')) + value = strUUid[i] - '0'; + if ((strUUid[i] >= 'a')&&(strUUid[i] <= 'f')) + value = strUUid[i] - 'a' + 10; + if ((strUUid[i] >= 'A')&&(strUUid[i] <= 'F')) + value = strUUid[i] - 'A' + 10; + if ((i % 2) == 0) + uuid[i / 2] += (value << 4); + else + uuid[i / 2] += value; + } + unsigned int *p32; + unsigned short *p16; + p32 = (unsigned int*)uuid; + *p32 = cpu_to_be32(*p32); + p16 = (unsigned short *)(uuid + 4); + *p16 = cpu_to_be16(*p16); + p16 = (unsigned short *)(uuid + 6); + *p16 = cpu_to_be16(*p16); +} + +static void getUuidFromString(char *str, PSTRUCT_CONFIG_ITEM p_config) { + char data_buf[strlen(str)]; + memcpy(data_buf, str, strlen(str)); + char *line = strtok(data_buf, "\n"); + while (line != NULL) { + if (line[0] == '#') { + continue; + } + + char *pline = strstr(line, "uuid"); + if(pline != NULL && (pline = strstr(pline, ":")) != NULL) { + pline++; //过滤掉冒号 + //过滤掉空格 + while(*pline == ' ') { + pline++; + } + char tmp; + char value[256] = {0}; + sscanf(pline, "%[^=]%c%s", p_config->name, &tmp, value); + string_to_uuid(value, p_config->value); + p_config++; + } + + line = strtok(NULL, "\n"); + } +} + +static void getParamFromString(char *str, PSTRUCT_PARAM_ITEM p_param) { + char data_buf[strlen(str)]; + memcpy(data_buf, str, strlen(str)); + char *line = strtok(data_buf, "\n"); + while (line != NULL) { + if (line[0] == '#') { + continue; + } + + char *pline = strstr(line, "mtdparts"); + if (pline != NULL && (pline = strstr(pline, ":")) != NULL) { + pline++; //过滤掉冒号 + //过滤掉空格 + while (*pline == ' ') { + pline++; + } + int pline_len = strlen(pline); + char mtdparts_line[pline_len]; + memset(mtdparts_line, 0, pline_len); + memcpy(mtdparts_line, pline, pline_len); + //开始解析文件 + char *token = strtok(mtdparts_line, ","); + while (token != NULL) { + char size[20], offset[20]; + char tmp; + if (*token == '-'){ + sscanf(token, "-@0x%x(%[^)]", &p_param->offset, p_param->name); + p_param->size = 0xFFFFFFFF; + p_param++; + } else { + sscanf(token, "0x%x@0x%x(%[^)]", &p_param->size, &p_param->offset, p_param->name); + p_param++; + } + token = strtok(NULL, ","); + } + } + line = strtok(NULL, "\n"); + } +} + +static void gen_rand_uuid(unsigned char *uuid_bin) +{ + efi_guid_t id; + unsigned int *ptr = (unsigned int *)&id; + unsigned int i; + + /* Set all fields randomly */ + for (i = 0; i < sizeof(id) / sizeof(*ptr); i++) + *(ptr + i) = cpu_to_be32(rand()); + + id.uuid.time_hi_and_version = (id.uuid.time_hi_and_version & 0x0FFF) | 0x4000; + id.uuid.clock_seq_hi_and_reserved = id.uuid.clock_seq_hi_and_reserved | 0x80; + + memcpy(uuid_bin, id.raw, sizeof(id)); +} + +#define tole(x) (x) +unsigned int crc32table_le[] = { + tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL), + tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L), + tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L), + tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L), + tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL), + tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L), + tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL), + tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L), + tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L), + tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL), + tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L), + tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L), + tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L), + tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL), + tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L), + tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL), + tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL), + tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L), + tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L), + tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L), + tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL), + tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L), + tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL), + tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L), + tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L), + tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL), + tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L), + tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L), + tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L), + tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL), + tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L), + tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL), + tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL), + tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L), + tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L), + tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L), + tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL), + tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L), + tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL), + tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L), + tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L), + tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL), + tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L), + tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L), + tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L), + tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL), + tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L), + tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL), + tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL), + tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L), + tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L), + tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L), + tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL), + tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L), + tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL), + tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L), + tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L), + tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL), + tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L), + tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L), + tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L), + tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL), + tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L), + tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL) +}; + +#define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) +static unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len) +{ + unsigned int *b =(unsigned int *)p; + unsigned int *tab = crc32table_le; + crc = crc ^ 0xFFFFFFFF; + if((((long)b)&3 && len)){ + do { + unsigned char *p = (unsigned char *)b; + DO_CRC(*p++); + b = (unsigned int *)p; + } while ((--len) && ((long)b)&3 ); + } + if((len >= 4)){ + unsigned int save_len = len & 3; + len = len >> 2; + --b; + do { + crc ^= *++b; + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + } while (--len); + b++; + len = save_len; + } + if(len){ + do { + unsigned char *p = (unsigned char *)b; + DO_CRC(*p++); + b = (unsigned int *)p; + } while (--len); + } + crc = crc ^ 0xFFFFFFFF; + return crc; + +} + +static void create_gpt_buffer(u8 *gpt, PSTRUCT_PARAM_ITEM p_param, int param_len, PSTRUCT_CONFIG_ITEM p_config, int config_len, u64 diskSectors) +{ + legacy_mbr *mbr = (legacy_mbr *)gpt; + gpt_header *gptHead = (gpt_header *)(gpt + SECTOR_SIZE); + gpt_entry *gptEntry = (gpt_entry *)(gpt + 2 * SECTOR_SIZE); + + /*1.protective mbr*/ + memset(gpt, 0, SECTOR_SIZE); + mbr->signature = MSDOS_MBR_SIGNATURE; + mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT; + mbr->partition_record[0].start_sect = 1; + mbr->partition_record[0].nr_sects = (u32)-1; + + /*2.gpt header*/ + memset(gpt + SECTOR_SIZE, 0, SECTOR_SIZE); + gptHead->signature = cpu_to_le64(GPT_HEADER_SIGNATURE); + gptHead->revision = cpu_to_le32(GPT_HEADER_REVISION_V1); + gptHead->header_size = cpu_to_le32(sizeof(gpt_header)); + gptHead->my_lba = cpu_to_le64(1); + gptHead->alternate_lba = cpu_to_le64(diskSectors - 1); + gptHead->first_usable_lba = cpu_to_le64(34); + gptHead->last_usable_lba = cpu_to_le64(diskSectors - 34); + gptHead->partition_entry_lba = cpu_to_le64(2); + gptHead->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS); + gptHead->sizeof_partition_entry = cpu_to_le32(GPT_ENTRY_SIZE); + gptHead->header_crc32 = 0; + gptHead->partition_entry_array_crc32 = 0; + gen_rand_uuid(gptHead->disk_guid.raw); + + /*3.gpt partition entry*/ + memset(gpt + 2 * SECTOR_SIZE, 0, 32 * SECTOR_SIZE); + for (int i = 0; i < param_len; i++) { + if (strcmp(p_param[i].name, "") == 0) { + continue; + } + gen_rand_uuid(gptEntry->partition_type_guid.raw); + gen_rand_uuid(gptEntry->unique_partition_guid.raw); + gptEntry->starting_lba = cpu_to_le64(p_param[i].offset); + gptEntry->ending_lba = cpu_to_le64(gptEntry->starting_lba + p_param[i].size - 1); + gptEntry->attributes.raw = 0; + + char partition_name[20] = {0}; + strcpy(partition_name, p_param[i].name); + char *p; + if ( (p = strstr(partition_name, ":")) != NULL) { + if (strstr(partition_name, "bootable") != NULL) { + gptEntry->attributes.raw = PART_PROPERTY_BOOTABLE; + } + if (strstr(partition_name, "grow") != NULL) { + gptEntry->ending_lba = cpu_to_le64(diskSectors - 34); + } + *p = '\0'; + strcpy(p_param[i].name, partition_name); + } + + for (int j = 0; j < strlen(p_param[i].name); j++) + gptEntry->partition_name[j] = p_param[i].name[j]; + for (int j = 0; j < config_len; j++) { + if (strcmp(p_config[j].name, p_param[i].name) == 0) { + memcpy(gptEntry->unique_partition_guid.raw, p_config[j].value, 16); + break ; + } + } + gptEntry++; + } + + gptHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, gpt + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS)); + gptHead->header_crc32 = cpu_to_le32(crc32_le(0, gpt + SECTOR_SIZE, sizeof(gpt_header))); + +} + +static void prepare_gpt_backup(u8 *master, u8 *backup) +{ + gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE); + gpt_header *gptBackupHead = (gpt_header *)(backup + 32 * SECTOR_SIZE); + u32 calc_crc32; + u64 val; + + /* recalculate the values for the Backup GPT Header */ + val = le64_to_cpu(gptMasterHead->my_lba); + gptBackupHead->my_lba = gptMasterHead->alternate_lba; + gptBackupHead->alternate_lba = cpu_to_le64(val); + gptBackupHead->partition_entry_lba = cpu_to_le64(le64_to_cpu(gptMasterHead->last_usable_lba) + 1); + gptBackupHead->header_crc32 = 0; + + calc_crc32 = crc32_le(0, (unsigned char *)gptBackupHead, le32_to_cpu(gptBackupHead->header_size)); + gptBackupHead->header_crc32 = cpu_to_le32(calc_crc32); +} + +int flash_register_partition_data(PSTRUCT_PARAM_ITEM p_param_item, long long *p_gpt_backup_offset) +{ + if (p_param_item) { + gp_param_item = p_param_item; + } + + if (p_gpt_backup_offset) { + gp_backup_gpt_offset = p_gpt_backup_offset; + } + + return 0; +} + +int flash_parameter(char *src_path, void *pupdate_cmd) { + LOGI("flash_parameter start src_path [%s].\n", src_path); + PUPDATE_CMD pcmd = (PUPDATE_CMD)pupdate_cmd; + + unsigned int m_uiParamFileSize = pcmd->size; + + if (m_uiParamFileSize % SECTOR_SIZE != 0) { + m_uiParamFileSize = (m_uiParamFileSize/SECTOR_SIZE + 1) * SECTOR_SIZE; + } + + // 1. 读取parameter 数据 + unsigned char data_buf[m_uiParamFileSize]; + memset(data_buf, 0, m_uiParamFileSize); + int fd_src = open(src_path, O_RDONLY); + if (fd_src < 0) { + LOGE("Can't open %s, %s\n", src_path, strerror(errno)); + return -2; + } + if (lseek64(fd_src, pcmd->offset, SEEK_SET) == -1) { + LOGE("lseek64 failed (%s:%d), %s.\n", __func__, __LINE__, strerror(errno)); + close(fd_src); + return -2; + } + if (read(fd_src, data_buf, pcmd->size) != pcmd->size) { + close(fd_src); + return -2; + } + close(fd_src); + + // 2. 获取分区大小和uuid + STRUCT_PARAM_ITEM param_item[20] = {0}; + STRUCT_CONFIG_ITEM config_item[10] = {0}; + getParamFromString((char *)data_buf + 8, param_item); + getUuidFromString((char *)data_buf + 8, config_item); + + if (gp_param_item) { + memcpy(gp_param_item, param_item, sizeof(param_item) ); + } + + LOGI("%s-%d: List partitions:\n", __func__, __LINE__); + for (int j = 0; j < sizeof(param_item)/sizeof(param_item[0]); j++) { + LOGI(" param_item[%d].name [%s]\n", j, param_item[j].name); + } + + // 3. 获得flash 的大小,和块数 + long long block_num; + if (getFlashSize(NULL, NULL, &block_num) != 0) { + LOGE("getFlashSize error.\n"); + return -2; + } + + LOGI("%s, block_num = %lld.\n", __func__, block_num); + + // 4. 创建gpt 表 + unsigned char write_buf[SECTOR_SIZE * 67]; + unsigned char *backup_gpt; + backup_gpt = write_buf+34*SECTOR_SIZE; + memset(write_buf, 0, SECTOR_SIZE * 67); + create_gpt_buffer(write_buf, param_item, 20, config_item, 10, block_num); + memcpy(backup_gpt, write_buf + 2* SECTOR_SIZE, 32 * SECTOR_SIZE); + memcpy(backup_gpt + 32 * SECTOR_SIZE, write_buf + SECTOR_SIZE, SECTOR_SIZE); + prepare_gpt_backup(write_buf, backup_gpt); + + if (gp_backup_gpt_offset) { + *gp_backup_gpt_offset = (block_num - 33) * SECTOR_SIZE; + } + + //5. 写入主GPT表 + int fd_dest = open(pcmd->dest_path, O_CREAT|O_RDWR| O_TRUNC, 0644); + if (fd_dest < 0) { + LOGE("Can't open %s, %s\n", pcmd->dest_path, strerror(errno)); + return -2; + } + lseek64(fd_dest, 0, SEEK_SET); + if (write(fd_dest, write_buf, 34*SECTOR_SIZE) != 34*SECTOR_SIZE) { + LOGE("write error %s: (%s:%d).\n", strerror(errno), __func__, __LINE__); + close(fd_dest); + return -2; + } + //6. 尾部写入GPT表到文件 + /* + * char gpt_backup_dest_path[100] = {0}; + * memset(gpt_backup_dest_path, 0, sizeof(gpt_backup_dest_path)/sizeof(gpt_backup_dest_path[0])); + * memcpy(gpt_backup_dest_path, pcmd->dest_path, strlen(pcmd->dest_path)); + * dirname(gpt_backup_dest_path); + * sprintf(gpt_backup_dest_path, "%s/%s", gpt_backup_dest_path, GPT_BACKUP_FILE_NAME); + */ + +#if 0 + int fd_backup = open(gpt_backup_dest_path, O_CREAT|O_RDWR| O_TRUNC, 0644); + if (fd_backup < 0) { + LOGE("Can't open %s, %s\n", gpt_backup_dest_path, strerror(errno)); + return -2; + } + + if (write(fd_backup, backup_gpt, 33*SECTOR_SIZE) != 33*SECTOR_SIZE) { + LOGE("write error %s: (%s:%d).\n", strerror(errno), __func__, __LINE__); + close(fd_backup); + return -2; + } + close(fd_backup); +#endif + close(fd_dest); + sync(); + return 0; +} + + +int flash_bootloader(char *src_path, void *pupdate_cmd) { + PUPDATE_CMD pcmd = (PUPDATE_CMD)pupdate_cmd; + + if (isMtdDevice()) { + // bootrom read IDBlock from the offset which is equal to block size for Nand Flash + size_t block_size = 0; + if (getFlashInfo(NULL, &block_size, NULL) != 0) { + LOGE("%s-%d: get mtd info error\n", __func__, __LINE__); + return false; + } + pcmd->flash_offset = block_size; + } else { + // bootrom read IDBlock from the offset (32KB + 512KB * n ) for eMMC + pcmd->flash_offset = 32*1024; + } + + // 1. 读取bootloader + unsigned char data_buf[pcmd->size]; + memset(data_buf, 0, pcmd->size); + int fd_src = open(src_path, O_RDONLY); + if (fd_src < 0) { + LOGE("Can't open %s, %s\n", src_path, strerror(errno)); + return -2; + } + if (lseek64(fd_src, pcmd->offset, SEEK_SET) == -1) { + LOGE("(%s:%d) lseek64 failed: %s.\n", __func__, __LINE__, strerror(errno)); + close(fd_src); + return -2; + } + if (read(fd_src, data_buf, pcmd->size) != pcmd->size) { + close(fd_src); + LOGE("read error(%s:%d) : %s.\n", __func__, __LINE__, strerror(errno)); + return -2; + } + close(fd_src); + + if (!download_loader(data_buf, pcmd->size, pcmd->dest_path)) { + LOGE("download_loader error.\n"); + return -1; + } + + return 0; +} + diff --git a/update_engine/recovery/update_engine/flash_image.h b/update_engine/recovery/update_engine/flash_image.h new file mode 100644 index 0000000..8216035 --- /dev/null +++ b/update_engine/recovery/update_engine/flash_image.h @@ -0,0 +1,31 @@ +/************************************************************************* + > File Name: flash_image.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Tue 21 May 2019 09:29:39 AM CST + ************************************************************************/ + +#ifndef _FLASH_IMAGE_H +#define _FLASH_IMAGE_H +#include "defineHeader.h" + +#pragma pack(1) +typedef struct +{ + char name[20]; + unsigned int offset; + unsigned int size; +}STRUCT_PARAM_ITEM,*PSTRUCT_PARAM_ITEM; + +typedef struct +{ + char name[20]; + char value[256]; +}STRUCT_CONFIG_ITEM,*PSTRUCT_CONFIG_ITEM; +#pragma pack() + +int flash_bootloader(char *dest_path, void *pupdate_cmd); +int flash_parameter(char *dest_path, void *pupdate_cmd); +int flash_normal(char *dest_path, void *pupdate_cmd); +int flash_register_partition_data(PSTRUCT_PARAM_ITEM p_param_item, long long *p_gpt_backup_offset); +#endif diff --git a/update_engine/recovery/update_engine/gpt.h b/update_engine/recovery/update_engine/gpt.h new file mode 100644 index 0000000..e67c571 --- /dev/null +++ b/update_engine/recovery/update_engine/gpt.h @@ -0,0 +1,163 @@ +#ifndef _GPT_H +#define _GPT_H + +#define MSDOS_MBR_SIGNATURE 0xAA55 +#define EFI_PMBR_OSTYPE_EFI 0xEF +#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE + +#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL +#define GPT_HEADER_REVISION_V1 0x00010000 +#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL +#define GPT_ENTRY_NAME "gpt" +#define GPT_ENTRY_NUMBERS 128 +#define GPT_ENTRY_SIZE 128 +#define PART_PROPERTY_BOOTABLE (1 << 2) + +#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ + ((efi_guid_t) \ + {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + +#define PARTITION_IDBLOCK_GUID \ + EFI_GUID(0xDA2BB095, 0x390E, 0x48ca, \ + 0x90, 0x47, 0x05, 0xE8, 0x18, 0xB2, 0x97, 0xCE) + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#define uswap_16(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) +#define uswap_32(x) \ + ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) +#define _uswap_64(x, sfx) \ + ((((x) & 0xff00000000000000##sfx) >> 56) | \ + (((x) & 0x00ff000000000000##sfx) >> 40) | \ + (((x) & 0x0000ff0000000000##sfx) >> 24) | \ + (((x) & 0x000000ff00000000##sfx) >> 8) | \ + (((x) & 0x00000000ff000000##sfx) << 8) | \ + (((x) & 0x0000000000ff0000##sfx) << 24) | \ + (((x) & 0x000000000000ff00##sfx) << 40) | \ + (((x) & 0x00000000000000ff##sfx) << 56)) +#if defined(__GNUC__) +# define uswap_64(x) _uswap_64(x, ull) +#else +# define uswap_64(x) _uswap_64(x, ) +#endif +#define __LITTLE_ENDIAN__ 1 +#ifdef __LITTLE_ENDIAN__ +# define cpu_to_le16(x) (x) +# define cpu_to_le32(x) (x) +# define cpu_to_le64(x) (x) +# define le16_to_cpu(x) (x) +# define le32_to_cpu(x) (x) +# define le64_to_cpu(x) (x) +# define cpu_to_be16(x) uswap_16(x) +# define cpu_to_be32(x) uswap_32(x) +# define cpu_to_be64(x) uswap_64(x) +# define be16_to_cpu(x) uswap_16(x) +# define be32_to_cpu(x) uswap_32(x) +# define be64_to_cpu(x) uswap_64(x) +#else +# define cpu_to_le16(x) uswap_16(x) +# define cpu_to_le32(x) uswap_32(x) +# define cpu_to_le64(x) uswap_64(x) +# define le16_to_cpu(x) uswap_16(x) +# define le32_to_cpu(x) uswap_32(x) +# define le64_to_cpu(x) uswap_64(x) +# define cpu_to_be16(x) (x) +# define cpu_to_be32(x) (x) +# define cpu_to_be64(x) (x) +# define be16_to_cpu(x) (x) +# define be32_to_cpu(x) (x) +# define be64_to_cpu(x) (x) +#endif + + +typedef union { + struct { + unsigned int time_low; + unsigned short time_mid; + unsigned short time_hi_and_version; + unsigned char clock_seq_hi_and_reserved; + unsigned char clock_seq_low; + unsigned char node[6]; + } uuid; + u8 raw[16]; +} efi_guid_t; +#pragma pack(1) +typedef struct { + u16 usTag;/*0xEEEE*/ + u16 usBackupGpt;/*0:no backup,1:has backup*/ + u16 usEntryCount; + u64 entryDataSize[32]; +} gpt_compact_info; +/* based on linux/include/genhd.h */ +typedef struct { + u8 boot_ind; /* 0x80 - active */ + u8 head; /* starting head */ + u8 sector; /* starting sector */ + u8 cyl; /* starting cylinder */ + u8 sys_ind; /* What partition type */ + u8 end_head; /* end head */ + u8 end_sector; /* end sector */ + u8 end_cyl; /* end cylinder */ + u32 start_sect; /* starting sector counting from 0 */ + u32 nr_sects; /* nr of sectors in partition */ +} mbr_partition ; + +/* based on linux/fs/partitions/efi.h */ +typedef struct _gpt_header { + u64 signature; //固定字符串“EFI PART” + u32 revision; //GPT版本号 + u32 header_size; //主GPT头大小 + u32 header_crc32; //主GPT头的CRC32校验数据,注意不是累加和校验 + u32 reserved1; //保留位 + u64 my_lba; //主GPT头起始扇区号,LBA1 + u64 alternate_lba; //主GPT头备份位置扇区号 LBA-1 + u64 first_usable_lba; //GPT分区起始扇区号,LBA34 + u64 last_usable_lba; //GPT分区结束扇区号,LBA-34 + efi_guid_t disk_guid; //磁盘的GUID,唯一标识,这也意味着全硬盘复制是行不通的. + u64 partition_entry_lba; //分区表起始扇区号,LBA2 + u32 num_partition_entries; //分区表项数目,MS强行给128 + u32 sizeof_partition_entry; //每个分区表占用字节数,128 + u32 partition_entry_array_crc32; //分区表CRC校验数据 +} gpt_header; + +typedef union _gpt_entry_attributes { + struct { + u64 required_to_function:1; + u64 no_block_io_protocol:1; + u64 legacy_bios_bootable:1; + u64 reserved:45; + u64 type_guid_specific:16; + } fields; + unsigned long long raw; +} gpt_entry_attributes; + +#define PARTNAME_SZ 72 +typedef struct _gpt_entry { + efi_guid_t partition_type_guid; + efi_guid_t unique_partition_guid; + u64 starting_lba; + u64 ending_lba; + gpt_entry_attributes attributes; + u16 partition_name[PARTNAME_SZ / sizeof(u16)]; +} gpt_entry; + +typedef struct _legacy_mbr { + u8 boot_code[440]; + u32 unique_mbr_signature; + u16 unknown; + mbr_partition partition_record[4]; + u16 signature; +} legacy_mbr; +#pragma pack() +#endif /* _GPT_H */ diff --git a/update_engine/recovery/update_engine/log.cpp b/update_engine/recovery/update_engine/log.cpp new file mode 100644 index 0000000..1428d1a --- /dev/null +++ b/update_engine/recovery/update_engine/log.cpp @@ -0,0 +1,47 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Log - implemented using the standard Android logging mechanism + +/* + * Qutoing from system/core/include/log/log.h: + * Normally we strip ALOGV (VERBOSE messages) from release builds. + * You can modify this (for example with "#define LOG_NDEBUG 0" + * at the top of your source file) to change that behavior. + */ +#ifndef LOG_NDEBUG +#ifdef NDEBUG +#define LOG_NDEBUG 1 +#else +#define LOG_NDEBUG 0 +#endif +#endif + +#define LOG_BUF_SIZE 1024 + +#include "log.h" +#include +#include + + +void InitLogging(int argc, const char* const* argv) {} + +void Log(const char* file, int line, LogPriority level, const char* fmt, ...) { + va_list ap; + char buf[LOG_BUF_SIZE]; + va_start(ap, fmt); + vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); + va_end(ap); + + switch(level) { + case LOG_ERROR: printf("LOG_ERROR : %s\n", buf); break; + case LOG_WARN: printf("LOG_WARN : %s\n", buf); break; + case LOG_INFO: printf("LOG_INFO :%s \n", buf); break; + case LOG_DEBUG: + //#if LOG_NDEBUG + printf("LOG_DEBUG :%s \n", buf); + //#endif + break; + default : + break; + } +} diff --git a/update_engine/recovery/update_engine/log.h b/update_engine/recovery/update_engine/log.h new file mode 100644 index 0000000..226e047 --- /dev/null +++ b/update_engine/recovery/update_engine/log.h @@ -0,0 +1,33 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Log - Platform independent interface for a Logging class +// +#ifndef update_engine_CORE_LOG_H_ +#define update_engine_CORE_LOG_H_ + +// Simple logging class. The implementation is platform dependent. + +typedef enum { + LOG_ERROR, + LOG_WARN, + LOG_INFO, + LOG_DEBUG, + LOG_VERBOSE +} LogPriority; + +// Enable/disable verbose logging (LOGV). +// This function is supplied for cases where the system layer does not +// initialize logging. This is also needed to initialize logging in +// unit tests. +void InitLogging(int argc, const char* const* argv); + +void Log(const char* file, int line, LogPriority level, const char* fmt, ...); + +// Log APIs +#define LOGE(...) Log(__FILE__, __LINE__, LOG_ERROR, __VA_ARGS__) +#define LOGW(...) Log(__FILE__, __LINE__, LOG_WARN, __VA_ARGS__) +#define LOGI(...) Log(__FILE__, __LINE__, LOG_INFO, __VA_ARGS__) +#define LOGD(...) Log(__FILE__, __LINE__, LOG_DEBUG, __VA_ARGS__) +#define LOGV(...) Log(__FILE__, __LINE__, LOG_VERBOSE, __VA_ARGS__) + +#endif // update_engine_CORE_LOG_H_ diff --git a/update_engine/recovery/update_engine/main.cpp b/update_engine/recovery/update_engine/main.cpp new file mode 100644 index 0000000..f02b783 --- /dev/null +++ b/update_engine/recovery/update_engine/main.cpp @@ -0,0 +1,349 @@ +/************************************************************************* + > File Name: main.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Mon 20 May 2019 10:56:06 AM CST + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "update.h" +#include "../bootloader.h" +#include "defineHeader.h" +#include "rktools.h" +#include +#include +#include +#include "download.h" + + +#define DOWNLOAD_VERSION_PATH "/tmp/version" +#define LOCAL_VERSION_PATH "/demo/bin/version" +extern bool is_sdboot; +RK_Upgrade_Status_t m_status = RK_UPGRADE_ERR; +int sleep_time = 30; + +// 回调函数,用于接收HTTP响应数据 +size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { + size_t totalSize = size * nmemb; + std::string *response = static_cast(userp); + response->append(static_cast(contents), totalSize); + return totalSize; +} + +bool _geturlFromfile(const char * filepath,char *url, int maxLength) { + if (filepath == NULL) { + LOGE("getLocalVersion is error, url == null.\n"); + return false; + } + FILE *fp = fopen(filepath, "r"); + if (fp == NULL) { + LOGE("open %s failed, error is %s.\n", filepath, strerror(errno)); + return false; + } + + int iffind=0; + char *line = NULL; + size_t len = 0; + size_t read; + while ((read = getline(&line, &len, fp)) != -1) { + if (read == 0 || line[0] == '#') { + continue; + } + char *pline = strstr(line, "RK_url"); + if (pline != NULL && (pline = strstr(pline, "=")) != NULL) { + pline++; //过滤掉等于号 + //过滤掉空格 + while (*pline == ' ') { + pline++; + } + int pline_len = strlen(pline) - 1; + int version_len = (pline_len > maxLength ? maxLength:pline_len); + memcpy(url, pline, version_len); + LOGI("dwon_url = %s\n", url); + iffind=1; + break; + } + + } + if (iffind == 0 ){ + printf("Can not find RK_url\n"); + return false; + } + free(line); + fclose(fp); + return true; +} + +bool _check_version(char **image_url){ + char local_version[20] = {0}; + char download_version[20] = {0}; + char download_url[255] = {0}; + getVersionFromfile(DOWNLOAD_VERSION_PATH, download_version, sizeof(download_version)); + getVersionFromfile(LOCAL_VERSION_PATH, local_version, sizeof(local_version)); + LOGI("check version new:%s old:%s", download_version, local_version); + if (strcmp(download_version, local_version) > 0) { + printf("check version OK!\n"); + if(_geturlFromfile(DOWNLOAD_VERSION_PATH,download_url,sizeof(download_url))){ + *image_url = download_url; + return true; + } + }else{ + printf("check version: no need to update\n"); + } + return false; +} + +void handle_upgrade_callback(void *user_data, RK_Upgrade_Status_t status){ + if (status == RK_UPGRADE_FINISHED) { + LOGI("rk ota success.\n"); + setSlotActivity(); + } + m_status = status; + LOGI("rk m_status = %d.\n", m_status); +} + + + +static int MiscUpdate(char *url, char *update_partition, char *save_path) { + int partition; + char *savepath = NULL; + int slot = -1; + if (url == NULL) { + //如果没有传入URL,则可以去查找是否有存在 + LOGE("MiscUpdate URL must be set.\n"); + return -1; + } + slot = getCurrentSlot(); + if (update_partition == NULL) { + //没有传入要升级的分区,默认升级 + if (slot == -1){ + // recovery mdoe + // u-boot/trust/boot/recovery/boot/rootfs/oem + partition = 0X3F0000; + } else { + // A/B mdoe + // uboot_a/uboot_b/boot_a/boot_b/system_a/system_b + partition = 0XFC00; + } + } else { + partition = strtol(update_partition+2, NULL, 16); + } + + if (save_path == NULL) { + savepath = url; + } else { + savepath = save_path; + } + + RK_ota_set_url(url, savepath); + LOGI("url = %s.\n", url); + LOGI("[%s:%d] save path: %s\n", __func__, __LINE__, savepath); + // If it's recovery mode, upgrade recovery in normal system. + if (slot == -1 && !is_sdboot){ + if (partition & 0x040000) { + LOGI("update recovery in normal system.\n"); + partition = partition & 0xFBFFFF; + + // upgrade recoery in normal system + if (!RK_ota_set_partition(0x040000)) { + LOGE("ota file is error.\n"); + return -1; + } + RK_ota_start(handle_upgrade_callback); + if (m_status != RK_UPGRADE_FINISHED) { + return -1; + } + + //写MISC + struct bootloader_message msg; + memset(&msg, 0, sizeof(msg)); + char recovery_str[] = "recovery\n--update_package="; + strcpy(msg.command, "boot-recovery"); + sprintf(msg.recovery, "%s%s", recovery_str, savepath); + msg.recovery[strlen(msg.recovery) + 1] = '\n'; + memcpy(msg.needupdate, &partition, 6); + set_bootloader_message(&msg); + return 0; + } + } else if (slot == 0) { + LOGI("In A system, now upgrade B system.\n"); + partition = partition & 0x155ff; + } else if (slot == 1) { + LOGI("In B system, now upgrade A system.\n"); + partition = partition & 0x1a9ff; + } + + if (!RK_ota_set_partition(partition)) { + LOGE("ota file is error.\n"); + return -1; + } + RK_ota_start(handle_upgrade_callback); + if (m_status != RK_UPGRADE_FINISHED) { + return -1; + } + + return 0; +} + +void display() { + LOGI("--misc=now Linux A/B mode: Setting the current partition to bootable.\n"); + LOGI("--misc=other Linux A/B mode: Setting another partition to bootable.\n"); + LOGI("--misc=update Recovery mode: Setting the partition to be upgraded.\n"); + LOGI("--misc=display Display misc info.\n"); + LOGI("--misc=wipe_userdata Format data partition.\n"); + LOGI("--update Upgrade mode.\n"); + LOGI("--partition=0x3FFC00 Set the partition to be upgraded.(NOTICE: OTA not support upgrade loader and parameter)\n"); + LOGI(" 0x3FFC00: 0011 1111 1111 1100 0000 0000.\n"); + LOGI(" uboot trust boot recovery rootfs oem\n"); + LOGI(" uboot_a uboot_b boot_a boot_b system_a system_b.\n"); + LOGI(" 100000000000000000000000: Upgrade loader\n"); + LOGI(" 010000000000000000000000: Upgrade parameter\n"); + LOGI(" 001000000000000000000000: Upgrade uboot\n"); + LOGI(" 000100000000000000000000: Upgrade trust\n"); + LOGI(" 000010000000000000000000: Upgrade boot\n"); + LOGI(" 000001000000000000000000: Upgrade recovery\n"); + LOGI(" 000000100000000000000000: Upgrade rootfs\n"); + LOGI(" 000000010000000000000000: Upgrade oem\n"); + LOGI(" 000000001000000000000000: Upgrade uboot_a\n"); + LOGI(" 000000000100000000000000: Upgrade uboot_b\n"); + LOGI(" 000000000010000000000000: Upgrade boot_a\n"); + LOGI(" 000000000001000000000000: Upgrade boot_b\n"); + LOGI(" 000000000000100000000000: Upgrade system_a\n"); + LOGI(" 000000000000010000000000: Upgrade system_b\n"); + LOGI(" 000000000000001000000000: Upgrade misc\n"); + LOGI(" 000000000000000100000000: Upgrade userdata\n"); + LOGI("--reboot Restart the machine at the end of the program.\n"); + LOGI("--version_url=url The path to the file of version.\n"); + LOGI("--image_url=url Path to upgrade firmware.\n"); + LOGI("--savepath=url save the update.img to url.\n"); + +} + +static const struct option engine_options[] = { + { "update", optional_argument, NULL, 'u' }, + { "version_url", required_argument, NULL, 'v' + 'u' }, + { "image_url", required_argument, NULL, 'i' + 'u'}, + { "check", required_argument, NULL, 'c' }, + { "misc", required_argument, NULL, 'm' }, + { "partition", required_argument, NULL, 'p' }, + { "reboot", no_argument, NULL, 'r' }, + { "help", no_argument, NULL, 'h' }, + { "pipefd", required_argument, NULL, 'p' + 'f' }, + { "savepath", required_argument, NULL, 's'}, + { "checkupdate_url", required_argument, NULL, 'c'+'u'}, + { NULL, 0, NULL, 0 }, +}; + +int main(int argc, char *argv[]) { + LOGI("*** update_engine: Version V1.1.4 ***.\n"); + int arg; + char *image_url = NULL; + char *version_url = NULL; + char *misc_func = NULL; + char *save_path = NULL; + char *partition = NULL; + char *checkupdate_url = NULL; + bool is_update = false; + bool is_reboot = false; + int pipefd = -1; + int res = 0; + + while ((arg = getopt_long(argc, argv, "", engine_options, NULL)) != -1) { + switch (arg) { + case 'u': is_update = true; if(optarg != NULL) is_sdboot = true; continue; + case 'c': version_url = optarg; continue; + case 'm': misc_func = optarg; continue; + case 'p': partition = optarg; continue; + case 's': save_path = optarg; continue; + case 'r': is_reboot = true; continue; + case 'v' + 'u': version_url = optarg; continue; + case 'i' + 'u': image_url = optarg; continue; + case 'p' + 'f': pipefd = atoi(optarg); continue; + case 'c' + 'u': checkupdate_url = optarg; continue; + case 'h': display(); break; + case '?': + LOGE("Invalid command argument\n"); + continue; + } + } + while(true){ + char *image_url = NULL; + + res = download_file(version_url,DOWNLOAD_VERSION_PATH); + if(res != 0){ + sleep(sleep_time); + continue; + } + + if(_check_version(&image_url)){ + printf("check version ok and get download_url!\n"); + if (is_update) { + if (is_sdboot) { + int res = 0x3FFC00; //默认升级的分区 + LOGI("%s-%d: is sdboot update.\n", __func__, __LINE__); + if (partition != NULL) { + res = strtol(partition+2, NULL, 16); + } + RK_ota_set_url(image_url, save_path); + if ( !RK_ota_set_partition(res) ){ + LOGE("ota file is error.\n"); + return -1; + } + + if (version_url != NULL) { + if (!RK_ota_check_version(version_url) ){ + LOGE("you shouldn't update the device.\n"); + return -1; + } + } + + RK_ota_start(handle_upgrade_callback); + } else { + LOGI("%s-%d: is ota update\n", __func__, __LINE__); + if (MiscUpdate(image_url, partition, save_path) == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } + }else if (misc_func != NULL) { + if (strcmp(misc_func, "now") == 0) { + if (setSlotSucceed() ==0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "other") == 0) { + if (setSlotActivity() == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "wipe_userdata") == 0) { + if (wipe_userdata(0) == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "update") == 0) { + + if (MiscUpdate(image_url, partition, save_path) == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "display") == 0) { + miscDisplay(); + } else { + LOGE("unknow misc cmdline : %s.\n", misc_func); + return 0; + } + } + + if (is_reboot && (m_status == RK_UPGRADE_FINISHED)) { + sync(); + //reboot(RB_AUTOBOOT); + system(" echo b > /proc/sysrq-trigger "); + } + } + + sleep(sleep_time); + } + return m_status; +} diff --git a/update_engine/recovery/update_engine/main备份10.26.cpp b/update_engine/recovery/update_engine/main备份10.26.cpp new file mode 100644 index 0000000..3f1f2d9 --- /dev/null +++ b/update_engine/recovery/update_engine/main备份10.26.cpp @@ -0,0 +1,341 @@ +/************************************************************************* + > File Name: main.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Mon 20 May 2019 10:56:06 AM CST + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "update.h" +#include "../bootloader.h" +#include "defineHeader.h" +#include "rktools.h" +#include +#include +#include +#include + +extern bool is_sdboot; +RK_Upgrade_Status_t m_status = RK_UPGRADE_ERR; +int sleep_time = 30; + +// 回调函数,用于接收HTTP响应数据 +size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { + size_t totalSize = size * nmemb; + std::string *response = static_cast(userp); + response->append(static_cast(contents), totalSize); + return totalSize; +} + +void handle_upgrade_callback(void *user_data, RK_Upgrade_Status_t status){ + if (status == RK_UPGRADE_FINISHED) { + LOGI("rk ota success.\n"); + setSlotActivity(); + } + m_status = status; + LOGI("rk m_status = %d.\n", m_status); +} + + + +static int MiscUpdate(char *url, char *update_partition, char *save_path) { + int partition; + char *savepath = NULL; + int slot = -1; + if (url == NULL) { + //如果没有传入URL,则可以去查找是否有存在 + LOGE("MiscUpdate URL must be set.\n"); + return -1; + } + slot = getCurrentSlot(); + if (update_partition == NULL) { + //没有传入要升级的分区,默认升级 + if (slot == -1){ + // recovery mdoe + // u-boot/trust/boot/recovery/boot/rootfs/oem + partition = 0X3F0000; + } else { + // A/B mdoe + // uboot_a/uboot_b/boot_a/boot_b/system_a/system_b + partition = 0XFC00; + } + } else { + partition = strtol(update_partition+2, NULL, 16); + } + + if (save_path == NULL) { + savepath = url; + } else { + savepath = save_path; + } + + RK_ota_set_url(url, savepath); + LOGI("url = %s.\n", url); + LOGI("[%s:%d] save path: %s\n", __func__, __LINE__, savepath); + // If it's recovery mode, upgrade recovery in normal system. + if (slot == -1 && !is_sdboot){ + if (partition & 0x040000) { + LOGI("update recovery in normal system.\n"); + partition = partition & 0xFBFFFF; + + // upgrade recoery in normal system + if (!RK_ota_set_partition(0x040000)) { + LOGE("ota file is error.\n"); + return -1; + } + RK_ota_start(handle_upgrade_callback); + if (m_status != RK_UPGRADE_FINISHED) { + return -1; + } + + //写MISC + struct bootloader_message msg; + memset(&msg, 0, sizeof(msg)); + char recovery_str[] = "recovery\n--update_package="; + strcpy(msg.command, "boot-recovery"); + sprintf(msg.recovery, "%s%s", recovery_str, savepath); + msg.recovery[strlen(msg.recovery) + 1] = '\n'; + memcpy(msg.needupdate, &partition, 6); + set_bootloader_message(&msg); + return 0; + } + } else if (slot == 0) { + LOGI("In A system, now upgrade B system.\n"); + partition = partition & 0x155ff; + } else if (slot == 1) { + LOGI("In B system, now upgrade A system.\n"); + partition = partition & 0x1a9ff; + } + + if (!RK_ota_set_partition(partition)) { + LOGE("ota file is error.\n"); + return -1; + } + RK_ota_start(handle_upgrade_callback); + if (m_status != RK_UPGRADE_FINISHED) { + return -1; + } + + return 0; +} + +void display() { + LOGI("--misc=now Linux A/B mode: Setting the current partition to bootable.\n"); + LOGI("--misc=other Linux A/B mode: Setting another partition to bootable.\n"); + LOGI("--misc=update Recovery mode: Setting the partition to be upgraded.\n"); + LOGI("--misc=display Display misc info.\n"); + LOGI("--misc=wipe_userdata Format data partition.\n"); + LOGI("--update Upgrade mode.\n"); + LOGI("--partition=0x3FFC00 Set the partition to be upgraded.(NOTICE: OTA not support upgrade loader and parameter)\n"); + LOGI(" 0x3FFC00: 0011 1111 1111 1100 0000 0000.\n"); + LOGI(" uboot trust boot recovery rootfs oem\n"); + LOGI(" uboot_a uboot_b boot_a boot_b system_a system_b.\n"); + LOGI(" 100000000000000000000000: Upgrade loader\n"); + LOGI(" 010000000000000000000000: Upgrade parameter\n"); + LOGI(" 001000000000000000000000: Upgrade uboot\n"); + LOGI(" 000100000000000000000000: Upgrade trust\n"); + LOGI(" 000010000000000000000000: Upgrade boot\n"); + LOGI(" 000001000000000000000000: Upgrade recovery\n"); + LOGI(" 000000100000000000000000: Upgrade rootfs\n"); + LOGI(" 000000010000000000000000: Upgrade oem\n"); + LOGI(" 000000001000000000000000: Upgrade uboot_a\n"); + LOGI(" 000000000100000000000000: Upgrade uboot_b\n"); + LOGI(" 000000000010000000000000: Upgrade boot_a\n"); + LOGI(" 000000000001000000000000: Upgrade boot_b\n"); + LOGI(" 000000000000100000000000: Upgrade system_a\n"); + LOGI(" 000000000000010000000000: Upgrade system_b\n"); + LOGI(" 000000000000001000000000: Upgrade misc\n"); + LOGI(" 000000000000000100000000: Upgrade userdata\n"); + LOGI("--reboot Restart the machine at the end of the program.\n"); + LOGI("--version_url=url The path to the file of version.\n"); + LOGI("--image_url=url Path to upgrade firmware.\n"); + LOGI("--savepath=url save the update.img to url.\n"); + +} + +static const struct option engine_options[] = { + { "update", optional_argument, NULL, 'u' }, + { "version_url", required_argument, NULL, 'v' + 'u' }, + { "image_url", required_argument, NULL, 'i' + 'u'}, + { "check", required_argument, NULL, 'c' }, + { "misc", required_argument, NULL, 'm' }, + { "partition", required_argument, NULL, 'p' }, + { "reboot", no_argument, NULL, 'r' }, + { "help", no_argument, NULL, 'h' }, + { "pipefd", required_argument, NULL, 'p' + 'f' }, + { "savepath", required_argument, NULL, 's'}, + { "checkupdate_url", required_argument, NULL, 'c'+'u'}, + { NULL, 0, NULL, 0 }, +}; + +int main(int argc, char *argv[]) { + LOGI("*** update_engine: Version V1.1.4 ***.\n"); + int arg; + char *image_url = NULL; + char *version_url = NULL; + char *misc_func = NULL; + char *save_path = NULL; + char *partition = NULL; + char *checkupdate_url = NULL; + bool is_update = false; + bool is_reboot = false; + int pipefd = -1; + + while ((arg = getopt_long(argc, argv, "", engine_options, NULL)) != -1) { + switch (arg) { + case 'u': is_update = true; if(optarg != NULL) is_sdboot = true; continue; + case 'c': version_url = optarg; continue; + case 'm': misc_func = optarg; continue; + case 'p': partition = optarg; continue; + case 's': save_path = optarg; continue; + case 'r': is_reboot = true; continue; + case 'v' + 'u': version_url = optarg; continue; + case 'i' + 'u': image_url = optarg; continue; + case 'p' + 'f': pipefd = atoi(optarg); continue; + case 'c' + 'u': checkupdate_url = optarg; continue; + case 'h': display(); break; + case '?': + LOGE("Invalid command argument\n"); + continue; + } + } + while(true){ + int Isupdate=0; + // 初始化libcurl + CURL *curl = curl_easy_init(); + if (!curl) { + std::cerr << "Failed to initialize libcurl." << std::endl; + sleep(sleep_time); + continue; + } + + // 设置服务器URL + const char *url = checkupdate_url; + + // 设置HTTP GET请求 + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); + + // 创建一个字符串来存储响应数据 + std::string response_data; + + // 设置回调函数来接收响应数据 + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data); + + // 执行HTTP GET请求 + CURLcode res = curl_easy_perform(curl); + + if (res == CURLE_OK) { + // HTTP请求成功 + std::cout << "Server response: " << response_data << std::endl; + + // 解析服务器响应 + json_object *root_obj = json_tokener_parse(response_data.c_str()); + if (root_obj) { + // 检查是否需要升级 + json_object *upgrade_obj; + if (json_object_object_get_ex(root_obj, "upgrade", &upgrade_obj)) { + if (json_object_is_type(upgrade_obj, json_type_boolean)) { + bool upgrade_required = json_object_get_boolean(upgrade_obj); + if (upgrade_required) { + // 执行升级操作 + std::cout << "Upgrade is required. Performing upgrade..." << std::endl; + Isupdate = 1; + } else { + // 不需要升级,执行其他操作 + std::cout << "No upgrade required. Performing other operations..." << std::endl; + // 在这里执行其他操作的代码 + } + } + } else { + std::cerr << "Invalid server response format." << std::endl; + } + json_object_put(root_obj); // 释放json-c对象 + } else { + std::cerr << "Failed to parse server response." << std::endl; + } + + } else { + // HTTP请求失败 + std::cerr << "Failed to perform HTTP request: " << curl_easy_strerror(res) << std::endl; + } + + // 清理并释放libcurl资源 + curl_easy_cleanup(curl); + if(Isupdate){ + if (is_update) { + if (is_sdboot) { + int res = 0x3FFC00; //默认升级的分区 + LOGI("%s-%d: is sdboot update.\n", __func__, __LINE__); + if (partition != NULL) { + res = strtol(partition+2, NULL, 16); + } + RK_ota_set_url(image_url, save_path); + if ( !RK_ota_set_partition(res) ){ + LOGE("ota file is error.\n"); + return -1; + } + + if (version_url != NULL) { + if (!RK_ota_check_version(version_url) ){ + LOGE("you shouldn't update the device.\n"); + return -1; + } + } + + RK_ota_start(handle_upgrade_callback); + } else { + LOGI("%s-%d: is ota update\n", __func__, __LINE__); + if (MiscUpdate(image_url, partition, save_path) == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } + }else if (misc_func != NULL) { + if (strcmp(misc_func, "now") == 0) { + if (setSlotSucceed() ==0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "other") == 0) { + if (setSlotActivity() == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "wipe_userdata") == 0) { + if (wipe_userdata(0) == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "update") == 0) { + if (version_url != NULL) { + if (!RK_ota_check_version(version_url) ){ + LOGE("you shouldn't update the device.\n"); + sleep(sleep_time); + continue; + } + } + if (MiscUpdate(image_url, partition, save_path) == 0) { + m_status = RK_UPGRADE_FINISHED; + } + } else if (strcmp(misc_func, "display") == 0) { + miscDisplay(); + } else { + LOGE("unknow misc cmdline : %s.\n", misc_func); + return 0; + } + } + + if (is_reboot && (m_status == RK_UPGRADE_FINISHED)) { + sync(); + //reboot(RB_AUTOBOOT); + system(" echo b > /proc/sysrq-trigger "); + } + } + sleep(sleep_time); + } + return m_status; +} diff --git a/update_engine/recovery/update_engine/md5sum.cpp b/update_engine/recovery/update_engine/md5sum.cpp new file mode 100644 index 0000000..0e7d0c3 --- /dev/null +++ b/update_engine/recovery/update_engine/md5sum.cpp @@ -0,0 +1,191 @@ +/************************************************************************* + > File Name: md5sum.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Thu 07 Mar 2019 03:06:21 PM CST + ************************************************************************/ + +#include +#include +#include +#include +#include + #include +#include +#include +#include +#include "log.h" +#include "rktools.h" +extern "C" { + #include "../mtdutils/mtdutils.h" +} + +#define TMP_MD5SUM_NAME "/tmp/.tmp_md5sum" + +bool checkdata_mtd(const char *dest_path, unsigned char* out_md5sum, long long offset, long long checkSize) { + + char nanddump_cmd[256] = {0}; + unsigned char buf[33] = {0}; + unsigned char md5sum[16]; + + LOGI( "[%s:%d] offset [%lld] checksize [%lld] \n", __func__, __LINE__, offset, checkSize ); + + memset(nanddump_cmd, 0, sizeof(nanddump_cmd)/sizeof(nanddump_cmd[0])); + sprintf(nanddump_cmd, "nanddump --bb=skipbad -l %lld -s %lld %s | md5sum > %s", + checkSize, offset, dest_path, TMP_MD5SUM_NAME); + system(nanddump_cmd); + + int dest_fd = open(TMP_MD5SUM_NAME, O_RDONLY ); + if(dest_fd == NULL){ + LOGE("open file failed %s", TMP_MD5SUM_NAME); + return -1; + } + + if (read(dest_fd, buf, 32) == -1) { + close(dest_fd); + LOGE("(%s:%d) read error: %s.\n", __func__, __LINE__, strerror(errno)); + return -2; + } + + printf("\n"); + buf[32] = '\0'; + printf("read new md5: [%s]\n", buf); + + unsigned char md5sum_tmp[32]; + for ( int ii=0; ii<32; ii+=2) { + sscanf((char *)(buf + ii), "%02hhx", &md5sum_tmp[ii]); + } + + for ( int ii=0, j=0; ii<32; ii+=2 ) { + // printf ( "%d = %02x\n", ii, md5sum_tmp[ii] ); + md5sum[j] = md5sum_tmp[ii]; + j++; + } + + printf("new md5:"); + for(int i = 0; i < 16; i++){ + printf("%02x", md5sum[i]); + } + printf("\n"); + //change + if(out_md5sum != NULL){ + memset(out_md5sum, 0, 16); + memcpy(out_md5sum, md5sum, 16); + } + + close(dest_fd); + LOGI("MD5Check is ok of %s\n", dest_path); + return 0; +} + +bool checkdata(const char *dest_path, unsigned char *out_md5sum, long long offset, long long checkSize){ + MD5_CTX ctx; + unsigned char md5sum[16]; + char buffer[512]; + int len = 0; + int ret; + + FILE *fp = fopen(dest_path, "rb"); + if(fp == NULL){ + LOGE("open file failed %s", dest_path); + return -1; + } + + ret = fseeko64(fp, offset, SEEK_SET); + if (ret < 0) + { + LOGE("%s:%d fseeko64 fail", __func__, __LINE__); + return false; + } + + MD5_Init(&ctx); + + long long readSize = 0; + int step = 512; + while(checkSize > 0){ + readSize = checkSize > step ? step: checkSize; + if(fread(buffer, 1, readSize, fp) != readSize){ + LOGE("fread error.\n"); + return false; + } + checkSize = checkSize - readSize; + MD5_Update(&ctx, buffer, readSize); + memset(buffer, 0, sizeof(buffer)); + } + MD5_Final(md5sum, &ctx); + fclose(fp); + + printf("\n"); + printf("new md5:"); + for(int i = 0; i < 16; i++){ + printf("%02x", md5sum[i]); + } + printf("\n"); + //change + if(out_md5sum != NULL){ + memset(out_md5sum, 0, 16); + memcpy(out_md5sum, md5sum, 16); + } + LOGI("MD5Check is ok of %s\n", dest_path); + return 0; +} + +bool comparefile(const char *dest_path, const char *source_path, long long dest_offset, long long source_offset, long long checkSize){ + unsigned char md5sum_source[16]; + unsigned char md5sum_dest[16]; + if (isMtdDevice()) { + checkdata_mtd(dest_path, md5sum_dest, dest_offset, checkSize); + } else { + checkdata(dest_path, md5sum_dest, dest_offset, checkSize); + } + checkdata(source_path, md5sum_source, source_offset, checkSize); + for(int i = 0; i < 16; i++){ + if(md5sum_dest[i] != md5sum_source[i]){ + LOGE("MD5Check is error of %s", dest_path); + return false; + } + } + return true; +} + +bool compareMd5sum(const char *dest_path, unsigned char *source_md5sum, long long offset, long long checkSize){ + unsigned char md5sum[16]; + + checkdata(dest_path, md5sum, offset, checkSize); + + unsigned char tmp[16][2] = { + 0x30, 0x00, + 0x31, 0x01, + 0x32, 0x02, + 0x33, 0x03, + 0x34, 0x04, + 0x35, 0x05, + 0x36, 0x06, + 0x37, 0x07, + 0x38, 0x08, + 0x39, 0x09, + 0x61, 0x0a, + 0x62, 0x0b, + 0x63, 0x0c, + 0x64, 0x0d, + 0x65, 0x0e, + 0x66, 0x0f, + }; + for(int i = 0; i < 32; i = i+2){ + for(int j = 0; j < 16; j++){ + if(tmp[j][1] == (md5sum[i/2] >> 4)){ + if(source_md5sum[i] != tmp[j][0]){ + LOGE("MD5Check is error of %s", dest_path); + return false; + } + } + if(tmp[j][1] == (md5sum[i/2] & 0x0f)){ + if(source_md5sum[i+1] != tmp[j][0]){ + LOGE("MD5Check is error of %s", dest_path); + return false; + } + } + } + } + return true; +} diff --git a/update_engine/recovery/update_engine/md5sum.h b/update_engine/recovery/update_engine/md5sum.h new file mode 100644 index 0000000..63301c5 --- /dev/null +++ b/update_engine/recovery/update_engine/md5sum.h @@ -0,0 +1,12 @@ +/************************************************************************* + > File Name: md5sum.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Thu 07 Mar 2019 03:14:08 PM CST + ************************************************************************/ + +#ifndef _MD5SUM_H +#define _MD5SUM_H +bool comparefile(const char *dest_path, const char *source_path, long long dest_offset, long long source_offset, long long checkSize); +bool compareMd5sum(const char *dest_path, unsigned char *source_md5sum, long long offset, long long checkSize); +#endif diff --git a/update_engine/recovery/update_engine/rkboot.cpp b/update_engine/recovery/update_engine/rkboot.cpp new file mode 100644 index 0000000..7883f7d --- /dev/null +++ b/update_engine/recovery/update_engine/rkboot.cpp @@ -0,0 +1,399 @@ +/************************************************************************* + > File Name: rkboot.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Mon 03 Jun 2019 03:46:18 PM CST + ************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include "rkimage.h" +#include "log.h" +#include "rktools.h" +#include "crc.h" +extern "C" { + #include "../mtdutils/mtdutils.h" +} + +USHORT m_usFlashDataSec; +USHORT m_usFlashBootSec; +DWORD m_dwLoaderSize; +DWORD m_dwLoaderDataSize; +DWORD uiSecNumPerIDB; +size_t uiFlashPageSize; +size_t uiFlashBlockSize; +USHORT usPhyBlokcPerIDB; +bool m_bRc4Disable; +DWORD m_idBlockOffset[IDB_BLOCKS]; + +long long m_FlashSize; +long long m_FlasBlockNum; +PSTRUCT_RKBOOT_HEAD pBootHead; + + +static bool CheckUid(BYTE uidSize,BYTE *pUid) +{ + if (uidSize!=RKDEVICE_UID_LEN) + { + return false; + } + USHORT oldCrc,newCrc; + oldCrc = *(USHORT *)(pUid+RKDEVICE_UID_LEN-2); + newCrc = CRC_CCITT(pUid,RKDEVICE_UID_LEN-2); + if (oldCrc!=newCrc) + { + return false; + } + return true; +} + +static USHORT UshortToBCD(USHORT num) { + USHORT bcd = 0; + bcd = (num % 10) | ( ((num/10 )% 10)<< 4 )|( ((num/100) %10) << 8)|( ((num/1000) %10) << 12); + return bcd; +} +static BYTE ByteToBCD(BYTE num) +{ + BYTE bcd = 0; + bcd = (num % 10) | ( ((num/10 )% 10)<< 4 ); + return bcd; +} + +static void WCHAR_To_char(WCHAR *src, char *dst, int len) { + memset(dst, 0, len*sizeof(char)); + for (int i = 0; i < len; i++) { + memcpy(dst, src, 1); + src++; + dst++; + } +} + +static DWORD getLoaderSizeAndData(char * loaderName, const unsigned char * data_buf, unsigned char **loaderBuffer) { + + DWORD dwOffset; + UCHAR ucCount, ucSize; + DWORD dwSize = 0; + + dwOffset = pBootHead->dwLoaderEntryOffset; + ucCount = pBootHead->ucLoaderEntryCount; + ucSize = pBootHead->ucLoaderEntrySize; + for(UCHAR i = 0; i < ucCount; i++) + { + PSTRUCT_RKBOOT_ENTRY pEntry; + pEntry = (PSTRUCT_RKBOOT_ENTRY)(data_buf+dwOffset+(ucSize*i)); + + char szName[20]; + WCHAR_To_char(pEntry->szName, szName, 20); + if (strcmp(loaderName, szName) == 0) + { + LOGI("pEntry->szName = %s.\n", szName); + dwSize = pEntry->dwDataSize; + *loaderBuffer = (unsigned char *)malloc(dwSize); + if (*loaderBuffer == NULL) { + LOGE("malloc error.\n"); + } + memset(*loaderBuffer, 0, dwSize); + memcpy(*loaderBuffer, data_buf+pEntry->dwDataOffset, pEntry->dwDataSize); + LOGI("pEntry->dwDataOffset = %d, pEntry->dwDataSize = %d.\n", pEntry->dwDataOffset, pEntry->dwDataSize); + + } + } + return dwSize; +} + +static CHAR FindValidBlocks(char bBegin, char bLen, PBYTE pblockState) +{ + char bCount = 0; + char bIndex = bBegin; + while(bBegin < IDBLOCK_TOP) + { + //if(0 == m_flashInfo.blockState[bBegin++]) + if (0 == pblockState[bBegin++]) + ++bCount; + else + { + bCount = 0; + bIndex = bBegin; + } + if(bCount >= bLen) + break; + } + if(bBegin >= IDBLOCK_TOP) + bIndex = -1; + + return bIndex; +} + +static bool MakeSector0(PBYTE pSector) +{ + PRKANDROID_IDB_SEC0 pSec0; + memset(pSector, 0, SECTOR_SIZE); + pSec0 = (PRKANDROID_IDB_SEC0)pSector; + + pSec0->dwTag = 0x0FF0AA55; + if (m_bRc4Disable) + { + pSec0->uiRc4Flag = 1; + } + pSec0->usBootCode1Offset = 0x4; + pSec0->usBootCode2Offset = 0x4; + pSec0->usBootDataSize = m_usFlashDataSec; + pSec0->usBootCodeSize = m_usFlashDataSec + m_usFlashBootSec; + return true; +} + +static void MakeSector1(PBYTE pSector) +{ + PRKANDROID_IDB_SEC1 pSec1; + memset(pSector,0,SECTOR_SIZE); + pSec1 = (PRKANDROID_IDB_SEC1)pSector; + USHORT usSysReserved; + if ((m_idBlockOffset[4]+1)%12==0) + { + usSysReserved=m_idBlockOffset[4]+13; + } + else + { + usSysReserved =((m_idBlockOffset[4]+1)/12+1)*12; + } + if (usSysReserved>IDBLOCK_TOP) + { + usSysReserved = IDBLOCK_TOP; + } + pSec1->usSysReservedBlock = usSysReserved; + + + pSec1->usDisk0Size = 0; + pSec1->usDisk1Size = 0; + pSec1->usDisk2Size = 0; + pSec1->usDisk3Size = 0; + pSec1->uiChipTag = 0x38324B52; + pSec1->uiMachineId = 0; + + pSec1->usLoaderYear = UshortToBCD(pBootHead->stReleaseTime.usYear); + pSec1->usLoaderDate = ByteToBCD(pBootHead->stReleaseTime.ucMonth); + pSec1->usLoaderDate = (pSec1->usLoaderDate<<8)|ByteToBCD(pBootHead->stReleaseTime.ucDay); + pSec1->usLoaderVer = pBootHead->dwVersion; + + pSec1->usLastLoaderVer = 0; + pSec1->usReadWriteTimes = 1; + + pSec1->uiFlashSize = m_FlashSize*1024; + LOGI("m_FlashSize * 1024 = %lld.\n", m_FlashSize*1024); + //pSec1->usBlockSize = m_flashInfo.usBlockSize*2; + //pSec1->bPageSize = m_flashInfo.uiPageSize*2; + //pSec1->bECCBits = m_flashInfo.bECCBits; + //pSec1->bAccessTime = m_flashInfo.bAccessTime; + + pSec1->usFlashInfoLen = 0; + pSec1->usFlashInfoOffset = 0; + + + pSec1->usIdBlock0 = m_idBlockOffset[0]; + pSec1->usIdBlock1 = m_idBlockOffset[1]; + pSec1->usIdBlock2 = m_idBlockOffset[2]; + pSec1->usIdBlock3 = m_idBlockOffset[3]; + pSec1->usIdBlock4 = m_idBlockOffset[4]; +} + +static bool MakeSector2(PBYTE pSector) +{ + PRKANDROID_IDB_SEC2 pSec2; + pSec2 = (PRKANDROID_IDB_SEC2)pSector; + + pSec2->usInfoSize = 0; + memset(pSec2->bChipInfo,0,CHIPINFO_LEN); + + memset(pSec2->reserved,0,RKANDROID_SEC2_RESERVED_LEN); + pSec2->usSec3CustomDataOffset = 0;//debug + pSec2->usSec3CustomDataSize = 0;//debug + + strcpy(pSec2->szVcTag,"VC"); + strcpy(pSec2->szCrcTag,"CRC"); + return true; +} +static bool MakeSector3(PBYTE pSector) +{ + PRKANDROID_IDB_SEC3 pSec3; + memset(pSector,0,SECTOR_SIZE); + pSec3 = (PRKANDROID_IDB_SEC3)pSector; + return true; +} + +static int MakeIDBlockData(PBYTE lpIDBlock, PBYTE loaderCodeBuffer, PBYTE loaderDataBuffer) { + + RKANDROID_IDB_SEC0 sector0Info; + RKANDROID_IDB_SEC1 sector1Info; + RKANDROID_IDB_SEC2 sector2Info; + RKANDROID_IDB_SEC3 sector3Info; + + MakeSector0((PBYTE)§or0Info); + MakeSector1((PBYTE)§or1Info); + if (!MakeSector2((PBYTE)§or2Info)) + { + return -6; + } + + if (!MakeSector3((PBYTE)§or3Info)) + { + return -7; + } + + sector2Info.usSec0Crc = CRC_16((PBYTE)§or0Info,SECTOR_SIZE); + sector2Info.usSec1Crc = CRC_16((PBYTE)§or1Info,SECTOR_SIZE); + sector2Info.usSec3Crc = CRC_16((PBYTE)§or3Info,SECTOR_SIZE); + memcpy(lpIDBlock, §or0Info, SECTOR_SIZE); + memcpy(lpIDBlock+SECTOR_SIZE, §or1Info, SECTOR_SIZE); + memcpy(lpIDBlock+SECTOR_SIZE*3, §or3Info, SECTOR_SIZE); + + //close rc4 encryption + if (sector0Info.uiRc4Flag) { + for (int i=0;i 0)?((uiSecNumPerIDB - 1) / 8 + 1):(uiSecNumPerIDB)); + LOGI("usPhyBlokcPerIDB = %d.\n", usPhyBlokcPerIDB); +} + +static int reserveIDBlock() { + // 3. ReserveIDBlock + CHAR iRet; + char iBlockIndex = 0; + + BYTE blockState[IDBLOCK_TOP]; + memset(m_idBlockOffset, 0, sizeof(DWORD)*IDB_BLOCKS); + memset(blockState, 0, IDBLOCK_TOP); + for (char i = 0; i < IDB_BLOCKS; i++) { + iRet = iBlockIndex = FindValidBlocks(iBlockIndex, usPhyBlokcPerIDB, blockState); + if (iRet < 0 ) { + return -1; + LOGE("FindValidBlocks Error.\n"); + } + m_idBlockOffset[i] = iBlockIndex; + iBlockIndex += usPhyBlokcPerIDB; + } + + return 0; +} + +static int WriteIDBlock(PBYTE lpIDBlock, DWORD dwSectorNum, char *dest_path) +{ + LOGE("WriteIDBlock start %s \n", dest_path); + // int fd_dest = open("/tmp/loader2.txt", O_RDWR|O_SYNC, 0); + int fd_dest = open(dest_path, O_CREAT|O_RDWR|O_SYNC|O_TRUNC, 0); + if (fd_dest < 0) { + LOGE("WriteIDBlock open %s failed. %s\n", dest_path, strerror(errno)); + return -2; + } + + for(int i = 0; i <= 4; i++) + { + //debug for 3308 + //256 为128k 的起始位置 + //每256k 备份一份 + lseek64(fd_dest, (i * 512)*SECTOR_SIZE, SEEK_SET); + if (write(fd_dest, lpIDBlock, dwSectorNum*SECTOR_SIZE) != dwSectorNum * SECTOR_SIZE) { + close(fd_dest); + LOGE("[%s:%d] error (%s).\n", __func__, __LINE__, strerror(errno)); + return -1; + } + } + sync(); + close(fd_dest); + return 0; +} + +bool download_loader(PBYTE data_buf, int size, char *dest_path) { + generate_gf(); + gen_poly(); + + if (getFlashInfo(NULL, &uiFlashBlockSize, &uiFlashPageSize) != 0) { + LOGE("%s-%d: get mtd info error\n", __func__, __LINE__); + return false; + } + // 1. 获取头部信息,和文件内容 + pBootHead = (PSTRUCT_RKBOOT_HEAD)(data_buf); + + if (pBootHead->uiTag!=0x544F4F42) { + LOGE("pBootHead->uiTag!=0x544F4F42\n"); + return false; + } + + if (pBootHead->ucRc4Flag) { + m_bRc4Disable = true; + } else { + m_bRc4Disable = false; + } + + char loaderDataName[] = "FlashData"; + unsigned char *loaderDataBuffer = NULL; + m_dwLoaderDataSize = getLoaderSizeAndData(loaderDataName, data_buf, &loaderDataBuffer); + m_usFlashDataSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderDataSize))*4; + LOGI("m_usFlashDataSec = %d, m_dwLoaderDataSize = %d.\n", m_usFlashDataSec, m_dwLoaderDataSize); + + char loaderName[] = "FlashBoot"; + unsigned char *loaderCodeBuffer = NULL; + m_dwLoaderSize = getLoaderSizeAndData(loaderName, data_buf, &loaderCodeBuffer); + m_usFlashBootSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderSize))*4; + LOGI("m_usFlashBootSec = %d, m_dwLoaderSize = %d.\n", m_usFlashBootSec, m_dwLoaderSize); + + calcIDBCount(); + reserveIDBlock(); + + // 4. MakeIDBlockData + if (getFlashSize(dest_path, &m_FlashSize, &m_FlasBlockNum) != 0) { + LOGE("getFlashSize error.\n"); + return false; + } + LOGI("[%s:%d] m_FlashSize [%lld]\n", __func__, __LINE__, m_FlashSize); + + // 5. download IDBlock + PBYTE pIDBData=NULL; + pIDBData = (PBYTE)malloc(uiSecNumPerIDB*SECTOR_SIZE); + if ( !pIDBData ) + return false; + memset(pIDBData, 0, uiSecNumPerIDB*SECTOR_SIZE); + if (MakeIDBlockData(pIDBData, loaderCodeBuffer, loaderDataBuffer) !=0 ) { + LOGE("[%s:%d] MakeIDBlockData failed.\n", __func__, __LINE__); + return false; + } + + if (WriteIDBlock(pIDBData, uiSecNumPerIDB, dest_path) != 0) { + LOGE("[%s:%d] WriteIDBlock failed.\n", __func__, __LINE__); + return false; + } + free(pIDBData); + free(loaderCodeBuffer); + free(loaderDataBuffer); + + return true; +} + diff --git a/update_engine/recovery/update_engine/rkboot.h b/update_engine/recovery/update_engine/rkboot.h new file mode 100644 index 0000000..c6025ed --- /dev/null +++ b/update_engine/recovery/update_engine/rkboot.h @@ -0,0 +1,11 @@ +/************************************************************************* + > File Name: rkboot.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Mon 03 Jun 2019 03:46:33 PM CST + ************************************************************************/ + +#ifndef _RKBOOT_H +#define _RKBOOT_H +bool download_loader(PBYTE data_buf, int size, char *dest_path); +#endif diff --git a/update_engine/recovery/update_engine/rkbootloader.cpp b/update_engine/recovery/update_engine/rkbootloader.cpp new file mode 100644 index 0000000..e24dad9 --- /dev/null +++ b/update_engine/recovery/update_engine/rkbootloader.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../bootloader.h" +#include "stdlib.h" + +extern "C" { + #include "../mtdutils/mtdutils.h" +} + +#include "rktools.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------ +// for misc partitions on block devices +// ------------------------------------ +static void wait_for_device(const char* fn) { + int tries = 0; + int ret; + struct stat buf; + do { + ++tries; + ret = stat(fn, &buf); + if (ret) { + printf("stat %s try %d: %s\n", fn, tries, strerror(errno)); + sleep(1); + } + } while (ret && tries < 10); + if (ret) { + printf("failed to stat %s\n", fn); + } +} + +static unsigned int iavb_crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/* Converts a 32-bit unsigned integer from host to big-endian byte order. */ +static unsigned int avb_htobe32(unsigned int in) { + union { + unsigned int word; + unsigned char bytes[4]; + } ret; + ret.bytes[0] = (in >> 24) & 0xff; + ret.bytes[1] = (in >> 16) & 0xff; + ret.bytes[2] = (in >> 8) & 0xff; + ret.bytes[3] = in & 0xff; + return ret.word; +} + +/* + * A function that calculates the CRC-32 based on the table above is + * given below for documentation purposes. An equivalent implementation + * of this function that's actually used in the kernel can be found + * in sys/libkern.h, where it can be inlined. + */ +static unsigned int iavb_crc32(unsigned int crc_in, const unsigned char* buf, int size) { + const unsigned char* p = buf; + unsigned int crc; + + crc = crc_in ^ ~0U; + while (size--) + crc = iavb_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + return crc ^ ~0U; +} + +static unsigned int avb_crc32(const unsigned char* buf, size_t size) { + return iavb_crc32(0, buf, size); +} + +static void AvbABData_update_crc(struct AvbABData *data) +{ + data->crc32 = avb_htobe32(avb_crc32((const unsigned char*)data, sizeof(struct AvbABData) - sizeof(unsigned int))); +} + +static int writeMisc_mtd(char *buf, int offset, int size) { + size_t page_size = 0; + mtd_scan_partitions(); + const MtdPartition *part = mtd_find_partition_by_name(MISC_PARTITION_NAME_MTD); + if (part == NULL || mtd_partition_info(part, NULL, NULL, &page_size)) { + LOGE("Can't find %s\n", MISC_PARTITION_NAME_MTD); + return -1; + } + + MtdReadContext *read = mtd_read_partition(part); + if (read == NULL) { + LOGE("Can't open %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + return -1; + } + + size_t write_size = page_size * 10; //读取20个页,24k + char data[write_size]; + ssize_t r = mtd_read_data(read, data, write_size); + if (r != write_size) LOGE("Can't read %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + mtd_read_close(read); + if (r != write_size) return -1; + + memcpy(&data[offset], buf, size); + + MtdWriteContext *write = mtd_write_partition(part); + if (write == NULL) { + LOGE("Can't open %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + return -1; + } + + if (mtd_write_data(write, data, write_size) != write_size) { + LOGE("Can't write %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + mtd_write_close(write); + return -1; + } + if (mtd_write_close(write)) { + LOGE("Can't finish %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + return -1; + } + + return 0; +} + +static int readMisc_mtd(char *buf, int offset, int size) { + size_t page_size; + memset(buf, 0, size); + mtd_scan_partitions(); + const MtdPartition *part = mtd_find_partition_by_name(MISC_PARTITION_NAME_MTD); + if (part == NULL || mtd_partition_info(part, NULL, NULL, &page_size)) { + LOGE("Can't find %s\n", MISC_PARTITION_NAME_MTD); + return -1; + } + + MtdReadContext *read = mtd_read_partition(part); + if (read == NULL) { + LOGE("Can't open %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + return -1; + } + size_t write_size = page_size * 10; //读取20个页,24k + char data[write_size]; + ssize_t r = mtd_read_data(read, data, write_size); + if (r != write_size) LOGE("Can't read %s\n(%s)\n", MISC_PARTITION_NAME_MTD, strerror(errno)); + mtd_read_close(read); + if (r != write_size) return -1; + + memcpy(buf, &data[offset], size); + return 0; +} + +static int writeMisc_block(char *buf, int offset, int size) { + FILE* f = fopen(MISC_PARTITION_NAME_BLOCK, "wb"); + if (f == NULL) { + LOGE("Can't open %s\n(%s)\n", MISC_PARTITION_NAME_BLOCK, strerror(errno)); + return -1; + } + fseek(f, offset, SEEK_SET); + int count = fwrite(buf, sizeof(char), size, f); + if (count != size) { + LOGE("Failed writing %s\n(%s)\n", MISC_PARTITION_NAME_BLOCK, strerror(errno)); + return -1; + } + if (fclose(f) != 0) { + LOGE("Failed closing %s\n(%s)\n", MISC_PARTITION_NAME_BLOCK, strerror(errno)); + return -1; + } + return 0; +} + +static int readMisc_block(char *buf, int offset, int size) { + wait_for_device(MISC_PARTITION_NAME_BLOCK); + FILE* f = fopen(MISC_PARTITION_NAME_BLOCK, "rb"); + if (f == NULL) { + LOGE("Can't open %s\n(%s)\n", MISC_PARTITION_NAME_BLOCK, strerror(errno)); + return -1; + } + + fseek(f, offset, SEEK_SET); + + int count = fread(buf, sizeof(char), size, f); + if (count != size) { + LOGE("Failed reading %s\n(%s)\n", MISC_PARTITION_NAME_BLOCK, strerror(errno)); + return -1; + } + if (fclose(f) != 0) { + LOGE("Failed closing %s\n(%s)\n", MISC_PARTITION_NAME_BLOCK, strerror(errno)); + return -1; + } + return 0; + +} + +static int writeMisc(char *buf, int offset, int size) { + if (isMtdDevice()) { + return writeMisc_mtd(buf, offset, size); + } else { + return writeMisc_block(buf, offset, size); + } +} + +static int readMisc(char *buf, int offset, int size) { + if (isMtdDevice()) { + return readMisc_mtd(buf, offset, size); + } else { + return readMisc_block(buf, offset, size); + } +} + +/** +* 往misc 偏移4k处写入格式化命令 +*/ +static int writeCmdMisc(char *cmdline, int size) { + return writeMisc(cmdline, MISC_OFFSET_CMDLINE, strlen(cmdline)); +} + +/** +* 读misc 偏移4K处格式化命令 +*/ +static int readCmdMisc(char *cmdline, int size) { + return readMisc(cmdline, MISC_OFFSET_CMDLINE, size); +} + +/** + * 从misc 偏移2k处读取引导信息 + */ +static int readABMisc(struct AvbABData* info) { + return readMisc((char *)info, MISC_OFFSET, sizeof(struct AvbABData)); +} + +/** + * 往misc 偏移2k处写入引导信息 + */ +static int writeABMisc(struct AvbABData *info) { + return writeMisc((char *)info, MISC_OFFSET, sizeof(struct AvbABData)); +} + +/** +* 往misc 偏移16k位置处读取recovery信息 +*/ +int get_bootloader_message(struct bootloader_message *out) { + return readMisc((char *)out, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, sizeof(struct bootloader_message)); +} + +/** +* 往misc 偏移16k位置写入recovery信息 +*/ + +int set_bootloader_message(const struct bootloader_message *in){ + return writeMisc((char*)in, BOOTLOADER_MESSAGE_OFFSET_IN_MISC, sizeof(struct bootloader_message)); +} + +int avb_safe_memcmp(const void* s1, const void* s2, size_t n) { + const unsigned char* us1 = (const unsigned char *)s1; + const unsigned char* us2 = (const unsigned char *)s2; + int result = 0; + + if (0 == n) { + return 0; + } + + /* + * Code snippet without data-dependent branch due to Nate Lawson + * (nate@root.org) of Root Labs. + */ + while (n--) { + result |= *us1++ ^ *us2++; + } + + return result != 0; +} +/** +* 设置当前分区为可启动分区 +*/ +int setSlotSucceed() { + int now_slot = getCurrentSlot(); + if (now_slot == -1) { + return -1; + } + struct AvbABData info; + if (readABMisc(&info) == -1) { + return -1; + } + + for (size_t i = 0; i < 4; i++) + { + printf("info.mafic is %x\n",info.magic[i]); + } + if (avb_safe_memcmp(info.magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) { + printf("Magic is incorrect.\n"); + return false; + } + if (info.slots[now_slot].priority != AVB_AB_MAX_PRIORITY) { + /* Something could be wrong, correct it because this slot is bootable */ + printf("Warning: current slot priorty is %d != %d, Correct it!\n", + info.slots[now_slot].priority, AVB_AB_MAX_PRIORITY); + info.slots[now_slot].priority = AVB_AB_MAX_PRIORITY; + } + #ifdef SUCCESSFUL_BOOT + info.slots[now_slot].tries_remaining = 0; + info.slots[now_slot].successful_boot = 1; + #endif + #ifdef RETRY_BOOT + info.slots[now_slot].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; + /* Clear suc boot flag anyway. Because it's chance that an older slot + * used succ mode without this patch applied, while the other one + * (new OTA slot) uses tries mode. We need to make sure not to confuse + * u-boot, otherwise this slot will be unbootable. + */ + info.slots[now_slot].successful_boot = 0; + #endif + info.last_boot = now_slot; + + AvbABData_update_crc(&info); + + if (writeABMisc(&info) != 0) { + return -1; + } + return 0; +} + +/** +* 设置升级分区, 即另外一个分区优先级最高 +*/ +int setSlotActivity() { + int now_slot = getCurrentSlot(); + if (now_slot == -1) { + return -1; + } + struct AvbABData info; + + if (readABMisc(&info) == -1) { + return -1; + } + + info.slots[now_slot].priority = AVB_AB_MAX_PRIORITY - 1; + info.slots[1 - now_slot].priority = AVB_AB_MAX_PRIORITY; + info.slots[1 - now_slot].tries_remaining = AVB_AB_MAX_TRIES_REMAINING; + /* When switch to another slot, assume it is not suc boot, try it out! */ + info.slots[1 - now_slot].successful_boot = 0; + + AvbABData_update_crc(&info); + + if (writeABMisc(&info) != 0) { + return -1; + } + return 0; +} + + + +/** +*格式化userdata_data +*/ +int wipe_userdata(int auto_reboot) { + if (writeCmdMisc(CMD_WIPE_USERDATA, sizeof(CMD_WIPE_USERDATA)) != 0) { + return -1; + } + + if (auto_reboot) { + LOGI("auto reboot, %s.\n", CMD_WIPE_USERDATA); + sleep(1); + reboot(RB_AUTOBOOT); + } + return 0; +} + +/* +* 显示MISC 分区的所有内容,方便调试 +*/ +void miscDisplay() { + // 显示A/B 分区的misc 信息 + LOGI("===============Linux A/B=============\n"); + struct AvbABData info_ab; + readABMisc(&info_ab); + LOGI("magic : %s.\n", info_ab.magic); + LOGI("version_major = %d.\n", info_ab.version_major); + LOGI("version_minor = %d.\n", info_ab.version_minor); + for (int i = 0; i < 2; i++) { + LOGI("slot.[%d]->priority = %d.\n", i, info_ab.slots[i].priority); + LOGI("slot.[%d]->successful_boot = %d.\n", i, info_ab.slots[i].successful_boot); + LOGI("slot.[%d]->tries_remaining = %d.\n", i, info_ab.slots[i].tries_remaining); + } + + LOGI("last_boot : %d.\n", info_ab.last_boot); + LOGI("calculate crc32: %x.\n", avb_htobe32(avb_crc32((const unsigned char*)&info_ab, sizeof(struct AvbABData) - sizeof(unsigned int)))); + LOGI("local crc32: %x.\n", info_ab.crc32); + LOGI("sizeof(struct AvbABData) = %ld\n", sizeof(struct AvbABData)); + + // 显示格式化信息 + LOGI("==============wipe================\n"); + // 显示recovery 的misc 信息 + char cmdline[20]; + readCmdMisc(cmdline, sizeof(cmdline)); + LOGI("cmdline = %s.\n", cmdline); + LOGI("==============recovery============\n"); + + bootloader_message boot; + get_bootloader_message(&boot); + LOGI("bootloader.command = %s.\n", boot.command); + LOGI("bootloader.recovery = %s.\n", boot.recovery); + LOGI("bootloader.status = %s.\n", boot.status); + LOGI("bootloader.needupdate = %x.\n", *((int *)boot.needupdate)); + LOGI("bootloader.systemFlag = %s.\n", boot.systemFlag); +} \ No newline at end of file diff --git a/update_engine/recovery/update_engine/rkimage.cpp b/update_engine/recovery/update_engine/rkimage.cpp new file mode 100644 index 0000000..52bc040 --- /dev/null +++ b/update_engine/recovery/update_engine/rkimage.cpp @@ -0,0 +1,215 @@ +/************************************************************************* + > File Name: rkimage.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Fri 17 May 2019 02:31:53 PM CST + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "rkimage.h" +#include "log.h" +#include "md5sum.h" +#include "rktools.h" +#include "update.h" + +static void display_head(PSTRUCT_RKIMAGE_HEAD pHead){ + LOGD("uiTag = %x.\n", pHead->uiTag); + LOGD("usSize = %x.\n", pHead->usSize); + LOGD("dwVersion = %x.\n", pHead->dwVersion); + UINT btMajor = ((pHead->dwVersion) & 0XFF000000) >> 24; + UINT btMinor = ((pHead->dwVersion) & 0X00FF0000) >> 16; + UINT usSmall = ((pHead->dwVersion) & 0x0000FFFF); + LOGD("btMajor = %x, btMinor = %x, usSmall = %02x.\n", btMajor, btMinor, usSmall); + LOGD("dwBootOffset = %x.\n", pHead->dwBootOffset); + LOGD("dwBootSize = %x.\n", pHead->dwBootSize); + LOGD("dwFWOffset = %x.\n", pHead->dwFWOffset); + LOGD("dwFWSize = %x.\n", pHead->dwFWSize); +} + +static void display_item(PRKIMAGE_ITEM pitem) { + //char name[PART_NAME]; + //char file[RELATIVE_PATH]; + //unsigned int offset; + //unsigned int flash_offset; + //unsigned int usespace; + //unsigned int size; + + LOGD("name = %s", pitem->name); + LOGD("file = %s", pitem->file); + LOGD("offset = %d", pitem->offset); + LOGD("flash_offset = %d", pitem->flash_offset); + LOGD("usespace = %d", pitem->usespace); + LOGD("size = %d", pitem->size); +} + +static void display_hdr(PRKIMAGE_HDR phdr) { + + //unsigned int tag; + //unsigned int size; + //char machine_model[MAX_MACHINE_MODEL]; + //char manufacturer[MAX_MANUFACTURER]; + //unsigned int version; + //int item_count; + //RKIMAGE_ITEM item[MAX_PACKAGE_FILES]; + + LOGD("tag = %d", phdr->tag); + LOGD("size = %d", phdr->size); + LOGD("machine_model = %s", phdr->machine_model); + LOGD("manufacturer = %s", phdr->manufacturer); + LOGD("version = %d", phdr->version); + LOGD("item = %d.\n", phdr->item_count); + for(int i = 0; i < phdr->item_count; i++){ + LOGI("================================================"); + display_item(&(phdr->item[i])); + } +} + +void adjustFileOffset(PRKIMAGE_HDR phdr, int offset, int loader_offset, int loader_size) +{ + for(int i = 0; i< phdr->item_count; i++){ + if( strcmp(phdr->item[i].name, "bootloader") == 0){ + phdr->item[i].offset = loader_offset; + phdr->item[i].size = loader_size; + continue ; + } + phdr->item[i].offset += offset; + } +} + +//解析固件,获得固件头部信息 +int analyticImage(const char *filepath, PRKIMAGE_HDR phdr) { + long long ulFwSize; + STRUCT_RKIMAGE_HEAD rkimage_head; + unsigned char m_md5[32]; + + + int fd = open(filepath, O_RDONLY); + if (fd < 0) { + LOGE("Can't open %s\n", filepath); + return -2; + } + + //1. image 头部信息读取 + if (read(fd, &rkimage_head, sizeof(STRUCT_RKIMAGE_HEAD)) != sizeof(STRUCT_RKIMAGE_HEAD)) { + LOGE("Can't read %s\n(%s)\n", filepath, strerror(errno)); + close(fd); + return -2; + } + + if ((rkimage_head.reserved[14]=='H')&&(rkimage_head.reserved[15]=='I')) { + ulFwSize = *((DWORD *)(&rkimage_head.reserved[16])); + ulFwSize <<= 32; + ulFwSize += rkimage_head.dwFWOffset; + ulFwSize += rkimage_head.dwFWSize; + } else { + ulFwSize = rkimage_head.dwFWOffset + rkimage_head.dwFWSize; + } + rkimage_head.dwFWSize = ulFwSize - rkimage_head.dwFWOffset; + display_head(&rkimage_head); + + //2. 固件md5 校验 + long long fileSize; + int nMd5DataSize; + + fileSize = lseek64(fd, 0L, SEEK_END); + nMd5DataSize = fileSize - ulFwSize; + if (nMd5DataSize >= 160) { + LOGE("md5 : not support sign image.\n"); + //sign image + //m_bSignFlag = true; + //m_signMd5Size = nMd5DataSize-32; + //fseeko64(m_pFile,ulFwSize,SEEK_SET); + //fread(m_md5,1,32,m_pFile); + //fread(m_signMd5,1,nMd5DataSize-32,m_pFile); + } else { + lseek64(fd, -32, SEEK_END); + if ( read(fd, m_md5, 32) != 32) { + LOGE("lseek failed.\n"); + close(fd); + return -2; + } + } + + //3. image 地址信息读取 + if (lseek64(fd, rkimage_head.dwFWOffset, SEEK_SET) == -1) { + LOGE("lseek failed.\n"); + close(fd); + return -2; + } + + if (read(fd, phdr, sizeof(RKIMAGE_HDR)) != sizeof(RKIMAGE_HDR)) { + LOGE("Can't read %s\n(%s)\n", filepath, strerror(errno)); + close(fd); + return -2; + } + + if (phdr->tag != RKIMAGE_TAG) { + LOGE("tag: %x\n", phdr->tag); + LOGE("Invalid image\n"); + close(fd); + return -3; + } + + if ((phdr->manufacturer[56]==0x55)&&(phdr->manufacturer[57]==0x66)) + { + USHORT *pItemRemain; + pItemRemain = (USHORT *)(&phdr->manufacturer[58]); + phdr->item_count += *pItemRemain; + } + + if (rkimage_head.dwFWOffset) { + adjustFileOffset(phdr, rkimage_head.dwFWOffset, rkimage_head.dwBootOffset, rkimage_head.dwBootSize); + } + + display_hdr(phdr); + + close(fd); + #if 1 + if (!compareMd5sum((char*)filepath, m_md5, 0, fileSize-32)) { + LOGE("Md5Check update.img fwSize:%ld", fileSize-32); + return -1; + } + #endif + LOGI("analyticImage ok.\n"); + return 0; +} + +// 获得Image 打包版本号 +bool getImageVersion(const char *filepath, char *version, int maxLength) { + STRUCT_RKIMAGE_HEAD rkimage_head; + + int fd = open(filepath, O_RDONLY); + if (fd < 0) { + LOGE("Can't open %s\n", filepath); + return false; + } + + //1. image 头部信息读取 + if (read(fd, &rkimage_head, sizeof(STRUCT_RKIMAGE_HEAD)) != sizeof(STRUCT_RKIMAGE_HEAD)) { + LOGE("Can't read %s\n(%s)\n", filepath, strerror(errno)); + close(fd); + return false; + } + close(fd); + UINT btMajor = ((rkimage_head.dwVersion) & 0XFF000000) >> 24; + UINT btMinor = ((rkimage_head.dwVersion) & 0x00FF0000) >> 16; + UINT usSmall = ((rkimage_head.dwVersion) & 0x0000FFFF); + + //转换成字符串 + sprintf(version, "%d.%d.%d", btMajor, btMinor, usSmall); + + return true; +} + +#if 0 +int main(int argc, char *argv[]){ + analyticImage(argv[1]); + compareVersion(); +} +#endif diff --git a/update_engine/recovery/update_engine/rkimage.h b/update_engine/recovery/update_engine/rkimage.h new file mode 100644 index 0000000..718134f --- /dev/null +++ b/update_engine/recovery/update_engine/rkimage.h @@ -0,0 +1,172 @@ +/************************************************************************* + > File Name: rkimage.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Fri 17 May 2019 02:32:13 PM CST + ************************************************************************/ + +#ifndef _RKIMAGE_H +#define _RKIMAGE_H +#include "defineHeader.h" +#pragma pack(1) +typedef struct +{ + USHORT usYear; + BYTE ucMonth; + BYTE ucDay; + BYTE ucHour; + BYTE ucMinute; + BYTE ucSecond; +}STRUCT_RKTIME, *PSTRUCT_RKTIME; + +typedef struct +{ + UINT uiTag; //标志,固定为0x57 0x46 0x4B 0x52 + USHORT usSize; //结构体大小 + DWORD dwVersion; //Image 文件版本 + DWORD dwMergeVersion; //打包工具版本 + STRUCT_RKTIME stReleaseTime; //生成时间 + ENUM_RKDEVICE_TYPE emSupportChip; //使用芯片 + DWORD dwBootOffset; //Boot偏移 + DWORD dwBootSize; //Boot大小 + DWORD dwFWOffset; //固件偏移 + DWORD dwFWSize; //固件大小 + BYTE reserved[61]; //预留空间,用于存放不同固件特征 +}STRUCT_RKIMAGE_HEAD,*PSTRUCT_RKIMAGE_HEAD; + +typedef struct tagRKIMAGE_ITEM +{ + char name[PART_NAME]; + char file[RELATIVE_PATH]; + unsigned int offset; + unsigned int flash_offset; + unsigned int usespace; + unsigned int size; +}RKIMAGE_ITEM, *PRKIMAGE_ITEM; + +typedef struct tagRKIMAGE_HDR +{ + unsigned int tag; + unsigned int size; + char machine_model[MAX_MACHINE_MODEL]; + char manufacturer[MAX_MANUFACTURER]; + unsigned int version; + int item_count; + RKIMAGE_ITEM item[MAX_PACKAGE_FILES]; +}RKIMAGE_HDR, *PRKIMAGE_HDR; + +typedef struct +{ + UINT uiTag; + USHORT usSize; + DWORD dwVersion; + DWORD dwMergeVersion; + STRUCT_RKTIME stReleaseTime; + ENUM_RKDEVICE_TYPE emSupportChip; + UCHAR uc471EntryCount; + DWORD dw471EntryOffset; + UCHAR uc471EntrySize; + UCHAR uc472EntryCount; + DWORD dw472EntryOffset; + UCHAR uc472EntrySize; + UCHAR ucLoaderEntryCount; + DWORD dwLoaderEntryOffset; + UCHAR ucLoaderEntrySize; + UCHAR ucSignFlag; + UCHAR ucRc4Flag; + UCHAR reserved[BOOT_RESERVED_SIZE]; +}STRUCT_RKBOOT_HEAD,*PSTRUCT_RKBOOT_HEAD; + +typedef struct +{ + UCHAR ucSize; + ENUM_RKBOOTENTRY emType; + WCHAR szName[20]; + DWORD dwDataOffset; + DWORD dwDataSize; + DWORD dwDataDelay;//以秒为单位 +}STRUCT_RKBOOT_ENTRY,*PSTRUCT_RKBOOT_ENTRY; +typedef struct +{ + DWORD dwTag; + BYTE reserved[4]; + UINT uiRc4Flag; + USHORT usBootCode1Offset; + USHORT usBootCode2Offset; + BYTE reserved1[490]; + USHORT usBootDataSize; + USHORT usBootCodeSize; + USHORT usCrc; +}RKANDROID_IDB_SEC0,*PRKANDROID_IDB_SEC0; + +typedef struct +{ + USHORT usSysReservedBlock; + USHORT usDisk0Size; + USHORT usDisk1Size; + USHORT usDisk2Size; + USHORT usDisk3Size; + UINT uiChipTag; + UINT uiMachineId; + USHORT usLoaderYear; + USHORT usLoaderDate; + USHORT usLoaderVer; + USHORT usLastLoaderVer; + USHORT usReadWriteTimes; + DWORD dwFwVer; + USHORT usMachineInfoLen; + UCHAR ucMachineInfo[30]; + USHORT usManufactoryInfoLen; + UCHAR ucManufactoryInfo[30]; + USHORT usFlashInfoOffset; + USHORT usFlashInfoLen; + UCHAR reserved[384]; + UINT uiFlashSize; + BYTE reserved1; + BYTE bAccessTime; + USHORT usBlockSize; + BYTE bPageSize; + BYTE bECCBits; + BYTE reserved2[8]; + USHORT usIdBlock0; + USHORT usIdBlock1; + USHORT usIdBlock2; + USHORT usIdBlock3; + USHORT usIdBlock4; +}RKANDROID_IDB_SEC1,*PRKANDROID_IDB_SEC1; + +typedef struct +{ + USHORT usInfoSize; + BYTE bChipInfo[CHIPINFO_LEN]; + BYTE reserved[RKANDROID_SEC2_RESERVED_LEN]; + char szVcTag[3]; + USHORT usSec0Crc; + USHORT usSec1Crc; + UINT uiBootCodeCrc; + USHORT usSec3CustomDataOffset; + USHORT usSec3CustomDataSize; + char szCrcTag[4]; + USHORT usSec3Crc; +}RKANDROID_IDB_SEC2,*PRKANDROID_IDB_SEC2; + +typedef struct +{ + USHORT usSNSize; + BYTE sn[RKDEVICE_SN_LEN]; + BYTE reserved[RKANDROID_SEC3_RESERVED_LEN]; + BYTE imeiSize; + BYTE imei[RKDEVICE_IMEI_LEN]; + BYTE uidSize; + BYTE uid[RKDEVICE_UID_LEN]; + BYTE blueToothSize; + BYTE blueToothAddr[RKDEVICE_BT_LEN]; + BYTE macSize; + BYTE macAddr[RKDEVICE_MAC_LEN]; +}RKANDROID_IDB_SEC3,*PRKANDROID_IDB_SEC3; + +#pragma pack() + +bool getImageVersion(const char *filepath, char *version, int maxLength) ; +int analyticImage(const char *filepath, PRKIMAGE_HDR phdr); +#endif diff --git a/update_engine/recovery/update_engine/rktools.cpp b/update_engine/recovery/update_engine/rktools.cpp new file mode 100644 index 0000000..0f9023b --- /dev/null +++ b/update_engine/recovery/update_engine/rktools.cpp @@ -0,0 +1,244 @@ +/************************************************************************* + > File Name: rktools.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Fri 17 May 2019 07:30:44 PM CST + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "rktools.h" +#include "download.h" +extern "C" { + #include "../mtdutils/mtdutils.h" +} + + +#define LOCAL_VERSION_PATH "/demo/bin/version" +#define DOWNLOAD_VERSION_PATH "/tmp/version" + +bool getVersionFromfile(const char * filepath,char *version, int maxLength) { + if (version == NULL || filepath == NULL) { + LOGE("getLocalVersion is error, version == null.\n"); + return false; + } + FILE *fp = fopen(filepath, "r"); + if (fp == NULL) { + LOGE("open %s failed, error is %s.\n", filepath, strerror(errno)); + return false; + } + + char *line = NULL; + size_t len = 0; + size_t read; + while ((read = getline(&line, &len, fp)) != -1) { + if (read == 0 || line[0] == '#') { + continue; + } + char *pline = strstr(line, "RK_VERSION"); + if (pline != NULL && (pline = strstr(pline, "=")) != NULL) { + pline++; //过滤掉等于号 + //过滤掉空格 + while (*pline == ' ') { + pline++; + } + int pline_len = strlen(pline) - 1; + int version_len = (pline_len > maxLength ? maxLength:pline_len); + memcpy(version, pline, version_len); + LOGI("version = %s.\n", version); + break; + } + } + free(line); + fclose(fp); + return true; +} + +//下载服务器版本号文件 +bool getRemoteVersion(char *url, char *version, int maxLength) { + if (url == NULL) { + LOGE("getRemoteVersion url is null.\n"); + return false; + } + + if (download_file(url, DOWNLOAD_VERSION_PATH) == -1){ + LOGE("getRemoteVersion failed, url is %s.\n", url); + return false; + } + + return getVersionFromfile(DOWNLOAD_VERSION_PATH, version, maxLength); +} + +//获取本地版本号 +bool getLocalVersion(char *version, int maxLength) { + return getVersionFromfile(LOCAL_VERSION_PATH, version, maxLength); +} + +//判断是MTD还是block 设备 +bool isMtdDevice() { + char param[2048]; + int fd, ret; + char *s = NULL; + fd = open("/proc/cmdline", O_RDONLY); + ret = read(fd, (char*)param, 2048); + close(fd); + s = strstr(param,"storagemedia"); + if(s == NULL){ + LOGI("no found storagemedia in cmdline, default is not MTD.\n"); + return false; + }else{ + s = strstr(s, "="); + if (s == NULL) { + LOGI("no found storagemedia in cmdline, default is not MTD.\n"); + return false; + } + + s++; + while (*s == ' ') { + s++; + } + + if (strncmp(s, "mtd", 3) == 0 ) { + LOGI("Now is MTD.\n"); + return true; + } else if (strncmp(s, "sd", 2) == 0) { + LOGI("Now is SD.\n"); + if ( !access(MTD_PATH, F_OK) ) { + fd = open(MTD_PATH, O_RDONLY); + ret = read(fd, (char*)param, 2048); + close(fd); + + s = strstr(param,"mtd"); + if(s == NULL){ + LOGI("no found mtd.\n"); + return false; + } + LOGI("Now is MTD.\n"); + return true; + } + } + } + LOGI("Current device is not MTD"); + return false; +} + +/** + * 从cmdline 获取从哪里引导 + * 返回值: + * 0: a分区 + * 1: b分区 + * -1: recovery 模式 + */ +int getCurrentSlot(){ + char cmdline[CMDLINE_LENGTH]; + int fd = open("/proc/cmdline", O_RDONLY); + read(fd, (char*)cmdline, CMDLINE_LENGTH); + close(fd); + char *slot = strstr(cmdline, "android_slotsufix"); + if(slot == NULL) slot = strstr(cmdline, "androidboot.slot_suffix"); + if(slot != NULL){ + slot = strstr(slot, "="); + if(slot != NULL && *(++slot) == '_'){ + slot += 1; + LOGI("Current Mode is '%c' system.\n", (*slot == 'a')? 'A':'B'); + if((*slot) == 'a'){ + return 0; + }else if((*slot) == 'b'){ + return 1; + } + } + } + LOGI("Current Mode is recovery.\n"); + return -1; +} + +void getFlashPoint(char *path) { + char *emmc_point = getenv(EMMC_POINT_NAME); + LOGI("test Current device is emmc : %s.\n", emmc_point); + if ( !access(emmc_point, F_OK) ) { + LOGI("Current device is emmc : %s.\n", emmc_point); + strcpy(path, emmc_point); + } else if (strncmp("emmc", getenv("storagemedia"), 4) == 0) { + LOGI("Current device is emmc : /dev/mmcblk0.\n"); + strcpy(path, "/dev/mmcblk0"); + } else { + LOGI("Current device is nand : %s.\n", NAND_DRIVER_DEV_LBA); + strcpy(path, NAND_DRIVER_DEV_LBA); + } +} +/* + * 获得flash 的大小,和块数 + */ +int getFlashSize(char *path, long long* flash_size, long long* block_num) { + + LOGI("[%s:%d]\n", __func__, __LINE__); + + off64_t total_size_64 = 0; + if (isMtdDevice()) { + size_t erase_size; + size_t total_size; + mtd_scan_partitions(); + const MtdPartition *part = mtd_find_partition_by_name("rk-nand"); + if ( part == NULL ) { + part = mtd_find_partition_by_name("spi-nand0"); + } + if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) { + LOGE("Can't find rk-nand or spi-nand0\n"); + return -1; + } + total_size = total_size - (erase_size * 4); + total_size_64 = total_size; + } else { + char flash_name[20]; + getFlashPoint(flash_name); + int fd_dest = open(flash_name, O_RDWR|O_LARGEFILE); + if (fd_dest < 0) { + LOGE("Can't open %s\n", flash_name); + return -2; + } + if ((total_size_64 = lseek64(fd_dest, 0, SEEK_END)) == -1) { + LOGE("getFlashInfo lseek64 failed.\n"); + close(fd_dest); + return -2; + } + lseek64(fd_dest, 0, SEEK_SET); + close(fd_dest); + } + if ( flash_size ) { + *flash_size = total_size_64 / 1024; //Kib + LOGI("[%s:%d] flash size [%lld] \n", __func__, __LINE__, *flash_size); + } + if ( block_num ) { + *block_num = (total_size_64 / 1024) * 2; + LOGI("[%s:%d] block num [%lld]\n", __func__, __LINE__, *block_num); + } + + return 0; +} + +int getFlashInfo (size_t *total_size, size_t *block_size, size_t *page_size) +{ + if (isMtdDevice()) { + if (mtd_get_flash_info(total_size, block_size, page_size) != 0) { + LOGE("%s-%d: get mtd info error\n", __func__, __LINE__); + return -1; + } + return 0; + } else { + LOGI("[%s:%d]\n", __func__, __LINE__); + if (total_size) { + LOGE("%s-%d: get flash total size error. NOT support now.\n", __func__, __LINE__); + return -1; + } + if (block_size) *block_size = 512*1024; + if (page_size) *page_size = 2*1024; + return 0; + } +} diff --git a/update_engine/recovery/update_engine/rktools.h b/update_engine/recovery/update_engine/rktools.h new file mode 100644 index 0000000..e6d57cb --- /dev/null +++ b/update_engine/recovery/update_engine/rktools.h @@ -0,0 +1,35 @@ +/************************************************************************* + > File Name: rktools.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Fri 17 May 2019 07:30:51 PM CST + ************************************************************************/ + +#ifndef _RKTOOLS_H +#define _RKTOOLS_H + +#define MTD_PATH "/proc/mtd" +#define CMDLINE_LENGTH 2048 +#define EMMC_POINT_NAME "emmc_point_name" +#define NAND_DRIVER_DEV_LBA "/dev/mtd0" + + +bool getVersionFromfile(const char * filepath,char *version, int maxLength); +//获取本地版本号 +bool getLocalVersion(char *version, int maxLength); +//获取服务器版本号,用于从服务端下载固件前,先比较版本号 +bool getRemoteVersion(char *url, char *version, int maxLength); +//从环境变量获取flash 的挂载点 +void getFlashPoint(char *path); +//获取flash 的大小,M为单位,和flash 的块数 +int getFlashSize(char *path, long long* flash_size, long long* block_num); +int getFlashInfo (size_t *total_size, size_t *block_size, size_t *page_size); + + +//itoa(number,string,10);//按十进制转换 +//itoa(number,string,16);//按16进制转换 +char* itoa(int num, char* str, int radix); + +bool isMtdDevice(); +int getCurrentSlot(); +#endif diff --git a/update_engine/recovery/update_engine/update.cpp b/update_engine/recovery/update_engine/update.cpp new file mode 100644 index 0000000..4708f65 --- /dev/null +++ b/update_engine/recovery/update_engine/update.cpp @@ -0,0 +1,441 @@ +/************************************************************************* + > File Name: update.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Mon 20 May 2019 09:59:19 AM CST + ************************************************************************/ +#include +#include +#include +#include "update.h" +#include "log.h" +#include "download.h" +#include "rkimage.h" +#include "flash_image.h" +#include "rktools.h" +#include "md5sum.h" +#include "defineHeader.h" + +#include +#include +#include +#include +#include + +#define CMD4RECOVERY_FILENAME "/mnt/sdcard/cmd4recovery" +static char * _url = NULL; +static char * _save_path = NULL; +static char _url_dir[128]; +double processvalue = 0; + +void RK_ota_set_url(char *url, char *savepath) { + LOGI("start RK_ota_url url [%s] save path [%s].\n", url, savepath); + if ( url == NULL ) { + LOGE("RK_ota_set_url : url is NULL.\n"); + return ; + } + if (savepath == NULL) { + _save_path = DEFAULT_DOWNLOAD_PATH; + } else { + _save_path = savepath; + } + LOGI("save image to %s.\n", _save_path); + _url = url; + + sprintf(_url_dir, "%s", _url); + dirname(_url_dir); +} + +bool is_sdboot = false; + +UPDATE_CMD update_cmd[] = { + {"bootloader" , false , false , 0 , 0 , 0 , "" , flash_bootloader} , + {"parameter" , false , false , 0 , 0 , 0 , "" , flash_parameter} , + {"uboot" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"trust" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"boot" , false , true , 0 , 0 , 0 , "" , flash_normal} , + {"recovery" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"rootfs" , false , true , 0 , 0 , 0 , "" , flash_normal} , + {"oem" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"uboot_a" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"uboot_b" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"boot_a" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"boot_b" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"system_a" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"system_b" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"misc" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"userdata" , false , false , 0 , 0 , 0 , "" , flash_normal} , + {"demo" , false, false, 0, 0, 0, "" , flash_normal} , +}; + +bool RK_ota_set_partition(int partition) { + //000000000000000000000000: 没有升级分区 + //100000000000000000000000: 升级loader分区 + //010000000000000000000000: 升级parameter分区 + //001000000000000000000000: 升级uboot分区 + //000100000000000000000000: 升级trust分区 + //000010000000000000000000: 升级boot分区 + //000001000000000000000000: 升级recovery分区 + //000000100000000000000000: 升级rootfs分区 + //000000010000000000000000: 升级oem分区 + //000000001000000000000000: 升级uboot_a分区 + //000000000100000000000000: 升级uboot_b分区 + //000000000010000000000000: 升级boot_a分区 + //000000000001000000000000: 升级boot_b分区 + //000000000000100000000000: 升级system_a分区 + //000000000000010000000000: 升级system_b分区 + //000000000000001000000000: 升级misc分区,sdboot使用 + //000000000000000100000000: 升级userdata分区 + + int num = sizeof(update_cmd)/sizeof(UPDATE_CMD); + LOGI("[%s:%d] num [%d]\n", __func__, __LINE__, num); + + if (partition == -1) { + //设置目标分区大小 + RKIMAGE_HDR rkimage_hdr; + if( analyticImage(_url, &rkimage_hdr) != 0){ + LOGE("analyticImage error.\n"); + return false; + } + + for (int i = 0; i < num; i++) { + if ( update_cmd[i].need_update || is_sdboot) { + update_cmd[i].need_update = false; + for (int j = 0; j < rkimage_hdr.item_count; j++) { + if (strcmp(rkimage_hdr.item[j].name, update_cmd[i].name) == 0) { + LOGI("found rkimage_hdr.item[%d].name = %s.\n", j, update_cmd[i].name); + if (rkimage_hdr.item[j].file[50]=='H') { + update_cmd[i].offset = *((DWORD *)(&rkimage_hdr.item[j].file[51])); + update_cmd[i].offset <<= 32; + update_cmd[i].offset += rkimage_hdr.item[j].offset; + LOGI("offset more than 4G, after adjusting is %lld.\n", update_cmd[i].offset); + } else { + update_cmd[i].offset = rkimage_hdr.item[j].offset; + } + + if (rkimage_hdr.item[j].file[55]=='H') { + update_cmd[i].size = *((DWORD *)(&rkimage_hdr.item[j].file[56])); + update_cmd[i].size <<= 32; + update_cmd[i].size += rkimage_hdr.item[j].size; + LOGI("size more than 4G, after adjusting is %lld.\n", update_cmd[i].size); + } else { + update_cmd[i].size = rkimage_hdr.item[j].size; + } + + if (is_sdboot) { + update_cmd[i].flash_offset = (long long)rkimage_hdr.item[j].flash_offset * SECTOR_SIZE; + } + update_cmd[i].need_update = true; + continue ; + } + } + } + } + + if (!is_sdboot) { + for ( int i=0; i0 ; j-- ) { + dd_bs = j*SECTOR_SIZE; + if ( !(flash_offset % dd_bs) ) { + dd_seek = flash_offset / dd_bs; + printf ( "flash offset = [%#llx] j=%d bs=%#x seek = %#llx result = [%s]\n", + flash_offset , j, dd_bs, dd_seek , (dd_bs*dd_seek == flash_offset)? "YES":"NO" ); + break; + } else { + dd_bs = 1; + dd_seek = flash_offset; + } + } + sprintf(data_buf, "dd of=%s if=%s bs=%d seek=%lld; \t###flash offset [%#10llx] \n", flash_name, dest_path, dd_bs, dd_seek, flash_offset); + } + + write_count = strlen(data_buf); + + if (write(fd, data_buf, write_count) != write_count) { + close(fd); + LOGE("[%s:%d] Write failed(%s)\n", __func__, __LINE__, strerror(errno)); + return -2; + } + + close(fd); + return 0; +} + +void RK_ota_start(RK_upgrade_callback cb) { + LOGI("start RK_ota_start.\n"); + processvalue = 95; + cb(NULL, RK_UPGRADE_START); + + //确认升级路径 + if (_url == NULL) { + LOGE("url is NULL\n"); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + + // 1. 获取文件 + int res = download_file(_url, _save_path); + if (res == 0) { + _url = _save_path; + } else if (res == -1) { + LOGE("download_file error.\n"); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + + // 2. 获取文件信息 + if (!RK_ota_set_partition(-1)) { + LOGE("RK_ota_set_partition failed.\n"); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + + STRUCT_PARAM_ITEM param_item[20] = {0}; + long long gpt_backup_offset = -1; + memset(param_item, 0, sizeof(param_item)); + flash_register_partition_data(param_item, &gpt_backup_offset); + + int is_mtd_flag = isMtdDevice(); + + // 3. 下载文件到分区并校验 + int num = sizeof(update_cmd)/sizeof(UPDATE_CMD); + for (int i = 0; i < num; i++ ) { + if (update_cmd[i].need_update) { + if (update_cmd[i].cmd != NULL) { + LOGI("now write %s to %s.\n", update_cmd[i].name, update_cmd[i].dest_path); + if (!is_sdboot && + ( (strcmp(update_cmd[i].name, "misc") == 0) || + (strcmp(update_cmd[i].name, "parameter") == 0) )) { + LOGI("ingore misc.\n"); + continue; + } + // 下载固件到分区 + printf("update_cmd.flash_offset = %lld.\n", update_cmd[i].flash_offset); + if (update_cmd[i].cmd(_url, (void*)(&update_cmd[i])) != 0) { + LOGE("update %s error.\n", update_cmd[i].dest_path); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + if (is_sdboot) { + if (ota_recovery_cmds(update_cmd[i].flash_offset, update_cmd[i].dest_path)) { + LOGE("write recovery cmds to %s failed.\n", CMD4RECOVERY_FILENAME); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + LOGI("not check in sdboot.\n"); + continue; + } + // parameter 和loader 先不校验 + if (strcmp(update_cmd[i].name, "parameter") == 0 || strcmp(update_cmd[i].name, "bootloader") == 0) { + LOGI("not check parameter and loader.\n"); + continue; + } + // 校验分区 + if (comparefile(update_cmd[i].dest_path, _url, update_cmd[i].flash_offset, update_cmd[i].offset, update_cmd[i].size)) + { + LOGI("check %s ok.\n", update_cmd[i].dest_path); + } else { + LOGE("check %s failed.\n", update_cmd[i].dest_path); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + } + } + } + + /* + * Fix if update_xxx.img not found some A/B partition image. + */ + if (is_sdboot) { + for (int i = 0; i < num; i++) { + if ( (!update_cmd[i].need_update) || (update_cmd[i].cmd == NULL)) { + continue; + } + unsigned char len = strlen(update_cmd[i].name); + if (update_cmd[i].name[len-2] == '_' && (update_cmd[i].name[len-1] == 'a' || update_cmd[i].name[len-1] == 'b') ) { + char slot_find = (update_cmd[i].name[len-1] == 'a')? 'b':'a'; + int part_need_fix = 1; + char part_name[32]; + memset(part_name, 0, sizeof(part_name)/sizeof(part_name[0])); + memcpy(part_name, update_cmd[i].name, len); + part_name[len-1] = slot_find; + + for (int k = 0; k < num; k++) { + if ( (!update_cmd[k].need_update) || (update_cmd[k].cmd == NULL)) { + continue; + } + if ( (strcmp(update_cmd[k].name, part_name) == 0) ) { + part_need_fix = 0; + } + } + + if (part_need_fix) { + for (int j = 0; j < sizeof(param_item)/sizeof(param_item[0]); j++) { + if (strcmp(param_item[j].name, part_name) == 0) { + if (ota_recovery_cmds(param_item[j].offset * SECTOR_SIZE, update_cmd[i].dest_path)) { + LOGE("sdboot fix write recovery cmds to %s failed.\n", CMD4RECOVERY_FILENAME); + cb(NULL, RK_UPGRADE_ERR); + return ; + } + } + } + } + } + } + + // write gpt backup + /* + * char gpt_backup_img_path[100] = {0}; + * sprintf(gpt_backup_img_path, "%s/%s", _url_dir, GPT_BACKUP_FILE_NAME); + * if (ota_recovery_cmds(gpt_backup_offset, gpt_backup_img_path)) { + * LOGE("write gpt backup to recovery cmds failed (%s).\n", gpt_backup_img_path); + * cb(NULL, RK_UPGRADE_ERR); + * return ; + * } + */ + + } + + // 4. 是否设置misc + + LOGI("RK_ota_start is ok!"); + processvalue = 100; + cb(NULL, RK_UPGRADE_FINISHED); +} + +int RK_ota_get_progress() { + return processvalue; +} + +void RK_ota_get_sw_version(char *buffer, int maxLength) { + getLocalVersion(buffer, maxLength); +} + +bool RK_ota_check_version(char *url) { + char source_version[20] = {0}; + char target_version[20] = {0}; + if (!getLocalVersion(source_version, sizeof(source_version))) { + return false; + } + + if (strncmp(url, "http", 4) == 0) { + //如果是远程文件,从远程获取版本号 + if (!getRemoteVersion(url, target_version, sizeof(target_version))) { + return false; + } + } else { + //如果是本地文件,从固件获取版本号 + if (!getImageVersion(url, target_version, sizeof(target_version))) { + return false; + } + } + + LOGI("check version new:%s old:%s", target_version, source_version); + if (strcmp(target_version, source_version) != 0) { + return true; + } + return false; +} diff --git a/update_engine/recovery/update_engine/update.h b/update_engine/recovery/update_engine/update.h new file mode 100644 index 0000000..2413167 --- /dev/null +++ b/update_engine/recovery/update_engine/update.h @@ -0,0 +1,39 @@ +/************************************************************************* + > File Name: update.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Mon 20 May 2019 09:59:27 AM CST + ************************************************************************/ + +#ifndef _UPDATE_H +#define _UPDATE_H + +typedef int (*update_func)(char *src_path, void* pupdate_cmd); +typedef struct { + char name[32]; + bool need_update; + bool is_ab; + long long size; + long long offset; + long long flash_offset; + char dest_path[100]; + update_func cmd; +}UPDATE_CMD, *PUPDATE_CMD; + +typedef enum{ + RK_UPGRADE_FINISHED, + RK_UPGRADE_START, + RK_UPGRADE_ERR, +}RK_Upgrade_Status_t; + +typedef void(*RK_upgrade_callback)(void *user_data, RK_Upgrade_Status_t status); + +void RK_ota_set_url(char *url, char *savepath); +bool RK_ota_set_partition(int partition); +void RK_ota_start(RK_upgrade_callback cb); +//void RK_ota_stop(); +int RK_ota_get_progress(); +void RK_ota_get_sw_version(char *buffer, int maxLength); +bool RK_ota_check_version(char *url); + +#endif diff --git a/ymodem-master/.gitignore b/ymodem-master/.gitignore new file mode 100644 index 0000000..c6127b3 --- /dev/null +++ b/ymodem-master/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/ymodem-master/CMakeLists copy.txt b/ymodem-master/CMakeLists copy.txt new file mode 100644 index 0000000..58e2838 --- /dev/null +++ b/ymodem-master/CMakeLists copy.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.8) +message(STATUS "cmake version ${CMAKE_VERSION}") + +set(TOOLCHAIN_DIR /opt/atk-dlrv1126-toolchain) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-g++) +set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-gcc) +set(SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot/usr/include) +set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot) + +set(CMAKE_CXX_STANDARD 11) +add_definitions(-g -O0 -ggdb -gdwarf -funwind-tables -rdynamic) +add_definitions(-Wno-write-strings -Wno-return-type) + +link_directories(include .) + +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIR}) +include_directories(.) + +add_executable(ymodem-test + ymodem_test.c + serial_port.c + ymodem.c + download.cpp + ) +target_link_libraries(ymodem-test pthread dl ${CURL_LIBRARIES}) \ No newline at end of file diff --git a/ymodem-master/CMakeLists.txt b/ymodem-master/CMakeLists.txt new file mode 100644 index 0000000..48712a3 --- /dev/null +++ b/ymodem-master/CMakeLists.txt @@ -0,0 +1,32 @@ +project(ymodem-test CXX C) +cmake_minimum_required(VERSION 3.8) +message(STATUS "cmake version ${CMAKE_VERSION}") + +set(TOOLCHAIN_DIR /opt/atk-dlrv1126-toolchain) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-g++) +set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/usr/bin/arm-linux-gnueabihf-gcc) +set(SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot/usr/include) +set(CMAKE_SYSROOT ${TOOLCHAIN_DIR}/arm-buildroot-linux-gnueabihf/sysroot) + +set(CMAKE_CXX_STANDARD 11) +add_definitions(-g -O0 -ggdb -gdwarf -funwind-tables -rdynamic) +add_definitions(-Wno-write-strings -Wno-return-type) + +link_directories(include .) + +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIR}) +include_directories(.) + +add_executable(ymodem-test + ymodem_test.cpp + serial_port.c + ymodem.c + download.cpp + log.cpp + checkversion.cpp + ) + +set_source_files_properties(download.cpp log.cpp PROPERTIES LANGUAGE CXX) + +target_link_libraries(ymodem-test pthread dl ${CURL_LIBRARIES}) \ No newline at end of file diff --git a/ymodem-master/LICENSE b/ymodem-master/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/ymodem-master/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/ymodem-master/Makefile b/ymodem-master/Makefile new file mode 100644 index 0000000..da130a8 --- /dev/null +++ b/ymodem-master/Makefile @@ -0,0 +1,22 @@ + +CROSS_COMPILE = /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf- + +LD = $(CROSS_COMPILE)gcc +CC = $(CROSS_COMPILE)gcc +TARGET = ymodem + +SRCS = $(wildcard *.c) +OBJS := $(patsubst %.c, %.o, $(SRCS)) + +LIBS = -L. + +all: $(TARGET) + +$(TARGET) : $(OBJS) + $(CC) $^ $(LIBS) -o $@ +$(OBJS): %.o:%.c + $(CC) -c $< $(INC) -o $@ + +.PHONY:clean +clean: + -rm $(OBJS) $(TARGET) diff --git a/ymodem-master/README.md b/ymodem-master/README.md new file mode 100644 index 0000000..9598cdd --- /dev/null +++ b/ymodem-master/README.md @@ -0,0 +1,97 @@ +由网上开源Ymodem代码修改而来,根据与服务器的通信协议以及传感器的协议做出以下修改: +1、定期查询version文件中的版本号version文件由update-engine工程中的updata进程负责下载 +2、定期向服务器查询当前传感器的版本号,并于version中的版本号做对比 +3、版本不一致,则进行升级 +4、根据与传感器的协议添加了升级失败时的失败代码的处理 + +以下时原工程的readme内容,有些方法可能失效: + +# ymodem +linux c ymodem + +### 在调用receive/send时,需要先设置好struct ymodem的几个回调函数.如ymodem_test中. + +### help +``` +/userdata/test # ./ymodem -h +Usage : ./ymodem [options] +options: +eg send Ymodem: ./ymodem -d /dev/ttyS0 -s /demo/bin/SE-app2.bin +eg receive Ymodem: ./ymodem -d /dev/ttyUSB0 + -d device path.设置设备名,默认/dev/ttyUSB0. + -s send Ymodem, receiving mode if not set.发送文件,如果不选,默认为接收文件 + -t Set getchar timeout,def:10(1s), 1=100ms.设置getchar超时,1为100毫秒,默认10=>1s. + --help display specific types of command line options. +``` + +### recevice file +``` +/userdata/test # ./ymodem -d /dev/ttyUSB0 +dev path: /dev/ttyUSB0 +open dev: /dev/ttyUSB0 +Receice Ymodem! + C + C + C +SOH 00 FF Data[128] CRC CRC + ACK + C +file name : xymodem.pdf, size : 53245 +STX 01 FE Data[1024] CRC CRC + ACK +STX 02 FD Data[1024] CRC CRC + ACK +. +. +. +STX 33 CC Data[1024] CRC CRC + ACK +STX 34 CB Data[1024] CRC CRC + ACK +EOT + NAK +EOT + ACK + C +SOH 00 FF Data[128] CRC CRC + ACK +Recevice complete! +file: xymodem.pdf, size: 53245 +/userdata/test # +``` + +### send file +``` +/userdata/test # +/userdata/test # ./ymodem -d /dev/ttyUSB0 -s xymodem.pdf +dev path: /dev/ttyUSB0 +send file: xymodem.pdf. +open dev: /dev/ttyUSB0 +Send Ymodem! file: xymodem.pdf + CAN + CAN + C +file name: xymodem.pdf, size: 53245 +SOH 00 FF Data[128] CRC CRC + ACK + C +STX 01 FE Data[1024] CRC CRC + ACK +STX 02 FD Data[1024] CRC CRC + ACK +. +. +. +STX 33 CC Data[1024] CRC CRC + ACK +STX 34 CB Data[1024] CRC CRC + ACK +EOT + NAK +EOT + ACK + C +SOH 00 FF Data[128] CRC CRC + ACK +Transfer complete! +``` \ No newline at end of file diff --git a/ymodem-master/build/CMakeCache.txt b/ymodem-master/build/CMakeCache.txt new file mode 100644 index 0000000..f3f0089 --- /dev/null +++ b/ymodem-master/build/CMakeCache.txt @@ -0,0 +1,449 @@ +# This is the CMakeCache file. +# For build in directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build +# It was generated by CMake: /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9 + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/pkgRedirects + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=ymodem-test + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//The directory containing a CMake configuration file for CURL. +CURL_DIR:PATH=CURL_DIR-NOTFOUND + +//Path to a file. +CURL_INCLUDE_DIR:PATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include + +//Path to a library. +CURL_LIBRARY_DEBUG:FILEPATH=CURL_LIBRARY_DEBUG-NOTFOUND + +//Path to a library. +CURL_LIBRARY_RELEASE:FILEPATH=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so + +//Arguments to supply to pkg-config +PKG_CONFIG_ARGN:STRING= + +//pkg-config executable +PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config + +//Path to a library. +pkgcfg_lib_PC_CURL_curl:FILEPATH=/usr/lib/x86_64-linux-gnu/libcurl.so + +//Value Computed by CMake +ymodem-test_BINARY_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build + +//Value Computed by CMake +ymodem-test_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +ymodem-test_SOURCE_DIR:STATIC=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=26 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=0 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_DIR +CURL_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_INCLUDE_DIR +CURL_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_DEBUG +CURL_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CURL_LIBRARY_RELEASE +CURL_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 +//Details about finding CURL +FIND_PACKAGE_MESSAGE_DETAILS_CURL:INTERNAL=[/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so][/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include][c ][v7.75.0()] +PC_CURL_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_CFLAGS_I:INTERNAL= +PC_CURL_CFLAGS_OTHER:INTERNAL= +PC_CURL_FOUND:INTERNAL=1 +PC_CURL_INCLUDEDIR:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-lcurl +PC_CURL_LDFLAGS_OTHER:INTERNAL= +PC_CURL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBRARIES:INTERNAL=curl +PC_CURL_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu +PC_CURL_LIBS:INTERNAL= +PC_CURL_LIBS_L:INTERNAL= +PC_CURL_LIBS_OTHER:INTERNAL= +PC_CURL_LIBS_PATHS:INTERNAL= +PC_CURL_MODULE_NAME:INTERNAL=libcurl +PC_CURL_PREFIX:INTERNAL=/usr +PC_CURL_STATIC_CFLAGS:INTERNAL=-I/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_CFLAGS_I:INTERNAL= +PC_CURL_STATIC_CFLAGS_OTHER:INTERNAL= +PC_CURL_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/x86_64-linux-gnu +PC_CURL_STATIC_LDFLAGS:INTERNAL=-L/usr/lib/x86_64-linux-gnu;-L/usr/lib/x86_64-linux-gnu/mit-krb5;-lcurl;-lnghttp2;-lidn2;-lrtmp;-lssh;-lpsl;-lssl;-lcrypto;-lssl;-lcrypto;-Wl,-Bsymbolic-functions;-Wl,-z,relro;-lgssapi_krb5;-lkrb5;-lk5crypto;-lcom_err;-llber;-lldap;-llber;-lbrotlidec;-lz +PC_CURL_STATIC_LDFLAGS_OTHER:INTERNAL=-Wl,-Bsymbolic-functions;-Wl,-z,relro +PC_CURL_STATIC_LIBDIR:INTERNAL= +PC_CURL_STATIC_LIBRARIES:INTERNAL=curl;nghttp2;idn2;rtmp;ssh;psl;ssl;crypto;ssl;crypto;gssapi_krb5;krb5;k5crypto;com_err;lber;ldap;lber;brotlidec;z +PC_CURL_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib/x86_64-linux-gnu;/usr/lib/x86_64-linux-gnu/mit-krb5 +PC_CURL_STATIC_LIBS:INTERNAL= +PC_CURL_STATIC_LIBS_L:INTERNAL= +PC_CURL_STATIC_LIBS_OTHER:INTERNAL= +PC_CURL_STATIC_LIBS_PATHS:INTERNAL= +PC_CURL_VERSION:INTERNAL=7.68.0 +PC_CURL_libcurl_INCLUDEDIR:INTERNAL= +PC_CURL_libcurl_LIBDIR:INTERNAL= +PC_CURL_libcurl_PREFIX:INTERNAL= +PC_CURL_libcurl_VERSION:INTERNAL= +//ADVANCED property for variable: PKG_CONFIG_ARGN +PKG_CONFIG_ARGN-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE +PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1 +//linker supports push/pop state +_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED:INTERNAL=TRUE +__pkg_config_arguments_PC_CURL:INTERNAL=QUIET;libcurl +__pkg_config_checked_PC_CURL:INTERNAL=1 +//ADVANCED property for variable: pkgcfg_lib_PC_CURL_curl +pkgcfg_lib_PC_CURL_curl-ADVANCED:INTERNAL=1 +prefix_result:INTERNAL=SSL;IPv6;UnixSockets;libz;brotli;AsynchDNS;IDN;GSS-API;PSL;SPNEGO;Kerberos;NTLM;NTLM_WB;TLS-SRP;HTTP2;HTTPS-proxy + diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake b/ymodem-master/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake new file mode 100644 index 0000000..db12033 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/3.26.0/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "9.4.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake b/ymodem-master/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..9950db3 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/3.26.0/CMakeCXXCompiler.cmake @@ -0,0 +1,83 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "9.4.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "") + +set(CMAKE_CXX_PLATFORM_ID "Linux") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_CXX_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar-9") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib-9") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin b/ymodem-master/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000..d10d50b Binary files /dev/null and b/ymodem-master/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_C.bin differ diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin b/ymodem-master/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin new file mode 100644 index 0000000..61bb758 Binary files /dev/null and b/ymodem-master/build/CMakeFiles/3.26.0/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CMakeSystem.cmake b/ymodem-master/build/CMakeFiles/3.26.0/CMakeSystem.cmake new file mode 100644 index 0000000..9da78d2 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/3.26.0/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-5.15.0-87-generic") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "5.15.0-87-generic") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-5.15.0-87-generic") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "5.15.0-87-generic") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c b/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..88155ff --- /dev/null +++ b/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,866 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp b/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..746b167 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,855 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/ymodem-master/build/CMakeFiles/CMakeConfigureLog.yaml b/ymodem-master/build/CMakeFiles/CMakeConfigureLog.yaml new file mode 100644 index 0000000..f495da3 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/CMakeConfigureLog.yaml @@ -0,0 +1,529 @@ + +--- +events: + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineSystem.cmake:204 (message)" + - "CMakeLists.txt:1 (project)" + message: | + The system is: Linux - 5.15.0-87-generic - x86_64 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:1 (project)" + message: | + Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. + Compiler: /usr/bin/c++ + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + + The CXX compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdCXX/a.out + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCCompiler.cmake:123 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:1 (project)" + message: | + Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. + Compiler: /usr/bin/cc + Build flags: + Id flags: + + The output was: + 0 + + + Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + + The C compiler identification is GNU, found in: + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/3.26.0/CompilerIdC/a.out + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:1 (project)" + checks: + - "Detecting CXX compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh" + cmakeVariables: + CMAKE_CXX_FLAGS: "" + buildResult: + variable: "CMAKE_CXX_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_caa1b/fast && /usr/bin/make -f CMakeFiles/cmTC_caa1b.dir/build.make CMakeFiles/cmTC_caa1b.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh' + Building CXX object CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o + /usr/bin/c++ -v -o CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccGb2dry.s + GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9" + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/include/c++/9 + /usr/include/x86_64-linux-gnu/c++/9 + /usr/include/c++/9/backward + /usr/lib/gcc/x86_64-linux-gnu/9/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 3d1eba838554fa2348dba760e4770469 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccGb2dry.s + GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34 + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + Linking CXX executable cmTC_caa1b + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_caa1b.dir/link.txt --verbose=1 + /usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_caa1b + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_caa1b' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJeFa0X.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_caa1b /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_caa1b' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:1 (project)" + message: | + Parsed CXX implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/include/c++/9] + add: [/usr/include/x86_64-linux-gnu/c++/9] + add: [/usr/include/c++/9/backward] + add: [/usr/lib/gcc/x86_64-linux-gnu/9/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/include/c++/9] ==> [/usr/include/c++/9] + collapse include dir [/usr/include/x86_64-linux-gnu/c++/9] ==> [/usr/include/x86_64-linux-gnu/c++/9] + collapse include dir [/usr/include/c++/9/backward] ==> [/usr/include/c++/9/backward] + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/9;/usr/include/x86_64-linux-gnu/c++/9;/usr/include/c++/9/backward;/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:1 (project)" + message: | + Parsed CXX implicit link information: + link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_caa1b/fast && /usr/bin/make -f CMakeFiles/cmTC_caa1b.dir/build.make CMakeFiles/cmTC_caa1b.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-dHVAJh'] + ignore line: [Building CXX object CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -v -o CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpbase CMakeCXXCompilerABI.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccGb2dry.s] + ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/9"] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/include/c++/9] + ignore line: [ /usr/include/x86_64-linux-gnu/c++/9] + ignore line: [ /usr/include/c++/9/backward] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C++14 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 3d1eba838554fa2348dba760e4770469] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccGb2dry.s] + ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking CXX executable cmTC_caa1b] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_caa1b.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v -rdynamic CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_caa1b ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_caa1b' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccJeFa0X.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_caa1b /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/ccJeFa0X.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_caa1b] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] + arg [CMakeFiles/cmTC_caa1b.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;c;gcc_s;gcc] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + + - + kind: "try_compile-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:1 (project)" + checks: + - "Detecting C compiler ABI info" + directories: + source: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh" + binary: "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh" + cmakeVariables: + CMAKE_C_FLAGS: "" + buildResult: + variable: "CMAKE_C_ABI_COMPILED" + cached: true + stdout: | + Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh + + Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_36f48/fast && /usr/bin/make -f CMakeFiles/cmTC_36f48.dir/build.make CMakeFiles/cmTC_36f48.dir/build + make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh' + Building C object CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o + /usr/bin/cc -v -o CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c + Using built-in specs. + COLLECT_GCC=/usr/bin/cc + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccLx0d6F.s + GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/lib/gcc/x86_64-linux-gnu/9/include + /usr/local/include + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu) + compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP + + GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 + Compiler executable checksum: 01da938ff5dc2163489aa33cb3b747a7 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + as -v --64 -o CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o /tmp/ccLx0d6F.s + GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34 + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64' + Linking C executable cmTC_36f48 + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_36f48.dir/link.txt --verbose=1 + /usr/bin/cc -v -rdynamic CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -o cmTC_36f48 + Using built-in specs. + COLLECT_GCC=/usr/bin/cc + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper + OFFLOAD_TARGET_NAMES=nvptx-none:hsa + OFFLOAD_TARGET_DEFAULT=1 + Target: x86_64-linux-gnu + Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu + Thread model: posix + gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) + COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_36f48' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc6QXCe6.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_36f48 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o + COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_36f48' '-mtune=generic' '-march=x86-64' + make[1]: Leaving directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:127 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:1 (project)" + message: | + Parsed C implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-linux-gnu/9/include] + add: [/usr/local/include] + add: [/usr/include/x86_64-linux-gnu] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-linux-gnu/9/include] ==> [/usr/lib/gcc/x86_64-linux-gnu/9/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include/x86_64-linux-gnu] ==> [/usr/include/x86_64-linux-gnu] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/lib/gcc/x86_64-linux-gnu/9/include;/usr/local/include;/usr/include/x86_64-linux-gnu;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeDetermineCompilerABI.cmake:152 (message)" + - "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:1 (project)" + message: | + Parsed C implicit link information: + link line regex: [^( *|.*[/\\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + ignore line: [Change Dir: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh] + ignore line: [] + ignore line: [Run Build Command(s):/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E env VERBOSE=1 /usr/bin/make -f Makefile cmTC_36f48/fast && /usr/bin/make -f CMakeFiles/cmTC_36f48.dir/build.make CMakeFiles/cmTC_36f48.dir/build] + ignore line: [make[1]: Entering directory '/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/CMakeScratch/TryCompile-Siu3Vh'] + ignore line: [Building C object CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -v -o CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -c /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu /home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccLx0d6F.s] + ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-linux-gnu/9/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include/x86_64-linux-gnu] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.2) version 9.4.0 (x86_64-linux-gnu)] + ignore line: [ compiled by GNU C version 9.4.0 GMP version 6.2.0 MPFR version 4.0.2 MPC version 1.1.0 isl version isl-0.22.1-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [Compiler executable checksum: 01da938ff5dc2163489aa33cb3b747a7] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o /tmp/ccLx0d6F.s] + ignore line: [GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o' '-c' '-mtune=generic' '-march=x86-64'] + ignore line: [Linking C executable cmTC_36f48] + ignore line: [/home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E cmake_link_script CMakeFiles/cmTC_36f48.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -o cmTC_36f48 ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none:hsa] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c ada c++ go brig d fortran objc obj-c++ gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32 m64 mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_36f48' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc6QXCe6.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_36f48 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/cc6QXCe6.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_36f48] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] + arg [CMakeFiles/cmTC_36f48.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o] ==> [/usr/lib/x86_64-linux-gnu/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o] ==> [/usr/lib/x86_64-linux-gnu/crti.o] + collapse obj [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o] ==> [/usr/lib/x86_64-linux-gnu/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9] ==> [/usr/lib/gcc/x86_64-linux-gnu/9] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/9/../../..] ==> [/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit objs: [/usr/lib/x86_64-linux-gnu/Scrt1.o;/usr/lib/x86_64-linux-gnu/crti.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o;/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o;/usr/lib/x86_64-linux-gnu/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/9;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + +... diff --git a/ymodem-master/build/CMakeFiles/CMakeDirectoryInformation.cmake b/ymodem-master/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..ec30a06 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/ymodem-master/build/CMakeFiles/Makefile.cmake b/ymodem-master/build/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..361a46e --- /dev/null +++ b/ymodem-master/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,52 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCXXInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeCommonLanguageInclude.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeGenericSystem.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeInitializeConfigs.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeLanguageInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeSystemSpecificInformation.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/CMakeSystemSpecificInitialize.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU-C.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU-CXX.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Compiler/GNU.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindCURL.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageHandleStandardArgs.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageMessage.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/FindPkgConfig.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU-C.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU-CXX.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux-GNU.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/Linux.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/Platform/UnixPaths.cmake" + "/home/atk/.local/lib/python3.8/site-packages/cmake/data/share/cmake-3.26/Modules/SelectLibraryConfigurations.cmake" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/CMakeLists.txt" + "CMakeFiles/3.26.0/CMakeCCompiler.cmake" + "CMakeFiles/3.26.0/CMakeCXXCompiler.cmake" + "CMakeFiles/3.26.0/CMakeSystem.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/ymodem-test.dir/DependInfo.cmake" + ) diff --git a/ymodem-master/build/CMakeFiles/Makefile2 b/ymodem-master/build/CMakeFiles/Makefile2 new file mode 100644 index 0000000..6fd1ca4 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/Makefile2 @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build + +#============================================================================= +# Directory level rules for the build root directory + +# The main recursive "all" target. +all: CMakeFiles/ymodem-test.dir/all +.PHONY : all + +# The main recursive "preinstall" target. +preinstall: +.PHONY : preinstall + +# The main recursive "clean" target. +clean: CMakeFiles/ymodem-test.dir/clean +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/ymodem-test.dir + +# All Build rule for target. +CMakeFiles/ymodem-test.dir/all: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/depend + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=1,2,3,4,5,6,7 "Built target ymodem-test" +.PHONY : CMakeFiles/ymodem-test.dir/all + +# Build rule for subdir invocation for target. +CMakeFiles/ymodem-test.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles 7 + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 CMakeFiles/ymodem-test.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles 0 +.PHONY : CMakeFiles/ymodem-test.dir/rule + +# Convenience name for target. +ymodem-test: CMakeFiles/ymodem-test.dir/rule +.PHONY : ymodem-test + +# clean rule for target. +CMakeFiles/ymodem-test.dir/clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/clean +.PHONY : CMakeFiles/ymodem-test.dir/clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/ymodem-master/build/CMakeFiles/TargetDirectories.txt b/ymodem-master/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..0f4345f --- /dev/null +++ b/ymodem-master/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/ymodem-test.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/edit_cache.dir +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/rebuild_cache.dir diff --git a/ymodem-master/build/CMakeFiles/cmake.check_cache b/ymodem-master/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/ymodem-master/build/CMakeFiles/progress.marks b/ymodem-master/build/CMakeFiles/progress.marks new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/progress.marks @@ -0,0 +1 @@ +7 diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/DependInfo.cmake b/ymodem-master/build/CMakeFiles/ymodem-test.dir/DependInfo.cmake new file mode 100644 index 0000000..14b963f --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/DependInfo.cmake @@ -0,0 +1,24 @@ + +# Consider dependencies only in project. +set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) + +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + ) + +# The set of dependency files which are needed: +set(CMAKE_DEPENDS_DEPENDENCY_FILES + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c" "CMakeFiles/ymodem-test.dir/serial_port.c.o" "gcc" "CMakeFiles/ymodem-test.dir/serial_port.c.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c" "CMakeFiles/ymodem-test.dir/ymodem.c.o" "gcc" "CMakeFiles/ymodem-test.dir/ymodem.c.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp" "CMakeFiles/ymodem-test.dir/checkversion.cpp.o" "gcc" "CMakeFiles/ymodem-test.dir/checkversion.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp" "CMakeFiles/ymodem-test.dir/download.cpp.o" "gcc" "CMakeFiles/ymodem-test.dir/download.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp" "CMakeFiles/ymodem-test.dir/log.cpp.o" "gcc" "CMakeFiles/ymodem-test.dir/log.cpp.o.d" + "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp" "CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o" "gcc" "CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o.d" + ) + +# Targets to which this target links which contain Fortran sources. +set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/build.make b/ymodem-master/build/CMakeFiles/ymodem-test.dir/build.make new file mode 100644 index 0000000..89f8929 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/build.make @@ -0,0 +1,191 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build + +# Include any dependencies generated for this target. +include CMakeFiles/ymodem-test.dir/depend.make +# Include any dependencies generated by the compiler for this target. +include CMakeFiles/ymodem-test.dir/compiler_depend.make + +# Include the progress variables for this target. +include CMakeFiles/ymodem-test.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/ymodem-test.dir/flags.make + +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o: CMakeFiles/ymodem-test.dir/flags.make +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o: CMakeFiles/ymodem-test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o -MF CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o.d -o CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp + +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/ymodem-test.dir/ymodem_test.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp > CMakeFiles/ymodem-test.dir/ymodem_test.cpp.i + +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/ymodem-test.dir/ymodem_test.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp -o CMakeFiles/ymodem-test.dir/ymodem_test.cpp.s + +CMakeFiles/ymodem-test.dir/serial_port.c.o: CMakeFiles/ymodem-test.dir/flags.make +CMakeFiles/ymodem-test.dir/serial_port.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c +CMakeFiles/ymodem-test.dir/serial_port.c.o: CMakeFiles/ymodem-test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/ymodem-test.dir/serial_port.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/ymodem-test.dir/serial_port.c.o -MF CMakeFiles/ymodem-test.dir/serial_port.c.o.d -o CMakeFiles/ymodem-test.dir/serial_port.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c + +CMakeFiles/ymodem-test.dir/serial_port.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/ymodem-test.dir/serial_port.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c > CMakeFiles/ymodem-test.dir/serial_port.c.i + +CMakeFiles/ymodem-test.dir/serial_port.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/ymodem-test.dir/serial_port.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c -o CMakeFiles/ymodem-test.dir/serial_port.c.s + +CMakeFiles/ymodem-test.dir/ymodem.c.o: CMakeFiles/ymodem-test.dir/flags.make +CMakeFiles/ymodem-test.dir/ymodem.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c +CMakeFiles/ymodem-test.dir/ymodem.c.o: CMakeFiles/ymodem-test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building C object CMakeFiles/ymodem-test.dir/ymodem.c.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/ymodem-test.dir/ymodem.c.o -MF CMakeFiles/ymodem-test.dir/ymodem.c.o.d -o CMakeFiles/ymodem-test.dir/ymodem.c.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c + +CMakeFiles/ymodem-test.dir/ymodem.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/ymodem-test.dir/ymodem.c.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c > CMakeFiles/ymodem-test.dir/ymodem.c.i + +CMakeFiles/ymodem-test.dir/ymodem.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/ymodem-test.dir/ymodem.c.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c -o CMakeFiles/ymodem-test.dir/ymodem.c.s + +CMakeFiles/ymodem-test.dir/download.cpp.o: CMakeFiles/ymodem-test.dir/flags.make +CMakeFiles/ymodem-test.dir/download.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp +CMakeFiles/ymodem-test.dir/download.cpp.o: CMakeFiles/ymodem-test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object CMakeFiles/ymodem-test.dir/download.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/ymodem-test.dir/download.cpp.o -MF CMakeFiles/ymodem-test.dir/download.cpp.o.d -o CMakeFiles/ymodem-test.dir/download.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp + +CMakeFiles/ymodem-test.dir/download.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/ymodem-test.dir/download.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp > CMakeFiles/ymodem-test.dir/download.cpp.i + +CMakeFiles/ymodem-test.dir/download.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/ymodem-test.dir/download.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp -o CMakeFiles/ymodem-test.dir/download.cpp.s + +CMakeFiles/ymodem-test.dir/log.cpp.o: CMakeFiles/ymodem-test.dir/flags.make +CMakeFiles/ymodem-test.dir/log.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp +CMakeFiles/ymodem-test.dir/log.cpp.o: CMakeFiles/ymodem-test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object CMakeFiles/ymodem-test.dir/log.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/ymodem-test.dir/log.cpp.o -MF CMakeFiles/ymodem-test.dir/log.cpp.o.d -o CMakeFiles/ymodem-test.dir/log.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp + +CMakeFiles/ymodem-test.dir/log.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/ymodem-test.dir/log.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp > CMakeFiles/ymodem-test.dir/log.cpp.i + +CMakeFiles/ymodem-test.dir/log.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/ymodem-test.dir/log.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp -o CMakeFiles/ymodem-test.dir/log.cpp.s + +CMakeFiles/ymodem-test.dir/checkversion.cpp.o: CMakeFiles/ymodem-test.dir/flags.make +CMakeFiles/ymodem-test.dir/checkversion.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp +CMakeFiles/ymodem-test.dir/checkversion.cpp.o: CMakeFiles/ymodem-test.dir/compiler_depend.ts + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building CXX object CMakeFiles/ymodem-test.dir/checkversion.cpp.o" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/ymodem-test.dir/checkversion.cpp.o -MF CMakeFiles/ymodem-test.dir/checkversion.cpp.o.d -o CMakeFiles/ymodem-test.dir/checkversion.cpp.o -c /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp + +CMakeFiles/ymodem-test.dir/checkversion.cpp.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/ymodem-test.dir/checkversion.cpp.i" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp > CMakeFiles/ymodem-test.dir/checkversion.cpp.i + +CMakeFiles/ymodem-test.dir/checkversion.cpp.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/ymodem-test.dir/checkversion.cpp.s" + /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp -o CMakeFiles/ymodem-test.dir/checkversion.cpp.s + +# Object files for target ymodem-test +ymodem__test_OBJECTS = \ +"CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o" \ +"CMakeFiles/ymodem-test.dir/serial_port.c.o" \ +"CMakeFiles/ymodem-test.dir/ymodem.c.o" \ +"CMakeFiles/ymodem-test.dir/download.cpp.o" \ +"CMakeFiles/ymodem-test.dir/log.cpp.o" \ +"CMakeFiles/ymodem-test.dir/checkversion.cpp.o" + +# External object files for target ymodem-test +ymodem__test_EXTERNAL_OBJECTS = + +ymodem-test: CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o +ymodem-test: CMakeFiles/ymodem-test.dir/serial_port.c.o +ymodem-test: CMakeFiles/ymodem-test.dir/ymodem.c.o +ymodem-test: CMakeFiles/ymodem-test.dir/download.cpp.o +ymodem-test: CMakeFiles/ymodem-test.dir/log.cpp.o +ymodem-test: CMakeFiles/ymodem-test.dir/checkversion.cpp.o +ymodem-test: CMakeFiles/ymodem-test.dir/build.make +ymodem-test: /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so +ymodem-test: CMakeFiles/ymodem-test.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Linking CXX executable ymodem-test" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/ymodem-test.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/ymodem-test.dir/build: ymodem-test +.PHONY : CMakeFiles/ymodem-test.dir/build + +CMakeFiles/ymodem-test.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/ymodem-test.dir/cmake_clean.cmake +.PHONY : CMakeFiles/ymodem-test.dir/clean + +CMakeFiles/ymodem-test.dir/depend: + cd /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles/ymodem-test.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/ymodem-test.dir/depend + diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/cmake_clean.cmake b/ymodem-master/build/CMakeFiles/ymodem-test.dir/cmake_clean.cmake new file mode 100644 index 0000000..1b1bbc0 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/cmake_clean.cmake @@ -0,0 +1,21 @@ +file(REMOVE_RECURSE + "CMakeFiles/ymodem-test.dir/checkversion.cpp.o" + "CMakeFiles/ymodem-test.dir/checkversion.cpp.o.d" + "CMakeFiles/ymodem-test.dir/download.cpp.o" + "CMakeFiles/ymodem-test.dir/download.cpp.o.d" + "CMakeFiles/ymodem-test.dir/log.cpp.o" + "CMakeFiles/ymodem-test.dir/log.cpp.o.d" + "CMakeFiles/ymodem-test.dir/serial_port.c.o" + "CMakeFiles/ymodem-test.dir/serial_port.c.o.d" + "CMakeFiles/ymodem-test.dir/ymodem.c.o" + "CMakeFiles/ymodem-test.dir/ymodem.c.o.d" + "CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o" + "CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o.d" + "ymodem-test" + "ymodem-test.pdb" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C CXX) + include(CMakeFiles/ymodem-test.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.internal b/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.internal new file mode 100644 index 0000000..2388132 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.internal @@ -0,0 +1,707 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/ymodem-test.dir/checkversion.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc + +CMakeFiles/ymodem-test.dir/download.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.h + +CMakeFiles/ymodem-test.dir/log.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + +CMakeFiles/ymodem-test.dir/serial_port.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + +CMakeFiles/ymodem-test.dir/ymodem.c.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.h + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h + diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.make b/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.make new file mode 100644 index 0000000..b1d3d13 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.make @@ -0,0 +1,1257 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +CMakeFiles/ymodem-test.dir/checkversion.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc + +CMakeFiles/ymodem-test.dir/download.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.h + +CMakeFiles/ymodem-test.dir/log.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h + +CMakeFiles/ymodem-test.dir/serial_port.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h + +CMakeFiles/ymodem-test.dir/ymodem.c.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h + +CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h \ + /opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.h \ + /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h \ + /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h + + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/semaphore.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/semaphore.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/getopt.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/tuple: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_conv.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/messages_members.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/locale: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iomanip: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf_iterator.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/clocale: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/std_abs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/cdefs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/socket.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cctype: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/istream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/invoke.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/typeinfo: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/os_defines.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigthread.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_ptr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/alloca.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/socket.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/range_access.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdint: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/istream.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets_nonio.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ctime: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/move.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigset_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/codecvt.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/type_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/nested_exception.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/postypes.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functexcept.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/exception_defines.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/exception: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/easy.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/char_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/numeric_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/xopen_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stringfwd.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/string: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/assertions.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stddef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ptr_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/unistd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/timex.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/fcntl.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/utility: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stat.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_iovec.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/pthreadtypes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigval_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uintn-identity.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_posix.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/stat.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/cpu-set.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdlib: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/uses_allocator.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigset_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_types.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sys_errlist.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/debug/debug.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/wint_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_core.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++locale.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/limits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwchar: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wctype.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clock_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/cookie_io_functions_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdlib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/error_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-uintn.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstdio: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/libc-header-start.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/type_traits: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/ioctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/confname.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__mbstate_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix_opt.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/timer_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/clockid_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/errno.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/checkversion.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/pthread.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/streambuf: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs-hard.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/time_members.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdc-predef.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdint-intn.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/stack_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_pair.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitstatus.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/new: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_function.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdint.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/features.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdlib-float.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wordsize.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/errno.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++io.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdint.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator_base_funcs.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_itimerspec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/functional_hash.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timeval.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ucontext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/typesizes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigstack.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem_test.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sched.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_iterator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/endian.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-consts-arch.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/environments.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/long-double.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/string_conversions.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/time_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/stdio_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include/stdarg.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/errno.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/ctype.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/wctype-wchar.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/strings.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cwctype: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/errno.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/memoryfwd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/FILE.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/endian.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/fcntl-linux.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/multi.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_vector.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/statx.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/system_error: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/locale.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/cpu_defines.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/waitflags.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_algobase.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/string.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_relops.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno-base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/uio_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/floatn-common.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/locale.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/atomic_word.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/hash_bytes.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/system.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iosfwd: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ostream_insert.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/unique_ptr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/gnu/stubs.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_forced.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/backward/binders.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/falloc.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/atomicity.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/gthr-default.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sched.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sched_param.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/time.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cpp_type_traits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_construct.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/time.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_tm.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/siginfo_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/thread-shared-types.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/alloc_traits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/locale_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/time.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ostream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/cxxabi_init_exception.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ios: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_timespec.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/ios_base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/libintl.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/predefined_ops.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_string.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_classes.tcc: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/error_constants.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_uninitialized.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdexcept: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/streambuf.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix2_lim.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/locale_facets.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_base.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/select.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/limits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/ctype_inline.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/basic_ios.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/curlver.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sockaddr.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sigevent_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cerrno: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_osockaddr.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/stdlib.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/termios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/setjmp.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/iostream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/c++config.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/stl_bvector.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/limits.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed/syslimits.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/posix1_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/local_lim.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/urlapi.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/curl/options.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/concept_check.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/fstream: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/arm-linux-gnueabihf/bits/basic_file.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigevent-consts.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/fstream.tcc: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/download.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/getopt_ext.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/socket_type.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/cstring: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.c: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/serial_port.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/localefwd.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/termios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/signum-generic.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/sys/ttydefaults.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/errno.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/initializer_list: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm/ioctl.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/ioctl.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/ymodem.c: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/array: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__fpos64_t.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/vector: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/signal.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/sig_atomic_t.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/asm-generic/sockios.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/__sigval_t.h: + +/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/log.cpp: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/siginfo-arch.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/ext/new_allocator.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigaction.h: + +/opt/atk-dlrv1126-toolchain/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/8.3.0/bits/vector.tcc: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/sigcontext.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/ss_flags.h: + +/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/types/struct_sigstack.h: diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.ts b/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.ts new file mode 100644 index 0000000..20859ce --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/compiler_depend.ts @@ -0,0 +1,2 @@ +# CMAKE generated file: DO NOT EDIT! +# Timestamp file for compiler generated dependencies management for ymodem-test. diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/depend.make b/ymodem-master/build/CMakeFiles/ymodem-test.dir/depend.make new file mode 100644 index 0000000..91268d1 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/depend.make @@ -0,0 +1,2 @@ +# Empty dependencies file for ymodem-test. +# This may be replaced when dependencies are built. diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/flags.make b/ymodem-master/build/CMakeFiles/ymodem-test.dir/flags.make new file mode 100644 index 0000000..faf954c --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/flags.make @@ -0,0 +1,17 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# compile C with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-gcc +# compile CXX with /opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ +C_DEFINES = + +C_INCLUDES = -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/. + +C_FLAGS = -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + +CXX_DEFINES = + +CXX_INCLUDES = -I/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include -I/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/. + +CXX_FLAGS = -std=gnu++11 -g -O0 -ggdb -gdwarf -funwind-tables -rdynamic -Wno-write-strings -Wno-return-type + diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/link.txt b/ymodem-master/build/CMakeFiles/ymodem-test.dir/link.txt new file mode 100644 index 0000000..628ef78 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/link.txt @@ -0,0 +1 @@ +/opt/atk-dlrv1126-toolchain/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot "CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o" "CMakeFiles/ymodem-test.dir/serial_port.c.o" "CMakeFiles/ymodem-test.dir/ymodem.c.o" "CMakeFiles/ymodem-test.dir/download.cpp.o" "CMakeFiles/ymodem-test.dir/log.cpp.o" "CMakeFiles/ymodem-test.dir/checkversion.cpp.o" -o ymodem-test -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/include -L/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/. -Wl,-rpath,/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/include:/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/.:/usr/lib -lpthread -ldl /opt/atk-dlrv1126-toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libcurl.so diff --git a/ymodem-master/build/CMakeFiles/ymodem-test.dir/progress.make b/ymodem-master/build/CMakeFiles/ymodem-test.dir/progress.make new file mode 100644 index 0000000..2f82315 --- /dev/null +++ b/ymodem-master/build/CMakeFiles/ymodem-test.dir/progress.make @@ -0,0 +1,8 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 +CMAKE_PROGRESS_3 = 3 +CMAKE_PROGRESS_4 = 4 +CMAKE_PROGRESS_5 = 5 +CMAKE_PROGRESS_6 = 6 +CMAKE_PROGRESS_7 = 7 + diff --git a/ymodem-master/build/Makefile b/ymodem-master/build/Makefile new file mode 100644 index 0000000..2d6c633 --- /dev/null +++ b/ymodem-master/build/Makefile @@ -0,0 +1,316 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.26 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake + +# The command to remove a file. +RM = /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /home/atk/.local/lib/python3.8/site-packages/cmake/data/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named ymodem-test + +# Build rule for target. +ymodem-test: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 ymodem-test +.PHONY : ymodem-test + +# fast build rule for target. +ymodem-test/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/build +.PHONY : ymodem-test/fast + +checkversion.o: checkversion.cpp.o +.PHONY : checkversion.o + +# target to build an object file +checkversion.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/checkversion.cpp.o +.PHONY : checkversion.cpp.o + +checkversion.i: checkversion.cpp.i +.PHONY : checkversion.i + +# target to preprocess a source file +checkversion.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/checkversion.cpp.i +.PHONY : checkversion.cpp.i + +checkversion.s: checkversion.cpp.s +.PHONY : checkversion.s + +# target to generate assembly for a file +checkversion.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/checkversion.cpp.s +.PHONY : checkversion.cpp.s + +download.o: download.cpp.o +.PHONY : download.o + +# target to build an object file +download.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/download.cpp.o +.PHONY : download.cpp.o + +download.i: download.cpp.i +.PHONY : download.i + +# target to preprocess a source file +download.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/download.cpp.i +.PHONY : download.cpp.i + +download.s: download.cpp.s +.PHONY : download.s + +# target to generate assembly for a file +download.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/download.cpp.s +.PHONY : download.cpp.s + +log.o: log.cpp.o +.PHONY : log.o + +# target to build an object file +log.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/log.cpp.o +.PHONY : log.cpp.o + +log.i: log.cpp.i +.PHONY : log.i + +# target to preprocess a source file +log.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/log.cpp.i +.PHONY : log.cpp.i + +log.s: log.cpp.s +.PHONY : log.s + +# target to generate assembly for a file +log.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/log.cpp.s +.PHONY : log.cpp.s + +serial_port.o: serial_port.c.o +.PHONY : serial_port.o + +# target to build an object file +serial_port.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/serial_port.c.o +.PHONY : serial_port.c.o + +serial_port.i: serial_port.c.i +.PHONY : serial_port.i + +# target to preprocess a source file +serial_port.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/serial_port.c.i +.PHONY : serial_port.c.i + +serial_port.s: serial_port.c.s +.PHONY : serial_port.s + +# target to generate assembly for a file +serial_port.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/serial_port.c.s +.PHONY : serial_port.c.s + +ymodem.o: ymodem.c.o +.PHONY : ymodem.o + +# target to build an object file +ymodem.c.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/ymodem.c.o +.PHONY : ymodem.c.o + +ymodem.i: ymodem.c.i +.PHONY : ymodem.i + +# target to preprocess a source file +ymodem.c.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/ymodem.c.i +.PHONY : ymodem.c.i + +ymodem.s: ymodem.c.s +.PHONY : ymodem.s + +# target to generate assembly for a file +ymodem.c.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/ymodem.c.s +.PHONY : ymodem.c.s + +ymodem_test.o: ymodem_test.cpp.o +.PHONY : ymodem_test.o + +# target to build an object file +ymodem_test.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/ymodem_test.cpp.o +.PHONY : ymodem_test.cpp.o + +ymodem_test.i: ymodem_test.cpp.i +.PHONY : ymodem_test.i + +# target to preprocess a source file +ymodem_test.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/ymodem_test.cpp.i +.PHONY : ymodem_test.cpp.i + +ymodem_test.s: ymodem_test.cpp.s +.PHONY : ymodem_test.s + +# target to generate assembly for a file +ymodem_test.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/ymodem-test.dir/build.make CMakeFiles/ymodem-test.dir/ymodem_test.cpp.s +.PHONY : ymodem_test.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... ymodem-test" + @echo "... checkversion.o" + @echo "... checkversion.i" + @echo "... checkversion.s" + @echo "... download.o" + @echo "... download.i" + @echo "... download.s" + @echo "... log.o" + @echo "... log.i" + @echo "... log.s" + @echo "... serial_port.o" + @echo "... serial_port.i" + @echo "... serial_port.s" + @echo "... ymodem.o" + @echo "... ymodem.i" + @echo "... ymodem.s" + @echo "... ymodem_test.o" + @echo "... ymodem_test.i" + @echo "... ymodem_test.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/ymodem-master/build/cmake_install.cmake b/ymodem-master/build/cmake_install.cmake new file mode 100644 index 0000000..0b72009 --- /dev/null +++ b/ymodem-master/build/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/atk/RV1126/rv1126_ai/by_cmake/720P/ymodem-master/build/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/ymodem-master/build/ymodem-test b/ymodem-master/build/ymodem-test new file mode 100644 index 0000000..9f146da Binary files /dev/null and b/ymodem-master/build/ymodem-test differ diff --git a/ymodem-master/checkversion.cpp b/ymodem-master/checkversion.cpp new file mode 100644 index 0000000..3f56295 --- /dev/null +++ b/ymodem-master/checkversion.cpp @@ -0,0 +1,223 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "checkversion.h" +#include +#include +#include +#include +#include + + +char _save_APP_path[100] = {0}; +#define LOCAL_VERSION_PATH "/demo/bin/version" +#define DOWNLOAD_VERSION_PATH "/tmp/version" + +#define DeviceID_FILE "/etc/DeviceID" +std::string DeviceID ; +#define URL_FILE "/demo/bin/URL/CheckAPPVersion" +std::string BASE_URL_string; +std::string URL_string; +std::string local_app_version; + +// 函数用于读取文件并将其内容保存在全局字符串变量中 +void readFileAndStoreInGlobal(const std::string& filename, std::string& destination) { + std::ifstream file(filename); + + if (file.is_open()) { + std::getline(file, destination); // 读取一行并存储在全局字符串中 + file.close(); + } else { + std::cerr << "无法打开文件: " << filename << std::endl; + } +} + +//回调函数 +size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response) { + size_t totalSize = size * nmemb; + unsigned char* data = static_cast(contents); + response->insert(response->end(), data, data + totalSize); + return totalSize; +} + +// 提取 "data" 字段的值 +std::string extractDataValue(const std::string& jsonString) { + std::size_t srcPos = jsonString.find("\"data\":\""); + if (srcPos == std::string::npos){ + std::cout << "未找到 data 字段 " << std::endl; + return ""; // 未找到 "src" 字段 + } + std::size_t valueStartPos = srcPos + 8; + std::size_t valueEndPos = jsonString.find("\"", valueStartPos); + if (valueEndPos == std::string::npos){ + std::cout << "未找到值的结束位置 " << std::endl; + return ""; // 未找到值的结束位置 + } + return jsonString.substr(valueStartPos, valueEndPos - valueStartPos); +} + + +bool Delete_string(char *substringToDelete_download,char *substringToDelete_local,char *download_SE_APP_version,char *local_SE_APP_version){ + if ((strlen(substringToDelete_download) != 0)&&(strlen(substringToDelete_local) != 0)) { + char* found1 = strstr(download_SE_APP_version, substringToDelete_download); + if (found1 != NULL) { + memmove(found1, found1 + strlen(substringToDelete_download), strlen(found1 + strlen(substringToDelete_download)) + 1); + } + char* found2 = strstr(local_SE_APP_version, substringToDelete_local); + if (found2 != NULL) { + memmove(found2, found2 + strlen(substringToDelete_local), strlen(found2 + strlen(substringToDelete_local)) + 1); + } + return true; + }else{ + printf("substringToDelete NULL\n"); + return false; + } + +} + +bool getVersionFromfile(const char * filepath,char *version, int maxLength,char *parameter) { + if (version == NULL || filepath == NULL) { + printf("getLocalVersion is error, version == null.\n"); + return false; + } + FILE *fp = fopen(filepath, "r"); + if (fp == NULL) { + printf("open %s failed, error is %s.\n", filepath, strerror(errno)); + return false; + } + int iffind=0; + char *line = NULL; + size_t len = 0; + size_t read; + while ((read = getline(&line, &len, fp)) != -1) { + if (read == 0 || line[0] == '#') { + continue; + } + char *pline = strstr(line, parameter); + if (pline != NULL && (pline = strstr(pline, "=")) != NULL) { + pline++; //过滤掉等于号 + //过滤掉空格 + while (*pline == ' ') { + pline++; + } + int pline_len = strlen(pline) - 1; + int version_len = (pline_len > maxLength ? maxLength:pline_len); + memcpy(version, pline, version_len); + printf("%s: %s = %s \n",filepath,parameter, version); + iffind=1; + break; + } + } + if (iffind == 0 ){ + printf("Can not find %s \n",parameter); + } + free(line); + fclose(fp); + return true; +} + +bool check_version(char *local_SE_APP_version,char *download_SE_APP_version,char *download_SE_APP_url, + int sizeof_local_SE_APP_version,int sizeof_download_SE_APP_version,int sizeof_download_SE_APP_url){ + + //从文件中读取url + readFileAndStoreInGlobal(URL_FILE,BASE_URL_string); + readFileAndStoreInGlobal(DeviceID_FILE,DeviceID); + + curlToServer_GET(); + std::cout << "local_app_version: " << local_app_version.c_str() << std::endl; + strcpy(local_SE_APP_version, local_app_version.c_str()); + printf("local_SE_APP_version after strcpy %s\n", local_SE_APP_version); + // getVersionFromfile(LOCAL_VERSION_PATH,local_SE_APP_version,sizeof_local_SE_APP_version,"SE-APP_VERSION"); + getVersionFromfile(DOWNLOAD_VERSION_PATH,download_SE_APP_version,sizeof_download_SE_APP_version,"SE-APP_VERSION"); + + char substringToDelete_download[10] = {0}; + char substringToDelete_local[10] = {0}; + if((strstr(download_SE_APP_version,"APP1") != NULL) && (strstr(local_SE_APP_version,"APP2") != NULL)){ + printf("download_SE_APP_version has APP1\n"); + printf("local_SE_APP_version has APP2\n"); + getVersionFromfile(DOWNLOAD_VERSION_PATH,download_SE_APP_url,sizeof_download_SE_APP_url,"SE-APP1_url"); + // strcpy(_save_APP_path, "/demo/bin/"); + // strcat(_save_APP_path, download_SE_APP_version); + strcpy(_save_APP_path, download_SE_APP_version); + strcpy(substringToDelete_download, "APP1"); + strcpy(substringToDelete_local, "APP2"); + // printf("substringToDelete %s\n", substringToDelete); + }else if((strstr(download_SE_APP_version,"APP2") != NULL) && (strstr(local_SE_APP_version,"APP1") != NULL)){ + printf("download_SE_APP_version has APP2\n"); + strcpy(_save_APP_path, "/demo/bin/SE-APP2.bin"); + getVersionFromfile(DOWNLOAD_VERSION_PATH,download_SE_APP_url,sizeof_download_SE_APP_url,"SE-APP2_url"); + // strcpy(_save_APP_path, "/demo/bin/"); + // strcat(_save_APP_path, download_SE_APP_version); + strcpy(_save_APP_path, download_SE_APP_version); + strcpy(substringToDelete_download, "APP2"); + strcpy(substringToDelete_local, "APP1"); + // printf("substringToDelete %s\n", substringToDelete); + + }else{ + printf("APP区域不匹配\n"); + + return false; + } + + + if(!Delete_string(substringToDelete_download,substringToDelete_local,download_SE_APP_version,local_SE_APP_version)){ + return false; + } + printf("local_SE_APP_version after Delete_string %s\n", local_SE_APP_version); + printf("check version new:%s old:%s\n", download_SE_APP_version, local_SE_APP_version); + if (strcmp(download_SE_APP_version, local_SE_APP_version) != 0) { + printf("check version OK!\n"); + return true; + }else{ + printf("check version:no need to upload\n"); + return false; + } + +} + + +void curlToServer_GET() { + CURL *curl; + CURLcode res; + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); + std::string checkappversionurl =BASE_URL_string + DeviceID; + curl_easy_setopt(curl, CURLOPT_URL, checkappversionurl.c_str()); + std::cout << "check app version url: " << checkappversionurl.c_str() << std::endl; + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https"); + struct curl_slist *headers = NULL; + + headers = curl_slist_append(headers, "Accept: */*"); + headers = curl_slist_append(headers, "Host: 36.108.213.190:10004"); + headers = curl_slist_append(headers, "Connection: keep-alive"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + // 设置响应回调函数和缓冲区 + // 创建一个用于存储返回数据的 unsigned char 数组 + std::string response; + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + res = curl_easy_perform(curl); + fprintf(stderr, "res: %s\n", curl_easy_strerror(res)); + /* Check for errors */ + if(res != CURLE_OK){ + fprintf(stderr, "curl_easy_perform() passmessage failed: %s\n",curl_easy_strerror(res)); + } else { + std::cout << "Response: " << response << std::endl; + local_app_version = extractDataValue(response); + // std::cout << "local_app_version: " << local_app_version.c_str() << std::endl; + } + } + curl_easy_cleanup(curl); + +} + + + + diff --git a/ymodem-master/checkversion.h b/ymodem-master/checkversion.h new file mode 100644 index 0000000..a5839f8 --- /dev/null +++ b/ymodem-master/checkversion.h @@ -0,0 +1,15 @@ +#include +#ifndef _CHECKVERSION_H +#define _CHECKVERSION_H + + +extern char _save_APP_path[100]; +// bool check_version(char *local_SE_APP_version,char *download_SE_APP_version,char *download_SE_APP_url); +bool check_version(char *local_SE_APP_version,char *download_SE_APP_version,char *download_SE_APP_url, + int sizeof_local_SE_APP_version,int sizeof_download_SE_APP_version,int sizeof_download_SE_APP_url); +bool getVersionFromfile(const char * filepath,char *version, int maxLength,char *parameter); +void readFileAndStoreInGlobal(const std::string& filename, std::string& destination); +void curlToServer_GET() ; + + +#endif //_CHECKVERSION_H \ No newline at end of file diff --git a/ymodem-master/doc/xymodem.pdf b/ymodem-master/doc/xymodem.pdf new file mode 100644 index 0000000..2399775 --- /dev/null +++ b/ymodem-master/doc/xymodem.pdf @@ -0,0 +1,1479 @@ + -1- + + XMODEM/YMODEM PROTOCOL REFERENCE + A compendium of documents describing the + + XMODEM and YMODEM + File Transfer Protocols + + This document was formatted 10-14-88. + + Edited by Chuck Forsberg + + This file may be redistributed without restriction + provided the text is not altered. + + Please distribute as widely as possible. + Questions to Chuck Forsberg + + Omen Technology Inc + The High Reliability Software + + 17505-V Sauvie Island Road + Portland Oregon 97231 + + VOICE: 503-621-3406 :VOICE +TeleGodzilla BBS: 503-621-3746 Speed 19200(Telebit PEP),2400,1200,300 + + CompuServe: 70007,2304 + GEnie: CAF + + UUCP: ...!tektronix!reed!omen!caf + -2- + +1. TOWER OF BABEL + +A "YMODEM Tower of Babel" has descended on the microcomputing community +bringing with it confusion, frustration, bloated phone bills, and wasted +man hours. Sadly, I (Chuck Forsberg) am partly to blame for this mess. + +As author of the early 1980s batch and 1k XMODEM extensions, I assumed +readers of earlier versions of this document would implement as much of +the YMODEM protocol as their programming skills and computing environments +would permit. This proved a rather naive assumption as programmers +motivated by competitive pressure implemented as little of YMODEM as +possible. Some have taken whatever parts of YMODEM that appealed to them, +applied them to MODEM7 Batch, Telink, XMODEM or whatever, and called the +result YMODEM. + +Jeff Garbers (Crosstalk package development director) said it all: "With +protocols in the public domain, anyone who wants to dink around with them +can go ahead." [1] + +Documents containing altered examples derived from YMODEM.DOC have added +to the confusion. In one instance, some self styled rewriter of history +altered the heading in YMODEM.DOC's Figure 1 from "1024 byte Packets" to +"YMODEM/CRC File Transfer Protocol". None of the XMODEM and YMODEM +examples shown in that document were correct. + +To put an end to this confusion, we must make "perfectly clear" what +YMODEM stands for, as Ward Christensen defined it in his 1985 coining of +the term. + +To the majority of you who read, understood, and respected Ward's +definition of YMODEM, I apologize for the inconvenience. + +1.1 Definitions + +ARC ARC is a program that compresses one or more files into an archive + + and extracts files from such archives. + +XMODEM refers to the file transfer etiquette introduced by Ward + Christensen's 1977 MODEM.ASM program. The name XMODEM comes from + Keith Petersen's XMODEM.ASM program, an adaptation of MODEM.ASM + for Remote CP/M (RCPM) systems. It's also called the MODEM or + MODEM2 protocol. Some who are unaware of MODEM7's unusual batch + file mode call it MODEM7. Other aliases include "CP/M Users' + Group" and "TERM II FTP 3". The name XMODEM caught on partly + because it is distinctive and partly because of media interest in + +__________ + 1. Page C/12, PC-WEEK July 12, 1987 + Chapter 1 + +X/YMODEM Protocol Reference June 18 1988 3 + + bulletin board and RCPM systems where it was accessed with an + "XMODEM" command. This protocol is supported by every serious + communications program because of its universality, simplicity, + and reasonable performance. + +XMODEM/CRC replaces XMODEM's 1 byte checksum with a two byte Cyclical + Redundancy Check (CRC-16), giving modern error detection + protection. + +XMODEM-1k Refers to the XMODEM/CRC protocol with 1024 byte data blocks. + +YMODEM Refers to the XMODEM/CRC (optional 1k blocks) protocol with batch + transmission as described below. In a nutshell, YMODEM means + BATCH. + +YMODEM-g Refers to the streaming YMODEM variation described below. + +True YMODEM(TM) In an attempt to sort out the YMODEM Tower of Babel, Omen + Technology has trademarked the term True YMODEM(TM) to represent + the complete YMODEM protocol described in this document, including + pathname, length, and modification date transmitted in block 0. + Please contact Omen Technology about certifying programs for True + YMODEM(TM) compliance. + +ZMODEM uses familiar XMODEM/CRC and YMODEM technology in a new protocol + that provides reliability, throughput, file management, and user + amenities appropriate to contemporary data communications. + +ZOO Like ARC, ZOO is a program that compresses one or more files into + + a "zoo archive". ZOO supports many different operating systems + + including Unix and VMS. + Chapter 1 + +X/YMODEM Protocol Reference June 18 1988 4 + +2. YMODEM MINIMUM REQUIREMENTS + +All programs claiming to support YMODEM must meet the following minimum +requirements: + + + The sending program shall send the pathname (file name) in block 0. + + + The pathname shall be a null terminated ASCII string as described + below. + + For those who are too lazy to read the entire document: + + + Unless specifically requested, only the file name portion is + sent. + + + No drive letter is sent. + + + Systems that do not distinguish between upper and lower case + letters in filenames shall send the pathname in lower case only. + + + The receiving program shall use this pathname for the received file + name, unless explicitly overridden. + + + When the receiving program receives this block and successfully + opened the output file, it shall acknowledge this block with an ACK + character and then proceed with a normal XMODEM file transfer + beginning with a "C" or NAK tranmsitted by the receiver. + + + The sending program shall use CRC-16 in response to a "C" pathname + nak, otherwise use 8 bit checksum. + + + The receiving program must accept any mixture of 128 and 1024 byte + blocks within each file it receives. Sending programs may + arbitrarily switch between 1024 and 128 byte blocks. + + + The sending program must not change the length of an unacknowledged + block. + + + At the end of each file, the sending program shall send EOT up to ten + times until it receives an ACK character. (This is part of the + XMODEM spec.) + + + The end of a transfer session shall be signified by a null (empty) + pathname, this pathname block shall be acknowledged the same as other + pathname blocks. + +Programs not meeting all of these requirements are not YMODEM compatible, +and shall not be described as supporting YMODEM. + +Meeting these MINIMUM requirements does not guarantee reliable file + Chapter 2 + +X/YMODEM Protocol Reference June 18 1988 5 + +transfers under stress. Particular attention is called to XMODEM's single +character supervisory messages that are easily corrupted by transmission +errors. + Chapter 2 + +X/YMODEM Protocol Reference June 18 1988 6 + +3. WHY YMODEM? + +Since its development half a decade ago, the Ward Christensen modem +protocol has enabled a wide variety of computer systems to interchange +data. There is hardly a communications program that doesn't at least +claim to support this protocol. + +Advances in computing, modems and networking have revealed a number of +weaknesses in the original protocol: + + + The short block length caused throughput to suffer when used with + timesharing systems, packet switched networks, satellite circuits, + and buffered (error correcting) modems. + + + The 8 bit arithmetic checksum and other aspects allowed line + impairments to interfere with dependable, accurate transfers. + + + Only one file could be sent per command. The file name had to be + given twice, first to the sending program and then again to the + receiving program. + + + The transmitted file could accumulate as many as 127 extraneous + bytes. + + + The modification date of the file was lost. + +A number of other protocols have been developed over the years, but none +have displaced XMODEM to date: + + + Lack of public domain documentation and example programs have kept + proprietary protocols such as Blast, Relay, and others tightly bound + to the fortunes of their suppliers. + + + Complexity discourages the widespread application of BISYNC, SDLC, + HDLC, X.25, and X.PC protocols. + + + Performance compromises and complexity have limited the popularity of + the Kermit protocol, which was developed to allow file transfers in + environments hostile to XMODEM. + +The XMODEM protocol extensions and YMODEM Batch address some of these +weaknesses while maintaining most of XMODEM's simplicity. + +YMODEM is supported by the public domain programs YAM (CP/M), +YAM(CP/M-86), YAM(CCPM-86), IMP (CP/M), KMD (CP/M), rz/sz (Unix, Xenix, +VMS, Berkeley Unix, Venix, Xenix, Coherent, IDRIS, Regulus). Commercial +implementations include MIRROR, and Professional-YAM.[1] Communications + Chapter 3 + +X/YMODEM Protocol Reference June 18 1988 7 + +programs supporting these extensions have been in use since 1981. + +The 1k block length (XMODEM-1k) described below may be used in conjunction +with YMODEM Batch Protocol, or with single file transfers identical to the +XMODEM/CRC protocol except for minimal changes to support 1k blocks. + +Another extension is the YMODEM-g protocol. YMODEM-g provides batch +transfers with maximum throughput when used with end to end error +correcting media, such as X.PC and error correcting modems, including 9600 +bps units by TeleBit, U.S.Robotics, Hayes, Electronic Vaults, Data Race, +and others. + +To complete this tome, edited versions of Ward Christensen's original +protocol document and John Byrns's CRC-16 document are included for +reference. + +References to the MODEM or MODEM7 protocol have been changed to XMODEM to +accommodate the vernacular. In Australia, it is properly called the +Christensen Protocol. + +3.1 Some Messages from the Pioneer + +#: 130940 S0/Communications 25-Apr-85 18:38:47 +Sb: my protocol +Fm: Ward Christensen 76703,302 [2] +To: all + +Be aware the article[3] DID quote me correctly in terms of the phrases +like "not robust", etc. + +It was a quick hack I threw together, very unplanned (like everything I +do), to satisfy a personal need to communicate with "some other" people. + +ONLY the fact that it was done in 8/77, and that I put it in the public +domain immediately, made it become the standard that it is. + +__________________________________________________________________________ + 1. Available for IBM PC,XT,AT, Unix and Xenix + 2. Edited for typesetting appearance + 3. Infoworld April 29 p. 16 + Chapter 3 + +X/YMODEM Protocol Reference June 18 1988 8 + +I think its time for me to + +(1) document it; (people call me and say "my product is going to include +it - what can I 'reference'", or "I'm writing a paper on it, what do I put +in the bibliography") and + +(2) propose an "incremental extension" to it, which might take "exactly" +the form of Chuck Forsberg's YAM protocol. He wrote YAM in C for CP/M and +put it in the public domain, and wrote a batch protocol for Unix[4] called +rb and sb (receive batch, send batch), which was basically XMODEM with + + (a) a record 0 containing filename date time and size + (b) a 1K block size option + (c) CRC-16. + +He did some clever programming to detect false ACK or EOT, but basically +left them the same. + +People who suggest I make SIGNIFICANT changes to the protocol, such as +"full duplex", "multiple outstanding blocks", "multiple destinations", etc +etc don't understand that the incredible simplicity of the protocol is one +of the reasons it survived to this day in as many machines and programs as +it may be found in! + +Consider the PC-NET group back in '77 or so - documenting to beat the band +- THEY had a protocol, but it was "extremely complex", because it tried to +be "all things to all people" - i.e. send binary files on a 7-bit system, +etc. I was not that "benevolent". I (emphasize > I < ) had an 8-bit UART, +so "my protocol was an 8-bit protocol", and I would just say "sorry" to +people who were held back by 7-bit limitations. ... + +Block size: Chuck Forsberg created an extension of my protocol, called +YAM, which is also supported via his public domain programs for UNIX +called rb and sb - receive batch and send batch. They cleverly send a +"block 0" which contains the filename, date, time, and size. +Unfortunately, its UNIX style, and is a bit weird[5] - octal numbers, etc. +BUT, it is a nice way to overcome the kludgy "echo the chars of the name" +introduced with MODEM7. Further, chuck uses CRC-16 and optional 1K +blocks. Thus the record 0, 1K, and CRC, make it a "pretty slick new +protocol" which is not significantly different from my own. + +Also, there is a catchy name - YMODEM. That means to some that it is the +"next thing after XMODEM", and to others that it is the Y(am)MODEM + +__________ + + 4. VAX/VMS versions of these programs are also available. + + 5. The file length, time, and file mode are optional. The pathname and + file length may be sent alone if desired. + Chapter 3 + +X/YMODEM Protocol Reference June 18 1988 9 + +protocol. I don't want to emphasize that too much - out of fear that +other mfgrs might think it is a "competitive" protocol, rather than an +"unaffiliated" protocol. Chuck is currently selling a much-enhanced +version of his CP/M-80 C program YAM, calling it Professional Yam, and its +for the PC - I'm using it right now. VERY slick! 32K capture buffer, +script, scrolling, previously captured text search, plus built-in commands +for just about everything - directory (sorted every which way), XMODEM, +YMODEM, KERMIT, and ASCII file upload/download, etc. You can program it +to "behave" with most any system - for example when trying a number for +CIS it detects the "busy" string back from the modem and substitutes a +diff phone # into the dialing string and branches back to try it. + Chapter 3 + +X/YMODEM Protocol Reference June 18 1988 10 + +4. XMODEM PROTOCOL ENHANCEMENTS + +This chapter discusses the protocol extensions to Ward Christensen's 1982 +XMODEM protocol description document. + +The original document recommends the user be asked whether to continue +trying or abort after 10 retries. Most programs no longer ask the +operator whether he wishes to keep retrying. Virtually all correctable +errors are corrected within the first few retransmissions. If the line is +so bad that ten attempts are insufficient, there is a significant danger +of undetected errors. If the connection is that bad, it's better to +redial for a better connection, or mail a floppy disk. + +4.1 Graceful Abort + +The YAM and Professional-YAM X/YMODEM routines recognize a sequence of two +consecutive CAN (Hex 18) characters without modem errors (overrun, +framing, etc.) as a transfer abort command. This sequence is recognized +when is waiting for the beginning of a block or for an acknowledgement to +a block that has been sent. The check for two consecutive CAN characters +reduces the number of transfers aborted by line hits. YAM sends eight CAN +characters when it aborts an XMODEM, YMODEM, or ZMODEM protocol file +transfer. Pro-YAM then sends eight backspaces to delete the CAN +characters from the remote's keyboard input buffer, in case the remote had +already aborted the transfer and was awaiting a keyboarded command. + +4.2 CRC-16 Option + +The XMODEM protocol uses an optional two character CRC-16 instead of the +one character arithmetic checksum used by the original protocol and by +most commercial implementations. CRC-16 guarantees detection of all +single and double bit errors, all errors with an odd number of error +bits, all burst errors of length 16 or less, 99.9969% of all 17-bit error +bursts, and 99.9984 per cent of all possible longer error bursts. By +contrast, a double bit error, or a burst error of 9 bits or more can sneak +past the XMODEM protocol arithmetic checksum. + +The XMODEM/CRC protocol is similar to the XMODEM protocol, except that the +receiver specifies CRC-16 by sending C (Hex 43) instead of NAK when +requesting the FIRST block. A two byte CRC is sent in place of the one +byte arithmetic checksum. + +YAM's c option to the r command enables CRC-16 in single file reception, +corresponding to the original implementation in the MODEM7 series +programs. This remains the default because many commercial communications +programs and bulletin board systems still do not support CRC-16, +especially those written in Basic or Pascal. + +XMODEM protocol with CRC is accurate provided both sender and receiver + Chapter 4 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 11 + +both report a successful transmission. The protocol is robust in the +presence of characters lost by buffer overloading on timesharing systems. + +The single character ACK/NAK responses generated by the receiving program +adapt well to split speed modems, where the reverse channel is limited to +ten per cent or less of the main channel's speed. + +XMODEM and YMODEM are half duplex protocols which do not attempt to +transmit information and control signals in both directions at the same +time. This avoids buffer overrun problems that have been reported by +users attempting to exploit full duplex asynchronous file transfer +protocols such as Blast. + +Professional-YAM adds several proprietary logic enhancements to XMODEM's +error detection and recovery. These compatible enhancements eliminate +most of the bad file transfers other programs make when using the XMODEM +protocol under less than ideal conditions. + +4.3 XMODEM-1k 1024 Byte Block + +Disappointing throughput downloading from Unix with YMODEM[1] lead to the +development of 1024 byte blocks in 1982. 1024 byte blocks reduce the +effect of delays from timesharing systems, modems, and packet switched +networks on throughput by 87.5 per cent in addition to decreasing XMODEM's +3 per cent overhead (block number, CRC, etc.). + +Some environments cannot accept 1024 byte bursts, including some networks +and minicomputer ports. The longer block length should be an option. + +The choice to use 1024 byte blocks is expressed to the sending program on +its command line or selection menu.[2] 1024 byte blocks improve throughput +in many applications. + +An STX (02) replaces the SOH (01) at the beginning of the transmitted +block to notify the receiver of the longer block length. The transmitted +block contains 1024 bytes of data. The receiver should be able to accept +any mixture of 128 and 1024 byte blocks. The block number (in the second +and third bytes of the block) is incremented by one for each block +regardless of the block length. + +The sender must not change between 128 and 1024 byte block lengths if it +has not received a valid ACK for the current block. Failure to observe + +__________ + + 1. The name hadn't been coined yet, but the protocol was the same. + + 2. See "KMD/IMP Exceptions to YMODEM" below. + Chapter 4 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 12 + +this restriction allows transmission errors to pass undetected. + +If 1024 byte blocks are being used, it is possible for a file to "grow" up +to the next multiple of 1024 bytes. This does not waste disk space if the +allocation granularity is 1k or greater. With YMODEM batch transmission, +the optional file length transmitted in the file name block allows the +receiver to discard the padding, preserving the exact file length and +contents. + +1024 byte blocks may be used with batch file transmission or with single +file transmission. CRC-16 should be used with the k option to preserve +data integrity over phone lines. If a program wishes to enforce this +recommendation, it should cancel the transfer, then issue an informative +diagnostic message if the receiver requests checksum instead of CRC-16. + +Under no circumstances may a sending program use CRC-16 unless the +receiver commands CRC-16. + +Figure 1. XMODEM-1k Blocks + +SENDER RECEIVER + + "sx -k foo.bar" + +"foo.bar open x.x minutes" + + C + +STX 01 FE Data[1024] CRC CRC + + ACK + +STX 02 FD Data[1024] CRC CRC + + ACK + +STX 03 FC Data[1000] CPMEOF[24] CRC CRC + + ACK + +EOT + + ACK + +Figure 2. Mixed 1024 and 128 byte Blocks + +SENDER RECEIVER +"foo.bar open x.x minutes" "sx -k foo.bar" +STX 01 FE Data[1024] CRC CRC C +STX 02 FD Data[1024] CRC CRC ACK +SOH 03 FC Data[128] CRC CRC ACK +SOH 04 FB Data[100] CPMEOF[28] CRC CRC ACK +EOT ACK + ACK + Chapter 4 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 13 + +5. YMODEM Batch File Transmission + +The YMODEM Batch protocol is an extension to the XMODEM/CRC protocol that +allows 0 or more files to be transmitted with a single command. (Zero +files may be sent if none of the requested files is accessible.) The +design approach of the YMODEM Batch protocol is to use the normal routines +for sending and receiving XMODEM blocks in a layered fashion similar to +packet switching methods. + +Why was it necessary to design a new batch protocol when one already +existed in MODEM7?[1] The batch file mode used by MODEM7 is unsuitable +because it does not permit full pathnames, file length, file date, or +other attribute information to be transmitted. Such a restrictive design, +hastily implemented with only CP/M in mind, would not have permitted +extensions to current areas of personal computing such as Unix, DOS, and +object oriented systems. In addition, the MODEM7 batch file mode is +somewhat susceptible to transmission impairments. + +As in the case of single a file transfer, the receiver initiates batch +file transmission by sending a "C" character (for CRC-16). + +The sender opens the first file and sends block number 0 with the +following information.[2] + +Only the pathname (file name) part is required for batch transfers. + +To maintain upwards compatibility, all unused bytes in block 0 must be set +to null. + +Pathname The pathname (conventionally, the file name) is sent as a null + +terminated ASCII string. This is the filename format used by the + +handle oriented MSDOS(TM) functions and C library fopen functions. + +An assembly language example follows: + + DB 'foo.bar',0 + +No spaces are included in the pathname. Normally only the file name + +stem (no directory prefix) is transmitted unless the sender has + +selected YAM's f option to send the full pathname. The source drive + +(A:, B:, etc.) is not sent. + +Filename Considerations: + +__________ + + 1. The MODEM7 batch protocol transmitted CP/M FCB bytes f1...f8 and + t1...t3 one character at a time. The receiver echoed these bytes as + received, one at a time. + + 2. Only the data part of the block is described here. + Chapter 5 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 14 + + + File names are forced to lower case unless the sending system + supports upper/lower case file names. This is a convenience for + users of systems (such as Unix) which store filenames in upper + and lower case. + + + The receiver should accommodate file names in lower and upper + case. + + + When transmitting files between different operating systems, + file names must be acceptable to both the sender and receiving + operating systems. + + If directories are included, they are delimited by /; i.e., + "subdir/foo" is acceptable, "subdir\foo" is not. + +Length The file length and each of the succeeding fields are optional.[3] + The length field is stored in the block as a decimal string counting + the number of data bytes in the file. The file length does not + include any CPMEOF (^Z) or other garbage characters used to pad the + last block. + + If the file being transmitted is growing during transmission, the + length field should be set to at least the final expected file + length, or not sent. + + The receiver stores the specified number of characters, discarding + any padding added by the sender to fill up the last block. + +Modification Date The mod date is optional, and the filename and length + may be sent without requiring the mod date to be sent. + + Iff the modification date is sent, a single space separates the + modification date from the file length. + + The mod date is sent as an octal number giving the time the contents + of the file were last changed, measured in seconds from Jan 1 1970 + Universal Coordinated Time (GMT). A date of 0 implies the + modification date is unknown and should be left as the date the file + is received. + + This standard format was chosen to eliminate ambiguities arising from + transfers between different time zones. + +__________ + 3. Fields may not be skipped. + Chapter 5 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 15 + +Mode Iff the file mode is sent, a single space separates the file mode + from the modification date. The file mode is stored as an octal + string. Unless the file originated from a Unix system, the file mode + is set to 0. rb(1) checks the file mode for the 0x8000 bit which + indicates a Unix type regular file. Files with the 0x8000 bit set + are assumed to have been sent from another Unix (or similar) system + which uses the same file conventions. Such files are not translated + in any way. + +Serial Number Iff the serial number is sent, a single space separates the + serial number from the file mode. The serial number of the + transmitting program is stored as an octal string. Programs which do + not have a serial number should omit this field, or set it to 0. The + receiver's use of this field is optional. + +Other Fields YMODEM was designed to allow additional header fields to be + added as above without creating compatibility problems with older + YMODEM programs. Please contact Omen Technology if other fields are + needed for special application requirements. + +The rest of the block is set to nulls. This is essential to preserve +upward compatibility.[4] + +If the filename block is received with a CRC or other error, a +retransmission is requested. After the filename block has been received, +it is ACK'ed if the write open is successful. If the file cannot be +opened for writing, the receiver cancels the transfer with CAN characters +as described above. + +The receiver then initiates transfer of the file contents with a "C" +character, according to the standard XMODEM/CRC protocol. + +After the file contents and XMODEM EOT have been transmitted and +acknowledged, the receiver again asks for the next pathname. + +Transmission of a null pathname terminates batch file transmission. + +Note that transmission of no files is not necessarily an error. This is +possible if none of the files requested of the sender could be opened for +reading. + +__________ + + 4. If, perchance, this information extends beyond 128 bytes (possible + with Unix 4.2 BSD extended file names), the block should be sent as a + 1k block as described above. + Chapter 5 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 16 + +Most YMODEM receivers request CRC-16 by default. + +The Unix programs sz(1) and rz(1) included in the source code file +RZSZ.ZOO should answer other questions about YMODEM batch protocol. + + Figure 3. YMODEM Batch Transmission Session (1 file) + + SENDER RECEIVER + "sending in batch mode etc." "sb foo.*" + SOH 00 FF foo.c NUL[123] CRC CRC + C (command:rb) + SOH 01 FE Data[128] CRC CRC + SOH 02 FC Data[128] CRC CRC ACK + SOH 03 FB Data[100] CPMEOF[28] CRC CRC C + EOT + EOT ACK + + SOH 00 FF NUL[128] CRC CRC ACK + + ACK + + NAK + + ACK + C + + ACK + + Figure 7. YMODEM Header Information and Features + +_____________________________________________________________ + +| Program | Length | Date | Mode | S/N | 1k-Blk | YMODEM-g | + +|___________|________|______|______|_____|________|__________| + +|Unix rz/sz | yes | yes | yes | no | yes | sb only | + +|___________|________|______|______|_____|________|__________| + +|VMS rb/sb | yes | no | no | no | yes | no | + +|___________|________|______|______|_____|________|__________| + +|Pro-YAM | yes | yes | no | yes | yes | yes | + +|___________|________|______|______|_____|________|__________| + +|CP/M YAM | no | no | no | no | yes | no | + +|___________|________|______|______|_____|________|__________| + +|KMD/IMP | ? | no | no | no | yes | no | + +|___________|________|______|______|_____|________|__________| + +5.1 KMD/IMP Exceptions to YMODEM + +KMD and IMP use a "CK" character sequence emitted by the receiver to +trigger the use of 1024 byte blocks as an alternative to specifying this +option to the sending program. This two character sequence generally +works well on single process micros in direct communication, provided the +programs rigorously adhere to all the XMODEM recommendations included + Chapter 5 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 17 + +Figure 4. YMODEM Batch Transmission Session (2 files) + +SENDER RECEIVER +"sending in batch mode etc." "sb foo.c baz.c" +SOH 00 FF foo.c NUL[123] CRC CRC + C (command:rb) +SOH 01 FE Data[128] CRC CRC +SOH 02 FC Data[128] CRC CRC ACK +SOH 03 FB Data[100] CPMEOF[28] CRC CRC C +EOT +EOT ACK + +SOH 00 FF baz.c NUL[123] CRC CRC ACK + +SOH 01 FB Data[100] CPMEOF[28] CRC CRC ACK +EOT +EOT NAK + +SOH 00 FF NUL[128] CRC CRC ACK + C + + ACK + C + + ACK + + NAK + + ACK + C + + ACK + +Figure 5. YMODEM Batch Transmission Session-1k Blocks + +SENDER RECEIVER +"sending in batch mode etc." "sb -k foo.*" +SOH 00 FF foo.c NUL[123] CRC CRC C (command:rb) + ACK +STX 01 FD Data[1024] CRC CRC C +SOH 02 FC Data[128] CRC CRC ACK +SOH 03 FB Data[100] CPMEOF[28] CRC CRC ACK +EOT ACK +EOT NAK + Chapter 5 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 18 + + ACK + C +SOH 00 FF NUL[128] CRC CRC + ACK + +Figure 6. YMODEM Filename block transmitted by sz + +-rw-r--r-- 6347 Jun 17 1984 20:34 bbcsched.txt + +00 0100FF62 62637363 6865642E 74787400 |...bbcsched.txt.| +10 36333437 20333331 34373432 35313320 |6347 3314742513 | +20 31303036 34340000 00000000 00000000 |100644..........| +30 00000000 00000000 00000000 00000000 +40 00000000 00000000 00000000 00000000 +50 00000000 00000000 00000000 00000000 +60 00000000 00000000 00000000 00000000 +70 00000000 00000000 00000000 00000000 +80 000000CA 56 + +herein. Programs with marginal XMODEM implementations do not fare so +well. Timesharing systems and packet switched networks can separate the +successive characters, rendering this method unreliable. + +Sending programs may detect the CK sequence if the operating enviornment +does not preclude reliable implementation. + +Instead of the standard YMODEM file length in decimal, KMD and IMP +transmit the CP/M record count in the last two bytes of the header block. + +6. YMODEM-g File Transmission + +Developing technology is providing phone line data transmission at ever +higher speeds using very specialized techniques. These high speed modems, +as well as session protocols such as X.PC, provide high speed, nearly +error free communications at the expense of considerably increased delay +time. + +This delay time is moderate compared to human interactions, but it +cripples the throughput of most error correcting protocols. + +The g option to YMODEM has proven effective under these circumstances. +The g option is driven by the receiver, which initiates the batch transfer +by transmitting a G instead of C. When the sender recognizes the G, it +bypasses the usual wait for an ACK to each transmitted block, sending +succeeding blocks at full speed, subject to XOFF/XON or other flow control +exerted by the medium. + +The sender expects an inital G to initiate the transmission of a +particular file, and also expects an ACK on the EOT sent at the end of +each file. This synchronization allows the receiver time to open and + Chapter 6 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 19 + +close files as necessary. + +If an error is detected in a YMODEM-g transfer, the receiver aborts the +transfer with the multiple CAN abort sequence. The ZMODEM protocol should +be used in applications that require both streaming throughput and error +recovery. + +Figure 8. YMODEM-g Transmission Session + +SENDER RECEIVER + "sb foo.*" +"sending in batch mode etc..." G (command:rb -g) + G +SOH 00 FF foo.c NUL[123] CRC CRC + ACK +SOH 01 FE Data[128] CRC CRC G +STX 02 FD Data[1024] CRC CRC +SOH 03 FC Data[128] CRC CRC +SOH 04 FB Data[100] CPMEOF[28] CRC CRC +EOT + +SOH 00 FF NUL[128] CRC CRC + Chapter 6 XMODEM Protocol Enhancements + +X/YMODEM Protocol Reference June 18 1988 20 + +7. XMODEM PROTOCOL OVERVIEW + +8/9/82 by Ward Christensen. + +I will maintain a master copy of this. Please pass on changes or +suggestions via CBBS/Chicago at (312) 545-8086, CBBS/CPMUG (312) 849-1132 +or by voice at (312) 849-6279. + +7.1 Definitions + + 01H + 04H + 06H + 15H + 18H + 43H + +7.2 Transmission Medium Level Protocol + +Asynchronous, 8 data bits, no parity, one stop bit. + +The protocol imposes no restrictions on the contents of the data being +transmitted. No control characters are looked for in the 128-byte data +messages. Absolutely any kind of data may be sent - binary, ASCII, etc. +The protocol has not formally been adopted to a 7-bit environment for the +transmission of ASCII-only (or unpacked-hex) data , although it could be +simply by having both ends agree to AND the protocol-dependent data with +7F hex before validating it. I specifically am referring to the checksum, +and the block numbers and their ones- complement. + +Those wishing to maintain compatibility of the CP/M file structure, i.e. +to allow modemming ASCII files to or from CP/M systems should follow this +data format: + + + ASCII tabs used (09H); tabs set every 8. + + + Lines terminated by CR/LF (0DH 0AH) + + + End-of-file indicated by ^Z, 1AH. (one or more) + + + Data is variable length, i.e. should be considered a continuous + stream of data bytes, broken into 128-byte chunks purely for the + purpose of transmission. + + + A CP/M "peculiarity": If the data ends exactly on a 128-byte + boundary, i.e. CR in 127, and LF in 128, a subsequent sector + containing the ^Z EOF character(s) is optional, but is preferred. + Some utilities or user programs still do not handle EOF without ^Zs. + Chapter 7 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 21 + ++ The last block sent is no different from others, i.e. there is no + "short block". + Figure 9. XMODEM Message Block Level Protocol + +Each block of the transfer looks like: + + <255-blk #><--128 data bytes--> + +in which: + + = 01 hex + + = binary number, starts at 01 increments by 1, and + + wraps 0FFH to 00H (not to 01) + +<255-blk #> = blk # after going thru 8080 "CMA" instr, i.e. + + each bit complemented in the 8-bit block number. + + Formally, this is the "ones complement". + + = the sum of the data bytes only. Toss any carry. + +7.3 File Level Protocol + +7.3.1 Common_to_Both_Sender_and_Receiver +All errors are retried 10 times. For versions running with an operator +(i.e. NOT with XMODEM), a message is typed after 10 errors asking the +operator whether to "retry or quit". + +Some versions of the protocol use , ASCII ^X, to cancel transmission. +This was never adopted as a standard, as having a single "abort" character +makes the transmission susceptible to false termination due to an + or being corrupted into a and aborting transmission. + +The protocol may be considered "receiver driven", that is, the sender need +not automatically re-transmit, although it does in the current +implementations. + +7.3.2 Receive_Program_Considerations +The receiver has a 10-second timeout. It sends a every time it +times out. The receiver's first timeout, which sends a , signals the +transmitter to start. Optionally, the receiver could send a +immediately, in case the sender was ready. This would save the initial 10 +second timeout. However, the receiver MUST continue to timeout every 10 +seconds in case the sender wasn't ready. + +Once into a receiving a block, the receiver goes into a one-second timeout +for each character and the checksum. If the receiver wishes to a +block for any reason (invalid header, timeout receiving data), it must +wait for the line to clear. See "programming tips" for ideas + +Synchronizing: If a valid block number is received, it will be: 1) the +expected one, in which case everything is fine; or 2) a repeat of the +previously received block. This should be considered OK, and only +indicates that the receivers got glitched, and the sender re- +transmitted; 3) any other block number indicates a fatal loss of +synchronization, such as the rare case of the sender getting a line-glitch + Chapter 7 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 22 + +that looked like an . Abort the transmission, sending a + +7.3.3 Sending_program_considerations +While waiting for transmission to begin, the sender has only a single very +long timeout, say one minute. In the current protocol, the sender has a +10 second timeout before retrying. I suggest NOT doing this, and letting +the protocol be completely receiver-driven. This will be compatible with +existing programs. + +When the sender has no more data, it sends an , and awaits an , +resending the if it doesn't get one. Again, the protocol could be +receiver-driven, with the sender only having the high-level 1-minute +timeout to abort. + +Here is a sample of the data flow, sending a 3-block message. It includes +the two most common line hits - a garbaged block, and an reply +getting garbaged. represents the checksum byte. + + Figure 10. Data flow including Error Recovery + +SENDER RECEIVER + + 01 FE -data- times out after 10 seconds, + 02 FD -data- xx + 02 FD -data- xx <--- + 03 FC -data- xx +(ack gets garbaged) ---> + 03 FC -data- xx + <--- + +(finished) ---> (data gets line hit) + + <--- + + ---> + + <--- + + ---> + + <--- + + ---> + + ---> + + <--- + + ---> + + <--- + +7.4 Programming Tips + ++ The character-receive subroutine should be called with a parameter + specifying the number of seconds to wait. The receiver should first + call it with a time of 10, then and try again, 10 times. + +After receiving the , the receiver should call the character +receive subroutine with a 1-second timeout, for the remainder of the +message and the . Since they are sent as a continuous stream, +timing out of this implies a serious like glitch that caused, say, +127 characters to be seen instead of 128. + Chapter 7 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 23 + ++ When the receiver wishes to , it should call a "PURGE" + subroutine, to wait for the line to clear. Recall the sender tosses + any characters in its UART buffer immediately upon completing sending + a block, to ensure no glitches were mis- interpreted. + + The most common technique is for "PURGE" to call the character + receive subroutine, specifying a 1-second timeout,[1] and looping + back to PURGE until a timeout occurs. The is then sent, + ensuring the other end will see it. + ++ You may wish to add code recommended by John Mahr to your character + receive routine - to set an error flag if the UART shows framing + error, or overrun. This will help catch a few more glitches - the + most common of which is a hit in the high bits of the byte in two + consecutive bytes. The comes out OK since counting in 1-byte + produces the same result of adding 80H + 80H as with adding 00H + + 00H. + +__________ + 1. These times should be adjusted for use with timesharing systems. + Chapter 7 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 24 + +8. XMODEM/CRC Overview + +Original 1/13/85 by John Byrns -- CRC option. + +Please pass on any reports of errors in this document or suggestions for +improvement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312) +885-1105. + +The CRC used in the Modem Protocol is an alternate form of block check +which provides more robust error detection than the original checksum. +Andrew S. Tanenbaum says in his book, Computer Networks, that the CRC- +CCITT used by the Modem Protocol will detect all single and double bit +errors, all errors with an odd number of bits, all burst errors of length +16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit and +longer bursts.[1] + +The changes to the Modem Protocol to replace the checksum with the CRC are +straight forward. If that were all that we did we would not be able to +communicate between a program using the old checksum protocol and one +using the new CRC protocol. An initial handshake was added to solve this +problem. The handshake allows a receiving program with CRC capability to +determine whether the sending program supports the CRC option, and to +switch it to CRC mode if it does. This handshake is designed so that it +will work properly with programs which implement only the original +protocol. A description of this handshake is presented in section 10. + + Figure 11. Message Block Level Protocol, CRC mode + +Each block of the transfer in CRC mode looks like: + +<255-blk #><--128 data bytes--> + +in which: + + = 01 hex + + = binary number, starts at 01 increments by 1, and + + wraps 0FFH to 00H (not to 01) + +<255-blk #> = ones complement of blk #. + + = byte containing the 8 hi order coefficients of the CRC. + + = byte containing the 8 lo order coefficients of the CRC. + +8.1 CRC Calculation + +8.1.1 Formal_Definition +To calculate the 16 bit CRC the message bits are considered to be the +coefficients of a polynomial. This message polynomial is first multiplied +by X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 + + +__________ + + 1. This reliability figure is misleading because XMODEM's critical + supervisory functions are not protected by this CRC. + Chapter 8 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 25 + +1) using modulo two arithmetic. The remainder left after the division is +the desired CRC. Since a message block in the Modem Protocol is 128 bytes +or 1024 bits, the message polynomial will be of order X^1023. The hi order +bit of the first byte of the message block is the coefficient of X^1023 in +the message polynomial. The lo order bit of the last byte of the message +block is the coefficient of X^0 in the message polynomial. + + Figure 12. Example of CRC Calculation written in C + +The following XMODEM crc routine is taken from "rbsb.c". Please refer to +the source code for these programs (contained in RZSZ.ZOO) for usage. A +fast table driven version is also included in this file. + +/* update CRC */ +unsigned short +updcrc(c, crc) +register c; +register unsigned crc; +{ + + register count; + + for (count=8; --count>=0;) { + if (crc & 0x8000) { + crc <<= 1; + crc += (((c<<=1) & 0400) != 0); + crc ^= 0x1021; + } + else { + crc <<= 1; + crc += (((c<<=1) & 0400) != 0); + } + + } + return crc; +} + +8.2 CRC File Level Protocol Changes + +8.2.1 Common_to_Both_Sender_and_Receiver +The only change to the File Level Protocol for the CRC option is the +initial handshake which is used to determine if both the sending and the +receiving programs support the CRC mode. All Modem Programs should support +the checksum mode for compatibility with older versions. A receiving +program that wishes to receive in CRC mode implements the mode setting +handshake by sending a in place of the initial . If the sending +program supports CRC mode it will recognize the and will set itself +into CRC mode, and respond by sending the first block as if a had +been received. If the sending program does not support CRC mode it will +not respond to the at all. After the receiver has sent the it will +wait up to 3 seconds for the that starts the first block. If it +receives a within 3 seconds it will assume the sender supports CRC +mode and will proceed with the file exchange in CRC mode. If no is + Chapter 8 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 26 + +received within 3 seconds the receiver will switch to checksum mode, send +a , and proceed in checksum mode. If the receiver wishes to use +checksum mode it should send an initial and the sending program +should respond to the as defined in the original Modem Protocol. +After the mode has been set by the initial or the protocol +follows the original Modem Protocol and is identical whether the checksum +or CRC is being used. + +8.2.2 Receive_Program_Considerations +There are at least 4 things that can go wrong with the mode setting +handshake. + + 1. the initial can be garbled or lost. + + 2. the initial can be garbled. + + 3. the initial can be changed to a . + + 4. the initial from a receiver which wants to receive in checksum + can be changed to a . + +The first problem can be solved if the receiver sends a second after +it times out the first time. This process can be repeated several times. +It must not be repeated too many times before sending a and +switching to checksum mode or a sending program without CRC support may +time out and abort. Repeating the will also fix the second problem if +the sending program cooperates by responding as if a were received +instead of ignoring the extra . + +It is possible to fix problems 3 and 4 but probably not worth the trouble +since they will occur very infrequently. They could be fixed by switching +modes in either the sending or the receiving program after a large number +of successive s. This solution would risk other problems however. + +8.2.3 Sending_Program_Considerations +The sending program should start in the checksum mode. This will insure +compatibility with checksum only receiving programs. Anytime a is +received before the first or the sending program should set +itself into CRC mode and respond as if a were received. The sender +should respond to additional s as if they were s until the first + is received. This will assist the receiving program in determining +the correct mode when the is lost or garbled. After the first +is received the sending program should ignore s. + Chapter 8 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 27 + +8.3 Data Flow Examples with CRC Option + +Here is a data flow example for the case where the receiver requests +transmission in the CRC mode but the sender does not support the CRC +option. This example also includes various transmission errors. +represents the checksum byte. + + Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't + +SENDER RECEIVER + + <--- times out after 3 seconds, + + <--- times out after 3 seconds, + + <--- times out after 3 seconds, + + <--- times out after 3 seconds, + + <--- + 01 FE -data- ---> + (data gets line hit) + <--- + 02 FD -data- ---> + + <--- + 02 FD -data- ---> + + <--- times out after 10 seconds, + 03 FC -data- ---> + + (ack gets garbaged) <--- + + <--- + + 03 FC -data- ---> + + <--- + + ---> + + <--- + +Here is a data flow example for the case where the receiver requests +transmission in the CRC mode and the sender supports the CRC option. This +example also includes various transmission errors. represents the +2 CRC bytes. + Chapter 8 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 28 + + Figure 14. Receiver and Sender Both have CRC Option + +SENDER RECEIVER + + <--- + + 01 FE -data- ---> (data gets line hit) + + <--- + + 02 FD -data- ---> + + <--- + times out after 10 seconds, + 02 FD -data- ---> + + <--- + + 03 FC -data- ---> + +(ack gets garbaged) <--- + + <--- + + 03 FC -data- ---> + + <--- + + ---> + + <--- + Chapter 8 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 29 + +9. MORE INFORMATION + +Please contact Omen Technology for troff source files and typeset copies +of this document. + +9.1 TeleGodzilla Bulletin Board + +More information may be obtained by calling TeleGodzilla at 503-621-3746. +Speed detection is automatic for 1200, 2400 and 19200(Telebit PEP) bps. +TrailBlazer modem users may issue the TeleGodzilla trailblazer command to +swith to 19200 bps once they have logged in. + +Interesting files include RZSZ.ZOO (C source code), YZMODEM.ZOO (Official +XMODEM, YMODEM, and ZMODEM protocol descriptions), ZCOMMEXE.ARC, +ZCOMMDOC.ARC, and ZCOMMHLP.ARC (PC-DOS shareware comm program with XMODEM, +True YMODEM(TM), ZMODEM, Kermit Sliding Windows, Telink, MODEM7 Batch, +script language, etc.). + +9.2 Unix UUCP Access + +UUCP sites can obtain the current version of this file with + uucp omen!/u/caf/public/ymodem.doc /tmp + +A continually updated list of available files is stored in +/usr/spool/uucppublic/FILES. When retrieving these files with uucp, +remember that the destination directory on your system must be writeable +by anyone, or the UUCP transfer will fail. + +The following L.sys line calls TeleGodzilla (Pro-YAM in host operation). +TeleGodzilla determines the incoming speed automatically. + +In response to "Name Please:" uucico gives the Pro-YAM "link" command as a +user name. The password (Giznoid) controls access to the Xenix system +connected to the IBM PC's other serial port. Communications between +Pro-YAM and Xenix use 9600 bps; YAM converts this to the caller's speed. + +Finally, the calling uucico logs in as uucp. + +omen Any ACU 2400 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp + +10. REVISIONS + +6-18-88 Further revised for clarity. Corrected block numbering in two +examples. +10-27-87 Optional fields added for number of files remaining to be sent +and total number of bytes remaining to be sent. +10-18-87 Flow control discussion added to 1024 byte block descritpion, +minor revisions for clarity per user comments. + Chapter 10 Xmodem Protocol Overview + +X/YMODEM Protocol Reference June 18 1988 30 + +8-03-87 Revised for clarity. +5-31-1987 emphasizes minimum requirements for YMODEM, and updates +information on accessing files. +9-11-1986 clarifies nomenclature and some minor points. +The April 15 1986 edition clarifies some points concerning CRC +calculations and spaces in the header. + +11. YMODEM Programs + +ZCOMM, A shareware little brother to Professional-YAM, is available as +ZCOMMEXE.ARC on TeleGodzilla and other bulletin board systems. ZCOMM may +be used to test YMODEM amd ZMODEM implementations. + +Unix programs supporting YMODEM are available on TeleGodzilla in RZSZ.ZOO. +This ZOO archive includes a ZCOMM/Pro-YAM/PowerCom script ZUPL.T to upload +a bootstrap program MINIRB.C, compile it, and then upload the rest of the +files using the compiled MINIRB. Most Unix like systems are supported, +including V7, Xenix, Sys III, 4.2 BSD, SYS V, Idris, Coherent, and +Regulus. + +A version for VAX-VMS is available in VRBSB.SHQ. + +Irv Hoff has added 1k blocks and basic YMODEM batch transfers to the KMD +and IMP series programs, which replace the XMODEM and MODEM7/MDM7xx series +respectively. Overlays are available for a wide variety of CP/M systems. + +Questions about Professional-YAM communications software may be directed +to: + + Chuck Forsberg + Omen Technology Inc + 17505-V Sauvie Island Road + Portland Oregon 97231 + VOICE: 503-621-3406 :VOICE + Modem: 503-621-3746 Speed: 19200(Telebit PEP),2400,1200,300 + Usenet: ...!tektronix!reed!omen!caf + CompuServe: 70007,2304 + GEnie: CAF + +Unlike ZMODEM and Kermit, XMODEM and YMODEM place obstacles in the path of +a reliable high performance implementation, evidenced by poor reliability +under stress of the industry leaders' XMODEM and YMODEM programs. Omen +Technology provides consulting and other services to those wishing to +implement XMODEM, YMODEM, and ZMODEM with state of the art features and +reliability. + Chapter 11 Xmodem Protocol Overview + + CONTENTS + + 1. TOWER OF BABEL................................................... 2 + 1.1 Definitions................................................. 2 + + 2. YMODEM MINIMUM REQUIREMENTS...................................... 4 + + 3. WHY YMODEM?...................................................... 6 + 3.1 Some Messages from the Pioneer.............................. 7 + + 4. XMODEM PROTOCOL ENHANCEMENTS..................................... 10 + 4.1 Graceful Abort.............................................. 10 + 4.2 CRC-16 Option............................................... 10 + 4.3 XMODEM-1k 1024 Byte Block................................... 11 + + 5. YMODEM Batch File Transmission................................... 13 + 5.1 KMD/IMP Exceptions to YMODEM................................ 16 + + 6. YMODEM-g File Transmission....................................... 18 + + 7. XMODEM PROTOCOL OVERVIEW......................................... 20 + 7.1 Definitions................................................. 20 + 7.2 Transmission Medium Level Protocol.......................... 20 + 7.3 File Level Protocol......................................... 21 + 7.4 Programming Tips............................................ 22 + + 8. XMODEM/CRC Overview.............................................. 24 + 8.1 CRC Calculation............................................. 24 + 8.2 CRC File Level Protocol Changes............................. 25 + 8.3 Data Flow Examples with CRC Option.......................... 27 + + 9. MORE INFORMATION................................................. 29 + 9.1 TeleGodzilla Bulletin Board................................. 29 + 9.2 Unix UUCP Access............................................ 29 + +10. REVISIONS........................................................ 29 + +11. YMODEM Programs.................................................. 30 + + -i- + LIST OF FIGURES + Figure 1. XMODEM-1k Blocks.......................................... 12 + Figure 2. Mixed 1024 and 128 byte Blocks............................ 12 + Figure 3. YMODEM Batch Transmission Session (1 file)................ 16 + Figure 4. YMODEM Batch Transmission Session (2 files)............... 16 + Figure 5. YMODEM Batch Transmission Session-1k Blocks............... 16 + Figure 6. YMODEM Filename block transmitted by sz................... 16 + Figure 7. YMODEM Header Information and Features.................... 16 + Figure 8. YMODEM-g Transmission Session............................. 19 + Figure 9. XMODEM Message Block Level Protocol....................... 21 +Figure 10. Data flow including Error Recovery........................ 22 +Figure 11. Message Block Level Protocol, CRC mode.................... 24 +Figure 12. Example of CRC Calculation written in C................... 25 +Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't........ 27 +Figure 14. Receiver and Sender Both have CRC Option.................. 28 + + - ii - + diff --git a/ymodem-master/download.cpp b/ymodem-master/download.cpp new file mode 100644 index 0000000..132025e --- /dev/null +++ b/ymodem-master/download.cpp @@ -0,0 +1,74 @@ +/************************************************************************* + > File Name: download.cpp + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Thu 07 Mar 2019 10:30:31 AM CST + ************************************************************************/ + +#include +#include +#include +#include "log.h" +size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + return fwrite(ptr, size, nmemb, stream); +} + +extern double processvalue; +static int down_processvalue; + +int my_progress_func(char *progress_data, + double t, /* dltotal */ + double d, /* dlnow */ + double ultotal, + double ulnow) +{ + processvalue = ulnow / ultotal * 100 / 110; + //LOGI("ultotal is %f, ulnow is %f, t is %f, d is %f\n", ultotal, ulnow, t, d); + if (down_processvalue != (int)(d / t * 100)) { + down_processvalue = (int)(d / t * 100); + LOGI("down_processvalue is %d%\n", down_processvalue); + } + + return 0; +} + +int download_file(char *url, char *output_filename) +{ + if (strncmp(url, "http", 4) != 0) { + LOGI("where the file is local.\n"); + return -2; + } + CURL *curl; + CURLcode res; + FILE *outfile; + char *progress_data = "* "; + down_processvalue = -1; + + curl = curl_easy_init(); + if(curl) + { + outfile = fopen(output_filename, "wb"); + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress_data); + + res = curl_easy_perform(curl); + + if(res != CURLE_OK) + LOGE("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + fclose(outfile); + /* always cleanup */ + curl_easy_cleanup(curl); + } + if(res != CURLE_OK){ + LOGE("download Error.\n"); + return -1; + } + return 0; +} + diff --git a/ymodem-master/download.h b/ymodem-master/download.h new file mode 100644 index 0000000..6565f08 --- /dev/null +++ b/ymodem-master/download.h @@ -0,0 +1,11 @@ +/************************************************************************* + > File Name: download.h + > Author: jkand.huang + > Mail: jkand.huang@rock-chips.com + > Created Time: Thu 07 Mar 2019 10:39:33 AM CST + ************************************************************************/ + +#ifndef _DOWNLOAD_H +#define _DOWNLOAD_H +int download_file(char *url, char *output_filename); +#endif diff --git a/ymodem-master/log.cpp b/ymodem-master/log.cpp new file mode 100644 index 0000000..1428d1a --- /dev/null +++ b/ymodem-master/log.cpp @@ -0,0 +1,47 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Log - implemented using the standard Android logging mechanism + +/* + * Qutoing from system/core/include/log/log.h: + * Normally we strip ALOGV (VERBOSE messages) from release builds. + * You can modify this (for example with "#define LOG_NDEBUG 0" + * at the top of your source file) to change that behavior. + */ +#ifndef LOG_NDEBUG +#ifdef NDEBUG +#define LOG_NDEBUG 1 +#else +#define LOG_NDEBUG 0 +#endif +#endif + +#define LOG_BUF_SIZE 1024 + +#include "log.h" +#include +#include + + +void InitLogging(int argc, const char* const* argv) {} + +void Log(const char* file, int line, LogPriority level, const char* fmt, ...) { + va_list ap; + char buf[LOG_BUF_SIZE]; + va_start(ap, fmt); + vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); + va_end(ap); + + switch(level) { + case LOG_ERROR: printf("LOG_ERROR : %s\n", buf); break; + case LOG_WARN: printf("LOG_WARN : %s\n", buf); break; + case LOG_INFO: printf("LOG_INFO :%s \n", buf); break; + case LOG_DEBUG: + //#if LOG_NDEBUG + printf("LOG_DEBUG :%s \n", buf); + //#endif + break; + default : + break; + } +} diff --git a/ymodem-master/log.h b/ymodem-master/log.h new file mode 100644 index 0000000..226e047 --- /dev/null +++ b/ymodem-master/log.h @@ -0,0 +1,33 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Log - Platform independent interface for a Logging class +// +#ifndef update_engine_CORE_LOG_H_ +#define update_engine_CORE_LOG_H_ + +// Simple logging class. The implementation is platform dependent. + +typedef enum { + LOG_ERROR, + LOG_WARN, + LOG_INFO, + LOG_DEBUG, + LOG_VERBOSE +} LogPriority; + +// Enable/disable verbose logging (LOGV). +// This function is supplied for cases where the system layer does not +// initialize logging. This is also needed to initialize logging in +// unit tests. +void InitLogging(int argc, const char* const* argv); + +void Log(const char* file, int line, LogPriority level, const char* fmt, ...); + +// Log APIs +#define LOGE(...) Log(__FILE__, __LINE__, LOG_ERROR, __VA_ARGS__) +#define LOGW(...) Log(__FILE__, __LINE__, LOG_WARN, __VA_ARGS__) +#define LOGI(...) Log(__FILE__, __LINE__, LOG_INFO, __VA_ARGS__) +#define LOGD(...) Log(__FILE__, __LINE__, LOG_DEBUG, __VA_ARGS__) +#define LOGV(...) Log(__FILE__, __LINE__, LOG_VERBOSE, __VA_ARGS__) + +#endif // update_engine_CORE_LOG_H_ diff --git a/ymodem-master/serial_port.c b/ymodem-master/serial_port.c new file mode 100644 index 0000000..b05838b --- /dev/null +++ b/ymodem-master/serial_port.c @@ -0,0 +1,108 @@ +// +// Created by hongg on 2020/3/30. +// + +#include "serial_port.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int serial_set(int fd, int speed, int bits, char event, int stop, int vtime, int vmin) +{ + struct termios new_tio; + + if (tcgetattr(fd, &new_tio) != 0) + return -1; + + bzero(&new_tio, sizeof(new_tio)); + new_tio.c_cflag |= CLOCAL | CREAD; + new_tio.c_cflag &= ~CSIZE; + + switch (bits) { + case 7: + new_tio.c_cflag |= CS7; + break; + case 8: + new_tio.c_cflag |= CS8; + break; + default : + new_tio.c_cflag |= CS8; + break; + } + + switch (event) { + case 'o': + case 'O': + new_tio.c_cflag |= PARENB; + new_tio.c_cflag |= PARODD; + new_tio.c_iflag |= (INPCK|ISTRIP); + break; + case 'e': + case 'E': + new_tio.c_cflag |= (INPCK|ISTRIP); + new_tio.c_cflag |= PARENB; + new_tio.c_iflag &= ~PARODD; + break; + case 'n': + case 'N': + new_tio.c_cflag &= ~PARENB; + break; + default: + new_tio.c_cflag &= ~PARENB; + break; + } + + switch (speed) { + case 2400: + cfsetispeed(&new_tio, B2400); + cfsetospeed(&new_tio, B2400); + break; + case 4800: + cfsetispeed(&new_tio, B4800); + cfsetospeed(&new_tio, B4800); + break; + case 9600: + cfsetispeed(&new_tio, B9600); + cfsetospeed(&new_tio, B9600); + break; + case 19200: + cfsetispeed(&new_tio, B19200); + cfsetospeed(&new_tio, B19200); + break; + case 38400: + cfsetispeed(&new_tio, B38400); + cfsetospeed(&new_tio, B38400); + break; + case 57600: + cfsetispeed(&new_tio, B57600); + cfsetospeed(&new_tio, B57600); + break; + case 115200: + cfsetispeed(&new_tio, B115200); + cfsetospeed(&new_tio, B115200); + break; + default: + cfsetispeed(&new_tio, B115200); + cfsetospeed(&new_tio, B115200); + break; + } + + if (stop == 1) + new_tio.c_cflag &= ~CSTOPB; + else + new_tio.c_cflag |= CSTOPB; + + new_tio.c_cc[VTIME] = vtime; + new_tio.c_cc[VMIN] = vmin; + + if ((tcsetattr(fd, TCSANOW, &new_tio)) != 0) + return -3; + return 0; +} \ No newline at end of file diff --git a/ymodem-master/serial_port.h b/ymodem-master/serial_port.h new file mode 100644 index 0000000..24f0f80 --- /dev/null +++ b/ymodem-master/serial_port.h @@ -0,0 +1,18 @@ +// +// Created by hongg on 2020/3/30. +// + +#ifndef _HGL_SERIAL_PORT_H +#define _HGL_SERIAL_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +int serial_set(int fd, int speed, int bits, char event, int stop, int vtime, int vmin); + +#ifdef __cplusplus +} +#endif + +#endif //MCUBRIDGE_SERIAL_PORT_H diff --git a/ymodem-master/ymodem.c b/ymodem-master/ymodem.c new file mode 100644 index 0000000..debc7fa --- /dev/null +++ b/ymodem-master/ymodem.c @@ -0,0 +1,626 @@ +#include "ymodem.h" +#include +#include +#include + +#define YMODEM_SEND_MAX_PACKET_SIZE PACKET_1K_SIZE +// #define YMODEM_SEND_MAX_PACKET_SIZE PACKET_SIZE + +#define YMODEM_DEBUG 1 + +#if YMODEM_DEBUG +#define ym_printf(...) printf(__VA_ARGS__) +#else +#define ym_printf(...) +#endif /*YMODEM_DEBUG*/ + +/* http://www.ccsinfo.com/forum/viewtopic.php?t=24977 */ +unsigned short crc16(const unsigned char *buf, unsigned long count) +{ + unsigned short crc = 0; + int i; + + while(count--) { + crc = crc ^ *buf++ << 8; + + for (i = 0; i < 8; i++) { + if (crc & 0x8000) { + crc = crc << 1 ^ 0x1021; + } else { + crc = crc << 1; + } + } + } + return crc; +} + +static unsigned long str_to_u32(char* str) +{ + const char *s = str; + unsigned long acc; + int c; + + /* strip leading spaces if any */ + do { + c = *s++; + } while (c == ' '); + + for (acc = 0; (c >= '0') && (c <= '9'); c = *s++) { + c -= '0'; + acc *= 10; + acc += c; + } + return acc; +} + +static const char *u32_to_str(unsigned int val) +{ + /* Maximum number of decimal digits in u32 is 10 */ + static char num_str[11]; + int pos = 10; + num_str[10] = 0; + + if (val == 0) { + /* If already zero then just return zero */ + return "0"; + } + + while ((val != 0) && (pos > 0)) { + num_str[--pos] = (val % 10) + '0'; + val /= 10; + } + + return &num_str[pos]; +} + +static int ymodem_show_packet(unsigned char *packet, unsigned int packet_size) +{ +#if YMODEM_DEBUG + switch (packet[0]) { + case YMODEM_CODE_SOH: + ym_printf("SOH "); + break; + case YMODEM_CODE_STX: + ym_printf("STX "); + break; + case YMODEM_CODE_EOT: + ym_printf("EOT "); + break; + case YMODEM_CODE_ACK: + ym_printf("ACK "); + break; + case YMODEM_CODE_NAK: + ym_printf("NAK "); + break; + case YMODEM_CODE_CAN: + ym_printf("CAN "); + break; + default: + break; + } + if (packet_size) { + ym_printf("%02X %02X Data[%d] CRC CRC\r\n", packet[1], packet[2], packet_size); + } else { + ym_printf("\r\n"); + } +#endif + return 0; +} + +static int ymodem_putc_and_show(struct ymodem *ymodem, unsigned char ch) +{ + if (ch == YMODEM_CODE_EOT) { + ym_printf("EOT\r\n"); + return ymodem->putchar(ch); + } + +#if YMODEM_DEBUG + ym_printf("\t\t\t\t"); + + switch (ch) { + case YMODEM_CODE_CRC: + ym_printf("%d ",ch); + ym_printf("C\r\n"); + break; + case YMODEM_CODE_CAN: + ym_printf("%d ",ch); + ym_printf("CAN\r\n"); + break; + case YMODEM_CODE_NAK: + ym_printf("%d ",ch); + ym_printf("NAK\r\n"); + break; + case YMODEM_CODE_ACK: + ym_printf("%d ",ch); + ym_printf("ACK\r\n"); + break; + default: + ym_printf("%d ",ch); + break; + } +#endif /*YMODEM_DEBUG*/ + return ymodem->putchar(ch); +} + +static int ymodem_getc_and_show(struct ymodem *ymodem) +{ + int ch; + + ch = ymodem->getchar(); + +#if YMODEM_DEBUG + ym_printf("\t\t\t\t"); + + switch (ch) { + case YMODEM_CODE_CRC: + ym_printf("0x%X ",ch); + ym_printf("C\r\n"); + break; + case YMODEM_CODE_CAN: + ym_printf("0x%X ",ch); + ym_printf("CAN\r\n"); + break; + case YMODEM_CODE_NAK: + ym_printf("0x%X ",ch); + ym_printf("NAK\r\n"); + break; + case YMODEM_CODE_ACK: + ym_printf("0x%X ",ch); + ym_printf("ACK\r\n"); + break; + default: + ym_printf("0x%X ",ch); + ym_printf("CAN\r\n"); + break; + } +#endif /*YMODEM_DEBUG*/ + return ch; +} + +static int receive_packet(struct ymodem *ymodem, unsigned char *data, unsigned long *length) +{ + int i, c; + unsigned long packet_size; + + *length = 0; + + c = ymodem->getchar(); + if (c < 0) + return -1; + + *data = (unsigned char)c; + + switch(c) { + case YMODEM_CODE_SOH: + packet_size = PACKET_SIZE; + break; + case YMODEM_CODE_STX: + packet_size = PACKET_1K_SIZE; + break; + case YMODEM_CODE_EOT: + packet_size = 0; + goto OUT; + case YMODEM_CODE_CAN: + c = ymodem->getchar(); + if (c == YMODEM_CODE_CAN) { + return 0; + } + default: + /* This case could be the result of corruption on the first octet + * of the packet, but it's more likely that it's the user banging + * on the terminal trying to abort a transfer. Technically, the + * former case deserves a NAK, but for now we'll just treat this + * as an abort case. + */ + return -1; + } + + + + for(i = 1; i < (packet_size + PACKET_OVERHEAD); ++i) { + c = ymodem->getchar(); + if (c < 0) { + return -1; + } + data[i] = (unsigned char)c; + } + + /* Just a sanity check on the sequence number/complement value. + * Caller should check for in-order arrival. + */ + if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff)) { + return 1; + } + + if (crc16(data + PACKET_HEADER, packet_size + PACKET_TRAILER) != 0) { + return 1; + } + *length = packet_size; +OUT: + ymodem_show_packet(data, packet_size); + + return 0; +} + + +static int ymodem_handshake(struct ymodem *ymodem) +{ + int timeout = YMODEM_TIMEOUT; + int ret = -1; + unsigned long packet_size = 0; + unsigned char packet[PACKET_OVERHEAD+PACKET_1K_SIZE] = {0}; + char *file_size; + + ymodem->stage = YMODEM_STAGE_ESTABLISHING; + + while (timeout--) { + ymodem_putc_and_show(ymodem, YMODEM_CODE_CRC); //send 'C' + + ret = receive_packet(ymodem, packet, &packet_size); + if (ret == 0 && packet_size >= PACKET_SIZE) { + + strcpy(ymodem->file_name, (const char *)&packet[PACKET_HEADER]); + file_size = (char *)&packet[PACKET_HEADER + strlen(ymodem->file_name) + 1]; + ymodem->file_size = str_to_u32(file_size); + ym_printf("file name : %s, size : %ld\r\n", ymodem->file_name, ymodem->file_size); + if (ymodem->begin_packet_cb) { + if (ymodem->begin_packet_cb(&packet[PACKET_HEADER], packet_size) != 0) + return -1; + } + ymodem_putc_and_show(ymodem, YMODEM_CODE_ACK); + ymodem_putc_and_show(ymodem, YMODEM_CODE_CRC); + break; + } else if (ret == -1) { + //timeout + } else if (ret == 1) { + //check failed + } + } + if (timeout <= 0) + return -1; + + return 0; +} + +int ymodem_receive_file_data(struct ymodem *ymodem) +{ + unsigned char packet[PACKET_OVERHEAD+PACKET_1K_SIZE]; + unsigned long packet_size = 0; + int i, ret = -1; + int retry = 0; + + ymodem->stage = YMODEM_STAGE_TRANSMITTING; + + while (1) { + ret = receive_packet(ymodem, packet, &packet_size); + if (ret == 0) { + if (packet_size) { + if (ymodem->data_packet_cb && + ymodem->data_packet_cb(&packet[PACKET_HEADER], packet_size) != 0) { + return -1; + } + ymodem_putc_and_show(ymodem, YMODEM_CODE_ACK); + } else if (packet[0] == YMODEM_CODE_CAN) { + /* the spec require multiple CAN */ + for (i = 0; i < YMODEM_END_SESSION_SEND_CAN_NUM; i++) { + ymodem_putc_and_show(ymodem, YMODEM_CODE_CAN); + } + } else if (packet[0] == YMODEM_CODE_EOT) { + //EOT + return 0; + } + } else { + if (retry++ > MAX_ERRORS) { + break; + } else { + ym_printf("retry!\r\n"); + } + } + } + return -1; +} + +static int ymodem_recv_finsh(struct ymodem *ymodem) +{ + int ch, ret; + unsigned char packet[PACKET_OVERHEAD+PACKET_1K_SIZE]; + unsigned long packet_size = 0; + + ymodem->stage = YMODEM_STAGE_FINISHING; + /* we already got one EOT in the caller. invoke the callback if there is + * one. */ + ymodem_putc_and_show(ymodem, YMODEM_CODE_NAK); + + ch = ymodem->getchar(); + if (ch != YMODEM_CODE_EOT) + return -1; + ymodem_show_packet((unsigned char*)&ch, 0); + + ymodem_putc_and_show(ymodem, YMODEM_CODE_ACK); + ymodem_putc_and_show(ymodem, YMODEM_CODE_CRC); + + ret = receive_packet(ymodem, packet, &packet_size); + if (ret != 0) + return -1; + + if (packet_size != PACKET_SIZE) + return -1; + + ymodem_putc_and_show(ymodem, YMODEM_CODE_ACK); + + if (ymodem->end_packet_cb) + ymodem->end_packet_cb(&packet[PACKET_HEADER], packet_size); + + if (packet[3] != 0x0) { //还有文件要接收 + if (ymodem->begin_packet_cb) + ymodem->begin_packet_cb(&packet[PACKET_HEADER], packet_size); + ymodem_putc_and_show(ymodem, YMODEM_CODE_CRC); + return 0; + } + + ymodem->stage = YMODEM_STAGE_FINISHED; + + return 0; +} +/* + Figure 3. YMODEM Batch Transmission Session (1 file) +SENDER RECEIVER + "sb foo.*" +"sending in batch mode etc." + C (command:rb) +SOH 00 FF foo.c NUL[123] CRC CRC + ACK + C +SOH 01 FE Data[128] CRC CRC + ACK +SOH 02 FC Data[128] CRC CRC + ACK +SOH 03 FB Data[100] CPMEOF[28] CRC CRC + ACK +EOT + NAK +EOT + ACK + C +SOH 00 FF NUL[128] CRC CRC + ACK +*/ + +/* +Figure 4. YMODEM Batch Transmission Session (2 files) +SENDER RECEIVER + "sb foo.c baz.c" +"sending in batch mode etc." + C (command:rb) +SOH 00 FF foo.c NUL[123] CRC CRC + ACK + C +SOH 01 FE Data[128] CRC CRC + ACK +SOH 02 FC Data[128] CRC CRC + ACK +SOH 03 FB Data[100] CPMEOF[28] CRC CRC + ACK +EOT + NAK +EOT + ACK + C +SOH 00 FF baz.c NUL[123] CRC CRC + ACK + C +SOH 01 FB Data[100] CPMEOF[28] CRC CRC + ACK +EOT + NAK +EOT + ACK + C +SOH 00 FF NUL[128] CRC CRC + ACK +*/ +int ymodem_receive(struct ymodem *ymodem) +{ + int ret = -1; + + if (NULL == ymodem || NULL == ymodem->getchar || NULL == ymodem->putchar) + return -1; + + ymodem->stage = YMODEM_STAGE_NONE; + + //handshake + ret = ymodem_handshake(ymodem); + if (ret != 0) + return ret; + + while (1) { + ret = ymodem_receive_file_data(ymodem); + if (ret != 0) + return ret; + + ret = ymodem_recv_finsh(ymodem); + if (ret != 0) + return ret; + if (ymodem->stage == YMODEM_STAGE_FINISHED) + break; + } + + return 0; +} + + +static void send_packet(struct ymodem *ymodem, unsigned char *data, int block_no, int packet_size) +{ + int count, crc; + unsigned char packet[3]; + + crc = crc16(data, packet_size); + /* 128 byte packets use SOH, 1K use STX */ + + packet[0] = (packet_size==PACKET_SIZE)?YMODEM_CODE_SOH:YMODEM_CODE_STX; + ymodem->putchar(packet[0]); + + packet[1] = (block_no & 0xFF); + ymodem->putchar(packet[1]); + + packet[2] = (~block_no & 0xFF); + ymodem->putchar(packet[2]); + + for (count=0; countputchar(data[count]); + + ymodem->putchar((crc >> 8) & 0xFF); + ymodem->putchar(crc & 0xFF); + + ymodem_show_packet(packet, packet_size); +} + + +/* Send block 0 (the filename block). filename might be truncated to fit. */ +static void send_packet0(struct ymodem *ymodem, char* filename, unsigned long size) +{ + unsigned long count = 0; + unsigned char block[PACKET_SIZE]; + const char* num; + + if (filename) { + while (*filename && (count < PACKET_SIZE-FILE_SIZE_LENGTH-2)) { + block[count++] = *filename++; + } + block[count++] = 0; + + num = u32_to_str(size); + while(*num) { + block[count++] = *num++; + } + ym_printf("file name: %s, size: %d\r\n", block, size); + } + + while (count < PACKET_SIZE) { + block[count++] = 0; + } + + send_packet(ymodem, block, 0, PACKET_SIZE); + if (ymodem->begin_packet_cb) + ymodem->begin_packet_cb(block, PACKET_SIZE); +} + +static void send_data_packets(struct ymodem *ymodem) +{ + int blockno = 1; + unsigned long i, size, send_size; + int ch; + unsigned char packet_data[PACKET_1K_SIZE]; + unsigned char *data = ymodem->data; + int retry = 0; + + size = ymodem->file_size; + while (size > 0) { + if (size > PACKET_SIZE) { + send_size = PACKET_1K_SIZE; + } else { + send_size = PACKET_SIZE; + } + if (send_size > YMODEM_SEND_MAX_PACKET_SIZE) + send_size = YMODEM_SEND_MAX_PACKET_SIZE; + + if (size < send_size) { + memcpy(packet_data, data, size); + //需要填充0x1A + for (i = size; i < send_size; i++) + packet_data[i] = 0x1A; + } else { + memcpy(packet_data, data, send_size); + } + + send_packet(ymodem, packet_data, blockno, send_size); + + if (ymodem->data_packet_cb) + ymodem->data_packet_cb(packet_data, send_size); + + ch = ymodem_getc_and_show(ymodem); + if (ch == YMODEM_CODE_ACK) { + retry = 0; + blockno++; + data += send_size; + if (size < send_size) + size = 0; + else + size -= send_size; + } else { + if (ch == YMODEM_CODE_NAK) { + if (retry++ > MAX_ERRORS) + return; + } + if((ch == YMODEM_CODE_CAN) || (ch == -1)) { + return; + } + } + } + + do { + ymodem_putc_and_show(ymodem, YMODEM_CODE_EOT); + ch = ymodem_getc_and_show(ymodem); + } while((ch != YMODEM_CODE_ACK) && (ch != -1)); + + /* Send last data packet */ + if (ch == YMODEM_CODE_ACK) { + ch = ymodem_getc_and_show(ymodem); + if (ch == YMODEM_CODE_CRC) { + do { + send_packet0(ymodem, 0, 0); + ch = ymodem_getc_and_show(ymodem); + } while((ch != YMODEM_CODE_ACK) && (ch != -1)); + } + } + if (ymodem->end_packet_cb) + ymodem->end_packet_cb(NULL, 0); +} + +/* + * 为了简单,需要一次性将文件内容复制到ymodem->data中, + * 大多数情况都是下位机发送,不会遇到内存问题. + * + */ + + +int ymodem_send(struct ymodem *ymodem) +{ + int ch, crc_nak = 1; + int retry = 0; + put_start_char(); + printf("put start_char\n"); + usleep(300000); + if (flush_serial_input() == 0) { + printf("Serial input buffer flushed.\n"); + } + do { + ch = ymodem_getc_and_show(ymodem); + } while (retry++ < YMODEM_TIMEOUT && ch != YMODEM_CODE_CRC); + + if (ch == YMODEM_CODE_CRC) { + while (1) { + send_packet0(ymodem, ymodem->file_name, ymodem->file_size); + ch = ymodem_getc_and_show(ymodem); + if (ch == YMODEM_CODE_ACK) { + ch = ymodem_getc_and_show(ymodem); + if (ch == YMODEM_CODE_CRC) { + send_data_packets(ymodem); + return 0; + } + // } else if ((ch == YMODEM_CODE_CRC) && (crc_nak)) { + } else if ((ch == YMODEM_CODE_CRC) && (crc_nak)) { + crc_nak = 0; + continue; + // } else if ((ch != YMODEM_CODE_NAK) || (crc_nak)) { + } else if ((ch != YMODEM_CODE_NAK)) { + break; + } + } + } else { + ymodem_putc_and_show(ymodem, YMODEM_CODE_CAN); + ymodem_putc_and_show(ymodem, YMODEM_CODE_CAN); + } + + return -1; +} \ No newline at end of file diff --git a/ymodem-master/ymodem.h b/ymodem-master/ymodem.h new file mode 100644 index 0000000..12a32b5 --- /dev/null +++ b/ymodem-master/ymodem.h @@ -0,0 +1,108 @@ +//http://code.google.com/p/xtreamerdev/source/browse/trunk/rtdsr/?r=2#rtdsr%253Fstate%253Dclosed + +/* ymodem for RTD Serial Recovery (rtdsr) + * + * copyright (c) 2011 Pete B. + * + * based on ymodem.h for bootldr, copyright (c) 2001 John G Dorsey + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + + + +#ifndef _HGL_YMODEM_H +#define _HGL_YMODEM_H + +#define PACKET_SEQNO_INDEX (1) +#define PACKET_SEQNO_COMP_INDEX (2) + +#define PACKET_HEADER (3) /* start, block, block-complement */ +#define PACKET_TRAILER (2) /* CRC bytes */ +#define PACKET_OVERHEAD (PACKET_HEADER + PACKET_TRAILER) +#define PACKET_SIZE (128) +#define PACKET_1K_SIZE (1024) +#define PACKET_TIMEOUT (1) + +#define FILE_NAME_LENGTH (64) +#define FILE_SIZE_LENGTH (16) + + +/* Number of consecutive receive errors before giving up: */ +#define MAX_ERRORS (20) + +#define YMODEM_END_SESSION_SEND_CAN_NUM 0x07 + +#define YMODEM_TIMEOUT 15 + +/* ASCII control codes: */ +enum ymodem_code { + YMODEM_CODE_NONE = 0x0, + YMODEM_CODE_SOH = 0x01, /* start of 128-byte data packet */ + YMODEM_CODE_STX = 0x02, /* start of 1024-byte data packet */ + YMODEM_CODE_EOT = 0x04, /* end of transmission */ + YMODEM_CODE_ACK = 0x06, /* receive OK */ + YMODEM_CODE_NAK = 0x015, /* receiver error; retry */ + YMODEM_CODE_CAN = 0x018, /* two of these in succession aborts transfer */ + YMODEM_CODE_CRC = 0x43, /* use in place of first NAK for CRC mode */ +}; + +enum ymodem_stage { + YMODEM_STAGE_NONE, + /* set when C is send */ + YMODEM_STAGE_ESTABLISHING, + /* set when we've got the packet 0 and sent ACK and second C */ + YMODEM_STAGE_ESTABLISHED, + /* set when the sender respond to our second C and recviever got a real + * data packet. */ + YMODEM_STAGE_TRANSMITTING, + /* set when the sender send a EOT */ + YMODEM_STAGE_FINISHING, + /* set when transmission is really finished, i.e., after the NAK, C, final + * NULL packet stuff. */ + YMODEM_STAGE_FINISHED, +}; + +struct ymodem { + char file_name[FILE_NAME_LENGTH]; + unsigned long file_size; + unsigned char *data; //If it is sending mode, it is file data, if it is receiving file, it will not be processed. 如果是发送文件,为文件数据,如果是接收文件,则不处理 + enum ymodem_stage stage; + + int (*putchar)(unsigned char ch); + int (*getchar)(void); + int (*begin_packet_cb)(const unsigned char *buf, unsigned long len); + int (*data_packet_cb)(const unsigned char *buf, unsigned long len); + int (*end_packet_cb)(const unsigned char *buf, unsigned long len); + +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int ymodem_receive(struct ymodem *ymodem); + +int ymodem_send(struct ymodem *ymodem); + +void put_start_char(); + +int flush_serial_input(); + +#ifdef __cplusplus +} +#endif + +#endif /*_HGL_YMODEM_H*/ \ No newline at end of file diff --git a/ymodem-master/ymodem_test.cpp b/ymodem-master/ymodem_test.cpp new file mode 100644 index 0000000..4736270 --- /dev/null +++ b/ymodem-master/ymodem_test.cpp @@ -0,0 +1,479 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + +#include + +#include + +#include "ymodem.h" +#include "serial_port.h" +#include "download.h" +#include "checkversion.h" +#include + +#include + + +#define DEV_PATH_DEF "/dev/ttyUSB0" +#define BAUDRATE_DEF 115200 +#define TIMEOUT_DEF 20 //10*100ms +double processvalue = 0; +#define short_wait_time 30 +#define long_wait_time 3600 + + + +static int g_fd; +static struct ymodem ymodem; +static FILE* g_fp; + +sem_t *my_semaphore; +int is_insem = 0; + +void signal_handler(int signo) { + if (signo == SIGINT || signo == SIGTERM) { + // 在这里执行你的操作 + sleep(1); + printf("Received termination signal. Performing cleanup...\n"); + unsigned char stop_data[] = {0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08}; + write(g_fd, stop_data, sizeof(stop_data)); + sleep(1); + // system("/demo/bin/testprogram &"); + if(is_insem == 1){ + sem_post(my_semaphore); + is_insem = 0; + printf("%d\n",is_insem); + printf("出锁\n"); + } + exit(0); + } +} +//输入进入ota的命令 +void put_start_char(){ + unsigned char start_data[] = {0xac,0x53,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x11,0x22,0x33,0x44,0x85,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01,0x00,0x84,0x09}; + write(g_fd, start_data, sizeof(start_data)); +} +//清空串口缓存 +int flush_serial_input() { + int result = tcflush(g_fd, TCIFLUSH); + if (result == -1) { + perror("tcflush"); + } + return result; +} + +int _putchar(unsigned char ch) +{ + return write(g_fd, &ch, 1); +} + +int _getchar(void) +{ + ssize_t size; + unsigned char ch; + + size = read(g_fd, &ch, 1); + if (size == 1) + return ch; + else + return -1; +} + +int get_result(void) +{ + ssize_t size; + unsigned char ch; + char buffer[255]; + + size = read(g_fd, buffer, sizeof(buffer)); + if (size > 0){ + char hexData[1024]; + std::vector byteArray; + int i; + for (i = 0; i < size; i++) { + snprintf(&hexData[i * 2], sizeof(hexData) - i * 2, "%02X", buffer[i]); + byteArray.push_back(static_cast(buffer[i])); + } + + printf("Received result: %s\n", hexData); + for (unsigned char c : byteArray) { + std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(c) << " "; + } + std::cout << std::endl; + + //解析部分 + if (byteArray.size() >= 16 && byteArray[15] == 0x04) { + // 第15个字节是1 + // 在这里编写处理逻辑 + std::cout << "功能码为0x04 OTA升级时状态码上报" <= 23 && byteArray[22] == 0x01){ + std::cout << "升级包过大,取消升级" <= 23 && byteArray[22] == 0x02){ + std::cout << "写入闪存错误" <= 23 && byteArray[22] == 0x03){ + std::cout << "用户取消升级" <= 23 && byteArray[22] == 0x04){ + std::cout << "获取包错误" <= 23 && byteArray[22] == 0x05){ + std::cout << " 升级超时" <= 23 && byteArray[22] == 0x06){ + std::cout << "升级成功!" <= 23 && byteArray[22] == 0x07){ + std::cout << "错误太多" <= 23 && byteArray[22] == 0x08){ + std::cout << "包名错误" <= 23 && byteArray[22] == 0x09){ + std::cout << "包名相同" < ymodem.file_size) { + invalid = recv_file_size - ymodem.file_size; + } + fwrite(buf, 1, len - invalid, g_fp); + return 0; +} + +int end_packet_callback(const unsigned char *buf, unsigned long len) +{ + fclose(g_fp); + return 0; +} + +int recevice(void) +{ + int ret; + + printf("Receice Ymodem!\r\n"); + + ret = ymodem_receive(&ymodem); + + //需要再发送两个0x4F,xshell/secureCRT才会提示传送完成 + sleep(1); + ymodem.putchar(0x4F); + ymodem.putchar(0x4F); + + return ret; +} + + +int send_begin_packet_callback(const unsigned char *buf, unsigned long len) +{ + return 0; +} + +int send_data_packet_callback(const unsigned char *buf, unsigned long len) +{ + return 0; +} + +int send_end_packet_callback(const unsigned char *buf, unsigned long len) +{ + return 0; +} + +int send_file(const char* file_name) +{ + int ret, fd, index, size; + + printf("Send Ymodem! file: %s\r\n", file_name); + + strcpy(ymodem.file_name, file_name); + + fd = open(file_name, O_RDONLY); + if (fd <= 0) + return -1; + //get file data + index = 0; + ymodem.data = (unsigned char *)malloc(300*1024); + do { + size = read(fd, &ymodem.data[index], 1024); + if (size) + index += size; + } while(size > 0); + close(fd); + ymodem.file_size = index; + ret = ymodem_send(&ymodem); + + free(ymodem.data); + + return ret; +} + +void ymodem_help(void) +{ + printf("Usage : ./ymodem [options]\n"); + printf("options:\r\n"); + printf("eg send Ymodem: ./ymodem -d /dev/ttyUSB0 -s /sdcard/test.txt\r\n"); + printf("eg receive Ymodem: ./ymodem -d /dev/ttyUSB0\r\n"); + printf("\t -d device path.设置设备名,默认/dev/ttyUSB0.\r\n"); + printf("\t -s send Ymodem, receiving mode if not set.发送文件,如果不选,默认为接收文件\r\n"); + printf("\t -t Set getchar timeout,def:10(1s), 1=100ms.设置getchar超时,1为100毫秒,默认10=>1s.\r\n"); + printf("\t --help display specific types of command line options.\r\n\r\n"); +} + +int main(int argc, char *argv[]) +{ + // 注册信号处理函数 + signal(SIGINT, signal_handler); // SIGINT 对应Ctrl+C + signal(SIGTERM, signal_handler); // SIGTERM 对应kill或pkill + my_semaphore = sem_open("/my_semaphore", O_CREAT, 0644, 1); + + int this_option_optind = optind ? optind : 1; + int option_index = 0; + int c = -1; + int timeout = TIMEOUT_DEF; + char dev_path[128] = DEV_PATH_DEF; + int is_send = 0; + char g_file_name[256] = {0}; + int putchar_flag = 0; + int putchar_value = 0; + char url_download[256] = ""; + char url_check[256] = ""; + + + + int res = -1; + + while (1) { + struct option long_options[] = { + {"help", no_argument, 0, 'h' }, + {"url_download", required_argument, 0, 'u'}, + {"url_check", required_argument, 0, 'w'}, + {0, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "c:s:d:t:u:w:h", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + break; + case 'c': + putchar_flag = 1; + putchar_value = optarg[0]; + printf("putchar value: %c\r\n", putchar_value); + break; + case 'd': + strcpy(dev_path, optarg); + printf("dev path: %s\r\n", dev_path); + break; + case 's': + strcpy(g_file_name, optarg); + printf("send file: %s.\r\n", g_file_name); + is_send = 1; + break; + case 't': + timeout = atoi(optarg); + printf("timeout: %d*100ms.\r\n", timeout); + break; + case 'u': + strcpy(url_download, optarg); + printf("URL_downlaod: %s\r\n", url_download); + break; + case 'w': + strcpy(url_check, optarg); + printf("URL_check: %s\r\n", url_check); + break; + case 'h': + case '?': + ymodem_help(); + return 0; + // break; + + default: + break; + } + + } + + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + + ymodem_help(); + return 0; + } + + while(1){ + char local_SE_APP_version[50] = {0}; + char download_SE_APP_version[50] = {0}; + char download_SE_APP_url[255] = {0}; + if(check_version(local_SE_APP_version,download_SE_APP_version,download_SE_APP_url, + sizeof(local_SE_APP_version),sizeof(download_SE_APP_version),sizeof(download_SE_APP_url))){ + + printf("_save_APP_path = %s\n",_save_APP_path); + //获取文件 + int res = download_file(download_SE_APP_url, _save_APP_path); + if (res == -1) { + printf("download_file error.\n"); + sleep(long_wait_time); + continue; + } + + strcpy(g_file_name, _save_APP_path); + is_send = 1; + + // init serial + printf("open dev: %s\r\n", dev_path); + g_fd = open(dev_path, O_RDWR); + if (g_fd <= 0) { + printf("open %s failed!\r\n", dev_path); + sleep(long_wait_time); + continue; + } + serial_set(g_fd, BAUDRATE_DEF, 8, 'N', 1, timeout, 0); //1vtime = 100ms, 10=1000ms=1s + + ymodem.putchar = _putchar; + ymodem.getchar = _getchar; + + + + + + + if (putchar_flag) { + ymodem.putchar(putchar_value); + printf("putchar: %c/%d\r\n", putchar_value,putchar_value); + sleep(30); + continue; + } + + if (is_send) { + // system("pkill testprogram"); + printf("等锁\n"); + sem_wait(my_semaphore); + is_insem = 1; + printf("入锁\n"); + sleep(1); + ymodem.begin_packet_cb = send_begin_packet_callback; + ymodem.data_packet_cb = send_data_packet_callback; + ymodem.end_packet_cb = send_end_packet_callback; + + + if (send_file(g_file_name) == 0) { + printf("Transfer complete!\r\n"); + // int i = 0; + // do { + // res = get_result(); + // i++; + // printf("res: %d i=%d\n",res,i); + // } while ((res != 0) && (i < 3)); + sem_post(my_semaphore); + is_insem = 0; + printf("出锁\n"); + // system("/demo/bin/testprogram &"); + + } else { + printf("Send Ymodem err!\r\n"); + printf("stage: %d\r\n", ymodem.stage); + // int i = 0; + // do { + // res = get_result(); + // i++; + // printf("res: %d i=%d\n",res,i); + // } while ((res != 0) && (i < 3)); + sem_post(my_semaphore); + is_insem = 0; + printf("出锁\n"); + // system("/demo/bin/testprogram &"); + } + } else { + ymodem.begin_packet_cb = begin_packet_callback; + ymodem.data_packet_cb = data_packet_callback; + ymodem.end_packet_cb = end_packet_callback; + + if (recevice() == 0) { + printf("Recevice complete!\r\n"); + printf("file: %s, size: %d\r\n", ymodem.file_name, ymodem.file_size); + } else { + printf("Recevice Ymodem err!\r\n"); + printf("stage: %d\r\n", ymodem.stage); + } + } + + close(g_fd); + sleep(long_wait_time); + continue; + + }else{ + sleep(long_wait_time); + continue; + } + } + + +}